diff --git a/prisma/triggers/dump_triggers.sql b/prisma/triggers/dump_triggers.sql deleted file mode 100644 index 649d5ee..0000000 --- a/prisma/triggers/dump_triggers.sql +++ /dev/null @@ -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; - diff --git a/prisma/triggers/dump_triggers_Backup.sql b/prisma/triggers/dump_triggers_Backup.sql deleted file mode 100644 index 8b84924..0000000 --- a/prisma/triggers/dump_triggers_Backup.sql +++ /dev/null @@ -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; diff --git a/prisma/triggers/stored_procedures.sql b/prisma/triggers/stored_procedures.sql deleted file mode 100644 index c284da1..0000000 --- a/prisma/triggers/stored_procedures.sql +++ /dev/null @@ -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; diff --git a/src/common/queryConstants/saleInvoice.ts b/src/common/queryConstants/saleInvoice.ts index 449336d..5780cc5 100644 --- a/src/common/queryConstants/saleInvoice.ts +++ b/src/common/queryConstants/saleInvoice.ts @@ -73,6 +73,12 @@ export const select: SalesInvoiceSelect = { select: { id: true, name: true, + economic_code: true, + guild: { + select: { + name: true, + }, + }, }, }, }, diff --git a/src/common/services/saleInvoices/sale-invoice-access.service.ts b/src/common/services/saleInvoices/sale-invoice-access.service.ts index 381e588..6c95839 100644 --- a/src/common/services/saleInvoices/sale-invoice-access.service.ts +++ b/src/common/services/saleInvoices/sale-invoice-access.service.ts @@ -21,7 +21,7 @@ export class SharedSaleInvoiceAccessService { }) if (!consumer) { - throw new BadRequestException('شما دسترسی لازم برای ارسال فاکتور را ندارید.') + throw new BadRequestException('شما دسترسی لازم برای ارسال صورت‌حساب را ندارید.') } return consumer.consumer_id diff --git a/src/common/services/saleInvoices/sale-invoice-create.service.ts b/src/common/services/saleInvoices/sale-invoice-create.service.ts index ff7d9fe..ebadcfa 100644 --- a/src/common/services/saleInvoices/sale-invoice-create.service.ts +++ b/src/common/services/saleInvoices/sale-invoice-create.service.ts @@ -109,7 +109,7 @@ export class SharedSaleInvoiceCreateService { } } - throw new BadRequestException('ایجاد فاکتور با خطا مواجه شد.') + throw new BadRequestException('ایجاد صورت‌حساب با خطا مواجه شد.') } private isRetryableInvoiceConflict(error: unknown) { @@ -197,7 +197,7 @@ export class SharedSaleInvoiceCreateService { const roundedTotalAmount = Number(Number(totalAmount).toFixed(2)) if (roundedTotalPayments !== roundedTotalAmount) { - throw new BadRequestException('مبلغ پرداختی باید برابر با مبلغ کل فاکتور باشد.') + throw new BadRequestException('مبلغ پرداختی باید برابر با مبلغ کل صورت‌حساب باشد.') } const terminalPayments = payments.filter( @@ -431,7 +431,7 @@ export class SharedSaleInvoiceCreateService { type !== TspProviderRequestType.ORIGINAL && !(main_invoice_id || ref_invoice_id) ) { - throw new BadRequestException('متاسفانه مشکلی در اطلاعات فاکتور وجود دارد.') + throw new BadRequestException('متاسفانه مشکلی در اطلاعات صورت‌حساب وجود دارد.') } const salesInvoiceData: SalesInvoiceCreateInput = { diff --git a/src/modules/consumer/saleInvoices/saleInvoices.service.ts b/src/modules/consumer/saleInvoices/saleInvoices.service.ts index 0af98b2..430a9d6 100644 --- a/src/modules/consumer/saleInvoices/saleInvoices.service.ts +++ b/src/modules/consumer/saleInvoices/saleInvoices.service.ts @@ -253,7 +253,7 @@ export class SaleInvoicesService { if (invoice) { return ResponseMapper.single(this.invoiceMapper(invoice)) } - throw new NotFoundException('فاکتور مورد نظر شما یافت نشد.') + throw new NotFoundException('صورت‌حساب مورد نظر شما یافت نشد.') } async send(invoiceId: string, posInfo: IPosPayload) { @@ -301,7 +301,7 @@ export class SaleInvoicesService { async sendBulk(consumer_id: string, invoiceIds: string[]) { if (!invoiceIds.length) { - throw new BadRequestException('لیست شناسه فاکتورها نمی‌تواند خالی باشد.') + throw new BadRequestException('لیست شناسه ‌صورت‌حساب‌ها نمی‌تواند خالی باشد.') } await this.salesInvoiceTaxService.sendBulk(consumer_id, invoiceIds) diff --git a/src/modules/pos/sales-invoices/sales-invoices.service.ts b/src/modules/pos/sales-invoices/sales-invoices.service.ts index bb9ec75..9644d91 100644 --- a/src/modules/pos/sales-invoices/sales-invoices.service.ts +++ b/src/modules/pos/sales-invoices/sales-invoices.service.ts @@ -91,7 +91,7 @@ export class SalesInvoicesService { } return ResponseMapper.single(mappedInvoice) - } else throw new NotFoundException('فاکتور مورد نظر شما یافت نشد.') + } else throw new NotFoundException('صورت‌حساب مورد نظر شما یافت نشد.') } async create(data: PosCreateSalesInvoiceDto, posInfo: IPosPayload) { diff --git a/src/modules/tspProviders/sales-invoice-tsp.service.ts b/src/modules/tspProviders/sales-invoice-tsp.service.ts index fa59467..2e42cdc 100644 --- a/src/modules/tspProviders/sales-invoice-tsp.service.ts +++ b/src/modules/tspProviders/sales-invoice-tsp.service.ts @@ -42,20 +42,28 @@ export class SalesInvoiceTspService { 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: { - attempt_no: attemptNumber, - invoice_id, - provider_request_payload: {}, - status: TspProviderResponseStatus.QUEUED, - raw_request_payload: JSON.parse(JSON.stringify(payload)), - sent_at: new Date().toISOString(), - message: 'در حال ارسال به سامانه مالیاتی...', + last_tsp_status: TspProviderResponseStatus.QUEUED, + last_attempt_no: attemptNumber, + 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.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 { @@ -75,18 +83,17 @@ export class SalesInvoiceTspService { pos_id: string, consumer_id: string, ): Promise { - const [attempt, pos] = await this.prisma.$transaction(async tx => [ - await tx.saleInvoiceTspAttempts.findFirst({ + const [invoice, pos] = await this.prisma.$transaction(async tx => [ + await tx.salesInvoice.findUnique({ where: { - invoice_id, - invoice: { - pos: { - id: pos_id, - }, + id: invoice_id, + pos: { + id: pos_id, }, }, - orderBy: { - attempt_no: 'desc', + select: { + last_tsp_status: true, + id: true, }, }), @@ -135,12 +142,25 @@ export class SalesInvoiceTspService { }), ]) - if (!attempt) { - throw new NotFoundException('صورت‌حساب ارسالی فاکتور شما به سامانه یافت نشد.') + if (!invoice) { + throw new NotFoundException('صورت‌حساب ارسالی صورت‌حساب شما به سامانه یافت نشد.') } if (!pos) { 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 @@ -153,7 +173,7 @@ export class SalesInvoiceTspService { business_activity.partner_token, ) - return await onResult(this.prisma, result, attempt.id) + return await onResult(this.prisma, result, invoice.id) } async correctionSend( @@ -282,18 +302,18 @@ export class SalesInvoiceTspService { }) if (!relatedInvoice) { - throw new NotFoundException('فاکتور مورد نظر یافت نشد.') + throw new NotFoundException('صورت‌حساب مورد نظر یافت نشد.') } if (relatedInvoice.type === TspProviderRequestType.REVOKE) { throw new BadRequestException( - 'فاکتور ارسالی قبلا ابطال شده است و امکان ویرایش آن وجود ندارد.', + 'صورت‌حساب ارسالی قبلا ابطال شده است و امکان ویرایش آن وجود ندارد.', ) } if (!relatedInvoice.tax_id) { throw new BadRequestException( - 'فاکتور قبلی همچنان در حال بررسی است و امکان ویرایش آن وجود ندارد.', + 'صورت‌حساب قبلی همچنان در حال بررسی است و امکان ویرایش آن وجود ندارد.', ) } diff --git a/src/modules/tspProviders/switch/nama/dto/common.dto.ts b/src/modules/tspProviders/switch/nama/dto/common.dto.ts index a43f1ae..3087eec 100644 --- a/src/modules/tspProviders/switch/nama/dto/common.dto.ts +++ b/src/modules/tspProviders/switch/nama/dto/common.dto.ts @@ -226,7 +226,7 @@ export class NamaProviderValidationErrorDto { } export class NamaProviderResponseDto { - @ApiProperty({ description: 'شناسه پیگیری فاکتور' }) + @ApiProperty({ description: 'شناسه پیگیری صورت‌حساب' }) @IsString() uuid: string diff --git a/src/modules/tspProviders/switch/nama/dto/revoke.dto.ts b/src/modules/tspProviders/switch/nama/dto/revoke.dto.ts index 075fb89..4851fa7 100644 --- a/src/modules/tspProviders/switch/nama/dto/revoke.dto.ts +++ b/src/modules/tspProviders/switch/nama/dto/revoke.dto.ts @@ -21,7 +21,7 @@ export class NamaProviderRevokeHeaderDto { @ApiProperty({ required: true, - description: 'آخرین شماره مالیاتی دریافت شده مربوط به فاکتور', + description: 'آخرین شماره مالیاتی دریافت شده مربوط به صورت‌حساب', }) @IsString() irtaxid: string diff --git a/src/modules/tspProviders/utils/sales-invoice-tsp.utils.ts b/src/modules/tspProviders/utils/sales-invoice-tsp.utils.ts index 8172deb..f627ff8 100644 --- a/src/modules/tspProviders/utils/sales-invoice-tsp.utils.ts +++ b/src/modules/tspProviders/utils/sales-invoice-tsp.utils.ts @@ -23,44 +23,46 @@ export async function getOriginalResendAttemptNumber( ): Promise { let attemptNumber = 1 - const existingAttempt = await prisma.saleInvoiceTspAttempts.findFirst({ + const invoice = await prisma.salesInvoice.findFirst({ where: { - invoice_id, + id: invoice_id, }, - include: { - invoice: { - select: { - type: true, - }, - }, + select: { + type: true, + last_attempt_no: true, + last_tsp_status: true, }, orderBy: { created_at: 'desc', }, }) - if (existingAttempt) { - attemptNumber = existingAttempt.attempt_no + 1 - if (existingAttempt.invoice.type !== TspProviderRequestType.ORIGINAL) { + if (invoice) { + const { last_attempt_no, type, last_tsp_status } = invoice + attemptNumber = (last_attempt_no ?? 0) + 1 + + if (type !== TspProviderRequestType.ORIGINAL) { throw new BadRequestException( - 'فقط فاکتورهای اصلی قابل ارسال مجدد به سامانه مالیاتی هستند.', + 'فقط ‌صورت‌حساب‌های اصلی قابل ارسال مجدد به سامانه مالیاتی هستند.', ) } - if (existingAttempt.status === TspProviderResponseStatus.SUCCESS) { + if (last_tsp_status === TspProviderResponseStatus.SUCCESS) { throw new BadRequestException( - 'فاکتور تایید شده از طرف سازمان مالیاتی قابل ارسال مجدد نیست.', + 'صورت‌حساب تایید شده از طرف سازمان مالیاتی قابل ارسال مجدد نیست.', ) } - if ( - existingAttempt.status === TspProviderResponseStatus.QUEUED || - existingAttempt.status === TspProviderResponseStatus.FISCAL_QUEUED - ) { + if (last_tsp_status === TspProviderResponseStatus.QUEUED) { throw new BadRequestException( - 'در حال حاضر فاکتور شما در حال بررسی توسط سازمان مالیاتی است.', + 'در حال حاضر صورت‌حساب شما در صف ارسال به سازمان مالیاتی است.', ) } - } + if (last_tsp_status === TspProviderResponseStatus.FISCAL_QUEUED) { + throw new BadRequestException( + 'در حال حاضر صورت‌حساب شما در حال بررسی توسط سازمان مالیاتی است.', + ) + } + } else throw new NotFoundException('صورت‌حساب مورد نظر یافت نشد.') return attemptNumber } @@ -138,7 +140,7 @@ export async function buildRevokePayload( }) if (!invoice) { - throw new NotFoundException('فاکتور مورد نظر یافت نشد.') + throw new NotFoundException('صورت‌حساب مورد نظر یافت نشد.') } const { partner } = (invoice.pos.complex.business_activity.consumer.legal || @@ -425,7 +427,7 @@ export async function buildOriginalPayload( }) if (!invoice) { - throw new NotFoundException('فاکتور مورد نظر یافت نشد.') + throw new NotFoundException('صورت‌حساب مورد نظر یافت نشد.') } const { @@ -552,12 +554,12 @@ export async function getRelatedInvoiceForModification( }) if (!relatedInvoice) { - throw new NotFoundException('فاکتور مورد نظر یافت نشد.') + throw new NotFoundException('صورت‌حساب مورد نظر یافت نشد.') } if (relatedInvoice.type === TspProviderRequestType.REVOKE) { throw new BadRequestException( - 'فاکتور ارسالی قبلا ابطال شده است و امکان ویرایش آن وجود ندارد.', + 'صورت‌حساب ارسالی قبلا ابطال شده است و امکان ویرایش آن وجود ندارد.', ) } @@ -566,7 +568,7 @@ export async function getRelatedInvoiceForModification( relatedInvoice.tsp_attempts?.[0].status !== TspProviderResponseStatus.SUCCESS ) { throw new BadRequestException( - 'فاکتور قبلی همچنان در حال بررسی است و امکان اصلاح آن وجود ندارد.', + 'صورت‌حساب قبلی همچنان در حال بررسی است و امکان اصلاح آن وجود ندارد.', ) } @@ -587,11 +589,11 @@ export async function trySend( export async function onResult( prisma: PrismaService, result: TspProviderOriginalResponseDto | TspProviderGetResponseDto, - attempt_id: string, + invoice_id: string, ): Promise { let attemptUpdatedData: SaleInvoiceTspAttemptsUpdateInput = {} - console.log('attempt', result, attempt_id) + console.log('attempt', result) const resultMessage = result.message @@ -606,7 +608,7 @@ export async function onResult( ? resultMessage : result.hasError ? 'وجود مشکل در ارسال به سامانه مالیاتی' - : 'فاکتور با موفقیت به سامانه مالیاتی ارسال شد.', + : 'صورت‌حساب با موفقیت به سامانه مالیاتی ارسال شد.', invoice: { update: { tax_id: result['tax_id'] ? result['tax_id'] : undefined, @@ -633,26 +635,37 @@ export async function onResult( attemptUpdatedData = { status: TspProviderResponseStatus.SEND_FAILURE, message: - 'متاسفانه امکان ارسال فاکتور به سیستم مالیاتی در حال حاضر وجود ندارد. لطفا بعدا تلاش کنید.', + 'متاسفانه امکان ارسال صورت‌حساب به سیستم مالیاتی در حال حاضر وجود ندارد. لطفا بعدا تلاش کنید.', received_at: new Date().toISOString(), } } - const updatedAttempt = await prisma.saleInvoiceTspAttempts.update({ - where: { - id: attempt_id, - }, - data: attemptUpdatedData, - select: { - status: true, - invoice: true, - message: true, - }, + const invoice = await prisma.$transaction(async tx => { + const lastAttempt = await tx.saleInvoiceTspAttempts.findFirst({ + where: { invoice_id }, + orderBy: { attempt_no: 'desc' }, + select: { id: true }, + }) + + if (!lastAttempt) throw new NotFoundException('صورت‌حساب مورد نظر یافت نشد.') + + await tx.saleInvoiceTspAttempts.update({ + where: { id: lastAttempt.id }, + data: attemptUpdatedData, + }) + + const updatedInvoice = await tx.salesInvoice.update({ + where: { id: invoice_id }, + data: { + last_tsp_status: attemptUpdatedData.status, + }, + }) + return updatedInvoice }) return { - invoice: updatedAttempt.invoice, - status: updatedAttempt.status, - message: updatedAttempt.message, + invoice, + status: attemptUpdatedData.status as TspProviderResponseStatus, + message: attemptUpdatedData.message as string, } }