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

124 lines
6.9 KiB
SQL
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 VIEW public."Hr_V_LeaveBalanceYear"
AS
-- Yıllık izin defteri: çalışan başına her hak ediş yılı bir satır (İş Kanunu md.53, kademeler
-- İnsan Kaynakları ayarlarından). YearNo = 0 satırı devir/düzeltmeleri ve ilk hak edişten önce
-- kullanılan izni toplar; böylece satırların toplamı bakiyeyi verir.
WITH TenantCfg AS (
SELECT t."TenantId",
COALESCE(z.Days1To5, 14)::numeric(5, 1) AS Days1To5,
COALESCE(z.Days5To15, 20)::numeric(5, 1) AS Days5To15,
COALESCE(z.Days15Plus, 26)::numeric(5, 1) AS Days15Plus,
COALESCE(z.MinDaysYoungOld, 20)::numeric(5, 1) AS MinDaysYoungOld
FROM (SELECT DISTINCT "TenantId" FROM "AbpUsers" WHERE "IsDeleted" = FALSE) t
CROSS JOIN LATERAL (
SELECT public."Hr_F_HrSetting"(t."TenantId", 'App.HrSettings.Leave.AnnualDays1To5') AS a,
public."Hr_F_HrSetting"(t."TenantId", 'App.HrSettings.Leave.AnnualDays5To15') AS b,
public."Hr_F_HrSetting"(t."TenantId", 'App.HrSettings.Leave.AnnualDays15Plus') AS c,
public."Hr_F_HrSetting"(t."TenantId", 'App.HrSettings.Leave.MinDaysYoungOld') AS d
) s
CROSS JOIN LATERAL (
SELECT CASE WHEN pg_input_is_valid(s.a, 'numeric(5,1)') THEN s.a::numeric(5, 1) END AS Days1To5,
CASE WHEN pg_input_is_valid(s.b, 'numeric(5,1)') THEN s.b::numeric(5, 1) END AS Days5To15,
CASE WHEN pg_input_is_valid(s.c, 'numeric(5,1)') THEN s.c::numeric(5, 1) END AS Days15Plus,
CASE WHEN pg_input_is_valid(s.d, 'numeric(5,1)') THEN s.d::numeric(5, 1) END AS MinDaysYoungOld
) z
),
Emp AS (
SELECT u."Id" AS EmployeeId, u."TenantId" AS TenantId,
COALESCE(u."SeniorityStartDate", u."HireDate")::date AS SeniorityStartDate,
u."BirthDate"::date AS BirthDate,
u."TerminationDate"::date AS TerminationDate,
c.Days1To5, c.Days5To15, c.Days15Plus, c.MinDaysYoungOld
FROM "AbpUsers" u
INNER JOIN TenantCfg c ON c."TenantId" IS NOT DISTINCT FROM u."TenantId"
WHERE u."IsDeleted" = FALSE
),
Years AS (
SELECT e.*, n.YearNo,
(e.SeniorityStartDate + make_interval(years => n.YearNo))::date AS AccrualDate,
(e.SeniorityStartDate + make_interval(years => n.YearNo + 1))::date AS NextPeriodDate
FROM Emp e
CROSS JOIN generate_series(1, 50) n (YearNo)
WHERE e.SeniorityStartDate IS NOT NULL
),
Entitlement AS (
SELECT y.*,
CASE
WHEN y.YearNo <= 5 THEN y.Days1To5
WHEN y.YearNo < 15 THEN y.Days5To15
ELSE y.Days15Plus
END AS BaseDays,
CASE
WHEN y.BirthDate IS NULL THEN NULL
ELSE (EXTRACT(YEAR FROM y.AccrualDate) - EXTRACT(YEAR FROM y.BirthDate))::int
- CASE WHEN (y.BirthDate + make_interval(years => (EXTRACT(YEAR FROM y.AccrualDate) - EXTRACT(YEAR FROM y.BirthDate))::int))::date
> y.AccrualDate THEN 1 ELSE 0 END
END AS AgeAtAccrual
FROM Years y
),
Accrued AS (
SELECT e.EmployeeId, e.TenantId, e.YearNo, e.AccrualDate, e.NextPeriodDate,
CASE
WHEN (e.AgeAtAccrual <= 18 OR e.AgeAtAccrual >= 50) AND e.BaseDays < e.MinDaysYoungOld THEN e.MinDaysYoungOld
ELSE e.BaseDays
END AS EntitledDays,
CASE WHEN e.AccrualDate <= LOCALTIMESTAMP::date
AND (e.TerminationDate IS NULL OR e.AccrualDate <= e.TerminationDate) THEN 1 ELSE 0 END AS IsAccrued
FROM Entitlement e
),
NextAccrual AS (
SELECT a.EmployeeId, MIN(a.AccrualDate) AS NextAccrualDate
FROM Accrued a
WHERE a.IsAccrued = 0
GROUP BY a.EmployeeId
),
Requests AS (
-- Yalnız yıllık izinden düşen türler; reddedilen talep bakiyeye girmez.
SELECT r."EmployeeId" AS EmployeeId, r."StartDate"::date AS StartDate, r."Days" AS Days,
CASE WHEN r."ApprovalStatus" = 'Onaylandı' THEN 1 ELSE 0 END AS IsApproved
FROM "Hr_T_LeaveRequest" r
INNER JOIN "Hr_T_LeaveType" t ON t."Id" = r."LeaveTypeId"
WHERE r."IsDeleted" = FALSE AND t."DeductsFromAnnualLeave" = TRUE
AND (r."ApprovalStatus" IS NULL OR r."ApprovalStatus" <> 'Reddedildi')
),
Ledger AS (
SELECT a.EmployeeId, a.TenantId, a.YearNo, a.AccrualDate, a.NextPeriodDate - 1 AS PeriodEndDate,
a.EntitledDays::numeric(38, 1) AS EntitledDays,
COALESCE((SELECT SUM(r.Days) FROM Requests r WHERE r.EmployeeId = a.EmployeeId AND r.IsApproved = 1
AND r.StartDate >= a.AccrualDate AND r.StartDate < a.NextPeriodDate), 0)::numeric(38, 1) AS UsedDays,
COALESCE((SELECT SUM(r.Days) FROM Requests r WHERE r.EmployeeId = a.EmployeeId AND r.IsApproved = 0
AND r.StartDate >= a.AccrualDate AND r.StartDate < a.NextPeriodDate), 0)::numeric(38, 1) AS PendingDays
FROM Accrued a
WHERE a.IsAccrued = 1
UNION ALL
SELECT e.EmployeeId, e.TenantId, 0, NULL::date, NULL::date,
COALESCE((SELECT SUM(x."Days") FROM "Hr_T_LeaveBalanceAdjustment" x
WHERE x."EmployeeId" = e.EmployeeId AND x."IsDeleted" = FALSE AND x."IsActive" = TRUE), 0)::numeric(38, 1),
COALESCE((SELECT SUM(r.Days) FROM Requests r WHERE r.EmployeeId = e.EmployeeId AND r.IsApproved = 1
AND (e.SeniorityStartDate IS NULL OR r.StartDate < (e.SeniorityStartDate + INTERVAL '1 year')::date)), 0)::numeric(38, 1),
COALESCE((SELECT SUM(r.Days) FROM Requests r WHERE r.EmployeeId = e.EmployeeId AND r.IsApproved = 0
AND (e.SeniorityStartDate IS NULL OR r.StartDate < (e.SeniorityStartDate + INTERVAL '1 year')::date)), 0)::numeric(38, 1)
FROM Emp e
)
-- Id'deki Guid metni SQL Server CONVERT çıktısıyla aynı kalsın diye büyük harf.
SELECT CONCAT(upper(l.EmployeeId::text), '-', l.YearNo)::varchar(49) AS "Id",
l.TenantId AS "TenantId",
l.EmployeeId AS "EmployeeId",
CONCAT(u."Name", ' ', u."Surname")::varchar(129) AS "EmployeeName",
u."DepartmentId",
u."JobPositionId",
l.YearNo AS "YearNo",
l.AccrualDate AS "AccrualDate",
l.PeriodEndDate AS "PeriodEndDate",
l.EntitledDays AS "EntitledDays",
l.UsedDays AS "UsedDays",
l.PendingDays AS "PendingDays",
(l.EntitledDays - l.UsedDays)::numeric(38, 1) AS "RemainingDays",
SUM(l.EntitledDays - l.UsedDays) OVER (PARTITION BY l.EmployeeId ORDER BY l.YearNo
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)::numeric(38, 1) AS "CumulativeRemainingDays",
na.NextAccrualDate AS "NextAccrualDate",
(SELECT a.EntitledDays FROM Accrued a WHERE a.EmployeeId = l.EmployeeId AND a.AccrualDate = na.NextAccrualDate)::numeric(5, 1) AS "NextAccrualDays"
FROM Ledger l
INNER JOIN "AbpUsers" u ON u."Id" = l.EmployeeId
LEFT JOIN NextAccrual na ON na.EmployeeId = l.EmployeeId
WHERE l.YearNo > 0 OR l.EntitledDays <> 0 OR l.UsedDays <> 0 OR l.PendingDays <> 0;