avicenna/service/data-hub/business-engine/db/queries/payroll.sql

239 lines
5.6 KiB
SQL

-- name: ListActiveEmployees :many
SELECT
de.id,
de.firstname,
de.surname,
de."contractStart",
de."contractEnd",
de."contractDaysWeek",
de."contractHoursWeek",
de."contractSalaryHour",
de."contractTypeName",
e.id as "dlId",
e."personTransportCertificate"
FROM "DyflexisEmployee" as de
INNER JOIN "Employee" as e ON de.id::text = e."personnelNumber"
WHERE de."contractStart" < CURRENT_DATE AND de."contractEnd" > (CURRENT_DATE - INTERVAL '2 months')
AND de.surname <> 'Shahrasebi'
ORDER BY de.firstname ASC;
-- name: GetWeeklyTimeSummaryForEmployee :many
WITH all_time_entries AS (
SELECT
DATE_TRUNC('week', "startDate") AS week_start,
SUM("duration" / 60.0) as worked_hours,
count(DISTINCT DATE_TRUNC('day', "startDate"))::float as worked_days,
0::float AS sick_hours,
0::float AS holiday_days
FROM "WorkTime"
WHERE
"startDate" BETWEEN @start_date AND @end_date
AND "userId"::int = @employee_id
AND "startDate" IS NOT NULL
GROUP BY
DATE_TRUNC('week', "startDate")
UNION ALL
SELECT
DATE_TRUNC('week', "start") AS week_start,
0::float as worked_hours,
0::float as worked_days,
SUM("hours") AS sick_hours,
0::float AS holiday_days
FROM "Sickdays"
WHERE
"start" BETWEEN @start_date AND @end_date
AND "employeeId" = @employee_id
AND "start" IS NOT NULL
GROUP BY
DATE_TRUNC('week', "start")
UNION ALL
SELECT
DATE_TRUNC('week', "date") AS week_start,
0::float as worked_hours,
0::float as worked_days,
0::float AS sick_hours,
count(*)::float AS holiday_days
FROM "Holiday"
WHERE
"date" BETWEEN @start_date AND @end_date
AND "employeeId" = @employee_id
AND "date" IS NOT NULL
GROUP BY
DATE_TRUNC('week', "date")
)
SELECT
week_start::timestamp,
SUM(worked_hours)::float AS total_worked_hours,
SUM(worked_days)::float AS total_worked_days,
SUM(sick_hours)::float AS total_sick_hours,
SUM(holiday_days)::float AS total_holiday_days
FROM all_time_entries
GROUP BY
week_start
ORDER BY
week_start;
-- name: EvaluatePunctualityForEmployee :one
WITH
planned_start_times AS (
SELECT
DISTINCT ON ("startDate"::DATE)
"startDate"::DATE AS plan_day,
"startDate" AS planned_start_time
FROM "PlannedTime" as p
WHERE
p."userId"::int = @employee_id::bigint
AND p."startDate" BETWEEN @start_date AND @end_date
AND p."startDate" IS NOT NULL
AND p.department <> 'Fortbildung'
AND p.note IS NULL
ORDER BY
"startDate"::DATE, "startDate" ASC
),
actual_start_times AS (
SELECT
DISTINCT ON ("startDate"::DATE)
"startDate"::DATE AS work_day,
"startDate" AS actual_start_time
FROM "WorkTime"
WHERE
"userId"::int = @employee_id::bigint
AND "startDate" BETWEEN @start_date AND @end_date
AND "startDate" IS NOT NULL
ORDER BY
"startDate"::DATE, "startDate" ASC
),
daily_comparison AS (
SELECT
p.plan_day,
p.planned_start_time,
a.actual_start_time,
(a.actual_start_time IS NOT NULL AND a.actual_start_time <= p.planned_start_time) AS was_punctual
FROM planned_start_times p
LEFT JOIN actual_start_times a ON p.plan_day = a.work_day
)
SELECT
COUNT(CASE WHEN was_punctual THEN 1 END) AS punctual_days
FROM daily_comparison;
-- name: IsEmployeesDepartmentNotLeitstelle :one
SELECT COALESCE(
(
(
bool_or(department LIKE '%KTW%')
OR bool_or(department LIKE '%BTW%')
OR bool_or(department LIKE '%TSW%')
)
AND
bool_and(department <> 'Leitstelle')
),
false
)::bool as meets_requirements
FROM "PlannedTime"
WHERE
"userId"::int = @employee_id::bigint
AND "startDate" BETWEEN @start_date AND @end_date
AND department IS NOT NULL;
-- name: IsEmployeesDepartmentKTW :one
SELECT COALESCE(
(
bool_or(department LIKE '%KTW%')
AND
bool_and(department <> 'Leitstelle')
),
false
)::bool as meets_requirements
FROM "PlannedTime"
WHERE
"userId"::int = @employee_id::bigint
AND "startDate" BETWEEN @start_date AND @end_date
AND department IS NOT NULL;
-- name: CountVerpflegungspauschale :one
SELECT
count(*)
FROM "WorkTime"
WHERE
duration > 480
AND "startDate" BETWEEN @start_date AND @end_date
AND "userId"::int = @employee_id::bigint;
-- name: CountTourengeldAmountInPeriod :one
WITH ToursInPeriod AS (
SELECT
(("startDate" AT TIME ZONE 'UTC') AT TIME ZONE 'Europe/Berlin')::DATE as day,
"operationId",
"occupiedKm",
CASE
WHEN "occupiedKm" <= 30 THEN 1.0
ELSE ROUND("occupiedKm" / 30.0)
END AS tour_value
FROM
"Tour"
WHERE
"check" <> 3
AND "deletedAt" IS NULL
AND (
"patientId" IS NULL
OR "patientId" NOT IN (
'b7424477-a4b2-42f7-b7e7-a4bef24f6979',
'3554e1a9-9c07-45e5-b53c-692a77e4fa9a'
)
)
-- ID's for Pause and Feierabend respectively
AND (
"carName" IS NULL
OR "carName" NOT IN (
'Storno',
'Abgabe',
'Löschen'
)
AND "carName" LIKE '%KTW%'
)
AND "startDate" >= @start_date
AND "startDate" <= @end_date
AND ("driverId" ILIKE @employee_id OR "codriverId" ILIKE @employee_id)
ORDER BY
"day"
),
DailyCounts AS (
SELECT
day,
SUM(tour_value) AS tour_amount
FROM
ToursInPeriod
GROUP BY
day
),
HighActivityDays AS (
SELECT
day,
GREATEST(0, tour_amount - 6) AS tourengeld
FROM
DailyCounts
),
TourenGeld AS (
SELECT
SUM(tourengeld)::float as tourengeld
FROM
HighActivityDays
)
SELECT
COALESCE(tourengeld, 0.0)
FROM TourenGeld;
-- name: ListSickdaysForEmployee :many
SELECT
"start",
"end",
"days",
locked
FROM "Sickdays"
WHERE
"employeeId" = @employee_id
ORDER BY start asc;