sozsoft-platform/configs/seeds/postgres/object/Inv_P_TransferValidate.sql
2026-10-14 12:07:11 +03:00

138 lines
8.8 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Tamamla: yapılan miktarlar stoğa işlenir (Inv_T_Stock, ürün biriminde, lot kırılımlı). İç konumdan çıkışta stok yetmezse
-- işlem durur; dış konumlar stok tutmaz. Envanter takibi kapalı ürün stoğa girmez. Lot/seri takipli üründe lot toplamı
-- yapılan miktara eşit olmalıdır. Sipariş kalemlerinin alınan, talep kalemlerinin teslim edilen miktarı güncellenir (iadede düşülür);
-- siparişli alım ürün–tedarikçi fiyatını yazar (Inv_P_TransferSupplierPrice).
-- Talepten az yapılan satırların kalanı aynı türde yeni belgeye (backorder) geçer.
CREATE OR REPLACE PROCEDURE public."Inv_P_TransferValidate"(p_id uuid, p_user_id uuid DEFAULT NULL)
LANGUAGE plpgsql AS $$
DECLARE v_tenant uuid; v_status varchar(16); v_kind varchar(32); v_return_of uuid; v_src uuid; v_dst uuid;
v_src_internal boolean := false; v_dst_internal boolean := false; v_dst_branch uuid; v_dst_warehouse uuid;
v_sign int; v_new uuid; v_now timestamp := NOW() AT TIME ZONE 'UTC'; v_msg varchar(512);
BEGIN
SELECT "TenantId", "Status", "OperationKind", "ReturnOfId", "SourceLocationId", "DestinationLocationId"
INTO v_tenant, v_status, v_kind, v_return_of, v_src, v_dst
FROM "Inv_T_Transfer" WHERE "Id" = p_id
FOR UPDATE;
IF v_status <> 'Ready' THEN
RAISE EXCEPTION 'Yalnız hazır belge tamamlanabilir.' USING ERRCODE = 'P0001', DETAIL = '50306';
END IF;
v_sign := CASE WHEN v_return_of IS NULL THEN 1 ELSE -1 END;
SELECT "LocationType" = 'Internal' INTO v_src_internal FROM "Inv_T_Location" WHERE "Id" = v_src;
SELECT "LocationType" = 'Internal', "BranchId", "WarehouseId" INTO v_dst_internal, v_dst_branch, v_dst_warehouse
FROM "Inv_T_Location" WHERE "Id" = v_dst;
v_src_internal := COALESCE(v_src_internal, false);
v_dst_internal := COALESCE(v_dst_internal, false);
IF NOT EXISTS (SELECT 1 FROM "Inv_T_TransferLine" WHERE "TransferId" = p_id AND "IsDeleted" = false AND "Quantity" > 0) THEN
RAISE EXCEPTION 'Yapılan miktarı girilmiş satır yok.' USING ERRCODE = 'P0001', DETAIL = '50309';
END IF;
SELECT p."Name" || ': lot/seri toplamı ' || rtrim(rtrim(z.q::text, '0'), '.') || ', yapılan miktar ' || rtrim(rtrim(l."Quantity"::text, '0'), '.') INTO v_msg
FROM "Inv_T_TransferLine" l
INNER JOIN "Inv_T_Product" p ON p."Id" = l."ProductId"
CROSS JOIN LATERAL (SELECT COALESCE(SUM(lt."Quantity"), 0) AS q FROM "Inv_T_TransferLineLot" lt WHERE lt."TransferLineId" = l."Id" AND lt."IsDeleted" = false) z
WHERE l."TransferId" = p_id AND l."IsDeleted" = false AND l."Quantity" > 0 AND p."TrackInventory" = true AND p."TrackingMethod" IN ('Lot', 'Serial')
AND z.q <> l."Quantity"
LIMIT 1;
IF v_msg IS NOT NULL THEN
RAISE EXCEPTION 'Lot/seri miktarı yapılan miktara eşit değil — %', v_msg USING ERRCODE = 'P0001', DETAIL = '50310';
END IF;
SELECT p."Name" || ' / ' || z."LotNo" INTO v_msg
FROM "Inv_T_TransferLineLot" z
INNER JOIN "Inv_T_TransferLine" l ON l."Id" = z."TransferLineId"
INNER JOIN "Inv_T_Product" p ON p."Id" = l."ProductId"
WHERE l."TransferId" = p_id AND l."IsDeleted" = false AND z."IsDeleted" = false AND p."TrackingMethod" = 'Serial'
AND (z."Quantity" <> 1 OR EXISTS (SELECT 1 FROM "Inv_T_TransferLineLot" z2
INNER JOIN "Inv_T_TransferLine" l2 ON l2."Id" = z2."TransferLineId"
WHERE l2."TransferId" = p_id AND l2."IsDeleted" = false AND z2."IsDeleted" = false
AND l2."ProductId" = l."ProductId" AND z2."LotNo" = z."LotNo" AND z2."Id" <> z."Id"))
LIMIT 1;
IF v_msg IS NOT NULL THEN
RAISE EXCEPTION 'Seri numaralı üründe her seri 1 adet ve tekil olmalıdır: %', v_msg USING ERRCODE = 'P0001', DETAIL = '50311';
END IF;
-- Stoğa işlenecek hareket: ürün × lot, ürün biriminde.
DROP TABLE IF EXISTS tmp_inv_move;
CREATE TEMP TABLE tmp_inv_move AS
SELECT m."ProductId", m."LotNo", SUM(m."Quantity") AS "Quantity", m."UomId"
FROM (SELECT l."ProductId", p."UomId",
CASE WHEN p."TrackingMethod" IN ('Lot', 'Serial') THEN z."LotNo" ELSE '' END AS "LotNo",
public."Inv_F_UomConvert"(CASE WHEN p."TrackingMethod" IN ('Lot', 'Serial') THEN z."Quantity" ELSE l."Quantity" END, l."UomId", p."UomId") AS "Quantity"
FROM "Inv_T_TransferLine" l
INNER JOIN "Inv_T_Product" p ON p."Id" = l."ProductId"
LEFT JOIN "Inv_T_TransferLineLot" z ON z."TransferLineId" = l."Id" AND z."IsDeleted" = false AND p."TrackingMethod" IN ('Lot', 'Serial')
WHERE l."TransferId" = p_id AND l."IsDeleted" = false AND l."Quantity" > 0 AND p."TrackInventory" = true) m
GROUP BY m."ProductId", m."LotNo", m."UomId";
IF v_src_internal THEN
PERFORM 1 FROM "Inv_T_Stock" s
WHERE s."LocationId" = v_src AND s."TenantId" IS NOT DISTINCT FROM v_tenant
AND (s."ProductId", s."LotNo") IN (SELECT "ProductId", "LotNo" FROM tmp_inv_move)
FOR UPDATE;
SELECT p."Name" || CASE WHEN m."LotNo" = '' THEN '' ELSE ' / ' || m."LotNo" END INTO v_msg
FROM tmp_inv_move m
INNER JOIN "Inv_T_Product" p ON p."Id" = m."ProductId"
LEFT JOIN "Inv_T_Stock" s ON s."LocationId" = v_src AND s."ProductId" = m."ProductId" AND s."LotNo" = m."LotNo"
AND s."TenantId" IS NOT DISTINCT FROM v_tenant
WHERE COALESCE(s."Quantity", 0) < m."Quantity"
LIMIT 1;
IF v_msg IS NOT NULL THEN
RAISE EXCEPTION 'Kaynak konumda yeterli stok yok: %', v_msg USING ERRCODE = 'P0001', DETAIL = '50312';
END IF;
UPDATE "Inv_T_Stock" s SET "Quantity" = s."Quantity" - m."Quantity", "LastMoveDate" = v_now, "LastModificationTime" = v_now, "LastModifierId" = p_user_id
FROM tmp_inv_move m
WHERE m."ProductId" = s."ProductId" AND m."LotNo" = s."LotNo" AND s."LocationId" = v_src AND s."TenantId" IS NOT DISTINCT FROM v_tenant;
END IF;
IF v_dst_internal THEN
UPDATE "Inv_T_Stock" s SET "Quantity" = s."Quantity" + m."Quantity", "LastMoveDate" = v_now, "LastModificationTime" = v_now, "LastModifierId" = p_user_id,
"InDate" = CASE WHEN s."Quantity" <= 0 THEN v_now ELSE s."InDate" END
FROM tmp_inv_move m
WHERE m."ProductId" = s."ProductId" AND m."LotNo" = s."LotNo" AND s."LocationId" = v_dst AND s."TenantId" IS NOT DISTINCT FROM v_tenant;
INSERT INTO "Inv_T_Stock" ("Id", "TenantId", "BranchId", "WarehouseId", "LocationId", "ProductId", "LotNo", "Quantity", "UomId", "InDate", "LastMoveDate", "CreationTime", "CreatorId", "IsDeleted")
SELECT gen_random_uuid(), v_tenant, v_dst_branch, v_dst_warehouse, v_dst, m."ProductId", m."LotNo", m."Quantity", m."UomId", v_now, v_now, v_now, p_user_id, false
FROM tmp_inv_move m
WHERE NOT EXISTS (SELECT 1 FROM "Inv_T_Stock" s
WHERE s."LocationId" = v_dst AND s."ProductId" = m."ProductId" AND s."LotNo" = m."LotNo"
AND s."TenantId" IS NOT DISTINCT FROM v_tenant);
END IF;
DROP TABLE tmp_inv_move;
UPDATE "Inv_T_Transfer"
SET "Status" = 'Done', "EffectiveDate" = v_now,
"ReceivedByUserId" = CASE WHEN v_kind = 'InternalTransfer' THEN p_user_id ELSE "ReceivedByUserId" END,
"ReceivedDate" = CASE WHEN v_kind = 'InternalTransfer' THEN v_now ELSE "ReceivedDate" END
WHERE "Id" = p_id;
UPDATE "Prc_T_PurchaseOrderLine" ol SET "ReceivedQuantity" = ol."ReceivedQuantity" + v_sign * x."Quantity"
FROM (SELECT l."PurchaseOrderLineId", SUM(public."Inv_F_UomConvert"(l."Quantity", l."UomId", pl."UomId")) AS "Quantity"
FROM "Inv_T_TransferLine" l
INNER JOIN "Prc_T_PurchaseOrderLine" pl ON pl."Id" = l."PurchaseOrderLineId"
WHERE l."TransferId" = p_id AND l."IsDeleted" = false AND l."Quantity" > 0
GROUP BY l."PurchaseOrderLineId") x
WHERE x."PurchaseOrderLineId" = ol."Id";
CALL public."Inv_P_TransferSupplierPrice"(p_id, p_user_id);
UPDATE "Prc_T_MaterialRequestItem" i SET "DeliveredQuantity" = i."DeliveredQuantity" + v_sign * x."Quantity",
"LineStatus" = CASE WHEN i."DeliveredQuantity" + v_sign * x."Quantity" >= i."Quantity" THEN 'Done'
WHEN i."LineStatus" = 'Done' THEN 'Waiting' ELSE i."LineStatus" END
FROM (SELECT l."MaterialRequestItemId", SUM(public."Inv_F_UomConvert"(l."Quantity", l."UomId", mi."UomId")) AS "Quantity"
FROM "Inv_T_TransferLine" l
INNER JOIN "Prc_T_MaterialRequestItem" mi ON mi."Id" = l."MaterialRequestItemId"
WHERE l."TransferId" = p_id AND l."IsDeleted" = false AND l."Quantity" > 0
GROUP BY l."MaterialRequestItemId") x
WHERE x."MaterialRequestItemId" = i."Id";
IF v_return_of IS NULL AND EXISTS (SELECT 1 FROM "Inv_T_TransferLine" WHERE "TransferId" = p_id AND "IsDeleted" = false AND "Quantity" < "DemandQuantity") THEN
CALL public."Inv_P_TransferCopy"(p_id, 'Backorder', p_user_id, v_new);
END IF;
CALL public."Inv_P_TransferRecalc"(p_id);
END;
$$;