sozsoft-platform/configs/seeds/postgres/object/Hr_S_AttendanceProcess.sql

98 lines
4.5 KiB
MySQL
Raw Normal View History

2026-10-06 11:24:30 +00:00
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;
$$;