Compare commits

..

18 Commits

Author SHA1 Message Date
ahasani 636daca703 fix: improve Redis client shutdown handling to avoid errors 2026-06-17 14:57:52 +03:30
ahasani 9bf294a1f3 refactor: comment out payment validation for invoice amount correction 2026-06-17 10:03:09 +03:30
ahasani 839f6de691 debug for build 2026-06-17 09:07:53 +03:30
ahasani 826041b07a update return from sale invoices jurney and set nama return from sale 2026-06-17 08:50:35 +03:30
ahasani f87e5b9d8e feat: refactor Prisma client initialization and update related services 2026-06-16 15:47:29 +03:30
ahasani 652177862d update config 2026-06-16 10:09:22 +03:30
ahasani ac2e7f5dab feat: comment out CORS configuration in bootstrap function 2026-06-15 21:50:29 +03:30
ahasani f94a108948 feat: update activation expiration handling and enhance payload structure in transaction services 2026-06-15 21:35:53 +03:30
ahasani d51b677f26 feat: update invoice processing to use last_tsp_status for status mapping 2026-06-15 19:34:21 +03:30
ahasani 9170d8cd5a feat: enhance sales invoice processing with correction and return functionalities 2026-06-15 17:14:54 +03:30
ahasani 5f70b95589 feat: refactor sales invoice services and introduce pagination and filtering
- Added SharedSaleInvoicePaginationService for handling pagination logic.
- Introduced SharedSaleInvoiceFilterService to centralize filtering logic for sales invoices.
- Updated SalesInvoicesService to utilize the new pagination and filtering services.
- Refactored findAll methods in SalesInvoicesService, CustomerSaleInvoicesService, and other related services to support pagination and filtering.
- Enhanced DTOs for sales invoice filtering to extend shared filter properties.
- Updated module imports to include new services.
- Cleaned up redundant code related to filtering and pagination across various services.
2026-06-14 16:34:00 +03:30
ahasani d2bd576277 feat(pos): enhance password update process with current password validation 2026-06-11 17:53:08 +03:30
ahasani 23bfe1ecbe Refactor: Remove stored procedures and replace with direct database operations
feat: Add economic code and guild information to sales invoice selection

fix: Update error messages for invoice access and creation to use "صورت‌حساب"

fix: Change error messages in SaleInvoicesService to use "صورت‌حساب" instead of "فاکتور"

fix: Update error messages in SalesInvoicesService for not found cases to use "صورت‌حساب"

fix: Modify TSP service to handle invoice updates and error messages consistently with "صورت‌حساب"

fix: Update common DTO descriptions to refer to "صورت‌حساب" instead of "فاکتور"

fix: Adjust utility functions to handle invoice references and error messages with "صورت‌حساب"
2026-06-11 16:13:17 +03:30
ahasani 47a27fb54f feat: enhance consumer and partner middleware with Redis caching
- Added Redis caching to ConsumerMiddleware and PartnerMiddleware to improve performance by reducing database calls for consumer and partner data.
- Implemented logic to check for cached data before querying the database.
- Updated the InvoicesService to include settlement_type in the selected fields.
- Removed unnecessary console logs from CustomersService.
- Modified SalesInvoicesService to optimize query logic and improve performance.
- Updated StatisticsService to streamline data retrieval and processing.
- Created a new migration to add last_attempt_no and last_tsp_status columns to sales_invoices for better tracking of TSP attempts.
2026-06-09 13:31:58 +03:30
ahasani f61100bf25 feat: enhance CustomerIndividual and CustomerLegal models with new unique input types
feat: add cache invalidation method for POS middleware

feat: implement Redis caching in POS middleware for improved performance

feat: refactor sales invoice DTOs for POS to include correction functionality

feat: extend SalesInvoicesController to handle invoice corrections and returns

feat: update SalesInvoicesService to support invoice correction and return operations

feat: enhance TSP provider correction functionality with new DTOs and utility methods

fix: improve error handling and logging in Nama provider switch adapter

refactor: streamline invoice payload building in TSP provider utilities
2026-06-06 19:53:00 +03:30
ahasani 25e589551b refactor(accounts): rename account DTOs for clarity and consistency 2026-06-05 01:33:30 +03:30
ahasani 5ce560ce97 feat(customers): enhance customer retrieval with filtering options
- Updated `findAll` method in `CustomersController` to accept filtering parameters.
- Implemented filtering logic in `CustomersService` to retrieve customers based on type and search query.
- Added `PosCustomerFilterDto` for query validation.
- Updated customer-related DTOs to make fields optional and added length validation where necessary.
- Modified customer-related logic in `sales-invoice-tsp.utils.ts` to accommodate new DTO structure.
- Added unique constraints to `customer_individuals` and `customer_legal` tables in the database migration.
- Removed commented-out code in `PosMiddleware` for cleaner codebase.
- Set default value for `is_default_guild_good` to false in `OwnedGoodsService`.
2026-06-03 18:00:06 +03:30
ahasani b2d8fdc8a0 some updates 2026-06-01 16:22:35 +03:30
109 changed files with 3849 additions and 4080 deletions
+52
View File
@@ -128,3 +128,55 @@ Typecheck before handoff:
```bash ```bash
pnpm -s tsc --noEmit pnpm -s tsc --noEmit
``` ```
# INVESTIGATION LIMITS
For localized fixes:
- maximum 3 file reads before first edit
- maximum 1 related-file read unless required
- maximum 5 total file reads before implementation
Stop searching once the target service, controller, DTO, schema, or repository method is identified.
# TARGETED READ RULES
Do not read files larger than 300 lines unless required.
For known symbols:
1. rtk grep
2. rtk smart
3. read only the relevant section
Avoid opening entire services, modules, or controllers for localized changes.
Prefer symbol-level inspection.
# REVIEW MODE
During reviews:
- inspect changed files only
- avoid repository-wide searches
- avoid architecture exploration
- avoid reading unrelated modules
Review only code affected by the diff.
# HARD TOKEN LIMITS
For localized fixes:
- Never read more than 5 files before the first edit.
- Never read a file larger than 300 lines unless the target symbol cannot be isolated.
- Never open an entire service, controller, or module when a symbol-level read is possible.
- Never reread a file already summarized by `rtk smart` unless implementation details are required.
When a file exceeds 300 lines:
1. rtk grep
2. rtk smart
3. read only the required section
Avoid full-file reads.
@@ -0,0 +1,25 @@
/*
Warnings:
- A unique constraint covering the columns `[business_activity_id,postal_code,national_id]` on the table `customer_individuals` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[business_activity_id,postal_code,registration_number]` on the table `customer_legal` will be added. If there are existing duplicate values, this will fail.
*/
-- AlterTable
ALTER TABLE `customer_individuals` MODIFY `first_name` VARCHAR(255) NULL,
MODIFY `last_name` VARCHAR(255) NULL,
MODIFY `national_id` CHAR(10) NULL,
MODIFY `mobile_number` CHAR(15) NULL,
MODIFY `postal_code` CHAR(10) NULL,
MODIFY `economic_code` CHAR(14) NULL;
-- AlterTable
ALTER TABLE `customer_legal` MODIFY `name` VARCHAR(255) NULL,
MODIFY `economic_code` CHAR(11) NULL,
MODIFY `postal_code` CHAR(10) NULL;
-- CreateIndex
CREATE UNIQUE INDEX `customer_individuals_business_activity_id_postal_code_nation_key` ON `customer_individuals`(`business_activity_id`, `postal_code`, `national_id`);
-- CreateIndex
CREATE UNIQUE INDEX `customer_legal_business_activity_id_postal_code_registration_key` ON `customer_legal`(`business_activity_id`, `postal_code`, `registration_number`);
@@ -0,0 +1,50 @@
-- ALTER TABLE
ALTER TABLE `sales_invoices`
ADD COLUMN `last_attempt_no` INT NULL,
ADD COLUMN `last_tsp_status` ENUM(
'NOT_SEND',
'QUEUED',
'FISCAL_QUEUED',
'SEND_FAILURE',
'SUCCESS',
'FAILURE'
) NULL;
-- INDEX
CREATE INDEX `sales_invoices_pos_id_invoice_date_idx`
ON `sales_invoices` (`pos_id`, `invoice_date`);
-- BACKFILL LAST ATTEMPT
UPDATE sales_invoices si
JOIN (
SELECT invoice_id, attempt_no, status
FROM (
SELECT
invoice_id,
attempt_no,
status,
ROW_NUMBER() OVER (
PARTITION BY invoice_id
ORDER BY created_at DESC
) rn
FROM sale_invoice_tsp_attempts
) t
WHERE rn = 1
) la ON la.invoice_id = si.id
SET
si.last_attempt_no = la.attempt_no,
si.last_tsp_status = la.status;
-- SET NOT_SEND FOR NO ATTEMPTS
UPDATE sales_invoices si
LEFT JOIN sale_invoice_tsp_attempts att
ON att.invoice_id = si.id
SET
si.last_attempt_no = NULL,
si.last_tsp_status = 'NOT_SEND'
WHERE att.invoice_id IS NULL;
-- SAFETY FILL
UPDATE sales_invoices
SET last_tsp_status = 'NOT_SEND'
WHERE last_tsp_status IS NULL;
+11 -9
View File
@@ -13,33 +13,35 @@ model Customer {
} }
model CustomerIndividual { model CustomerIndividual {
first_name String @db.VarChar(255) first_name String? @db.VarChar(255)
last_name String @db.VarChar(255) last_name String? @db.VarChar(255)
national_id String @db.Char(10) national_id String? @db.Char(10)
mobile_number String @db.Char(15) mobile_number String? @db.Char(15)
postal_code String @db.Char(10) postal_code String? @db.Char(10)
economic_code String? @db.Char(10) economic_code String? @db.Char(14)
customer_id String @id customer_id String @id
business_activity_id String business_activity_id String
business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id]) business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id])
customer Customer @relation(fields: [customer_id], references: [id], onDelete: Cascade) customer Customer @relation(fields: [customer_id], references: [id], onDelete: Cascade)
@@unique([business_activity_id, national_id]) @@unique([business_activity_id, national_id])
@@unique([business_activity_id, postal_code, national_id])
@@index([business_activity_id]) @@index([business_activity_id])
@@map("customer_individuals") @@map("customer_individuals")
} }
model CustomerLegal { model CustomerLegal {
name String @db.VarChar(255) name String? @db.VarChar(255)
economic_code String @db.Char(10) economic_code String? @db.Char(11)
registration_number String? @db.Char(20) registration_number String? @db.Char(20)
postal_code String @db.Char(10) postal_code String? @db.Char(10)
customer_id String @id customer_id String @id
business_activity_id String business_activity_id String
business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id]) business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id])
customer Customer @relation(fields: [customer_id], references: [id], onDelete: Cascade) customer Customer @relation(fields: [customer_id], references: [id], onDelete: Cascade)
@@unique([business_activity_id, economic_code]) @@unique([business_activity_id, economic_code])
@@unique([business_activity_id, postal_code, registration_number])
@@index([business_activity_id]) @@index([business_activity_id])
@@map("customer_legal") @@map("customer_legal")
} }
+37 -34
View File
@@ -1,63 +1,66 @@
model SalesInvoice { model SalesInvoice {
id String @id @default(uuid()) id String @id @default(uuid())
code String @unique @db.VarChar(100) code String @unique @db.VarChar(100)
total_amount Decimal @db.Decimal(15, 2) total_amount Decimal @db.Decimal(15, 2)
invoice_number Int invoice_number Int
invoice_date DateTime @default(now()) @db.Timestamp(0) invoice_date DateTime @default(now()) @db.Timestamp(0)
type TspProviderRequestType type TspProviderRequestType
tax_id String? @unique @db.VarChar(32) tax_id String? @unique @db.VarChar(32)
notes String? @db.Text notes String? @db.Text
unknown_customer Json? unknown_customer Json?
created_at DateTime @default(now()) @db.Timestamp(0) created_at DateTime @default(now()) @db.Timestamp(0)
updated_at DateTime @updatedAt @db.Timestamp(0) updated_at DateTime @updatedAt @db.Timestamp(0)
main_id String? @db.VarChar(50) main_id String? @db.VarChar(50)
ref_id String? @unique @db.VarChar(50) ref_id String? @unique @db.VarChar(50)
customer_id String? customer_id String?
consumer_account_id String consumer_account_id String
pos_id String pos_id String
settlement_type InvoiceSettlementType settlement_type InvoiceSettlementType
discount_amount Decimal? @db.Decimal(15, 2) discount_amount Decimal? @db.Decimal(15, 2)
tax_amount Decimal? @db.Decimal(15, 2) tax_amount Decimal? @db.Decimal(15, 2)
last_tsp_status TspProviderResponseStatus?
last_attempt_no Int?
tsp_attempts SaleInvoiceTspAttempts[] tsp_attempts SaleInvoiceTspAttempts[]
items SalesInvoiceItem[] items SalesInvoiceItem[]
payments SalesInvoicePayment[] payments SalesInvoicePayment[]
consumer_account ConsumerAccount @relation(fields: [consumer_account_id], references: [id]) consumer_account ConsumerAccount @relation(fields: [consumer_account_id], references: [id])
customer Customer? @relation(fields: [customer_id], references: [id]) customer Customer? @relation(fields: [customer_id], references: [id])
pos Pos @relation(fields: [pos_id], references: [id]) pos Pos @relation(fields: [pos_id], references: [id])
reference_invoice SalesInvoice? @relation("SalesInvoiceReference", fields: [ref_id], references: [id]) reference_invoice SalesInvoice? @relation("SalesInvoiceReference", fields: [ref_id], references: [id])
referenced_by SalesInvoice? @relation("SalesInvoiceReference") referenced_by SalesInvoice? @relation("SalesInvoiceReference")
@@unique([invoice_number, pos_id]) @@unique([invoice_number, pos_id])
@@index([pos_id, invoice_date])
@@index([ref_id]) @@index([ref_id])
@@index([tax_id]) @@index([tax_id])
@@index([consumer_account_id], map: "sales_invoices_consumer_account_id_fkey") @@index([consumer_account_id], map: "sales_invoices_consumer_account_id_fkey")
@@index([customer_id], map: "sales_invoices_customer_id_fkey") @@index([customer_id], map: "sales_invoices_customer_id_fkey")
@@index([pos_id], map: "sales_invoices_pos_id_fkey")
@@map("sales_invoices") @@map("sales_invoices")
} }
model SalesInvoiceItem { model SalesInvoiceItem {
id String @id @default(ulid()) id String @id @default(ulid())
quantity Decimal @db.Decimal(10, 0) quantity Decimal @db.Decimal(10, 0)
measure_unit_text String @db.VarChar(50) measure_unit_text String @db.VarChar(50)
measure_unit_code String @db.VarChar(50) measure_unit_code String @db.VarChar(50)
sku_code String @db.VarChar(50) sku_code String @db.VarChar(50)
sku_vat Decimal @default(0.00) @db.Decimal(15, 2) sku_vat Decimal @default(0.00) @db.Decimal(15, 2)
unit_price Decimal @default(0.00) @db.Decimal(15, 2) unit_price Decimal @default(0.00) @db.Decimal(15, 2)
total_amount Decimal @default(0.00) @db.Decimal(15, 2) total_amount Decimal @default(0.00) @db.Decimal(15, 2)
created_at DateTime @default(now()) @db.Timestamp(0) created_at DateTime @default(now()) @db.Timestamp(0)
discount Decimal @default(0.00) @db.Decimal(15, 2) discount Decimal @default(0.00) @db.Decimal(15, 2)
notes String? @db.Text notes String? @db.Text
payload Json? payload Json?
good_snapshot Json good_snapshot Json
invoice_id String invoice_id String
good_id String good_id String
service_id String? service_id String?
discount_amount Decimal? @db.Decimal(15, 2) discount_amount Decimal? @db.Decimal(15, 2)
tax_amount Decimal? @db.Decimal(15, 2) tax_amount Decimal? @db.Decimal(15, 2)
good Good @relation(fields: [good_id], references: [id])
invoice SalesInvoice @relation(fields: [invoice_id], references: [id]) good Good @relation(fields: [good_id], references: [id])
service Service? @relation(fields: [service_id], references: [id]) invoice SalesInvoice @relation(fields: [invoice_id], references: [id])
service Service? @relation(fields: [service_id], references: [id])
@@index([invoice_id, good_id]) @@index([invoice_id, good_id])
@@index([good_id], map: "sales_invoice_items_good_id_fkey") @@index([good_id], map: "sales_invoice_items_good_id_fkey")
+4 -3
View File
@@ -1,7 +1,10 @@
import { PasswordUtil } from '@/common/utils/password.util' import { PasswordUtil } from '@/common/utils/password.util'
import { GoodPricingModel } from '@/generated/prisma/enums' import { GoodPricingModel } from '@/generated/prisma/enums'
import { GoodCreateManyInput } from '@/generated/prisma/models' import { GoodCreateManyInput } from '@/generated/prisma/models'
import { prisma } from '../src/lib/prisma' import { PrismaClient } from '../src/generated/prisma/client'
import { prismaAdapter } from '../src/lib/prisma'
const prisma = new PrismaClient({ adapter: prismaAdapter })
async function main() { async function main() {
const password = await PasswordUtil.hash('123456') const password = await PasswordUtil.hash('123456')
@@ -198,8 +201,6 @@ async function main() {
code: sku_code, code: sku_code,
}, },
}) })
console.log(name)
console.log(sku?.id)
if (sku) { if (sku) {
return { return {
-548
View File
@@ -1,548 +0,0 @@
-- AUTO-GENERATED MYSQL TRIGGER DUMP
-- Generated at: 2026-01-06T16:09:38.959Z
-- ------------------------------------------
-- index: 1
-- Trigger: trg_bank_account_transaction_after_delete
-- Event: DELETE
-- Table: Bank_Account_Transactions
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_bank_account_transaction_after_delete`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_bank_account_transaction_after_delete` AFTER DELETE ON `Bank_Account_Transactions` FOR EACH ROW BEGIN
UPDATE `Bank_Account_Balance` SET balance = balance - OLD.amount WHERE `bankAccountId` = OLD.bankAccountId;
END;
-- ------------------------------------------
-- index: 2
-- Trigger: trg_transfer_item_after_insert
-- Event: INSERT
-- Table: Inventory_Transfer_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_transfer_item_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_transfer_item_after_insert` AFTER INSERT ON `Inventory_Transfer_Items` FOR EACH ROW begin
DECLARE fromInv INT;
DECLARE toInv INT;
DECLARE _avgCost DECIMAL(10,2);
DECLARE latestQuantityInOrigin DECIMAL(10,2);
DECLARE latestQuantityInDestination DECIMAL(10,2);
SELECT fromInventoryId, toInventoryId INTO fromInv, toInv
FROM Inventory_Transfers WHERE id = NEW.transferId;
SELECT COALESCE(avgCost, 0), COALESCE(quantity, 0) INTO _avgCost, latestQuantityInOrigin FROM Stock_Balance
WHERE ProductId = NEW.productId AND inventoryId = fromInv LIMIT 1;
SELECT COALESCE(quantity, 0) INTO latestQuantityInDestination FROM Stock_Balance
WHERE ProductId = NEW.productId AND inventoryId = toInv LIMIT 1;
-- OUT from source
INSERT INTO Stock_Movements
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
VALUES
('OUT', NEW.count, _avgCost, _avgCost*NEW.count, _avgCost, 'INVENTORY_TRANSFER', NEW.transferId, NEW.productId, fromInv, toInv, NOW(), latestQuantityInOrigin-NEW.count);
-- IN to destination
INSERT INTO Stock_Movements
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
VALUES
('IN', NEW.count,_avgCost, _avgCost*NEW.count,_avgCost, 'INVENTORY_TRANSFER', NEW.transferId, NEW.productId, toInv, fromInv, NOW(), latestQuantityInOrigin-NEW.count);
end;
-- ------------------------------------------
-- index: 3
-- Trigger: trg_order_item_after_update
-- Event: UPDATE
-- Table: Order_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_order_item_after_update`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_update` AFTER UPDATE ON `Order_Items` FOR EACH ROW BEGIN
UPDATE Stock_Reservations
SET quantity = quantity - OLD.quantity + NEW.quantity
WHERE orderId = NEW.orderId AND productId = NEW.productId;
END;
-- ------------------------------------------
-- index: 4
-- Trigger: trg_order_item_after_delete
-- Event: DELETE
-- Table: Order_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_order_item_after_delete`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_delete` AFTER DELETE ON `Order_Items` FOR EACH ROW BEGIN
DELETE From Stock_Reservations
WHERE orderId = OLD.orderId AND productId = OLD.productId;
END;
-- ------------------------------------------
-- index: 5
-- Trigger: trg_order_after_cancel
-- Event: UPDATE
-- Table: Orders
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_order_after_cancel`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_after_cancel` AFTER UPDATE ON `Orders` FOR EACH ROW BEGIN
IF NEW.status = 'CANCELED' OR NEW.status = 'REJECTED' OR NEW.status = 'DONE' THEN
UPDATE Stock_Reservations sr SET quantity = 0
WHERE sr.orderId = NEW.id;
END IF;
END;
-- ------------------------------------------
-- index: 6
-- Trigger: trg_purchase_receipt_item_after_insert
-- Event: INSERT
-- Table: Purchase_Receipt_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_purchase_receipt_item_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_receipt_item_after_insert` AFTER INSERT ON `Purchase_Receipt_Items` FOR EACH ROW BEGIN DECLARE latestQuantity DECIMAL(10, 2) DEFAULT 0;
DECLARE invId INT;
DECLARE suppId INT;
-- Get inventory & supplier from
SELECT inventoryId, supplierId
INTO invId, suppId
FROM Purchase_Receipts
WHERE id = NEW.receiptId;
-- Get current stock quantity (if exists)
SELECT COALESCE(quantity, 0)
INTO latestQuantity
FROM Stock_Balance sb
WHERE sb.inventoryId = invId
AND sb.productId = NEW.productId
LIMIT 1;
-- Insert stock movement
INSERT INTO Stock_Movements (
type,
quantity,
unitPrice,
totalCost,
referenceType,
referenceId,
productId,
inventoryId,
avgCost,
supplierId,
remainedInStock,
createdAt
)
VALUES (
'IN',
NEW.count,
NEW.unitPrice,
NEW.totalAmount,
'PURCHASE',
NEW.receiptId,
NEW.productId,
invId,
CASE
WHEN NEW.count = 0 THEN 0
ELSE NEW.totalAmount / NEW.count
END
,
suppId,
latestQuantity + NEW.count,
NOW()
);
END;
-- ------------------------------------------
-- index: 7
-- Trigger: trg_pr_payment_after_delete
-- Event: DELETE
-- Table: Purchase_Receipt_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_pr_payment_after_delete`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pr_payment_after_delete` AFTER DELETE ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
DECLARE receiptTotal DECIMAL(14,2);
DECLARE newPaid DECIMAL(14,2);
SELECT totalAmount, paidAmount
INTO receiptTotal, newPaid
FROM Purchase_Receipts
WHERE id = OLD.receiptId
FOR UPDATE;
IF OLD.type = 'PAYMENT' THEN
SET newPaid = newPaid - OLD.amount;
ELSE
SET newPaid = newPaid + OLD.amount;
END IF;
UPDATE Purchase_Receipts
SET
paidAmount = newPaid,
status =
CASE
WHEN newPaid = 0 THEN 'UNPAID'
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
ELSE 'PAID'
END
WHERE id = OLD.receiptId;
END;
-- ------------------------------------------
-- index: 8
-- Trigger: trg_sales_invoice_items_before_insert
-- Event: INSERT
-- Table: Sales_Invoice_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_before_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_items_before_insert` BEFORE INSERT ON `Sales_Invoice_Items` FOR EACH ROW BEGIN
DECLARE current_stock DECIMAL(10, 2);
DECLARE inventory_id INT;
SELECT pa.inventoryId INTO inventory_id
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = NEW.invoiceId;
SELECT COALESCE(sav.availableQuantity, 0) INTO current_stock
FROM Stock_Available_View sav
WHERE productId = NEW.productId AND sav.inventoryId = inventory_id;
IF NEW.count > current_stock THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'موجودی کالا در انبار کافی نیست.';
END IF;
end;
-- ------------------------------------------
-- index: 9
-- Trigger: trg_sales_invoice_items_after_insert
-- Event: INSERT
-- Table: Sales_Invoice_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_items_after_insert` AFTER INSERT ON `Sales_Invoice_Items` FOR EACH ROW begin DECLARE current_stock DECIMAL(10, 2);
DECLARE inventory_id INT;
DECLARE customer_id INT;
DECLARE pos_id INT;
SELECT posAccountId, customerId INTO pos_id, customer_id
FROM Sales_Invoices si
WHERE si.id = NEW.invoiceId
LIMIT 1;
INSERT INTO Trigger_Logs (name , message) VALUES ('pos_id', pos_id);
INSERT INTO Trigger_Logs (name , message) VALUES ('customer_id', customer_id);
SELECT pa.inventoryId INTO inventory_id
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = NEW.invoiceId;
SELECT COALESCE(quantity, 0) INTO current_stock
FROM Stock_Balance sb
WHERE productId = NEW.productId AND sb.inventoryId = inventory_id
LIMIT 1;
INSERT INTO Stock_Movements (
type,
quantity,
unitPrice,
totalCost,
referenceType,
referenceId,
productId,
inventoryId,
avgCost,
remainedInStock,
customerId,
createdAt
)
VALUES (
'OUT',
NEW.count,
NEW.unitPrice,
NEW.totalAmount,
'SALES',
NEW.invoiceId,
NEW.productId,
inventory_id,
CASE
WHEN NEW.count = 0 THEN 0
ELSE NEW.totalAmount / NEW.count
END,
current_stock - NEW.count,
customer_id,
NOW()
);
END;
-- ------------------------------------------
-- index: 10
-- Trigger: trg_pos_account_payment_after_insert
-- Event: INSERT
-- Table: Sales_Invoice_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_pos_account_payment_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pos_account_payment_after_insert` AFTER INSERT ON `Sales_Invoice_Payments` FOR EACH ROW BEGIN
DECLARE _bankAccountId INT;
IF(NEW.paymentMethod != 'CASH') THEN
SELECT cashBankAccountId INTO _bankAccountId
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = NEW.invoiceId;
End IF;
INSERT INTO Bank_Account_Transactions (
bankAccountId,
type,
amount,
balanceAfter,
referenceType,
referenceId
)
VALUES(
_bankAccountId,
'DEPOSIT',
NEW.amount,
0,
'POS_SALE',
NEW.id
);
END;
-- ------------------------------------------
-- index: 11
-- Trigger: trg_sales_invoice_payment_after_insert
-- Event: INSERT
-- Table: Sales_Invoice_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_sales_invoice_payment_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_payment_after_insert` AFTER INSERT ON `Sales_Invoice_Payments` FOR EACH ROW BEGIN
DECLARE currentBalance DECIMAL(15,2);
DECLARE bankAccountId INT;
SELECT pa.bankAccountId INTO bankAccountId
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = NEW.invoiceId;
SELECT balance INTO currentBalance
FROM Bank_Account_Balance
WHERE bankAccountId = bankAccountId
FOR UPDATE;
IF currentBalance IS NULL THEN
SET currentBalance = 0;
INSERT INTO Bank_Account_Balance (bankAccountId, balance)
VALUES (bankAccountId, 0);
END IF;
SET currentBalance = currentBalance + NEW.amount;
INSERT INTO Bank_Account_Transactions
(bankAccountId, type, amount, balanceAfter, referenceType, referenceId)
VALUES
(bankAccountId, 'DEPOSIT', NEW.amount, currentBalance, 'POS_SALE', NEW.id);
UPDATE Bank_Account_Balance
SET balance = currentBalance
WHERE bankAccountId = bankAccountId;
END;
-- ------------------------------------------
-- index: 12
-- Trigger: trg_stock_sale_insert
-- Event: INSERT
-- Table: Stock_Movements
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_stock_sale_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_sale_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'SALES' THEN
INSERT INTO
Stock_Balance (
productId,
quantity,
avgCost,
totalCost,
inventoryId,
updatedAt
)
VALUES (
NEW.productId,
NEW.quantity,
NEW.unitPrice,
NEW.totalCost,
NEW.inventoryId,
NOW()
)
ON DUPLICATE KEY UPDATE
quantity = quantity - NEW.quantity,
totalCost = totalCost - NEW.totalCost,
avgCost = totalCost / quantity;
END IF;
END;
-- ------------------------------------------
-- index: 13
-- Trigger: trg_stock_purchase_insert
-- Event: INSERT
-- Table: Stock_Movements
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_stock_purchase_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_purchase_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'PURCHASE' THEN
INSERT INTO
Stock_Balance (
productId,
quantity,
avgCost,
totalCost,
inventoryId,
updatedAt
)
VALUES (
NEW.productId,
NEW.quantity,
NEW.unitPrice,
NEW.totalCost,
NEW.inventoryId,
NOW()
)
ON DUPLICATE KEY UPDATE
quantity = quantity + NEW.quantity,
totalCost = totalCost + NEW.totalCost,
avgCost = totalCost / quantity;
END IF;
END;
-- ------------------------------------------
-- index: 14
-- Trigger: trg_stock_transfer
-- Event: INSERT
-- Table: Stock_Movements
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_stock_transfer`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_transfer` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'INVENTORY_TRANSFER' THEN IF NEW.type = 'IN' THEN
INSERT INTO
Stock_Balance (
productId,
inventoryId,
quantity,
totalCost,
avgCost,
updatedAt
)
VALUES (
NEW.productId,
NEW.inventoryId,
NEW.quantity,
NEW.totalCost,
CASE
WHEN NEW.quantity = 0 THEN 0
ELSE NEW.totalCost / NEW.quantity
END,
NOW()
)
ON DUPLICATE KEY UPDATE
quantity = quantity + NEW.quantity,
totalCost = totalCost + NEW.totalCost,
avgCost = CASE
WHEN (quantity + NEW.quantity) = 0 THEN 0
ELSE (totalCost + NEW.totalCost) / (quantity + NEW.quantity)
END,
updatedAt = NOW();
END IF;
IF NEW.type = 'OUT' THEN IF EXISTS (
SELECT 1
FROM Stock_Balance sb
WHERE
sb.productId = NEW.productId
AND sb.inventoryId = NEW.inventoryId
) THEN
UPDATE Stock_Balance sb
SET
sb.quantity = sb.quantity - NEW.quantity,
sb.totalCost = sb.totalCost - (sb.avgCost * NEW.quantity),
sb.updatedAt = NOW()
WHERE
sb.productId = NEW.productId
AND sb.inventoryId = NEW.inventoryId;
ELSE
INSERT INTO
Stock_Balance (
productId,
inventoryId,
quantity,
totalCost,
avgCost,
updatedAt
)
VALUES (
NEW.productId,
NEW.inventoryId,
- NEW.quantity,
- COALESCE(NEW.unitPrice, 0) * NEW.quantity,
COALESCE(NEW.unitPrice, 0),
NOW()
);
END IF;
END IF;
END IF;
END;
-- ------------------------------------------
-- index: 15
-- Trigger: trg_no_negative_available_stock
-- Event: INSERT
-- Table: Stock_Reservations
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_no_negative_available_stock`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_no_negative_available_stock` BEFORE INSERT ON `Stock_Reservations` FOR EACH ROW BEGIN
DECLARE available DECIMAL(14,3);
SELECT availableQuantity
INTO available
FROM Stock_Available_View
WHERE productId = NEW.productId
AND inventoryId = NEW.inventoryId;
IF available < NEW.quantity THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'موجودی کافی نیست';
END IF;
END;
-825
View File
@@ -1,825 +0,0 @@
-- AUTO-GENERATED MYSQL TRIGGER DUMP
-- Generated at: 2026-01-04T09:46:30.365Z
-- ------------------------------------------
-- index: 1
-- Trigger: trg_bank_account_transaction_after_insert
-- Event: INSERT
-- Table: Bank_Account_Transactions
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_bank_account_transaction_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_bank_account_transaction_after_insert` AFTER INSERT ON `Bank_Account_Transactions` FOR EACH ROW BEGIN
IF NEW.type = 'DEPOSIT' THEN
UPDATE Bank_Account_Balance SET balance = balance + NEW.amount WHERE bankAccountId = NEW.bankAccountId;
ELSEIF NEW.type = 'WITHDRAWAL' THEN
UPDATE Bank_Account_Balance SET balance = balance - NEW.amount WHERE bankAccountId = NEW.bankAccountId;
END IF;
END;
-- ------------------------------------------
-- index: 2
-- Trigger: trg_bank_account_transaction_after_delete
-- Event: DELETE
-- Table: Bank_Account_Transactions
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_bank_account_transaction_after_delete`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_bank_account_transaction_after_delete` AFTER DELETE ON `Bank_Account_Transactions` FOR EACH ROW BEGIN
UPDATE Bank_Accounts SET balance = balance - OLD.amount;
END;
-- ------------------------------------------
-- index: 3
-- Trigger: trg_transfer_item_after_insert
-- Event: INSERT
-- Table: Inventory_Transfer_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_transfer_item_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_transfer_item_after_insert` AFTER INSERT ON `Inventory_Transfer_Items` FOR EACH ROW begin
DECLARE fromInv INT;
DECLARE toInv INT;
DECLARE _avgCost DECIMAL(10,2);
DECLARE latestQuantityInOrigin DECIMAL(10,2);
DECLARE latestQuantityInDestination DECIMAL(10,2);
SELECT fromInventoryId, toInventoryId INTO fromInv, toInv
FROM Inventory_Transfers WHERE id = NEW.transferId;
SELECT COALESCE(avgCost, 0), COALESCE(quantity, 0) INTO _avgCost, latestQuantityInOrigin FROM Stock_Balance
WHERE ProductId = NEW.productId AND inventoryId = fromInv LIMIT 1;
SELECT COALESCE(quantity, 0) INTO latestQuantityInDestination FROM Stock_Balance
WHERE ProductId = NEW.productId AND inventoryId = toInv LIMIT 1;
-- OUT from source
INSERT INTO Stock_Movements
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
VALUES
('OUT', NEW.count, _avgCost, _avgCost*NEW.count, _avgCost, 'INVENTORY_TRANSFER', NEW.transferId, NEW.productId, fromInv, toInv, NOW(), latestQuantityInOrigin-NEW.count);
-- IN to destination
INSERT INTO Stock_Movements
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
VALUES
('IN', NEW.count,_avgCost, _avgCost*NEW.count,_avgCost, 'INVENTORY_TRANSFER', NEW.transferId, NEW.productId, toInv, fromInv, NOW(), latestQuantityInOrigin-NEW.count);
end;
-- ------------------------------------------
-- index: 4
-- Trigger: trg_order_item_after_insert
-- Event: INSERT
-- Table: Order_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_order_item_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_insert` AFTER INSERT ON `Order_Items` FOR EACH ROW BEGIN
UPDATE Stock_Reservations SET quantity = quantity + NEW.quantity
WHERE orderId = NEW.orderId AND productId = NEW.productId;
END;
-- ------------------------------------------
-- index: 5
-- Trigger: trg_order_item_after_update
-- Event: UPDATE
-- Table: Order_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_order_item_after_update`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_update` AFTER UPDATE ON `Order_Items` FOR EACH ROW BEGIN
UPDATE Stock_Reservations
SET quantity = quantity - OLD.quantity + NEW.quantity
WHERE orderId = NEW.orderId AND productId = NEW.productId;
END;
-- ------------------------------------------
-- index: 6
-- Trigger: trg_order_item_after_delete
-- Event: DELETE
-- Table: Order_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_order_item_after_delete`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_delete` AFTER DELETE ON `Order_Items` FOR EACH ROW BEGIN
UPDATE Stock_Reservations SET quantity = quantity - OLD.quantity
WHERE orderId = OLD.orderId AND productId = OLD.productId;
END;
-- ------------------------------------------
-- index: 7
-- Trigger: trg_order_after_cancel
-- Event: UPDATE
-- Table: Orders
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_order_after_cancel`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_after_cancel` AFTER UPDATE ON `Orders` FOR EACH ROW BEGIN
IF NEW.status = 'CANCELED' OR NEW.status = 'REJECTED' OR NEW.status = 'DONE' THEN
UPDATE Stock_Reservations sr SET quantity = 0
WHERE sr.orderId = NEW.id;
END IF;
END;
-- ------------------------------------------
-- index: 8
-- Trigger: trg_purchase_receipt_item_after_insert
-- Event: INSERT
-- Table: Purchase_Receipt_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_purchase_receipt_item_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_receipt_item_after_insert` AFTER INSERT ON `Purchase_Receipt_Items` FOR EACH ROW BEGIN DECLARE latestQuantity DECIMAL(10, 2) DEFAULT 0;
DECLARE invId INT;
DECLARE suppId INT;
-- Get inventory & supplier from
SELECT inventoryId, supplierId
INTO invId, suppId
FROM Purchase_Receipts
WHERE id = NEW.receiptId;
-- Get current stock quantity (if exists)
SELECT COALESCE(quantity, 0)
INTO latestQuantity
FROM Stock_Balance sb
WHERE sb.inventoryId = invId
AND sb.productId = NEW.productId
LIMIT 1;
-- Insert stock movement
INSERT INTO Stock_Movements (
type,
quantity,
unitPrice,
totalCost,
referenceType,
referenceId,
productId,
inventoryId,
avgCost,
supplierId,
remainedInStock,
createdAt
)
VALUES (
'IN',
NEW.count,
NEW.unitPrice,
NEW.totalAmount,
'PURCHASE',
NEW.receiptId,
NEW.productId,
invId,
CASE
WHEN NEW.count = 0 THEN 0
ELSE NEW.totalAmount / NEW.count
END
,
suppId,
latestQuantity + NEW.count,
NOW()
);
END;
-- ------------------------------------------
-- index: 9
-- Trigger: trg_pr_payment_before_insert
-- Event: INSERT
-- Table: Purchase_Receipt_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_pr_payment_before_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pr_payment_before_insert` BEFORE INSERT ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
DECLARE receiptTotal DECIMAL(14,2);
DECLARE paid DECIMAL(14,2);
SELECT totalAmount, paidAmount
INTO receiptTotal, paid
FROM Purchase_Receipts
WHERE id = NEW.receiptId
FOR UPDATE;
IF NEW.type = 'PAYMENT' AND paid + NEW.amount > receiptTotal THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'مجموع مبلغ پرداختی بیشتر از مبلغ فاکتور است.';
END IF;
END;
-- ------------------------------------------
-- index: 10
-- Trigger: trg_purchase_payment_update_receipt
-- Event: INSERT
-- Table: Purchase_Receipt_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_purchase_payment_update_receipt`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_payment_update_receipt` AFTER INSERT ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
DECLARE paid DECIMAL(15,2);
DECLARE total DECIMAL(15,2);
SELECT
COALESCE(SUM(
CASE WHEN type = 'PAYMENT' THEN amount ELSE -amount END
),0)
INTO paid
FROM Purchase_Receipt_Payments
WHERE receiptId = NEW.receiptId;
SELECT totalAmount INTO total
FROM Purchase_Receipts
WHERE id = NEW.receiptId;
UPDATE Purchase_Receipts
SET
paidAmount = paid,
status = CASE
WHEN paid = 0 THEN 'UNPAID'
WHEN paid < total THEN 'PARTIALLY_PAID'
ELSE 'PAID'
END
WHERE id = NEW.receiptId;
END;
-- ------------------------------------------
-- index: 11
-- Trigger: trg_purchase_payment_after_insert
-- Event: INSERT
-- Table: Purchase_Receipt_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_purchase_payment_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_payment_after_insert` AFTER INSERT ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
DECLARE currentBalance DECIMAL(15, 2);
SELECT balance INTO currentBalance
FROM Bank_Account_Balance
WHERE
bankAccountId = NEW.bankAccountId FOR
UPDATE;
IF currentBalance IS NULL THEN SET currentBalance = 0;
INSERT INTO
Bank_Account_Balance (bankAccountId, balance, updatedAt)
VALUES (NEW.bankAccountId, 0, NOW());
END IF;
IF NEW.type = 'PAYMENT' THEN
SET
currentBalance = currentBalance - NEW.amount;
INSERT INTO
Bank_Account_Transactions (
bankAccountId,
type,
amount,
balanceAfter,
referenceType,
referenceId
)
VALUES (
NEW.bankAccountId,
'WITHDRAWAL',
NEW.amount,
currentBalance,
'PURCHASE_PAYMENT',
NEW.id
);
ELSE SET currentBalance = currentBalance + NEW.amount;
INSERT INTO
Bank_Account_Transactions (
bankAccountId,
type,
amount,
balanceAfter,
referenceType,
referenceId
)
VALUES (
NEW.bankAccountId,
'DEPOSIT',
NEW.amount,
currentBalance,
'PURCHASE_REFUND',
NEW.id
);
END IF;
UPDATE Bank_Account_Balance
SET
balance = currentBalance
WHERE
bankAccountId = NEW.bankAccountId;
END;
-- ------------------------------------------
-- index: 12
-- Trigger: trg_pr_payment_after_insert
-- Event: INSERT
-- Table: Purchase_Receipt_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_pr_payment_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pr_payment_after_insert` AFTER INSERT ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
DECLARE receiptTotal DECIMAL(14,2) Default 0;
DECLARE newPaid DECIMAL(14,2) Default 0;
DECLARE _supplierId INT;
DECLARE lastBalance DECIMAL(14,2) Default 0;
-- Lock receipt row
SELECT COALESCE(totalAmount, 0), COALESCE(paidAmount, 0), supplierId
INTO receiptTotal, newPaid, _supplierId
FROM Purchase_Receipts
WHERE id = NEW.receiptId
FOR UPDATE;
-- Apply payment or refund
IF NEW.type = 'PAYMENT' THEN
SET newPaid = newPaid + NEW.amount;
ELSE
SET newPaid = newPaid - NEW.amount;
END IF;
-- Update receipt
UPDATE Purchase_Receipts
SET
paidAmount = newPaid,
status =
CASE
WHEN newPaid = 0 THEN 'UNPAID'
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
ELSE 'PAID'
END
WHERE id = NEW.receiptId;
-- Get last supplier balance
SELECT IFNULL(balance, 0)
INTO lastBalance
FROM Supplier_Ledger
WHERE supplierId = _supplierId
ORDER BY id DESC
LIMIT 1;
-- Insert supplier ledger
INSERT INTO Supplier_Ledger
(
supplierId,
debit,
credit,
balance,
sourceType,
sourceId,
createdAt
)
VALUES
(
_supplierId,
IF(NEW.type = 'REFUND', NEW.amount, 0),
IF(NEW.type = 'PAYMENT', NEW.amount, 0),
lastBalance
+ IF(NEW.type = 'PAYMENT', NEW.amount, 0)
- IF(NEW.type = 'REFUND', NEW.amount, 0),
'PAYMENT',
NEW.id,
NOW()
);
END;
-- ------------------------------------------
-- index: 13
-- Trigger: trg_pr_payment_after_delete
-- Event: DELETE
-- Table: Purchase_Receipt_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_pr_payment_after_delete`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pr_payment_after_delete` AFTER DELETE ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
DECLARE receiptTotal DECIMAL(14,2);
DECLARE newPaid DECIMAL(14,2);
SELECT totalAmount, paidAmount
INTO receiptTotal, newPaid
FROM Purchase_Receipts
WHERE id = OLD.receiptId
FOR UPDATE;
IF OLD.type = 'PAYMENT' THEN
SET newPaid = newPaid - OLD.amount;
ELSE
SET newPaid = newPaid + OLD.amount;
END IF;
UPDATE Purchase_Receipts
SET
paidAmount = newPaid,
status =
CASE
WHEN newPaid = 0 THEN 'UNPAID'
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
ELSE 'PAID'
END
WHERE id = OLD.receiptId;
END;
-- ------------------------------------------
-- index: 14
-- Trigger: trg_purchase_receipt_after_insert
-- Event: INSERT
-- Table: Purchase_Receipts
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_purchase_receipt_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_receipt_after_insert` AFTER INSERT ON `Purchase_Receipts` FOR EACH ROW BEGIN
DECLARE lastBalance DECIMAL(14,2) DEFAULT 0;
SELECT COALESCE(balance, 0)
INTO lastBalance
FROM Supplier_Ledger
WHERE supplierId = NEW.supplierId
ORDER BY id DESC
LIMIT 1;
INSERT INTO Supplier_Ledger
(
supplierId,
debit,
credit,
balance,
sourceType,
sourceId,
createdAt
)
VALUES
(
NEW.supplierId,
NEW.totalAmount,
0,
lastBalance - NEW.totalAmount,
'PURCHASE',
NEW.id,
NOW()
);
END;
-- ------------------------------------------
-- index: 15
-- Trigger: trg_sales_invoice_items_before_insert
-- Event: INSERT
-- Table: Sales_Invoice_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_before_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_items_before_insert` BEFORE INSERT ON `Sales_Invoice_Items` FOR EACH ROW BEGIN
DECLARE current_stock DECIMAL(10, 2);
DECLARE inventory_id INT;
SELECT pa.inventoryId INTO inventory_id
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = NEW.invoiceId;
SELECT COALESCE(quantity, 0) INTO current_stock
FROM Stock_Balance sb
WHERE productId = NEW.productId AND sb.inventoryId = inventory_id
LIMIT 1;
IF NEW.count > current_stock THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'موجودی کالا در انبار کافی نیست.';
END IF;
end;
-- ------------------------------------------
-- index: 16
-- Trigger: trg_sales_invoice_items_after_insert
-- Event: INSERT
-- Table: Sales_Invoice_Items
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_items_after_insert` AFTER INSERT ON `Sales_Invoice_Items` FOR EACH ROW begin DECLARE current_stock DECIMAL(10, 2);
DECLARE inventory_id INT;
DECLARE customer_id INT;
DECLARE pos_id INT;
SELECT posAccountId, customerId INTO pos_id, customer_id
FROM Sales_Invoices si
WHERE si.id = NEW.invoiceId
LIMIT 1;
INSERT INTO Trigger_Logs (name , message) VALUES ('pos_id', pos_id);
INSERT INTO Trigger_Logs (name , message) VALUES ('customer_id', customer_id);
SELECT pa.inventoryId INTO inventory_id
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = NEW.invoiceId;
SELECT COALESCE(quantity, 0) INTO current_stock
FROM Stock_Balance sb
WHERE productId = NEW.productId AND sb.inventoryId = inventory_id
LIMIT 1;
INSERT INTO Stock_Movements (
type,
quantity,
unitPrice,
totalCost,
referenceType,
referenceId,
productId,
inventoryId,
avgCost,
remainedInStock,
customerId,
createdAt
)
VALUES (
'OUT',
NEW.count,
NEW.unitPrice,
NEW.totalAmount,
'SALES',
NEW.invoiceId,
NEW.productId,
inventory_id,
CASE
WHEN NEW.count = 0 THEN 0
ELSE NEW.totalAmount / NEW.count
END,
current_stock - NEW.count,
customer_id,
NOW()
);
END;
-- ------------------------------------------
-- index: 17
-- Trigger: trg_sales_invoice_payment_after_insert
-- Event: INSERT
-- Table: Sales_Invoice_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_sales_invoice_payment_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_payment_after_insert` AFTER INSERT ON `Sales_Invoice_Payments` FOR EACH ROW BEGIN
DECLARE currentBalance DECIMAL(15,2);
DECLARE bankAccountId INT;
SELECT pa.bankAccountId INTO bankAccountId
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = NEW.invoiceId;
SELECT balance INTO currentBalance
FROM Bank_Account_Balance
WHERE bankAccountId = bankAccountId
FOR UPDATE;
IF currentBalance IS NULL THEN
SET currentBalance = 0;
INSERT INTO Bank_Account_Balance (bankAccountId, balance)
VALUES (bankAccountId, 0);
END IF;
SET currentBalance = currentBalance + NEW.amount;
INSERT INTO Bank_Account_Transactions
(bankAccountId, type, amount, balanceAfter, referenceType, referenceId)
VALUES
(bankAccountId, 'DEPOSIT', NEW.amount, currentBalance, 'POS_SALE', NEW.id);
UPDATE Bank_Account_Balance
SET balance = currentBalance
WHERE bankAccountId = bankAccountId;
END;
-- ------------------------------------------
-- index: 18
-- Trigger: trg_pos_account_payment_after_insert
-- Event: INSERT
-- Table: Sales_Invoice_Payments
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_pos_account_payment_after_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pos_account_payment_after_insert` AFTER INSERT ON `Sales_Invoice_Payments` FOR EACH ROW BEGIN
DECLARE _bankAccountId INT;
IF(NEW.paymentMethod != 'CASH') THEN
SELECT cashBankAccountId INTO _bankAccountId
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = NEW.invoiceId;
End IF;
INSERT INTO Bank_Account_Transactions (
bankAccountId,
type,
amount,
balanceAfter,
referenceType,
referenceId
)
VALUES(
_bankAccountId,
'DEPOSIT',
NEW.amount,
0,
'POS_SALE',
NEW.id
);
END;
-- ------------------------------------------
-- index: 19
-- Trigger: trg_stock_transfer
-- Event: INSERT
-- Table: Stock_Movements
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_stock_transfer`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_transfer` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'INVENTORY_TRANSFER' THEN IF NEW.type = 'IN' THEN
INSERT INTO
Stock_Balance (
productId,
inventoryId,
quantity,
totalCost,
avgCost,
updatedAt
)
VALUES (
NEW.productId,
NEW.inventoryId,
NEW.quantity,
NEW.totalCost,
CASE
WHEN NEW.quantity = 0 THEN 0
ELSE NEW.totalCost / NEW.quantity
END,
NOW()
)
ON DUPLICATE KEY UPDATE
quantity = quantity + NEW.quantity,
totalCost = totalCost + NEW.totalCost,
avgCost = CASE
WHEN (quantity + NEW.quantity) = 0 THEN 0
ELSE (totalCost + NEW.totalCost) / (quantity + NEW.quantity)
END,
updatedAt = NOW();
END IF;
IF NEW.type = 'OUT' THEN IF EXISTS (
SELECT 1
FROM Stock_Balance sb
WHERE
sb.productId = NEW.productId
AND sb.inventoryId = NEW.inventoryId
) THEN
UPDATE Stock_Balance sb
SET
sb.quantity = sb.quantity - NEW.quantity,
sb.totalCost = sb.totalCost - (sb.avgCost * NEW.quantity),
sb.updatedAt = NOW()
WHERE
sb.productId = NEW.productId
AND sb.inventoryId = NEW.inventoryId;
ELSE
INSERT INTO
Stock_Balance (
productId,
inventoryId,
quantity,
totalCost,
avgCost,
updatedAt
)
VALUES (
NEW.productId,
NEW.inventoryId,
- NEW.quantity,
- COALESCE(NEW.unitPrice, 0) * NEW.quantity,
COALESCE(NEW.unitPrice, 0),
NOW()
);
END IF;
END IF;
END IF;
END;
-- ------------------------------------------
-- index: 20
-- Trigger: trg_stock_purchase_insert
-- Event: INSERT
-- Table: Stock_Movements
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_stock_purchase_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_purchase_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'PURCHASE' THEN
INSERT INTO
Stock_Balance (
productId,
quantity,
avgCost,
totalCost,
inventoryId,
updatedAt
)
VALUES (
NEW.productId,
NEW.quantity,
NEW.unitPrice,
NEW.totalCost,
NEW.inventoryId,
NOW()
)
ON DUPLICATE KEY UPDATE
quantity = quantity + NEW.quantity,
totalCost = totalCost + NEW.totalCost,
avgCost = totalCost / quantity;
END IF;
END;
-- ------------------------------------------
-- index: 21
-- Trigger: trg_stock_sale_insert
-- Event: INSERT
-- Table: Stock_Movements
-- ------------------------------------------
DROP TRIGGER IF EXISTS `trg_stock_sale_insert`;
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_sale_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'SALES' THEN
INSERT INTO
Stock_Balance (
productId,
quantity,
avgCost,
totalCost,
inventoryId,
updatedAt
)
VALUES (
NEW.productId,
NEW.quantity,
NEW.unitPrice,
NEW.totalCost,
NEW.inventoryId,
NOW()
)
ON DUPLICATE KEY UPDATE
quantity = quantity - NEW.quantity,
totalCost = totalCost - NEW.totalCost,
avgCost = totalCost / quantity;
END IF;
END;
-657
View File
@@ -1,657 +0,0 @@
-- Stored Procedures equivalent to triggers
DELIMITER / /
-- Procedure for trg_bank_account_transaction_after_insert
CREATE PROCEDURE update_bank_balance(IN p_bankAccountId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2))
BEGIN
START TRANSACTION;
IF p_type = 'DEPOSIT' THEN
UPDATE Bank_Account_Balance SET balance = balance + p_amount WHERE bankAccountId = p_bankAccountId;
ELSEIF p_type = 'WITHDRAWAL' THEN
UPDATE Bank_Account_Balance SET balance = balance - p_amount WHERE bankAccountId = p_bankAccountId;
END IF;
COMMIT;
END //
-- Procedure for trg_bank_account_transaction_after_delete
CREATE PROCEDURE update_bank_balance_on_delete(IN p_bankAccountId INT, IN p_amount DECIMAL(15,2))
BEGIN
START TRANSACTION;
UPDATE Bank_Accounts SET balance = balance - p_amount WHERE id = p_bankAccountId;
COMMIT;
END //
-- Procedure for trg_transfer_item_after_insert
CREATE PROCEDURE process_transfer_item(IN p_transferId INT, IN p_productId INT, IN p_count DECIMAL(10,2))
BEGIN
START TRANSACTION;
DECLARE fromInv INT;
DECLARE toInv INT;
DECLARE _avgCost DECIMAL(10,2);
DECLARE latestQuantityInOrigin DECIMAL(10,2);
DECLARE latestQuantityInDestination DECIMAL(10,2);
SELECT fromInventoryId, toInventoryId INTO fromInv, toInv
FROM Inventory_Transfers WHERE id = p_transferId;
SELECT COALESCE(avgCost, 0), COALESCE(quantity, 0) INTO _avgCost, latestQuantityInOrigin FROM Stock_Balance
WHERE ProductId = p_productId AND inventoryId = fromInv LIMIT 1;
SELECT COALESCE(quantity, 0) INTO latestQuantityInDestination FROM Stock_Balance
WHERE ProductId = p_productId AND inventoryId = toInv LIMIT 1;
-- OUT from source
INSERT INTO Stock_Movements
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
VALUES
('OUT', p_count, _avgCost, _avgCost*p_count, _avgCost, 'INVENTORY_TRANSFER', p_transferId, p_productId, fromInv, toInv, NOW(), latestQuantityInOrigin-p_count);
-- IN to destination
INSERT INTO Stock_Movements
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
VALUES
('IN', p_count, _avgCost, _avgCost*p_count, _avgCost, 'INVENTORY_TRANSFER', p_transferId, p_productId, toInv, fromInv, NOW(), latestQuantityInOrigin-p_count);
COMMIT;
END //
-- Procedure for trg_order_item_after_insert
CREATE PROCEDURE update_stock_reservation_insert(IN p_orderId INT, IN p_productId INT, IN p_quantity DECIMAL(10,2))
BEGIN
START TRANSACTION;
UPDATE Stock_Reservations SET quantity = quantity + p_quantity
WHERE orderId = p_orderId AND productId = p_productId;
COMMIT;
END //
-- Procedure for trg_order_item_after_update
CREATE PROCEDURE update_stock_reservation_update(IN p_orderId INT, IN p_productId INT, IN p_old_quantity DECIMAL(10,2), IN p_new_quantity DECIMAL(10,2))
BEGIN
START TRANSACTION;
UPDATE Stock_Reservations
SET quantity = quantity - p_old_quantity + p_new_quantity
WHERE orderId = p_orderId AND productId = p_productId;
COMMIT;
END //
-- Procedure for trg_order_item_after_delete
CREATE PROCEDURE update_stock_reservation_delete(IN p_orderId INT, IN p_productId INT, IN p_quantity DECIMAL(10,2))
BEGIN
START TRANSACTION;
UPDATE Stock_Reservations SET quantity = quantity - p_quantity
WHERE orderId = p_orderId AND productId = p_productId;
COMMIT;
END //
-- Procedure for trg_order_after_cancel
CREATE PROCEDURE cancel_order_stock(IN p_orderId INT, IN p_status VARCHAR(20))
BEGIN
START TRANSACTION;
IF p_status = 'CANCELED' OR p_status = 'REJECTED' OR p_status = 'DONE' THEN
UPDATE Stock_Reservations sr SET quantity = 0
WHERE sr.orderId = p_orderId;
END IF;
COMMIT;
END //
-- Procedure for trg_purchase_receipt_item_after_insert
CREATE PROCEDURE process_purchase_item(IN p_receiptId INT, IN p_productId INT, IN p_count DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalAmount DECIMAL(15,2))
BEGIN
START TRANSACTION;
DECLARE latestQuantity DECIMAL(10, 2) DEFAULT 0;
DECLARE invId INT;
DECLARE suppId INT;
-- Get inventory & supplier from
SELECT inventoryId, supplierId
INTO invId, suppId
FROM Purchase_Receipts
WHERE id = p_receiptId;
-- Get current stock quantity (if exists)
SELECT COALESCE(quantity, 0)
INTO latestQuantity
FROM Stock_Balance sb
WHERE sb.inventoryId = invId
AND sb.productId = p_productId
LIMIT 1;
-- Insert stock movement
INSERT INTO Stock_Movements (
type,
quantity,
unitPrice,
totalCost,
referenceType,
referenceId,
productId,
inventoryId,
avgCost,
supplierId,
remainedInStock,
createdAt
)
VALUES (
'IN',
p_count,
p_unitPrice,
p_totalAmount,
'PURCHASE',
p_receiptId,
p_productId,
invId,
CASE
WHEN p_count = 0 THEN 0
ELSE p_totalAmount / p_count
END,
suppId,
latestQuantity + p_count,
NOW()
);
COMMIT;
END //
-- Procedure for trg_pr_payment_before_insert
CREATE PROCEDURE validate_payment_before_insert(IN p_receiptId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2))
BEGIN
START TRANSACTION;
DECLARE receiptTotal DECIMAL(14,2);
DECLARE paid DECIMAL(14,2);
SELECT totalAmount, paidAmount
INTO receiptTotal, paid
FROM Purchase_Receipts
WHERE id = p_receiptId
FOR UPDATE;
IF p_type = 'PAYMENT' AND paid + p_amount > receiptTotal THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'مجموع مبلغ پرداختی بیشتر از مبلغ فاکتور است.';
END IF;
COMMIT;
END //
-- Procedure for trg_purchase_payment_update_receipt
CREATE PROCEDURE update_receipt_payment(IN p_receiptId INT)
BEGIN
START TRANSACTION;
DECLARE paid DECIMAL(15,2);
DECLARE total DECIMAL(15,2);
SELECT
COALESCE(SUM(
CASE WHEN type = 'PAYMENT' THEN amount ELSE -amount END
),0)
INTO paid
FROM Purchase_Receipt_Payments
WHERE receiptId = p_receiptId;
SELECT totalAmount INTO total
FROM Purchase_Receipts
WHERE id = p_receiptId;
UPDATE Purchase_Receipts
SET
paidAmount = paid,
status = CASE
WHEN paid = 0 THEN 'UNPAID'
WHEN paid < total THEN 'PARTIALLY_PAID'
ELSE 'PAID'
END
WHERE id = p_receiptId;
COMMIT;
END //
-- Procedure for trg_purchase_payment_after_insert
CREATE PROCEDURE process_purchase_payment(IN p_bankAccountId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2), IN p_id INT)
BEGIN
START TRANSACTION;
DECLARE currentBalance DECIMAL(15, 2);
SELECT balance INTO currentBalance
FROM Bank_Account_Balance
WHERE bankAccountId = p_bankAccountId FOR UPDATE;
IF currentBalance IS NULL THEN SET currentBalance = 0;
INSERT INTO Bank_Account_Balance (bankAccountId, balance, updatedAt)
VALUES (p_bankAccountId, 0, NOW());
END IF;
IF p_type = 'PAYMENT' THEN
SET currentBalance = currentBalance - p_amount;
INSERT INTO Bank_Account_Transactions (
bankAccountId,
type,
amount,
balanceAfter,
referenceType,
referenceId
)
VALUES (
p_bankAccountId,
'WITHDRAWAL',
p_amount,
currentBalance,
'PURCHASE_PAYMENT',
p_id
);
ELSE
SET currentBalance = currentBalance + p_amount;
INSERT INTO Bank_Account_Transactions (
bankAccountId,
type,
amount,
balanceAfter,
referenceType,
referenceId
)
VALUES (
p_bankAccountId,
'DEPOSIT',
p_amount,
currentBalance,
'PURCHASE_REFUND',
p_id
);
END IF;
UPDATE Bank_Account_Balance
SET balance = currentBalance
WHERE bankAccountId = p_bankAccountId;
COMMIT;
END //
-- Procedure for trg_pr_payment_after_insert
CREATE PROCEDURE update_supplier_ledger(IN p_receiptId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2), IN p_id INT)
BEGIN
START TRANSACTION;
DECLARE receiptTotal DECIMAL(14,2) DEFAULT 0;
DECLARE newPaid DECIMAL(14,2) DEFAULT 0;
DECLARE _supplierId INT;
DECLARE lastBalance DECIMAL(14,2) DEFAULT 0;
-- Lock receipt row
SELECT COALESCE(totalAmount, 0), COALESCE(paidAmount, 0), supplierId
INTO receiptTotal, newPaid, _supplierId
FROM Purchase_Receipts
WHERE id = p_receiptId
FOR UPDATE;
-- Apply payment or refund
IF p_type = 'PAYMENT' THEN
SET newPaid = newPaid + p_amount;
ELSE
SET newPaid = newPaid - p_amount;
END IF;
-- Update receipt
UPDATE Purchase_Receipts
SET
paidAmount = newPaid,
status =
CASE
WHEN newPaid = 0 THEN 'UNPAID'
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
ELSE 'PAID'
END
WHERE id = p_receiptId;
-- Get last supplier balance
SELECT IFNULL(balance, 0)
INTO lastBalance
FROM Supplier_Ledger
WHERE supplierId = _supplierId
ORDER BY id DESC
LIMIT 1;
-- Insert supplier ledger
INSERT INTO Supplier_Ledger
(
supplierId,
debit,
credit,
balance,
sourceType,
sourceId,
createdAt
)
VALUES
(
_supplierId,
IF(p_type = 'REFUND', p_amount, 0),
IF(p_type = 'PAYMENT', p_amount, 0),
lastBalance
+ IF(p_type = 'PAYMENT', p_amount, 0)
- IF(p_type = 'REFUND', p_amount, 0),
'PAYMENT',
p_id,
NOW()
);
COMMIT;
END //
-- Procedure for trg_pr_payment_after_delete
CREATE PROCEDURE update_receipt_on_payment_delete(IN p_receiptId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2))
BEGIN
DECLARE receiptTotal DECIMAL(14,2);
DECLARE newPaid DECIMAL(14,2);
SELECT totalAmount, paidAmount
INTO receiptTotal, newPaid
FROM Purchase_Receipts
WHERE id = p_receiptId
FOR UPDATE;
IF p_type = 'PAYMENT' THEN
SET newPaid = newPaid - p_amount;
ELSE
SET newPaid = newPaid + p_amount;
END IF;
UPDATE Purchase_Receipts
SET
paidAmount = newPaid,
status =
CASE
WHEN newPaid = 0 THEN 'UNPAID'
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
ELSE 'PAID'
END
WHERE id = p_receiptId;
END //
-- Procedure for trg_purchase_receipt_after_insert
CREATE PROCEDURE insert_supplier_ledger_purchase(IN p_supplierId INT, IN p_totalAmount DECIMAL(15,2), IN p_id INT)
BEGIN
DECLARE lastBalance DECIMAL(14,2) DEFAULT 0;
SELECT COALESCE(balance, 0)
INTO lastBalance
FROM Supplier_Ledger
WHERE supplierId = p_supplierId
ORDER BY id DESC
LIMIT 1;
INSERT INTO Supplier_Ledger
(
supplierId,
debit,
credit,
balance,
sourceType,
sourceId,
createdAt
)
VALUES
(
p_supplierId,
p_totalAmount,
0,
lastBalance - p_totalAmount,
'PURCHASE',
p_id,
NOW()
);
END //
-- Procedure for trg_sales_invoice_items_before_insert
CREATE PROCEDURE validate_stock_before_sale(IN p_invoiceId INT, IN p_productId INT, IN p_count DECIMAL(10,2))
BEGIN
DECLARE current_stock DECIMAL(10, 2);
DECLARE inventory_id INT;
SELECT pa.inventoryId INTO inventory_id
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = p_invoiceId;
SELECT COALESCE(quantity, 0) INTO current_stock
FROM Stock_Balance sb
WHERE productId = p_productId AND sb.inventoryId = inventory_id
LIMIT 1;
IF p_count > current_stock THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'موجودی کالا در انبار کافی نیست.';
END IF;
END //
-- Procedure for trg_sales_invoice_items_after_insert
CREATE PROCEDURE process_sale_item(IN p_invoiceId INT, IN p_productId INT, IN p_count DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalAmount DECIMAL(15,2))
BEGIN
DECLARE current_stock DECIMAL(10, 2);
DECLARE inventory_id INT;
DECLARE customer_id INT;
DECLARE pos_id INT;
SELECT posAccountId, customerId INTO pos_id, customer_id
FROM Sales_Invoices si
WHERE si.id = p_invoiceId
LIMIT 1;
SELECT pa.inventoryId INTO inventory_id
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = p_invoiceId;
SELECT COALESCE(quantity, 0) INTO current_stock
FROM Stock_Balance sb
WHERE productId = p_productId AND sb.inventoryId = inventory_id
LIMIT 1;
INSERT INTO Stock_Movements (
type,
quantity,
unitPrice,
totalCost,
referenceType,
referenceId,
productId,
inventoryId,
avgCost,
remainedInStock,
customerId,
createdAt
)
VALUES (
'OUT',
p_count,
p_unitPrice,
p_totalAmount,
'SALES',
p_invoiceId,
p_productId,
inventory_id,
CASE
WHEN p_count = 0 THEN 0
ELSE p_totalAmount / p_count
END,
current_stock - p_count,
customer_id,
NOW()
);
END //
-- Procedure for trg_sales_invoice_payment_after_insert
CREATE PROCEDURE process_sale_payment(IN p_invoiceId INT, IN p_amount DECIMAL(15,2), IN p_id INT)
BEGIN
DECLARE currentBalance DECIMAL(15,2);
DECLARE bankAccountId INT;
SELECT pa.bankAccountId INTO bankAccountId
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = p_invoiceId;
SELECT balance INTO currentBalance
FROM Bank_Account_Balance
WHERE bankAccountId = bankAccountId
FOR UPDATE;
IF currentBalance IS NULL THEN
SET currentBalance = 0;
INSERT INTO Bank_Account_Balance (bankAccountId, balance, updatedAt)
VALUES (bankAccountId, 0, NOW());
END IF;
SET currentBalance = currentBalance + p_amount;
INSERT INTO Bank_Account_Transactions
(bankAccountId, type, amount, balanceAfter, referenceType, referenceId)
VALUES
(bankAccountId, 'DEPOSIT', p_amount, currentBalance, 'POS_SALE', p_id);
UPDATE Bank_Account_Balance
SET balance = currentBalance
WHERE bankAccountId = bankAccountId;
END //
-- Procedure for trg_pos_account_payment_after_insert
CREATE PROCEDURE process_pos_payment(IN p_invoiceId INT, IN p_paymentMethod VARCHAR(20), IN p_amount DECIMAL(15,2), IN p_id INT)
BEGIN
DECLARE _bankAccountId INT;
IF(p_paymentMethod != 'CASH') THEN
SELECT cashBankAccountId INTO _bankAccountId
FROM Pos_Accounts pa
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
WHERE si.id = p_invoiceId;
END IF;
INSERT INTO Bank_Account_Transactions (
bankAccountId,
type,
amount,
balanceAfter,
referenceType,
referenceId
)
VALUES(
_bankAccountId,
'DEPOSIT',
p_amount,
0,
'POS_SALE',
p_id
);
END //
-- Procedure for trg_stock_transfer
CREATE PROCEDURE update_stock_balance_transfer(IN p_productId INT, IN p_inventoryId INT, IN p_quantity DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalCost DECIMAL(15,2), IN p_type VARCHAR(10))
BEGIN
IF p_type = 'IN' THEN
INSERT INTO Stock_Balance (
productId,
inventoryId,
quantity,
totalCost,
avgCost,
updatedAt
)
VALUES (
p_productId,
p_inventoryId,
p_quantity,
p_totalCost,
CASE
WHEN p_quantity = 0 THEN 0
ELSE p_totalCost / p_quantity
END,
NOW()
)
ON DUPLICATE KEY UPDATE
quantity = quantity + p_quantity,
totalCost = totalCost + p_totalCost,
avgCost = CASE
WHEN (quantity + p_quantity) = 0 THEN 0
ELSE (totalCost + p_totalCost) / (quantity + p_quantity)
END,
updatedAt = NOW();
END IF;
IF p_type = 'OUT' THEN
IF EXISTS (
SELECT 1
FROM Stock_Balance sb
WHERE sb.productId = p_productId AND sb.inventoryId = p_inventoryId
) THEN
UPDATE Stock_Balance sb
SET
sb.quantity = sb.quantity - p_quantity,
sb.totalCost = sb.totalCost - (sb.avgCost * p_quantity),
sb.updatedAt = NOW()
WHERE
sb.productId = p_productId
AND sb.inventoryId = p_inventoryId;
ELSE
INSERT INTO Stock_Balance (
productId,
inventoryId,
quantity,
totalCost,
avgCost,
updatedAt
)
VALUES (
p_productId,
p_inventoryId,
- p_quantity,
- COALESCE(p_unitPrice, 0) * p_quantity,
COALESCE(p_unitPrice, 0),
NOW()
);
END IF;
END IF;
END //
-- Procedure for trg_stock_purchase_insert
CREATE PROCEDURE update_stock_balance_purchase(IN p_productId INT, IN p_quantity DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalCost DECIMAL(15,2), IN p_inventoryId INT)
BEGIN
INSERT INTO Stock_Balance (
productId,
quantity,
avgCost,
totalCost,
inventoryId,
updatedAt
)
VALUES (
p_productId,
p_quantity,
p_unitPrice,
p_totalCost,
p_inventoryId,
NOW()
)
ON DUPLICATE KEY UPDATE
quantity = quantity + p_quantity,
totalCost = totalCost + p_totalCost,
avgCost = totalCost / quantity;
END //
-- Procedure for trg_stock_sale_insert
CREATE PROCEDURE update_stock_balance_sale(IN p_productId INT, IN p_quantity DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalCost DECIMAL(15,2), IN p_inventoryId INT)
BEGIN
INSERT INTO Stock_Balance (
productId,
quantity,
avgCost,
totalCost,
inventoryId,
updatedAt
)
VALUES (
p_productId,
p_quantity,
p_unitPrice,
p_totalCost,
p_inventoryId,
NOW()
)
ON DUPLICATE KEY UPDATE
quantity = quantity - p_quantity,
totalCost = totalCost - p_totalCost,
avgCost = totalCost / quantity;
END //
DELIMITER;
+55 -56
View File
@@ -1,66 +1,65 @@
#!/usr/bin/env ts-node // #!/usr/bin/env ts-node
import * as fs from 'fs' // import * as fs from 'fs'
import * as path from 'path' // import * as path from 'path'
import { prisma } from '../src/lib/prisma'
function findModules(dir: string): string[] { // function findModules(dir: string): string[] {
const results: string[] = [] // const results: string[] = []
const entries = fs.readdirSync(dir, { withFileTypes: true }) // const entries = fs.readdirSync(dir, { withFileTypes: true })
for (const e of entries) { // for (const e of entries) {
const full = path.join(dir, e.name) // const full = path.join(dir, e.name)
if (e.isDirectory()) { // if (e.isDirectory()) {
results.push(...findModules(full)) // results.push(...findModules(full))
} else if (e.isFile() && e.name.endsWith('.module.ts')) { // } else if (e.isFile() && e.name.endsWith('.module.ts')) {
results.push(full) // results.push(full)
} // }
} // }
return results // return results
} // }
function moduleNameFromFile(filePath: string) { // function moduleNameFromFile(filePath: string) {
const name = path.basename(filePath).replace('.module.ts', '') // const name = path.basename(filePath).replace('.module.ts', '')
return name.replace(/-module$|\.module$/i, '') // return name.replace(/-module$|\.module$/i, '')
} // }
function makePermissionsFor(moduleName: string) { // function makePermissionsFor(moduleName: string) {
const base = moduleName.replace(/\W+/g, '_').toLowerCase() // const base = moduleName.replace(/\W+/g, '_').toLowerCase()
return [`${base}:create`, `${base}:read`, `${base}:update`, `${base}:delete`] // return [`${base}:create`, `${base}:read`, `${base}:update`, `${base}:delete`]
} // }
async function main() { // async function main() {
// const srcDir = path.resolve(__dirname, '..', 'src') // // const srcDir = path.resolve(__dirname, '..', 'src')
// const moduleFiles = findModules(srcDir) // // const moduleFiles = findModules(srcDir)
// const modules = moduleFiles.map(moduleNameFromFile) // // const modules = moduleFiles.map(moduleNameFromFile)
// const permsMap: Record<string, boolean> = {} // // const permsMap: Record<string, boolean> = {}
// for (const m of modules) { // // for (const m of modules) {
// for (const p of makePermissionsFor(m)) permsMap[p] = false // // for (const p of makePermissionsFor(m)) permsMap[p] = false
// } // // }
// // Upsert roles: ensure admin has full permissions, others get entries added // // // Upsert roles: ensure admin has full permissions, others get entries added
// const roles = await prisma.role.findMany() // // const roles = await prisma.role.findMany()
// for (const r of roles) { // // for (const r of roles) {
// const current: Record<string, any> = (r.permissions as any) || {} // // const current: Record<string, any> = (r.permissions as any) || {}
// const merged = { ...permsMap, ...current } // // const merged = { ...permsMap, ...current }
// // If role name is admin (case-insensitive), set all permissions to true // // // If role name is admin (case-insensitive), set all permissions to true
// if (r.name && r.name.toLowerCase() === 'admin') { // // if (r.name && r.name.toLowerCase() === 'admin') {
// for (const key of Object.keys(merged)) merged[key] = true // // for (const key of Object.keys(merged)) merged[key] = true
// } else { // // } else {
// // keep existing truthy values, otherwise false // // // keep existing truthy values, otherwise false
// for (const key of Object.keys(merged)) merged[key] = merged[key] || false // // for (const key of Object.keys(merged)) merged[key] = merged[key] || false
// } // // }
// await prisma.role.update({ where: { id: r.id }, data: { permissions: merged } }) // // await prisma.role.update({ where: { id: r.id }, data: { permissions: merged } })
// console.log( // // console.log(
// `Updated role ${r.name} (id=${r.id}) with ${Object.keys(merged).length} permissions`, // // `Updated role ${r.name} (id=${r.id}) with ${Object.keys(merged).length} permissions`,
// ) // // )
// } // // }
await prisma.$disconnect() // await prisma.$disconnect()
} // }
main().catch(e => { // main().catch(e => {
console.error(e) // console.error(e)
process.exit(1) // process.exit(1)
}) // })
+121 -122
View File
@@ -1,144 +1,143 @@
import fs from 'node:fs' // import fs from 'node:fs'
import path from 'node:path' // import path from 'node:path'
import { prisma } from '../src/lib/prisma'
type CsvRow = { // type CsvRow = {
ID?: string // ID?: string
DescriptionOfID?: string // DescriptionOfID?: string
Vat?: string // Vat?: string
Type?: string // Type?: string
} // }
function parseCsvLine(line: string): string[] { // function parseCsvLine(line: string): string[] {
const result: string[] = [] // const result: string[] = []
let current = '' // let current = ''
let inQuotes = false // let inQuotes = false
for (let index = 0; index < line.length; index++) { // for (let index = 0; index < line.length; index++) {
const char = line[index] // const char = line[index]
if (char === '"') { // if (char === '"') {
if (inQuotes && line[index + 1] === '"') { // if (inQuotes && line[index + 1] === '"') {
current += '"' // current += '"'
index++ // index++
} else { // } else {
inQuotes = !inQuotes // inQuotes = !inQuotes
} // }
continue // continue
} // }
if (char === ',' && !inQuotes) { // if (char === ',' && !inQuotes) {
result.push(current) // result.push(current)
current = '' // current = ''
continue // continue
} // }
current += char // current += char
} // }
result.push(current) // result.push(current)
return result.map(value => value.trim()) // return result.map(value => value.trim())
} // }
function parseCsv(content: string): CsvRow[] { // function parseCsv(content: string): CsvRow[] {
const lines = content // const lines = content
.split(/\r?\n/) // .split(/\r?\n/)
.map(line => line.trim()) // .map(line => line.trim())
.filter(Boolean) // .filter(Boolean)
if (!lines.length) return [] // if (!lines.length) return []
const headers = parseCsvLine(lines[0]) // const headers = parseCsvLine(lines[0])
return lines.slice(1).map(line => { // return lines.slice(1).map(line => {
const cols = parseCsvLine(line) // const cols = parseCsvLine(line)
const row: Record<string, string> = {} // const row: Record<string, string> = {}
for (let index = 0; index < headers.length; index++) { // for (let index = 0; index < headers.length; index++) {
row[headers[index]] = cols[index] || '' // row[headers[index]] = cols[index] || ''
} // }
return row // return row
}) // })
} // }
function toBooleanFlags(typeValue: string) { // function toBooleanFlags(typeValue: string) {
const normalized = typeValue || '' // const normalized = typeValue || ''
const isPublic = normalized.includes('شناسه عمومی') // const isPublic = normalized.includes('شناسه عمومی')
const isImported = normalized.includes('وارداتی') // const isImported = normalized.includes('وارداتی')
const isDomestic = !isImported // const isDomestic = !isImported
return { isPublic, isDomestic } // return { isPublic, isDomestic }
} // }
function parseVat(vatValue: string) { // function parseVat(vatValue: string) {
const parsed = Number(vatValue || '0') // const parsed = Number(vatValue || '0')
if (!Number.isFinite(parsed)) return 0 // if (!Number.isFinite(parsed)) return 0
return parsed // return parsed
} // }
async function main() { // async function main() {
const defaultPath = // const defaultPath =
'/Users/ahasani/Desktop/product_good_2026-05-01T11-35-57_part_1_28812448-0dd9-411c-99e1-334c28d781fe.csv' // '/Users/ahasani/Desktop/product_good_2026-05-01T11-35-57_part_1_28812448-0dd9-411c-99e1-334c28d781fe.csv'
const csvPath = process.argv[2] || defaultPath // const csvPath = process.argv[2] || defaultPath
const absolutePath = path.resolve(csvPath) // const absolutePath = path.resolve(csvPath)
if (!fs.existsSync(absolutePath)) { // if (!fs.existsSync(absolutePath)) {
throw new Error(`CSV file not found: ${absolutePath}`) // throw new Error(`CSV file not found: ${absolutePath}`)
} // }
const raw = fs.readFileSync(absolutePath, 'utf8').replace(/^\uFEFF/, '') // const raw = fs.readFileSync(absolutePath, 'utf8').replace(/^\uFEFF/, '')
const rows = parseCsv(raw) // const rows = parseCsv(raw)
let upserted = 0 // let upserted = 0
let skipped = 0 // let skipped = 0
const guild = await prisma.guild.findFirst({}) // const guild = await prisma.guild.findFirst({})
for (const row of rows) { // for (const row of rows) {
const code = (row.ID || '').trim() // const code = (row.ID || '').trim()
const name = (row.DescriptionOfID || '').trim() // const name = (row.DescriptionOfID || '').trim()
const vat = parseVat((row.Vat || '').trim()) // const vat = parseVat((row.Vat || '').trim())
const type = (row.Type || '').trim() // const type = (row.Type || '').trim()
const { isPublic, isDomestic } = toBooleanFlags(type) // const { isPublic, isDomestic } = toBooleanFlags(type)
if (!code || !name) { // if (!code || !name) {
skipped++ // skipped++
continue // continue
} // }
await prisma.stockKeepingUnits.upsert({ // await prisma.stockKeepingUnits.upsert({
where: { code }, // where: { code },
create: { // create: {
code, // code,
name, // name,
VAT: vat, // VAT: vat,
guild: { // guild: {
connect: { // connect: {
id: guild?.id, // id: guild?.id,
}, // },
}, // },
is_public: isPublic, // is_public: isPublic,
is_domestic: isDomestic, // is_domestic: isDomestic,
}, // },
update: { // update: {
name, // name,
VAT: vat, // VAT: vat,
guild: { // guild: {
connect: { // connect: {
id: guild?.id, // id: guild?.id,
}, // },
}, // },
is_public: isPublic, // is_public: isPublic,
is_domestic: isDomestic, // is_domestic: isDomestic,
}, // },
}) // })
upserted++ // upserted++
} // }
} // }
main() // main()
.catch(error => { // .catch(error => {
console.error(error) // console.error(error)
process.exit(1) // process.exit(1)
}) // })
.finally(async () => { // .finally(async () => {
await prisma.$disconnect() // await prisma.$disconnect()
}) // })
+14 -5
View File
@@ -1,4 +1,8 @@
import { TspProviderResponseStatus } from '@/generated/prisma/enums' import {
InvoiceSettlementType,
TspProviderRequestType,
TspProviderResponseStatus,
} from '@/generated/prisma/enums'
export default { export default {
PaymentMethodType: { PaymentMethodType: {
@@ -144,11 +148,16 @@ export default {
[TspProviderResponseStatus.FISCAL_QUEUED]: 'در انتظار تایید سازمان', [TspProviderResponseStatus.FISCAL_QUEUED]: 'در انتظار تایید سازمان',
[TspProviderResponseStatus.SEND_FAILURE]: 'خطا در ارسال', [TspProviderResponseStatus.SEND_FAILURE]: 'خطا در ارسال',
}, },
InvoiceSettlementType: {
[InvoiceSettlementType.CASH]: 'نقدی',
[InvoiceSettlementType.CREDIT]: 'نسیه',
[InvoiceSettlementType.MIXED]: 'نقدی / نسیه',
},
TspProviderRequestType: { TspProviderRequestType: {
ORIGINAL: 'اصلی', [TspProviderRequestType.ORIGINAL]: 'اصلی',
CORRECTION: 'اصلاح', [TspProviderRequestType.CORRECTION]: 'اصلاح',
REVOKE: 'ابطال', [TspProviderRequestType.REVOKE]: 'ابطال',
REMOVE: 'حذف', [TspProviderRequestType.RETURN]: 'برگشت از فروش',
}, },
TspProviderCustomerType: { TspProviderCustomerType: {
Unknown: 'ناشناس', Unknown: 'ناشناس',
@@ -24,9 +24,10 @@ export const summarySelect: BusinessActivitySelect = {
select: { select: {
activation: { activation: {
select: { select: {
_count: { account_allocations: {
select: { select: {
account_allocations: true, id: true,
account_id: true,
}, },
}, },
}, },
@@ -44,13 +45,18 @@ export const select: BusinessActivitySelect = {
export const mappedData = (businessActivity: any) => { export const mappedData = (businessActivity: any) => {
const { license_activation, ...rest } = businessActivity const { license_activation, ...rest } = businessActivity
const { license, ...license_activation_rest } = license_activation const { license, ...license_activation_rest } = license_activation
const { _count } = license.activation const { account_allocations } = license.activation
console.log('license_activation', license_activation)
return { return {
...rest, ...rest,
license_info: { license_info: {
...license_activation_rest, ...license_activation_rest,
accounts_limit: _count.account_allocations, accounts_limit: account_allocations.length,
allocated_account_count: account_allocations.filter(
allocation => allocation.account_id,
).length,
}, },
} }
} }
+18 -24
View File
@@ -11,6 +11,10 @@ export const summarySelect: SalesInvoiceSelect = {
type: true, type: true,
notes: true, notes: true,
created_at: true, created_at: true,
settlement_type: true,
unknown_customer: true,
last_attempt_no: true,
last_tsp_status: true,
customer: { customer: {
select: { select: {
type: true, type: true,
@@ -20,6 +24,8 @@ export const summarySelect: SalesInvoiceSelect = {
last_name: true, last_name: true,
mobile_number: true, mobile_number: true,
national_id: true, national_id: true,
economic_code: true,
postal_code: true,
}, },
}, },
legal: { legal: {
@@ -27,22 +33,18 @@ export const summarySelect: SalesInvoiceSelect = {
name: true, name: true,
economic_code: true, economic_code: true,
registration_number: true, registration_number: true,
postal_code: true,
}, },
}, },
}, },
}, },
tsp_attempts: { reference_invoice: {
orderBy: {
created_at: 'desc',
},
take: 1,
select: { select: {
status: true, id: true,
sent_at: true, invoice_number: true,
message: true,
}, },
}, },
reference_invoice: { referenced_by: {
select: { select: {
id: true, id: true,
invoice_number: true, invoice_number: true,
@@ -56,6 +58,7 @@ export const select: SalesInvoiceSelect = {
tax_amount: true, tax_amount: true,
updated_at: true, updated_at: true,
unknown_customer: true, unknown_customer: true,
pos: { pos: {
select: { select: {
id: true, id: true,
@@ -68,6 +71,12 @@ export const select: SalesInvoiceSelect = {
select: { select: {
id: true, id: true,
name: true, name: true,
economic_code: true,
guild: {
select: {
name: true,
},
},
}, },
}, },
}, },
@@ -122,19 +131,4 @@ export const select: SalesInvoiceSelect = {
}, },
}, },
}, },
tsp_attempts: {
orderBy: {
created_at: 'desc',
},
select: {
id: true,
attempt_no: true,
status: true,
message: true,
sent_at: true,
received_at: true,
created_at: true,
},
take: 1,
},
} }
@@ -21,7 +21,7 @@ export class SharedSaleInvoiceAccessService {
}) })
if (!consumer) { if (!consumer) {
throw new BadRequestException('شما دسترسی لازم برای ارسال فاکتور را ندارید.') throw new BadRequestException('شما دسترسی لازم برای ارسال صورت‌حساب را ندارید.')
} }
return consumer.consumer_id return consumer.consumer_id
@@ -1,12 +1,25 @@
import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service' import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service'
import { Injectable } from '@nestjs/common' import {
PosCorrectionSalesInvoiceDto,
PosReturnSalesInvoiceDto,
} from '@/modules/pos/sales-invoices/dto/create-sales-invoice.dto'
import { SalesInvoiceTspService } from '@/modules/tspProviders/sales-invoice-tsp.service' import { SalesInvoiceTspService } from '@/modules/tspProviders/sales-invoice-tsp.service'
import { PrismaService } from '@/prisma/prisma.service'
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'
import {
CustomerType,
TspProviderRequestType,
TspProviderResponseStatus,
} from 'generated/prisma/enums'
import { SharedSaleInvoiceCreateService } from './sale-invoice-create.service'
@Injectable() @Injectable()
export class SharedSaleInvoiceActionsService { export class SharedSaleInvoiceActionsService {
constructor( constructor(
private prisma: PrismaService,
private readonly salesInvoiceTspService: SalesInvoiceTspService, private readonly salesInvoiceTspService: SalesInvoiceTspService,
private readonly saleInvoiceAccessService: SharedSaleInvoiceAccessService, private readonly saleInvoiceAccessService: SharedSaleInvoiceAccessService,
private sharedSaleInvoiceCreateService: SharedSaleInvoiceCreateService,
) {} ) {}
async send(consumerAccountId: string, posId: string, invoiceId: string) { async send(consumerAccountId: string, posId: string, invoiceId: string) {
@@ -45,6 +58,478 @@ export class SharedSaleInvoiceActionsService {
) )
} }
async correction(
data: PosCorrectionSalesInvoiceDto,
consumerAccountId: string,
posId: string,
complexId: string,
businessId: string,
invoiceId: string,
) {
await this.saleInvoiceAccessService.getConsumerIdWithPosAccess(
consumerAccountId,
posId,
)
const newInvoice = await this.prisma.$transaction(async tx => {
const relatedInvoice = await tx.salesInvoice.findUnique({
where: {
id: invoiceId,
pos_id: posId,
},
select: {
id: true,
invoice_date: true,
settlement_type: true,
customer_id: true,
main_id: true,
last_tsp_status: true,
referenced_by: {
select: {
id: true,
},
},
customer: {
select: {
type: true,
},
},
total_amount: true,
items: {
select: {
id: true,
good_id: true,
service_id: true,
quantity: true,
unit_price: true,
total_amount: true,
discount_amount: true,
tax_amount: true,
payload: true,
notes: true,
},
},
},
})
if (!relatedInvoice) {
throw new NotFoundException('صورت‌حساب مورد نظر شما یافت نشد.')
}
if (relatedInvoice.last_tsp_status !== TspProviderResponseStatus.SUCCESS) {
throw new BadRequestException('امکان اصلاح این صورت‌حساب وجود ندارد.')
}
if (relatedInvoice.referenced_by) {
throw new BadRequestException(
'این صورت‌حساب قبلا با یک صورت‌حساب دیگر جایگزین شده است.',
)
}
const normalizedInvoiceDate = this.normalizeInvoiceDate(data.invoice_date)
const originalInvoiceDate = this.normalizeInvoiceDate(relatedInvoice.invoice_date)
const originalItemsByKey = new Map(
relatedInvoice.items.map(item => [this.getItemKey(item), item]),
)
const usedItemKeys = new Set<string>()
const normalizedItems = data.items.map(item => {
const itemKey = this.getItemKey(item)
if (!itemKey) {
throw new BadRequestException('هر قلم باید شناسه کالا یا خدمت داشته باشد.')
}
usedItemKeys.add(itemKey)
const originalItem = originalItemsByKey.get(itemKey)
if (!originalItem) {
throw new BadRequestException(
'فقط اقلام موجود در صورت‌حساب اصلی قابل اصلاح هستند.',
)
}
const originalQuantity = Number(originalItem.quantity)
const requestedQuantity = Number(item.quantity)
const originalUnitPrice = Number(originalItem.unit_price)
const requestedUnitPrice = Number(item.unit_price)
const originalTotalAmount = this.roundAmount(Number(originalItem.total_amount))
const requestedTotalAmount = this.roundAmount(Number(item.total_amount))
if (requestedQuantity <= 0) {
throw new BadRequestException(
'تعداد/مقدار اقلام اصلاحی باید بیشتر از صفر باشد.',
)
}
// if (requestedUnitPrice < originalUnitPrice) {
// throw new BadRequestException(
// 'مبلغ واحد اقلام اصلاحی نمی‌تواند کمتر از صورت‌حساب اصلی باشد.',
// )
// }
return {
invoice_id: originalItem.id,
good_id: originalItem.good_id,
service_id: originalItem.service_id || undefined,
quantity: requestedQuantity,
unit_price: requestedUnitPrice,
total_amount: requestedTotalAmount,
discount_amount: this.roundAmount(Number(item.discount_amount || 0)),
tax_amount: this.roundAmount(Number(item.tax_amount || 0)),
payload: item.payload ? JSON.parse(JSON.stringify(item.payload)) : undefined,
notes: item.notes || undefined,
}
})
if (usedItemKeys.size !== relatedInvoice.items.length) {
throw new BadRequestException(
'فقط اقلام موجود در صورت‌حساب اصلی قابل اصلاح هستند.',
)
}
const hasChangedQuantity = normalizedItems.some(item => {
const originalItem = relatedInvoice.items.find(
relatedItem => this.getItemKey(relatedItem) === this.getItemKey(item),
)
if (!originalItem) {
return false
}
return Number(originalItem.quantity) !== Number(item.quantity)
})
const hasChangedAmount = normalizedItems.some(item => {
const originalItem = relatedInvoice.items.find(
relatedItem => this.getItemKey(relatedItem) === this.getItemKey(item),
)
if (!originalItem) {
return false
}
return (
this.roundAmount(Number(originalItem.total_amount)) !==
this.roundAmount(Number(item.total_amount))
)
})
const hasChangedInvoiceDate = normalizedInvoiceDate !== originalInvoiceDate
if (!hasChangedQuantity && !hasChangedAmount && !hasChangedInvoiceDate) {
throw new BadRequestException('مقداری تغییر نکرده است.')
}
const requestedTotalAmount = this.roundAmount(Number(data.total_amount))
const originalTotalAmount = this.roundAmount(Number(relatedInvoice.total_amount))
const totalDiff = this.roundAmount(requestedTotalAmount - originalTotalAmount)
const paymentsAmount = this.roundAmount(this.getPaymentsAmount(data.payments))
if (totalDiff > 0 && paymentsAmount !== totalDiff) {
throw new BadRequestException(
'جمع پرداختی باید برابر با اختلاف مبلغ صورت‌حساب اصلاحی و صورت‌حساب مرجع باشد.',
)
}
if (totalDiff === 0 && paymentsAmount !== 0) {
throw new BadRequestException('در صورت عدم افزایش مبلغ، پرداختی نباید ثبت شود.')
}
const newInvoice = await this.sharedSaleInvoiceCreateService.create({
tx,
data: {
invoice_date: new Date(normalizedInvoiceDate),
items: normalizedItems as any,
total_amount: requestedTotalAmount,
discount_amount: this.roundAmount(Number(data.discount_amount)),
tax_amount: this.roundAmount(Number(data.tax_amount)),
customer_id: relatedInvoice.customer_id || undefined,
customer_type: relatedInvoice.customer?.type || CustomerType.UNKNOWN,
settlement_type: relatedInvoice.settlement_type,
payments: data.payments,
} as any,
businessId,
complexId,
posId,
consumerAccountId,
main_invoice_id: relatedInvoice.main_id || relatedInvoice.id,
ref_invoice_id: relatedInvoice.id,
type: TspProviderRequestType.CORRECTION,
})
await tx.salesInvoice.update({
where: {
id: relatedInvoice.id,
},
data: {
referenced_by: {
connect: {
id: newInvoice.id,
},
},
},
})
return newInvoice
})
return this.salesInvoiceTspService.correctionSend(posId, newInvoice.id)
}
async return(
data: PosReturnSalesInvoiceDto,
consumerAccountId: string,
pos_id: string,
complex_id: string,
business_id: string,
invoiceId: string,
) {
await this.saleInvoiceAccessService.getConsumerIdWithPosAccess(
consumerAccountId,
pos_id,
)
const newInvoice = await this.prisma.$transaction(async tx => {
const relatedInvoice = await tx.salesInvoice.findUnique({
where: {
id: invoiceId,
pos_id,
},
select: {
id: true,
type: true,
invoice_date: true,
settlement_type: true,
customer_id: true,
main_id: true,
last_tsp_status: true,
referenced_by: {
select: {
id: true,
},
},
customer: {
select: {
type: true,
},
},
items: {
select: {
id: true,
good_id: true,
service_id: true,
quantity: true,
unit_price: true,
total_amount: true,
discount_amount: true,
tax_amount: true,
payload: true,
notes: true,
},
},
},
})
if (!relatedInvoice) {
throw new NotFoundException('صورت‌حساب مورد نظر شما یافت نشد.')
}
if (relatedInvoice.last_tsp_status !== TspProviderResponseStatus.SUCCESS) {
throw new BadRequestException('امکان برگشت از خرید روی این صورت‌حساب وجود ندارد.')
}
if (relatedInvoice.referenced_by) {
throw new BadRequestException(
'این صورت‌حساب قبلا با یک صورت‌حساب دیگر جایگزین شده است.',
)
}
const normalizedInvoiceDate = this.normalizeInvoiceDate(data.invoice_date)
const originalInvoiceDate = this.normalizeInvoiceDate(relatedInvoice.invoice_date)
const originalItemsByKey = new Map(
relatedInvoice.items.map(item => [this.getReturnItemKey(item), item]),
)
const usedItemKeys = new Set<string>()
const normalizedItems = data.items.map(item => {
const itemKey = this.getReturnItemKey(item)
if (!itemKey) {
throw new BadRequestException('هر قلم باید شناسه کالا یا خدمت داشته باشد.')
}
// if (usedItemKeys.has(itemKey)) {
// throw new BadRequestException('اقلام تکراری در صورت‌حساب بازگشتی مجاز نیستند.')
// }
usedItemKeys.add(itemKey)
const originalItem = originalItemsByKey.get(itemKey)
if (!originalItem) {
throw new BadRequestException(
'فقط اقلام موجود در صورت‌حساب اصلی قابل بازگشت هستند.',
)
}
const originalQuantity = Number(originalItem.quantity)
const requestedQuantity = Number(item.quantity)
if (requestedQuantity <= 0) {
throw new BadRequestException(
'تعداد/مقدار اقلام بازگشتی باید بیشتر از صفر باشد.',
)
}
if (requestedQuantity > originalQuantity) {
throw new BadRequestException(
'تعداد/مقدار اقلام بازگشتی نمی‌تواند از مقدار صورت‌حساب اصلی بیشتر باشد.',
)
}
const quantityRatio = requestedQuantity / originalQuantity
return {
invoice_id: originalItem.id,
good_id: originalItem.good_id,
service_id: originalItem.service_id || undefined,
quantity: requestedQuantity,
unit_price: Number(originalItem.unit_price),
total_amount: this.roundAmount(
Number(originalItem.total_amount) * quantityRatio,
),
discount_amount: this.roundAmount(
Number(originalItem.discount_amount || 0) * quantityRatio,
),
tax_amount: this.roundAmount(
Number(originalItem.tax_amount || 0) * quantityRatio,
),
payload: originalItem.payload
? JSON.parse(JSON.stringify(originalItem.payload))
: undefined,
notes: originalItem.notes || undefined,
}
})
if (!normalizedItems.length) {
throw new BadRequestException(
'حداقل یک قلم باید در صورت‌حساب بازگشتی باقی بماند.',
)
}
const hasRemovedItem = relatedInvoice.items.some(
item => !usedItemKeys.has(this.getReturnItemKey(item)),
)
const hasChangedQuantity = normalizedItems.some(item => {
const originalItem = relatedInvoice.items.find(
relatedItem =>
this.getReturnItemKey(relatedItem) === this.getReturnItemKey(item),
)
if (!originalItem) {
return false
}
return Number(originalItem.quantity) !== Number(item.quantity)
})
const hasChangedInvoiceDate = normalizedInvoiceDate !== originalInvoiceDate
if (!hasRemovedItem && !hasChangedQuantity && !hasChangedInvoiceDate) {
throw new BadRequestException('مقداری تغییر نکرده است.')
}
const totalAmount = normalizedItems.reduce(
(sum, item) => sum + Number(item.total_amount),
0,
)
const discountAmount = normalizedItems.reduce(
(sum, item) => sum + Number(item.discount_amount || 0),
0,
)
const taxAmount = normalizedItems.reduce(
(sum, item) => sum + Number(item.tax_amount || 0),
0,
)
const newInvoice = await this.sharedSaleInvoiceCreateService.create({
tx,
data: {
invoice_date: new Date(normalizedInvoiceDate),
items: normalizedItems as any,
total_amount: totalAmount,
discount_amount: discountAmount,
tax_amount: taxAmount,
customer_id: relatedInvoice.customer_id || undefined,
customer_type: relatedInvoice.customer?.type || CustomerType.UNKNOWN,
settlement_type: relatedInvoice.settlement_type,
payments: undefined,
} as any,
businessId: business_id,
complexId: complex_id,
posId: pos_id,
consumerAccountId,
main_invoice_id: relatedInvoice.main_id || relatedInvoice.id,
ref_invoice_id: relatedInvoice.id,
type: TspProviderRequestType.RETURN,
})
await tx.salesInvoice.update({
where: {
id: relatedInvoice.id,
},
data: {
referenced_by: {
connect: {
id: newInvoice.id,
},
},
},
})
return newInvoice
})
return this.salesInvoiceTspService.returnFromSaleSend(
pos_id,
business_id,
newInvoice.id,
)
}
private normalizeInvoiceDate(invoiceDate: Date | string) {
return new Date(invoiceDate).toISOString()
}
private getItemKey(item: { good_id?: string | null; service_id?: string | null }) {
return item.good_id || item.service_id || ''
}
private getPaymentsAmount(payments?: {
terminals?: { amount?: number }
cash?: number
set_off?: number
card?: number
bank?: number
check?: number
other?: number
}) {
return (
Number(payments?.terminals?.amount || 0) +
Number(payments?.cash || 0) +
Number(payments?.set_off || 0) +
Number(payments?.card || 0) +
Number(payments?.bank || 0) +
Number(payments?.check || 0) +
Number(payments?.other || 0)
)
}
private roundAmount(amount: number) {
return Number(amount.toFixed(2))
}
async inquiry(consumerAccountId: string, posId: string, invoiceId: string) { async inquiry(consumerAccountId: string, posId: string, invoiceId: string) {
const consumerId = await this.saleInvoiceAccessService.getConsumerIdWithPosAccess( const consumerId = await this.saleInvoiceAccessService.getConsumerIdWithPosAccess(
consumerAccountId, consumerAccountId,
@@ -52,4 +537,11 @@ export class SharedSaleInvoiceActionsService {
) )
return this.salesInvoiceTspService.get(invoiceId, posId, consumerId) return this.salesInvoiceTspService.get(invoiceId, posId, consumerId)
} }
private getReturnItemKey(item: {
good_id?: string | null
service_id?: string | null
}) {
return item.good_id || item.service_id || ''
}
} }
@@ -1,5 +1,5 @@
import type { SaleInvoiceType } from '@/common/interfaces/sale-invoice-payload' import type { SaleInvoiceType } from '@/common/interfaces/sale-invoice-payload'
import { ApiProperty } from '@nestjs/swagger' import { ApiProperty, OmitType } from '@nestjs/swagger'
import { Type } from 'class-transformer' import { Type } from 'class-transformer'
import { import {
ArrayMinSize, ArrayMinSize,
@@ -83,7 +83,7 @@ export class SharedCreateTerminalPayment {
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
@ApiProperty({ required: true }) @ApiProperty({ required: true })
terminalId: string terminal_id: string
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
@@ -196,6 +196,11 @@ export class SharedCreateSalesInvoiceDto {
@ValidateNested({ each: true }) @ValidateNested({ each: true })
items: SharedCreateSalesInvoiceItemDto[] items: SharedCreateSalesInvoiceItemDto[]
@ApiProperty({ required: false })
@IsOptional()
@IsString()
ref_invoice_id?: string
@ApiProperty({ required: false }) @ApiProperty({ required: false })
@IsOptional() @IsOptional()
@IsString() @IsString()
@@ -206,8 +211,6 @@ export class SharedCreateSalesInvoiceDto {
@IsBoolean() @IsBoolean()
send_to_tsp?: boolean send_to_tsp?: boolean
@ApiProperty({ required: true, default: CustomerType.UNKNOWN }) @ApiProperty({ required: true, default: CustomerType.UNKNOWN })
@IsEnum(CustomerType) @IsEnum(CustomerType)
customer_type: CustomerType customer_type: CustomerType
@@ -229,3 +232,16 @@ export class SharedCreateSalesInvoiceDto {
} }
} }
} }
export class SharedCorrectionSalesInvoiceDto extends OmitType(
SharedCreateSalesInvoiceDto,
['customer', 'customer_id', 'customer_type', 'settlement_type'],
) {}
export class SharedReturnSalesInvoiceDto extends OmitType(SharedCreateSalesInvoiceDto, [
'customer',
'customer_id',
'customer_type',
'settlement_type',
'payments',
]) {}
@@ -23,6 +23,7 @@ interface TerminalPaymentInfo {
interface NormalizedPayment { interface NormalizedPayment {
method: PaymentMethodType method: PaymentMethodType
amount: number amount: number
terminalInfo?: TerminalPaymentInfo
} }
interface CreateSharedSaleInvoiceInput { interface CreateSharedSaleInvoiceInput {
@@ -57,10 +58,10 @@ export class SharedSaleInvoiceCreateService {
} = input } = input
const normalizedInvoiceDate = this.normalizeInvoiceDate(data.invoice_date) const normalizedInvoiceDate = this.normalizeInvoiceDate(data.invoice_date)
const { payments, terminalInfo } = this.buildPaymentsData( const payments =
data.payments, type === TspProviderRequestType.ORIGINAL || data.payments
data.total_amount, ? this.buildPaymentsData(data.payments, data.total_amount)
) : []
for (let attempt = 1; attempt <= this.createInvoiceRetries; attempt++) { for (let attempt = 1; attempt <= this.createInvoiceRetries; attempt++) {
try { try {
@@ -88,13 +89,14 @@ export class SharedSaleInvoiceCreateService {
select: { ...QUERY_CONSTANTS.SALE_INVOICE.select }, select: { ...QUERY_CONSTANTS.SALE_INVOICE.select },
}) })
await this.createPayments( if (payments.length) {
$tx, await this.createPayments(
salesInvoice.id, $tx,
payments, salesInvoice.id,
terminalInfo, payments,
normalizedInvoiceDate, normalizedInvoiceDate,
) )
}
return salesInvoice return salesInvoice
}) })
@@ -109,7 +111,7 @@ export class SharedSaleInvoiceCreateService {
} }
} }
throw new BadRequestException('ایجاد فاکتور با خطا مواجه شد.') throw new BadRequestException('ایجاد صورت‌حساب با خطا مواجه شد.')
} }
private isRetryableInvoiceConflict(error: unknown) { private isRetryableInvoiceConflict(error: unknown) {
@@ -148,7 +150,7 @@ export class SharedSaleInvoiceCreateService {
} }
const rawPayments = (paymentsData || {}) as Record<string, unknown> const rawPayments = (paymentsData || {}) as Record<string, unknown>
const terminalInfo = rawPayments.terminals as TerminalPaymentInfo | undefined const terminalPayments = rawPayments.terminals as TerminalPaymentInfo[] | undefined
const payments: NormalizedPayment[] = Object.entries(rawPayments) const payments: NormalizedPayment[] = Object.entries(rawPayments)
.filter(([key, value]) => key !== 'terminals' && value && Number(value) > 0) .filter(([key, value]) => key !== 'terminals' && value && Number(value) > 0)
@@ -158,54 +160,31 @@ export class SharedSaleInvoiceCreateService {
})) }))
.filter(payment => payment.method && payment.amount > 0) as NormalizedPayment[] .filter(payment => payment.method && payment.amount > 0) as NormalizedPayment[]
const hasTerminalPayment = payments.some( const hasTerminalPayment = terminalPayments && terminalPayments.length
payment => payment.method === PaymentMethodType.TERMINAL,
)
const nonTerminalTotal = payments
.filter(payment => payment.method !== PaymentMethodType.TERMINAL)
.reduce((sum, payment) => sum + payment.amount, 0)
if (!hasTerminalPayment && terminalInfo) { if (hasTerminalPayment) {
const terminalAmount = for (const terminal of terminalPayments) {
typeof terminalInfo.amount === 'number'
? terminalInfo.amount
: Math.max(0, Number(totalAmount) - nonTerminalTotal)
if (terminalAmount > 0) {
payments.push({ payments.push({
method: PaymentMethodType.TERMINAL, method: PaymentMethodType.TERMINAL,
amount: terminalAmount, amount: terminal.amount,
terminalInfo: terminal,
}) })
} }
} }
this.validatePayments(payments, totalAmount, terminalInfo) //TODO: for correction i need to validate payments with diff of total amount and original invoice amount
// this.validatePayments(payments, totalAmount)
return { return payments
payments,
terminalInfo,
}
} }
private validatePayments( private validatePayments(payments: NormalizedPayment[], totalAmount: number) {
payments: NormalizedPayment[],
totalAmount: number,
terminalInfo?: TerminalPaymentInfo,
) {
const totalPayments = payments.reduce((sum, payment) => sum + payment.amount, 0) const totalPayments = payments.reduce((sum, payment) => sum + payment.amount, 0)
const roundedTotalPayments = Number(totalPayments.toFixed(2)) const roundedTotalPayments = Number(totalPayments.toFixed(2))
const roundedTotalAmount = Number(Number(totalAmount).toFixed(2)) const roundedTotalAmount = Number(Number(totalAmount).toFixed(2))
if (roundedTotalPayments !== roundedTotalAmount) { if (roundedTotalPayments !== roundedTotalAmount) {
throw new BadRequestException('مبلغ پرداختی باید برابر با مبلغ کل فاکتور باشد.') throw new BadRequestException('مبلغ پرداختی باید برابر با مبلغ کل صورت‌حساب باشد.')
}
const terminalPayments = payments.filter(
payment => payment.method === PaymentMethodType.TERMINAL,
)
if (terminalPayments.length > 0 && !terminalInfo) {
throw new BadRequestException('برای پرداخت ترمینال اطلاعات ترمینال الزامی است.')
} }
} }
@@ -214,84 +193,124 @@ export class SharedSaleInvoiceCreateService {
data: SharedCreateSalesInvoiceDto, data: SharedCreateSalesInvoiceDto,
businessId: string, businessId: string,
) { ) {
if (data.customer_id) { const { customer_id, customer_type, customer } = data
return data.customer_id
if (customer_id) {
return customer_id
} }
if ( if (customer_type === CustomerType.INDIVIDUAL && customer?.customer_individual) {
data.customer_type === CustomerType.INDIVIDUAL && const { national_id, postal_code, economic_code, ...rest } =
data.customer?.customer_individual customer.customer_individual
) {
const { national_id, mobile_number, ...rest } = data.customer.customer_individual
const customerIndividual = await tx.customerIndividual.upsert({ const foundedCustomer = await tx.customerIndividual.findFirst({
where: { where: {
business_activity_id_national_id: { business_activity_id: businessId,
business_activity_id: businessId, OR: [
national_id: data.customer.customer_individual.national_id, {
}, economic_code,
},
create: {
...data.customer.customer_individual,
customer: {
create: {
type: CustomerType.INDIVIDUAL,
}, },
}, {
business_activity: { postal_code,
connect: { national_id,
id: businessId,
}, },
}, ],
},
update: { ...rest },
select: {
customer_id: true,
},
})
if (!customerIndividual) {
throw new BadRequestException('متاسفانه مشکلی در اطلاعات مشتری وجود دارد.')
}
return customerIndividual.customer_id
}
if (data.customer_type === CustomerType.LEGAL && data.customer?.customer_legal) {
const { registration_number, ...rest } = data.customer.customer_legal
const customerLegal = await tx.customerLegal.upsert({
where: {
business_activity_id_economic_code: {
business_activity_id: businessId,
economic_code: data.customer.customer_legal.economic_code,
},
},
create: {
...data.customer.customer_legal,
customer: {
create: {
type: CustomerType.LEGAL,
},
},
business_activity: {
connect: {
id: businessId,
},
},
},
update: {
...rest,
}, },
select: { select: {
customer_id: true, customer_id: true,
}, },
}) })
let customerIndividualId: string | undefined = foundedCustomer?.customer_id
if (!customerLegal) { if (foundedCustomer) {
await tx.customerIndividual.update({
where: {
customer_id: foundedCustomer.customer_id,
},
data: {
...customer.customer_individual,
},
})
} else {
const createdCustomer = await tx.customerIndividual.create({
data: {
...customer.customer_individual,
customer: {
create: {
type: CustomerType.INDIVIDUAL,
},
},
business_activity: {
connect: {
id: businessId,
},
},
},
})
customerIndividualId = createdCustomer.customer_id
}
if (!customerIndividualId) {
throw new BadRequestException('متاسفانه مشکلی در اطلاعات مشتری وجود دارد.') throw new BadRequestException('متاسفانه مشکلی در اطلاعات مشتری وجود دارد.')
} }
return customerLegal.customer_id return customerIndividualId
} else if (customer_type === CustomerType.LEGAL && customer?.customer_legal) {
const { registration_number, economic_code, postal_code } = customer.customer_legal
const foundedCustomer = await tx.customerLegal.findFirst({
where: {
business_activity_id: businessId,
OR: [
{
economic_code,
},
{
postal_code,
registration_number,
},
],
},
select: {
customer_id: true,
},
})
let customerLegalId: string | undefined = foundedCustomer?.customer_id
if (foundedCustomer) {
await tx.customerLegal.update({
where: {
customer_id: foundedCustomer.customer_id,
},
data: {
...customer.customer_legal,
},
})
} else {
const createdCustomer = await tx.customerLegal.create({
data: {
...customer.customer_legal,
customer: {
create: {
type: CustomerType.LEGAL,
},
},
business_activity: {
connect: {
id: businessId,
},
},
},
})
customerLegalId = createdCustomer.customer_id
}
if (!customerLegalId) {
throw new BadRequestException('متاسفانه مشکلی در اطلاعات مشتری وجود دارد.')
}
return customerLegalId
} }
return null return null
@@ -382,6 +401,7 @@ export class SharedSaleInvoiceCreateService {
customer, customer,
payments, payments,
settlement_type, settlement_type,
send_to_tsp,
...invoiceData ...invoiceData
} = data } = data
@@ -389,7 +409,7 @@ export class SharedSaleInvoiceCreateService {
type !== TspProviderRequestType.ORIGINAL && type !== TspProviderRequestType.ORIGINAL &&
!(main_invoice_id || ref_invoice_id) !(main_invoice_id || ref_invoice_id)
) { ) {
throw new BadRequestException('متاسفانه مشکلی در اطلاعات فاکتور وجود دارد.') throw new BadRequestException('متاسفانه مشکلی در اطلاعات صورت‌حساب وجود دارد.')
} }
const salesInvoiceData: SalesInvoiceCreateInput = { const salesInvoiceData: SalesInvoiceCreateInput = {
@@ -444,6 +464,8 @@ export class SharedSaleInvoiceCreateService {
id: customerId, id: customerId,
}, },
} }
} else if (data.customer?.customer_unknown) {
salesInvoiceData.unknown_customer = data.customer.customer_unknown
} }
if (type !== TspProviderRequestType.ORIGINAL) { if (type !== TspProviderRequestType.ORIGINAL) {
@@ -458,7 +480,7 @@ export class SharedSaleInvoiceCreateService {
return salesInvoiceData return salesInvoiceData
} }
private async getNextInvoiceNumber(tx: Prisma.TransactionClient, businessId: string) { async getNextInvoiceNumber(tx: Prisma.TransactionClient, businessId: string) {
const latestInvoice = await tx.salesInvoice.findFirst({ const latestInvoice = await tx.salesInvoice.findFirst({
where: { where: {
pos: { pos: {
@@ -499,7 +521,6 @@ export class SharedSaleInvoiceCreateService {
tx: Prisma.TransactionClient, tx: Prisma.TransactionClient,
invoiceId: string, invoiceId: string,
payments: NormalizedPayment[], payments: NormalizedPayment[],
terminalInfo: TerminalPaymentInfo | undefined,
paidAt: Date, paidAt: Date,
) { ) {
for (const payment of payments) { for (const payment of payments) {
@@ -515,16 +536,27 @@ export class SharedSaleInvoiceCreateService {
}, },
}) })
if (payment.method === PaymentMethodType.TERMINAL && terminalInfo) { if (payment.method === PaymentMethodType.TERMINAL && payment.terminalInfo) {
const {
terminal_id,
stan,
rrn,
transaction_date_time,
customer_card_no,
description,
} = payment.terminalInfo
await tx.salesInvoicePaymentTerminalInfo.create({ await tx.salesInvoicePaymentTerminalInfo.create({
data: { data: {
payment_id: createdPayment.id, payment_id: createdPayment.id,
terminal_id: terminalInfo.terminal_id, terminal_id,
stan: terminalInfo.stan, stan: stan,
rrn: terminalInfo.rrn, rrn: rrn,
transaction_date_time: new Date(terminalInfo.transaction_date_time || ''), transaction_date_time: transaction_date_time
customer_card_no: terminalInfo.customer_card_no || null, ? new Date(transaction_date_time)
description: terminalInfo.description || null, : new Date(),
customer_card_no: '1234567890123456',
// customer_card_no: customer_card_no || null,
description: description || null,
}, },
}) })
} }
@@ -0,0 +1,90 @@
import { ApiPropertyOptional } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import {
IsDateString,
IsEnum,
IsNumber,
IsOptional,
IsString,
Min,
} from 'class-validator'
import { TspProviderResponseStatus } from 'generated/prisma/enums'
export class SharedSaleInvoicesFilterDto {
@ApiPropertyOptional({ default: 1 })
@IsOptional()
@Type(() => Number)
@IsNumber()
@Min(1)
page?: number
@ApiPropertyOptional({ default: 10 })
@IsOptional()
@Type(() => Number)
@IsNumber()
@Min(1)
perPage?: number
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
invoice_date_from?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
invoice_date_to?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
created_at_from?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
created_at_to?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_name?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_mobile?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_national_id?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_economic_code?: string
@ApiPropertyOptional({ enum: TspProviderResponseStatus })
@IsOptional()
@IsEnum(TspProviderResponseStatus)
status?: TspProviderResponseStatus
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount?: number
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount_from?: number
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount_to?: number
}
@@ -0,0 +1,137 @@
import { TspProviderResponseStatus } from '@/generated/prisma/enums'
import { SalesInvoiceWhereInput } from '@/generated/prisma/models'
import { Injectable } from '@nestjs/common'
import { SharedSaleInvoicesFilterDto } from './sale-invoice-filter.dto'
@Injectable()
export class SharedSaleInvoiceFilterService {
buildWhere(filter: SharedSaleInvoicesFilterDto): SalesInvoiceWhereInput {
const where: SalesInvoiceWhereInput = {}
if (filter.invoice_date_from || filter.invoice_date_to) {
where.invoice_date = {
...(filter.invoice_date_from ? { gte: new Date(filter.invoice_date_from) } : {}),
...(filter.invoice_date_to ? { lte: new Date(filter.invoice_date_to) } : {}),
}
}
if (filter.created_at_from || filter.created_at_to) {
where.created_at = {
...(filter.created_at_from ? { gte: new Date(filter.created_at_from) } : {}),
...(filter.created_at_to ? { lte: new Date(filter.created_at_to) } : {}),
}
}
if (
filter.total_amount !== undefined ||
filter.total_amount_from !== undefined ||
filter.total_amount_to !== undefined
) {
where.total_amount = {
...(filter.total_amount !== undefined ? { equals: filter.total_amount } : {}),
...(filter.total_amount_from !== undefined
? { gte: filter.total_amount_from }
: {}),
...(filter.total_amount_to !== undefined ? { lte: filter.total_amount_to } : {}),
}
}
if (
filter.customer_name?.trim() ||
filter.customer_mobile?.trim() ||
filter.customer_national_id?.trim() ||
filter.customer_economic_code?.trim()
) {
where.customer = {
is: {
OR: [
...(filter.customer_name?.trim()
? [
{
individual: {
is: {
OR: [
{ first_name: { contains: filter.customer_name.trim() } },
{ last_name: { contains: filter.customer_name.trim() } },
],
},
},
},
{
legal: {
is: {
name: {
contains: filter.customer_name.trim(),
},
},
},
},
]
: []),
...(filter.customer_mobile?.trim()
? [
{
individual: {
is: {
mobile_number: { contains: filter.customer_mobile.trim() },
},
},
},
]
: []),
...(filter.customer_national_id?.trim()
? [
{
individual: {
is: {
national_id: { contains: filter.customer_national_id.trim() },
},
},
},
]
: []),
...(filter.customer_economic_code?.trim()
? [
{
legal: {
is: {
OR: [
{
economic_code: {
contains: filter.customer_economic_code.trim(),
},
},
{
registration_number: {
contains: filter.customer_economic_code.trim(),
},
},
],
},
},
},
]
: []),
],
},
}
}
if (filter.status) {
if (filter.status === TspProviderResponseStatus.NOT_SEND) {
where.OR = [
{
last_tsp_status: null,
},
{
last_tsp_status: TspProviderResponseStatus.NOT_SEND,
},
]
} else {
where.last_tsp_status = filter.status
}
}
return where
}
}
@@ -0,0 +1,29 @@
import { Injectable } from '@nestjs/common'
@Injectable()
export class SharedSaleInvoicePaginationService {
normalize(
page: number = 1,
perPage: number = 10,
defaultPerPage: number = 10,
maxPerPage: number = 50,
) {
const normalizedPageValue = Number(page ?? 1)
const normalizedPage = Number.isFinite(normalizedPageValue)
? Math.max(1, Math.floor(normalizedPageValue))
: 1
const requestedPerPageValue = Number(perPage ?? defaultPerPage)
const requestedPerPage = Number.isFinite(requestedPerPageValue)
? Math.max(1, Math.floor(requestedPerPageValue))
: defaultPerPage
const normalizedPerPage = Math.min(requestedPerPage, maxPerPage)
return {
page: normalizedPage,
perPage: normalizedPerPage,
skip: (normalizedPage - 1) * normalizedPerPage,
take: normalizedPerPage,
}
}
}
+11 -3
View File
@@ -20,14 +20,18 @@ export function getCurrentJalaliSeasonStart(
const date = dayjs(baseDate).calendar('jalali') const date = dayjs(baseDate).calendar('jalali')
const month = date.month() + 1 const month = date.month() + 1
const seasonStartMonth = Math.floor((month - 1) / 3) * 3 + 1 const seasonStartMonth = Math.floor((month - 1) / 3) * 3 + 1
return date.month(seasonStartMonth - 1).startOf('month').startOf('day').toDate() return date
.month(seasonStartMonth - 1)
.startOf('month')
.startOf('day')
.toDate()
} }
export function getCurrentJalaliSeasonEnd( export function getCurrentJalaliSeasonEnd(
baseDate: string | number | Date | Dayjs = dayjs(), baseDate: string | number | Date | Dayjs = dayjs(),
): Date { ): Date {
return dayjs(getCurrentJalaliSeasonStart(baseDate)) return dayjs(getCurrentJalaliSeasonStart(baseDate))
.add(2, 'month') .add(3, 'month')
.endOf('month') .endOf('month')
.endOf('day') .endOf('day')
.toDate() .toDate()
@@ -39,7 +43,11 @@ export function getCurrentGregorianSeasonStart(
const date = dayjs(baseDate).calendar('gregory') const date = dayjs(baseDate).calendar('gregory')
const month = date.month() + 1 const month = date.month() + 1
const seasonStartMonth = Math.floor((month - 1) / 3) * 3 + 1 const seasonStartMonth = Math.floor((month - 1) / 3) * 3 + 1
return date.month(seasonStartMonth - 1).startOf('month').startOf('day').toDate() return date
.month(seasonStartMonth - 1)
.startOf('month')
.startOf('day')
.toDate()
} }
export function getCurrentGregorianSeasonEnd( export function getCurrentGregorianSeasonEnd(
+2 -2
View File
@@ -18,13 +18,13 @@ export function checkAndDecodeJwtToken(
token = authHeader.slice(7) token = authHeader.slice(7)
} }
} }
if (!token) throw new UnauthorizedException('Missing accessToken cookie') if (!token) throw new UnauthorizedException('توکن احراز هویت ارسال نشده است')
try { try {
const payload = jwtService.decode(token) as AccessTokenPayload const payload = jwtService.decode(token) as AccessTokenPayload
return payload as ITokenPayload return payload as ITokenPayload
} catch { } catch {
return null throw new UnauthorizedException('توکن احراز هویت نامعتبر است')
} }
} }
@@ -1,4 +1,8 @@
export class ConsumerKeyMaker { export class ConsumerKeyMaker {
static middleware(token: string): string {
return `consumer:middleware:${token}`
}
static consumerInfo(consumerId: string): string { static consumerInfo(consumerId: string): string {
return `consumers:${consumerId}:info` return `consumers:${consumerId}:info`
} }
+3
View File
@@ -14,12 +14,15 @@ export class RedisKeyMaker extends PartnerKeyMaker {
static pos = PosKeyMaker static pos = PosKeyMaker
static consumerInfo = ConsumerKeyMaker.consumerInfo static consumerInfo = ConsumerKeyMaker.consumerInfo
static consumerMiddleware = ConsumerKeyMaker.middleware
static consumerBusinessActivitiesList = ConsumerKeyMaker.consumerBusinessActivitiesList static consumerBusinessActivitiesList = ConsumerKeyMaker.consumerBusinessActivitiesList
static consumerBusinessActivityInfo = ConsumerKeyMaker.consumerBusinessActivityInfo static consumerBusinessActivityInfo = ConsumerKeyMaker.consumerBusinessActivityInfo
static guildStockKeepingUnitsList = GuildKeyMaker.guildStockKeepingUnitsList static guildStockKeepingUnitsList = GuildKeyMaker.guildStockKeepingUnitsList
static guildGoodsList = GuildKeyMaker.guildGoodsList static guildGoodsList = GuildKeyMaker.guildGoodsList
static posMiddleware = PosKeyMaker.middleware
static partnerMiddleware = PartnerKeyMaker.middleware
static posInfo = PosKeyMaker.info static posInfo = PosKeyMaker.info
static posMe = PosKeyMaker.me static posMe = PosKeyMaker.me
static posGoodsList = PosKeyMaker.goodList static posGoodsList = PosKeyMaker.goodList
@@ -1,4 +1,8 @@
export class PartnerKeyMaker { export class PartnerKeyMaker {
static middleware(token): string {
return `partner:middleware:${token}`
}
static partnersList(): string { static partnersList(): string {
return 'partners:list' return 'partners:list'
} }
+4
View File
@@ -1,4 +1,8 @@
export class PosKeyMaker { export class PosKeyMaker {
static middleware(token: string): string {
return `pos:${token}:middleware`
}
static info(posId: string): string { static info(posId: string): string {
return `pos:${posId}:info` return `pos:${posId}:info`
} }
+88
View File
@@ -630,6 +630,24 @@ export type EnumInvoiceSettlementTypeFilter<$PrismaModel = never> = {
not?: Prisma.NestedEnumInvoiceSettlementTypeFilter<$PrismaModel> | $Enums.InvoiceSettlementType not?: Prisma.NestedEnumInvoiceSettlementTypeFilter<$PrismaModel> | $Enums.InvoiceSettlementType
} }
export type EnumTspProviderResponseStatusNullableFilter<$PrismaModel = never> = {
equals?: $Enums.TspProviderResponseStatus | Prisma.EnumTspProviderResponseStatusFieldRefInput<$PrismaModel> | null
in?: $Enums.TspProviderResponseStatus[] | null
notIn?: $Enums.TspProviderResponseStatus[] | null
not?: Prisma.NestedEnumTspProviderResponseStatusNullableFilter<$PrismaModel> | $Enums.TspProviderResponseStatus | null
}
export type IntNullableFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null
in?: number[] | null
notIn?: number[] | null
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null
}
export type EnumTspProviderRequestTypeWithAggregatesFilter<$PrismaModel = never> = { export type EnumTspProviderRequestTypeWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.TspProviderRequestType | Prisma.EnumTspProviderRequestTypeFieldRefInput<$PrismaModel> equals?: $Enums.TspProviderRequestType | Prisma.EnumTspProviderRequestTypeFieldRefInput<$PrismaModel>
in?: $Enums.TspProviderRequestType[] in?: $Enums.TspProviderRequestType[]
@@ -650,6 +668,32 @@ export type EnumInvoiceSettlementTypeWithAggregatesFilter<$PrismaModel = never>
_max?: Prisma.NestedEnumInvoiceSettlementTypeFilter<$PrismaModel> _max?: Prisma.NestedEnumInvoiceSettlementTypeFilter<$PrismaModel>
} }
export type EnumTspProviderResponseStatusNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.TspProviderResponseStatus | Prisma.EnumTspProviderResponseStatusFieldRefInput<$PrismaModel> | null
in?: $Enums.TspProviderResponseStatus[] | null
notIn?: $Enums.TspProviderResponseStatus[] | null
not?: Prisma.NestedEnumTspProviderResponseStatusNullableWithAggregatesFilter<$PrismaModel> | $Enums.TspProviderResponseStatus | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedEnumTspProviderResponseStatusNullableFilter<$PrismaModel>
_max?: Prisma.NestedEnumTspProviderResponseStatusNullableFilter<$PrismaModel>
}
export type IntNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null
in?: number[] | null
notIn?: number[] | null
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_avg?: Prisma.NestedFloatNullableFilter<$PrismaModel>
_sum?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedIntNullableFilter<$PrismaModel>
_max?: Prisma.NestedIntNullableFilter<$PrismaModel>
}
export type JsonFilter<$PrismaModel = never> = export type JsonFilter<$PrismaModel = never> =
| Prisma.PatchUndefined< | Prisma.PatchUndefined<
Prisma.Either<Required<JsonFilterBase<$PrismaModel>>, Exclude<keyof Required<JsonFilterBase<$PrismaModel>>, 'path'>>, Prisma.Either<Required<JsonFilterBase<$PrismaModel>>, Exclude<keyof Required<JsonFilterBase<$PrismaModel>>, 'path'>>,
@@ -1341,6 +1385,13 @@ export type NestedEnumInvoiceSettlementTypeFilter<$PrismaModel = never> = {
not?: Prisma.NestedEnumInvoiceSettlementTypeFilter<$PrismaModel> | $Enums.InvoiceSettlementType not?: Prisma.NestedEnumInvoiceSettlementTypeFilter<$PrismaModel> | $Enums.InvoiceSettlementType
} }
export type NestedEnumTspProviderResponseStatusNullableFilter<$PrismaModel = never> = {
equals?: $Enums.TspProviderResponseStatus | Prisma.EnumTspProviderResponseStatusFieldRefInput<$PrismaModel> | null
in?: $Enums.TspProviderResponseStatus[] | null
notIn?: $Enums.TspProviderResponseStatus[] | null
not?: Prisma.NestedEnumTspProviderResponseStatusNullableFilter<$PrismaModel> | $Enums.TspProviderResponseStatus | null
}
export type NestedEnumTspProviderRequestTypeWithAggregatesFilter<$PrismaModel = never> = { export type NestedEnumTspProviderRequestTypeWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.TspProviderRequestType | Prisma.EnumTspProviderRequestTypeFieldRefInput<$PrismaModel> equals?: $Enums.TspProviderRequestType | Prisma.EnumTspProviderRequestTypeFieldRefInput<$PrismaModel>
in?: $Enums.TspProviderRequestType[] in?: $Enums.TspProviderRequestType[]
@@ -1361,6 +1412,43 @@ export type NestedEnumInvoiceSettlementTypeWithAggregatesFilter<$PrismaModel = n
_max?: Prisma.NestedEnumInvoiceSettlementTypeFilter<$PrismaModel> _max?: Prisma.NestedEnumInvoiceSettlementTypeFilter<$PrismaModel>
} }
export type NestedEnumTspProviderResponseStatusNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: $Enums.TspProviderResponseStatus | Prisma.EnumTspProviderResponseStatusFieldRefInput<$PrismaModel> | null
in?: $Enums.TspProviderResponseStatus[] | null
notIn?: $Enums.TspProviderResponseStatus[] | null
not?: Prisma.NestedEnumTspProviderResponseStatusNullableWithAggregatesFilter<$PrismaModel> | $Enums.TspProviderResponseStatus | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedEnumTspProviderResponseStatusNullableFilter<$PrismaModel>
_max?: Prisma.NestedEnumTspProviderResponseStatusNullableFilter<$PrismaModel>
}
export type NestedIntNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null
in?: number[] | null
notIn?: number[] | null
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_avg?: Prisma.NestedFloatNullableFilter<$PrismaModel>
_sum?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedIntNullableFilter<$PrismaModel>
_max?: Prisma.NestedIntNullableFilter<$PrismaModel>
}
export type NestedFloatNullableFilter<$PrismaModel = never> = {
equals?: number | Prisma.FloatFieldRefInput<$PrismaModel> | null
in?: number[] | null
notIn?: number[] | null
lt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
lte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
gt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
gte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
not?: Prisma.NestedFloatNullableFilter<$PrismaModel> | number | null
}
export type NestedJsonFilter<$PrismaModel = never> = export type NestedJsonFilter<$PrismaModel = never> =
| Prisma.PatchUndefined< | Prisma.PatchUndefined<
Prisma.Either<Required<NestedJsonFilterBase<$PrismaModel>>, Exclude<keyof Required<NestedJsonFilterBase<$PrismaModel>>, 'path'>>, Prisma.Either<Required<NestedJsonFilterBase<$PrismaModel>>, Exclude<keyof Required<NestedJsonFilterBase<$PrismaModel>>, 'path'>>,
File diff suppressed because one or more lines are too long
@@ -4094,8 +4094,6 @@ export const SalesInvoiceScalarFieldEnum = {
id: 'id', id: 'id',
code: 'code', code: 'code',
total_amount: 'total_amount', total_amount: 'total_amount',
tax_amount: 'tax_amount',
discount_amount: 'discount_amount',
invoice_number: 'invoice_number', invoice_number: 'invoice_number',
invoice_date: 'invoice_date', invoice_date: 'invoice_date',
type: 'type', type: 'type',
@@ -4109,7 +4107,11 @@ export const SalesInvoiceScalarFieldEnum = {
customer_id: 'customer_id', customer_id: 'customer_id',
consumer_account_id: 'consumer_account_id', consumer_account_id: 'consumer_account_id',
pos_id: 'pos_id', pos_id: 'pos_id',
settlement_type: 'settlement_type' settlement_type: 'settlement_type',
discount_amount: 'discount_amount',
tax_amount: 'tax_amount',
last_tsp_status: 'last_tsp_status',
last_attempt_no: 'last_attempt_no'
} as const } as const
export type SalesInvoiceScalarFieldEnum = (typeof SalesInvoiceScalarFieldEnum)[keyof typeof SalesInvoiceScalarFieldEnum] export type SalesInvoiceScalarFieldEnum = (typeof SalesInvoiceScalarFieldEnum)[keyof typeof SalesInvoiceScalarFieldEnum]
@@ -4125,14 +4127,15 @@ export const SalesInvoiceItemScalarFieldEnum = {
unit_price: 'unit_price', unit_price: 'unit_price',
total_amount: 'total_amount', total_amount: 'total_amount',
created_at: 'created_at', created_at: 'created_at',
discount_amount: 'discount_amount', discount: 'discount',
tax_amount: 'tax_amount',
notes: 'notes', notes: 'notes',
payload: 'payload', payload: 'payload',
good_snapshot: 'good_snapshot', good_snapshot: 'good_snapshot',
invoice_id: 'invoice_id', invoice_id: 'invoice_id',
good_id: 'good_id', good_id: 'good_id',
service_id: 'service_id' service_id: 'service_id',
discount_amount: 'discount_amount',
tax_amount: 'tax_amount'
} as const } as const
export type SalesInvoiceItemScalarFieldEnum = (typeof SalesInvoiceItemScalarFieldEnum)[keyof typeof SalesInvoiceItemScalarFieldEnum] export type SalesInvoiceItemScalarFieldEnum = (typeof SalesInvoiceItemScalarFieldEnum)[keyof typeof SalesInvoiceItemScalarFieldEnum]
@@ -619,8 +619,6 @@ export const SalesInvoiceScalarFieldEnum = {
id: 'id', id: 'id',
code: 'code', code: 'code',
total_amount: 'total_amount', total_amount: 'total_amount',
tax_amount: 'tax_amount',
discount_amount: 'discount_amount',
invoice_number: 'invoice_number', invoice_number: 'invoice_number',
invoice_date: 'invoice_date', invoice_date: 'invoice_date',
type: 'type', type: 'type',
@@ -634,7 +632,11 @@ export const SalesInvoiceScalarFieldEnum = {
customer_id: 'customer_id', customer_id: 'customer_id',
consumer_account_id: 'consumer_account_id', consumer_account_id: 'consumer_account_id',
pos_id: 'pos_id', pos_id: 'pos_id',
settlement_type: 'settlement_type' settlement_type: 'settlement_type',
discount_amount: 'discount_amount',
tax_amount: 'tax_amount',
last_tsp_status: 'last_tsp_status',
last_attempt_no: 'last_attempt_no'
} as const } as const
export type SalesInvoiceScalarFieldEnum = (typeof SalesInvoiceScalarFieldEnum)[keyof typeof SalesInvoiceScalarFieldEnum] export type SalesInvoiceScalarFieldEnum = (typeof SalesInvoiceScalarFieldEnum)[keyof typeof SalesInvoiceScalarFieldEnum]
@@ -650,14 +652,15 @@ export const SalesInvoiceItemScalarFieldEnum = {
unit_price: 'unit_price', unit_price: 'unit_price',
total_amount: 'total_amount', total_amount: 'total_amount',
created_at: 'created_at', created_at: 'created_at',
discount_amount: 'discount_amount', discount: 'discount',
tax_amount: 'tax_amount',
notes: 'notes', notes: 'notes',
payload: 'payload', payload: 'payload',
good_snapshot: 'good_snapshot', good_snapshot: 'good_snapshot',
invoice_id: 'invoice_id', invoice_id: 'invoice_id',
good_id: 'good_id', good_id: 'good_id',
service_id: 'service_id' service_id: 'service_id',
discount_amount: 'discount_amount',
tax_amount: 'tax_amount'
} as const } as const
export type SalesInvoiceItemScalarFieldEnum = (typeof SalesInvoiceItemScalarFieldEnum)[keyof typeof SalesInvoiceItemScalarFieldEnum] export type SalesInvoiceItemScalarFieldEnum = (typeof SalesInvoiceItemScalarFieldEnum)[keyof typeof SalesInvoiceItemScalarFieldEnum]
+133 -126
View File
@@ -166,11 +166,11 @@ export type CustomerIndividualGroupByArgs<ExtArgs extends runtime.Types.Extensio
} }
export type CustomerIndividualGroupByOutputType = { export type CustomerIndividualGroupByOutputType = {
first_name: string first_name: string | null
last_name: string last_name: string | null
national_id: string national_id: string | null
mobile_number: string mobile_number: string | null
postal_code: string postal_code: string | null
economic_code: string | null economic_code: string | null
customer_id: string customer_id: string
business_activity_id: string business_activity_id: string
@@ -198,11 +198,11 @@ export type CustomerIndividualWhereInput = {
AND?: Prisma.CustomerIndividualWhereInput | Prisma.CustomerIndividualWhereInput[] AND?: Prisma.CustomerIndividualWhereInput | Prisma.CustomerIndividualWhereInput[]
OR?: Prisma.CustomerIndividualWhereInput[] OR?: Prisma.CustomerIndividualWhereInput[]
NOT?: Prisma.CustomerIndividualWhereInput | Prisma.CustomerIndividualWhereInput[] NOT?: Prisma.CustomerIndividualWhereInput | Prisma.CustomerIndividualWhereInput[]
first_name?: Prisma.StringFilter<"CustomerIndividual"> | string first_name?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
last_name?: Prisma.StringFilter<"CustomerIndividual"> | string last_name?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
national_id?: Prisma.StringFilter<"CustomerIndividual"> | string national_id?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
mobile_number?: Prisma.StringFilter<"CustomerIndividual"> | string mobile_number?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
postal_code?: Prisma.StringFilter<"CustomerIndividual"> | string postal_code?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
economic_code?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null economic_code?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
customer_id?: Prisma.StringFilter<"CustomerIndividual"> | string customer_id?: Prisma.StringFilter<"CustomerIndividual"> | string
business_activity_id?: Prisma.StringFilter<"CustomerIndividual"> | string business_activity_id?: Prisma.StringFilter<"CustomerIndividual"> | string
@@ -211,11 +211,11 @@ export type CustomerIndividualWhereInput = {
} }
export type CustomerIndividualOrderByWithRelationInput = { export type CustomerIndividualOrderByWithRelationInput = {
first_name?: Prisma.SortOrder first_name?: Prisma.SortOrderInput | Prisma.SortOrder
last_name?: Prisma.SortOrder last_name?: Prisma.SortOrderInput | Prisma.SortOrder
national_id?: Prisma.SortOrder national_id?: Prisma.SortOrderInput | Prisma.SortOrder
mobile_number?: Prisma.SortOrder mobile_number?: Prisma.SortOrderInput | Prisma.SortOrder
postal_code?: Prisma.SortOrder postal_code?: Prisma.SortOrderInput | Prisma.SortOrder
economic_code?: Prisma.SortOrderInput | Prisma.SortOrder economic_code?: Prisma.SortOrderInput | Prisma.SortOrder
customer_id?: Prisma.SortOrder customer_id?: Prisma.SortOrder
business_activity_id?: Prisma.SortOrder business_activity_id?: Prisma.SortOrder
@@ -227,26 +227,27 @@ export type CustomerIndividualOrderByWithRelationInput = {
export type CustomerIndividualWhereUniqueInput = Prisma.AtLeast<{ export type CustomerIndividualWhereUniqueInput = Prisma.AtLeast<{
customer_id?: string customer_id?: string
business_activity_id_national_id?: Prisma.CustomerIndividualBusiness_activity_idNational_idCompoundUniqueInput business_activity_id_national_id?: Prisma.CustomerIndividualBusiness_activity_idNational_idCompoundUniqueInput
business_activity_id_postal_code_national_id?: Prisma.CustomerIndividualBusiness_activity_idPostal_codeNational_idCompoundUniqueInput
AND?: Prisma.CustomerIndividualWhereInput | Prisma.CustomerIndividualWhereInput[] AND?: Prisma.CustomerIndividualWhereInput | Prisma.CustomerIndividualWhereInput[]
OR?: Prisma.CustomerIndividualWhereInput[] OR?: Prisma.CustomerIndividualWhereInput[]
NOT?: Prisma.CustomerIndividualWhereInput | Prisma.CustomerIndividualWhereInput[] NOT?: Prisma.CustomerIndividualWhereInput | Prisma.CustomerIndividualWhereInput[]
first_name?: Prisma.StringFilter<"CustomerIndividual"> | string first_name?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
last_name?: Prisma.StringFilter<"CustomerIndividual"> | string last_name?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
national_id?: Prisma.StringFilter<"CustomerIndividual"> | string national_id?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
mobile_number?: Prisma.StringFilter<"CustomerIndividual"> | string mobile_number?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
postal_code?: Prisma.StringFilter<"CustomerIndividual"> | string postal_code?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
economic_code?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null economic_code?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
business_activity_id?: Prisma.StringFilter<"CustomerIndividual"> | string business_activity_id?: Prisma.StringFilter<"CustomerIndividual"> | string
business_activity?: Prisma.XOR<Prisma.BusinessActivityScalarRelationFilter, Prisma.BusinessActivityWhereInput> business_activity?: Prisma.XOR<Prisma.BusinessActivityScalarRelationFilter, Prisma.BusinessActivityWhereInput>
customer?: Prisma.XOR<Prisma.CustomerScalarRelationFilter, Prisma.CustomerWhereInput> customer?: Prisma.XOR<Prisma.CustomerScalarRelationFilter, Prisma.CustomerWhereInput>
}, "customer_id" | "business_activity_id_national_id"> }, "customer_id" | "business_activity_id_national_id" | "business_activity_id_postal_code_national_id">
export type CustomerIndividualOrderByWithAggregationInput = { export type CustomerIndividualOrderByWithAggregationInput = {
first_name?: Prisma.SortOrder first_name?: Prisma.SortOrderInput | Prisma.SortOrder
last_name?: Prisma.SortOrder last_name?: Prisma.SortOrderInput | Prisma.SortOrder
national_id?: Prisma.SortOrder national_id?: Prisma.SortOrderInput | Prisma.SortOrder
mobile_number?: Prisma.SortOrder mobile_number?: Prisma.SortOrderInput | Prisma.SortOrder
postal_code?: Prisma.SortOrder postal_code?: Prisma.SortOrderInput | Prisma.SortOrder
economic_code?: Prisma.SortOrderInput | Prisma.SortOrder economic_code?: Prisma.SortOrderInput | Prisma.SortOrder
customer_id?: Prisma.SortOrder customer_id?: Prisma.SortOrder
business_activity_id?: Prisma.SortOrder business_activity_id?: Prisma.SortOrder
@@ -259,86 +260,86 @@ export type CustomerIndividualScalarWhereWithAggregatesInput = {
AND?: Prisma.CustomerIndividualScalarWhereWithAggregatesInput | Prisma.CustomerIndividualScalarWhereWithAggregatesInput[] AND?: Prisma.CustomerIndividualScalarWhereWithAggregatesInput | Prisma.CustomerIndividualScalarWhereWithAggregatesInput[]
OR?: Prisma.CustomerIndividualScalarWhereWithAggregatesInput[] OR?: Prisma.CustomerIndividualScalarWhereWithAggregatesInput[]
NOT?: Prisma.CustomerIndividualScalarWhereWithAggregatesInput | Prisma.CustomerIndividualScalarWhereWithAggregatesInput[] NOT?: Prisma.CustomerIndividualScalarWhereWithAggregatesInput | Prisma.CustomerIndividualScalarWhereWithAggregatesInput[]
first_name?: Prisma.StringWithAggregatesFilter<"CustomerIndividual"> | string first_name?: Prisma.StringNullableWithAggregatesFilter<"CustomerIndividual"> | string | null
last_name?: Prisma.StringWithAggregatesFilter<"CustomerIndividual"> | string last_name?: Prisma.StringNullableWithAggregatesFilter<"CustomerIndividual"> | string | null
national_id?: Prisma.StringWithAggregatesFilter<"CustomerIndividual"> | string national_id?: Prisma.StringNullableWithAggregatesFilter<"CustomerIndividual"> | string | null
mobile_number?: Prisma.StringWithAggregatesFilter<"CustomerIndividual"> | string mobile_number?: Prisma.StringNullableWithAggregatesFilter<"CustomerIndividual"> | string | null
postal_code?: Prisma.StringWithAggregatesFilter<"CustomerIndividual"> | string postal_code?: Prisma.StringNullableWithAggregatesFilter<"CustomerIndividual"> | string | null
economic_code?: Prisma.StringNullableWithAggregatesFilter<"CustomerIndividual"> | string | null economic_code?: Prisma.StringNullableWithAggregatesFilter<"CustomerIndividual"> | string | null
customer_id?: Prisma.StringWithAggregatesFilter<"CustomerIndividual"> | string customer_id?: Prisma.StringWithAggregatesFilter<"CustomerIndividual"> | string
business_activity_id?: Prisma.StringWithAggregatesFilter<"CustomerIndividual"> | string business_activity_id?: Prisma.StringWithAggregatesFilter<"CustomerIndividual"> | string
} }
export type CustomerIndividualCreateInput = { export type CustomerIndividualCreateInput = {
first_name: string first_name?: string | null
last_name: string last_name?: string | null
national_id: string national_id?: string | null
mobile_number: string mobile_number?: string | null
postal_code: string postal_code?: string | null
economic_code?: string | null economic_code?: string | null
business_activity: Prisma.BusinessActivityCreateNestedOneWithoutCustomer_individualsInput business_activity: Prisma.BusinessActivityCreateNestedOneWithoutCustomer_individualsInput
customer: Prisma.CustomerCreateNestedOneWithoutIndividualInput customer: Prisma.CustomerCreateNestedOneWithoutIndividualInput
} }
export type CustomerIndividualUncheckedCreateInput = { export type CustomerIndividualUncheckedCreateInput = {
first_name: string first_name?: string | null
last_name: string last_name?: string | null
national_id: string national_id?: string | null
mobile_number: string mobile_number?: string | null
postal_code: string postal_code?: string | null
economic_code?: string | null economic_code?: string | null
customer_id: string customer_id: string
business_activity_id: string business_activity_id: string
} }
export type CustomerIndividualUpdateInput = { export type CustomerIndividualUpdateInput = {
first_name?: Prisma.StringFieldUpdateOperationsInput | string first_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
last_name?: Prisma.StringFieldUpdateOperationsInput | string last_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
national_id?: Prisma.StringFieldUpdateOperationsInput | string national_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
mobile_number?: Prisma.StringFieldUpdateOperationsInput | string mobile_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
business_activity?: Prisma.BusinessActivityUpdateOneRequiredWithoutCustomer_individualsNestedInput business_activity?: Prisma.BusinessActivityUpdateOneRequiredWithoutCustomer_individualsNestedInput
customer?: Prisma.CustomerUpdateOneRequiredWithoutIndividualNestedInput customer?: Prisma.CustomerUpdateOneRequiredWithoutIndividualNestedInput
} }
export type CustomerIndividualUncheckedUpdateInput = { export type CustomerIndividualUncheckedUpdateInput = {
first_name?: Prisma.StringFieldUpdateOperationsInput | string first_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
last_name?: Prisma.StringFieldUpdateOperationsInput | string last_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
national_id?: Prisma.StringFieldUpdateOperationsInput | string national_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
mobile_number?: Prisma.StringFieldUpdateOperationsInput | string mobile_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer_id?: Prisma.StringFieldUpdateOperationsInput | string customer_id?: Prisma.StringFieldUpdateOperationsInput | string
business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string
} }
export type CustomerIndividualCreateManyInput = { export type CustomerIndividualCreateManyInput = {
first_name: string first_name?: string | null
last_name: string last_name?: string | null
national_id: string national_id?: string | null
mobile_number: string mobile_number?: string | null
postal_code: string postal_code?: string | null
economic_code?: string | null economic_code?: string | null
customer_id: string customer_id: string
business_activity_id: string business_activity_id: string
} }
export type CustomerIndividualUpdateManyMutationInput = { export type CustomerIndividualUpdateManyMutationInput = {
first_name?: Prisma.StringFieldUpdateOperationsInput | string first_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
last_name?: Prisma.StringFieldUpdateOperationsInput | string last_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
national_id?: Prisma.StringFieldUpdateOperationsInput | string national_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
mobile_number?: Prisma.StringFieldUpdateOperationsInput | string mobile_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
} }
export type CustomerIndividualUncheckedUpdateManyInput = { export type CustomerIndividualUncheckedUpdateManyInput = {
first_name?: Prisma.StringFieldUpdateOperationsInput | string first_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
last_name?: Prisma.StringFieldUpdateOperationsInput | string last_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
national_id?: Prisma.StringFieldUpdateOperationsInput | string national_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
mobile_number?: Prisma.StringFieldUpdateOperationsInput | string mobile_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer_id?: Prisma.StringFieldUpdateOperationsInput | string customer_id?: Prisma.StringFieldUpdateOperationsInput | string
business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string
@@ -370,6 +371,12 @@ export type CustomerIndividualBusiness_activity_idNational_idCompoundUniqueInput
national_id: string national_id: string
} }
export type CustomerIndividualBusiness_activity_idPostal_codeNational_idCompoundUniqueInput = {
business_activity_id: string
postal_code: string
national_id: string
}
export type CustomerIndividualCountOrderByAggregateInput = { export type CustomerIndividualCountOrderByAggregateInput = {
first_name?: Prisma.SortOrder first_name?: Prisma.SortOrder
last_name?: Prisma.SortOrder last_name?: Prisma.SortOrder
@@ -478,21 +485,21 @@ export type CustomerIndividualUncheckedUpdateOneWithoutCustomerNestedInput = {
} }
export type CustomerIndividualCreateWithoutBusiness_activityInput = { export type CustomerIndividualCreateWithoutBusiness_activityInput = {
first_name: string first_name?: string | null
last_name: string last_name?: string | null
national_id: string national_id?: string | null
mobile_number: string mobile_number?: string | null
postal_code: string postal_code?: string | null
economic_code?: string | null economic_code?: string | null
customer: Prisma.CustomerCreateNestedOneWithoutIndividualInput customer: Prisma.CustomerCreateNestedOneWithoutIndividualInput
} }
export type CustomerIndividualUncheckedCreateWithoutBusiness_activityInput = { export type CustomerIndividualUncheckedCreateWithoutBusiness_activityInput = {
first_name: string first_name?: string | null
last_name: string last_name?: string | null
national_id: string national_id?: string | null
mobile_number: string mobile_number?: string | null
postal_code: string postal_code?: string | null
economic_code?: string | null economic_code?: string | null
customer_id: string customer_id: string
} }
@@ -527,32 +534,32 @@ export type CustomerIndividualScalarWhereInput = {
AND?: Prisma.CustomerIndividualScalarWhereInput | Prisma.CustomerIndividualScalarWhereInput[] AND?: Prisma.CustomerIndividualScalarWhereInput | Prisma.CustomerIndividualScalarWhereInput[]
OR?: Prisma.CustomerIndividualScalarWhereInput[] OR?: Prisma.CustomerIndividualScalarWhereInput[]
NOT?: Prisma.CustomerIndividualScalarWhereInput | Prisma.CustomerIndividualScalarWhereInput[] NOT?: Prisma.CustomerIndividualScalarWhereInput | Prisma.CustomerIndividualScalarWhereInput[]
first_name?: Prisma.StringFilter<"CustomerIndividual"> | string first_name?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
last_name?: Prisma.StringFilter<"CustomerIndividual"> | string last_name?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
national_id?: Prisma.StringFilter<"CustomerIndividual"> | string national_id?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
mobile_number?: Prisma.StringFilter<"CustomerIndividual"> | string mobile_number?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
postal_code?: Prisma.StringFilter<"CustomerIndividual"> | string postal_code?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
economic_code?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null economic_code?: Prisma.StringNullableFilter<"CustomerIndividual"> | string | null
customer_id?: Prisma.StringFilter<"CustomerIndividual"> | string customer_id?: Prisma.StringFilter<"CustomerIndividual"> | string
business_activity_id?: Prisma.StringFilter<"CustomerIndividual"> | string business_activity_id?: Prisma.StringFilter<"CustomerIndividual"> | string
} }
export type CustomerIndividualCreateWithoutCustomerInput = { export type CustomerIndividualCreateWithoutCustomerInput = {
first_name: string first_name?: string | null
last_name: string last_name?: string | null
national_id: string national_id?: string | null
mobile_number: string mobile_number?: string | null
postal_code: string postal_code?: string | null
economic_code?: string | null economic_code?: string | null
business_activity: Prisma.BusinessActivityCreateNestedOneWithoutCustomer_individualsInput business_activity: Prisma.BusinessActivityCreateNestedOneWithoutCustomer_individualsInput
} }
export type CustomerIndividualUncheckedCreateWithoutCustomerInput = { export type CustomerIndividualUncheckedCreateWithoutCustomerInput = {
first_name: string first_name?: string | null
last_name: string last_name?: string | null
national_id: string national_id?: string | null
mobile_number: string mobile_number?: string | null
postal_code: string postal_code?: string | null
economic_code?: string | null economic_code?: string | null
business_activity_id: string business_activity_id: string
} }
@@ -574,61 +581,61 @@ export type CustomerIndividualUpdateToOneWithWhereWithoutCustomerInput = {
} }
export type CustomerIndividualUpdateWithoutCustomerInput = { export type CustomerIndividualUpdateWithoutCustomerInput = {
first_name?: Prisma.StringFieldUpdateOperationsInput | string first_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
last_name?: Prisma.StringFieldUpdateOperationsInput | string last_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
national_id?: Prisma.StringFieldUpdateOperationsInput | string national_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
mobile_number?: Prisma.StringFieldUpdateOperationsInput | string mobile_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
business_activity?: Prisma.BusinessActivityUpdateOneRequiredWithoutCustomer_individualsNestedInput business_activity?: Prisma.BusinessActivityUpdateOneRequiredWithoutCustomer_individualsNestedInput
} }
export type CustomerIndividualUncheckedUpdateWithoutCustomerInput = { export type CustomerIndividualUncheckedUpdateWithoutCustomerInput = {
first_name?: Prisma.StringFieldUpdateOperationsInput | string first_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
last_name?: Prisma.StringFieldUpdateOperationsInput | string last_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
national_id?: Prisma.StringFieldUpdateOperationsInput | string national_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
mobile_number?: Prisma.StringFieldUpdateOperationsInput | string mobile_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string
} }
export type CustomerIndividualCreateManyBusiness_activityInput = { export type CustomerIndividualCreateManyBusiness_activityInput = {
first_name: string first_name?: string | null
last_name: string last_name?: string | null
national_id: string national_id?: string | null
mobile_number: string mobile_number?: string | null
postal_code: string postal_code?: string | null
economic_code?: string | null economic_code?: string | null
customer_id: string customer_id: string
} }
export type CustomerIndividualUpdateWithoutBusiness_activityInput = { export type CustomerIndividualUpdateWithoutBusiness_activityInput = {
first_name?: Prisma.StringFieldUpdateOperationsInput | string first_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
last_name?: Prisma.StringFieldUpdateOperationsInput | string last_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
national_id?: Prisma.StringFieldUpdateOperationsInput | string national_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
mobile_number?: Prisma.StringFieldUpdateOperationsInput | string mobile_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer?: Prisma.CustomerUpdateOneRequiredWithoutIndividualNestedInput customer?: Prisma.CustomerUpdateOneRequiredWithoutIndividualNestedInput
} }
export type CustomerIndividualUncheckedUpdateWithoutBusiness_activityInput = { export type CustomerIndividualUncheckedUpdateWithoutBusiness_activityInput = {
first_name?: Prisma.StringFieldUpdateOperationsInput | string first_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
last_name?: Prisma.StringFieldUpdateOperationsInput | string last_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
national_id?: Prisma.StringFieldUpdateOperationsInput | string national_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
mobile_number?: Prisma.StringFieldUpdateOperationsInput | string mobile_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer_id?: Prisma.StringFieldUpdateOperationsInput | string customer_id?: Prisma.StringFieldUpdateOperationsInput | string
} }
export type CustomerIndividualUncheckedUpdateManyWithoutBusiness_activityInput = { export type CustomerIndividualUncheckedUpdateManyWithoutBusiness_activityInput = {
first_name?: Prisma.StringFieldUpdateOperationsInput | string first_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
last_name?: Prisma.StringFieldUpdateOperationsInput | string last_name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
national_id?: Prisma.StringFieldUpdateOperationsInput | string national_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
mobile_number?: Prisma.StringFieldUpdateOperationsInput | string mobile_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer_id?: Prisma.StringFieldUpdateOperationsInput | string customer_id?: Prisma.StringFieldUpdateOperationsInput | string
} }
@@ -674,11 +681,11 @@ export type $CustomerIndividualPayload<ExtArgs extends runtime.Types.Extensions.
customer: Prisma.$CustomerPayload<ExtArgs> customer: Prisma.$CustomerPayload<ExtArgs>
} }
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
first_name: string first_name: string | null
last_name: string last_name: string | null
national_id: string national_id: string | null
mobile_number: string mobile_number: string | null
postal_code: string postal_code: string | null
economic_code: string | null economic_code: string | null
customer_id: string customer_id: string
business_activity_id: string business_activity_id: string
+83 -76
View File
@@ -154,10 +154,10 @@ export type CustomerLegalGroupByArgs<ExtArgs extends runtime.Types.Extensions.In
} }
export type CustomerLegalGroupByOutputType = { export type CustomerLegalGroupByOutputType = {
name: string name: string | null
economic_code: string economic_code: string | null
registration_number: string | null registration_number: string | null
postal_code: string postal_code: string | null
customer_id: string customer_id: string
business_activity_id: string business_activity_id: string
_count: CustomerLegalCountAggregateOutputType | null _count: CustomerLegalCountAggregateOutputType | null
@@ -184,10 +184,10 @@ export type CustomerLegalWhereInput = {
AND?: Prisma.CustomerLegalWhereInput | Prisma.CustomerLegalWhereInput[] AND?: Prisma.CustomerLegalWhereInput | Prisma.CustomerLegalWhereInput[]
OR?: Prisma.CustomerLegalWhereInput[] OR?: Prisma.CustomerLegalWhereInput[]
NOT?: Prisma.CustomerLegalWhereInput | Prisma.CustomerLegalWhereInput[] NOT?: Prisma.CustomerLegalWhereInput | Prisma.CustomerLegalWhereInput[]
name?: Prisma.StringFilter<"CustomerLegal"> | string name?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
economic_code?: Prisma.StringFilter<"CustomerLegal"> | string economic_code?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
registration_number?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null registration_number?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
postal_code?: Prisma.StringFilter<"CustomerLegal"> | string postal_code?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
customer_id?: Prisma.StringFilter<"CustomerLegal"> | string customer_id?: Prisma.StringFilter<"CustomerLegal"> | string
business_activity_id?: Prisma.StringFilter<"CustomerLegal"> | string business_activity_id?: Prisma.StringFilter<"CustomerLegal"> | string
business_activity?: Prisma.XOR<Prisma.BusinessActivityScalarRelationFilter, Prisma.BusinessActivityWhereInput> business_activity?: Prisma.XOR<Prisma.BusinessActivityScalarRelationFilter, Prisma.BusinessActivityWhereInput>
@@ -195,10 +195,10 @@ export type CustomerLegalWhereInput = {
} }
export type CustomerLegalOrderByWithRelationInput = { export type CustomerLegalOrderByWithRelationInput = {
name?: Prisma.SortOrder name?: Prisma.SortOrderInput | Prisma.SortOrder
economic_code?: Prisma.SortOrder economic_code?: Prisma.SortOrderInput | Prisma.SortOrder
registration_number?: Prisma.SortOrderInput | Prisma.SortOrder registration_number?: Prisma.SortOrderInput | Prisma.SortOrder
postal_code?: Prisma.SortOrder postal_code?: Prisma.SortOrderInput | Prisma.SortOrder
customer_id?: Prisma.SortOrder customer_id?: Prisma.SortOrder
business_activity_id?: Prisma.SortOrder business_activity_id?: Prisma.SortOrder
business_activity?: Prisma.BusinessActivityOrderByWithRelationInput business_activity?: Prisma.BusinessActivityOrderByWithRelationInput
@@ -209,23 +209,24 @@ export type CustomerLegalOrderByWithRelationInput = {
export type CustomerLegalWhereUniqueInput = Prisma.AtLeast<{ export type CustomerLegalWhereUniqueInput = Prisma.AtLeast<{
customer_id?: string customer_id?: string
business_activity_id_economic_code?: Prisma.CustomerLegalBusiness_activity_idEconomic_codeCompoundUniqueInput business_activity_id_economic_code?: Prisma.CustomerLegalBusiness_activity_idEconomic_codeCompoundUniqueInput
business_activity_id_postal_code_registration_number?: Prisma.CustomerLegalBusiness_activity_idPostal_codeRegistration_numberCompoundUniqueInput
AND?: Prisma.CustomerLegalWhereInput | Prisma.CustomerLegalWhereInput[] AND?: Prisma.CustomerLegalWhereInput | Prisma.CustomerLegalWhereInput[]
OR?: Prisma.CustomerLegalWhereInput[] OR?: Prisma.CustomerLegalWhereInput[]
NOT?: Prisma.CustomerLegalWhereInput | Prisma.CustomerLegalWhereInput[] NOT?: Prisma.CustomerLegalWhereInput | Prisma.CustomerLegalWhereInput[]
name?: Prisma.StringFilter<"CustomerLegal"> | string name?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
economic_code?: Prisma.StringFilter<"CustomerLegal"> | string economic_code?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
registration_number?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null registration_number?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
postal_code?: Prisma.StringFilter<"CustomerLegal"> | string postal_code?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
business_activity_id?: Prisma.StringFilter<"CustomerLegal"> | string business_activity_id?: Prisma.StringFilter<"CustomerLegal"> | string
business_activity?: Prisma.XOR<Prisma.BusinessActivityScalarRelationFilter, Prisma.BusinessActivityWhereInput> business_activity?: Prisma.XOR<Prisma.BusinessActivityScalarRelationFilter, Prisma.BusinessActivityWhereInput>
customer?: Prisma.XOR<Prisma.CustomerScalarRelationFilter, Prisma.CustomerWhereInput> customer?: Prisma.XOR<Prisma.CustomerScalarRelationFilter, Prisma.CustomerWhereInput>
}, "customer_id" | "business_activity_id_economic_code"> }, "customer_id" | "business_activity_id_economic_code" | "business_activity_id_postal_code_registration_number">
export type CustomerLegalOrderByWithAggregationInput = { export type CustomerLegalOrderByWithAggregationInput = {
name?: Prisma.SortOrder name?: Prisma.SortOrderInput | Prisma.SortOrder
economic_code?: Prisma.SortOrder economic_code?: Prisma.SortOrderInput | Prisma.SortOrder
registration_number?: Prisma.SortOrderInput | Prisma.SortOrder registration_number?: Prisma.SortOrderInput | Prisma.SortOrder
postal_code?: Prisma.SortOrder postal_code?: Prisma.SortOrderInput | Prisma.SortOrder
customer_id?: Prisma.SortOrder customer_id?: Prisma.SortOrder
business_activity_id?: Prisma.SortOrder business_activity_id?: Prisma.SortOrder
_count?: Prisma.CustomerLegalCountOrderByAggregateInput _count?: Prisma.CustomerLegalCountOrderByAggregateInput
@@ -237,71 +238,71 @@ export type CustomerLegalScalarWhereWithAggregatesInput = {
AND?: Prisma.CustomerLegalScalarWhereWithAggregatesInput | Prisma.CustomerLegalScalarWhereWithAggregatesInput[] AND?: Prisma.CustomerLegalScalarWhereWithAggregatesInput | Prisma.CustomerLegalScalarWhereWithAggregatesInput[]
OR?: Prisma.CustomerLegalScalarWhereWithAggregatesInput[] OR?: Prisma.CustomerLegalScalarWhereWithAggregatesInput[]
NOT?: Prisma.CustomerLegalScalarWhereWithAggregatesInput | Prisma.CustomerLegalScalarWhereWithAggregatesInput[] NOT?: Prisma.CustomerLegalScalarWhereWithAggregatesInput | Prisma.CustomerLegalScalarWhereWithAggregatesInput[]
name?: Prisma.StringWithAggregatesFilter<"CustomerLegal"> | string name?: Prisma.StringNullableWithAggregatesFilter<"CustomerLegal"> | string | null
economic_code?: Prisma.StringWithAggregatesFilter<"CustomerLegal"> | string economic_code?: Prisma.StringNullableWithAggregatesFilter<"CustomerLegal"> | string | null
registration_number?: Prisma.StringNullableWithAggregatesFilter<"CustomerLegal"> | string | null registration_number?: Prisma.StringNullableWithAggregatesFilter<"CustomerLegal"> | string | null
postal_code?: Prisma.StringWithAggregatesFilter<"CustomerLegal"> | string postal_code?: Prisma.StringNullableWithAggregatesFilter<"CustomerLegal"> | string | null
customer_id?: Prisma.StringWithAggregatesFilter<"CustomerLegal"> | string customer_id?: Prisma.StringWithAggregatesFilter<"CustomerLegal"> | string
business_activity_id?: Prisma.StringWithAggregatesFilter<"CustomerLegal"> | string business_activity_id?: Prisma.StringWithAggregatesFilter<"CustomerLegal"> | string
} }
export type CustomerLegalCreateInput = { export type CustomerLegalCreateInput = {
name: string name?: string | null
economic_code: string economic_code?: string | null
registration_number?: string | null registration_number?: string | null
postal_code: string postal_code?: string | null
business_activity: Prisma.BusinessActivityCreateNestedOneWithoutCustomer_legalsInput business_activity: Prisma.BusinessActivityCreateNestedOneWithoutCustomer_legalsInput
customer: Prisma.CustomerCreateNestedOneWithoutLegalInput customer: Prisma.CustomerCreateNestedOneWithoutLegalInput
} }
export type CustomerLegalUncheckedCreateInput = { export type CustomerLegalUncheckedCreateInput = {
name: string name?: string | null
economic_code: string economic_code?: string | null
registration_number?: string | null registration_number?: string | null
postal_code: string postal_code?: string | null
customer_id: string customer_id: string
business_activity_id: string business_activity_id: string
} }
export type CustomerLegalUpdateInput = { export type CustomerLegalUpdateInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.StringFieldUpdateOperationsInput | string economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
business_activity?: Prisma.BusinessActivityUpdateOneRequiredWithoutCustomer_legalsNestedInput business_activity?: Prisma.BusinessActivityUpdateOneRequiredWithoutCustomer_legalsNestedInput
customer?: Prisma.CustomerUpdateOneRequiredWithoutLegalNestedInput customer?: Prisma.CustomerUpdateOneRequiredWithoutLegalNestedInput
} }
export type CustomerLegalUncheckedUpdateInput = { export type CustomerLegalUncheckedUpdateInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.StringFieldUpdateOperationsInput | string economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer_id?: Prisma.StringFieldUpdateOperationsInput | string customer_id?: Prisma.StringFieldUpdateOperationsInput | string
business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string
} }
export type CustomerLegalCreateManyInput = { export type CustomerLegalCreateManyInput = {
name: string name?: string | null
economic_code: string economic_code?: string | null
registration_number?: string | null registration_number?: string | null
postal_code: string postal_code?: string | null
customer_id: string customer_id: string
business_activity_id: string business_activity_id: string
} }
export type CustomerLegalUpdateManyMutationInput = { export type CustomerLegalUpdateManyMutationInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.StringFieldUpdateOperationsInput | string economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
} }
export type CustomerLegalUncheckedUpdateManyInput = { export type CustomerLegalUncheckedUpdateManyInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.StringFieldUpdateOperationsInput | string economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer_id?: Prisma.StringFieldUpdateOperationsInput | string customer_id?: Prisma.StringFieldUpdateOperationsInput | string
business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string
} }
@@ -332,6 +333,12 @@ export type CustomerLegalBusiness_activity_idEconomic_codeCompoundUniqueInput =
economic_code: string economic_code: string
} }
export type CustomerLegalBusiness_activity_idPostal_codeRegistration_numberCompoundUniqueInput = {
business_activity_id: string
postal_code: string
registration_number: string
}
export type CustomerLegalCountOrderByAggregateInput = { export type CustomerLegalCountOrderByAggregateInput = {
name?: Prisma.SortOrder name?: Prisma.SortOrder
economic_code?: Prisma.SortOrder economic_code?: Prisma.SortOrder
@@ -434,18 +441,18 @@ export type CustomerLegalUncheckedUpdateOneWithoutCustomerNestedInput = {
} }
export type CustomerLegalCreateWithoutBusiness_activityInput = { export type CustomerLegalCreateWithoutBusiness_activityInput = {
name: string name?: string | null
economic_code: string economic_code?: string | null
registration_number?: string | null registration_number?: string | null
postal_code: string postal_code?: string | null
customer: Prisma.CustomerCreateNestedOneWithoutLegalInput customer: Prisma.CustomerCreateNestedOneWithoutLegalInput
} }
export type CustomerLegalUncheckedCreateWithoutBusiness_activityInput = { export type CustomerLegalUncheckedCreateWithoutBusiness_activityInput = {
name: string name?: string | null
economic_code: string economic_code?: string | null
registration_number?: string | null registration_number?: string | null
postal_code: string postal_code?: string | null
customer_id: string customer_id: string
} }
@@ -479,27 +486,27 @@ export type CustomerLegalScalarWhereInput = {
AND?: Prisma.CustomerLegalScalarWhereInput | Prisma.CustomerLegalScalarWhereInput[] AND?: Prisma.CustomerLegalScalarWhereInput | Prisma.CustomerLegalScalarWhereInput[]
OR?: Prisma.CustomerLegalScalarWhereInput[] OR?: Prisma.CustomerLegalScalarWhereInput[]
NOT?: Prisma.CustomerLegalScalarWhereInput | Prisma.CustomerLegalScalarWhereInput[] NOT?: Prisma.CustomerLegalScalarWhereInput | Prisma.CustomerLegalScalarWhereInput[]
name?: Prisma.StringFilter<"CustomerLegal"> | string name?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
economic_code?: Prisma.StringFilter<"CustomerLegal"> | string economic_code?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
registration_number?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null registration_number?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
postal_code?: Prisma.StringFilter<"CustomerLegal"> | string postal_code?: Prisma.StringNullableFilter<"CustomerLegal"> | string | null
customer_id?: Prisma.StringFilter<"CustomerLegal"> | string customer_id?: Prisma.StringFilter<"CustomerLegal"> | string
business_activity_id?: Prisma.StringFilter<"CustomerLegal"> | string business_activity_id?: Prisma.StringFilter<"CustomerLegal"> | string
} }
export type CustomerLegalCreateWithoutCustomerInput = { export type CustomerLegalCreateWithoutCustomerInput = {
name: string name?: string | null
economic_code: string economic_code?: string | null
registration_number?: string | null registration_number?: string | null
postal_code: string postal_code?: string | null
business_activity: Prisma.BusinessActivityCreateNestedOneWithoutCustomer_legalsInput business_activity: Prisma.BusinessActivityCreateNestedOneWithoutCustomer_legalsInput
} }
export type CustomerLegalUncheckedCreateWithoutCustomerInput = { export type CustomerLegalUncheckedCreateWithoutCustomerInput = {
name: string name?: string | null
economic_code: string economic_code?: string | null
registration_number?: string | null registration_number?: string | null
postal_code: string postal_code?: string | null
business_activity_id: string business_activity_id: string
} }
@@ -520,50 +527,50 @@ export type CustomerLegalUpdateToOneWithWhereWithoutCustomerInput = {
} }
export type CustomerLegalUpdateWithoutCustomerInput = { export type CustomerLegalUpdateWithoutCustomerInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.StringFieldUpdateOperationsInput | string economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
business_activity?: Prisma.BusinessActivityUpdateOneRequiredWithoutCustomer_legalsNestedInput business_activity?: Prisma.BusinessActivityUpdateOneRequiredWithoutCustomer_legalsNestedInput
} }
export type CustomerLegalUncheckedUpdateWithoutCustomerInput = { export type CustomerLegalUncheckedUpdateWithoutCustomerInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.StringFieldUpdateOperationsInput | string economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string business_activity_id?: Prisma.StringFieldUpdateOperationsInput | string
} }
export type CustomerLegalCreateManyBusiness_activityInput = { export type CustomerLegalCreateManyBusiness_activityInput = {
name: string name?: string | null
economic_code: string economic_code?: string | null
registration_number?: string | null registration_number?: string | null
postal_code: string postal_code?: string | null
customer_id: string customer_id: string
} }
export type CustomerLegalUpdateWithoutBusiness_activityInput = { export type CustomerLegalUpdateWithoutBusiness_activityInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.StringFieldUpdateOperationsInput | string economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer?: Prisma.CustomerUpdateOneRequiredWithoutLegalNestedInput customer?: Prisma.CustomerUpdateOneRequiredWithoutLegalNestedInput
} }
export type CustomerLegalUncheckedUpdateWithoutBusiness_activityInput = { export type CustomerLegalUncheckedUpdateWithoutBusiness_activityInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.StringFieldUpdateOperationsInput | string economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer_id?: Prisma.StringFieldUpdateOperationsInput | string customer_id?: Prisma.StringFieldUpdateOperationsInput | string
} }
export type CustomerLegalUncheckedUpdateManyWithoutBusiness_activityInput = { export type CustomerLegalUncheckedUpdateManyWithoutBusiness_activityInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
economic_code?: Prisma.StringFieldUpdateOperationsInput | string economic_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null registration_number?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
postal_code?: Prisma.StringFieldUpdateOperationsInput | string postal_code?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
customer_id?: Prisma.StringFieldUpdateOperationsInput | string customer_id?: Prisma.StringFieldUpdateOperationsInput | string
} }
@@ -604,10 +611,10 @@ export type $CustomerLegalPayload<ExtArgs extends runtime.Types.Extensions.Inter
customer: Prisma.$CustomerPayload<ExtArgs> customer: Prisma.$CustomerPayload<ExtArgs>
} }
scalars: runtime.Types.Extensions.GetPayloadResult<{ scalars: runtime.Types.Extensions.GetPayloadResult<{
name: string name: string | null
economic_code: string economic_code: string | null
registration_number: string | null registration_number: string | null
postal_code: string postal_code: string | null
customer_id: string customer_id: string
business_activity_id: string business_activity_id: string
}, ExtArgs["result"]["customerLegal"]> }, ExtArgs["result"]["customerLegal"]>
File diff suppressed because it is too large Load Diff
+142 -91
View File
@@ -31,6 +31,7 @@ export type SalesInvoiceItemAvgAggregateOutputType = {
sku_vat: runtime.Decimal | null sku_vat: runtime.Decimal | null
unit_price: runtime.Decimal | null unit_price: runtime.Decimal | null
total_amount: runtime.Decimal | null total_amount: runtime.Decimal | null
discount: runtime.Decimal | null
discount_amount: runtime.Decimal | null discount_amount: runtime.Decimal | null
tax_amount: runtime.Decimal | null tax_amount: runtime.Decimal | null
} }
@@ -40,6 +41,7 @@ export type SalesInvoiceItemSumAggregateOutputType = {
sku_vat: runtime.Decimal | null sku_vat: runtime.Decimal | null
unit_price: runtime.Decimal | null unit_price: runtime.Decimal | null
total_amount: runtime.Decimal | null total_amount: runtime.Decimal | null
discount: runtime.Decimal | null
discount_amount: runtime.Decimal | null discount_amount: runtime.Decimal | null
tax_amount: runtime.Decimal | null tax_amount: runtime.Decimal | null
} }
@@ -54,12 +56,13 @@ export type SalesInvoiceItemMinAggregateOutputType = {
unit_price: runtime.Decimal | null unit_price: runtime.Decimal | null
total_amount: runtime.Decimal | null total_amount: runtime.Decimal | null
created_at: Date | null created_at: Date | null
discount_amount: runtime.Decimal | null discount: runtime.Decimal | null
tax_amount: runtime.Decimal | null
notes: string | null notes: string | null
invoice_id: string | null invoice_id: string | null
good_id: string | null good_id: string | null
service_id: string | null service_id: string | null
discount_amount: runtime.Decimal | null
tax_amount: runtime.Decimal | null
} }
export type SalesInvoiceItemMaxAggregateOutputType = { export type SalesInvoiceItemMaxAggregateOutputType = {
@@ -72,12 +75,13 @@ export type SalesInvoiceItemMaxAggregateOutputType = {
unit_price: runtime.Decimal | null unit_price: runtime.Decimal | null
total_amount: runtime.Decimal | null total_amount: runtime.Decimal | null
created_at: Date | null created_at: Date | null
discount_amount: runtime.Decimal | null discount: runtime.Decimal | null
tax_amount: runtime.Decimal | null
notes: string | null notes: string | null
invoice_id: string | null invoice_id: string | null
good_id: string | null good_id: string | null
service_id: string | null service_id: string | null
discount_amount: runtime.Decimal | null
tax_amount: runtime.Decimal | null
} }
export type SalesInvoiceItemCountAggregateOutputType = { export type SalesInvoiceItemCountAggregateOutputType = {
@@ -90,14 +94,15 @@ export type SalesInvoiceItemCountAggregateOutputType = {
unit_price: number unit_price: number
total_amount: number total_amount: number
created_at: number created_at: number
discount_amount: number discount: number
tax_amount: number
notes: number notes: number
payload: number payload: number
good_snapshot: number good_snapshot: number
invoice_id: number invoice_id: number
good_id: number good_id: number
service_id: number service_id: number
discount_amount: number
tax_amount: number
_all: number _all: number
} }
@@ -107,6 +112,7 @@ export type SalesInvoiceItemAvgAggregateInputType = {
sku_vat?: true sku_vat?: true
unit_price?: true unit_price?: true
total_amount?: true total_amount?: true
discount?: true
discount_amount?: true discount_amount?: true
tax_amount?: true tax_amount?: true
} }
@@ -116,6 +122,7 @@ export type SalesInvoiceItemSumAggregateInputType = {
sku_vat?: true sku_vat?: true
unit_price?: true unit_price?: true
total_amount?: true total_amount?: true
discount?: true
discount_amount?: true discount_amount?: true
tax_amount?: true tax_amount?: true
} }
@@ -130,12 +137,13 @@ export type SalesInvoiceItemMinAggregateInputType = {
unit_price?: true unit_price?: true
total_amount?: true total_amount?: true
created_at?: true created_at?: true
discount_amount?: true discount?: true
tax_amount?: true
notes?: true notes?: true
invoice_id?: true invoice_id?: true
good_id?: true good_id?: true
service_id?: true service_id?: true
discount_amount?: true
tax_amount?: true
} }
export type SalesInvoiceItemMaxAggregateInputType = { export type SalesInvoiceItemMaxAggregateInputType = {
@@ -148,12 +156,13 @@ export type SalesInvoiceItemMaxAggregateInputType = {
unit_price?: true unit_price?: true
total_amount?: true total_amount?: true
created_at?: true created_at?: true
discount_amount?: true discount?: true
tax_amount?: true
notes?: true notes?: true
invoice_id?: true invoice_id?: true
good_id?: true good_id?: true
service_id?: true service_id?: true
discount_amount?: true
tax_amount?: true
} }
export type SalesInvoiceItemCountAggregateInputType = { export type SalesInvoiceItemCountAggregateInputType = {
@@ -166,14 +175,15 @@ export type SalesInvoiceItemCountAggregateInputType = {
unit_price?: true unit_price?: true
total_amount?: true total_amount?: true
created_at?: true created_at?: true
discount_amount?: true discount?: true
tax_amount?: true
notes?: true notes?: true
payload?: true payload?: true
good_snapshot?: true good_snapshot?: true
invoice_id?: true invoice_id?: true
good_id?: true good_id?: true
service_id?: true service_id?: true
discount_amount?: true
tax_amount?: true
_all?: true _all?: true
} }
@@ -273,14 +283,15 @@ export type SalesInvoiceItemGroupByOutputType = {
unit_price: runtime.Decimal unit_price: runtime.Decimal
total_amount: runtime.Decimal total_amount: runtime.Decimal
created_at: Date created_at: Date
discount_amount: runtime.Decimal discount: runtime.Decimal
tax_amount: runtime.Decimal
notes: string | null notes: string | null
payload: runtime.JsonValue | null payload: runtime.JsonValue | null
good_snapshot: runtime.JsonValue good_snapshot: runtime.JsonValue
invoice_id: string invoice_id: string
good_id: string good_id: string
service_id: string | null service_id: string | null
discount_amount: runtime.Decimal | null
tax_amount: runtime.Decimal | null
_count: SalesInvoiceItemCountAggregateOutputType | null _count: SalesInvoiceItemCountAggregateOutputType | null
_avg: SalesInvoiceItemAvgAggregateOutputType | null _avg: SalesInvoiceItemAvgAggregateOutputType | null
_sum: SalesInvoiceItemSumAggregateOutputType | null _sum: SalesInvoiceItemSumAggregateOutputType | null
@@ -316,14 +327,15 @@ export type SalesInvoiceItemWhereInput = {
unit_price?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFilter<"SalesInvoiceItem"> | Date | string created_at?: Prisma.DateTimeFilter<"SalesInvoiceItem"> | Date | string
discount_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null notes?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null
payload?: Prisma.JsonNullableFilter<"SalesInvoiceItem"> payload?: Prisma.JsonNullableFilter<"SalesInvoiceItem">
good_snapshot?: Prisma.JsonFilter<"SalesInvoiceItem"> good_snapshot?: Prisma.JsonFilter<"SalesInvoiceItem">
invoice_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string invoice_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string
good_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string good_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string
service_id?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null service_id?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null
discount_amount?: Prisma.DecimalNullableFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.DecimalNullableFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string | null
good?: Prisma.XOR<Prisma.GoodScalarRelationFilter, Prisma.GoodWhereInput> good?: Prisma.XOR<Prisma.GoodScalarRelationFilter, Prisma.GoodWhereInput>
invoice?: Prisma.XOR<Prisma.SalesInvoiceScalarRelationFilter, Prisma.SalesInvoiceWhereInput> invoice?: Prisma.XOR<Prisma.SalesInvoiceScalarRelationFilter, Prisma.SalesInvoiceWhereInput>
service?: Prisma.XOR<Prisma.ServiceNullableScalarRelationFilter, Prisma.ServiceWhereInput> | null service?: Prisma.XOR<Prisma.ServiceNullableScalarRelationFilter, Prisma.ServiceWhereInput> | null
@@ -339,14 +351,15 @@ export type SalesInvoiceItemOrderByWithRelationInput = {
unit_price?: Prisma.SortOrder unit_price?: Prisma.SortOrder
total_amount?: Prisma.SortOrder total_amount?: Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder discount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder
notes?: Prisma.SortOrderInput | Prisma.SortOrder notes?: Prisma.SortOrderInput | Prisma.SortOrder
payload?: Prisma.SortOrderInput | Prisma.SortOrder payload?: Prisma.SortOrderInput | Prisma.SortOrder
good_snapshot?: Prisma.SortOrder good_snapshot?: Prisma.SortOrder
invoice_id?: Prisma.SortOrder invoice_id?: Prisma.SortOrder
good_id?: Prisma.SortOrder good_id?: Prisma.SortOrder
service_id?: Prisma.SortOrderInput | Prisma.SortOrder service_id?: Prisma.SortOrderInput | Prisma.SortOrder
discount_amount?: Prisma.SortOrderInput | Prisma.SortOrder
tax_amount?: Prisma.SortOrderInput | Prisma.SortOrder
good?: Prisma.GoodOrderByWithRelationInput good?: Prisma.GoodOrderByWithRelationInput
invoice?: Prisma.SalesInvoiceOrderByWithRelationInput invoice?: Prisma.SalesInvoiceOrderByWithRelationInput
service?: Prisma.ServiceOrderByWithRelationInput service?: Prisma.ServiceOrderByWithRelationInput
@@ -366,14 +379,15 @@ export type SalesInvoiceItemWhereUniqueInput = Prisma.AtLeast<{
unit_price?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFilter<"SalesInvoiceItem"> | Date | string created_at?: Prisma.DateTimeFilter<"SalesInvoiceItem"> | Date | string
discount_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null notes?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null
payload?: Prisma.JsonNullableFilter<"SalesInvoiceItem"> payload?: Prisma.JsonNullableFilter<"SalesInvoiceItem">
good_snapshot?: Prisma.JsonFilter<"SalesInvoiceItem"> good_snapshot?: Prisma.JsonFilter<"SalesInvoiceItem">
invoice_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string invoice_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string
good_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string good_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string
service_id?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null service_id?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null
discount_amount?: Prisma.DecimalNullableFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.DecimalNullableFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string | null
good?: Prisma.XOR<Prisma.GoodScalarRelationFilter, Prisma.GoodWhereInput> good?: Prisma.XOR<Prisma.GoodScalarRelationFilter, Prisma.GoodWhereInput>
invoice?: Prisma.XOR<Prisma.SalesInvoiceScalarRelationFilter, Prisma.SalesInvoiceWhereInput> invoice?: Prisma.XOR<Prisma.SalesInvoiceScalarRelationFilter, Prisma.SalesInvoiceWhereInput>
service?: Prisma.XOR<Prisma.ServiceNullableScalarRelationFilter, Prisma.ServiceWhereInput> | null service?: Prisma.XOR<Prisma.ServiceNullableScalarRelationFilter, Prisma.ServiceWhereInput> | null
@@ -389,14 +403,15 @@ export type SalesInvoiceItemOrderByWithAggregationInput = {
unit_price?: Prisma.SortOrder unit_price?: Prisma.SortOrder
total_amount?: Prisma.SortOrder total_amount?: Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder discount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder
notes?: Prisma.SortOrderInput | Prisma.SortOrder notes?: Prisma.SortOrderInput | Prisma.SortOrder
payload?: Prisma.SortOrderInput | Prisma.SortOrder payload?: Prisma.SortOrderInput | Prisma.SortOrder
good_snapshot?: Prisma.SortOrder good_snapshot?: Prisma.SortOrder
invoice_id?: Prisma.SortOrder invoice_id?: Prisma.SortOrder
good_id?: Prisma.SortOrder good_id?: Prisma.SortOrder
service_id?: Prisma.SortOrderInput | Prisma.SortOrder service_id?: Prisma.SortOrderInput | Prisma.SortOrder
discount_amount?: Prisma.SortOrderInput | Prisma.SortOrder
tax_amount?: Prisma.SortOrderInput | Prisma.SortOrder
_count?: Prisma.SalesInvoiceItemCountOrderByAggregateInput _count?: Prisma.SalesInvoiceItemCountOrderByAggregateInput
_avg?: Prisma.SalesInvoiceItemAvgOrderByAggregateInput _avg?: Prisma.SalesInvoiceItemAvgOrderByAggregateInput
_max?: Prisma.SalesInvoiceItemMaxOrderByAggregateInput _max?: Prisma.SalesInvoiceItemMaxOrderByAggregateInput
@@ -417,14 +432,15 @@ export type SalesInvoiceItemScalarWhereWithAggregatesInput = {
unit_price?: Prisma.DecimalWithAggregatesFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalWithAggregatesFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalWithAggregatesFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalWithAggregatesFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeWithAggregatesFilter<"SalesInvoiceItem"> | Date | string created_at?: Prisma.DateTimeWithAggregatesFilter<"SalesInvoiceItem"> | Date | string
discount_amount?: Prisma.DecimalWithAggregatesFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalWithAggregatesFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalWithAggregatesFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.StringNullableWithAggregatesFilter<"SalesInvoiceItem"> | string | null notes?: Prisma.StringNullableWithAggregatesFilter<"SalesInvoiceItem"> | string | null
payload?: Prisma.JsonNullableWithAggregatesFilter<"SalesInvoiceItem"> payload?: Prisma.JsonNullableWithAggregatesFilter<"SalesInvoiceItem">
good_snapshot?: Prisma.JsonWithAggregatesFilter<"SalesInvoiceItem"> good_snapshot?: Prisma.JsonWithAggregatesFilter<"SalesInvoiceItem">
invoice_id?: Prisma.StringWithAggregatesFilter<"SalesInvoiceItem"> | string invoice_id?: Prisma.StringWithAggregatesFilter<"SalesInvoiceItem"> | string
good_id?: Prisma.StringWithAggregatesFilter<"SalesInvoiceItem"> | string good_id?: Prisma.StringWithAggregatesFilter<"SalesInvoiceItem"> | string
service_id?: Prisma.StringNullableWithAggregatesFilter<"SalesInvoiceItem"> | string | null service_id?: Prisma.StringNullableWithAggregatesFilter<"SalesInvoiceItem"> | string | null
discount_amount?: Prisma.DecimalNullableWithAggregatesFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.DecimalNullableWithAggregatesFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemCreateInput = { export type SalesInvoiceItemCreateInput = {
@@ -437,11 +453,12 @@ export type SalesInvoiceItemCreateInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
good: Prisma.GoodCreateNestedOneWithoutSales_invoice_itemsInput good: Prisma.GoodCreateNestedOneWithoutSales_invoice_itemsInput
invoice: Prisma.SalesInvoiceCreateNestedOneWithoutItemsInput invoice: Prisma.SalesInvoiceCreateNestedOneWithoutItemsInput
service?: Prisma.ServiceCreateNestedOneWithoutSales_invoice_itemsInput service?: Prisma.ServiceCreateNestedOneWithoutSales_invoice_itemsInput
@@ -457,14 +474,15 @@ export type SalesInvoiceItemUncheckedCreateInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id: string invoice_id: string
good_id: string good_id: string
service_id?: string | null service_id?: string | null
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemUpdateInput = { export type SalesInvoiceItemUpdateInput = {
@@ -477,11 +495,12 @@ export type SalesInvoiceItemUpdateInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
good?: Prisma.GoodUpdateOneRequiredWithoutSales_invoice_itemsNestedInput good?: Prisma.GoodUpdateOneRequiredWithoutSales_invoice_itemsNestedInput
invoice?: Prisma.SalesInvoiceUpdateOneRequiredWithoutItemsNestedInput invoice?: Prisma.SalesInvoiceUpdateOneRequiredWithoutItemsNestedInput
service?: Prisma.ServiceUpdateOneWithoutSales_invoice_itemsNestedInput service?: Prisma.ServiceUpdateOneWithoutSales_invoice_itemsNestedInput
@@ -497,14 +516,15 @@ export type SalesInvoiceItemUncheckedUpdateInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id?: Prisma.StringFieldUpdateOperationsInput | string invoice_id?: Prisma.StringFieldUpdateOperationsInput | string
good_id?: Prisma.StringFieldUpdateOperationsInput | string good_id?: Prisma.StringFieldUpdateOperationsInput | string
service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemCreateManyInput = { export type SalesInvoiceItemCreateManyInput = {
@@ -517,14 +537,15 @@ export type SalesInvoiceItemCreateManyInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id: string invoice_id: string
good_id: string good_id: string
service_id?: string | null service_id?: string | null
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemUpdateManyMutationInput = { export type SalesInvoiceItemUpdateManyMutationInput = {
@@ -537,11 +558,12 @@ export type SalesInvoiceItemUpdateManyMutationInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemUncheckedUpdateManyInput = { export type SalesInvoiceItemUncheckedUpdateManyInput = {
@@ -554,14 +576,15 @@ export type SalesInvoiceItemUncheckedUpdateManyInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id?: Prisma.StringFieldUpdateOperationsInput | string invoice_id?: Prisma.StringFieldUpdateOperationsInput | string
good_id?: Prisma.StringFieldUpdateOperationsInput | string good_id?: Prisma.StringFieldUpdateOperationsInput | string
service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemListRelationFilter = { export type SalesInvoiceItemListRelationFilter = {
@@ -590,14 +613,15 @@ export type SalesInvoiceItemCountOrderByAggregateInput = {
unit_price?: Prisma.SortOrder unit_price?: Prisma.SortOrder
total_amount?: Prisma.SortOrder total_amount?: Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder discount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder
notes?: Prisma.SortOrder notes?: Prisma.SortOrder
payload?: Prisma.SortOrder payload?: Prisma.SortOrder
good_snapshot?: Prisma.SortOrder good_snapshot?: Prisma.SortOrder
invoice_id?: Prisma.SortOrder invoice_id?: Prisma.SortOrder
good_id?: Prisma.SortOrder good_id?: Prisma.SortOrder
service_id?: Prisma.SortOrder service_id?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder
} }
export type SalesInvoiceItemAvgOrderByAggregateInput = { export type SalesInvoiceItemAvgOrderByAggregateInput = {
@@ -605,6 +629,7 @@ export type SalesInvoiceItemAvgOrderByAggregateInput = {
sku_vat?: Prisma.SortOrder sku_vat?: Prisma.SortOrder
unit_price?: Prisma.SortOrder unit_price?: Prisma.SortOrder
total_amount?: Prisma.SortOrder total_amount?: Prisma.SortOrder
discount?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder discount_amount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder tax_amount?: Prisma.SortOrder
} }
@@ -619,12 +644,13 @@ export type SalesInvoiceItemMaxOrderByAggregateInput = {
unit_price?: Prisma.SortOrder unit_price?: Prisma.SortOrder
total_amount?: Prisma.SortOrder total_amount?: Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder discount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder
notes?: Prisma.SortOrder notes?: Prisma.SortOrder
invoice_id?: Prisma.SortOrder invoice_id?: Prisma.SortOrder
good_id?: Prisma.SortOrder good_id?: Prisma.SortOrder
service_id?: Prisma.SortOrder service_id?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder
} }
export type SalesInvoiceItemMinOrderByAggregateInput = { export type SalesInvoiceItemMinOrderByAggregateInput = {
@@ -637,12 +663,13 @@ export type SalesInvoiceItemMinOrderByAggregateInput = {
unit_price?: Prisma.SortOrder unit_price?: Prisma.SortOrder
total_amount?: Prisma.SortOrder total_amount?: Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder discount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder
notes?: Prisma.SortOrder notes?: Prisma.SortOrder
invoice_id?: Prisma.SortOrder invoice_id?: Prisma.SortOrder
good_id?: Prisma.SortOrder good_id?: Prisma.SortOrder
service_id?: Prisma.SortOrder service_id?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder
} }
export type SalesInvoiceItemSumOrderByAggregateInput = { export type SalesInvoiceItemSumOrderByAggregateInput = {
@@ -650,6 +677,7 @@ export type SalesInvoiceItemSumOrderByAggregateInput = {
sku_vat?: Prisma.SortOrder sku_vat?: Prisma.SortOrder
unit_price?: Prisma.SortOrder unit_price?: Prisma.SortOrder
total_amount?: Prisma.SortOrder total_amount?: Prisma.SortOrder
discount?: Prisma.SortOrder
discount_amount?: Prisma.SortOrder discount_amount?: Prisma.SortOrder
tax_amount?: Prisma.SortOrder tax_amount?: Prisma.SortOrder
} }
@@ -790,11 +818,12 @@ export type SalesInvoiceItemCreateWithoutGoodInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
invoice: Prisma.SalesInvoiceCreateNestedOneWithoutItemsInput invoice: Prisma.SalesInvoiceCreateNestedOneWithoutItemsInput
service?: Prisma.ServiceCreateNestedOneWithoutSales_invoice_itemsInput service?: Prisma.ServiceCreateNestedOneWithoutSales_invoice_itemsInput
} }
@@ -809,13 +838,14 @@ export type SalesInvoiceItemUncheckedCreateWithoutGoodInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id: string invoice_id: string
service_id?: string | null service_id?: string | null
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemCreateOrConnectWithoutGoodInput = { export type SalesInvoiceItemCreateOrConnectWithoutGoodInput = {
@@ -857,14 +887,15 @@ export type SalesInvoiceItemScalarWhereInput = {
unit_price?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFilter<"SalesInvoiceItem"> | Date | string created_at?: Prisma.DateTimeFilter<"SalesInvoiceItem"> | Date | string
discount_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null notes?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null
payload?: Prisma.JsonNullableFilter<"SalesInvoiceItem"> payload?: Prisma.JsonNullableFilter<"SalesInvoiceItem">
good_snapshot?: Prisma.JsonFilter<"SalesInvoiceItem"> good_snapshot?: Prisma.JsonFilter<"SalesInvoiceItem">
invoice_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string invoice_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string
good_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string good_id?: Prisma.StringFilter<"SalesInvoiceItem"> | string
service_id?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null service_id?: Prisma.StringNullableFilter<"SalesInvoiceItem"> | string | null
discount_amount?: Prisma.DecimalNullableFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.DecimalNullableFilter<"SalesInvoiceItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemCreateWithoutInvoiceInput = { export type SalesInvoiceItemCreateWithoutInvoiceInput = {
@@ -877,11 +908,12 @@ export type SalesInvoiceItemCreateWithoutInvoiceInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
good: Prisma.GoodCreateNestedOneWithoutSales_invoice_itemsInput good: Prisma.GoodCreateNestedOneWithoutSales_invoice_itemsInput
service?: Prisma.ServiceCreateNestedOneWithoutSales_invoice_itemsInput service?: Prisma.ServiceCreateNestedOneWithoutSales_invoice_itemsInput
} }
@@ -896,13 +928,14 @@ export type SalesInvoiceItemUncheckedCreateWithoutInvoiceInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
good_id: string good_id: string
service_id?: string | null service_id?: string | null
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemCreateOrConnectWithoutInvoiceInput = { export type SalesInvoiceItemCreateOrConnectWithoutInvoiceInput = {
@@ -941,11 +974,12 @@ export type SalesInvoiceItemCreateWithoutServiceInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
good: Prisma.GoodCreateNestedOneWithoutSales_invoice_itemsInput good: Prisma.GoodCreateNestedOneWithoutSales_invoice_itemsInput
invoice: Prisma.SalesInvoiceCreateNestedOneWithoutItemsInput invoice: Prisma.SalesInvoiceCreateNestedOneWithoutItemsInput
} }
@@ -960,13 +994,14 @@ export type SalesInvoiceItemUncheckedCreateWithoutServiceInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id: string invoice_id: string
good_id: string good_id: string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemCreateOrConnectWithoutServiceInput = { export type SalesInvoiceItemCreateOrConnectWithoutServiceInput = {
@@ -1005,13 +1040,14 @@ export type SalesInvoiceItemCreateManyGoodInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id: string invoice_id: string
service_id?: string | null service_id?: string | null
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemUpdateWithoutGoodInput = { export type SalesInvoiceItemUpdateWithoutGoodInput = {
@@ -1024,11 +1060,12 @@ export type SalesInvoiceItemUpdateWithoutGoodInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
invoice?: Prisma.SalesInvoiceUpdateOneRequiredWithoutItemsNestedInput invoice?: Prisma.SalesInvoiceUpdateOneRequiredWithoutItemsNestedInput
service?: Prisma.ServiceUpdateOneWithoutSales_invoice_itemsNestedInput service?: Prisma.ServiceUpdateOneWithoutSales_invoice_itemsNestedInput
} }
@@ -1043,13 +1080,14 @@ export type SalesInvoiceItemUncheckedUpdateWithoutGoodInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id?: Prisma.StringFieldUpdateOperationsInput | string invoice_id?: Prisma.StringFieldUpdateOperationsInput | string
service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemUncheckedUpdateManyWithoutGoodInput = { export type SalesInvoiceItemUncheckedUpdateManyWithoutGoodInput = {
@@ -1062,13 +1100,14 @@ export type SalesInvoiceItemUncheckedUpdateManyWithoutGoodInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id?: Prisma.StringFieldUpdateOperationsInput | string invoice_id?: Prisma.StringFieldUpdateOperationsInput | string
service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemCreateManyInvoiceInput = { export type SalesInvoiceItemCreateManyInvoiceInput = {
@@ -1081,13 +1120,14 @@ export type SalesInvoiceItemCreateManyInvoiceInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
good_id: string good_id: string
service_id?: string | null service_id?: string | null
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemUpdateWithoutInvoiceInput = { export type SalesInvoiceItemUpdateWithoutInvoiceInput = {
@@ -1100,11 +1140,12 @@ export type SalesInvoiceItemUpdateWithoutInvoiceInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
good?: Prisma.GoodUpdateOneRequiredWithoutSales_invoice_itemsNestedInput good?: Prisma.GoodUpdateOneRequiredWithoutSales_invoice_itemsNestedInput
service?: Prisma.ServiceUpdateOneWithoutSales_invoice_itemsNestedInput service?: Prisma.ServiceUpdateOneWithoutSales_invoice_itemsNestedInput
} }
@@ -1119,13 +1160,14 @@ export type SalesInvoiceItemUncheckedUpdateWithoutInvoiceInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
good_id?: Prisma.StringFieldUpdateOperationsInput | string good_id?: Prisma.StringFieldUpdateOperationsInput | string
service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemUncheckedUpdateManyWithoutInvoiceInput = { export type SalesInvoiceItemUncheckedUpdateManyWithoutInvoiceInput = {
@@ -1138,13 +1180,14 @@ export type SalesInvoiceItemUncheckedUpdateManyWithoutInvoiceInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
good_id?: Prisma.StringFieldUpdateOperationsInput | string good_id?: Prisma.StringFieldUpdateOperationsInput | string
service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null service_id?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemCreateManyServiceInput = { export type SalesInvoiceItemCreateManyServiceInput = {
@@ -1157,13 +1200,14 @@ export type SalesInvoiceItemCreateManyServiceInput = {
unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Date | string created_at?: Date | string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string discount?: runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: string | null notes?: string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id: string invoice_id: string
good_id: string good_id: string
discount_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemUpdateWithoutServiceInput = { export type SalesInvoiceItemUpdateWithoutServiceInput = {
@@ -1176,11 +1220,12 @@ export type SalesInvoiceItemUpdateWithoutServiceInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
good?: Prisma.GoodUpdateOneRequiredWithoutSales_invoice_itemsNestedInput good?: Prisma.GoodUpdateOneRequiredWithoutSales_invoice_itemsNestedInput
invoice?: Prisma.SalesInvoiceUpdateOneRequiredWithoutItemsNestedInput invoice?: Prisma.SalesInvoiceUpdateOneRequiredWithoutItemsNestedInput
} }
@@ -1195,13 +1240,14 @@ export type SalesInvoiceItemUncheckedUpdateWithoutServiceInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id?: Prisma.StringFieldUpdateOperationsInput | string invoice_id?: Prisma.StringFieldUpdateOperationsInput | string
good_id?: Prisma.StringFieldUpdateOperationsInput | string good_id?: Prisma.StringFieldUpdateOperationsInput | string
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
export type SalesInvoiceItemUncheckedUpdateManyWithoutServiceInput = { export type SalesInvoiceItemUncheckedUpdateManyWithoutServiceInput = {
@@ -1214,13 +1260,14 @@ export type SalesInvoiceItemUncheckedUpdateManyWithoutServiceInput = {
unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string unit_price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string total_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
discount_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string discount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
tax_amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string
notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue good_snapshot?: Prisma.JsonNullValueInput | runtime.InputJsonValue
invoice_id?: Prisma.StringFieldUpdateOperationsInput | string invoice_id?: Prisma.StringFieldUpdateOperationsInput | string
good_id?: Prisma.StringFieldUpdateOperationsInput | string good_id?: Prisma.StringFieldUpdateOperationsInput | string
discount_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
tax_amount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null
} }
@@ -1235,14 +1282,15 @@ export type SalesInvoiceItemSelect<ExtArgs extends runtime.Types.Extensions.Inte
unit_price?: boolean unit_price?: boolean
total_amount?: boolean total_amount?: boolean
created_at?: boolean created_at?: boolean
discount_amount?: boolean discount?: boolean
tax_amount?: boolean
notes?: boolean notes?: boolean
payload?: boolean payload?: boolean
good_snapshot?: boolean good_snapshot?: boolean
invoice_id?: boolean invoice_id?: boolean
good_id?: boolean good_id?: boolean
service_id?: boolean service_id?: boolean
discount_amount?: boolean
tax_amount?: boolean
good?: boolean | Prisma.GoodDefaultArgs<ExtArgs> good?: boolean | Prisma.GoodDefaultArgs<ExtArgs>
invoice?: boolean | Prisma.SalesInvoiceDefaultArgs<ExtArgs> invoice?: boolean | Prisma.SalesInvoiceDefaultArgs<ExtArgs>
service?: boolean | Prisma.SalesInvoiceItem$serviceArgs<ExtArgs> service?: boolean | Prisma.SalesInvoiceItem$serviceArgs<ExtArgs>
@@ -1260,17 +1308,18 @@ export type SalesInvoiceItemSelectScalar = {
unit_price?: boolean unit_price?: boolean
total_amount?: boolean total_amount?: boolean
created_at?: boolean created_at?: boolean
discount_amount?: boolean discount?: boolean
tax_amount?: boolean
notes?: boolean notes?: boolean
payload?: boolean payload?: boolean
good_snapshot?: boolean good_snapshot?: boolean
invoice_id?: boolean invoice_id?: boolean
good_id?: boolean good_id?: boolean
service_id?: boolean service_id?: boolean
discount_amount?: boolean
tax_amount?: boolean
} }
export type SalesInvoiceItemOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "quantity" | "measure_unit_text" | "measure_unit_code" | "sku_code" | "sku_vat" | "unit_price" | "total_amount" | "created_at" | "discount_amount" | "tax_amount" | "notes" | "payload" | "good_snapshot" | "invoice_id" | "good_id" | "service_id", ExtArgs["result"]["salesInvoiceItem"]> export type SalesInvoiceItemOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "quantity" | "measure_unit_text" | "measure_unit_code" | "sku_code" | "sku_vat" | "unit_price" | "total_amount" | "created_at" | "discount" | "notes" | "payload" | "good_snapshot" | "invoice_id" | "good_id" | "service_id" | "discount_amount" | "tax_amount", ExtArgs["result"]["salesInvoiceItem"]>
export type SalesInvoiceItemInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type SalesInvoiceItemInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
good?: boolean | Prisma.GoodDefaultArgs<ExtArgs> good?: boolean | Prisma.GoodDefaultArgs<ExtArgs>
invoice?: boolean | Prisma.SalesInvoiceDefaultArgs<ExtArgs> invoice?: boolean | Prisma.SalesInvoiceDefaultArgs<ExtArgs>
@@ -1294,14 +1343,15 @@ export type $SalesInvoiceItemPayload<ExtArgs extends runtime.Types.Extensions.In
unit_price: runtime.Decimal unit_price: runtime.Decimal
total_amount: runtime.Decimal total_amount: runtime.Decimal
created_at: Date created_at: Date
discount_amount: runtime.Decimal discount: runtime.Decimal
tax_amount: runtime.Decimal
notes: string | null notes: string | null
payload: runtime.JsonValue | null payload: runtime.JsonValue | null
good_snapshot: runtime.JsonValue good_snapshot: runtime.JsonValue
invoice_id: string invoice_id: string
good_id: string good_id: string
service_id: string | null service_id: string | null
discount_amount: runtime.Decimal | null
tax_amount: runtime.Decimal | null
}, ExtArgs["result"]["salesInvoiceItem"]> }, ExtArgs["result"]["salesInvoiceItem"]>
composites: {} composites: {}
} }
@@ -1683,14 +1733,15 @@ export interface SalesInvoiceItemFieldRefs {
readonly unit_price: Prisma.FieldRef<"SalesInvoiceItem", 'Decimal'> readonly unit_price: Prisma.FieldRef<"SalesInvoiceItem", 'Decimal'>
readonly total_amount: Prisma.FieldRef<"SalesInvoiceItem", 'Decimal'> readonly total_amount: Prisma.FieldRef<"SalesInvoiceItem", 'Decimal'>
readonly created_at: Prisma.FieldRef<"SalesInvoiceItem", 'DateTime'> readonly created_at: Prisma.FieldRef<"SalesInvoiceItem", 'DateTime'>
readonly discount_amount: Prisma.FieldRef<"SalesInvoiceItem", 'Decimal'> readonly discount: Prisma.FieldRef<"SalesInvoiceItem", 'Decimal'>
readonly tax_amount: Prisma.FieldRef<"SalesInvoiceItem", 'Decimal'>
readonly notes: Prisma.FieldRef<"SalesInvoiceItem", 'String'> readonly notes: Prisma.FieldRef<"SalesInvoiceItem", 'String'>
readonly payload: Prisma.FieldRef<"SalesInvoiceItem", 'Json'> readonly payload: Prisma.FieldRef<"SalesInvoiceItem", 'Json'>
readonly good_snapshot: Prisma.FieldRef<"SalesInvoiceItem", 'Json'> readonly good_snapshot: Prisma.FieldRef<"SalesInvoiceItem", 'Json'>
readonly invoice_id: Prisma.FieldRef<"SalesInvoiceItem", 'String'> readonly invoice_id: Prisma.FieldRef<"SalesInvoiceItem", 'String'>
readonly good_id: Prisma.FieldRef<"SalesInvoiceItem", 'String'> readonly good_id: Prisma.FieldRef<"SalesInvoiceItem", 'String'>
readonly service_id: Prisma.FieldRef<"SalesInvoiceItem", 'String'> readonly service_id: Prisma.FieldRef<"SalesInvoiceItem", 'String'>
readonly discount_amount: Prisma.FieldRef<"SalesInvoiceItem", 'Decimal'>
readonly tax_amount: Prisma.FieldRef<"SalesInvoiceItem", 'Decimal'>
} }
+7 -5
View File
@@ -2,18 +2,20 @@ import { PrismaMariaDb } from '@prisma/adapter-mariadb'
import 'dotenv/config' import 'dotenv/config'
import { env } from 'prisma/config' import { env } from 'prisma/config'
import { PrismaClient } from '../generated/prisma/client'
const adapter = new PrismaMariaDb({ const adapter = new PrismaMariaDb({
host: env('DATABASE_HOST'), host: env('DATABASE_HOST'),
user: env('DATABASE_USER'), user: env('DATABASE_USER'),
password: env('DATABASE_PASSWORD'), password: env('DATABASE_PASSWORD'),
database: env('DATABASE_NAME'), database: env('DATABASE_NAME'),
ssl: false,
connectionLimit: 5, connectionLimit: 5,
port: Number(env('DATABASE_PORT')) || 3306, port: Number(env('DATABASE_PORT')) || 3306,
allowPublicKeyRetrieval: true,
ssl: {
rejectUnauthorized: false,
},
connectTimeout: 10000,
}) })
const prisma = new PrismaClient({ adapter }) // const prisma = new PrismaClient({ adapter })
export { prisma } export { adapter as prismaAdapter }
+3 -2
View File
@@ -17,6 +17,8 @@ const cookieParser = require('cookie-parser')
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule) const app = await NestFactory.create(AppModule)
app.enableShutdownHooks()
app.use(cookieParser()) app.use(cookieParser())
const config = new DocumentBuilder() const config = new DocumentBuilder()
@@ -33,6 +35,7 @@ async function bootstrap() {
in: 'header', in: 'header',
}) })
.build() .build()
const documentFactory = () => SwaggerModule.createDocument(app, config) const documentFactory = () => SwaggerModule.createDocument(app, config)
SwaggerModule.setup('swagger', app, documentFactory, { SwaggerModule.setup('swagger', app, documentFactory, {
swaggerOptions: { swaggerOptions: {
@@ -47,14 +50,12 @@ async function bootstrap() {
}, },
}, },
}) })
// Set API prefix and enable URI versioning so alls routes live under /api/v1/* // Set API prefix and enable URI versioning so alls routes live under /api/v1/*
app.setGlobalPrefix('api') app.setGlobalPrefix('api')
app.enableVersioning({ app.enableVersioning({
type: VersioningType.URI, type: VersioningType.URI,
defaultVersion: '1', defaultVersion: '1',
}) })
// Enable CORS. You can set `CORS_ORIGINS` to a comma-separated list of allowed origins. // Enable CORS. You can set `CORS_ORIGINS` to a comma-separated list of allowed origins.
// Defaults include common localhost origins used by front-end dev servers. // Defaults include common localhost origins used by front-end dev servers.
const defaultOrigins: string[] = [] const defaultOrigins: string[] = []
@@ -1,8 +1,16 @@
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common' import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger' import { ApiTags } from '@nestjs/swagger'
import { AccountsService } from './accounts.service' import { AccountsService } from './accounts.service'
import { CreateConsumerAccountDto, UpdateAccountDto } from './dto/account.dto' import {
import type { AccountsServiceCreateResponseDto, AccountsServiceFindAllResponseDto, AccountsServiceFindOneResponseDto, AccountsServiceUpdateResponseDto } from './dto/accounts-response.dto' CreateAdminConsumerAccountDto,
UpdateAdminConsumerAccountDto,
} from './dto/account.dto'
import type {
AccountsServiceCreateResponseDto,
AccountsServiceFindAllResponseDto,
AccountsServiceFindOneResponseDto,
AccountsServiceUpdateResponseDto,
} from './dto/accounts-response.dto'
@ApiTags('AdminConsumerAccounts') @ApiTags('AdminConsumerAccounts')
@Controller('admin/consumers/:consumerId/accounts') @Controller('admin/consumers/:consumerId/accounts')
@@ -10,7 +18,9 @@ export class AccountsController {
constructor(private readonly accountsService: AccountsService) {} constructor(private readonly accountsService: AccountsService) {}
@Get() @Get()
async findAll(@Param('consumerId') consumerId: string): Promise<AccountsServiceFindAllResponseDto> { async findAll(
@Param('consumerId') consumerId: string,
): Promise<AccountsServiceFindAllResponseDto> {
return this.accountsService.findAll(consumerId) return this.accountsService.findAll(consumerId)
} }
@@ -22,13 +32,16 @@ export class AccountsController {
@Post() @Post()
async create( async create(
@Param('consumerId') consumerId: string, @Param('consumerId') consumerId: string,
@Body() data: CreateConsumerAccountDto, @Body() data: CreateAdminConsumerAccountDto,
): Promise<AccountsServiceCreateResponseDto> { ): Promise<AccountsServiceCreateResponseDto> {
return this.accountsService.create(consumerId, data) return this.accountsService.create(consumerId, data)
} }
@Patch(':id') @Patch(':id')
async update(@Param('id') id: string, @Body() data: UpdateAccountDto): Promise<AccountsServiceUpdateResponseDto> { async update(
@Param('id') id: string,
@Body() data: UpdateAdminConsumerAccountDto,
): Promise<AccountsServiceUpdateResponseDto> {
return this.accountsService.update(id, data) return this.accountsService.update(id, data)
} }
@@ -4,7 +4,10 @@ import { AccountStatus, AccountType } from '@/generated/prisma/enums'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
import { CreateConsumerAccountDto, UpdateAccountDto } from './dto/account.dto' import {
CreateAdminConsumerAccountDto,
UpdateAdminConsumerAccountDto,
} from './dto/account.dto'
@Injectable() @Injectable()
export class AccountsService { export class AccountsService {
@@ -70,7 +73,7 @@ export class AccountsService {
return ResponseMapper.single(account) return ResponseMapper.single(account)
} }
async create(consumerId: string, data: CreateConsumerAccountDto) { async create(consumerId: string, data: CreateAdminConsumerAccountDto) {
const account = await this.prisma.consumerAccount.create({ const account = await this.prisma.consumerAccount.create({
data: { data: {
role: data.role, role: data.role,
@@ -95,7 +98,7 @@ export class AccountsService {
return ResponseMapper.create(account) return ResponseMapper.create(account)
} }
async update(id: string, data: UpdateAccountDto) { async update(id: string, data: UpdateAdminConsumerAccountDto) {
const account = await this.prisma.account.update({ where: { id }, data }) const account = await this.prisma.account.update({ where: { id }, data })
return ResponseMapper.update(account) return ResponseMapper.update(account)
} }
@@ -3,7 +3,7 @@ import { ApiProperty, PartialType } from '@nestjs/swagger'
import { IsEnum, IsOptional, IsString } from 'class-validator' import { IsEnum, IsOptional, IsString } from 'class-validator'
import { AccountStatus, ConsumerRole } from 'generated/prisma/enums' import { AccountStatus, ConsumerRole } from 'generated/prisma/enums'
export class CreateConsumerAccountDto { export class CreateAdminConsumerAccountDto {
@IsString() @IsString()
@UsernameFieldValidator() @UsernameFieldValidator()
@ApiProperty({ required: true }) @ApiProperty({ required: true })
@@ -19,7 +19,9 @@ export class CreateConsumerAccountDto {
role: ConsumerRole role: ConsumerRole
} }
export class UpdateAccountDto extends PartialType(CreateConsumerAccountDto) { export class UpdateAdminConsumerAccountDto extends PartialType(
CreateAdminConsumerAccountDto,
) {
@IsOptional() @IsOptional()
@IsEnum(AccountStatus) @IsEnum(AccountStatus)
@ApiProperty({ enum: AccountStatus }) @ApiProperty({ enum: AccountStatus })
@@ -1,7 +1,6 @@
import { SKUGuildType } from '@/common/enums/enums'
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger' import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
import { Type } from 'class-transformer' import { Type } from 'class-transformer'
import { IsBoolean, IsEnum, IsNumber, IsString, Min } from 'class-validator' import { IsBoolean, IsNumber, IsString, Min } from 'class-validator'
export class CreateStockKeepingUnitDto { export class CreateStockKeepingUnitDto {
@ApiProperty() @ApiProperty()
@@ -18,9 +17,9 @@ export class CreateStockKeepingUnitDto {
@Min(0) @Min(0)
VAT: number VAT: number
@ApiPropertyOptional({ enum: SKUGuildType, default: SKUGuildType.GOLD }) // @ApiPropertyOptional({ enum: SKUGuildType, default: SKUGuildType.GOLD })
@IsEnum(SKUGuildType) // @IsEnum(SKUGuildType)
type: SKUGuildType = SKUGuildType.GOLD // type: SKUGuildType = SKUGuildType.GOLD
@ApiPropertyOptional({ default: true }) @ApiPropertyOptional({ default: true })
@IsBoolean() @IsBoolean()
@@ -105,7 +105,9 @@ export class PartnerAccountChargeTransactionService {
try { try {
createdTransaction = await tx.partnerAccountQuotaChargeTransaction.create({ createdTransaction = await tx.partnerAccountQuotaChargeTransaction.create({
data: { data: {
activation_expires_at: data.activated_expires_at, activation_expires_at: data.activated_expires_at
? new Date(data.activated_expires_at).toISOString()
: new Date().toISOString(),
tracking_code: generateTrackingCode('AQC', this.TRACKING_CODE_LENGTH), tracking_code: generateTrackingCode('AQC', this.TRACKING_CODE_LENGTH),
purchased_count: data.quantity, purchased_count: data.quantity,
partner: { connect: { id: partner_id } }, partner: { connect: { id: partner_id } },
@@ -121,7 +121,9 @@ export class PartnerLicenseChargeTransactionService {
try { try {
createdTransaction = await tx.licenseChargeTransaction.create({ createdTransaction = await tx.licenseChargeTransaction.create({
data: { data: {
activation_expires_at: data.activated_expires_at, activation_expires_at: data.activated_expires_at
? new Date(data.activated_expires_at).toISOString()
: new Date().toISOString(),
tracking_code: generateTrackingCode('LIC', this.TRACKING_CODE_LENGTH), tracking_code: generateTrackingCode('LIC', this.TRACKING_CODE_LENGTH),
purchased_count: data.quantity, purchased_count: data.quantity,
partner: { connect: { id: partner_id } }, partner: { connect: { id: partner_id } },
@@ -1,14 +1,25 @@
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common' import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common'
import { AccountsService } from './accounts.service' import { AccountsService } from './accounts.service'
import { CreatePartnerAccountDto, UpdateAccountDto } from './dto/account.dto' import {
import type { AccountsServiceCreateResponseDto, AccountsServiceDeleteResponseDto, AccountsServiceFindAllResponseDto, AccountsServiceFindOneResponseDto, AccountsServiceUpdateResponseDto } from './dto/accounts-response.dto' CreateAdminPartnerAccountDto,
UpdateAdminPartnerAccountDto,
} from './dto/account.dto'
import type {
AccountsServiceCreateResponseDto,
AccountsServiceDeleteResponseDto,
AccountsServiceFindAllResponseDto,
AccountsServiceFindOneResponseDto,
AccountsServiceUpdateResponseDto,
} from './dto/accounts-response.dto'
@Controller('admin/partners/:partnerId/accounts') @Controller('admin/partners/:partnerId/accounts')
export class AccountsController { export class AccountsController {
constructor(private readonly accountsService: AccountsService) {} constructor(private readonly accountsService: AccountsService) {}
@Get() @Get()
async findAll(@Param('partnerId') partnerId: string): Promise<AccountsServiceFindAllResponseDto> { async findAll(
@Param('partnerId') partnerId: string,
): Promise<AccountsServiceFindAllResponseDto> {
return this.accountsService.findAll(partnerId) return this.accountsService.findAll(partnerId)
} }
@@ -20,13 +31,16 @@ export class AccountsController {
@Post() @Post()
async create( async create(
@Param('partnerId') partnerId: string, @Param('partnerId') partnerId: string,
@Body() data: CreatePartnerAccountDto, @Body() data: CreateAdminPartnerAccountDto,
): Promise<AccountsServiceCreateResponseDto> { ): Promise<AccountsServiceCreateResponseDto> {
return this.accountsService.create(partnerId, data) return this.accountsService.create(partnerId, data)
} }
@Patch(':id') @Patch(':id')
async update(@Param('id') id: string, @Body() data: UpdateAccountDto): Promise<AccountsServiceUpdateResponseDto> { async update(
@Param('id') id: string,
@Body() data: UpdateAdminPartnerAccountDto,
): Promise<AccountsServiceUpdateResponseDto> {
return this.accountsService.update(id, data) return this.accountsService.update(id, data)
} }
@@ -4,7 +4,10 @@ import { Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
import { PasswordUtil } from 'common/utils/password.util' import { PasswordUtil } from 'common/utils/password.util'
import { AccountStatus, AccountType, PartnerRole } from 'generated/prisma/enums' import { AccountStatus, AccountType, PartnerRole } from 'generated/prisma/enums'
import { CreatePartnerAccountDto, UpdateAccountDto } from './dto/account.dto' import {
CreateAdminPartnerAccountDto,
UpdateAdminPartnerAccountDto,
} from './dto/account.dto'
@Injectable() @Injectable()
export class AccountsService { export class AccountsService {
@@ -38,7 +41,7 @@ export class AccountsService {
return ResponseMapper.single(account) return ResponseMapper.single(account)
} }
async create(partnerId: string, data: CreatePartnerAccountDto) { async create(partnerId: string, data: CreateAdminPartnerAccountDto) {
const { username, password } = data const { username, password } = data
const result = await this.prisma.$transaction(async tx => { const result = await this.prisma.$transaction(async tx => {
@@ -69,7 +72,7 @@ export class AccountsService {
return ResponseMapper.create(result) return ResponseMapper.create(result)
} }
async update(id: string, data: UpdateAccountDto) { async update(id: string, data: UpdateAdminPartnerAccountDto) {
const account = await this.prisma.account.update({ where: { id }, data }) const account = await this.prisma.account.update({ where: { id }, data })
return ResponseMapper.update(account) return ResponseMapper.update(account)
} }
@@ -3,7 +3,7 @@ import { ApiProperty, PartialType } from '@nestjs/swagger'
import { IsEnum, IsOptional, IsString } from 'class-validator' import { IsEnum, IsOptional, IsString } from 'class-validator'
import { PartnerRole } from 'generated/prisma/enums' import { PartnerRole } from 'generated/prisma/enums'
export class CreatePartnerAccountDto { export class CreateAdminPartnerAccountDto {
@IsString() @IsString()
@ApiProperty({}) @ApiProperty({})
@UsernameFieldValidator() @UsernameFieldValidator()
@@ -15,7 +15,9 @@ export class CreatePartnerAccountDto {
password: string password: string
} }
export class UpdateAccountDto extends PartialType(CreatePartnerAccountDto) { export class UpdateAdminPartnerAccountDto extends PartialType(
CreateAdminPartnerAccountDto,
) {
@IsOptional() @IsOptional()
@IsEnum(PartnerRole) @IsEnum(PartnerRole)
@ApiProperty({ enum: PartnerRole }) @ApiProperty({ enum: PartnerRole })
@@ -1,8 +1,13 @@
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common' import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger' import { ApiTags } from '@nestjs/swagger'
import { AccountsService } from './accounts.service' import { AccountsService } from './accounts.service'
import { CreateAccountDto, UpdateAccountDto } from './dto/account.dto' import { CreateAdminAccountDto, UpdateAdminAccountDto } from './dto/account.dto'
import type { AccountsServiceCreateResponseDto, AccountsServiceFindAllResponseDto, AccountsServiceFindOneResponseDto, AccountsServiceUpdateResponseDto } from './dto/accounts-response.dto' import type {
AccountsServiceCreateResponseDto,
AccountsServiceFindAllResponseDto,
AccountsServiceFindOneResponseDto,
AccountsServiceUpdateResponseDto,
} from './dto/accounts-response.dto'
@ApiTags('accounts') @ApiTags('accounts')
@Controller('admin/users/:userId/accounts') @Controller('admin/users/:userId/accounts')
@@ -10,7 +15,9 @@ export class AccountsController {
constructor(private readonly accountsService: AccountsService) {} constructor(private readonly accountsService: AccountsService) {}
@Get() @Get()
async findAll(@Param('userId') userId: string): Promise<AccountsServiceFindAllResponseDto> { async findAll(
@Param('userId') userId: string,
): Promise<AccountsServiceFindAllResponseDto> {
return this.accountsService.findAll(userId) return this.accountsService.findAll(userId)
} }
@@ -20,12 +27,18 @@ export class AccountsController {
} }
@Post() @Post()
async create(@Param('userId') userId: string, @Body() data: CreateAccountDto): Promise<AccountsServiceCreateResponseDto> { async create(
@Param('userId') userId: string,
@Body() data: CreateAdminAccountDto,
): Promise<AccountsServiceCreateResponseDto> {
return this.accountsService.create(userId, data) return this.accountsService.create(userId, data)
} }
@Patch(':id') @Patch(':id')
async update(@Param('id') id: string, @Body() data: UpdateAccountDto): Promise<AccountsServiceUpdateResponseDto> { async update(
@Param('id') id: string,
@Body() data: UpdateAdminAccountDto,
): Promise<AccountsServiceUpdateResponseDto> {
return this.accountsService.update(id, data) return this.accountsService.update(id, data)
} }
@@ -1,7 +1,7 @@
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
import { CreateAccountDto, UpdateAccountDto } from './dto/account.dto' import { CreateAdminAccountDto, UpdateAdminAccountDto } from './dto/account.dto'
@Injectable() @Injectable()
export class AccountsService { export class AccountsService {
@@ -23,7 +23,7 @@ export class AccountsService {
return ResponseMapper.single({}) return ResponseMapper.single({})
} }
async create(userId: string, data: CreateAccountDto) { async create(userId: string, data: CreateAdminAccountDto) {
// const account = await this.prisma.account.create({ // const account = await this.prisma.account.create({
// data: { // data: {
// ...data, // ...data,
@@ -39,7 +39,7 @@ export class AccountsService {
return ResponseMapper.create({}) return ResponseMapper.create({})
} }
async update(id: string, data: UpdateAccountDto) { async update(id: string, data: UpdateAdminAccountDto) {
const account = await this.prisma.account.update({ where: { id }, data }) const account = await this.prisma.account.update({ where: { id }, data })
return ResponseMapper.update(account) return ResponseMapper.update(account)
} }
@@ -3,7 +3,7 @@ import { ApiProperty, PartialType } from '@nestjs/swagger'
import { IsEnum, IsOptional, IsString } from 'class-validator' import { IsEnum, IsOptional, IsString } from 'class-validator'
import { AccountStatus, AccountType } from 'generated/prisma/enums' import { AccountStatus, AccountType } from 'generated/prisma/enums'
export class CreateAccountDto { export class CreateAdminAccountDto {
@IsString() @IsString()
@UsernameFieldValidator() @UsernameFieldValidator()
@ApiProperty() @ApiProperty()
@@ -19,7 +19,7 @@ export class CreateAccountDto {
type: AccountType type: AccountType
} }
export class UpdateAccountDto extends PartialType(CreateAccountDto) { export class UpdateAdminAccountDto extends PartialType(CreateAdminAccountDto) {
@IsOptional() @IsOptional()
@IsEnum(AccountStatus) @IsEnum(AccountStatus)
@ApiProperty({ enum: AccountStatus }) @ApiProperty({ enum: AccountStatus })
@@ -2,8 +2,12 @@ import { TokenAccount } from '@/common/decorators/tokenInfo.decorator'
import { Body, Controller, Get, Param, Patch } from '@nestjs/common' import { Body, Controller, Get, Param, Patch } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger' import { ApiTags } from '@nestjs/swagger'
import { AccountsService } from './accounts.service' import { AccountsService } from './accounts.service'
import { UpdateAccountDto } from './dto/account.dto' import { UpdateConsumerAccountDto } from './dto/account.dto'
import type { AccountsServiceFindAllResponseDto, AccountsServiceFindOneResponseDto, AccountsServiceUpdateResponseDto } from './dto/accounts-response.dto' import type {
AccountsServiceFindAllResponseDto,
AccountsServiceFindOneResponseDto,
AccountsServiceUpdateResponseDto,
} from './dto/accounts-response.dto'
@ApiTags('ConsumerAccounts') @ApiTags('ConsumerAccounts')
@Controller('consumer/accounts') @Controller('consumer/accounts')
@@ -11,7 +15,9 @@ export class AccountsController {
constructor(private readonly accountsService: AccountsService) {} constructor(private readonly accountsService: AccountsService) {}
@Get() @Get()
async findAll(@TokenAccount('userId') consumerId: string): Promise<AccountsServiceFindAllResponseDto> { async findAll(
@TokenAccount('userId') consumerId: string,
): Promise<AccountsServiceFindAllResponseDto> {
return this.accountsService.findAll(consumerId) return this.accountsService.findAll(consumerId)
} }
@@ -29,7 +35,10 @@ export class AccountsController {
// } // }
@Patch(':id') @Patch(':id')
async update(@Param('id') id: string, @Body() data: UpdateAccountDto): Promise<AccountsServiceUpdateResponseDto> { async update(
@Param('id') id: string,
@Body() data: UpdateConsumerAccountDto,
): Promise<AccountsServiceUpdateResponseDto> {
return this.accountsService.update(id, data) return this.accountsService.update(id, data)
} }
@@ -2,7 +2,7 @@ import { ConsumerRole } from '@/generated/prisma/enums'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
import { UpdateAccountDto } from './dto/account.dto' import { UpdateConsumerAccountDto } from './dto/account.dto'
@Injectable() @Injectable()
export class AccountsService { export class AccountsService {
@@ -91,7 +91,7 @@ export class AccountsService {
// return ResponseMapper.create(account) // return ResponseMapper.create(account)
// } // }
async update(id: string, data: UpdateAccountDto) { async update(id: string, data: UpdateConsumerAccountDto) {
const account = await this.prisma.account.update({ where: { id }, data }) const account = await this.prisma.account.update({ where: { id }, data })
return ResponseMapper.update(account) return ResponseMapper.update(account)
} }
@@ -19,7 +19,7 @@ export class CreateConsumerAccountDto {
// role: ConsumerRole // role: ConsumerRole
} }
export class UpdateAccountDto extends PartialType(CreateConsumerAccountDto) { export class UpdateConsumerAccountDto extends PartialType(CreateConsumerAccountDto) {
@IsOptional() @IsOptional()
@IsEnum(AccountStatus) @IsEnum(AccountStatus)
@ApiProperty({ enum: AccountStatus }) @ApiProperty({ enum: AccountStatus })
@@ -71,7 +71,7 @@ export class BusinessActivitiesService {
async findOne(consumer_id: string, id: string) { async findOne(consumer_id: string, id: string) {
const cacheKey = RedisKeyMaker.consumerBusinessActivityInfo(consumer_id, id) const cacheKey = RedisKeyMaker.consumerBusinessActivityInfo(consumer_id, id)
return await this.redisService.getAndSet(cacheKey, 'list', async () => { return await this.redisService.getAndSet(cacheKey, 'single', async () => {
return await this.businessActivitiesQueryService.findOneByConsumer( return await this.businessActivitiesQueryService.findOneByConsumer(
consumer_id, consumer_id,
id, id,
@@ -1,4 +1,4 @@
import { Controller, Get, Param, Post } from '@nestjs/common' import { Controller, Get, Param, Post, Query } from '@nestjs/common'
import { TokenAccount } from '@/common/decorators/tokenInfo.decorator' import { TokenAccount } from '@/common/decorators/tokenInfo.decorator'
import { ApiTags } from '@nestjs/swagger' import { ApiTags } from '@nestjs/swagger'
@@ -14,8 +14,10 @@ export class SalesInvoicesController {
@TokenAccount('userId') userId: string, @TokenAccount('userId') userId: string,
@Param('complexId') complexId: string, @Param('complexId') complexId: string,
@Param('posId') posId: string, @Param('posId') posId: string,
@Query('page') page: number,
@Query('perPage') perPage: number,
) { ) {
return this.salesInvoicesService.findAll(userId, complexId, posId) return this.salesInvoicesService.findAll(userId, complexId, posId, page, perPage)
} }
@Get(':id') @Get(':id')
@@ -1,5 +1,6 @@
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service' import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service'
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { SharedSaleInvoicePaginationService } from '@/common/services/saleInvoices/sale-invoice-pagination.service'
import { SaleInvoiceTspModule } from '@/modules/tspProviders/sales-invoice-tsp.module' import { SaleInvoiceTspModule } from '@/modules/tspProviders/sales-invoice-tsp.module'
import { Module } from '@nestjs/common' import { Module } from '@nestjs/common'
import { SalesInvoicesController } from './sales-invoices.controller' import { SalesInvoicesController } from './sales-invoices.controller'
@@ -12,6 +13,7 @@ import { SalesInvoicesService } from './sales-invoices.service'
SalesInvoicesService, SalesInvoicesService,
SharedSaleInvoiceActionsService, SharedSaleInvoiceActionsService,
SharedSaleInvoiceAccessService, SharedSaleInvoiceAccessService,
SharedSaleInvoicePaginationService,
], ],
}) })
export class ConsumerPosSalesInvoicesModule {} export class ConsumerPosSalesInvoicesModule {}
@@ -1,5 +1,8 @@
import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { ResponseMapper } from '@/common/response/response-mapper' import { ResponseMapper } from '@/common/response/response-mapper'
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service' import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { SharedSaleInvoicePaginationService } from '@/common/services/saleInvoices/sale-invoice-pagination.service'
import { translateEnumValue } from '@/common/utils'
import { SalesInvoiceWhereInput } from '@/generated/prisma/models' import { SalesInvoiceWhereInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable, NotFoundException } from '@nestjs/common' import { Injectable, NotFoundException } from '@nestjs/common'
@@ -9,9 +12,19 @@ export class SalesInvoicesService {
constructor( constructor(
private prisma: PrismaService, private prisma: PrismaService,
private readonly sharedSaleInvoiceActionsService: SharedSaleInvoiceActionsService, private readonly sharedSaleInvoiceActionsService: SharedSaleInvoiceActionsService,
private readonly sharedSaleInvoicePaginationService: SharedSaleInvoicePaginationService,
) {} ) {}
async findAll(consumer_id: string, complex_id: string, pos_id: string) { async findAll(
consumer_id: string,
complex_id: string,
pos_id: string,
requestedPage: number = 1,
requestedPerPage: number = 10,
) {
const { page, perPage, skip, take } =
this.sharedSaleInvoicePaginationService.normalize(requestedPage, requestedPerPage)
const defaultWhere: SalesInvoiceWhereInput = { const defaultWhere: SalesInvoiceWhereInput = {
pos_id, pos_id,
pos: { pos: {
@@ -24,98 +37,41 @@ export class SalesInvoicesService {
}, },
} }
const perPage = 10 const [saleInvoices, total] = await this.prisma.$transaction([
const page = 1
const [items, total] = await this.prisma.$transaction([
this.prisma.salesInvoice.findMany({ this.prisma.salesInvoice.findMany({
where: defaultWhere, where: defaultWhere,
select: { select: {
id: true, ...QUERY_CONSTANTS.SALE_INVOICE.select,
code: true, _count: {
invoice_date: true,
notes: true,
total_amount: true,
items: {
select: { select: {
measure_unit_code: true, items: true,
measure_unit_text: true,
sku_code: true,
discount_amount: true,
tax_amount: true,
notes: true,
quantity: true,
total_amount: true,
unit_price: true,
payload: true,
good: {
select: {
id: true,
name: true,
sku: {
select: {
id: true,
name: true,
},
},
barcode: true,
local_sku: true,
pricing_model: true,
measure_unit: {
select: {
id: true,
name: true,
},
},
category: {
select: {
id: true,
name: true,
},
},
},
},
}, },
}, },
payments: {
select: {
amount: true,
paid_at: true,
payment_method: true,
},
},
customer: {
select: {
type: true,
individual: {
select: {
economic_code: true,
first_name: true,
last_name: true,
postal_code: true,
national_id: true,
},
},
legal: {
select: {
economic_code: true,
postal_code: true,
registration_number: true,
},
},
},
},
unknown_customer: true,
}, },
skip: (page - 1) * perPage, orderBy: {
take: perPage, created_at: 'desc',
},
skip,
take,
}), }),
this.prisma.salesInvoice.count({ this.prisma.salesInvoice.count({
where: defaultWhere, where: defaultWhere,
}), }),
]) ])
return ResponseMapper.paginate(items, { total, page, perPage }) const mappedAccounts = saleInvoices.map(saleInvoice => {
const { _count, consumer_account, last_tsp_status, ...rest } = saleInvoice
return {
...rest,
items_count: _count.items,
status: translateEnumValue('TspProviderResponseStatus', last_tsp_status),
}
})
return ResponseMapper.paginate(mappedAccounts, {
total,
page,
perPage,
})
} }
findOne(complex_id: string, pos_id: string, id: string) { findOne(complex_id: string, pos_id: string, id: string) {
+24 -1
View File
@@ -1,5 +1,7 @@
import { RedisKeyMaker } from '@/common/utils'
import { checkAndDecodeJwtToken } from '@/common/utils/jwt-user.util' import { checkAndDecodeJwtToken } from '@/common/utils/jwt-user.util'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { RedisService } from '@/redis/redis.service'
import { import {
ForbiddenException, ForbiddenException,
Injectable, Injectable,
@@ -14,6 +16,7 @@ export class ConsumerMiddleware implements NestMiddleware {
constructor( constructor(
private prisma: PrismaService, private prisma: PrismaService,
private jwtService: JwtService, private jwtService: JwtService,
private redisService: RedisService,
) {} ) {}
async use(req: Request, _res: Response, next: NextFunction) { async use(req: Request, _res: Response, next: NextFunction) {
@@ -21,7 +24,15 @@ export class ConsumerMiddleware implements NestMiddleware {
throw new ForbiddenException('شما دسترسی لازم را ندارید') throw new ForbiddenException('شما دسترسی لازم را ندارید')
} }
try { try {
const token = req.cookies?.accessToken
const cacheKey = RedisKeyMaker.consumerMiddleware(token)
let cachedConsumerData: unknown
try {
cachedConsumerData = await this.redisService.getJson(cacheKey)
} catch (_) {}
const tokenAccount = checkAndDecodeJwtToken(req, this.jwtService) const tokenAccount = checkAndDecodeJwtToken(req, this.jwtService)
req.decodedToken = tokenAccount!
if ( if (
tokenAccount?.type !== 'CONSUMER' || tokenAccount?.type !== 'CONSUMER' ||
@@ -30,6 +41,16 @@ export class ConsumerMiddleware implements NestMiddleware {
throw new UnauthorizedException() throw new UnauthorizedException()
} }
if (
cachedConsumerData &&
typeof cachedConsumerData === 'object' &&
'account_id' in cachedConsumerData &&
'id' in cachedConsumerData
) {
req.consumerData = cachedConsumerData as any
return next()
}
const consumerAccount = await this.prisma.consumerAccount.findUnique({ const consumerAccount = await this.prisma.consumerAccount.findUnique({
where: { where: {
id: tokenAccount.account_id, id: tokenAccount.account_id,
@@ -49,7 +70,9 @@ export class ConsumerMiddleware implements NestMiddleware {
id: consumerAccount.consumer_id, id: consumerAccount.consumer_id,
} }
req.decodedToken = tokenAccount try {
await this.redisService.setJson(cacheKey, req.consumerData, 60 * 60)
} catch (_) {}
return next() return next()
} catch (error) { } catch (error) {
@@ -1,3 +1,4 @@
import { SharedSaleInvoicePaginationService } from '@/common/services/saleInvoices/sale-invoice-pagination.service'
import { PrismaModule } from '@/prisma/prisma.module' import { PrismaModule } from '@/prisma/prisma.module'
import { Module } from '@nestjs/common' import { Module } from '@nestjs/common'
import { consumerCustomersController } from './customers.controller' import { consumerCustomersController } from './customers.controller'
@@ -7,6 +8,6 @@ import { ConsumerSaleInvoicesModule } from './sale-invoices/sale-invoices.module
@Module({ @Module({
imports: [PrismaModule, ConsumerSaleInvoicesModule], imports: [PrismaModule, ConsumerSaleInvoicesModule],
controllers: [consumerCustomersController], controllers: [consumerCustomersController],
providers: [consumerCustomersService], providers: [consumerCustomersService, SharedSaleInvoicePaginationService],
}) })
export class ConsumerCustomersModule {} export class ConsumerCustomersModule {}
@@ -1,3 +1,4 @@
import { SharedSaleInvoicePaginationService } from '@/common/services/saleInvoices/sale-invoice-pagination.service'
import { CustomerSelect, CustomerWhereInput } from '@/generated/prisma/models' import { CustomerSelect, CustomerWhereInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
@@ -9,7 +10,10 @@ import {
@Injectable() @Injectable()
export class consumerCustomersService { export class consumerCustomersService {
constructor(private readonly prisma: PrismaService) {} constructor(
private readonly prisma: PrismaService,
private readonly sharedSaleInvoicePaginationService: SharedSaleInvoicePaginationService,
) {}
defaultSelect: CustomerSelect = { defaultSelect: CustomerSelect = {
id: true, id: true,
@@ -56,13 +60,15 @@ export class consumerCustomersService {
} }
} }
async findAll(consumer_id: string, page = 1, perPage = 10) { async findAll(consumer_id: string, requestedPage = 1, requestedPerPage = 10) {
const { page, perPage, skip, take } =
this.sharedSaleInvoicePaginationService.normalize(requestedPage, requestedPerPage)
const [customers, total] = await this.prisma.$transaction(async tx => [ const [customers, total] = await this.prisma.$transaction(async tx => [
await tx.customer.findMany({ await tx.customer.findMany({
where: this.defaultWhere(consumer_id), where: this.defaultWhere(consumer_id),
select: this.defaultSelect, select: this.defaultSelect,
skip: (page - 1) * perPage, skip,
take: 10, take,
}), }),
await tx.customer.count({ await tx.customer.count({
where: this.defaultWhere(consumer_id), where: this.defaultWhere(consumer_id),
@@ -1,3 +1,4 @@
import { SharedSaleInvoicePaginationService } from '@/common/services/saleInvoices/sale-invoice-pagination.service'
import { PrismaModule } from '@/prisma/prisma.module' import { PrismaModule } from '@/prisma/prisma.module'
import { Module } from '@nestjs/common' import { Module } from '@nestjs/common'
import { CustomerSaleInvoicesController } from './sale-invoices.controller' import { CustomerSaleInvoicesController } from './sale-invoices.controller'
@@ -6,6 +7,6 @@ import { CustomerSaleInvoicesService } from './sale-invoices.service'
@Module({ @Module({
imports: [PrismaModule], imports: [PrismaModule],
controllers: [CustomerSaleInvoicesController], controllers: [CustomerSaleInvoicesController],
providers: [CustomerSaleInvoicesService], providers: [CustomerSaleInvoicesService, SharedSaleInvoicePaginationService],
}) })
export class ConsumerSaleInvoicesModule {} export class ConsumerSaleInvoicesModule {}
@@ -1,57 +1,28 @@
import { QUERY_CONSTANTS } from '@/common/queryConstants' import { QUERY_CONSTANTS } from '@/common/queryConstants'
import consumer_mappersUtil from '@/common/utils/mappers/consumer_mappers.util' import { SharedSaleInvoicePaginationService } from '@/common/services/saleInvoices/sale-invoice-pagination.service'
import { SalesInvoiceSelect, SalesInvoiceWhereInput } from '@/generated/prisma/models' import { translateEnumValue } from '@/common/utils'
import { TspProviderResponseStatus } from '@/generated/prisma/enums'
import { SalesInvoiceWhereInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable, NotFoundException } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
@Injectable() @Injectable()
export class CustomerSaleInvoicesService { export class CustomerSaleInvoicesService {
constructor(private readonly prisma: PrismaService) {} constructor(
private readonly prisma: PrismaService,
private readonly sharedSaleInvoicePaginationService: SharedSaleInvoicePaginationService,
) {}
private readonly defaultSelect: SalesInvoiceSelect = { async findAll(
id: true, consumer_id: string,
code: true, customer_id: string,
invoice_date: true, requestedPage = 1,
notes: true, requestedPerPage = 10,
total_amount: true, ) {
pos: { const { page, perPage, skip, take } =
select: { this.sharedSaleInvoicePaginationService.normalize(requestedPage, requestedPerPage)
id: true,
name: true,
complex: {
select: {
id: true,
name: true,
business_activity: {
select: {
id: true,
name: true,
},
},
},
},
},
},
consumer_account: {
select: {
role: true,
consumer: {
select: {
...QUERY_CONSTANTS.CONSUMER.infoSelect,
},
},
account: {
select: {
username: true,
},
},
},
},
created_at: true,
}
async findAll(consumer_id: string, customer_id: string, page = 1, perPage = 10) {
const salesWhere: SalesInvoiceWhereInput = { const salesWhere: SalesInvoiceWhereInput = {
customer_id, customer_id,
pos: { pos: {
@@ -67,15 +38,30 @@ export class CustomerSaleInvoicesService {
await tx.salesInvoice.findMany({ await tx.salesInvoice.findMany({
where: salesWhere, where: salesWhere,
select: { select: {
...this.defaultSelect, ...QUERY_CONSTANTS.SALE_INVOICE.summarySelect,
pos: {
select: {
name: true,
complex: {
select: {
name: true,
business_activity: {
select: {
name: true,
},
},
},
},
},
},
_count: { _count: {
select: { select: {
items: true, items: true,
}, },
}, },
}, },
skip: (page - 1) * perPage, skip,
take: 10, take,
}), }),
await tx.salesInvoice.count({ await tx.salesInvoice.count({
where: salesWhere, where: salesWhere,
@@ -83,16 +69,11 @@ export class CustomerSaleInvoicesService {
]) ])
const mappedAccounts = saleInvoices.map(saleInvoice => { const mappedAccounts = saleInvoices.map(saleInvoice => {
const { _count, consumer_account, ...rest } = saleInvoice const { _count, consumer_account, last_tsp_status, ...rest } = saleInvoice
const { consumer, ...restConsumerAccount } = consumer_account as any
const mappedConsumer = consumer_mappersUtil(consumer)
return { return {
...rest, ...rest,
items_count: _count.items, items_count: _count.items,
consumer_account: { status: translateEnumValue('TspProviderResponseStatus', last_tsp_status),
...restConsumerAccount,
consumer: mappedConsumer,
},
} }
}) })
@@ -104,7 +85,7 @@ export class CustomerSaleInvoicesService {
} }
async findOne(consumer_id: string, customer_id: string, id: string) { async findOne(consumer_id: string, customer_id: string, id: string) {
const saleInvoice = await this.prisma.salesInvoice.findUniqueOrThrow({ const invoice = await this.prisma.salesInvoice.findUnique({
where: { where: {
id, id,
customer_id, customer_id,
@@ -117,59 +98,26 @@ export class CustomerSaleInvoicesService {
}, },
}, },
select: { select: {
...this.defaultSelect, ...QUERY_CONSTANTS.SALE_INVOICE.select,
items: {
select: {
id: true,
notes: true,
unit_price: true,
quantity: true,
discount_amount: true,
tax_amount: true,
total_amount: true,
payload: true,
good: {
select: {
id: true,
name: true,
pricing_model: true,
measure_unit: {
select: {
id: true,
name: true,
},
},
category: {
select: {
id: true,
name: true,
image_url: true,
},
},
},
},
},
},
payments: {
select: {
amount: true,
paid_at: true,
payment_method: true,
},
},
}, },
}) })
const { _count, consumer_account, ...rest } = saleInvoice
const { consumer, ...restConsumerAccount } = consumer_account as any
const mappedConsumer = consumer_mappersUtil(consumer)
return ResponseMapper.single({ if (invoice) {
...rest, const { type, ...rest } = invoice
items_count: _count.items, const mappedInvoice = {
consumer_account: { ...rest,
...restConsumerAccount, type: translateEnumValue('TspProviderRequestType', type),
consumer: mappedConsumer, status: translateEnumValue(
}, 'TspProviderResponseStatus',
}) invoice.last_tsp_status || TspProviderResponseStatus.NOT_SEND,
),
settlement_type: translateEnumValue(
'InvoiceSettlementType',
invoice.settlement_type,
),
}
return ResponseMapper.single(mappedInvoice)
}
throw new NotFoundException('صورت‌حساب مورد نظر شما یافت نشد.')
} }
} }
+2 -1
View File
@@ -2,6 +2,7 @@ import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
import { UpdateBusinessActivityDto } from './dto/poses.dto'
@Injectable() @Injectable()
export class PosesService { export class PosesService {
@@ -43,7 +44,7 @@ export class PosesService {
}) })
} }
async update(consumer_id: string, id: string, data: any) { async update(consumer_id: string, id: string, data: UpdateBusinessActivityDto) {
const pos = await this.prisma.pos.update({ const pos = await this.prisma.pos.update({
where: { ...this.defaultWhere(consumer_id), id }, where: { ...this.defaultWhere(consumer_id), id },
data, data,
@@ -1,95 +1,12 @@
import { SharedSaleInvoicesFilterDto } from '@/common/services/saleInvoices/sale-invoice-filter.dto'
import { ApiPropertyOptional } from '@nestjs/swagger' import { ApiPropertyOptional } from '@nestjs/swagger'
import { Type } from 'class-transformer' import { Max } from 'class-validator'
import {
IsDateString,
IsEnum,
IsNumber,
IsOptional,
IsString,
Max,
Min,
} from 'class-validator'
import { TspProviderResponseStatus } from 'generated/prisma/enums'
export class ConsumerSaleInvoicesFilterDto {
@ApiPropertyOptional({ type: Number, example: 1 })
@Type(() => Number)
@Min(1)
@IsOptional()
page?: number
export class ConsumerSaleInvoicesFilterDto extends SharedSaleInvoicesFilterDto {
@ApiPropertyOptional({ type: Number, example: 10, description: 'Max value is 50.' }) @ApiPropertyOptional({ type: Number, example: 10, description: 'Max value is 50.' })
@Type(() => Number)
@Min(1)
@Max(50) @Max(50)
@IsOptional() declare perPage?: number
perPage?: number
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional()
@IsDateString()
invoice_date_from?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
invoice_date_to?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
created_at_from?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
created_at_to?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
code?: string code?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_name?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_mobile?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_national_id?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_economic_code?: string
@ApiPropertyOptional({ enum: TspProviderResponseStatus })
@IsOptional()
@IsEnum(TspProviderResponseStatus)
status?: TspProviderResponseStatus
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount?: number
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount_from?: number
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount_to?: number
} }
@@ -4,6 +4,7 @@ import type { IPosPayload } from '@/common/models'
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common' import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger' import { ApiTags } from '@nestjs/swagger'
import { ConsumerSaleInvoicesFilterDto } from './dto/saleInvoices-filter.dto' import { ConsumerSaleInvoicesFilterDto } from './dto/saleInvoices-filter.dto'
import { PosCorrectionSalesInvoiceDto } from '../../pos/sales-invoices/dto/create-sales-invoice.dto'
import type { import type {
SaleInvoicesServiceFindAllResponseDto, SaleInvoicesServiceFindAllResponseDto,
SaleInvoicesServiceFindOneResponseDto, SaleInvoicesServiceFindOneResponseDto,
@@ -59,4 +60,18 @@ export class StatisticsController {
revoke(@Param('id') id: string, @PosInfo() posInfo: IPosPayload) { revoke(@Param('id') id: string, @PosInfo() posInfo: IPosPayload) {
return this.service.revoke(id, posInfo) return this.service.revoke(id, posInfo)
} }
@Post(':id/correction')
correction(
@Param('id') id: string,
@PosInfo() posInfo: IPosPayload,
@Body() data: PosCorrectionSalesInvoiceDto,
) {
return this.service.correction(id, posInfo, data)
}
@Post(':id/return')
return(@Param('id') id: string, @PosInfo() posInfo: IPosPayload) {
return this.service.return(id, posInfo)
}
} }
@@ -1,5 +1,7 @@
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service' import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service' import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service'
import { SharedSaleInvoiceFilterService } from '@/common/services/saleInvoices/sale-invoice-filter.service'
import { SharedSaleInvoicePaginationService } from '@/common/services/saleInvoices/sale-invoice-pagination.service'
import { SaleInvoiceTspModule } from '@/modules/tspProviders/sales-invoice-tsp.module' import { SaleInvoiceTspModule } from '@/modules/tspProviders/sales-invoice-tsp.module'
import { PrismaModule } from '@/prisma/prisma.module' import { PrismaModule } from '@/prisma/prisma.module'
import { Module } from '@nestjs/common' import { Module } from '@nestjs/common'
@@ -9,7 +11,13 @@ import { SaleInvoicesService } from './saleInvoices.service'
@Module({ @Module({
imports: [PrismaModule, SaleInvoiceTspModule], imports: [PrismaModule, SaleInvoiceTspModule],
controllers: [StatisticsController], controllers: [StatisticsController],
providers: [SaleInvoicesService, SharedSaleInvoiceActionsService, SharedSaleInvoiceAccessService], providers: [
SaleInvoicesService,
SharedSaleInvoiceActionsService,
SharedSaleInvoiceAccessService,
SharedSaleInvoiceFilterService,
SharedSaleInvoicePaginationService,
],
exports: [SaleInvoicesService], exports: [SaleInvoicesService],
}) })
export class ConsumerSaleInvoicesModule {} export class ConsumerSaleInvoicesModule {}
@@ -1,6 +1,8 @@
import { IPosPayload } from '@/common/models' import { IPosPayload } from '@/common/models'
import { QUERY_CONSTANTS } from '@/common/queryConstants' import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service' import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { SharedSaleInvoiceFilterService } from '@/common/services/saleInvoices/sale-invoice-filter.service'
import { SharedSaleInvoicePaginationService } from '@/common/services/saleInvoices/sale-invoice-pagination.service'
import { translateEnumValue } from '@/common/utils' import { translateEnumValue } from '@/common/utils'
import { TspProviderResponseStatus } from '@/generated/prisma/enums' import { TspProviderResponseStatus } from '@/generated/prisma/enums'
import { import {
@@ -11,6 +13,7 @@ import {
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common' import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
import { PosCorrectionSalesInvoiceDto } from '../../pos/sales-invoices/dto/create-sales-invoice.dto'
import { SalesInvoiceTspService } from '../../tspProviders/sales-invoice-tsp.service' import { SalesInvoiceTspService } from '../../tspProviders/sales-invoice-tsp.service'
import { ConsumerSaleInvoicesFilterDto } from './dto/saleInvoices-filter.dto' import { ConsumerSaleInvoicesFilterDto } from './dto/saleInvoices-filter.dto'
@@ -20,11 +23,10 @@ export class SaleInvoicesService {
private readonly prisma: PrismaService, private readonly prisma: PrismaService,
private salesInvoiceTaxService: SalesInvoiceTspService, private salesInvoiceTaxService: SalesInvoiceTspService,
private sharedSaleInvoiceActionsService: SharedSaleInvoiceActionsService, private sharedSaleInvoiceActionsService: SharedSaleInvoiceActionsService,
private sharedSaleInvoiceFilterService: SharedSaleInvoiceFilterService,
private sharedSaleInvoicePaginationService: SharedSaleInvoicePaginationService,
) {} ) {}
private readonly defaultPerPage = 10
private readonly maxPerPage = 50
private readonly defaultSelect: SalesInvoiceSelect = { private readonly defaultSelect: SalesInvoiceSelect = {
pos: { pos: {
select: { select: {
@@ -47,29 +49,21 @@ export class SaleInvoicesService {
} }
private readonly invoiceMapper = (invoice: any) => { private readonly invoiceMapper = (invoice: any) => {
const { tsp_attempts, ...rest } = invoice || {} const { last_tsp_status, ...rest } = invoice || {}
return { return {
...rest, ...rest,
status: translateEnumValue( status: translateEnumValue(
'TspProviderResponseStatus', 'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND, last_tsp_status || TspProviderResponseStatus.NOT_SEND,
), ),
} }
} }
async findAll(consumer_id: string, filter: ConsumerSaleInvoicesFilterDto) { async findAll(consumer_id: string, filter: ConsumerSaleInvoicesFilterDto) {
const invoicesWhere = this.buildFindAllWhere(consumer_id, filter) const invoicesWhere = this.buildFindAllWhere(consumer_id, filter)
const normalizedPageValue = Number(filter.page ?? 1) const { page, perPage, skip, take } =
const normalizedPage = Number.isFinite(normalizedPageValue) this.sharedSaleInvoicePaginationService.normalize(filter.page, filter.perPage)
? Math.max(1, Math.floor(normalizedPageValue))
: 1
const requestedPerPageValue = Number(filter.perPage ?? this.defaultPerPage)
const requestedPerPage = Number.isFinite(requestedPerPageValue)
? Math.max(1, Math.floor(requestedPerPageValue))
: this.defaultPerPage
const normalizedPerPage = Math.min(requestedPerPage, this.maxPerPage)
const [invoices, total] = await this.prisma.$transaction(async tx => [ const [invoices, total] = await this.prisma.$transaction(async tx => [
await tx.salesInvoice.findMany({ await tx.salesInvoice.findMany({
@@ -77,8 +71,8 @@ export class SaleInvoicesService {
orderBy: { orderBy: {
created_at: 'desc', created_at: 'desc',
}, },
skip: (normalizedPage - 1) * normalizedPerPage, skip,
take: normalizedPerPage, take,
select: { select: {
...QUERY_CONSTANTS.SALE_INVOICE.summarySelect, ...QUERY_CONSTANTS.SALE_INVOICE.summarySelect,
...this.defaultSelect, ...this.defaultSelect,
@@ -89,8 +83,8 @@ export class SaleInvoicesService {
const mappedInvoices = invoices.map(this.invoiceMapper) const mappedInvoices = invoices.map(this.invoiceMapper)
return ResponseMapper.paginate(mappedInvoices, { return ResponseMapper.paginate(mappedInvoices, {
page: normalizedPage, page,
perPage: normalizedPerPage, perPage,
total, total,
}) })
} }
@@ -100,9 +94,11 @@ export class SaleInvoicesService {
filter: ConsumerSaleInvoicesFilterDto, filter: ConsumerSaleInvoicesFilterDto,
): SalesInvoiceWhereInput { ): SalesInvoiceWhereInput {
const where: SalesInvoiceWhereInput = { const where: SalesInvoiceWhereInput = {
...this.sharedSaleInvoiceFilterService.buildWhere(filter),
consumer_account: { consumer_account: {
consumer_id, consumer_id,
}, },
referenced_by: null,
} }
if (filter.code?.trim()) { if (filter.code?.trim()) {
@@ -111,127 +107,6 @@ export class SaleInvoicesService {
} }
} }
if (filter.invoice_date_from || filter.invoice_date_to) {
where.invoice_date = {
...(filter.invoice_date_from ? { gte: new Date(filter.invoice_date_from) } : {}),
...(filter.invoice_date_to ? { lte: new Date(filter.invoice_date_to) } : {}),
}
}
if (filter.created_at_from || filter.created_at_to) {
where.created_at = {
...(filter.created_at_from ? { gte: new Date(filter.created_at_from) } : {}),
...(filter.created_at_to ? { lte: new Date(filter.created_at_to) } : {}),
}
}
if (
filter.total_amount !== undefined ||
filter.total_amount_from !== undefined ||
filter.total_amount_to !== undefined
) {
where.total_amount = {
...(filter.total_amount !== undefined ? { equals: filter.total_amount } : {}),
...(filter.total_amount_from !== undefined
? { gte: filter.total_amount_from }
: {}),
...(filter.total_amount_to !== undefined ? { lte: filter.total_amount_to } : {}),
}
}
if (
filter.customer_name?.trim() ||
filter.customer_mobile?.trim() ||
filter.customer_national_id?.trim() ||
filter.customer_economic_code?.trim()
) {
where.customer = {
is: {
OR: [
...(filter.customer_name?.trim()
? [
{
individual: {
is: {
OR: [
{ first_name: { contains: filter.customer_name.trim() } },
{ last_name: { contains: filter.customer_name.trim() } },
],
},
},
},
{
legal: {
is: {
name: {
contains: filter.customer_name.trim(),
},
},
},
},
]
: []),
...(filter.customer_mobile?.trim()
? [
{
individual: {
is: {
mobile_number: { contains: filter.customer_mobile.trim() },
},
},
},
]
: []),
...(filter.customer_national_id?.trim()
? [
{
individual: {
is: {
national_id: { contains: filter.customer_national_id.trim() },
},
},
},
]
: []),
...(filter.customer_economic_code?.trim()
? [
{
legal: {
is: {
OR: [
{
economic_code: {
contains: filter.customer_economic_code.trim(),
},
},
{
registration_number: {
contains: filter.customer_economic_code.trim(),
},
},
],
},
},
},
]
: []),
],
},
}
}
if (filter.status) {
if (filter.status === TspProviderResponseStatus.NOT_SEND) {
where.tsp_attempts = undefined
} else {
where.tsp_attempts = {
some: {
status: filter.status,
},
}
}
}
return where return where
} }
@@ -242,7 +117,7 @@ export class SaleInvoicesService {
consumer_id, consumer_id,
}, },
} }
const invoice = await this.prisma.salesInvoice.findUniqueOrThrow({ const invoice = await this.prisma.salesInvoice.findUnique({
where: invoicesWhere, where: invoicesWhere,
select: { select: {
...QUERY_CONSTANTS.SALE_INVOICE.select, ...QUERY_CONSTANTS.SALE_INVOICE.select,
@@ -251,9 +126,22 @@ export class SaleInvoicesService {
}) })
if (invoice) { if (invoice) {
return ResponseMapper.single(this.invoiceMapper(invoice)) const { type, ...rest } = invoice
const mappedInvoice = {
...rest,
type: translateEnumValue('TspProviderRequestType', type),
status: translateEnumValue(
'TspProviderResponseStatus',
invoice.last_tsp_status || TspProviderResponseStatus.NOT_SEND,
),
settlement_type: translateEnumValue(
'InvoiceSettlementType',
invoice.settlement_type,
),
}
return ResponseMapper.single(mappedInvoice)
} }
throw new NotFoundException('فاکتور مورد نظر شما یافت نشد.') throw new NotFoundException('صورت‌حساب مورد نظر شما یافت نشد.')
} }
async send(invoiceId: string, posInfo: IPosPayload) { async send(invoiceId: string, posInfo: IPosPayload) {
@@ -290,6 +178,39 @@ export class SaleInvoicesService {
return ResponseMapper.single(invoice) return ResponseMapper.single(invoice)
} }
async correction(
invoiceId: string,
posInfo: IPosPayload,
data: PosCorrectionSalesInvoiceDto,
) {
const { consumer_account_id, pos_id, business_id, complex_id } = posInfo
const invoice = await this.sharedSaleInvoiceActionsService.correction(
data,
consumer_account_id,
pos_id,
complex_id,
business_id,
invoiceId,
)
return ResponseMapper.single(invoice)
}
async return(invoiceId: string, posInfo: IPosPayload) {
const { consumer_account_id, pos_id, business_id, complex_id } = posInfo
const invoice = await this.sharedSaleInvoiceActionsService.revoke(
consumer_account_id,
pos_id,
complex_id,
business_id,
invoiceId,
)
return ResponseMapper.single(invoice)
}
async inquiry(consumer_account_id: string, pos_id: string, invoiceId: string) { async inquiry(consumer_account_id: string, pos_id: string, invoiceId: string) {
const invoice = await this.sharedSaleInvoiceActionsService.inquiry( const invoice = await this.sharedSaleInvoiceActionsService.inquiry(
consumer_account_id, consumer_account_id,
@@ -301,7 +222,7 @@ export class SaleInvoicesService {
async sendBulk(consumer_id: string, invoiceIds: string[]) { async sendBulk(consumer_id: string, invoiceIds: string[]) {
if (!invoiceIds.length) { if (!invoiceIds.length) {
throw new BadRequestException('لیست شناسه فاکتورها نمی‌تواند خالی باشد.') throw new BadRequestException('لیست شناسه ‌صورت‌حساب‌ها نمی‌تواند خالی باشد.')
} }
await this.salesInvoiceTaxService.sendBulk(consumer_id, invoiceIds) await this.salesInvoiceTaxService.sendBulk(consumer_id, invoiceIds)
@@ -10,13 +10,13 @@ export class StatisticsService {
constructor(private readonly prisma: PrismaService) {} constructor(private readonly prisma: PrismaService) {}
private readonly invoiceMapper = (invoice: any) => { private readonly invoiceMapper = (invoice: any) => {
const { tsp_attempts, ...rest } = invoice || {} const { last_tsp_status, ...rest } = invoice || {}
return { return {
...rest, ...rest,
status: translateEnumValue( status: translateEnumValue(
'TspProviderResponseStatus', 'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND, last_tsp_status || TspProviderResponseStatus.NOT_SEND,
), ),
} }
} }
+2 -2
View File
@@ -25,7 +25,7 @@ import {
TspProviderType, TspProviderType,
} from '@/generated/prisma/enums' } from '@/generated/prisma/enums'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { GoldKarat, SKUGuildType, TspProviderCustomerType } from 'common/enums/enums' import { GoldKarat, TspProviderCustomerType } from 'common/enums/enums'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
@Injectable() @Injectable()
@@ -80,7 +80,7 @@ export class EnumsService {
TspProviderCustomerType, TspProviderCustomerType,
'TspProviderCustomerType', 'TspProviderCustomerType',
), ),
SKUGuildType: this.prepareData(SKUGuildType, 'SKUGuildType'), // SKUGuildType: this.prepareData(SKUGuildType, 'SKUGuildType'),
InvoiceTemplateType: this.prepareData(InvoiceTemplateType, 'InvoiceTemplateType'), InvoiceTemplateType: this.prepareData(InvoiceTemplateType, 'InvoiceTemplateType'),
} }
} }
+3 -2
View File
@@ -21,6 +21,7 @@ export class InvoicesService {
tax_id: true, tax_id: true,
total_amount: true, total_amount: true,
type: true, type: true,
settlement_type: true,
pos: { pos: {
select: { select: {
name: true, name: true,
@@ -114,14 +115,14 @@ export class InvoicesService {
private readonly where = () => ({}) private readonly where = () => ({})
private readonly invoiceMapper = (invoice: any) => { private readonly invoiceMapper = (invoice: any) => {
const { tsp_attempts, type, ...rest } = invoice || {} const { last_tsp_status, type, ...rest } = invoice || {}
return { return {
...rest, ...rest,
type: translateEnumValue('TspProviderRequestType', type), type: translateEnumValue('TspProviderRequestType', type),
status: translateEnumValue( status: translateEnumValue(
'TspProviderResponseStatus', 'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND, last_tsp_status || TspProviderResponseStatus.NOT_SEND,
), ),
} }
} }
@@ -2,8 +2,12 @@ import { TokenAccount } from '@/common/decorators/tokenInfo.decorator'
import { Body, Controller, Get, Param, Patch } from '@nestjs/common' import { Body, Controller, Get, Param, Patch } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger' import { ApiTags } from '@nestjs/swagger'
import { AccountsService } from './accounts.service' import { AccountsService } from './accounts.service'
import { UpdateAccountDto } from './dto/account.dto' import { UpdatePartnerAccountDto } from './dto/account.dto'
import type { AccountsServiceFindAllResponseDto, AccountsServiceFindOneResponseDto, AccountsServiceUpdateResponseDto } from './dto/accounts-response.dto' import type {
AccountsServiceFindAllResponseDto,
AccountsServiceFindOneResponseDto,
AccountsServiceUpdateResponseDto,
} from './dto/accounts-response.dto'
@ApiTags('PartnerAccounts') @ApiTags('PartnerAccounts')
@Controller('partner/accounts') @Controller('partner/accounts')
@@ -11,7 +15,9 @@ export class AccountsController {
constructor(private readonly service: AccountsService) {} constructor(private readonly service: AccountsService) {}
@Get() @Get()
async findAll(@TokenAccount('userId') consumerId: string): Promise<AccountsServiceFindAllResponseDto> { async findAll(
@TokenAccount('userId') consumerId: string,
): Promise<AccountsServiceFindAllResponseDto> {
return this.service.findAll(consumerId) return this.service.findAll(consumerId)
} }
@@ -29,7 +35,10 @@ export class AccountsController {
// } // }
@Patch(':id') @Patch(':id')
async update(@Param('id') id: string, @Body() data: UpdateAccountDto): Promise<AccountsServiceUpdateResponseDto> { async update(
@Param('id') id: string,
@Body() data: UpdatePartnerAccountDto,
): Promise<AccountsServiceUpdateResponseDto> {
return this.service.update(id, data) return this.service.update(id, data)
} }
@@ -3,7 +3,7 @@ import { AccountStatus, AccountType } from '@/generated/prisma/enums'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
import { CreatePartnerAccountDto, UpdateAccountDto } from './dto/account.dto' import { CreatePartnerAccountDto, UpdatePartnerAccountDto } from './dto/account.dto'
@Injectable() @Injectable()
export class AccountsService { export class AccountsService {
@@ -73,7 +73,7 @@ export class AccountsService {
return ResponseMapper.create(account) return ResponseMapper.create(account)
} }
async update(id: string, data: UpdateAccountDto) { async update(id: string, data: UpdatePartnerAccountDto) {
const account = await this.prisma.account.update({ where: { id }, data }) const account = await this.prisma.account.update({ where: { id }, data })
return ResponseMapper.update(account) return ResponseMapper.update(account)
} }
@@ -16,7 +16,7 @@ export class CreatePartnerAccountDto {
role: PartnerRole role: PartnerRole
} }
export class UpdateAccountDto extends PartialType(CreatePartnerAccountDto) { export class UpdatePartnerAccountDto extends PartialType(CreatePartnerAccountDto) {
@IsOptional() @IsOptional()
@IsEnum(AccountStatus) @IsEnum(AccountStatus)
@ApiProperty({ enum: AccountStatus }) @ApiProperty({ enum: AccountStatus })
@@ -1,10 +1,14 @@
import { RedisKeyMaker } from '@/common/utils' import { RedisKeyMaker } from '@/common/utils'
import { PosCacheInvalidationService } from '@/modules/pos/cache/pos-cache-invalidation.service'
import { RedisService } from '@/redis/redis.service' import { RedisService } from '@/redis/redis.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
@Injectable() @Injectable()
export class PartnersCacheInvalidationService { export class PartnersCacheInvalidationService {
constructor(private readonly redisService: RedisService) {} constructor(
private readonly redisService: RedisService,
private readonly PosCacheInvalidationService: PosCacheInvalidationService,
) {}
async invalidatePartnerSummary(partnerId: string): Promise<void> { async invalidatePartnerSummary(partnerId: string): Promise<void> {
await this.invalidatePartnersList() await this.invalidatePartnersList()
@@ -2,8 +2,12 @@ import { PartnerInfo } from '@/common/decorators/partnerInfo.decorator'
import { Body, Controller, Get, Param, Patch } from '@nestjs/common' import { Body, Controller, Get, Param, Patch } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger' import { ApiTags } from '@nestjs/swagger'
import { AccountsService } from './accounts.service' import { AccountsService } from './accounts.service'
import { UpdateAccountDto } from './dto/account.dto' import { UpdatePartnerConsumerAccountDto } from './dto/account.dto'
import type { AccountsServiceFindAllResponseDto, AccountsServiceFindOneResponseDto, AccountsServiceUpdateResponseDto } from './dto/accounts-response.dto' import type {
AccountsServiceFindAllResponseDto,
AccountsServiceFindOneResponseDto,
AccountsServiceUpdateResponseDto,
} from './dto/accounts-response.dto'
@ApiTags('PartnerConsumerAccounts') @ApiTags('PartnerConsumerAccounts')
@Controller('partner/consumers/:consumerId/accounts') @Controller('partner/consumers/:consumerId/accounts')
@@ -41,7 +45,7 @@ export class AccountsController {
@PartnerInfo('id') partnerId: string, @PartnerInfo('id') partnerId: string,
@Param('consumerId') consumerId: string, @Param('consumerId') consumerId: string,
@Param('id') id: string, @Param('id') id: string,
@Body() data: UpdateAccountDto, @Body() data: UpdatePartnerConsumerAccountDto,
): Promise<AccountsServiceUpdateResponseDto> { ): Promise<AccountsServiceUpdateResponseDto> {
return this.accountsService.update(partnerId, consumerId, id, data) return this.accountsService.update(partnerId, consumerId, id, data)
} }
@@ -3,7 +3,7 @@ import { ConsumerAccountSelect } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
import { UpdateAccountDto } from './dto/account.dto' import { UpdatePartnerConsumerAccountDto } from './dto/account.dto'
@Injectable() @Injectable()
export class AccountsService { export class AccountsService {
@@ -126,7 +126,7 @@ export class AccountsService {
partner_id: string, partner_id: string,
consumer_id: string, consumer_id: string,
id: string, id: string,
data: UpdateAccountDto, data: UpdatePartnerConsumerAccountDto,
) { ) {
const account = await this.prisma.account.update({ const account = await this.prisma.account.update({
where: { where: {
@@ -3,7 +3,7 @@ import { ApiProperty, PartialType } from '@nestjs/swagger'
import { IsEnum, IsOptional, IsString } from 'class-validator' import { IsEnum, IsOptional, IsString } from 'class-validator'
import { AccountStatus, ConsumerRole } from 'generated/prisma/enums' import { AccountStatus, ConsumerRole } from 'generated/prisma/enums'
export class CreateConsumerAccountDto { export class CreatePartnerConsumerAccountDto {
@IsString() @IsString()
@UsernameFieldValidator() @UsernameFieldValidator()
@ApiProperty({ required: true }) @ApiProperty({ required: true })
@@ -19,7 +19,9 @@ export class CreateConsumerAccountDto {
role: ConsumerRole role: ConsumerRole
} }
export class UpdateAccountDto extends PartialType(CreateConsumerAccountDto) { export class UpdatePartnerConsumerAccountDto extends PartialType(
CreatePartnerConsumerAccountDto,
) {
@IsOptional() @IsOptional()
@IsEnum(AccountStatus) @IsEnum(AccountStatus)
@ApiProperty({ enum: AccountStatus }) @ApiProperty({ enum: AccountStatus })
@@ -1,9 +1,9 @@
import { POSStatus, POSType } from '@/generated/prisma/enums' import { POSStatus, POSType } from '@/generated/prisma/enums'
import { CreateConsumerAccountDto } from '@/modules/partners/consumers/accounts/dto/account.dto' import { CreatePartnerConsumerAccountDto } from '@/modules/partners/consumers/accounts/dto/account.dto'
import { ApiProperty, OmitType, PartialType } from '@nestjs/swagger' import { ApiProperty, OmitType, PartialType } from '@nestjs/swagger'
import { IsEnum, IsOptional, IsString } from 'class-validator' import { IsEnum, IsOptional, IsString } from 'class-validator'
export class CreatePosDto extends OmitType(CreateConsumerAccountDto, ['role']) { export class CreatePosDto extends OmitType(CreatePartnerConsumerAccountDto, ['role']) {
@IsString() @IsString()
@ApiProperty({}) @ApiProperty({})
name: string name: string
+24 -1
View File
@@ -1,5 +1,7 @@
import { RedisKeyMaker } from '@/common/utils'
import { checkAndDecodeJwtToken } from '@/common/utils/jwt-user.util' import { checkAndDecodeJwtToken } from '@/common/utils/jwt-user.util'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { RedisService } from '@/redis/redis.service'
import { import {
ForbiddenException, ForbiddenException,
Injectable, Injectable,
@@ -14,6 +16,7 @@ export class PartnerMiddleware implements NestMiddleware {
constructor( constructor(
private prisma: PrismaService, private prisma: PrismaService,
private jwtService: JwtService, private jwtService: JwtService,
private redisService: RedisService,
) {} ) {}
async use(req: Request, _res: Response, next: NextFunction) { async use(req: Request, _res: Response, next: NextFunction) {
@@ -21,12 +24,30 @@ export class PartnerMiddleware implements NestMiddleware {
throw new ForbiddenException('شما دسترسی لازم را ندارید') throw new ForbiddenException('شما دسترسی لازم را ندارید')
} }
try { try {
const token = req.cookies?.accessToken
const cacheKey = RedisKeyMaker.partnerMiddleware(token)
let cachedPartnerData: unknown
try {
cachedPartnerData = await this.redisService.getJson(cacheKey)
} catch (_) {}
const tokenAccount = checkAndDecodeJwtToken(req, this.jwtService) const tokenAccount = checkAndDecodeJwtToken(req, this.jwtService)
req.decodedToken = tokenAccount!
if (tokenAccount?.type !== 'PARTNER') { if (tokenAccount?.type !== 'PARTNER') {
throw new UnauthorizedException() throw new UnauthorizedException()
} }
if (
cachedPartnerData &&
typeof cachedPartnerData === 'object' &&
'account_id' in cachedPartnerData &&
'id' in cachedPartnerData
) {
req.partnerData = cachedPartnerData as any
return next()
}
const partnerAccount = await this.prisma.partnerAccount.findUnique({ const partnerAccount = await this.prisma.partnerAccount.findUnique({
where: { where: {
id: tokenAccount.account_id, id: tokenAccount.account_id,
@@ -46,7 +67,9 @@ export class PartnerMiddleware implements NestMiddleware {
id: partnerAccount.partner_id, id: partnerAccount.partner_id,
} }
req.decodedToken = tokenAccount try {
await this.redisService.setJson(cacheKey, req.partnerData, 60 * 60)
} catch (_) {}
return next() return next()
} catch (error) { } catch (error) {
@@ -6,6 +6,14 @@ import { Injectable } from '@nestjs/common'
export class PosCacheInvalidationService { export class PosCacheInvalidationService {
constructor(private readonly redisService: RedisService) {} constructor(private readonly redisService: RedisService) {}
async invalidatePosInfo(posId: string): Promise<void> {
this.redisService.delete(PosKeyMaker.info(posId))
}
async invalidatePosMiddleware(token: string): Promise<void> {
this.redisService.delete(PosKeyMaker.middleware(token))
}
async invalidatePosGoodsList( async invalidatePosGoodsList(
guildId: string, guildId: string,
businessActivityId: string, businessActivityId: string,
@@ -1,22 +1,25 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common' import { PosInfo } from '@/common/decorators/posInfo.decorator'
import type { IPosPayload } from '@/common/models'
import { Controller, Get, Query } from '@nestjs/common'
import { CustomersService } from './customers.service' import { CustomersService } from './customers.service'
import { PosCustomerFilterDto } from './dto/customer-filter.dto'
@Controller('pos/customers') @Controller('pos/customers')
export class CustomersController { export class CustomersController {
constructor(private readonly customerService: CustomersService) {} constructor(private readonly customerService: CustomersService) {}
@Get() @Get()
findAll() { findAll(@PosInfo() posInfo: IPosPayload, @Query() query: PosCustomerFilterDto) {
return this.customerService.findAll() return this.customerService.findAll(posInfo, query)
} }
@Get(':id') // @Get(':id')
findOne(@Param('id') id: string) { // findOne(@Param('id') id: string) {
return this.customerService.findOne(+id) // return this.customerService.findOne(+id)
} // }
@Post() // @Post()
create(@Body() data: any) { // create(@Body() data: any) {
return this.customerService.create(data) // return this.customerService.create(data)
} // }
} }
+120 -3
View File
@@ -1,10 +1,127 @@
import { IPosPayload } from '@/common/models'
import { ResponseMapper } from '@/common/response/response-mapper'
import { CustomerType } from '@/generated/prisma/enums'
import { CustomerSelect, CustomerWhereInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { PosCustomerFilterDto } from './dto/customer-filter.dto'
@Injectable() @Injectable()
export class CustomersService { export class CustomersService {
findAll() { constructor(private prisma: PrismaService) {}
// TODO: Implement fetching all customers
return [] async findAll(posInfo: IPosPayload, query: PosCustomerFilterDto) {
const { type, q } = query
const where: CustomerWhereInput = {
type,
}
const select: CustomerSelect = {
id: true,
}
if (type === CustomerType.LEGAL) {
where.legal = {
business_activity_id: posInfo.business_id,
}
select.legal = {
select: {
name: true,
economic_code: true,
postal_code: true,
registration_number: true,
},
}
if (q) {
where.legal = {
...where.legal,
OR: [
{
name: {
contains: q,
},
},
{
economic_code: {
contains: q,
},
},
{
postal_code: {
contains: q,
},
},
{
registration_number: {
contains: q,
},
},
],
}
}
} else if (type === CustomerType.INDIVIDUAL) {
where.individual = {
business_activity_id: posInfo.business_id,
}
select.individual = {
select: {
first_name: true,
last_name: true,
economic_code: true,
postal_code: true,
mobile_number: true,
national_id: true,
},
}
if (q) {
where.individual = {
...where.individual,
OR: [
{
first_name: {
contains: q,
},
},
{
last_name: {
contains: q,
},
},
{
economic_code: {
contains: q,
},
},
{
postal_code: {
contains: q,
},
},
{
mobile_number: {
contains: q,
},
},
{
national_id: {
contains: q,
},
},
],
}
}
}
const customers = await this.prisma.customer.findMany({
where,
take: 20,
orderBy: {
created_at: 'desc',
},
select: {
id: true,
...select,
},
})
return ResponseMapper.list(customers)
} }
findOne(id: number) { findOne(id: number) {
@@ -0,0 +1,15 @@
import { ApiPropertyOptional } from '@nestjs/swagger'
import { IsEnum, IsOptional, IsString } from 'class-validator'
import { CustomerType } from 'generated/prisma/enums'
export class PosCustomerFilterDto {
@ApiPropertyOptional({ enum: CustomerType })
@IsOptional()
@IsEnum(CustomerType)
type: CustomerType
@ApiPropertyOptional()
@IsOptional()
@IsString()
q?: string
}
@@ -1,8 +1,13 @@
import { ApiProperty } from '@nestjs/swagger' import { ApiProperty } from '@nestjs/swagger'
import { IsString } from 'class-validator' import { IsString, Length } from 'class-validator'
export class UpdatePosAccountPasswordDto { export class UpdatePosAccountPasswordDto {
@IsString()
@ApiProperty({ required: true }) @ApiProperty({ required: true })
@IsString()
currentPassword: string
@ApiProperty({ required: true })
@IsString()
@Length(6, 32)
password: string password: string
} }
@@ -87,7 +87,7 @@ export class OwnedGoodsService {
return await tx.good.create({ return await tx.good.create({
data: { data: {
...rest, ...rest,
is_default_guild_good: true, is_default_guild_good: false,
image_url, image_url,
sku: { sku: {
connect: { connect: {
+39 -38
View File
@@ -1,7 +1,9 @@
import { RedisKeyMaker } from '@/common/utils'
import { checkAndDecodeJwtToken } from '@/common/utils/jwt-user.util' import { checkAndDecodeJwtToken } from '@/common/utils/jwt-user.util'
import { ConsumerRole, POSStatus } from '@/generated/prisma/enums' import { ConsumerRole, POSStatus } from '@/generated/prisma/enums'
import { PosSelect, PosWhereInput } from '@/generated/prisma/models' import { PosSelect, PosWhereInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { RedisService } from '@/redis/redis.service'
import { import {
ForbiddenException, ForbiddenException,
Injectable, Injectable,
@@ -16,15 +18,38 @@ export class PosMiddleware implements NestMiddleware {
constructor( constructor(
private prisma: PrismaService, private prisma: PrismaService,
private jwtService: JwtService, private jwtService: JwtService,
private redisService: RedisService,
) {} ) {}
async use(req: Request, _res: Response, next: NextFunction) { async use(req: Request, _res: Response, next: NextFunction) {
const doForbidden = () => { const doForbidden = () => {
throw new ForbiddenException('شما دسترسی لازم را ندارید') throw new ForbiddenException('شما دسترسی لازم را ندارید')
} }
const token = req.cookies?.accessToken
const cacheKey = RedisKeyMaker.posMiddleware(token)
let cashedPosData: unknown
try {
cashedPosData = await this.redisService.getJson(cacheKey)
} catch (_) {}
const tokenAccount = checkAndDecodeJwtToken(req, this.jwtService)
req.decodedToken = tokenAccount!
if (
cashedPosData &&
typeof cashedPosData === 'object' &&
'pos_id' in cashedPosData &&
'complex_id' in cashedPosData &&
'business_id' in cashedPosData &&
'guild_id' in cashedPosData &&
'consumer_account_id' in cashedPosData
) {
req.posData = cashedPosData as any
return next()
}
return this.prisma.$transaction(async tx => { return this.prisma.$transaction(async tx => {
try { try {
const tokenAccount = checkAndDecodeJwtToken(req, this.jwtService)
const { type, role, account_id } = tokenAccount! const { type, role, account_id } = tokenAccount!
const posSelect: PosSelect = { const posSelect: PosSelect = {
id: true, id: true,
@@ -103,42 +128,19 @@ export class PosMiddleware implements NestMiddleware {
return doForbidden() return doForbidden()
} }
// if (role !== ConsumerRole.OWNER) { try {
// const accountPermissions = await tx.permissionConsumer.findUnique({ await this.redisService.setJson(
// where: { cacheKey,
// consumer_account_id: account_id, {
// }, pos_id: posId,
// select: { complex_id: pos.complex.id,
// pos_permissions: { business_id: pos.complex.business_activity.id,
// select: { guild_id: pos.complex.business_activity.guild_id,
// pos_id: true, consumer_account_id: account_id,
// }, },
// }, 60 * 60,
// business_permissions: { )
// select: { } catch (_) {}
// business_id: true,
// },
// },
// complex_permissions: {
// select: {
// complex_id: true,
// },
// },
// },
// })
// if (
// !// accountPermissions?.business_permissions.some(
// // permission => permission.id,
// // ) ||
// // accountPermissions?.complex_permissions.some(
// // permission => permission.complex_id,
// // ) ||
// accountPermissions?.pos_permissions.some(permission => permission.pos_id)
// ) {
// return doForbidden()
// }
// }
req.posData = { req.posData = {
pos_id: posId, pos_id: posId,
@@ -147,7 +149,6 @@ export class PosMiddleware implements NestMiddleware {
guild_id: pos.complex.business_activity.guild_id, guild_id: pos.complex.business_activity.guild_id,
consumer_account_id: account_id, consumer_account_id: account_id,
} }
req.decodedToken = tokenAccount!
return next() return next()
} catch (error) { } catch (error) {
+25 -3
View File
@@ -5,7 +5,7 @@ import { RedisKeyMaker } from '@/common/utils/redisKeyMaker'
import { ConsumerStatus } from '@/generated/prisma/enums' import { ConsumerStatus } from '@/generated/prisma/enums'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { RedisService } from '@/redis/redis.service' import { RedisService } from '@/redis/redis.service'
import { Injectable } from '@nestjs/common' import { BadRequestException, Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper' import { ResponseMapper } from 'common/response/response-mapper'
import { UpdatePosAccountPasswordDto } from './dto/update-password-request.dto' import { UpdatePosAccountPasswordDto } from './dto/update-password-request.dto'
@@ -218,7 +218,29 @@ export class PosService {
accountId: string, accountId: string,
data: UpdatePosAccountPasswordDto, data: UpdatePosAccountPasswordDto,
) { ) {
const consumer = await this.prisma.consumerAccount.update({ const currentCustomerAccount = await this.prisma.consumerAccount.findUniqueOrThrow({
where: {
id: accountId,
consumer_id,
},
select: {
account: {
select: {
password: true,
},
},
},
})
const isCurrentPasswordValid = await PasswordUtil.compare(
data.currentPassword,
currentCustomerAccount.account.password,
)
if (!isCurrentPasswordValid) {
throw new BadRequestException('رمز عبور فعلی اشتباه است')
}
const consumerAccount = await this.prisma.consumerAccount.update({
where: { where: {
id: accountId, id: accountId,
consumer_id, consumer_id,
@@ -232,6 +254,6 @@ export class PosService {
}, },
}) })
return ResponseMapper.update(consumer) return ResponseMapper.update(consumerAccount)
} }
} }
@@ -1,6 +1,52 @@
import { SharedCreateSalesInvoiceDto } from '@/common/services/saleInvoices/sale-invoice-create.dto' import {
import { PartialType } from '@nestjs/swagger' SharedCorrectionSalesInvoiceDto,
SharedCreateSalesInvoiceDto,
} from '@/common/services/saleInvoices/sale-invoice-create.dto'
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import {
ArrayMinSize,
IsArray,
IsDateString,
IsNumber,
IsOptional,
IsString,
Min,
ValidateNested,
} from 'class-validator'
export class CreateSalesInvoiceDto extends SharedCreateSalesInvoiceDto {} export class PosCreateSalesInvoiceDto extends SharedCreateSalesInvoiceDto {}
export class PosCorrectionSalesInvoiceDto extends SharedCorrectionSalesInvoiceDto {}
export class UpdateSalesInvoiceDto extends PartialType(CreateSalesInvoiceDto) {} export class PosReturnSalesInvoiceItemDto {
@ApiProperty({ required: false })
@IsOptional()
@IsString()
good_id?: string
@ApiProperty({ required: false })
@IsOptional()
@IsString()
service_id?: string
@ApiProperty({ required: true, default: 1 })
@IsNumber()
@Min(1)
quantity: number
}
export class PosReturnSalesInvoiceDto {
@ApiProperty({ required: true })
@IsDateString(
{ strict: true },
{ message: 'invoice_date must be a valid ISO-8601 string' },
)
invoice_date: Date
@ApiProperty({ required: true, type: [PosReturnSalesInvoiceItemDto] })
@IsArray()
@ArrayMinSize(1)
@ValidateNested({ each: true })
@Type(() => PosReturnSalesInvoiceItemDto)
items: PosReturnSalesInvoiceItemDto[]
}
@@ -1,95 +1,10 @@
import { SharedSaleInvoicesFilterDto } from '@/common/services/saleInvoices/sale-invoice-filter.dto'
import { ApiPropertyOptional } from '@nestjs/swagger' import { ApiPropertyOptional } from '@nestjs/swagger'
import { Type } from 'class-transformer' import { IsNumber, IsOptional } from 'class-validator'
import {
IsDateString,
IsEnum,
IsNumber,
IsOptional,
IsString,
Min,
} from 'class-validator'
import { TspProviderResponseStatus } from 'generated/prisma/enums'
export class SalesInvoicesFilterDto {
@ApiPropertyOptional({ default: 1 })
@IsOptional()
@Type(() => Number)
@IsNumber()
@Min(1)
page?: number
@ApiPropertyOptional({ default: 10 })
@IsOptional()
@Type(() => Number)
@IsNumber()
@Min(1)
perPage?: number
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
invoice_date_from?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
invoice_date_to?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
created_at_from?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
created_at_to?: string
export class SalesInvoicesFilterDto extends SharedSaleInvoicesFilterDto {
@ApiPropertyOptional() @ApiPropertyOptional()
@IsOptional() @IsOptional()
@IsNumber() @IsNumber()
invoice_number?: number invoice_number?: number
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_name?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_mobile?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_national_id?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_economic_code?: string
@ApiPropertyOptional({ enum: TspProviderResponseStatus })
@IsOptional()
@IsEnum(TspProviderResponseStatus)
status?: TspProviderResponseStatus
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount?: number
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount_from?: number
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount_to?: number
} }
@@ -2,7 +2,11 @@ import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common'
import { PosInfo } from '@/common/decorators/posInfo.decorator' import { PosInfo } from '@/common/decorators/posInfo.decorator'
import type { IPosPayload } from '@/common/models/posPayload.model' import type { IPosPayload } from '@/common/models/posPayload.model'
import { CreateSalesInvoiceDto } from './dto/create-sales-invoice.dto' import {
PosCorrectionSalesInvoiceDto,
PosCreateSalesInvoiceDto,
PosReturnSalesInvoiceDto,
} from './dto/create-sales-invoice.dto'
import { SalesInvoicesFilterDto } from './dto/sales-invoices-filter.dto' import { SalesInvoicesFilterDto } from './dto/sales-invoices-filter.dto'
import { SalesInvoicesService } from './sales-invoices.service' import { SalesInvoicesService } from './sales-invoices.service'
@@ -30,7 +34,7 @@ export class SalesInvoicesController {
} }
@Post() @Post()
create(@Body() data: CreateSalesInvoiceDto, @PosInfo() posInfo: IPosPayload) { create(@Body() data: PosCreateSalesInvoiceDto, @PosInfo() posInfo: IPosPayload) {
return this.salesInvoicesService.create(data, posInfo) return this.salesInvoicesService.create(data, posInfo)
} }
@@ -49,6 +53,23 @@ export class SalesInvoicesController {
return this.salesInvoicesService.revoke(id, posInfo) return this.salesInvoicesService.revoke(id, posInfo)
} }
@Post(':id/correction')
correction(
@Param('id') id: string,
@PosInfo() posInfo: IPosPayload,
@Body() data: PosCorrectionSalesInvoiceDto,
) {
return this.salesInvoicesService.correction(id, posInfo, data)
}
@Post(':id/return_from_sale')
return(
@Param('id') id: string,
@PosInfo() posInfo: IPosPayload,
@Body() data: PosReturnSalesInvoiceDto,
) {
return this.salesInvoicesService.return(id, posInfo, data)
}
// @Post('send/bulk') // @Post('send/bulk')
// sendBulk(@Body() data: SendBulkSalesInvoicesDto, @PosInfo() posInfo: IPosPayload) { // sendBulk(@Body() data: SendBulkSalesInvoicesDto, @PosInfo() posInfo: IPosPayload) {
// return this.salesInvoicesService.sendBulk(data.invoice_ids, posInfo) // return this.salesInvoicesService.sendBulk(data.invoice_ids, posInfo)
@@ -1,6 +1,7 @@
import { SharedSaleInvoiceCreateService } from '@/common/services/saleInvoices/sale-invoice-create.service' import { SharedSaleInvoiceCreateService } from '@/common/services/saleInvoices/sale-invoice-create.service'
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service' import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service' import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service'
import { SharedSaleInvoiceFilterService } from '@/common/services/saleInvoices/sale-invoice-filter.service'
import { SaleInvoiceTspModule } from '@/modules/tspProviders/sales-invoice-tsp.module' import { SaleInvoiceTspModule } from '@/modules/tspProviders/sales-invoice-tsp.module'
import { Module } from '@nestjs/common' import { Module } from '@nestjs/common'
import { SalesInvoicesController } from './sales-invoices.controller' import { SalesInvoicesController } from './sales-invoices.controller'
@@ -14,6 +15,7 @@ import { SalesInvoicesService } from './sales-invoices.service'
SharedSaleInvoiceCreateService, SharedSaleInvoiceCreateService,
SharedSaleInvoiceActionsService, SharedSaleInvoiceActionsService,
SharedSaleInvoiceAccessService, SharedSaleInvoiceAccessService,
SharedSaleInvoiceFilterService,
], ],
}) })
export class PosSalesInvoicesModule {} export class PosSalesInvoicesModule {}
@@ -2,6 +2,7 @@ import { IPosPayload } from '@/common/models/posPayload.model'
import { QUERY_CONSTANTS } from '@/common/queryConstants' import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service' import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { SharedSaleInvoiceCreateService } from '@/common/services/saleInvoices/sale-invoice-create.service' import { SharedSaleInvoiceCreateService } from '@/common/services/saleInvoices/sale-invoice-create.service'
import { SharedSaleInvoiceFilterService } from '@/common/services/saleInvoices/sale-invoice-filter.service'
import { translateEnumValue } from '@/common/utils' import { translateEnumValue } from '@/common/utils'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable, NotFoundException } from '@nestjs/common' import { Injectable, NotFoundException } from '@nestjs/common'
@@ -9,7 +10,11 @@ import { ResponseMapper } from 'common/response/response-mapper'
import { Prisma } from 'generated/prisma/client' import { Prisma } from 'generated/prisma/client'
import { TspProviderRequestType, TspProviderResponseStatus } from 'generated/prisma/enums' import { TspProviderRequestType, TspProviderResponseStatus } from 'generated/prisma/enums'
import { SalesInvoiceTspService } from '../../tspProviders/sales-invoice-tsp.service' import { SalesInvoiceTspService } from '../../tspProviders/sales-invoice-tsp.service'
import { CreateSalesInvoiceDto } from './dto/create-sales-invoice.dto' import {
PosCorrectionSalesInvoiceDto,
PosCreateSalesInvoiceDto,
PosReturnSalesInvoiceDto,
} from './dto/create-sales-invoice.dto'
import { SalesInvoicesFilterDto } from './dto/sales-invoices-filter.dto' import { SalesInvoicesFilterDto } from './dto/sales-invoices-filter.dto'
@Injectable() @Injectable()
@@ -19,6 +24,7 @@ export class SalesInvoicesService {
private salesInvoiceTaxService: SalesInvoiceTspService, private salesInvoiceTaxService: SalesInvoiceTspService,
private sharedSaleInvoiceCreateService: SharedSaleInvoiceCreateService, private sharedSaleInvoiceCreateService: SharedSaleInvoiceCreateService,
private sharedSaleInvoiceActionsService: SharedSaleInvoiceActionsService, private sharedSaleInvoiceActionsService: SharedSaleInvoiceActionsService,
private sharedSaleInvoiceFilterService: SharedSaleInvoiceFilterService,
) {} ) {}
async findAll(posInfo: IPosPayload, query: SalesInvoicesFilterDto = {}) { async findAll(posInfo: IPosPayload, query: SalesInvoicesFilterDto = {}) {
@@ -42,13 +48,13 @@ export class SalesInvoicesService {
]) ])
const summaryItems = items.map(invoice => { const summaryItems = items.map(invoice => {
const { tsp_attempts, type, ...rest } = invoice const { last_tsp_status, type, ...rest } = invoice
return { return {
...rest, ...rest,
type: translateEnumValue('TspProviderRequestType', type), type: translateEnumValue('TspProviderRequestType', type),
status: translateEnumValue( status: translateEnumValue(
'TspProviderResponseStatus', 'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND, last_tsp_status || TspProviderResponseStatus.NOT_SEND,
), ),
} }
}) })
@@ -73,21 +79,25 @@ export class SalesInvoicesService {
}) })
if (invoice) { if (invoice) {
const { tsp_attempts, type, ...rest } = invoice const { last_tsp_status, type, ...rest } = invoice
const mappedInvoice = { const mappedInvoice = {
...rest, ...rest,
type: translateEnumValue('TspProviderRequestType', type), type: translateEnumValue('TspProviderRequestType', type),
status: translateEnumValue( status: translateEnumValue(
'TspProviderResponseStatus', 'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND, last_tsp_status || TspProviderResponseStatus.NOT_SEND,
),
settlement_type: translateEnumValue(
'InvoiceSettlementType',
invoice.settlement_type,
), ),
} }
return ResponseMapper.single(mappedInvoice) return ResponseMapper.single(mappedInvoice)
} else throw new NotFoundException('فاکتور مورد نظر شما یافت نشد.') } else throw new NotFoundException('صورت‌حساب مورد نظر شما یافت نشد.')
} }
async create(data: CreateSalesInvoiceDto, posInfo: IPosPayload) { async create(data: PosCreateSalesInvoiceDto, posInfo: IPosPayload) {
let salesInvoice = await this.sharedSaleInvoiceCreateService.create({ let salesInvoice = await this.sharedSaleInvoiceCreateService.create({
data, data,
businessId: posInfo.business_id, businessId: posInfo.business_id,
@@ -144,6 +154,40 @@ export class SalesInvoicesService {
return ResponseMapper.single(invoice) return ResponseMapper.single(invoice)
} }
async correction(
invoiceId: string,
posInfo: IPosPayload,
data: PosCorrectionSalesInvoiceDto,
) {
const { consumer_account_id, pos_id, business_id, complex_id } = posInfo
const invoice = await this.sharedSaleInvoiceActionsService.correction(
data,
consumer_account_id,
pos_id,
complex_id,
business_id,
invoiceId,
)
return ResponseMapper.single(invoice)
}
async return(invoiceId: string, posInfo: IPosPayload, data: PosReturnSalesInvoiceDto) {
const { consumer_account_id, pos_id, business_id, complex_id } = posInfo
const invoice = await this.sharedSaleInvoiceActionsService.return(
data,
consumer_account_id,
pos_id,
complex_id,
business_id,
invoiceId,
)
return ResponseMapper.create(invoice)
}
async inquiry(consumer_account_id: string, pos_id: string, invoiceId: string) { async inquiry(consumer_account_id: string, pos_id: string, invoiceId: string) {
const invoice = await this.sharedSaleInvoiceActionsService.inquiry( const invoice = await this.sharedSaleInvoiceActionsService.inquiry(
consumer_account_id, consumer_account_id,
@@ -155,151 +199,20 @@ export class SalesInvoicesService {
private buildFindAllWhere(posInfo: IPosPayload, query: SalesInvoicesFilterDto) { private buildFindAllWhere(posInfo: IPosPayload, query: SalesInvoicesFilterDto) {
const where: Prisma.SalesInvoiceWhereInput = { const where: Prisma.SalesInvoiceWhereInput = {
...this.sharedSaleInvoiceFilterService.buildWhere(query),
pos: { pos: {
id: posInfo.pos_id, id: posInfo.pos_id,
complex: { complex: {
business_activity_id: posInfo.business_id, business_activity_id: posInfo.business_id,
}, },
}, },
referenced_by: null,
} }
if (query.invoice_number) { if (query.invoice_number) {
where.invoice_number = parseInt(query.invoice_number + '') where.invoice_number = parseInt(query.invoice_number + '')
} }
if (query.invoice_date_from || query.invoice_date_to) {
where.invoice_date = {
...(query.invoice_date_from ? { gte: new Date(query.invoice_date_from) } : {}),
...(query.invoice_date_to ? { lte: new Date(query.invoice_date_to) } : {}),
}
}
if (query.created_at_from || query.created_at_to) {
where.created_at = {
...(query.created_at_from ? { gte: new Date(query.created_at_from) } : {}),
...(query.created_at_to ? { lte: new Date(query.created_at_to) } : {}),
}
}
if (
query.total_amount !== undefined ||
query.total_amount_from !== undefined ||
query.total_amount_to !== undefined
) {
where.total_amount = {
...(query.total_amount !== undefined ? { equals: query.total_amount } : {}),
...(query.total_amount_from !== undefined
? { gte: query.total_amount_from }
: {}),
...(query.total_amount_to !== undefined ? { lte: query.total_amount_to } : {}),
}
}
if (
query.customer_name?.trim() ||
query.customer_mobile?.trim() ||
query.customer_national_id?.trim() ||
query.customer_economic_code?.trim()
) {
where.customer = {
is: {
OR: [
...(query.customer_name?.trim()
? [
{
individual: {
is: {
OR: [
{
first_name: {
contains: query.customer_name.trim(),
},
},
{
last_name: {
contains: query.customer_name.trim(),
},
},
],
},
},
},
{
legal: {
is: {
name: {
contains: query.customer_name.trim(),
},
},
},
},
]
: []),
...(query.customer_mobile?.trim()
? [
{
individual: {
is: {
mobile_number: {
contains: query.customer_mobile.trim(),
},
},
},
},
]
: []),
...(query.customer_national_id?.trim()
? [
{
individual: {
is: {
national_id: {
contains: query.customer_national_id.trim(),
},
},
},
},
]
: []),
...(query.customer_economic_code?.trim()
? [
{
legal: {
is: {
OR: [
{
economic_code: {
contains: query.customer_economic_code.trim(),
},
},
{
registration_number: {
contains: query.customer_economic_code.trim(),
},
},
],
},
},
},
]
: []),
],
},
}
}
if (query.status) {
if (query.status === TspProviderResponseStatus.NOT_SEND) {
where.tsp_attempts = undefined
} else {
where.tsp_attempts = {
some: {
status: query.status,
},
}
}
}
return where return where
} }
} }
@@ -14,105 +14,98 @@ export class StatisticsService {
async findAll(posId: string, businessId: string, fromDate: Date = new Date()) { async findAll(posId: string, businessId: string, fromDate: Date = new Date()) {
const seasonDate = getCurrentJalaliSeasonRange(fromDate) const seasonDate = getCurrentJalaliSeasonRange(fromDate)
const [item] = await this.prisma.$queryRaw< const rows = await this.prisma.$queryRaw<
Array<{ Array<{
all_amount_sum: number | null all_amount_sum: number
all_tax_sum: number | null all_tax_sum: number
all_count: number | null all_count: number
success_amount_sum: number | null success_amount_sum: number
success_tax_sum: number | null success_tax_sum: number
success_count: number | null success_count: number
failure_amount_sum: number | null failure_amount_sum: number
failure_tax_sum: number | null failure_tax_sum: number
failure_count: number | null failure_count: number
pending_amount_sum: number | null pending_amount_sum: number
pending_tax_sum: number | null pending_tax_sum: number
pending_count: number | null pending_count: number
not_sended_amount_sum: number | null not_sended_amount_sum: number
not_sended_tax_sum: number | null not_sended_tax_sum: number
not_sended_count: number | null not_sended_count: number
not_original_amount_sum: number | null not_original_amount_sum: number
not_original_tax_sum: number | null not_original_tax_sum: number
not_original_count: number | null not_original_count: number
}> }>
>` >`
SELECT SELECT
SUM(si.total_amount) AS all_amount_sum, COUNT(*) AS all_count,
SUM(si.tax_amount) AS all_tax_sum, COALESCE(SUM(si.total_amount), 0) AS all_amount_sum,
si.type, COALESCE(SUM(si.tax_amount), 0) AS all_tax_sum,
COUNT(*) AS all_count,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.SUCCESS} THEN si.total_amount ELSE 0 END) AS success_amount_sum, SUM(si.last_tsp_status = ${TspProviderResponseStatus.SUCCESS}) AS success_count,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.SUCCESS} THEN si.tax_amount ELSE 0 END) AS success_tax_sum, COALESCE(SUM(CASE WHEN si.last_tsp_status = ${TspProviderResponseStatus.SUCCESS} THEN si.total_amount ELSE 0 END), 0) AS success_amount_sum,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.SUCCESS} THEN 1 ELSE 0 END) AS success_count, COALESCE(SUM(CASE WHEN si.last_tsp_status = ${TspProviderResponseStatus.SUCCESS} THEN si.tax_amount ELSE 0 END), 0) AS success_tax_sum,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.FAILURE} THEN si.total_amount ELSE 0 END) AS failure_amount_sum,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.FAILURE} THEN si.tax_amount ELSE 0 END) AS failure_tax_sum, SUM(si.last_tsp_status = ${TspProviderResponseStatus.FAILURE}) AS failure_count,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.FAILURE} THEN 1 ELSE 0 END) AS failure_count, COALESCE(SUM(CASE WHEN si.last_tsp_status = ${TspProviderResponseStatus.FAILURE} THEN si.total_amount ELSE 0 END), 0) AS failure_amount_sum,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.QUEUED} THEN si.total_amount ELSE 0 END) AS pending_amount_sum, COALESCE(SUM(CASE WHEN si.last_tsp_status = ${TspProviderResponseStatus.FAILURE} THEN si.tax_amount ELSE 0 END), 0) AS failure_tax_sum,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.QUEUED} THEN si.tax_amount ELSE 0 END) AS pending_tax_sum,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.QUEUED} THEN 1 ELSE 0 END) AS pending_count, SUM(si.last_tsp_status = ${TspProviderResponseStatus.FISCAL_QUEUED}) AS pending_count,
SUM(CASE WHEN la.status IS NULL THEN si.total_amount ELSE 0 END) AS not_sended_amount_sum, COALESCE(SUM(CASE WHEN si.last_tsp_status = ${TspProviderResponseStatus.FISCAL_QUEUED} THEN si.total_amount ELSE 0 END), 0) AS pending_amount_sum,
SUM(CASE WHEN la.status IS NULL THEN si.tax_amount ELSE 0 END) AS not_sended_tax_sum, COALESCE(SUM(CASE WHEN si.last_tsp_status = ${TspProviderResponseStatus.FISCAL_QUEUED} THEN si.tax_amount ELSE 0 END), 0) AS pending_tax_sum,
SUM(CASE WHEN la.status IS NULL THEN 1 ELSE 0 END) AS not_sended_count,
SUM(CASE WHEN si.type <> ${TspProviderRequestType.ORIGINAL} THEN si.total_amount ELSE 0 END) AS not_original_amount_sum, SUM(si.last_tsp_status = ${TspProviderResponseStatus.NOT_SEND}) AS not_sended_count,
SUM(CASE WHEN si.type <> ${TspProviderRequestType.ORIGINAL} THEN si.tax_amount ELSE 0 END) AS not_original_tax_sum, COALESCE(SUM(CASE WHEN si.last_tsp_status = ${TspProviderResponseStatus.NOT_SEND} THEN si.total_amount ELSE 0 END), 0) AS not_sended_amount_sum,
SUM(CASE WHEN si.type <> ${TspProviderRequestType.ORIGINAL} THEN 1 ELSE 0 END) AS not_original_count COALESCE(SUM(CASE WHEN si.last_tsp_status = ${TspProviderResponseStatus.NOT_SEND} THEN si.tax_amount ELSE 0 END), 0) AS not_sended_tax_sum,
SUM(si.type <> ${TspProviderRequestType.ORIGINAL}) AS not_original_count,
COALESCE(SUM(CASE WHEN si.type <> ${TspProviderRequestType.ORIGINAL} THEN si.total_amount ELSE 0 END), 0) AS not_original_amount_sum,
COALESCE(SUM(CASE WHEN si.type <> ${TspProviderRequestType.ORIGINAL} THEN si.tax_amount ELSE 0 END), 0) AS not_original_tax_sum
FROM sales_invoices si FROM sales_invoices si
INNER JOIN poses p ON p.id = si.pos_id INNER JOIN poses p ON p.id = si.pos_id
LEFT JOIN (
SELECT att.invoice_id, att.status
FROM sale_invoice_tsp_attempts att
INNER JOIN (
SELECT invoice_id, MAX(attempt_no) AS max_attempt_no
FROM sale_invoice_tsp_attempts
GROUP BY invoice_id
) latest
ON latest.invoice_id = att.invoice_id
AND latest.max_attempt_no = att.attempt_no
) la ON la.invoice_id = si.id
WHERE si.invoice_date >= ${seasonDate.start} WHERE si.invoice_date >= ${seasonDate.start}
AND si.invoice_date <= ${seasonDate.end} AND si.invoice_date <= ${seasonDate.end}
AND si.pos_id = ${posId} AND si.pos_id = ${posId}
AND p.complex_id IN ( AND p.complex_id IN (
SELECT c.id FROM complexes c WHERE c.business_activity_id = ${businessId} SELECT c.id FROM complexes c WHERE c.business_activity_id = ${businessId}
) )
AND NOT EXISTS ( AND NOT EXISTS (
SELECT 1 SELECT 1
FROM sales_invoices child FROM sales_invoices child
WHERE child.ref_id = si.id WHERE child.ref_id = si.id
) );
GROUP BY si.type `
`
return ResponseMapper.single({ return ResponseMapper.single({
all: { all: {
total_amount: Number(item?.all_amount_sum || 0), total_amount: Number(rows[0].all_amount_sum || 0),
total_tax: Number(item?.all_tax_sum), total_tax: Number(rows[0].all_tax_sum || 0),
count: Number(item?.all_count || 0), count: Number(rows[0].all_count || 0),
}, },
success: { success: {
total_amount: Number(item?.success_amount_sum || 0), total_amount: Number(rows[0].success_amount_sum || 0),
tax_amount: Number(item?.success_tax_sum || 0), total_tax: Number(rows[0].success_tax_sum || 0),
count: Number(item?.success_count || 0), count: Number(rows[0].success_count || 0),
}, },
failure: { failure: {
total_amount: Number(item?.failure_amount_sum || 0), total_amount: Number(rows[0].failure_amount_sum || 0),
tax_amount: Number(item?.failure_tax_sum || 0), total_tax: Number(rows[0].failure_tax_sum || 0),
count: Number(item?.failure_count || 0), count: Number(rows[0].failure_count || 0),
}, },
pending: { pending: {
total_amount: Number(item?.pending_amount_sum || 0), total_amount: Number(rows[0].pending_amount_sum || 0),
tax_amount: Number(item?.pending_tax_sum || 0), total_tax: Number(rows[0].pending_tax_sum || 0),
count: Number(item?.pending_count || 0), count: Number(rows[0].pending_count || 0),
}, },
not_sended: { not_send: {
total_amount: Number(item?.not_sended_amount_sum || 0), total_amount: Number(rows[0].not_sended_amount_sum || 0),
tax_amount: Number(item?.not_sended_tax_sum || 0), total_tax: Number(rows[0].not_sended_tax_sum || 0),
count: Number(item?.not_sended_count || 0), count: Number(rows[0].not_sended_count || 0),
}, },
not_original: { not_original: {
total_amount: Number(item?.not_original_amount_sum || 0), total_amount: Number(rows[0].not_original_amount_sum || 0),
tax_amount: Number(item?.not_original_tax_sum || 0), total_tax: Number(rows[0].not_original_tax_sum || 0),
count: Number(item?.not_original_count || 0), count: Number(rows[0].not_original_count || 0),
}, },
}) })
} }
+45 -18
View File
@@ -13,48 +13,77 @@ import {
IsObject, IsObject,
IsOptional, IsOptional,
IsString, IsString,
Length,
Min, Min,
ValidateNested, ValidateNested,
} from 'class-validator' } from 'class-validator'
export class CustomerUnknownInfoDto { export class CustomerUnknownInfoDto {
@ApiProperty({}) @ApiProperty()
@IsString() @IsString()
@IsOptional() @IsOptional()
name: string name?: string
@ApiProperty({}) @ApiProperty()
@IsString() @IsString()
@IsOptional() @IsOptional()
economic_code: string economic_code?: string
} }
export class CustomerLegalInfoDto { export class CustomerLegalInfoDto {
@ApiProperty({ required: true }) @ApiProperty()
@IsOptional()
@IsString() @IsString()
name: string name?: string
@ApiProperty({ required: true }) @ApiProperty()
@IsOptional()
@IsString() @IsString()
economic_code: string registration_number?: string
@ApiProperty()
@IsOptional()
@IsString()
postal_code?: string
@ApiProperty()
@IsOptional()
@IsString()
@Length(11)
economic_code?: string
} }
export class CustomerIndividualInfoDto { export class CustomerIndividualInfoDto {
@ApiProperty({ required: true }) @ApiProperty()
@IsOptional()
@IsString() @IsString()
first_name: string first_name?: string
@ApiProperty({ required: true }) @ApiProperty()
@IsOptional()
@IsString() @IsString()
last_name: string last_name?: string
@ApiProperty({ required: true }) @ApiProperty()
@IsOptional()
@IsString() @IsString()
national_id: string national_id?: string
@ApiProperty({ required: true }) @ApiProperty()
@IsOptional()
@IsString() @IsString()
mobile_number: string mobile_number?: string
@ApiProperty()
@IsOptional()
@IsString()
postal_code?: string
@ApiProperty()
@IsOptional()
@IsString()
@Length(14)
economic_code?: string
} }
export class CustomerInfoDto { export class CustomerInfoDto {
@@ -64,12 +93,10 @@ export class CustomerInfoDto {
@ApiProperty({}) @ApiProperty({})
@Type(() => CustomerLegalInfoDto) @Type(() => CustomerLegalInfoDto)
@ValidateNested({ each: true })
legal_info?: CustomerLegalInfoDto legal_info?: CustomerLegalInfoDto
@ApiProperty({}) @ApiProperty({})
@Type(() => CustomerIndividualInfoDto) @Type(() => CustomerIndividualInfoDto)
@ValidateNested({ each: true })
individual_info?: CustomerIndividualInfoDto individual_info?: CustomerIndividualInfoDto
@ApiProperty({}) @ApiProperty({})
+12 -3
View File
@@ -7,14 +7,22 @@ import { Type } from 'class-transformer'
import { import {
ArrayMinSize, ArrayMinSize,
IsArray, IsArray,
IsDateString,
IsNumber, IsNumber,
IsObject, IsObject,
IsString, IsString,
ValidateNested, ValidateNested,
} from 'class-validator' } from 'class-validator'
import { TspProviderOriginalSendPayloadDto } from './original.dto' import {
TspProviderOriginalResponseDto,
TspProviderOriginalSendPayloadDto,
} from './original.dto'
export class TspProviderCorrectionInvoicePayloadDto { export class TspProviderCorrectionInvoicePayloadDto {
@ApiProperty({ required: true, nullable: true })
@IsDateString()
invoice_date: Date
@ApiProperty({ type: [SharedCreateSalesInvoiceItemDto] }) @ApiProperty({ type: [SharedCreateSalesInvoiceItemDto] })
@IsArray() @IsArray()
@ValidateNested({ each: true }) @ValidateNested({ each: true })
@@ -38,12 +46,13 @@ export class TspProviderCorrectionInvoicePayloadDto {
@IsObject() @IsObject()
@ValidateNested({ each: true }) @ValidateNested({ each: true })
@Type(() => SharedCreateSalesInvoicePaymentsDto) @Type(() => SharedCreateSalesInvoicePaymentsDto)
payments: SharedCreateSalesInvoicePaymentsDto payments?: SharedCreateSalesInvoicePaymentsDto
} }
export class TspProviderCorrectionSendPayloadDto extends TspProviderOriginalSendPayloadDto { export class TspProviderCorrectionSendPayloadDto extends TspProviderOriginalSendPayloadDto {
@ApiProperty({ required: true }) @ApiProperty({ required: true })
@IsString() @IsString()
last_tax_id: string last_tax_id: string
} }
export class TspProviderCorrectionSendResponseDto {} export class TspProviderCorrectionSendResponseDto extends TspProviderOriginalResponseDto {}
+1
View File
@@ -3,4 +3,5 @@ export * from './correction.dto'
export * from './get.dto' export * from './get.dto'
export * from './original.dto' export * from './original.dto'
export * from './provider-switch.dto' export * from './provider-switch.dto'
export * from './return.dto'
export * from './revoke.dto' export * from './revoke.dto'
+1 -1
View File
@@ -14,7 +14,7 @@ import {
IsOptional, IsOptional,
IsString, IsString,
Min, Min,
ValidateNested ValidateNested,
} from 'class-validator' } from 'class-validator'
import { import {
CustomerInfoDto, CustomerInfoDto,
@@ -0,0 +1,48 @@
import { SharedCreateSalesInvoiceItemDto } from '@/common/services/saleInvoices/sale-invoice-create.dto'
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import {
ArrayMinSize,
IsArray,
IsDateString,
IsNumber,
IsString,
ValidateNested,
} from 'class-validator'
import {
TspProviderOriginalResponseDto,
TspProviderOriginalSendPayloadDto,
} from './original.dto'
export class TspProviderReturnInvoicePayloadDto {
@ApiProperty({ required: true, nullable: true })
@IsDateString()
invoice_date: Date
@ApiProperty({ type: [SharedCreateSalesInvoiceItemDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => SharedCreateSalesInvoiceItemDto)
@ArrayMinSize(1)
items: SharedCreateSalesInvoiceItemDto[]
@ApiProperty()
@IsNumber()
total_amount: number
@ApiProperty()
@IsNumber()
discount_amount: number
@ApiProperty()
@IsNumber()
tax_amount: number
}
export class TspProviderReturnSendPayloadDto extends TspProviderOriginalSendPayloadDto {
@ApiProperty({ required: true })
@IsString()
last_tax_id: string
}
export class TspProviderReturnSendResponseDto extends TspProviderOriginalResponseDto {}
@@ -6,6 +6,8 @@ import {
TspProviderGetResponseDto, TspProviderGetResponseDto,
TspProviderOriginalResponseDto, TspProviderOriginalResponseDto,
TspProviderOriginalSendPayloadDto, TspProviderOriginalSendPayloadDto,
TspProviderReturnSendPayloadDto,
TspProviderReturnSendResponseDto,
TspProviderRevokePayloadDto, TspProviderRevokePayloadDto,
TspProviderRevokeResponseDto, TspProviderRevokeResponseDto,
} from './dto' } from './dto'
@@ -48,6 +50,14 @@ export class SalesInvoiceTspSwitchService {
return adapter.correctionSend(payload) return adapter.correctionSend(payload)
} }
async returnFromSale(
payload: TspProviderReturnSendPayloadDto,
): Promise<TspProviderReturnSendResponseDto> {
const adapter = this.resolveSwitch(payload.tsp_provider)
return adapter.returnSend(payload)
}
async sendBulk( async sendBulk(
payloads: TspProviderOriginalSendPayloadDto[], payloads: TspProviderOriginalSendPayloadDto[],
): Promise<TspProviderBulkSendResultDto[]> { ): Promise<TspProviderBulkSendResultDto[]> {
@@ -6,18 +6,15 @@ import {
TspProviderRequestType, TspProviderRequestType,
TspProviderResponseStatus, TspProviderResponseStatus,
} from 'generated/prisma/client' } from 'generated/prisma/client'
import { import { TspProviderActionResponseDto } from './dto'
TspProviderActionResponseDto,
TspProviderCorrectionInvoicePayloadDto,
} from './dto'
import { SalesInvoiceTspSwitchService } from './sales-invoice-tsp-switch.service' import { SalesInvoiceTspSwitchService } from './sales-invoice-tsp-switch.service'
import { import {
buildCorrectionPayload, buildCorrectionPayload,
buildOriginalPayload, buildOriginalPayload,
buildReturnFromSalePayload,
buildRevokePayload, buildRevokePayload,
getOriginalResendAttemptNumber, getOriginalResendAttemptNumber,
onResult, onResult,
trySend,
} from './utils/sales-invoice-tsp.utils' } from './utils/sales-invoice-tsp.utils'
type ItemTspRow = { type ItemTspRow = {
@@ -41,20 +38,28 @@ export class SalesInvoiceTspService {
const attemptNumber = await getOriginalResendAttemptNumber(this.prisma, invoice_id) const attemptNumber = await getOriginalResendAttemptNumber(this.prisma, invoice_id)
const attempt = await this.prisma.saleInvoiceTspAttempts.create({ const invoice = await this.prisma.salesInvoice.update({
where: {
id: invoice_id,
},
data: { data: {
attempt_no: attemptNumber, last_tsp_status: TspProviderResponseStatus.QUEUED,
invoice_id, last_attempt_no: attemptNumber,
provider_request_payload: {}, tsp_attempts: {
status: TspProviderResponseStatus.QUEUED, create: {
raw_request_payload: JSON.parse(JSON.stringify(payload)), attempt_no: attemptNumber,
sent_at: new Date().toISOString(), provider_request_payload: {},
message: 'در حال ارسال به سامانه مالیاتی...', status: TspProviderResponseStatus.QUEUED,
raw_request_payload: JSON.parse(JSON.stringify(payload)),
sent_at: new Date().toISOString(),
message: 'در حال ارسال به سامانه مالیاتی...',
},
},
}, },
}) })
const result = await this.tspSwitchService.send(payload) const result = await this.tspSwitchService.send(payload)
return await onResult(this.prisma, result, attempt.id) return await onResult(this.prisma, result, invoice.id)
} }
async sendBulk(consumer_id: string, invoice_ids: string[]): Promise<void> { async sendBulk(consumer_id: string, invoice_ids: string[]): Promise<void> {
@@ -74,18 +79,17 @@ export class SalesInvoiceTspService {
pos_id: string, pos_id: string,
consumer_id: string, consumer_id: string,
): Promise<TspProviderActionResponseDto> { ): Promise<TspProviderActionResponseDto> {
const [attempt, pos] = await this.prisma.$transaction(async tx => [ const [invoice, pos] = await this.prisma.$transaction(async tx => [
await tx.saleInvoiceTspAttempts.findFirst({ await tx.salesInvoice.findUnique({
where: { where: {
invoice_id, id: invoice_id,
invoice: { pos: {
pos: { id: pos_id,
id: pos_id,
},
}, },
}, },
orderBy: { select: {
attempt_no: 'desc', last_tsp_status: true,
id: true,
}, },
}), }),
@@ -134,12 +138,25 @@ export class SalesInvoiceTspService {
}), }),
]) ])
if (!attempt) { if (!invoice) {
throw new NotFoundException('صورت‌حساب ارسالی فاکتور شما به سامانه یافت نشد.') throw new NotFoundException('صورت‌حساب ارسالی صورت‌حساب شما به سامانه یافت نشد.')
} }
if (!pos) { if (!pos) {
throw new NotFoundException('مشکلی در ساختار اطلاعات ورودی شما وجود دارد.') throw new NotFoundException('مشکلی در ساختار اطلاعات ورودی شما وجود دارد.')
} }
if (
!invoice.last_tsp_status ||
invoice.last_tsp_status === TspProviderResponseStatus.NOT_SEND
) {
throw new BadRequestException(
'صورت‌حساب شما هنوز به سامانه مالیاتی ارسال نشده است. لطفا چند لحظه دیگر مجددا تلاش کنید.',
)
}
if (invoice.last_tsp_status === TspProviderResponseStatus.QUEUED) {
throw new BadRequestException(
'صورت‌حساب شما در صف ارسال به سامانه مالیاتی قرار دارد. لطفا چند لحظه دیگر مجددا تلاش کنید.',
)
}
const { business_activity } = pos.complex const { business_activity } = pos.complex
@@ -152,130 +169,72 @@ export class SalesInvoiceTspService {
business_activity.partner_token, business_activity.partner_token,
) )
return await onResult(this.prisma, result, attempt.id) return await onResult(this.prisma, result, invoice.id)
} }
async correctionSend( async correctionSend(
consumerAccountId: string,
posId: string, posId: string,
complexId: string, invoice_id: string,
businessId: string,
ref_invoice_id: string,
dataToUpdate: TspProviderCorrectionInvoicePayloadDto,
): Promise<TspProviderActionResponseDto> { ): Promise<TspProviderActionResponseDto> {
const [newInvoice, attempt, correctionPayload] = await this.prisma.$transaction( const payload = await buildCorrectionPayload(this.prisma, invoice_id, posId)
async tx => {
const relatedInvoice = await tx.salesInvoice.findUnique({
where: {
id: ref_invoice_id,
},
include: {
customer: {
select: {
type: true,
},
},
tsp_attempts: {
orderBy: {
attempt_no: 'desc',
},
take: 1,
},
},
})
if (!relatedInvoice) { const attemptNumber = 1
throw new NotFoundException('فاکتور مورد نظر یافت نشد.')
}
if (relatedInvoice.type === TspProviderRequestType.REVOKE) { const invoice = await this.prisma.salesInvoice.update({
throw new BadRequestException( where: {
'فاکتور ارسالی قبلا ابطال شده است و امکان ویرایش آن وجود ندارد.', id: invoice_id,
)
}
if (!relatedInvoice.tax_id) {
throw new BadRequestException(
'فاکتور قبلی همچنان در حال بررسی است و امکان ویرایش آن وجود ندارد.',
)
}
const newInvoice = await this.sharedSaleInvoiceCreateService.create({
data: {
customer_type: relatedInvoice.customer?.type || CustomerType.UNKNOWN,
invoice_date: new Date(),
payments: dataToUpdate.payments,
items: dataToUpdate.items,
total_amount: dataToUpdate.total_amount,
discount_amount: dataToUpdate.discount_amount,
tax_amount: dataToUpdate.tax_amount,
customer_id: relatedInvoice.customer_id || undefined,
settlement_type: relatedInvoice.settlement_type,
},
businessId,
complexId,
posId,
consumerAccountId,
main_invoice_id: relatedInvoice.main_id || relatedInvoice.id,
ref_invoice_id: relatedInvoice.id,
type: TspProviderRequestType.CORRECTION,
})
const correctionPayload = await buildCorrectionPayload(tx, newInvoice.id)
const attempt = await tx.saleInvoiceTspAttempts.create({
data: {
attempt_no: 1,
invoice_id: newInvoice.id,
message: 'در حال ارسال به سامانه مالیاتی...',
status: TspProviderResponseStatus.QUEUED,
sent_at: new Date().toISOString(),
raw_request_payload: JSON.parse(JSON.stringify(correctionPayload)),
provider_request_payload: {},
},
})
return [newInvoice, attempt, correctionPayload]
}, },
) data: {
last_tsp_status: TspProviderResponseStatus.QUEUED,
last_attempt_no: attemptNumber,
type: TspProviderRequestType.CORRECTION,
tsp_attempts: {
create: {
attempt_no: attemptNumber,
provider_request_payload: {},
status: TspProviderResponseStatus.QUEUED,
raw_request_payload: JSON.parse(JSON.stringify(payload)),
sent_at: new Date().toISOString(),
message: 'در حال ارسال به سامانه مالیاتی...',
},
},
},
})
const result = await this.runProviderCall(() => const result = await this.tspSwitchService.send(payload)
trySend(this.tspSwitchService, correctionPayload), return await onResult(this.prisma, result, invoice.id)
) }
if (result?.hasError) {
result.provider_request_payload =
result.provider_request_payload || JSON.parse(JSON.stringify(correctionPayload))
result.sent_at = result.sent_at || new Date().toISOString()
result.received_at = result.received_at || new Date().toISOString()
}
return onResult(this.prisma, result, attempt.id) async returnFromSaleSend(
pos_id: string,
business_id: string,
invoice_id: string,
): Promise<TspProviderActionResponseDto> {
const payload = await buildReturnFromSalePayload(this.prisma, invoice_id, pos_id)
// const countByGoodId = (goodIds: string[]): Map<string, number> => { const attemptNumber = 1
// const counts = new Map<string, number>()
// for (const goodId of goodIds) {
// counts.set(goodId, (counts.get(goodId) ?? 0) + 1)
// }
// return counts
// }
// const updatedGoodIds = dataToUpdate.items.map(item => item.good_id!) const invoice = await this.prisma.salesInvoice.update({
// const previousGoodIds = lastAttempt.invoice.items.map(item => item.good_id) where: {
id: invoice_id,
// const updatedCounts = countByGoodId(updatedGoodIds) },
// const previousCounts = countByGoodId(previousGoodIds) data: {
last_tsp_status: TspProviderResponseStatus.QUEUED,
// let isBackFromSale = false last_attempt_no: attemptNumber,
// if (updatedCounts.size !== previousCounts.size) { tsp_attempts: {
// isBackFromSale = true create: {
// } else { attempt_no: attemptNumber,
// for (const [goodId, count] of updatedCounts) { provider_request_payload: {},
// if (previousCounts.get(goodId) !== count) { status: TspProviderResponseStatus.QUEUED,
// isBackFromSale = true raw_request_payload: JSON.parse(JSON.stringify(payload)),
// break sent_at: new Date().toISOString(),
// } message: 'در حال ارسال به سامانه مالیاتی...',
// } },
// } },
},
})
const result = await this.tspSwitchService.returnFromSale(payload)
return await onResult(this.prisma, result, invoice.id)
} }
async revoke( async revoke(
@@ -313,86 +272,87 @@ export class SalesInvoiceTspService {
}) })
if (!relatedInvoice) { if (!relatedInvoice) {
throw new NotFoundException('فاکتور مورد نظر یافت نشد.') throw new NotFoundException('صورت‌حساب مورد نظر یافت نشد.')
} }
if (relatedInvoice.type === TspProviderRequestType.REVOKE) { if (relatedInvoice.type === TspProviderRequestType.REVOKE) {
throw new BadRequestException( throw new BadRequestException(
'فاکتور ارسالی قبلا ابطال شده است و امکان ویرایش آن وجود ندارد.', 'صورت‌حساب ارسالی قبلا ابطال شده است و امکان ویرایش آن وجود ندارد.',
) )
} }
if (!relatedInvoice.tax_id) { if (!relatedInvoice.tax_id) {
throw new BadRequestException( throw new BadRequestException(
'فاکتور قبلی همچنان در حال بررسی است و امکان ویرایش آن وجود ندارد.', 'صورت‌حساب قبلی همچنان در حال بررسی است و امکان ویرایش آن وجود ندارد.',
) )
} }
const payments = relatedInvoice.payments.reduce( // const payments = relatedInvoice.payments.reduce(
(acc, payment) => { // (acc, payment) => {
const amount = Number(payment.amount) // const amount = Number(payment.amount)
switch (payment.payment_method) { // switch (payment.payment_method) {
case 'CASH': // case 'CASH':
acc.cash = (acc.cash || 0) + amount // acc.cash = (acc.cash || 0) + amount
break // break
case 'SET_OFF': // case 'SET_OFF':
acc.set_off = (acc.set_off || 0) + amount // acc.set_off = (acc.set_off || 0) + amount
break // break
case 'CARD': // case 'CARD':
acc.card = (acc.card || 0) + amount // acc.card = (acc.card || 0) + amount
break // break
case 'BANK': // case 'BANK':
acc.bank = (acc.bank || 0) + amount // acc.bank = (acc.bank || 0) + amount
break // break
case 'CHEQUE': // case 'CHEQUE':
acc.check = (acc.check || 0) + amount // acc.check = (acc.check || 0) + amount
break // break
case 'OTHER': // case 'OTHER':
acc.other = (acc.other || 0) + amount // acc.other = (acc.other || 0) + amount
break // break
case 'TERMINAL': // case 'TERMINAL':
acc.terminals = payment.terminal_info // acc.terminals = payment.terminal_info
? { // ? {
amount, // amount,
terminalId: payment.terminal_info.terminal_id, // terminal_id: payment.terminal_info.terminal_id,
stan: payment.terminal_info.stan, // stan: payment.terminal_info.stan,
rrn: payment.terminal_info.rrn, // rrn: payment.terminal_info.rrn,
customer_card_no: // customer_card_no:
payment.terminal_info.customer_card_no || undefined, // payment.terminal_info.customer_card_no || undefined,
transaction_date_time: payment.terminal_info.transaction_date_time, // transaction_date_time: payment.terminal_info.transaction_date_time,
description: payment.terminal_info.description || undefined, // description: payment.terminal_info.description || undefined,
} // }
: acc.terminals // : acc.terminals
break // break
default: // default:
break // break
} // }
return acc // return acc
}, // },
{} as { // {} as {
terminals?: { // terminals?: {
amount?: number // amount?: number
terminalId: string // terminalId: string
stan: string // stan: string
rrn: string // rrn: string
customer_card_no?: string // customer_card_no?: string
transaction_date_time: Date // transaction_date_time: Date
description?: string // description?: string
} // }
cash?: number // cash?: number
set_off?: number // set_off?: number
card?: number // card?: number
bank?: number // bank?: number
check?: number // check?: number
other?: number // other?: number
}, // },
) // )
const newInvoice = await this.sharedSaleInvoiceCreateService.create({ const newInvoice = await this.sharedSaleInvoiceCreateService.create({
data: { data: {
customer_type: relatedInvoice.customer?.type || CustomerType.UNKNOWN, customer_type: relatedInvoice.customer?.type || CustomerType.UNKNOWN,
invoice_date: new Date(), invoice_date: new Date(),
payments, // @ts-ignore
payments: undefined,
settlement_type: relatedInvoice.settlement_type, settlement_type: relatedInvoice.settlement_type,
items: relatedInvoice.items.map(item => ({ items: relatedInvoice.items.map(item => ({
unit_price: Number(item.unit_price), unit_price: Number(item.unit_price),
@@ -226,7 +226,7 @@ export class NamaProviderValidationErrorDto {
} }
export class NamaProviderResponseDto { export class NamaProviderResponseDto {
@ApiProperty({ description: 'شناسه پیگیری فاکتور' }) @ApiProperty({ description: 'شناسه پیگیری صورت‌حساب' })
@IsString() @IsString()
uuid: string uuid: string

Some files were not shown because too many files have changed in this diff Show More