181 lines
11 KiB
MySQL
181 lines
11 KiB
MySQL
|
|
-- Planlama kararı: talep kaleminin planlanacak kalanından p_plan_quantity kadarını satınalmaya ya da iç transfere ayırır; kalanın geri kalanı
|
|||
|
|
-- listede kalır. Planla diyaloğunun onayı (Prc_P_MaterialRequestPlanConfirm) her taslak plan satırı için çağırır.
|
|||
|
|
-- Purchase: tedarikçinin talebin şubesi ve deposu için taslak teklif talebi varsa kalem ona eklenir (kalem zaten oradaysa miktarı artar), yoksa
|
|||
|
|
-- talebin deposunun alım operasyon türüyle yeni taslak teklif talebi açılır (para birimi ve koşullar kontak kartından; alıcı — satınalma sorumlusu —
|
|||
|
|
-- planlayan). Fiyat tedarikçinin fiyat listesinden gelir; teklif → sipariş → alım akışı oradan sürer.
|
|||
|
|
-- Transfer: kaynak konumun serbest stoğu (Prc_V_MaterialRequestPlanSource) yetmelidir; aynı kaynak → talebin konumu için onaya
|
|||
|
|
-- girmemiş taslak iç transfer varsa satır ona, yoksa kaynak deponun iç transfer operasyon türüyle yeni taslak açılır. Kalanın tamamı transferle
|
|||
|
|
-- planlanan, satınalma payı olmayan kalem transfer belgesinin yeniden hesabında kapanır (Prc_P_MaterialRequestItemSync).
|
|||
|
|
-- Stock: stok talebin teslim konumundadır; belge açılmaz, serbest stok yetmelidir. Miktar kalemin stoktan karşılanan ve teslim edilen
|
|||
|
|
-- miktarına eklenir; satınalma payı olmayan ve kalanı biten kalem kapanır.
|
|||
|
|
CREATE OR REPLACE PROCEDURE public."Prc_P_MaterialRequestPlan"(
|
|||
|
|
p_id uuid,
|
|||
|
|
p_plan_method varchar,
|
|||
|
|
p_plan_quantity numeric(18, 4),
|
|||
|
|
p_plan_supplier_id uuid,
|
|||
|
|
p_plan_source_location_id uuid,
|
|||
|
|
p_tenant_id uuid,
|
|||
|
|
p_last_modifier_id uuid
|
|||
|
|
)
|
|||
|
|
LANGUAGE plpgsql AS $$
|
|||
|
|
DECLARE v_product uuid; v_uom varchar(64); v_due timestamp; v_reason varchar(256); v_branch uuid; v_warehouse uuid; v_location uuid;
|
|||
|
|
v_request_no varchar(32); v_remaining numeric(18, 4); v_doc uuid; v_line uuid; v_op_type uuid; v_src_warehouse uuid;
|
|||
|
|
v_free numeric(18, 4); v_no varchar(128);
|
|||
|
|
BEGIN
|
|||
|
|
-- Kalem kilitlenir: aynı kalemin eşzamanlı iki planı kalanı iki kez dağıtamaz.
|
|||
|
|
SELECT i."ProductId", i."UomId", i."DueDate", i."RequestReason", r."BranchId", r."WarehouseId", r."LocationId", r."RequestNo"
|
|||
|
|
INTO v_product, v_uom, v_due, v_reason, v_branch, v_warehouse, v_location, v_request_no
|
|||
|
|
FROM "Prc_T_MaterialRequestItem" i
|
|||
|
|
INNER JOIN "Prc_T_MaterialRequest" r ON r."Id" = i."MaterialRequestId"
|
|||
|
|
WHERE i."Id" = p_id AND i."IsDeleted" = false AND i."LineStatus" = 'Waiting' AND r."IsDeleted" = false
|
|||
|
|
AND i."TenantId" IS NOT DISTINCT FROM p_tenant_id
|
|||
|
|
AND r."ApprovalStatus" IN ('Onaylandı', 'Teklif Talebi', 'Teklif Talebi Gönderildi', 'Satınalma Siparişi')
|
|||
|
|
FOR UPDATE OF i;
|
|||
|
|
IF v_product IS NULL THEN
|
|||
|
|
RAISE EXCEPTION 'Kalem planlanamaz: talep onaylı değil ya da kalem kapalı.' USING ERRCODE = 'P0001', DETAIL = '50191';
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
SELECT "RemainingQuantity" INTO v_remaining FROM public."Prc_V_MaterialRequestItemPlan" WHERE "Id" = p_id;
|
|||
|
|
IF COALESCE(p_plan_quantity, 0) <= 0 THEN
|
|||
|
|
RAISE EXCEPTION 'Plan miktarı sıfırdan büyük olmalıdır.' USING ERRCODE = 'P0001', DETAIL = '50192';
|
|||
|
|
END IF;
|
|||
|
|
IF p_plan_quantity > v_remaining THEN
|
|||
|
|
RAISE EXCEPTION 'Plan miktarı planlanacak kalanı aşamaz (kalan: % %).', trim_scale(v_remaining), v_uom USING ERRCODE = 'P0001', DETAIL = '50193';
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
IF p_plan_method = 'Purchase' THEN
|
|||
|
|
IF p_plan_supplier_id IS NULL THEN
|
|||
|
|
RAISE EXCEPTION 'Satınalma kararında tedarikçi seçilmelidir.' USING ERRCODE = 'P0001', DETAIL = '50194';
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
SELECT "Id" INTO v_doc
|
|||
|
|
FROM "Prc_T_PurchaseRfq"
|
|||
|
|
WHERE "IsDeleted" = false AND "Status" = 'Draft' AND "SupplierId" = p_plan_supplier_id AND "BranchId" = v_branch AND "WarehouseId" = v_warehouse
|
|||
|
|
AND "TenantId" IS NOT DISTINCT FROM p_tenant_id
|
|||
|
|
ORDER BY "CreationTime" DESC
|
|||
|
|
LIMIT 1;
|
|||
|
|
|
|||
|
|
IF v_doc IS NULL THEN
|
|||
|
|
SELECT "Id" INTO v_op_type
|
|||
|
|
FROM "Inv_T_OperationType"
|
|||
|
|
WHERE "IsDeleted" = false AND "IsActive" = true AND "OperationKind" = 'Receipt' AND "WarehouseId" = v_warehouse
|
|||
|
|
ORDER BY "Name"
|
|||
|
|
LIMIT 1;
|
|||
|
|
IF v_op_type IS NULL THEN
|
|||
|
|
RAISE EXCEPTION 'Talebin deposu için aktif bir alım operasyon türü tanımlı değil.' USING ERRCODE = 'P0001', DETAIL = '50195';
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
v_doc := gen_random_uuid();
|
|||
|
|
CALL public."Adm_P_SequenceNext"('Prc.PurchaseRfq', p_tenant_id, v_no);
|
|||
|
|
INSERT INTO "Prc_T_PurchaseRfq" ("Id", "TenantId", "RfqNo", "TenderGroupId", "SupplierId", "BranchId", "OperationTypeId", "WarehouseId", "CurrencyId",
|
|||
|
|
"BuyerUserId", "IncotermId", "IncotermLocation", "PaymentTermId", "CreationTime", "CreatorId", "IsDeleted")
|
|||
|
|
SELECT v_doc, p_tenant_id, left(v_no, 32), v_doc, c."Id", v_branch, v_op_type, v_warehouse, COALESCE(c."SupplierCurrency", 'TRY'),
|
|||
|
|
p_last_modifier_id, c."PurchaseIncotermId", c."PurchaseIncotermLocation", c."PurchasePaymentTermId",
|
|||
|
|
NOW() AT TIME ZONE 'UTC', p_last_modifier_id, false
|
|||
|
|
FROM "Adm_T_Contact" c
|
|||
|
|
WHERE c."Id" = p_plan_supplier_id AND c."IsDeleted" = false;
|
|||
|
|
IF NOT FOUND THEN
|
|||
|
|
RAISE EXCEPTION 'Satınalma kararında tedarikçi seçilmelidir.' USING ERRCODE = 'P0001', DETAIL = '50194';
|
|||
|
|
END IF;
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
SELECT "Id" INTO v_line FROM "Prc_T_PurchaseRfqLine" WHERE "PurchaseRfqId" = v_doc AND "MaterialRequestItemId" = p_id AND "IsDeleted" = false LIMIT 1;
|
|||
|
|
IF v_line IS NOT NULL THEN
|
|||
|
|
UPDATE "Prc_T_PurchaseRfqLine"
|
|||
|
|
SET "Quantity" = "Quantity" + public."Inv_F_UomConvert"(p_plan_quantity, v_uom, "UomId"),
|
|||
|
|
"LastModificationTime" = NOW() AT TIME ZONE 'UTC', "LastModifierId" = p_last_modifier_id
|
|||
|
|
WHERE "Id" = v_line;
|
|||
|
|
ELSE
|
|||
|
|
INSERT INTO "Prc_T_PurchaseRfqLine" ("Id", "TenantId", "PurchaseRfqId", "ProductId", "Description", "Quantity", "UomId", "UnitPrice", "TaxRate", "Amount",
|
|||
|
|
"DeliveryDate", "MaterialRequestItemId", "CreationTime", "CreatorId", "IsDeleted")
|
|||
|
|
SELECT gen_random_uuid(), p_tenant_id, v_doc, v_product, v_reason, p_plan_quantity, v_uom,
|
|||
|
|
COALESCE((SELECT ps."Price" FROM "Inv_T_ProductSupplier" ps
|
|||
|
|
WHERE ps."ProductId" = v_product AND ps."ContactId" = p_plan_supplier_id AND ps."IsDeleted" = false
|
|||
|
|
ORDER BY ps."MinQuantity" LIMIT 1), 0),
|
|||
|
|
COALESCE(p."PurchaseTaxRate", 0), 0, v_due, p_id, NOW() AT TIME ZONE 'UTC', p_last_modifier_id, false
|
|||
|
|
FROM "Inv_T_Product" p
|
|||
|
|
WHERE p."Id" = v_product;
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
CALL public."Prc_P_PurchaseRfqRecalc"(v_doc);
|
|||
|
|
ELSIF p_plan_method = 'Transfer' THEN
|
|||
|
|
IF p_plan_source_location_id IS NULL THEN
|
|||
|
|
RAISE EXCEPTION 'İç transfer kararında kaynak konum seçilmelidir.' USING ERRCODE = 'P0001', DETAIL = '50196';
|
|||
|
|
END IF;
|
|||
|
|
-- Konum ve serbest stok kuralı diyaloğun İç Transfer ızgarasıyla aynıdır.
|
|||
|
|
SELECT "WarehouseId", "FreeQuantity" INTO v_src_warehouse, v_free
|
|||
|
|
FROM public."Prc_V_MaterialRequestPlanSource"
|
|||
|
|
WHERE "BaseId" = p_id AND "LocationId" = p_plan_source_location_id;
|
|||
|
|
IF v_src_warehouse IS NULL OR p_plan_source_location_id = v_location THEN
|
|||
|
|
RAISE EXCEPTION 'Kaynak konum, talebin teslim konumundan farklı ve ürünün stoğu olan bir iç konum olmalıdır.' USING ERRCODE = 'P0001', DETAIL = '50197';
|
|||
|
|
END IF;
|
|||
|
|
IF p_plan_quantity > v_free THEN
|
|||
|
|
RAISE EXCEPTION 'Kaynak konumda yeterli serbest stok yok (serbest: % %).', trim_scale(GREATEST(v_free, 0)), v_uom USING ERRCODE = 'P0001', DETAIL = '50198';
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
SELECT "Id" INTO v_doc
|
|||
|
|
FROM "Inv_T_Transfer"
|
|||
|
|
WHERE "IsDeleted" = false AND "OperationKind" = 'InternalTransfer' AND "Status" = 'Draft' AND "ReturnOfId" IS NULL AND "BackorderOfId" IS NULL
|
|||
|
|
AND "SourceLocationId" = p_plan_source_location_id AND "DestinationLocationId" = v_location
|
|||
|
|
AND COALESCE("ApprovalStatus", 'Onay Gerekmez') = 'Onay Gerekmez'
|
|||
|
|
AND "TenantId" IS NOT DISTINCT FROM p_tenant_id
|
|||
|
|
ORDER BY "CreationTime" DESC
|
|||
|
|
LIMIT 1;
|
|||
|
|
|
|||
|
|
IF v_doc IS NULL THEN
|
|||
|
|
SELECT "Id" INTO v_op_type
|
|||
|
|
FROM "Inv_T_OperationType"
|
|||
|
|
WHERE "IsDeleted" = false AND "IsActive" = true AND "OperationKind" = 'InternalTransfer' AND "WarehouseId" = v_src_warehouse
|
|||
|
|
ORDER BY "Name"
|
|||
|
|
LIMIT 1;
|
|||
|
|
IF v_op_type IS NULL THEN
|
|||
|
|
RAISE EXCEPTION 'Kaynak depo için aktif bir iç transfer operasyon türü tanımlı değil.' USING ERRCODE = 'P0001', DETAIL = '50199';
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
v_doc := gen_random_uuid();
|
|||
|
|
INSERT INTO "Inv_T_Transfer" ("Id", "TenantId", "BranchId", "WarehouseId", "OperationTypeId", "OperationKind", "SourceLocationId", "DestinationLocationId",
|
|||
|
|
"SourceDocument", "ResponsibleUserId", "Status", "CreationTime", "CreatorId", "IsDeleted")
|
|||
|
|
SELECT v_doc, p_tenant_id, ot."BranchId", ot."WarehouseId", ot."Id", 'InternalTransfer', p_plan_source_location_id, v_location,
|
|||
|
|
v_request_no, p_last_modifier_id, 'Draft', NOW() AT TIME ZONE 'UTC', p_last_modifier_id, false
|
|||
|
|
FROM "Inv_T_OperationType" ot
|
|||
|
|
WHERE ot."Id" = v_op_type;
|
|||
|
|
ELSE
|
|||
|
|
UPDATE "Inv_T_Transfer"
|
|||
|
|
SET "SourceDocument" = left(COALESCE("SourceDocument", '') || CASE WHEN COALESCE("SourceDocument", '') = '' THEN '' ELSE ', ' END || v_request_no, 128)
|
|||
|
|
WHERE "Id" = v_doc AND strpos(COALESCE("SourceDocument", ''), v_request_no) = 0;
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
SELECT "Id" INTO v_line FROM "Inv_T_TransferLine" WHERE "TransferId" = v_doc AND "MaterialRequestItemId" = p_id AND "IsDeleted" = false LIMIT 1;
|
|||
|
|
IF v_line IS NOT NULL THEN
|
|||
|
|
UPDATE "Inv_T_TransferLine"
|
|||
|
|
SET "DemandQuantity" = "DemandQuantity" + public."Inv_F_UomConvert"(p_plan_quantity, v_uom, "UomId"),
|
|||
|
|
"LastModificationTime" = NOW() AT TIME ZONE 'UTC', "LastModifierId" = p_last_modifier_id
|
|||
|
|
WHERE "Id" = v_line;
|
|||
|
|
ELSE
|
|||
|
|
INSERT INTO "Inv_T_TransferLine" ("Id", "TenantId", "TransferId", "ProductId", "Description", "DemandQuantity", "Quantity", "UomId", "MaterialRequestItemId",
|
|||
|
|
"CreationTime", "CreatorId", "IsDeleted")
|
|||
|
|
VALUES (gen_random_uuid(), p_tenant_id, v_doc, v_product, v_reason, p_plan_quantity, 0, v_uom, p_id, NOW() AT TIME ZONE 'UTC', p_last_modifier_id, false);
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
-- Numara, kaynak depo onaycısı ve yeniden hesap (kalemin kapanması dahil) belge kaydı sonrasıyla aynıdır.
|
|||
|
|
CALL public."Inv_P_TransferAfterSave"(v_doc, p_last_modifier_id);
|
|||
|
|
ELSIF p_plan_method = 'Stock' THEN
|
|||
|
|
SELECT "FreeQuantity" INTO v_free FROM public."Prc_V_MaterialRequestPlanSource" WHERE "BaseId" = p_id AND "LocationId" = v_location;
|
|||
|
|
IF p_plan_quantity > COALESCE(v_free, 0) THEN
|
|||
|
|
RAISE EXCEPTION 'Teslim konumunda yeterli serbest stok yok (serbest: % %).', trim_scale(GREATEST(COALESCE(v_free, 0), 0)), v_uom
|
|||
|
|
USING ERRCODE = 'P0001', DETAIL = '50198';
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
UPDATE "Prc_T_MaterialRequestItem"
|
|||
|
|
SET "FromStockQuantity" = "FromStockQuantity" + p_plan_quantity, "DeliveredQuantity" = "DeliveredQuantity" + p_plan_quantity,
|
|||
|
|
"LastModificationTime" = NOW() AT TIME ZONE 'UTC', "LastModifierId" = p_last_modifier_id
|
|||
|
|
WHERE "Id" = p_id;
|
|||
|
|
UPDATE "Prc_T_MaterialRequestItem" i SET "LineStatus" = 'Done'
|
|||
|
|
FROM public."Prc_V_MaterialRequestItemPlan" p
|
|||
|
|
WHERE p."Id" = i."Id" AND i."Id" = p_id AND p."PurchaseQuantity" = 0 AND p."RemainingQuantity" <= 0;
|
|||
|
|
ELSE
|
|||
|
|
RAISE EXCEPTION 'Karar Satınalma, İç Transfer ya da Stoktan olmalıdır.' USING ERRCODE = 'P0001', DETAIL = '50192';
|
|||
|
|
END IF;
|
|||
|
|
END;
|
|||
|
|
$$;
|