Spaces:
Running
Running
| -- FUNCTION: trans.apply_stock_movement(text, text, text, text, text, date, text, numeric, text, text, uuid, text) | |
| -- DROP FUNCTION IF EXISTS trans.apply_stock_movement(text, text, text, text, text, date, text, numeric, text, text, uuid, text); | |
| CREATE OR REPLACE FUNCTION trans.apply_stock_movement( | |
| p_merchant_id text, | |
| p_warehouse_id text, | |
| p_sku text, | |
| p_batch_no text, | |
| p_catalogue_id text, | |
| p_expiry_date date, | |
| p_uom text, | |
| p_qty numeric, | |
| p_txn_type text, | |
| p_ref_type text, | |
| p_ref_id uuid, | |
| p_user text) | |
| RETURNS void | |
| LANGUAGE 'plpgsql' | |
| COST 100 | |
| VOLATILE PARALLEL UNSAFE | |
| AS $BODY$ | |
| DECLARE | |
| v_ledger_id uuid := gen_random_uuid(); | |
| v_qty_change numeric; | |
| BEGIN | |
| ---------------------------------------------------------------- | |
| -- Idempotency check | |
| ---------------------------------------------------------------- | |
| IF EXISTS ( | |
| SELECT 1 | |
| FROM trans.scm_stock_ledger | |
| WHERE ref_type = p_ref_type | |
| AND ref_id = p_ref_id | |
| AND sku = p_sku | |
| AND batch_no = p_batch_no | |
| ) THEN | |
| RETURN; | |
| END IF; | |
| ---------------------------------------------------------------- | |
| -- Determine quantity change based on transaction type | |
| ---------------------------------------------------------------- | |
| CASE p_txn_type | |
| WHEN 'GRN_IN' THEN | |
| v_qty_change := p_qty; -- Add stock | |
| WHEN 'ADJUST_IN' THEN | |
| v_qty_change := p_qty; -- Add stock | |
| WHEN 'RETURN_IN' THEN | |
| v_qty_change := p_qty; -- Add stock | |
| WHEN 'TRANSFER_IN' THEN | |
| v_qty_change := p_qty; -- Add stock | |
| WHEN 'ADJUST_OUT' THEN | |
| v_qty_change := -p_qty; -- Subtract stock (negate the positive qty) | |
| WHEN 'SALE_OUT' THEN | |
| v_qty_change := -p_qty; -- Subtract stock | |
| WHEN 'TRANSFER_OUT' THEN | |
| v_qty_change := -p_qty; -- Subtract stock | |
| ELSE | |
| RAISE EXCEPTION 'Unknown transaction type: %', p_txn_type; | |
| END CASE; | |
| Raise Notice 'in'; | |
| RAISE NOTICE 'Transaction type: %, Input qty: %, Calculated change: %', | |
| p_txn_type, p_qty, v_qty_change; | |
| RAISE NOTICE 'Inserting ledger: %, %, %, %, %, %, %, %, %, %, %', | |
| v_ledger_id, | |
| p_merchant_id, | |
| p_warehouse_id, | |
| p_sku, | |
| p_batch_no, | |
| p_txn_type, | |
| v_qty_change, -- Store the calculated change in ledger | |
| p_ref_type, | |
| p_ref_id, | |
| p_user, | |
| NOW(); | |
| ---------------------------------------------------------------- | |
| -- Ledger insert (store the ACTUAL qty change with proper sign) | |
| ---------------------------------------------------------------- | |
| INSERT INTO trans.scm_stock_ledger ( | |
| ledger_id, | |
| merchant_id, | |
| warehouse_id, | |
| sku, | |
| batch_no, | |
| txn_type, | |
| qty, | |
| ref_type, | |
| ref_id, | |
| created_by, | |
| created_at | |
| ) VALUES ( | |
| v_ledger_id, | |
| p_merchant_id, | |
| p_warehouse_id, | |
| p_sku, | |
| p_batch_no, | |
| p_txn_type, | |
| v_qty_change, -- Store with correct sign | |
| p_ref_type, | |
| p_ref_id, | |
| p_user, | |
| NOW() | |
| ); | |
| RAISE NOTICE 'Stock ledger done'; | |
| ---------------------------------------------------------------- | |
| -- Stock snapshot upsert (ALL TABLE COLUMNS) | |
| ---------------------------------------------------------------- | |
| INSERT INTO trans.scm_stock ( | |
| merchant_id, | |
| warehouse_id, | |
| sku, | |
| batch_no, | |
| catalogue_id, | |
| uom, | |
| qty_on_hand, | |
| qty_reserved, | |
| qty_available, | |
| cost_price, | |
| expiry_date, | |
| ledger_id, | |
| created_at, | |
| updated_at | |
| ) VALUES ( | |
| p_merchant_id, | |
| p_warehouse_id, | |
| p_sku, | |
| p_batch_no, | |
| p_catalogue_id, | |
| p_uom, | |
| GREATEST(v_qty_change, 0), -- Use calculated change (don't allow negative on insert) | |
| 0, -- qty_reserved | |
| GREATEST(v_qty_change, 0), -- qty_available | |
| NULL, -- cost_price | |
| p_expiry_date, -- expiry_date | |
| v_ledger_id, | |
| NOW(), | |
| NOW() | |
| ) | |
| ON CONFLICT (merchant_id, warehouse_id, catalogue_id, batch_no) | |
| DO UPDATE SET | |
| qty_on_hand = GREATEST(trans.scm_stock.qty_on_hand + v_qty_change, 0), | |
| qty_available = GREATEST((trans.scm_stock.qty_on_hand + v_qty_change) - trans.scm_stock.qty_reserved, 0), | |
| ledger_id = v_ledger_id, | |
| updated_at = NOW(); | |
| RAISE NOTICE 'Stock updated. Final qty change applied: %', v_qty_change; | |
| END; | |
| $BODY$; | |
| ALTER FUNCTION trans.apply_stock_movement(text, text, text, text, text, date, text, numeric, text, text, uuid, text) | |
| OWNER TO trans_owner; | |