-- Zamanlanmış işin BeforeSp'si PostgreSQL'de "SELECT * FROM public.()" ile çağrıldığı için -- prosedür değil, void dönen fonksiyondur. CREATE OR REPLACE FUNCTION public."Hr_S_TimesheetNightly"() RETURNS void LANGUAGE plpgsql AS $$ DECLARE v_Today date := LOCALTIMESTAMP::date; v_Yesterday date := LOCALTIMESTAMP::date - 1; v_MonthStart date; v_PrevStart date; v_TenantId uuid; v_PeriodId uuid; v_From date; BEGIN -- Zamanlanmış iş (Timesheet Nightly, her gece 02:00). Hareketi olmayan günleri (devamsız, hafta -- tatili, resmî tatil, izinli, raporlu) kurar ve geriye dönük onaylanan izin/rapor, takvim ya da -- vardiya değişikliğini yansıtır: dünün ayı ve kapanmamışsa bir önceki ay, işlenmemiş ve kartı sonradan -- tanımlanan hareketler. -- İş host ve her kiracı için çağrılır, prosedür parametre almaz; bu yüzden veritabanındaki bütün -- kiracıları işler ve aynı gün işlenmiş kiracıyı (dönemin NightlyAt değeri) atlar. v_MonthStart := make_date(EXTRACT(YEAR FROM v_Yesterday)::integer, EXTRACT(MONTH FROM v_Yesterday)::integer, 1); v_PrevStart := (v_MonthStart - INTERVAL '1 month')::date; -- Kart numarası kullanıcı kartına sonradan girilen okutmalar yeniden işlenir. UPDATE public."Hr_T_AttendanceLog" l SET "IsProcessed" = FALSE, "ProcessError" = NULL WHERE l."IsDeleted" = FALSE AND l."ProcessError" = 'UnknownCard' AND EXISTS (SELECT 1 FROM public."AbpUsers" u WHERE (lower(u."PdksCardNo") = lower(l."CardNo") OR lower(u."RegistrationNo") = lower(l."CardNo")) AND u."IsDeleted" = FALSE AND (u."TenantId" = l."TenantId" OR (u."TenantId" IS NULL AND l."TenantId" IS NULL))); CALL public."Hr_S_AttendanceProcess"(FALSE); FOR v_TenantId IN SELECT DISTINCT "TenantId" FROM public."AbpUsers" WHERE "IsDeleted" = FALSE AND "HireDate" IS NOT NULL LOOP v_PeriodId := (SELECT "Id" FROM public."Hr_T_TimesheetPeriod" WHERE "IsDeleted" = FALSE AND "PeriodYear" = EXTRACT(YEAR FROM v_Yesterday)::integer AND "PeriodMonth" = EXTRACT(MONTH FROM v_Yesterday)::integer AND ("TenantId" = v_TenantId OR ("TenantId" IS NULL AND v_TenantId IS NULL)) LIMIT 1); -- Ay dönemi gece işinde kendiliğinden açılır. IF v_PeriodId IS NULL THEN v_PeriodId := gen_random_uuid(); INSERT INTO public."Hr_T_TimesheetPeriod" ("Id", "TenantId", "PeriodYear", "PeriodMonth", "Status", "CreationTime", "IsDeleted") VALUES (v_PeriodId, v_TenantId, EXTRACT(YEAR FROM v_Yesterday)::integer, EXTRACT(MONTH FROM v_Yesterday)::integer, 'Open', (NOW() AT TIME ZONE 'UTC'), FALSE); END IF; IF NOT EXISTS (SELECT 1 FROM public."Hr_T_TimesheetPeriod" WHERE "Id" = v_PeriodId AND "NightlyAt" >= v_Today::timestamp) THEN v_From := CASE WHEN EXISTS ( SELECT 1 FROM public."Hr_T_TimesheetPeriod" WHERE "IsDeleted" = FALSE AND "Status" = 'Closed' AND "PeriodYear" = EXTRACT(YEAR FROM v_PrevStart)::integer AND "PeriodMonth" = EXTRACT(MONTH FROM v_PrevStart)::integer AND ("TenantId" = v_TenantId OR ("TenantId" IS NULL AND v_TenantId IS NULL))) THEN v_MonthStart ELSE v_PrevStart END; CALL public."Hr_S_TimesheetCalculate"(v_TenantId, NULL, v_From, v_Yesterday, NULL); UPDATE public."Hr_T_TimesheetPeriod" SET "NightlyAt" = LOCALTIMESTAMP, "CalculatedAt" = (NOW() AT TIME ZONE 'UTC') WHERE "Id" = v_PeriodId; END IF; END LOOP; END; $$;