-- AUTO-GENERATED MYSQL TRIGGER DUMP
-- Generated at: 2026-01-04T17:29:18.092Z

-- ------------------------------------------
-- 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_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: 4
-- 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: 5
-- 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: 6
-- 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: 7
-- 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: 8
-- 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: 9
-- 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: 10
-- 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: 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
-- 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: 13
-- 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: 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
-- 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;

