refactor: restructure purchase receipts module and related workflows
- Removed old DTOs for creating and updating purchase receipts. - Updated purchase receipts controller and service to use new DTOs and workflows. - Introduced transaction helper for managing database transactions. - Added new workflows for handling purchase receipt payments and supplier ledgers. - Implemented new logic for managing purchase receipt items and payments. - Enhanced error handling for payment processing in workflows. - Updated supplier ledger management to reflect changes in purchase receipts.
This commit is contained in:
+111
-380
@@ -1,34 +1,19 @@
|
|||||||
-- AUTO-GENERATED MYSQL TRIGGER DUMP
|
-- AUTO-GENERATED MYSQL TRIGGER DUMP
|
||||||
-- Generated at: 2026-01-04T09:46:30.365Z
|
-- Generated at: 2026-01-04T17:29:18.092Z
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 1
|
-- 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
|
-- Trigger: trg_bank_account_transaction_after_delete
|
||||||
-- Event: DELETE
|
-- Event: DELETE
|
||||||
-- Table: Bank_Account_Transactions
|
-- Table: Bank_Account_Transactions
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
DROP TRIGGER IF EXISTS `trg_bank_account_transaction_after_delete`;
|
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
|
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;
|
UPDATE `Bank_Account_Balance` SET balance = balance - OLD.amount WHERE `bankAccountId` = OLD.bankAccountId;
|
||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 3
|
-- index: 2
|
||||||
-- Trigger: trg_transfer_item_after_insert
|
-- Trigger: trg_transfer_item_after_insert
|
||||||
-- Event: INSERT
|
-- Event: INSERT
|
||||||
-- Table: Inventory_Transfer_Items
|
-- Table: Inventory_Transfer_Items
|
||||||
@@ -66,7 +51,7 @@ DECLARE fromInv INT;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 4
|
-- index: 3
|
||||||
-- Trigger: trg_order_item_after_insert
|
-- Trigger: trg_order_item_after_insert
|
||||||
-- Event: INSERT
|
-- Event: INSERT
|
||||||
-- Table: Order_Items
|
-- Table: Order_Items
|
||||||
@@ -78,7 +63,7 @@ CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_insert` AFTER INSERT ON `
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 5
|
-- index: 4
|
||||||
-- Trigger: trg_order_item_after_update
|
-- Trigger: trg_order_item_after_update
|
||||||
-- Event: UPDATE
|
-- Event: UPDATE
|
||||||
-- Table: Order_Items
|
-- Table: Order_Items
|
||||||
@@ -91,7 +76,7 @@ CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_update` AFTER UPDATE ON `
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 6
|
-- index: 5
|
||||||
-- Trigger: trg_order_item_after_delete
|
-- Trigger: trg_order_item_after_delete
|
||||||
-- Event: DELETE
|
-- Event: DELETE
|
||||||
-- Table: Order_Items
|
-- Table: Order_Items
|
||||||
@@ -104,7 +89,7 @@ CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_delete` AFTER DELETE ON `
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 7
|
-- index: 6
|
||||||
-- Trigger: trg_order_after_cancel
|
-- Trigger: trg_order_after_cancel
|
||||||
-- Event: UPDATE
|
-- Event: UPDATE
|
||||||
-- Table: Orders
|
-- Table: Orders
|
||||||
@@ -118,7 +103,7 @@ CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_after_cancel` AFTER UPDATE ON `Order
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 8
|
-- index: 7
|
||||||
-- Trigger: trg_purchase_receipt_item_after_insert
|
-- Trigger: trg_purchase_receipt_item_after_insert
|
||||||
-- Event: INSERT
|
-- Event: INSERT
|
||||||
-- Table: Purchase_Receipt_Items
|
-- Table: Purchase_Receipt_Items
|
||||||
@@ -181,222 +166,7 @@ DECLARE invId INT;
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 9
|
-- index: 8
|
||||||
-- 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
|
-- Trigger: trg_pr_payment_after_delete
|
||||||
-- Event: DELETE
|
-- Event: DELETE
|
||||||
-- Table: Purchase_Receipt_Payments
|
-- Table: Purchase_Receipt_Payments
|
||||||
@@ -431,46 +201,7 @@ CREATE DEFINER=`pos`@`%` TRIGGER `trg_pr_payment_after_delete` AFTER DELETE ON `
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 14
|
-- index: 9
|
||||||
-- 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
|
-- Trigger: trg_sales_invoice_items_before_insert
|
||||||
-- Event: INSERT
|
-- Event: INSERT
|
||||||
-- Table: Sales_Invoice_Items
|
-- Table: Sales_Invoice_Items
|
||||||
@@ -503,7 +234,7 @@ CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_items_before_insert` BEFORE
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 16
|
-- index: 10
|
||||||
-- Trigger: trg_sales_invoice_items_after_insert
|
-- Trigger: trg_sales_invoice_items_after_insert
|
||||||
-- Event: INSERT
|
-- Event: INSERT
|
||||||
-- Table: Sales_Invoice_Items
|
-- Table: Sales_Invoice_Items
|
||||||
@@ -576,7 +307,43 @@ DECLARE pos_id INT;
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 17
|
-- index: 11
|
||||||
|
-- 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: 12
|
||||||
-- Trigger: trg_sales_invoice_payment_after_insert
|
-- Trigger: trg_sales_invoice_payment_after_insert
|
||||||
-- Event: INSERT
|
-- Event: INSERT
|
||||||
-- Table: Sales_Invoice_Payments
|
-- Table: Sales_Invoice_Payments
|
||||||
@@ -615,43 +382,77 @@ CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_payment_after_insert` AFTER
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 18
|
-- index: 13
|
||||||
-- Trigger: trg_pos_account_payment_after_insert
|
-- Trigger: trg_stock_sale_insert
|
||||||
-- Event: INSERT
|
-- Event: INSERT
|
||||||
-- Table: Sales_Invoice_Payments
|
-- Table: Stock_Movements
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
DROP TRIGGER IF EXISTS `trg_pos_account_payment_after_insert`;
|
DROP TRIGGER IF EXISTS `trg_stock_sale_insert`;
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pos_account_payment_after_insert` AFTER INSERT ON `Sales_Invoice_Payments` FOR EACH ROW BEGIN
|
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_sale_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'SALES' THEN
|
||||||
|
|
||||||
DECLARE _bankAccountId INT;
|
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;
|
||||||
|
|
||||||
IF(NEW.paymentMethod != 'CASH') THEN
|
END IF;
|
||||||
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;
|
END;
|
||||||
|
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- index: 19
|
-- index: 14
|
||||||
|
-- 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: 15
|
||||||
-- Trigger: trg_stock_transfer
|
-- Trigger: trg_stock_transfer
|
||||||
-- Event: INSERT
|
-- Event: INSERT
|
||||||
-- Table: Stock_Movements
|
-- Table: Stock_Movements
|
||||||
@@ -733,73 +534,3 @@ END IF;
|
|||||||
|
|
||||||
END;
|
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;
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,31 @@
|
|||||||
-- Stored Procedures equivalent to triggers
|
-- Stored Procedures equivalent to triggers
|
||||||
|
|
||||||
DELIMITER //
|
DELIMITER / /
|
||||||
|
|
||||||
-- Procedure for trg_bank_account_transaction_after_insert
|
-- 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))
|
CREATE PROCEDURE update_bank_balance(IN p_bankAccountId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2))
|
||||||
BEGIN
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
IF p_type = 'DEPOSIT' THEN
|
IF p_type = 'DEPOSIT' THEN
|
||||||
UPDATE Bank_Account_Balance SET balance = balance + p_amount WHERE bankAccountId = p_bankAccountId;
|
UPDATE Bank_Account_Balance SET balance = balance + p_amount WHERE bankAccountId = p_bankAccountId;
|
||||||
ELSEIF p_type = 'WITHDRAWAL' THEN
|
ELSEIF p_type = 'WITHDRAWAL' THEN
|
||||||
UPDATE Bank_Account_Balance SET balance = balance - p_amount WHERE bankAccountId = p_bankAccountId;
|
UPDATE Bank_Account_Balance SET balance = balance - p_amount WHERE bankAccountId = p_bankAccountId;
|
||||||
END IF;
|
END IF;
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_bank_account_transaction_after_delete
|
-- 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))
|
CREATE PROCEDURE update_bank_balance_on_delete(IN p_bankAccountId INT, IN p_amount DECIMAL(15,2))
|
||||||
BEGIN
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
UPDATE Bank_Accounts SET balance = balance - p_amount WHERE id = p_bankAccountId;
|
UPDATE Bank_Accounts SET balance = balance - p_amount WHERE id = p_bankAccountId;
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_transfer_item_after_insert
|
-- 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))
|
CREATE PROCEDURE process_transfer_item(IN p_transferId INT, IN p_productId INT, IN p_count DECIMAL(10,2))
|
||||||
BEGIN
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
DECLARE fromInv INT;
|
DECLARE fromInv INT;
|
||||||
DECLARE toInv INT;
|
DECLARE toInv INT;
|
||||||
DECLARE _avgCost DECIMAL(10,2);
|
DECLARE _avgCost DECIMAL(10,2);
|
||||||
@@ -47,42 +52,52 @@ BEGIN
|
|||||||
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
|
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
|
||||||
VALUES
|
VALUES
|
||||||
('IN', p_count, _avgCost, _avgCost*p_count, _avgCost, 'INVENTORY_TRANSFER', p_transferId, p_productId, toInv, fromInv, NOW(), latestQuantityInOrigin-p_count);
|
('IN', p_count, _avgCost, _avgCost*p_count, _avgCost, 'INVENTORY_TRANSFER', p_transferId, p_productId, toInv, fromInv, NOW(), latestQuantityInOrigin-p_count);
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_order_item_after_insert
|
-- 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))
|
CREATE PROCEDURE update_stock_reservation_insert(IN p_orderId INT, IN p_productId INT, IN p_quantity DECIMAL(10,2))
|
||||||
BEGIN
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
UPDATE Stock_Reservations SET quantity = quantity + p_quantity
|
UPDATE Stock_Reservations SET quantity = quantity + p_quantity
|
||||||
WHERE orderId = p_orderId AND productId = p_productId;
|
WHERE orderId = p_orderId AND productId = p_productId;
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_order_item_after_update
|
-- 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))
|
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
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
UPDATE Stock_Reservations
|
UPDATE Stock_Reservations
|
||||||
SET quantity = quantity - p_old_quantity + p_new_quantity
|
SET quantity = quantity - p_old_quantity + p_new_quantity
|
||||||
WHERE orderId = p_orderId AND productId = p_productId;
|
WHERE orderId = p_orderId AND productId = p_productId;
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_order_item_after_delete
|
-- 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))
|
CREATE PROCEDURE update_stock_reservation_delete(IN p_orderId INT, IN p_productId INT, IN p_quantity DECIMAL(10,2))
|
||||||
BEGIN
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
UPDATE Stock_Reservations SET quantity = quantity - p_quantity
|
UPDATE Stock_Reservations SET quantity = quantity - p_quantity
|
||||||
WHERE orderId = p_orderId AND productId = p_productId;
|
WHERE orderId = p_orderId AND productId = p_productId;
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_order_after_cancel
|
-- Procedure for trg_order_after_cancel
|
||||||
CREATE PROCEDURE cancel_order_stock(IN p_orderId INT, IN p_status VARCHAR(20))
|
CREATE PROCEDURE cancel_order_stock(IN p_orderId INT, IN p_status VARCHAR(20))
|
||||||
BEGIN
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
IF p_status = 'CANCELED' OR p_status = 'REJECTED' OR p_status = 'DONE' THEN
|
IF p_status = 'CANCELED' OR p_status = 'REJECTED' OR p_status = 'DONE' THEN
|
||||||
UPDATE Stock_Reservations sr SET quantity = 0
|
UPDATE Stock_Reservations sr SET quantity = 0
|
||||||
WHERE sr.orderId = p_orderId;
|
WHERE sr.orderId = p_orderId;
|
||||||
END IF;
|
END IF;
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_purchase_receipt_item_after_insert
|
-- 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))
|
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
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
DECLARE latestQuantity DECIMAL(10, 2) DEFAULT 0;
|
DECLARE latestQuantity DECIMAL(10, 2) DEFAULT 0;
|
||||||
DECLARE invId INT;
|
DECLARE invId INT;
|
||||||
DECLARE suppId INT;
|
DECLARE suppId INT;
|
||||||
@@ -133,11 +148,13 @@ BEGIN
|
|||||||
latestQuantity + p_count,
|
latestQuantity + p_count,
|
||||||
NOW()
|
NOW()
|
||||||
);
|
);
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_pr_payment_before_insert
|
-- 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))
|
CREATE PROCEDURE validate_payment_before_insert(IN p_receiptId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2))
|
||||||
BEGIN
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
DECLARE receiptTotal DECIMAL(14,2);
|
DECLARE receiptTotal DECIMAL(14,2);
|
||||||
DECLARE paid DECIMAL(14,2);
|
DECLARE paid DECIMAL(14,2);
|
||||||
|
|
||||||
@@ -151,11 +168,13 @@ BEGIN
|
|||||||
SIGNAL SQLSTATE '45000'
|
SIGNAL SQLSTATE '45000'
|
||||||
SET MESSAGE_TEXT = 'مجموع مبلغ پرداختی بیشتر از مبلغ فاکتور است.';
|
SET MESSAGE_TEXT = 'مجموع مبلغ پرداختی بیشتر از مبلغ فاکتور است.';
|
||||||
END IF;
|
END IF;
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_purchase_payment_update_receipt
|
-- Procedure for trg_purchase_payment_update_receipt
|
||||||
CREATE PROCEDURE update_receipt_payment(IN p_receiptId INT)
|
CREATE PROCEDURE update_receipt_payment(IN p_receiptId INT)
|
||||||
BEGIN
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
DECLARE paid DECIMAL(15,2);
|
DECLARE paid DECIMAL(15,2);
|
||||||
DECLARE total DECIMAL(15,2);
|
DECLARE total DECIMAL(15,2);
|
||||||
|
|
||||||
@@ -180,11 +199,13 @@ BEGIN
|
|||||||
ELSE 'PAID'
|
ELSE 'PAID'
|
||||||
END
|
END
|
||||||
WHERE id = p_receiptId;
|
WHERE id = p_receiptId;
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_purchase_payment_after_insert
|
-- 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)
|
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
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
DECLARE currentBalance DECIMAL(15, 2);
|
DECLARE currentBalance DECIMAL(15, 2);
|
||||||
|
|
||||||
SELECT balance INTO currentBalance
|
SELECT balance INTO currentBalance
|
||||||
@@ -237,11 +258,13 @@ BEGIN
|
|||||||
UPDATE Bank_Account_Balance
|
UPDATE Bank_Account_Balance
|
||||||
SET balance = currentBalance
|
SET balance = currentBalance
|
||||||
WHERE bankAccountId = p_bankAccountId;
|
WHERE bankAccountId = p_bankAccountId;
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_pr_payment_after_insert
|
-- 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)
|
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
|
BEGIN
|
||||||
|
START TRANSACTION;
|
||||||
DECLARE receiptTotal DECIMAL(14,2) DEFAULT 0;
|
DECLARE receiptTotal DECIMAL(14,2) DEFAULT 0;
|
||||||
DECLARE newPaid DECIMAL(14,2) DEFAULT 0;
|
DECLARE newPaid DECIMAL(14,2) DEFAULT 0;
|
||||||
DECLARE _supplierId INT;
|
DECLARE _supplierId INT;
|
||||||
@@ -304,6 +327,7 @@ BEGIN
|
|||||||
p_id,
|
p_id,
|
||||||
NOW()
|
NOW()
|
||||||
);
|
);
|
||||||
|
COMMIT;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
-- Procedure for trg_pr_payment_after_delete
|
-- Procedure for trg_pr_payment_after_delete
|
||||||
@@ -630,4 +654,4 @@ BEGIN
|
|||||||
avgCost = totalCost / quantity;
|
avgCost = totalCost / quantity;
|
||||||
END //
|
END //
|
||||||
|
|
||||||
DELIMITER ;
|
DELIMITER;
|
||||||
|
|||||||
+1
-5
@@ -11,7 +11,7 @@ import { BanksModule } from './modules/banks/banks.module'
|
|||||||
import { CardexModule } from './modules/cardex/cardex.module'
|
import { CardexModule } from './modules/cardex/cardex.module'
|
||||||
import { InventoriesModule } from './modules/inventories/inventories.module'
|
import { InventoriesModule } from './modules/inventories/inventories.module'
|
||||||
import { PosModule } from './modules/pos/pos.module'
|
import { PosModule } from './modules/pos/pos.module'
|
||||||
import { PurchaseReceiptPaymentsModule } from './modules/purchase-receipt-payments/purchase-receipt-payments.module'
|
import { PurchaseReceiptsModule } from './modules/purchase-receipts/purchase-receipts.module'
|
||||||
import { StatisticsModule } from './modules/statistics/statistics.module'
|
import { StatisticsModule } from './modules/statistics/statistics.module'
|
||||||
import { SuppliersModule } from './modules/suppliers/suppliers.module'
|
import { SuppliersModule } from './modules/suppliers/suppliers.module'
|
||||||
import { PrismaModule } from './prisma/prisma.module'
|
import { PrismaModule } from './prisma/prisma.module'
|
||||||
@@ -19,8 +19,6 @@ import { ProductBrandsModule } from './product-brands/product-brands.module'
|
|||||||
import { ProductCategoriesModule } from './product-categories/product-categories.module'
|
import { ProductCategoriesModule } from './product-categories/product-categories.module'
|
||||||
import { ProductVariantsModule } from './product-variants/product-variants.module'
|
import { ProductVariantsModule } from './product-variants/product-variants.module'
|
||||||
import { ProductsModule } from './products/products.module'
|
import { ProductsModule } from './products/products.module'
|
||||||
import { PurchaseReceiptItemsModule } from './purchase-receipt-items/purchase-receipt-items.module'
|
|
||||||
import { PurchaseReceiptsModule } from './purchase-receipts/purchase-receipts.module'
|
|
||||||
import { RolesModule } from './roles/roles.module'
|
import { RolesModule } from './roles/roles.module'
|
||||||
import { SalesInvoiceItemsModule } from './sales-invoice-items/sales-invoice-items.module'
|
import { SalesInvoiceItemsModule } from './sales-invoice-items/sales-invoice-items.module'
|
||||||
import { SalesInvoicesModule } from './sales-invoices/sales-invoices.module'
|
import { SalesInvoicesModule } from './sales-invoices/sales-invoices.module'
|
||||||
@@ -43,8 +41,6 @@ import { UsersModule } from './users/users.module'
|
|||||||
CustomersModule,
|
CustomersModule,
|
||||||
InventoriesModule,
|
InventoriesModule,
|
||||||
PurchaseReceiptsModule,
|
PurchaseReceiptsModule,
|
||||||
PurchaseReceiptItemsModule,
|
|
||||||
PurchaseReceiptPaymentsModule,
|
|
||||||
SalesInvoicesModule,
|
SalesInvoicesModule,
|
||||||
SalesInvoiceItemsModule,
|
SalesInvoiceItemsModule,
|
||||||
InventoryTransfersModule,
|
InventoryTransfersModule,
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// src/common/database/transaction.helper.ts
|
||||||
|
import { PrismaService } from '../../prisma/prisma.service'
|
||||||
|
|
||||||
|
export async function withTransaction<T>(
|
||||||
|
prisma: PrismaService,
|
||||||
|
fn: (tx: PrismaService) => Promise<T>,
|
||||||
|
): Promise<T> {
|
||||||
|
return prisma.$transaction(async tx => {
|
||||||
|
return fn(tx as PrismaService)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -2,10 +2,12 @@ import { Module } from '@nestjs/common'
|
|||||||
import { PrismaModule } from '../../prisma/prisma.module'
|
import { PrismaModule } from '../../prisma/prisma.module'
|
||||||
import { BankAccountsController } from './bank-accounts.controller'
|
import { BankAccountsController } from './bank-accounts.controller'
|
||||||
import { BankAccountsService } from './bank-accounts.service'
|
import { BankAccountsService } from './bank-accounts.service'
|
||||||
|
import { BankAccountsWorkflow } from './bank-accounts.workflow'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [PrismaModule],
|
imports: [PrismaModule],
|
||||||
controllers: [BankAccountsController],
|
controllers: [BankAccountsController],
|
||||||
providers: [BankAccountsService],
|
providers: [BankAccountsService, BankAccountsWorkflow],
|
||||||
|
exports: [BankAccountsWorkflow],
|
||||||
})
|
})
|
||||||
export class BankAccountsModule {}
|
export class BankAccountsModule {}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { withTransaction } from '../../common/database/transaction.helper'
|
||||||
import { ResponseMapper } from '../../common/response/response-mapper'
|
import { ResponseMapper } from '../../common/response/response-mapper'
|
||||||
import { PrismaService } from '../../prisma/prisma.service'
|
import { PrismaService } from '../../prisma/prisma.service'
|
||||||
|
|
||||||
@@ -6,8 +7,16 @@ import { PrismaService } from '../../prisma/prisma.service'
|
|||||||
export class BankAccountsService {
|
export class BankAccountsService {
|
||||||
constructor(private prisma: PrismaService) {}
|
constructor(private prisma: PrismaService) {}
|
||||||
async create(data: any) {
|
async create(data: any) {
|
||||||
const item = await this.prisma.bankAccount.create({ data })
|
return withTransaction(this.prisma, async tx => {
|
||||||
return ResponseMapper.create(item)
|
const item = await tx.bankAccount.create({ data })
|
||||||
|
await tx.bankAccountBalance.create({
|
||||||
|
data: {
|
||||||
|
bankAccountId: item.id,
|
||||||
|
balance: 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ResponseMapper.create(item)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll() {
|
async findAll() {
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { Prisma } from '../../generated/prisma/client'
|
||||||
|
import { AddTransactionToBankAccountDto } from './dto/add-transaction.dto'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BankAccountsWorkflow {
|
||||||
|
async addTransaction(
|
||||||
|
tx: Prisma.TransactionClient,
|
||||||
|
payload: AddTransactionToBankAccountDto,
|
||||||
|
) {
|
||||||
|
const item = await tx.bankAccountBalance.findUnique({
|
||||||
|
where: {
|
||||||
|
bankAccountId: payload.bankAccountId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const balance = item ? Number(item.balance) : 0
|
||||||
|
|
||||||
|
const newBalance = item
|
||||||
|
? payload.type === 'DEPOSIT'
|
||||||
|
? balance + payload.amount
|
||||||
|
: balance - payload.amount
|
||||||
|
: payload.type === 'DEPOSIT'
|
||||||
|
? payload.amount
|
||||||
|
: -payload.amount
|
||||||
|
|
||||||
|
await tx.bankAccountTransaction.create({
|
||||||
|
data: {
|
||||||
|
bankAccount: { connect: { id: payload.bankAccountId } },
|
||||||
|
amount: payload.amount,
|
||||||
|
type: payload.type,
|
||||||
|
balanceAfter: newBalance,
|
||||||
|
|
||||||
|
referenceId: payload.referenceId,
|
||||||
|
referenceType: payload.referenceType,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('first')
|
||||||
|
|
||||||
|
const bankAccountBalanceItem = await tx.bankAccountBalance.findUnique({
|
||||||
|
where: {
|
||||||
|
bankAccountId: payload.bankAccountId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!bankAccountBalanceItem) {
|
||||||
|
return await tx.bankAccountBalance.create({
|
||||||
|
data: {
|
||||||
|
bankAccount: { connect: { id: payload.bankAccountId } },
|
||||||
|
balance: newBalance,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return await tx.bankAccountBalance.update({
|
||||||
|
where: {
|
||||||
|
bankAccountId: payload.bankAccountId,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
balance: newBalance,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { IsEnum, IsInt } from 'class-validator'
|
||||||
|
import {
|
||||||
|
BankAccountTransactionType,
|
||||||
|
BankTransactionRefType,
|
||||||
|
} from '../../../generated/prisma/enums'
|
||||||
|
|
||||||
|
export class AddTransactionToBankAccountDto {
|
||||||
|
@IsInt()
|
||||||
|
bankAccountId: number
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
amount: number
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
referenceId: number
|
||||||
|
|
||||||
|
@IsEnum(BankTransactionRefType)
|
||||||
|
referenceType: BankTransactionRefType
|
||||||
|
|
||||||
|
@IsEnum(BankAccountTransactionType)
|
||||||
|
type: BankAccountTransactionType
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common'
|
|
||||||
|
|
||||||
import { PrismaModule } from '../../prisma/prisma.module'
|
|
||||||
import { PurchaseReceiptPaymentsController } from './purchase-receipt-payments.controller'
|
|
||||||
import { PurchaseReceiptPaymentsService } from './purchase-receipt-payments.service'
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [PrismaModule],
|
|
||||||
controllers: [PurchaseReceiptPaymentsController],
|
|
||||||
providers: [PurchaseReceiptPaymentsService],
|
|
||||||
})
|
|
||||||
export class PurchaseReceiptPaymentsModule {}
|
|
||||||
+26
-12
@@ -1,12 +1,17 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
import { ResponseMapper } from '../common/response/response-mapper'
|
import { withTransaction } from '../../../common/database/transaction.helper'
|
||||||
import { Prisma } from '../generated/prisma/client'
|
import { ResponseMapper } from '../../../common/response/response-mapper'
|
||||||
import { PrismaService } from '../prisma/prisma.service'
|
import { Prisma } from '../../../generated/prisma/client'
|
||||||
|
import { PrismaService } from '../../../prisma/prisma.service'
|
||||||
import { CreatePurchaseReceiptDto } from './dto/create-purchase-receipt.dto'
|
import { CreatePurchaseReceiptDto } from './dto/create-purchase-receipt.dto'
|
||||||
|
import { PurchaseReceiptWorkflow } from './purchase-receipts.workflow'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PurchaseReceiptsService {
|
export class PurchaseReceiptsService {
|
||||||
constructor(private prisma: PrismaService) {}
|
constructor(
|
||||||
|
private prisma: PrismaService,
|
||||||
|
private purchaseReceiptWorkflow: PurchaseReceiptWorkflow,
|
||||||
|
) {}
|
||||||
|
|
||||||
async create(dto: CreatePurchaseReceiptDto) {
|
async create(dto: CreatePurchaseReceiptDto) {
|
||||||
const data: Prisma.PurchaseReceiptCreateInput = {
|
const data: Prisma.PurchaseReceiptCreateInput = {
|
||||||
@@ -31,15 +36,24 @@ export class PurchaseReceiptsService {
|
|||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
}
|
}
|
||||||
const item = await this.prisma.purchaseReceipt.create({
|
|
||||||
data,
|
return withTransaction(this.prisma, async tx => {
|
||||||
include: { items: true },
|
const item = await tx.purchaseReceipt.create({
|
||||||
omit: {
|
data,
|
||||||
supplierId: true,
|
include: { items: true },
|
||||||
inventoryId: true,
|
omit: {
|
||||||
},
|
supplierId: true,
|
||||||
|
inventoryId: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await this.purchaseReceiptWorkflow.onCreatePurchaseReceipt(
|
||||||
|
tx,
|
||||||
|
dto.supplierId,
|
||||||
|
dto.totalAmount,
|
||||||
|
item.id,
|
||||||
|
)
|
||||||
|
return ResponseMapper.create(item)
|
||||||
})
|
})
|
||||||
return ResponseMapper.create(item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll() {
|
async findAll() {
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { Prisma } from '../../../generated/prisma/client'
|
||||||
|
import { SupplierLedgerWorkflow } from '../../suppliers/ledger/supplier-ledger.workflow'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PurchaseReceiptWorkflow {
|
||||||
|
constructor(private supplierLedgerWorkflow: SupplierLedgerWorkflow) {}
|
||||||
|
|
||||||
|
async onCreatePurchaseReceipt(
|
||||||
|
tx: Prisma.TransactionClient,
|
||||||
|
supplierId: number,
|
||||||
|
amount: number,
|
||||||
|
sourceId: number,
|
||||||
|
) {
|
||||||
|
await this.supplierLedgerWorkflow.updateLedgerBalance(
|
||||||
|
tx,
|
||||||
|
supplierId,
|
||||||
|
amount,
|
||||||
|
sourceId,
|
||||||
|
'PURCHASE',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
import { PrismaModule } from '../prisma/prisma.module'
|
import { PrismaModule } from '../../../prisma/prisma.module'
|
||||||
import { PurchaseReceiptItemsController } from './purchase-receipt-items.controller'
|
import { PurchaseReceiptItemsController } from './purchase-receipt-items.controller'
|
||||||
import { PurchaseReceiptItemsService } from './purchase-receipt-items.service'
|
import { PurchaseReceiptItemsService } from './purchase-receipt-items.service'
|
||||||
|
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
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 { PrismaService } from '../prisma/prisma.service'
|
import { PrismaService } from '../../../prisma/prisma.service'
|
||||||
import { CreatePurchaseReceiptItemDto } from './dto/create-purchase-receipt-item.dto'
|
import { CreatePurchaseReceiptItemDto } from './dto/create-purchase-receipt-item.dto'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import { IsEnum, IsInt, IsNumber, IsOptional, IsString } from 'class-validator'
|
import { IsEnum, IsInt, IsNumber, IsOptional, IsString } from 'class-validator'
|
||||||
import { PaymentMethodType, PaymentType } from '../../../generated/prisma/enums'
|
import { PaymentMethodType, PaymentType } from '../../../../generated/prisma/enums'
|
||||||
|
|
||||||
export class CreatePurchaseReceiptPaymentDto {
|
export class CreatePurchaseReceiptPaymentDto {
|
||||||
@IsNumber()
|
@IsNumber()
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
|
||||||
|
import { PrismaModule } from '../../../prisma/prisma.module'
|
||||||
|
import { BankAccountsModule } from '../../bank-accounts/bank-accounts.module'
|
||||||
|
import { PurchaseReceiptPaymentsController } from './purchase-receipt-payments.controller'
|
||||||
|
import { PurchaseReceiptPaymentsService } from './purchase-receipt-payments.service'
|
||||||
|
import { PurchaseReceiptPaymentsWorkflow } from './purchase-receipt-payments.workflow'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [PrismaModule, BankAccountsModule],
|
||||||
|
controllers: [PurchaseReceiptPaymentsController],
|
||||||
|
providers: [PurchaseReceiptPaymentsService, PurchaseReceiptPaymentsWorkflow],
|
||||||
|
exports: [PurchaseReceiptPaymentsWorkflow],
|
||||||
|
})
|
||||||
|
export class PurchaseReceiptPaymentsModule {}
|
||||||
+21
-6
@@ -1,14 +1,29 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
import { ResponseMapper } from '../../common/response/response-mapper'
|
import { withTransaction } from '../../../common/database/transaction.helper'
|
||||||
import { PrismaService } from '../../prisma/prisma.service'
|
import { ResponseMapper } from '../../../common/response/response-mapper'
|
||||||
|
import { PrismaService } from '../../../prisma/prisma.service'
|
||||||
|
import { CreatePurchaseReceiptPaymentDto } from './dto/create-purchase-receipt-payment.dto'
|
||||||
|
import { PurchaseReceiptPaymentsWorkflow } from './purchase-receipt-payments.workflow'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PurchaseReceiptPaymentsService {
|
export class PurchaseReceiptPaymentsService {
|
||||||
constructor(private prisma: PrismaService) {}
|
constructor(
|
||||||
|
private prisma: PrismaService,
|
||||||
|
private purchaseReceiptPaymentsWorkflow: PurchaseReceiptPaymentsWorkflow,
|
||||||
|
) {}
|
||||||
|
|
||||||
async create(data: any) {
|
async create(data: CreatePurchaseReceiptPaymentDto) {
|
||||||
const item = await this.prisma.purchaseReceiptPayments.create({ data })
|
return withTransaction(this.prisma, async tx => {
|
||||||
return ResponseMapper.create(item)
|
const item = await tx.purchaseReceiptPayments.create({ data })
|
||||||
|
await this.purchaseReceiptPaymentsWorkflow.onAddPayment(
|
||||||
|
tx,
|
||||||
|
data.bankAccountId,
|
||||||
|
data.receiptId,
|
||||||
|
data.amount,
|
||||||
|
data.type,
|
||||||
|
)
|
||||||
|
return ResponseMapper.create(item)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll() {
|
async findAll() {
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { Prisma } from '../../../generated/prisma/client'
|
||||||
|
import { PaymentType } from '../../../generated/prisma/enums'
|
||||||
|
import { BankAccountsWorkflow } from '../../bank-accounts/bank-accounts.workflow'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PurchaseReceiptPaymentsWorkflow {
|
||||||
|
constructor(private bankAccountsWorkflow: BankAccountsWorkflow) {}
|
||||||
|
|
||||||
|
async onAddPayment(
|
||||||
|
tx: Prisma.TransactionClient,
|
||||||
|
bankAccountId: number,
|
||||||
|
receiptId: number,
|
||||||
|
amount: number,
|
||||||
|
type: PaymentType,
|
||||||
|
) {
|
||||||
|
const { paidAmount, totalAmount } = await tx.purchaseReceipt.findUniqueOrThrow({
|
||||||
|
where: { id: receiptId },
|
||||||
|
})
|
||||||
|
|
||||||
|
if (type === 'PAYMENT' && Number(paidAmount) + Number(amount) > Number(totalAmount)) {
|
||||||
|
throw new Error('مجموع مبلغ پرداختی بیشتر از مبلغ فاکتور است.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'REFUND' && Number(paidAmount) - Number(amount) < 0) {
|
||||||
|
throw new Error(
|
||||||
|
'مجموع مبلغ بازپرداختی بیشتر از مبلغ پرداخت شده در این فاکتور است.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.bankAccountsWorkflow.addTransaction(tx, {
|
||||||
|
bankAccountId: bankAccountId,
|
||||||
|
amount: amount,
|
||||||
|
type: type === 'PAYMENT' ? 'WITHDRAWAL' : 'DEPOSIT',
|
||||||
|
referenceId: receiptId,
|
||||||
|
referenceType: type === 'PAYMENT' ? 'PURCHASE_PAYMENT' : 'PURCHASE_REFUND',
|
||||||
|
})
|
||||||
|
|
||||||
|
const newPaidAmount =
|
||||||
|
type === 'PAYMENT'
|
||||||
|
? Number(paidAmount) + Number(amount)
|
||||||
|
: Number(paidAmount) - Number(amount)
|
||||||
|
const newStatus =
|
||||||
|
newPaidAmount === 0
|
||||||
|
? 'UNPAID'
|
||||||
|
: newPaidAmount >= Number(totalAmount)
|
||||||
|
? 'PAID'
|
||||||
|
: 'PARTIALLY_PAID'
|
||||||
|
|
||||||
|
await tx.purchaseReceipt.update({
|
||||||
|
where: { id: receiptId },
|
||||||
|
data: {
|
||||||
|
paidAmount: newPaidAmount,
|
||||||
|
status: newStatus,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { PrismaModule } from '../../prisma/prisma.module'
|
||||||
|
import { SupplierLedgerModule } from '../suppliers/ledger/supplier-ledger.module'
|
||||||
|
import { PurchaseReceiptsController } from './index/purchase-receipts.controller'
|
||||||
|
import { PurchaseReceiptsService } from './index/purchase-receipts.service'
|
||||||
|
import { PurchaseReceiptWorkflow } from './index/purchase-receipts.workflow'
|
||||||
|
import { PurchaseReceiptItemsModule } from './purchase-receipt-items/purchase-receipt-items.module'
|
||||||
|
import { PurchaseReceiptPaymentsModule } from './purchase-receipt-payments/purchase-receipt-payments.module'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
PrismaModule,
|
||||||
|
PurchaseReceiptItemsModule,
|
||||||
|
PurchaseReceiptPaymentsModule,
|
||||||
|
SupplierLedgerModule,
|
||||||
|
],
|
||||||
|
controllers: [PurchaseReceiptsController],
|
||||||
|
providers: [PurchaseReceiptsService, PurchaseReceiptWorkflow],
|
||||||
|
exports: [PurchaseReceiptWorkflow],
|
||||||
|
})
|
||||||
|
export class PurchaseReceiptsModule {}
|
||||||
@@ -22,11 +22,6 @@ export class SuppliersController {
|
|||||||
return this.suppliersService.findOne(Number(supplierId))
|
return this.suppliersService.findOne(Number(supplierId))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':supplierId/ledger')
|
|
||||||
getLedger(@Param('supplierId') supplierId: string) {
|
|
||||||
return this.suppliersService.getLedger(Number(supplierId))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
update(@Param('id') id: string, @Body() dto: UpdateSupplierDto) {
|
update(@Param('id') id: string, @Body() dto: UpdateSupplierDto) {
|
||||||
return this.suppliersService.update(Number(id), dto)
|
return this.suppliersService.update(Number(id), dto)
|
||||||
|
|||||||
@@ -37,21 +37,6 @@ export class SuppliersService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLedger(supplierId: number) {
|
|
||||||
const items = await this.prisma.supplierLedger.findMany({
|
|
||||||
where: {
|
|
||||||
supplierId,
|
|
||||||
},
|
|
||||||
omit: {
|
|
||||||
supplierId: true,
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'desc',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return ResponseMapper.list(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
async update(id: number, data: any) {
|
async update(id: number, data: any) {
|
||||||
const item = await this.prisma.supplier.update({ where: { id }, data })
|
const item = await this.prisma.supplier.update({ where: { id }, data })
|
||||||
return ResponseMapper.update(item)
|
return ResponseMapper.update(item)
|
||||||
|
|||||||
@@ -21,10 +21,15 @@ export class SupplierInvoicesController {
|
|||||||
|
|
||||||
@Post(':invoiceId/pay')
|
@Post(':invoiceId/pay')
|
||||||
createPayment(
|
createPayment(
|
||||||
|
@Param('supplierId') supplierId: string,
|
||||||
@Param('invoiceId') invoiceId: string,
|
@Param('invoiceId') invoiceId: string,
|
||||||
@Body() data: CreateReceiptPaymentDto,
|
@Body() data: CreateReceiptPaymentDto,
|
||||||
) {
|
) {
|
||||||
return this.supplierInvoicesService.createPayment(Number(invoiceId), data)
|
return this.supplierInvoicesService.createPayment(
|
||||||
|
Number(supplierId),
|
||||||
|
Number(invoiceId),
|
||||||
|
data,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':invoiceId/payments')
|
@Get(':invoiceId/payments')
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
import { PrismaModule } from '../../../prisma/prisma.module'
|
import { PrismaModule } from '../../../prisma/prisma.module'
|
||||||
|
import { PurchaseReceiptPaymentsModule } from '../../purchase-receipts/purchase-receipt-payments/purchase-receipt-payments.module'
|
||||||
|
import { SupplierLedgerModule } from '../ledger/supplier-ledger.module'
|
||||||
import { SupplierInvoicesController } from './invoices.controller'
|
import { SupplierInvoicesController } from './invoices.controller'
|
||||||
import { SupplierInvoicesService } from './invoices.service'
|
import { SupplierInvoicesService } from './invoices.service'
|
||||||
|
import { SupplierInvoicesWorkflow } from './invoices.workflow'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [PrismaModule],
|
imports: [PrismaModule, PurchaseReceiptPaymentsModule, SupplierLedgerModule],
|
||||||
controllers: [SupplierInvoicesController],
|
controllers: [SupplierInvoicesController],
|
||||||
providers: [SupplierInvoicesService],
|
providers: [SupplierInvoicesService, SupplierInvoicesWorkflow],
|
||||||
})
|
})
|
||||||
export class SupplierInvoicesModule {}
|
export class SupplierInvoicesModule {}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { withTransaction } from '../../../common/database/transaction.helper'
|
||||||
import { ResponseMapper } from '../../../common/response/response-mapper'
|
import { ResponseMapper } from '../../../common/response/response-mapper'
|
||||||
import { PrismaService } from '../../../prisma/prisma.service'
|
import { PrismaService } from '../../../prisma/prisma.service'
|
||||||
import { CreateReceiptPaymentDto } from './dto/create-receipt-payment.dto'
|
import { CreateReceiptPaymentDto } from './dto/create-receipt-payment.dto'
|
||||||
|
import { SupplierInvoicesWorkflow } from './invoices.workflow'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SupplierInvoicesService {
|
export class SupplierInvoicesService {
|
||||||
constructor(private prisma: PrismaService) {}
|
constructor(
|
||||||
|
private prisma: PrismaService,
|
||||||
|
private supplierInvoicesWorkflow: SupplierInvoicesWorkflow,
|
||||||
|
) {}
|
||||||
|
|
||||||
async findAll(supplierId: number) {
|
async findAll(supplierId: number) {
|
||||||
const items = await this.prisma.purchaseReceipt.findMany({
|
const items = await this.prisma.purchaseReceipt.findMany({
|
||||||
@@ -147,32 +152,45 @@ export class SupplierInvoicesService {
|
|||||||
return ResponseMapper.list(items)
|
return ResponseMapper.list(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
async createPayment(invoiceId: number, data: CreateReceiptPaymentDto) {
|
async createPayment(
|
||||||
|
supplierId: number,
|
||||||
|
invoiceId: number,
|
||||||
|
data: CreateReceiptPaymentDto,
|
||||||
|
) {
|
||||||
const { bankAccountId, ...rest } = data
|
const { bankAccountId, ...rest } = data
|
||||||
console.log(data)
|
|
||||||
|
|
||||||
const payment = await this.prisma.purchaseReceiptPayments.create({
|
return withTransaction(this.prisma, async tx => {
|
||||||
data: {
|
await this.supplierInvoicesWorkflow.onPaymentCreated(
|
||||||
...rest,
|
tx,
|
||||||
payedAt: new Date(data.payedAt),
|
supplierId,
|
||||||
receipt: {
|
data.amount,
|
||||||
connect: {
|
invoiceId,
|
||||||
id: invoiceId,
|
bankAccountId,
|
||||||
|
)
|
||||||
|
|
||||||
|
const payment = await tx.purchaseReceiptPayments.create({
|
||||||
|
data: {
|
||||||
|
...rest,
|
||||||
|
payedAt: new Date(data.payedAt),
|
||||||
|
receipt: {
|
||||||
|
connect: {
|
||||||
|
id: invoiceId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bankAccount: {
|
||||||
|
connect: {
|
||||||
|
id: bankAccountId,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bankAccount: {
|
include: {
|
||||||
connect: {
|
receipt: true,
|
||||||
id: bankAccountId,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
omit: {
|
||||||
include: {
|
receiptId: true,
|
||||||
receipt: true,
|
},
|
||||||
},
|
})
|
||||||
omit: {
|
return ResponseMapper.create(payment)
|
||||||
receiptId: true,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
return ResponseMapper.create(payment)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { Prisma } from '../../../generated/prisma/client'
|
||||||
|
import { PurchaseReceiptPaymentsWorkflow } from '../../purchase-receipts/purchase-receipt-payments/purchase-receipt-payments.workflow'
|
||||||
|
import { SupplierLedgerWorkflow } from '../ledger/supplier-ledger.workflow'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SupplierInvoicesWorkflow {
|
||||||
|
constructor(
|
||||||
|
private supplierLedgerWorkflow: SupplierLedgerWorkflow,
|
||||||
|
private purchaseReceiptPaymentWorkflow: PurchaseReceiptPaymentsWorkflow,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async onPaymentCreated(
|
||||||
|
tx: Prisma.TransactionClient,
|
||||||
|
supplierId: number,
|
||||||
|
amount: number,
|
||||||
|
invoiceId: number,
|
||||||
|
bankAccountId: number,
|
||||||
|
) {
|
||||||
|
await this.supplierLedgerWorkflow.updateLedgerBalance(
|
||||||
|
tx,
|
||||||
|
supplierId,
|
||||||
|
amount,
|
||||||
|
invoiceId,
|
||||||
|
'PAYMENT',
|
||||||
|
)
|
||||||
|
|
||||||
|
await this.purchaseReceiptPaymentWorkflow.onAddPayment(
|
||||||
|
tx,
|
||||||
|
bankAccountId,
|
||||||
|
invoiceId,
|
||||||
|
amount,
|
||||||
|
'PAYMENT',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Controller, Get, Param } from '@nestjs/common'
|
||||||
|
import { SupplierLedgerService } from './supplier-ledger.service'
|
||||||
|
|
||||||
|
@Controller('suppliers/:supplierId/ledger')
|
||||||
|
export class SupplierLedgerController {
|
||||||
|
constructor(private readonly supplierLedgerService: SupplierLedgerService) {}
|
||||||
|
|
||||||
|
@Get('')
|
||||||
|
getLedger(@Param('supplierId') supplierId: string) {
|
||||||
|
return this.supplierLedgerService.findAll(Number(supplierId))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { PrismaModule } from '../../../prisma/prisma.module'
|
||||||
|
import { SupplierLedgerController } from './supplier-ledger.controller'
|
||||||
|
import { SupplierLedgerService } from './supplier-ledger.service'
|
||||||
|
import { SupplierLedgerWorkflow } from './supplier-ledger.workflow'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [PrismaModule],
|
||||||
|
controllers: [SupplierLedgerController],
|
||||||
|
providers: [SupplierLedgerService, SupplierLedgerWorkflow],
|
||||||
|
exports: [SupplierLedgerWorkflow],
|
||||||
|
})
|
||||||
|
export class SupplierLedgerModule {}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { ResponseMapper } from '../../../common/response/response-mapper'
|
||||||
|
import { PrismaService } from '../../../prisma/prisma.service'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SupplierLedgerService {
|
||||||
|
constructor(private prisma: PrismaService) {}
|
||||||
|
|
||||||
|
async findAll(supplierId: number) {
|
||||||
|
const items = await this.prisma.supplierLedger.findMany({
|
||||||
|
where: {
|
||||||
|
supplierId,
|
||||||
|
},
|
||||||
|
omit: {
|
||||||
|
supplierId: true,
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
createdAt: 'desc',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ResponseMapper.list(items)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { Prisma } from '../../../generated/prisma/client'
|
||||||
|
import { LedgerSourceType } from '../../../generated/prisma/enums'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SupplierLedgerWorkflow {
|
||||||
|
async updateLedgerBalance(
|
||||||
|
tx: Prisma.TransactionClient,
|
||||||
|
supplierId: number,
|
||||||
|
amount: number,
|
||||||
|
sourceId: number,
|
||||||
|
sourceType: LedgerSourceType,
|
||||||
|
) {
|
||||||
|
const lastSupplierLedgerBalance = await tx.supplierLedger
|
||||||
|
.findFirstOrThrow({
|
||||||
|
where: { supplierId },
|
||||||
|
orderBy: { createdAt: 'desc' },
|
||||||
|
})
|
||||||
|
.then(sl => (sl ? sl.balance : 0))
|
||||||
|
|
||||||
|
let newBalance = Number(lastSupplierLedgerBalance)
|
||||||
|
let credit = 0
|
||||||
|
let debit = 0
|
||||||
|
let description = ''
|
||||||
|
|
||||||
|
switch (sourceType) {
|
||||||
|
case 'PURCHASE':
|
||||||
|
newBalance += amount
|
||||||
|
credit = amount
|
||||||
|
description = `خرید به مبلغ ${amount} بابت خرید شماره ${sourceId}`
|
||||||
|
break
|
||||||
|
case 'REFUND':
|
||||||
|
case 'PAYMENT':
|
||||||
|
newBalance -= amount
|
||||||
|
debit = amount
|
||||||
|
description = `پرداخت به مبلغ ${amount} بابت پرداخت شماره ${sourceId}`
|
||||||
|
break
|
||||||
|
case 'ADJUSTMENT':
|
||||||
|
newBalance = amount
|
||||||
|
description = `اصلاح حساب به مبلغ ${amount} بابت پرداخت شماره ${sourceId}`
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return await tx.supplierLedger.create({
|
||||||
|
data: {
|
||||||
|
supplierId,
|
||||||
|
debit,
|
||||||
|
credit,
|
||||||
|
balance: newBalance,
|
||||||
|
sourceId,
|
||||||
|
sourceType,
|
||||||
|
description,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,9 +3,10 @@ import { PrismaModule } from '../../prisma/prisma.module'
|
|||||||
import { SuppliersController } from './index/suppliers.controller'
|
import { SuppliersController } from './index/suppliers.controller'
|
||||||
import { SuppliersService } from './index/suppliers.service'
|
import { SuppliersService } from './index/suppliers.service'
|
||||||
import { SupplierInvoicesModule } from './invoices/invoices.module'
|
import { SupplierInvoicesModule } from './invoices/invoices.module'
|
||||||
|
import { SupplierLedgerModule } from './ledger/supplier-ledger.module'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [PrismaModule, SupplierInvoicesModule],
|
imports: [PrismaModule, SupplierInvoicesModule, SupplierLedgerModule],
|
||||||
controllers: [SuppliersController],
|
controllers: [SuppliersController],
|
||||||
providers: [SuppliersService],
|
providers: [SuppliersService],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common'
|
|
||||||
import { PrismaModule } from '../prisma/prisma.module'
|
|
||||||
import { PurchaseReceiptsController } from './purchase-receipts.controller'
|
|
||||||
import { PurchaseReceiptsService } from './purchase-receipts.service'
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [PrismaModule],
|
|
||||||
controllers: [PurchaseReceiptsController],
|
|
||||||
providers: [PurchaseReceiptsService],
|
|
||||||
})
|
|
||||||
export class PurchaseReceiptsModule {}
|
|
||||||
Reference in New Issue
Block a user