Spaces:
Runtime error
Runtime error
vanitha commited on
Commit ·
1e111cb
1
Parent(s): 1720144
added all sql stored function
Browse files- app/sql/apply_bulk_stock_movements.sql +76 -0
- app/sql/apply_stock_movement.sql +157 -0
- app/sql/fn_get_po_items_details.sql +44 -0
- app/sql/fn_get_po_items_for_grn.sql +35 -0
- app/sql/fn_get_po_items_for_order_process.sql +72 -0
- app/sql/fn_get_po_items_for_purchase_return.sql +50 -0
- app/sql/fn_get_po_ready_for_action.sql +72 -0
- app/sql/fn_get_ready_for_purchase_return.sql +59 -0
- app/sql/get_stock_ledger.sql +32 -0
- app/sql/get_stock_summary.sql +29 -0
- app/sql/get_trade_sales_analytics.sql +77 -0
- app/sql/release_stock_reservation.sql +34 -0
- app/sql/reserve_stock.sql +51 -0
app/sql/apply_bulk_stock_movements.sql
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.apply_bulk_stock_movements(jsonb)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.apply_bulk_stock_movements(jsonb);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.apply_bulk_stock_movements(
|
| 6 |
+
p_movements jsonb)
|
| 7 |
+
RETURNS jsonb
|
| 8 |
+
LANGUAGE 'plpgsql'
|
| 9 |
+
COST 100
|
| 10 |
+
VOLATILE PARALLEL UNSAFE
|
| 11 |
+
AS $BODY$
|
| 12 |
+
DECLARE
|
| 13 |
+
v_movement JSONB;
|
| 14 |
+
v_results JSONB := '[]'::JSONB;
|
| 15 |
+
v_result JSONB;
|
| 16 |
+
v_success BOOLEAN := TRUE;
|
| 17 |
+
v_error_msg TEXT;
|
| 18 |
+
BEGIN
|
| 19 |
+
-- Process each movement in the array
|
| 20 |
+
FOR v_movement IN SELECT * FROM jsonb_array_elements(p_movements)
|
| 21 |
+
LOOP
|
| 22 |
+
BEGIN
|
| 23 |
+
-- Apply individual stock movement using the 9-parameter function
|
| 24 |
+
PERFORM trans.apply_stock_movement(
|
| 25 |
+
(v_movement->>'merchant_id')::TEXT,
|
| 26 |
+
(v_movement->>'location_id')::TEXT,
|
| 27 |
+
(v_movement->>'sku')::TEXT,
|
| 28 |
+
(v_movement->>'batch_no')::TEXT,
|
| 29 |
+
(v_movement->>'catalogue_id')::TEXT,
|
| 30 |
+
(v_movement->>'expiry_date')::DATE,
|
| 31 |
+
(v_movement->>'uom')::TEXT,
|
| 32 |
+
(v_movement->>'qty')::NUMERIC,
|
| 33 |
+
(v_movement->>'txn_type')::TEXT,
|
| 34 |
+
(v_movement->>'ref_type')::TEXT,
|
| 35 |
+
(v_movement->>'ref_id')::UUID,
|
| 36 |
+
(v_movement->>'created_by')::TEXT
|
| 37 |
+
);
|
| 38 |
+
|
| 39 |
+
-- Build success result object
|
| 40 |
+
v_result := jsonb_build_object(
|
| 41 |
+
'ledger_id', gen_random_uuid(),
|
| 42 |
+
'sku', v_movement->>'sku',
|
| 43 |
+
'qty', v_movement->>'qty',
|
| 44 |
+
'success', true,
|
| 45 |
+
'error', null
|
| 46 |
+
);
|
| 47 |
+
|
| 48 |
+
EXCEPTION WHEN OTHERS THEN
|
| 49 |
+
-- Handle individual movement errors
|
| 50 |
+
v_success := FALSE;
|
| 51 |
+
v_error_msg := SQLERRM;
|
| 52 |
+
|
| 53 |
+
v_result := jsonb_build_object(
|
| 54 |
+
'ledger_id', null,
|
| 55 |
+
'sku', v_movement->>'sku',
|
| 56 |
+
'qty', v_movement->>'qty',
|
| 57 |
+
'success', false,
|
| 58 |
+
'error', v_error_msg
|
| 59 |
+
);
|
| 60 |
+
END;
|
| 61 |
+
|
| 62 |
+
-- Add to results array
|
| 63 |
+
v_results := v_results || v_result;
|
| 64 |
+
END LOOP;
|
| 65 |
+
|
| 66 |
+
-- If any movement failed, rollback the entire transaction
|
| 67 |
+
IF NOT v_success THEN
|
| 68 |
+
RAISE EXCEPTION 'One or more stock movements failed. Transaction rolled back.';
|
| 69 |
+
END IF;
|
| 70 |
+
|
| 71 |
+
RETURN v_results;
|
| 72 |
+
END;
|
| 73 |
+
$BODY$;
|
| 74 |
+
|
| 75 |
+
ALTER FUNCTION trans.apply_bulk_stock_movements(jsonb)
|
| 76 |
+
OWNER TO trans_owner;
|
app/sql/apply_stock_movement.sql
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.apply_stock_movement(text, text, text, text, text, date, text, numeric, text, text, uuid, text)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.apply_stock_movement(text, text, text, text, text, date, text, numeric, text, text, uuid, text);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.apply_stock_movement(
|
| 6 |
+
p_merchant_id text,
|
| 7 |
+
p_location_id text,
|
| 8 |
+
p_sku text,
|
| 9 |
+
p_batch_no text,
|
| 10 |
+
p_catalogue_id text,
|
| 11 |
+
p_expiry_date date,
|
| 12 |
+
p_uom text,
|
| 13 |
+
p_qty numeric,
|
| 14 |
+
p_txn_type text,
|
| 15 |
+
p_ref_type text,
|
| 16 |
+
p_ref_id uuid,
|
| 17 |
+
p_user text)
|
| 18 |
+
RETURNS void
|
| 19 |
+
LANGUAGE 'plpgsql'
|
| 20 |
+
COST 100
|
| 21 |
+
VOLATILE PARALLEL UNSAFE
|
| 22 |
+
AS $BODY$
|
| 23 |
+
DECLARE
|
| 24 |
+
v_ledger_id uuid := gen_random_uuid();
|
| 25 |
+
v_qty_change numeric;
|
| 26 |
+
BEGIN
|
| 27 |
+
----------------------------------------------------------------
|
| 28 |
+
-- Idempotency check
|
| 29 |
+
----------------------------------------------------------------
|
| 30 |
+
IF EXISTS (
|
| 31 |
+
SELECT 1
|
| 32 |
+
FROM trans.scm_stock_ledger
|
| 33 |
+
WHERE ref_type = p_ref_type
|
| 34 |
+
AND ref_id = p_ref_id
|
| 35 |
+
AND sku = p_sku
|
| 36 |
+
AND batch_no = p_batch_no
|
| 37 |
+
) THEN
|
| 38 |
+
RETURN;
|
| 39 |
+
END IF;
|
| 40 |
+
|
| 41 |
+
----------------------------------------------------------------
|
| 42 |
+
-- Determine quantity change based on transaction type
|
| 43 |
+
----------------------------------------------------------------
|
| 44 |
+
CASE p_txn_type
|
| 45 |
+
WHEN 'GRN_IN' THEN
|
| 46 |
+
v_qty_change := p_qty; -- Add stock
|
| 47 |
+
WHEN 'ADJUST_IN' THEN
|
| 48 |
+
v_qty_change := p_qty; -- Add stock
|
| 49 |
+
WHEN 'RETURN_IN' THEN
|
| 50 |
+
v_qty_change := p_qty; -- Add stock
|
| 51 |
+
WHEN 'TRANSFER_IN' THEN
|
| 52 |
+
v_qty_change := p_qty; -- Add stock
|
| 53 |
+
WHEN 'ADJUST_OUT' THEN
|
| 54 |
+
v_qty_change := -p_qty; -- Subtract stock (negate the positive qty)
|
| 55 |
+
WHEN 'SALE_OUT' THEN
|
| 56 |
+
v_qty_change := -p_qty; -- Subtract stock
|
| 57 |
+
WHEN 'TRANSFER_OUT' THEN
|
| 58 |
+
v_qty_change := -p_qty; -- Subtract stock
|
| 59 |
+
ELSE
|
| 60 |
+
RAISE EXCEPTION 'Unknown transaction type: %', p_txn_type;
|
| 61 |
+
END CASE;
|
| 62 |
+
|
| 63 |
+
Raise Notice 'in';
|
| 64 |
+
RAISE NOTICE 'Transaction type: %, Input qty: %, Calculated change: %',
|
| 65 |
+
p_txn_type, p_qty, v_qty_change;
|
| 66 |
+
|
| 67 |
+
RAISE NOTICE 'Inserting ledger: %, %, %, %, %, %, %, %, %, %, %',
|
| 68 |
+
v_ledger_id,
|
| 69 |
+
p_merchant_id,
|
| 70 |
+
p_location_id,
|
| 71 |
+
p_sku,
|
| 72 |
+
p_batch_no,
|
| 73 |
+
p_txn_type,
|
| 74 |
+
v_qty_change, -- Store the calculated change in ledger
|
| 75 |
+
p_ref_type,
|
| 76 |
+
p_ref_id,
|
| 77 |
+
p_user,
|
| 78 |
+
NOW();
|
| 79 |
+
|
| 80 |
+
----------------------------------------------------------------
|
| 81 |
+
-- Ledger insert (store the ACTUAL qty change with proper sign)
|
| 82 |
+
----------------------------------------------------------------
|
| 83 |
+
INSERT INTO trans.scm_stock_ledger (
|
| 84 |
+
ledger_id,
|
| 85 |
+
merchant_id,
|
| 86 |
+
location_id,
|
| 87 |
+
sku,
|
| 88 |
+
batch_no,
|
| 89 |
+
txn_type,
|
| 90 |
+
qty,
|
| 91 |
+
ref_type,
|
| 92 |
+
ref_id,
|
| 93 |
+
created_by,
|
| 94 |
+
created_at
|
| 95 |
+
) VALUES (
|
| 96 |
+
v_ledger_id,
|
| 97 |
+
p_merchant_id,
|
| 98 |
+
p_location_id,
|
| 99 |
+
p_sku,
|
| 100 |
+
p_batch_no,
|
| 101 |
+
p_txn_type,
|
| 102 |
+
v_qty_change, -- Store with correct sign
|
| 103 |
+
p_ref_type,
|
| 104 |
+
p_ref_id,
|
| 105 |
+
p_user,
|
| 106 |
+
NOW()
|
| 107 |
+
);
|
| 108 |
+
|
| 109 |
+
RAISE NOTICE 'Stock ledger done';
|
| 110 |
+
|
| 111 |
+
----------------------------------------------------------------
|
| 112 |
+
-- Stock snapshot upsert (ALL TABLE COLUMNS)
|
| 113 |
+
----------------------------------------------------------------
|
| 114 |
+
INSERT INTO trans.scm_stock (
|
| 115 |
+
merchant_id,
|
| 116 |
+
location_id,
|
| 117 |
+
sku,
|
| 118 |
+
batch_no,
|
| 119 |
+
catalogue_id,
|
| 120 |
+
uom,
|
| 121 |
+
qty_on_hand,
|
| 122 |
+
qty_reserved,
|
| 123 |
+
qty_available,
|
| 124 |
+
cost_price,
|
| 125 |
+
expiry_date,
|
| 126 |
+
ledger_id,
|
| 127 |
+
created_at,
|
| 128 |
+
updated_at
|
| 129 |
+
) VALUES (
|
| 130 |
+
p_merchant_id,
|
| 131 |
+
p_location_id,
|
| 132 |
+
p_sku,
|
| 133 |
+
p_batch_no,
|
| 134 |
+
p_catalogue_id,
|
| 135 |
+
p_uom,
|
| 136 |
+
GREATEST(v_qty_change, 0), -- Use calculated change (don't allow negative on insert)
|
| 137 |
+
0, -- qty_reserved
|
| 138 |
+
GREATEST(v_qty_change, 0), -- qty_available
|
| 139 |
+
NULL, -- cost_price
|
| 140 |
+
p_expiry_date, -- expiry_date
|
| 141 |
+
v_ledger_id,
|
| 142 |
+
NOW(),
|
| 143 |
+
NOW()
|
| 144 |
+
)
|
| 145 |
+
ON CONFLICT (merchant_id, location_id, catalogue_id, batch_no)
|
| 146 |
+
DO UPDATE SET
|
| 147 |
+
qty_on_hand = GREATEST(trans.scm_stock.qty_on_hand + v_qty_change, 0),
|
| 148 |
+
qty_available = GREATEST((trans.scm_stock.qty_on_hand + v_qty_change) - trans.scm_stock.qty_reserved, 0),
|
| 149 |
+
ledger_id = v_ledger_id,
|
| 150 |
+
updated_at = NOW();
|
| 151 |
+
|
| 152 |
+
RAISE NOTICE 'Stock updated. Final qty change applied: %', v_qty_change;
|
| 153 |
+
END;
|
| 154 |
+
$BODY$;
|
| 155 |
+
|
| 156 |
+
ALTER FUNCTION trans.apply_stock_movement(text, text, text, text, text, date, text, numeric, text, text, uuid, text)
|
| 157 |
+
OWNER TO trans_owner;
|
app/sql/fn_get_po_items_details.sql
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.fn_get_po_item_details(uuid)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.fn_get_po_item_details(uuid);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.fn_get_po_item_details(
|
| 6 |
+
p_po_id uuid)
|
| 7 |
+
RETURNS TABLE(po_id uuid, catalogue_code text, catalogue_name text, hsn_code text, gst_rate numeric, ord_qty numeric, dispatched_qty numeric, rcvd_qty numeric, rejected_qty numeric, returned_qty numeric, net_accepted_qty numeric, unit_price numeric, taxable_amount numeric, gst_amount numeric, final_amount numeric)
|
| 8 |
+
LANGUAGE 'plpgsql'
|
| 9 |
+
COST 100
|
| 10 |
+
VOLATILE PARALLEL UNSAFE
|
| 11 |
+
ROWS 1000
|
| 12 |
+
|
| 13 |
+
AS $BODY$
|
| 14 |
+
BEGIN
|
| 15 |
+
RETURN QUERY
|
| 16 |
+
SELECT
|
| 17 |
+
poi.po_id,
|
| 18 |
+
|
| 19 |
+
cr.catalogue_code,
|
| 20 |
+
cr.catalogue_name,
|
| 21 |
+
cr.hsn_code,
|
| 22 |
+
cr.gst_rate,
|
| 23 |
+
|
| 24 |
+
poi.ord_qty,
|
| 25 |
+
poi.dispatched_qty,
|
| 26 |
+
poi.rcvd_qty,
|
| 27 |
+
poi.rejected_qty,
|
| 28 |
+
poi.returned_qty,
|
| 29 |
+
(poi.rcvd_qty - poi.rejected_qty - poi.returned_qty) AS net_accepted_qty,
|
| 30 |
+
|
| 31 |
+
poi.unit_price,
|
| 32 |
+
poi.line_amt AS taxable_amount,
|
| 33 |
+
poi.tax_amt AS gst_amount,
|
| 34 |
+
|
| 35 |
+
(poi.line_amt + poi.tax_amt) AS final_amount
|
| 36 |
+
FROM trans.scm_po_item poi
|
| 37 |
+
JOIN trans.catalogue_ref cr
|
| 38 |
+
ON cr.catalogue_id = poi.catalogue_id
|
| 39 |
+
WHERE poi.po_id = p_po_id;
|
| 40 |
+
END;
|
| 41 |
+
$BODY$;
|
| 42 |
+
|
| 43 |
+
ALTER FUNCTION trans.fn_get_po_item_details(uuid)
|
| 44 |
+
OWNER TO trans_owner;
|
app/sql/fn_get_po_items_for_grn.sql
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.fn_get_po_items_for_grn(uuid)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.fn_get_po_items_for_grn(uuid);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.fn_get_po_items_for_grn(
|
| 6 |
+
p_po_id uuid)
|
| 7 |
+
RETURNS TABLE(po_item_id uuid, catalogue_id uuid, catalogue_name text, ordered_qty numeric, received_qty numeric, rejected_qty numeric, pending_grn numeric, cost_price numeric)
|
| 8 |
+
LANGUAGE 'plpgsql'
|
| 9 |
+
COST 100
|
| 10 |
+
VOLATILE PARALLEL UNSAFE
|
| 11 |
+
ROWS 1000
|
| 12 |
+
|
| 13 |
+
AS $BODY$
|
| 14 |
+
BEGIN
|
| 15 |
+
RETURN QUERY
|
| 16 |
+
SELECT
|
| 17 |
+
po.id AS po_item_id,
|
| 18 |
+
po.catalogue_id,
|
| 19 |
+
cr.catalogue_name,
|
| 20 |
+
po.ord_qty AS ordered_qty,
|
| 21 |
+
po.rcvd_qty AS received_qty,
|
| 22 |
+
po.rejected_qty,
|
| 23 |
+
(po.ord_qty - po.rcvd_qty - po.rejected_qty) AS pending_grn,
|
| 24 |
+
po.cost_price
|
| 25 |
+
FROM scm_po_item po
|
| 26 |
+
JOIN catalogue_ref cr
|
| 27 |
+
ON po.catalogue_id = cr.catalogue_id
|
| 28 |
+
WHERE po.po_id = p_po_id
|
| 29 |
+
AND (po.ord_qty - po.rcvd_qty - po.rejected_qty) > 0
|
| 30 |
+
ORDER BY cr.catalogue_name;
|
| 31 |
+
END;
|
| 32 |
+
$BODY$;
|
| 33 |
+
|
| 34 |
+
ALTER FUNCTION trans.fn_get_po_items_for_grn(uuid)
|
| 35 |
+
OWNER TO trans_owner;
|
app/sql/fn_get_po_items_for_order_process.sql
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.fn_get_po_items_for_order_process(uuid, text, text)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.fn_get_po_items_for_order_process(uuid, text, text);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.fn_get_po_items_for_order_process(
|
| 6 |
+
p_po_id uuid,
|
| 7 |
+
p_warehouse_id text,
|
| 8 |
+
p_mode text)
|
| 9 |
+
RETURNS TABLE(po_item_id uuid, catalogue_id uuid, catalogue_name text, ordered_qty numeric, received_qty numeric, dispatched_qty numeric, pending_qty numeric, qty_available numeric, batch_no character varying, expiry_date date, unit_price numeric)
|
| 10 |
+
LANGUAGE 'plpgsql'
|
| 11 |
+
COST 100
|
| 12 |
+
VOLATILE PARALLEL UNSAFE
|
| 13 |
+
ROWS 1000
|
| 14 |
+
|
| 15 |
+
AS $BODY$
|
| 16 |
+
BEGIN
|
| 17 |
+
IF p_mode = 'DISPATCH' THEN
|
| 18 |
+
|
| 19 |
+
RETURN QUERY
|
| 20 |
+
SELECT
|
| 21 |
+
po.po_id,
|
| 22 |
+
po.catalogue_id,
|
| 23 |
+
cr.catalogue_name,
|
| 24 |
+
po.ord_qty,
|
| 25 |
+
po.rcvd_qty,
|
| 26 |
+
po.dispatched_qty,
|
| 27 |
+
(po.rcvd_qty - po.dispatched_qty) AS pending_qty,
|
| 28 |
+
st.qty_available,
|
| 29 |
+
st.batch_no,
|
| 30 |
+
st.expiry_date,
|
| 31 |
+
po.unit_price
|
| 32 |
+
FROM trans.scm_po_item po
|
| 33 |
+
JOIN trans.catalogue_ref cr
|
| 34 |
+
ON po.catalogue_id = cr.catalogue_id
|
| 35 |
+
JOIN trans.scm_stock st
|
| 36 |
+
ON st.catalogue_id = po.catalogue_id
|
| 37 |
+
AND st.location_id = p_warehouse_id
|
| 38 |
+
WHERE po.po_id = p_po_id
|
| 39 |
+
AND (po.ord_qty - coalesce(po.dispatched_qty,0)) > 0
|
| 40 |
+
AND st.qty_available > 0
|
| 41 |
+
ORDER BY cr.catalogue_name, st.expiry_date;
|
| 42 |
+
|
| 43 |
+
ELSIF p_mode = 'INVOICE' THEN
|
| 44 |
+
|
| 45 |
+
RETURN QUERY
|
| 46 |
+
SELECT
|
| 47 |
+
po.po_id,
|
| 48 |
+
po.catalogue_id,
|
| 49 |
+
cr.catalogue_name,
|
| 50 |
+
po.ord_qty,
|
| 51 |
+
po.rcvd_qty,
|
| 52 |
+
po.dispatched_qty,
|
| 53 |
+
(po.ord_qty - po.dispatched_qty) AS pending_qty,
|
| 54 |
+
NULL::numeric AS qty_available,
|
| 55 |
+
NULL::character varying(50) AS batch_no,
|
| 56 |
+
NULL::date AS expiry_date,
|
| 57 |
+
po.unit_price
|
| 58 |
+
FROM trans.scm_po_item po
|
| 59 |
+
JOIN trans.catalogue_ref cr
|
| 60 |
+
ON po.catalogue_id = cr.catalogue_id
|
| 61 |
+
WHERE po.po_id = p_po_id
|
| 62 |
+
AND (po.dispatched_qty - po.returned_qty) > 0
|
| 63 |
+
ORDER BY cr.catalogue_name;
|
| 64 |
+
|
| 65 |
+
ELSE
|
| 66 |
+
RAISE EXCEPTION 'Invalid p_mode: %', p_mode;
|
| 67 |
+
END IF;
|
| 68 |
+
END;
|
| 69 |
+
$BODY$;
|
| 70 |
+
|
| 71 |
+
ALTER FUNCTION trans.fn_get_po_items_for_order_process(uuid, text, text)
|
| 72 |
+
OWNER TO trans_owner;
|
app/sql/fn_get_po_items_for_purchase_return.sql
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.fn_get_po_items_for_purchase_return(uuid, uuid)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.fn_get_po_items_for_purchase_return(uuid, uuid);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.fn_get_po_items_for_purchase_return(
|
| 6 |
+
p_po_id uuid,
|
| 7 |
+
p_warehouse_id uuid)
|
| 8 |
+
RETURNS TABLE(po_item_id uuid, catalogue_id uuid, catalogue_name text, received_qty numeric, returned_qty numeric, dispatched_qty numeric, returnable_qty numeric, batch_no text, expiry_date date, qty_available numeric, cost_price numeric)
|
| 9 |
+
LANGUAGE 'plpgsql'
|
| 10 |
+
COST 100
|
| 11 |
+
VOLATILE PARALLEL UNSAFE
|
| 12 |
+
ROWS 1000
|
| 13 |
+
|
| 14 |
+
AS $BODY$
|
| 15 |
+
BEGIN
|
| 16 |
+
RETURN QUERY
|
| 17 |
+
SELECT
|
| 18 |
+
pi.po_item_id,
|
| 19 |
+
pi.catalogue_id,
|
| 20 |
+
cr.catalogue_name,
|
| 21 |
+
pi.rcvd_qty,
|
| 22 |
+
pi.returned_qty,
|
| 23 |
+
pi.dispatched_qty,
|
| 24 |
+
(
|
| 25 |
+
COALESCE(pi.rcvd_qty, 0)
|
| 26 |
+
- COALESCE(pi.rejected_qty, 0)
|
| 27 |
+
- COALESCE(pi.returned_qty, 0)
|
| 28 |
+
- COALESCE(pi.dispatched_qty, 0)
|
| 29 |
+
) AS returnable_qty,
|
| 30 |
+
st.batch_no::text,
|
| 31 |
+
st.expiry_date,
|
| 32 |
+
st.qty_available,
|
| 33 |
+
pi.unit_price
|
| 34 |
+
|
| 35 |
+
FROM trans.scm_po_item pi
|
| 36 |
+
JOIN trans.catalogue_ref cr
|
| 37 |
+
ON cr.catalogue_id = pi.catalogue_id
|
| 38 |
+
JOIN trans.scm_stock st
|
| 39 |
+
ON st.catalogue_id = pi.catalogue_id
|
| 40 |
+
AND st.location_id = p_warehouse_id
|
| 41 |
+
|
| 42 |
+
WHERE pi.po_id = p_po_id
|
| 43 |
+
AND st.qty_available > 0
|
| 44 |
+
|
| 45 |
+
ORDER BY cr.catalogue_name, st.expiry_date;
|
| 46 |
+
END;
|
| 47 |
+
$BODY$;
|
| 48 |
+
|
| 49 |
+
ALTER FUNCTION trans.fn_get_po_items_for_purchase_return(uuid, uuid)
|
| 50 |
+
OWNER TO trans_owner;
|
app/sql/fn_get_po_ready_for_action.sql
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.fn_get_po_ready_for_action(text, character varying)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.fn_get_po_ready_for_action(text, character varying);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.fn_get_po_ready_for_action(
|
| 6 |
+
p_mode text,
|
| 7 |
+
p_client_id character varying DEFAULT NULL::character varying)
|
| 8 |
+
RETURNS TABLE(po_id uuid, po_no character varying, supplier_id character varying, client_id character varying, shipment_count integer, latest_shipment_date date, shipment_no text, lr_no text, transporter text)
|
| 9 |
+
LANGUAGE 'plpgsql'
|
| 10 |
+
COST 100
|
| 11 |
+
VOLATILE PARALLEL UNSAFE
|
| 12 |
+
ROWS 1000
|
| 13 |
+
|
| 14 |
+
AS $BODY$
|
| 15 |
+
BEGIN
|
| 16 |
+
IF p_mode = 'INVOICE' THEN
|
| 17 |
+
RETURN QUERY
|
| 18 |
+
SELECT
|
| 19 |
+
po.po_id,
|
| 20 |
+
po.po_no,
|
| 21 |
+
po.supplier_id,
|
| 22 |
+
po.buyer_id,
|
| 23 |
+
COUNT(DISTINCT sh.shipment_id)::integer AS shipment_count,
|
| 24 |
+
MAX(sh.shipment_date)::date AS latest_shipment_date,
|
| 25 |
+
MAX(sh.shipment_no) AS shipment_no,
|
| 26 |
+
MAX(sh.lr_no) AS lr_no,
|
| 27 |
+
MAX(sh.transporter) AS transporter
|
| 28 |
+
FROM trans.scm_po po
|
| 29 |
+
JOIN trans.scm_trade_shipment sh
|
| 30 |
+
ON sh.order_id = po.po_id
|
| 31 |
+
AND sh.status = 'COMPLETED'
|
| 32 |
+
WHERE po.status = 'APPROVED'
|
| 33 |
+
AND (p_client_id IS NULL OR po.buyer_id = p_client_id)
|
| 34 |
+
GROUP BY
|
| 35 |
+
po.po_id,
|
| 36 |
+
po.po_no,
|
| 37 |
+
po.supplier_id,
|
| 38 |
+
po.buyer_id
|
| 39 |
+
ORDER BY latest_shipment_date DESC;
|
| 40 |
+
|
| 41 |
+
ELSIF p_mode = 'DISPATCH' THEN
|
| 42 |
+
RETURN QUERY
|
| 43 |
+
SELECT
|
| 44 |
+
po.po_id,
|
| 45 |
+
po.po_no,
|
| 46 |
+
po.supplier_id,
|
| 47 |
+
po.buyer_id,
|
| 48 |
+
COUNT(DISTINCT sh.shipment_id)::integer AS shipment_count,
|
| 49 |
+
MAX(sh.shipment_date)::date AS latest_shipment_date,
|
| 50 |
+
MAX(sh.shipment_no) AS shipment_no,
|
| 51 |
+
MAX(sh.lr_no) AS lr_no,
|
| 52 |
+
MAX(sh.transporter) AS transporter
|
| 53 |
+
FROM trans.scm_po po
|
| 54 |
+
LEFT JOIN trans.scm_trade_shipment sh
|
| 55 |
+
ON sh.order_id = po.po_id
|
| 56 |
+
WHERE po.status = 'APPROVED'
|
| 57 |
+
AND (p_client_id IS NULL OR po.buyer_id = p_client_id)
|
| 58 |
+
GROUP BY
|
| 59 |
+
po.po_id,
|
| 60 |
+
po.po_no,
|
| 61 |
+
po.supplier_id,
|
| 62 |
+
po.buyer_id
|
| 63 |
+
ORDER BY po.po_no DESC;
|
| 64 |
+
|
| 65 |
+
ELSE
|
| 66 |
+
RAISE EXCEPTION 'Invalid p_mode: % (expected DISPATCH or INVOICE)', p_mode;
|
| 67 |
+
END IF;
|
| 68 |
+
END;
|
| 69 |
+
$BODY$;
|
| 70 |
+
|
| 71 |
+
ALTER FUNCTION trans.fn_get_po_ready_for_action(text, character varying)
|
| 72 |
+
OWNER TO trans_owner;
|
app/sql/fn_get_ready_for_purchase_return.sql
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.fn_get_po_ready_for_purchase_return(character varying)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.fn_get_po_ready_for_purchase_return(character varying);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.fn_get_po_ready_for_purchase_return(
|
| 6 |
+
p_client_id character varying DEFAULT NULL::character varying)
|
| 7 |
+
RETURNS TABLE(po_id uuid, po_no character varying, supplier_id character varying, client_id character varying, returnable_qty numeric, last_grn_date date)
|
| 8 |
+
LANGUAGE 'plpgsql'
|
| 9 |
+
COST 100
|
| 10 |
+
VOLATILE PARALLEL UNSAFE
|
| 11 |
+
ROWS 1000
|
| 12 |
+
|
| 13 |
+
AS $BODY$
|
| 14 |
+
BEGIN
|
| 15 |
+
RETURN QUERY
|
| 16 |
+
SELECT
|
| 17 |
+
po.po_id,
|
| 18 |
+
po.po_no,
|
| 19 |
+
po.supplier_id,
|
| 20 |
+
po.client_id,
|
| 21 |
+
|
| 22 |
+
SUM(
|
| 23 |
+
pi.received_qty
|
| 24 |
+
- pi.rejected_qty
|
| 25 |
+
- pi.returned_qty
|
| 26 |
+
- pi.dispatched_qty
|
| 27 |
+
) AS returnable_qty,
|
| 28 |
+
|
| 29 |
+
MAX(grn.grn_date) AS last_grn_date
|
| 30 |
+
|
| 31 |
+
FROM trans.scm_po po
|
| 32 |
+
JOIN trans.scm_po_item pi
|
| 33 |
+
ON pi.po_id = po.po_id
|
| 34 |
+
LEFT JOIN trans.scm_grn grn
|
| 35 |
+
ON grn.po_id = po.po_id
|
| 36 |
+
|
| 37 |
+
WHERE po.status = 'APPROVED'
|
| 38 |
+
AND (p_client_id IS NULL OR po.client_id = p_client_id)
|
| 39 |
+
|
| 40 |
+
GROUP BY
|
| 41 |
+
po.po_id,
|
| 42 |
+
po.po_no,
|
| 43 |
+
po.supplier_id,
|
| 44 |
+
po.client_id
|
| 45 |
+
|
| 46 |
+
HAVING
|
| 47 |
+
SUM(
|
| 48 |
+
pi.received_qty
|
| 49 |
+
- pi.rejected_qty
|
| 50 |
+
- pi.returned_qty
|
| 51 |
+
- pi.dispatched_qty
|
| 52 |
+
) > 0
|
| 53 |
+
|
| 54 |
+
ORDER BY last_grn_date DESC;
|
| 55 |
+
END;
|
| 56 |
+
$BODY$;
|
| 57 |
+
|
| 58 |
+
ALTER FUNCTION trans.fn_get_po_ready_for_purchase_return(character varying)
|
| 59 |
+
OWNER TO trans_owner;
|
app/sql/get_stock_ledger.sql
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.get_stock_ledger(character varying, character varying, character varying, integer)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.get_stock_ledger(character varying, character varying, character varying, integer);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.get_stock_ledger(
|
| 6 |
+
p_merchant_id character varying,
|
| 7 |
+
p_sku character varying DEFAULT NULL::character varying,
|
| 8 |
+
p_batch_no character varying DEFAULT NULL::character varying,
|
| 9 |
+
p_limit integer DEFAULT 100)
|
| 10 |
+
RETURNS TABLE(ledger_id uuid, location_id character varying, catalogue_id uuid, sku character varying, batch_no character varying, txn_type character varying, qty numeric, uom character varying, ref_type character varying, ref_id uuid, ref_no character varying, remarks text, created_by character varying, created_at timestamp without time zone)
|
| 11 |
+
LANGUAGE 'plpgsql'
|
| 12 |
+
COST 100
|
| 13 |
+
VOLATILE PARALLEL UNSAFE
|
| 14 |
+
ROWS 1000
|
| 15 |
+
|
| 16 |
+
AS $BODY$
|
| 17 |
+
BEGIN
|
| 18 |
+
RETURN QUERY
|
| 19 |
+
SELECT l.ledger_id, l.location_id, l.catalogue_id, l.sku, l.batch_no,
|
| 20 |
+
l.txn_type, l.qty, l.uom, l.ref_type, l.ref_id, l.ref_no,
|
| 21 |
+
l.remarks, l.created_by, l.created_at
|
| 22 |
+
FROM trans.scm_stock_ledger l
|
| 23 |
+
WHERE l.merchant_id = p_merchant_id
|
| 24 |
+
AND (p_sku IS NULL OR l.sku = p_sku)
|
| 25 |
+
AND (p_batch_no IS NULL OR l.batch_no = p_batch_no)
|
| 26 |
+
ORDER BY l.created_at DESC
|
| 27 |
+
LIMIT p_limit;
|
| 28 |
+
END;
|
| 29 |
+
$BODY$;
|
| 30 |
+
|
| 31 |
+
ALTER FUNCTION trans.get_stock_ledger(character varying, character varying, character varying, integer)
|
| 32 |
+
OWNER TO trans_owner;
|
app/sql/get_stock_summary.sql
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.get_stock_summary(character varying, character varying, character varying)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.get_stock_summary(character varying, character varying, character varying);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.get_stock_summary(
|
| 6 |
+
p_merchant_id character varying,
|
| 7 |
+
p_location_id character varying DEFAULT NULL::character varying,
|
| 8 |
+
p_sku character varying DEFAULT NULL::character varying)
|
| 9 |
+
RETURNS TABLE(stock_id uuid, location_id character varying, catalogue_id uuid, sku character varying, batch_no character varying, qty_on_hand numeric, qty_reserved numeric, qty_available numeric, uom character varying, last_updated_at timestamp without time zone)
|
| 10 |
+
LANGUAGE 'plpgsql'
|
| 11 |
+
COST 100
|
| 12 |
+
VOLATILE PARALLEL UNSAFE
|
| 13 |
+
ROWS 1000
|
| 14 |
+
|
| 15 |
+
AS $BODY$
|
| 16 |
+
BEGIN
|
| 17 |
+
RETURN QUERY
|
| 18 |
+
SELECT s.stock_id, s.location_id, s.catalogue_id, s.sku, s.batch_no,
|
| 19 |
+
s.qty_on_hand, s.qty_reserved, s.qty_available, s.uom, s.last_updated_at
|
| 20 |
+
FROM trans.scm_stock s
|
| 21 |
+
WHERE s.merchant_id = p_merchant_id
|
| 22 |
+
AND (p_location_id IS NULL OR s.location_id = p_location_id)
|
| 23 |
+
AND (p_sku IS NULL OR s.sku = p_sku)
|
| 24 |
+
ORDER BY s.sku, s.batch_no;
|
| 25 |
+
END;
|
| 26 |
+
$BODY$;
|
| 27 |
+
|
| 28 |
+
ALTER FUNCTION trans.get_stock_summary(character varying, character varying, character varying)
|
| 29 |
+
OWNER TO trans_owner;
|
app/sql/get_trade_sales_analytics.sql
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.get_trade_sales_analytics(character varying, character varying, date, date)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.get_trade_sales_analytics(character varying, character varying, date, date);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.get_trade_sales_analytics(
|
| 6 |
+
p_supplier_id character varying DEFAULT NULL::character varying,
|
| 7 |
+
p_client_id character varying DEFAULT NULL::character varying,
|
| 8 |
+
p_date_from date DEFAULT NULL::date,
|
| 9 |
+
p_date_to date DEFAULT NULL::date)
|
| 10 |
+
RETURNS TABLE(metric_name character varying, metric_value numeric, metric_unit character varying)
|
| 11 |
+
LANGUAGE 'plpgsql'
|
| 12 |
+
COST 100
|
| 13 |
+
VOLATILE PARALLEL UNSAFE
|
| 14 |
+
ROWS 1000
|
| 15 |
+
|
| 16 |
+
AS $BODY$
|
| 17 |
+
BEGIN
|
| 18 |
+
-- Total shipments
|
| 19 |
+
RETURN QUERY
|
| 20 |
+
SELECT
|
| 21 |
+
'total_shipments'::VARCHAR(50) as metric_name,
|
| 22 |
+
COUNT(*)::NUMERIC as metric_value,
|
| 23 |
+
'count'::VARCHAR(20) as metric_unit
|
| 24 |
+
FROM trans.scm_trade_shipment ts
|
| 25 |
+
WHERE (p_supplier_id IS NULL OR ts.supplier_id = p_supplier_id)
|
| 26 |
+
AND (p_client_id IS NULL OR ts.client_id = p_client_id)
|
| 27 |
+
AND (p_date_from IS NULL OR ts.shipment_date >= p_date_from)
|
| 28 |
+
AND (p_date_to IS NULL OR ts.shipment_date <= p_date_to);
|
| 29 |
+
|
| 30 |
+
-- Total quantity shipped
|
| 31 |
+
RETURN QUERY
|
| 32 |
+
SELECT
|
| 33 |
+
'total_qty_shipped'::VARCHAR(50) as metric_name,
|
| 34 |
+
COALESCE(SUM(tsi.shipped_qty), 0)::NUMERIC as metric_value,
|
| 35 |
+
'units'::VARCHAR(20) as metric_unit
|
| 36 |
+
FROM trans.scm_trade_shipment ts
|
| 37 |
+
JOIN trans.scm_trade_shipment_item tsi ON ts.shipment_id = tsi.shipment_id
|
| 38 |
+
WHERE (p_supplier_id IS NULL OR ts.supplier_id = p_supplier_id)
|
| 39 |
+
AND (p_client_id IS NULL OR ts.client_id = p_client_id)
|
| 40 |
+
AND (p_date_from IS NULL OR ts.shipment_date >= p_date_from)
|
| 41 |
+
AND (p_date_to IS NULL OR ts.shipment_date <= p_date_to);
|
| 42 |
+
|
| 43 |
+
-- Unique SKUs shipped
|
| 44 |
+
RETURN QUERY
|
| 45 |
+
SELECT
|
| 46 |
+
'unique_skus'::VARCHAR(50) as metric_name,
|
| 47 |
+
COUNT(DISTINCT tsi.sku)::NUMERIC as metric_value,
|
| 48 |
+
'count'::VARCHAR(20) as metric_unit
|
| 49 |
+
FROM trans.scm_trade_shipment ts
|
| 50 |
+
JOIN trans.scm_trade_shipment_item tsi ON ts.shipment_id = tsi.shipment_id
|
| 51 |
+
WHERE (p_supplier_id IS NULL OR ts.supplier_id = p_supplier_id)
|
| 52 |
+
AND (p_client_id IS NULL OR ts.client_id = p_client_id)
|
| 53 |
+
AND (p_date_from IS NULL OR ts.shipment_date >= p_date_from)
|
| 54 |
+
AND (p_date_to IS NULL OR ts.shipment_date <= p_date_to);
|
| 55 |
+
|
| 56 |
+
-- Average shipment size
|
| 57 |
+
RETURN QUERY
|
| 58 |
+
SELECT
|
| 59 |
+
'avg_shipment_size'::VARCHAR(50) as metric_name,
|
| 60 |
+
COALESCE(AVG(shipment_totals.total_qty), 0)::NUMERIC as metric_value,
|
| 61 |
+
'units'::VARCHAR(20) as metric_unit
|
| 62 |
+
FROM (
|
| 63 |
+
SELECT ts.shipment_id, SUM(tsi.shipped_qty) as total_qty
|
| 64 |
+
FROM trans.scm_trade_shipment ts
|
| 65 |
+
JOIN trans.scm_trade_shipment_item tsi ON ts.shipment_id = tsi.shipment_id
|
| 66 |
+
WHERE (p_supplier_id IS NULL OR ts.supplier_id = p_supplier_id)
|
| 67 |
+
AND (p_client_id IS NULL OR ts.client_id = p_client_id)
|
| 68 |
+
AND (p_date_from IS NULL OR ts.shipment_date >= p_date_from)
|
| 69 |
+
AND (p_date_to IS NULL OR ts.shipment_date <= p_date_to)
|
| 70 |
+
GROUP BY ts.shipment_id
|
| 71 |
+
) shipment_totals;
|
| 72 |
+
|
| 73 |
+
END;
|
| 74 |
+
$BODY$;
|
| 75 |
+
|
| 76 |
+
ALTER FUNCTION trans.get_trade_sales_analytics(character varying, character varying, date, date)
|
| 77 |
+
OWNER TO trans_owner;
|
app/sql/release_stock_reservation.sql
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.release_stock_reservation(character varying, character varying, character varying, character varying, numeric, uuid, character varying)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.release_stock_reservation(character varying, character varying, character varying, character varying, numeric, uuid, character varying);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.release_stock_reservation(
|
| 6 |
+
p_merchant_id character varying,
|
| 7 |
+
p_location_id character varying,
|
| 8 |
+
p_sku character varying,
|
| 9 |
+
p_batch_no character varying,
|
| 10 |
+
p_qty numeric,
|
| 11 |
+
p_ref_id uuid,
|
| 12 |
+
p_created_by character varying)
|
| 13 |
+
RETURNS boolean
|
| 14 |
+
LANGUAGE 'plpgsql'
|
| 15 |
+
COST 100
|
| 16 |
+
VOLATILE PARALLEL UNSAFE
|
| 17 |
+
AS $BODY$
|
| 18 |
+
BEGIN
|
| 19 |
+
-- Update stock reservation
|
| 20 |
+
UPDATE trans.scm_stock
|
| 21 |
+
SET qty_reserved = GREATEST(qty_reserved - p_qty, 0),
|
| 22 |
+
qty_available = qty_on_hand - GREATEST(qty_reserved - p_qty, 0),
|
| 23 |
+
last_updated_at = NOW()
|
| 24 |
+
WHERE merchant_id = p_merchant_id
|
| 25 |
+
AND location_id = p_location_id
|
| 26 |
+
AND sku = p_sku
|
| 27 |
+
AND batch_no = p_batch_no;
|
| 28 |
+
|
| 29 |
+
RETURN TRUE;
|
| 30 |
+
END;
|
| 31 |
+
$BODY$;
|
| 32 |
+
|
| 33 |
+
ALTER FUNCTION trans.release_stock_reservation(character varying, character varying, character varying, character varying, numeric, uuid, character varying)
|
| 34 |
+
OWNER TO trans_owner;
|
app/sql/reserve_stock.sql
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- FUNCTION: trans.reserve_stock(character varying, character varying, character varying, character varying, numeric, uuid, character varying)
|
| 2 |
+
|
| 3 |
+
-- DROP FUNCTION IF EXISTS trans.reserve_stock(character varying, character varying, character varying, character varying, numeric, uuid, character varying);
|
| 4 |
+
|
| 5 |
+
CREATE OR REPLACE FUNCTION trans.reserve_stock(
|
| 6 |
+
p_merchant_id character varying,
|
| 7 |
+
p_location_id character varying,
|
| 8 |
+
p_sku character varying,
|
| 9 |
+
p_batch_no character varying,
|
| 10 |
+
p_qty numeric,
|
| 11 |
+
p_ref_id uuid,
|
| 12 |
+
p_created_by character varying)
|
| 13 |
+
RETURNS boolean
|
| 14 |
+
LANGUAGE 'plpgsql'
|
| 15 |
+
COST 100
|
| 16 |
+
VOLATILE PARALLEL UNSAFE
|
| 17 |
+
AS $BODY$
|
| 18 |
+
DECLARE
|
| 19 |
+
v_available_qty NUMERIC(14,3);
|
| 20 |
+
BEGIN
|
| 21 |
+
-- Get current available quantity
|
| 22 |
+
SELECT qty_available
|
| 23 |
+
INTO v_available_qty
|
| 24 |
+
FROM trans.scm_stock
|
| 25 |
+
WHERE merchant_id = p_merchant_id
|
| 26 |
+
AND location_id = p_location_id
|
| 27 |
+
AND sku = p_sku
|
| 28 |
+
AND batch_no = p_batch_no;
|
| 29 |
+
|
| 30 |
+
-- Check if sufficient stock available
|
| 31 |
+
IF v_available_qty IS NULL OR v_available_qty < p_qty THEN
|
| 32 |
+
RAISE EXCEPTION 'Insufficient available stock for SKU: %. Available: %, Required: %',
|
| 33 |
+
p_sku, COALESCE(v_available_qty, 0), p_qty;
|
| 34 |
+
END IF;
|
| 35 |
+
|
| 36 |
+
-- Update stock reservation
|
| 37 |
+
UPDATE trans.scm_stock
|
| 38 |
+
SET qty_reserved = qty_reserved + p_qty,
|
| 39 |
+
qty_available = qty_available - p_qty,
|
| 40 |
+
last_updated_at = NOW()
|
| 41 |
+
WHERE merchant_id = p_merchant_id
|
| 42 |
+
AND location_id = p_location_id
|
| 43 |
+
AND sku = p_sku
|
| 44 |
+
AND batch_no = p_batch_no;
|
| 45 |
+
|
| 46 |
+
RETURN TRUE;
|
| 47 |
+
END;
|
| 48 |
+
$BODY$;
|
| 49 |
+
|
| 50 |
+
ALTER FUNCTION trans.reserve_stock(character varying, character varying, character varying, character varying, numeric, uuid, character varying)
|
| 51 |
+
OWNER TO trans_owner;
|