sozsoft-platform/configs/seeds/postgres/object/Mnt_S_MaintenanceInstructionSchedule.sql
2026-10-19 17:35:08 +03:00

107 lines
6.2 KiB
PL/PgSQL
Raw Permalink 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.

-- Zamanlanmış işin BeforeSp'si PostgreSQL'de "SELECT * FROM public.<ad>()" ile çağrıldığı için
-- prosedür değil, void dönen fonksiyondur.
CREATE OR REPLACE FUNCTION public."Mnt_S_MaintenanceInstructionSchedule"()
RETURNS void
LANGUAGE plpgsql
AS $$
DECLARE
v_Today date := LOCALTIMESTAMP::date;
v_due record;
v_wo uuid;
v_no varchar(128);
v_pass integer;
BEGIN
-- Zamanlanmış iş (Maintenance Instruction Schedule, her gece 01:00).
-- 0. Sonraki bakım tarihi boş olan aktif talimatın tarihi önce hesaplanır; böylece başlangıcı geçmiş ya da yeni
-- onaylanan talimatın bugünkü vadesi aynı çalıştırmada iş emri alır.
-- 1. Sonraki bakım tarihi bugün ya da geçmiş olan aktif ve onaylanmış her talimattan o vade için Taslak, Otomatik bakım
-- iş emri açar: numara Mnt.WorkOrder numaratöründen, ekip talimatın ilk ekibi, malzemeler talimattan; kullanım konumu
-- ekipmanın departmanının ilk iç konumudur. Aynı talimat ve vade için otomatik emir varsa tekrar açılmaz; önceki
-- emir kapanmamış olsa da her vade yeni emir alır.
-- 2. Aktif talimatların sonraki bakım tarihini Başlangıç Tarihi + k × periyot dizisinde bugüne eşit ya da bugünden
-- sonraki ilk tarihe taşır; Bitiş Tarihi geçmişse ya da talimat pasifse tarih boşalır.
-- İş host ve her kiracı için çağrılır, fonksiyon parametre almaz; bütün kiracıların satırlarını işler ve aynı gün tekrar
-- çalışması sonucu değiştirmez.
FOR v_pass IN 1..2 LOOP
IF v_pass = 2 THEN
FOR v_due IN
SELECT i."Id", i."TenantId", i."NextDueDate"
FROM "Mnt_T_MaintenanceInstruction" i
WHERE i."IsDeleted" = false AND i."IsActive" = true AND i."ApprovalStatus" = 'Onaylandı'
AND i."NextDueDate" IS NOT NULL AND i."NextDueDate" <= v_Today
AND NOT EXISTS (SELECT 1 FROM "Mnt_T_WorkOrder" w
WHERE w."MaintenanceInstructionId" = i."Id" AND w."Source" = 'Automatic' AND w."IsDeleted" = false
AND w."PlannedStart"::date = i."NextDueDate")
LOOP
v_wo := gen_random_uuid();
v_no := NULL;
CALL public."Adm_P_SequenceNext"('Mnt.WorkOrder', v_due."TenantId", v_no);
INSERT INTO "Mnt_T_WorkOrder" ("Id", "TenantId", "BranchId", "WorkOrderNo", "Name", "EquipmentId", "RequestDate", "MaintenanceKind",
"ResourceType", "MaintenanceTypeId", "TeamId", "Source", "MaintenanceInstructionId", "PlannedStart",
"Priority", "Status", "IsActive", "CreationTime", "IsDeleted")
SELECT v_wo, i."TenantId", i."BranchId", left(v_no, 32), left(i."Name" || ' - ' || p."Name", 256), i."EquipmentId", v_Today,
'Preventive', 'Internal', i."MaintenanceTypeId",
CASE WHEN split_part(COALESCE(i."TeamIds", ''), '|', 1) ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
THEN split_part(i."TeamIds", '|', 1)::uuid END,
'Automatic', i."Id", v_due."NextDueDate" + interval '8 hours', 0, 'Draft', true, NOW() AT TIME ZONE 'UTC', false
FROM "Mnt_T_MaintenanceInstruction" i
INNER JOIN "Stk_T_Product" p ON p."Id" = i."EquipmentId"
WHERE i."Id" = v_due."Id";
INSERT INTO "Mnt_T_WorkOrderMaterial" ("Id", "TenantId", "WorkOrderId", "ProductId", "Quantity", "UomId", "LocationId", "Description",
"CreationTime", "IsDeleted")
SELECT gen_random_uuid(), m."TenantId", v_wo, m."ProductId", m."Quantity", m."UomId",
(SELECT l."Id"
FROM "Mnt_T_MaintenanceInstruction" i
INNER JOIN "Stk_T_Product" p ON p."Id" = i."EquipmentId"
INNER JOIN "Stk_T_Location" l ON l."DepartmentId" = p."EquipmentDepartmentId"
WHERE i."Id" = v_due."Id" AND l."IsDeleted" = false AND l."IsActive" = true AND l."LocationType" = 'Internal'
ORDER BY l."Code", l."Name"
LIMIT 1),
m."Description", NOW() AT TIME ZONE 'UTC', false
FROM "Mnt_T_MaintenanceInstructionMaterial" m
WHERE m."MaintenanceInstructionId" = v_due."Id" AND m."IsDeleted" = false AND m."IsActive" = true;
CALL public."Mnt_P_WorkOrderAfterSave"(v_wo, NULL);
END LOOP;
END IF;
UPDATE "Mnt_T_MaintenanceInstruction" i SET
"NextDueDate" = CASE WHEN n."NextDate" > i."EndDate" THEN NULL ELSE n."NextDate" END
FROM (
SELECT c."Id",
CASE
WHEN c."StartDate" >= v_Today THEN c."StartDate"
WHEN c."Candidate" >= v_Today THEN c."Candidate"
WHEN c."IsMonth" THEN (c."StartDate" + make_interval(months => (c."K" + 1) * c."Step"))::date
ELSE c."StartDate" + (c."K" + 1) * c."Step"
END AS "NextDate"
FROM (
SELECT k.*,
CASE WHEN k."IsMonth" THEN (k."StartDate" + make_interval(months => k."K" * k."Step"))::date
ELSE k."StartDate" + k."K" * k."Step" END AS "Candidate"
FROM (
SELECT s.*,
(CASE WHEN s."IsMonth"
THEN ((EXTRACT(YEAR FROM v_Today) - EXTRACT(YEAR FROM s."StartDate")) * 12
+ EXTRACT(MONTH FROM v_Today) - EXTRACT(MONTH FROM s."StartDate"))::integer
ELSE v_Today - s."StartDate" END) / s."Step" AS "K"
FROM (
SELECT x."Id", x."StartDate",
x."PeriodUnit" IN ('Month', 'Year') AS "IsMonth",
CASE x."PeriodUnit" WHEN 'Week' THEN 7 * x."PeriodValue" WHEN 'Year' THEN 12 * x."PeriodValue" ELSE x."PeriodValue" END AS "Step"
FROM "Mnt_T_MaintenanceInstruction" x
WHERE x."IsDeleted" = FALSE AND x."IsActive" = TRUE AND x."PeriodValue" > 0
AND (v_pass = 2 OR x."NextDueDate" IS NULL)
) s
) k
) c
) n
WHERE n."Id" = i."Id";
END LOOP;
UPDATE "Mnt_T_MaintenanceInstruction" SET "NextDueDate" = NULL
WHERE "NextDueDate" IS NOT NULL AND ("IsDeleted" = TRUE OR "IsActive" = FALSE OR "PeriodValue" <= 0);
END;
$$;