sozsoft-platform/configs/seeds/postgres/object/Hr_S_AttendanceProcess.sql
2026-10-06 14:24:30 +03:00

97 lines
4.5 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.

CREATE OR REPLACE PROCEDURE public."Hr_S_AttendanceProcess"(
p_FailOnClosed boolean DEFAULT TRUE
)
LANGUAGE plpgsql
AS $$
DECLARE
v_Key record;
BEGIN
-- İşlenmemiş hareketleri (ekran, Excel import, PDKS ucu; silinenler dahil) işler: çalışanı kullanıcı
-- kartındaki PDKS Kart No'dan (yoksa Sicil No'dan) bulur, hareketin iş gününü vardiyaya göre belirler ve etkilenen günlerin puantajını
-- yeniden hesaplar. Ekrandan gelen değişiklik kapalı döneme düşerse kayıt geri alınır
-- (p_FailOnClosed = TRUE); PDKS ve gece işinde satır hatalı işaretlenir.
-- Kart/sicil eşleşmesi SQL Server harmanlaması gibi büyük/küçük harf duyarsızdır.
DROP TABLE IF EXISTS ap_log;
CREATE TEMP TABLE ap_log
(
Id uuid PRIMARY KEY, TenantId uuid NULL, EmployeeId uuid NULL,
CardNo varchar(64) NULL, EventTime timestamp, IsDeleted boolean, OldWorkDate date NULL,
NewWorkDate date NULL, Error varchar(32) NULL
) ON COMMIT DROP;
INSERT INTO ap_log (Id, TenantId, EmployeeId, CardNo, EventTime, IsDeleted, OldWorkDate)
SELECT "Id", "TenantId", "EmployeeId", "CardNo", "EventTime", "IsDeleted", "WorkDate"
FROM public."Hr_T_AttendanceLog"
WHERE "IsProcessed" = FALSE;
IF NOT EXISTS (SELECT 1 FROM ap_log) THEN
RETURN;
END IF;
UPDATE ap_log a
SET EmployeeId = u.Id
FROM (
SELECT a2.Id AS LogId, (
SELECT x."Id"
FROM public."AbpUsers" x
WHERE (lower(x."PdksCardNo") = lower(a2.CardNo) OR lower(x."RegistrationNo") = lower(a2.CardNo)) AND x."IsDeleted" = FALSE
AND (x."TenantId" = a2.TenantId OR (x."TenantId" IS NULL AND a2.TenantId IS NULL))
ORDER BY CASE WHEN lower(x."PdksCardNo") = lower(a2.CardNo) THEN 0 ELSE 1 END, x."IsActive" DESC NULLS LAST
LIMIT 1) AS Id
FROM ap_log a2
WHERE a2.EmployeeId IS NULL AND a2.CardNo IS NOT NULL AND a2.CardNo <> ''
) u
WHERE u.LogId = a.Id AND u.Id IS NOT NULL;
UPDATE ap_log SET Error = 'UnknownCard' WHERE EmployeeId IS NULL AND IsDeleted = FALSE;
UPDATE ap_log a
SET NewWorkDate = (a.EventTime - s."DayOffset" * INTERVAL '1 minute')::date
FROM public."Hr_V_AttendanceShift" s
WHERE s."EmployeeId" = a.EmployeeId
AND a.IsDeleted = FALSE AND a.Error IS NULL;
-- Kapalı dönem: hareketin eski ya da yeni günü kapalı aya düşüyorsa.
UPDATE ap_log a
SET Error = 'ClosedPeriod'
WHERE EXISTS (
SELECT 1 FROM public."Hr_T_TimesheetPeriod" p
WHERE p."IsDeleted" = FALSE AND p."Status" = 'Closed'
AND (p."TenantId" = a.TenantId OR (p."TenantId" IS NULL AND a.TenantId IS NULL))
AND ((p."PeriodYear" = EXTRACT(YEAR FROM a.OldWorkDate)::integer AND p."PeriodMonth" = EXTRACT(MONTH FROM a.OldWorkDate)::integer)
OR (p."PeriodYear" = EXTRACT(YEAR FROM a.NewWorkDate)::integer AND p."PeriodMonth" = EXTRACT(MONTH FROM a.NewWorkDate)::integer)));
IF p_FailOnClosed = TRUE AND EXISTS (SELECT 1 FROM ap_log WHERE Error = 'ClosedPeriod') THEN
RAISE EXCEPTION 'Kapalı puantaj dönemine ait hareket eklenemez, değiştirilemez ya da silinemez. Dönemi İnsan Kaynakları açabilir.'
USING ERRCODE = 'P0001', DETAIL = '51200';
END IF;
UPDATE public."Hr_T_AttendanceLog" l
SET "EmployeeId" = a.EmployeeId,
"WorkDate" = CASE WHEN a.Error = 'ClosedPeriod' THEN l."WorkDate" ELSE a.NewWorkDate END,
"ProcessError" = a.Error,
"Source" = COALESCE(l."Source", 'Import'),
"IsProcessed" = TRUE
FROM ap_log a
WHERE a.Id = l."Id";
-- Etkilenen günler: hareketin eski günü (taşındıysa ya da silindiyse) ve yeni günü.
DROP TABLE IF EXISTS ap_keys;
CREATE TEMP TABLE ap_keys (TenantId uuid NULL, EmployeeId uuid, FromDate date, ToDate date) ON COMMIT DROP;
INSERT INTO ap_keys (TenantId, EmployeeId, FromDate, ToDate)
SELECT k.TenantId, k.EmployeeId, MIN(k.D), MAX(k.D)
FROM (
SELECT TenantId, EmployeeId, OldWorkDate AS D FROM ap_log
WHERE EmployeeId IS NOT NULL AND OldWorkDate IS NOT NULL AND COALESCE(Error, '') <> 'ClosedPeriod'
UNION ALL
SELECT TenantId, EmployeeId, NewWorkDate FROM ap_log
WHERE EmployeeId IS NOT NULL AND NewWorkDate IS NOT NULL AND Error IS NULL
) k
GROUP BY k.TenantId, k.EmployeeId;
FOR v_Key IN SELECT TenantId, EmployeeId, FromDate, ToDate FROM ap_keys LOOP
CALL public."Hr_S_TimesheetCalculate"(v_Key.TenantId, v_Key.EmployeeId, v_Key.FromDate, v_Key.ToDate, NULL);
END LOOP;
END;
$$;