implement latest changes to employee payroll process
- Add ContractDaysWeek - Add Sickness Days to employee export sheet - Add Gesundheitsbonus value per employee - Additional fixes
This commit is contained in:
parent
156733f65a
commit
0951282f11
|
|
@ -1,3 +1,5 @@
|
||||||
|
daten.csv
|
||||||
|
|
||||||
tmp/
|
tmp/
|
||||||
|
|
||||||
# Binaries for programs and plugins
|
# Binaries for programs and plugins
|
||||||
|
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
,,,Vertrag,Vertrag,Vertrag,Vertrag,Vertrag,Vertrag,Vertrag,Vertrag,"Stunden innerhalb der Soll-Stunden","Stunden innerhalb der Soll-Stunden","Stunden innerhalb der Soll-Stunden","Stunden innerhalb der Soll-Stunden","Stunden innerhalb der Soll-Stunden","Stunden innerhalb der Soll-Stunden",Ist-/Soll-Stunden,Ist-/Soll-Stunden,Ist-/Soll-Stunden,Ist-/Soll-Stunden,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Berechnung,Salden,Salden,Salden,Salden,Salden,Salden,Salden,Salden,Salden,Auszahlen,Auszahlen,Auszahlen,Auszahlen,Auszahlen,Auszahlen,Auszahlen,Auszahlen,Auszahlen,Auszahlen,Auszahlen
|
|
||||||
,,,,,,,,,,,"Gearbeitete Stunden","Gearbeitete Stunden","Urlaub nehmen","Urlaub nehmen",Krankheitsstunden,Krankheitsstunden,Gesamt,Gesamt,Vertrag,Vertrag,Plus/Min,Mehrstunden,Überstunden,"Zuschlag P-Schein","Krank ohne AU","Krank ohne AU","Nachtzuschlag 25 (25%)","Nachtzuschlag 25 (25%)","Nachtzuschlag 40 (40%)","Nachtzuschlag 40 (40%)","Sonntagszuschlag (50%)","Sonntagszuschlag (50%)","Feiertagszuschlag (125%)","Feiertagszuschlag (125%)","Verpfl.-pauschale (14%)","Samstagzuschlag (15%)","Samstagzuschlag (15%)",Zeitausgleich,Zeitausgleich,Zeitausgleich,Zeitausgleich,Zeitausgleich,Urlaub,Urlaub,Urlaub,Urlaub,Mehrstunden,"Überstunden auszahlen",Fahrtkosten,Verpflegungspauschale,"Zuschlag P-Schein",25%,40%,50%,125%,14%,15%
|
|
||||||
Persnr.,Nachname,Vorname,Art,P-Schein,"Recht auf Zuschläge?",Start,Tage,Stunden,Max,"Urlaubstage pro Jahr",Tage,Stunden,Tage,Stunden,Tage,Stunden,Tage,Stunden,Tage,Stunden,Stunden,Stunden,Stunden,anzahl,Tage,Stunden,Tage,Stunden,Tage,Stunden,Tage,Stunden,Tage,Stunden,Tage,Tage,Stunden,Start,+/-,Änderungen,Auszahlen,Jetzt,Start,Abbau,Korrektur,Jetzt,Stunden,Stunden,km,Tage,Anzahl,Stunden,Stunden,Stunden,Stunden,Stunden,Stunden
|
|
||||||
169,Safari,"Abdul Latif ",Fest,Ja,Ja,2025-09-01,5.00,40.00,0.00,20,20,180.4167,5,40,0,0,25,220.41666666667,21.667,173.333,47.08366666667,0.00033333332999064,47.08333333334,20,0,0,0,0,0,0,0,0,2,16.166666666667,16,2,17.35,0.334,47.08366666667,47.08366666667,47.08366666667,0.334,19,5,0,14,0.00033333332999064,47.08333333334,0.00,20,20,0,0,0,16.166666666667,18.9,17.35
|
|
||||||
93,"Moshtagh Askari",Adel,Fest,Ja,Ja,2025-01-01,5.00,40.00,0.00,20,25,218.4167,0,0,0,0,25,218.41666666667,21.667,173.333,45.08366666667,0.00033333332999064,45.08333333334,25,0,0,0,0,0,0,0,0,2,18.65,20,3,24.95,0.007,45.08366666667,45.08366666667,45.08366666667,0.0069999999999979,31,0,0,31,0.00033333332999064,45.08333333334,0.00,25,25,0,0,0,18.65,14.816666666667,24.95
|
|
||||||
18,Mihailescu,"Adrian Lucian",Fest,Ja,Ja,2025-09-01,5.00,40.00,0.00,20,21,177.5667,0,0,0,0,21,177.56666666667,21.667,173.333,4.23366666667,0.00033333332999064,4.23333333334,21,0,0,0,0,0,0,0,0,1,8.6333333333333,15,3,24.116666666667,0,4.23366666667,4.23366666667,4.23366666667,0,20,0,0,20,0.00033333332999064,4.23333333334,0.00,18,21,0,0,0,8.6333333333333,11.1,24.116666666667
|
|
||||||
,"Esmaeili Dashtbayaz",Amin,Fest,Nein,Ja,2025-04-01,5.00,40.00,0.00,,20,171.2667,0,0,0,0,20,171.26666666667,21.667,173.333,-2.06633333333,0,0,,0,0,0,0,0,0,0,0,0,0,18,2,16.083333333333,0,-2.06633333333,-2.06633333333,0,-2.06633333333,-3,0,15,12,0,0,0.00,20,0,0,0,0,0,11.183333333333,16.083333333333
|
|
||||||
,Ahmadpour,Amirhossein,Fest,Ja,Ja,2025-09-01,5.00,40.00,0.00,24,21,193.6333,2,16,0,0,23,209.63333333333,21.667,173.333,36.30033333333,0.00033333332999064,36.3,21,0,0,0,0,0,0,1,8.4666666666667,1,8.7833333333333,19,0,0,0,36.30033333333,36.30033333333,36.30033333333,0,-2,2,13,9,0.00033333332999064,36.3,0.00,21,21,0,0,8.4666666666667,8.7833333333333,24.383333333333,0
|
|
||||||
188,"Malani Karizi",Arasch,Fest,Nein,Ja,2025-09-01,5.00,40.00,0.00,20,24,211.9833,0,0,0,0,24,211.98333333333,21.667,173.333,38.65033333333,0.00033333332999064,38.65,,0,0,6,2.6,0,0,0,0,1,8.25,20,3,24.7,-147.647,38.65033333333,38.65033333333,0,-108.99666666667,5,0,0,5,0,0,0.00,24,0,2.6,0,0,8.25,16.433333333333,24.7
|
|
||||||
113,Ziaudin,Atiq,Fest,Ja,Ja,2025-02-24,5.00,40.00,0.00,20,23,194.3167,0,0,0,0,23,194.31666666667,21.667,173.333,20.98366666667,0.00033333332999064,20.98333333334,23,0,0,0,0,0,0,0,0,1,6.4333333333333,20,2,15.05,14.047,20.98366666667,20.98366666667,20.98366666667,14.047,9,0,0,9,0.00033333332999064,20.98333333334,0.00,21,23,0,0,0,6.4333333333333,12.833333333333,15.05
|
|
||||||
,Rahmati,Behnam,Fest,Ja,Ja,2025-04-01,5.00,40.00,0.00,,20,176.05,0,0,0,0,20,176.05,21.667,173.333,2.717,0.00033333332999064,2.71666666667,20,1,8.5,0,0,0,0,0,0,0,0,20,0,0,0,2.717,2.717,2.717,0,-2,0,15,13,0.00033333332999064,2.71666666667,0.00,20,20,0,0,0,0,16.05,0
|
|
||||||
,Altner,"Christian Van Manh",Fest,Ja,Ja,2025-10-01,5.00,40.00,0.00,20,22,184.0833,0,0,0,0,22,184.08333333333,21.667,173.333,10.75033333333,0.00033333332999064,10.75,22,0,0,1,0.2,0,0,0,0,1,7.9333333333333,20,1,8.0166666666667,0,10.75033333333,10.75033333333,10.75033333333,0,0,0,2,2,0.00033333332999064,10.75,0.00,21,22,0.2,0,0,7.9333333333333,7.9333333333333,8.0166666666667
|
|
||||||
,Aba,Cuan,Fest,Nein,Ja,2025-08-01,5.00,40.00,0.00,,8,50.25,6,39,0,0,14,89.25,21.667,173.333,-84.083,0,0,,0,0,0,0,0,0,0,0,0,0,0,0,0,-144.25,-84.083,-84.083,0,-228.333,0,6,10,4,0,0,0.00,,0,0,0,0,0,0,0
|
|
||||||
,Haghighivand,Danial,Fest,Nein,Ja,2025-04-01,5.00,40.00,0.00,,19,166.0333,2,16,0,0,21,182.03333333333,21.667,173.333,8.70033333333,0.00033333332999064,8.7,,0,0,0,0,0,0,0,0,0,0,19,0,0,0,8.70033333333,8.70033333333,8.70033333333,0,-10,2,15,3,0.00033333332999064,8.7,0.00,19,0,0,0,0,0,14.033333333333,0
|
|
||||||
,Mohammadi,Danial,Fest,Ja,Ja,2025-01-01,5.00,40.00,0.00,20,21,182.8667,0,0,0,0,21,182.86666666667,21.667,173.333,9.53366666667,0.00033333332999064,9.53333333334,21,0,0,0,0,0,0,0,0,1,8.3333333333333,18,2,16.616666666667,0,9.53366666667,9.53366666667,9.53366666667,0,7,0,0,7,0.00033333332999064,9.53333333334,0.00,20,21,0,0,0,8.3333333333333,13.916666666667,16.616666666667
|
|
||||||
,Shahrasebi,Danial,Fest,,,2021-05-01,0.00,0.00,0.00,,,,0,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5,0,0,,,0,0,0,0,0,0,0
|
|
||||||
,Emkani,Daniel,Fest,Nein,Ja,2025-07-15,3.00,25.00,0.00,,14,118.45,0,0,0,0,14,118.45,13,108.333,10.117,10.117,0,,0,0,0,0,0,0,0,0,1,8.6833333333333,0,2,13.3,0,10.117,10.117,10.117,0,0,0,7,7,10.117,0,0.00,12,0,0,0,0,8.6833333333333,0,13.3
|
|
||||||
,Lolies,Danny,Fest,Ja,Ja,2025-03-01,5.00,40.00,0.00,,19,158.9,0,0,1,8.5,20,167.4,21.667,173.333,-5.933,0,0,19,3,24,0,0,0,0,0,0,1,5.55,15,2,17.05,0,-5.933,-5.933,0,-5.933,10,0,0,10,0,0,0.00,17,19,0,0,0,5.55,11.05,17.05
|
|
||||||
,Hastedt,David,Fest,Nein,Ja,2025-01-27,4.00,32.00,0.00,20,14,112.3167,0,0,4,32,18,144.31666666667,17.333,138.667,5.64966666667,5.64966666667,0,,0,0,0,0,0,0,0,0,0,0,11,0,0,0,5.64966666667,5.64966666667,5.64966666667,0,2,0,0,2,5.64966666667,0,0.00,11,0,0,0,0,0,7.4166666666667,0
|
|
||||||
2,Shahrasebi,David,Fest,Ja,Ja,2022-10-01,5.00,40.00,0.00,20,,0,0,0,0,0,0,0,21.667,173.333,0,0,0,,1,8.5,0,0,0,0,0,0,0,0,0,0,0,151.34,0,0,0,151.34,2,0,0,2,0,0,,,0,0,0,0,0,0,0
|
|
||||||
,Golmohammadi,"Davood ",Fest,Ja,Ja,2025-08-01,5.00,40.00,0.00,20,20,182.2167,0,0,0,0,20,182.21666666667,21.667,173.333,8.88366666667,0.00033333332999064,8.88333333334,20,1,8,0,0,0,0,0,0,0,0,20,0,0,0,8.88366666667,8.88366666667,8.88366666667,0,-6,0,8,2,0.00033333332999064,8.88333333334,0.00,20,20,0,0,0,0,22.216666666667,0
|
|
||||||
202,Pouzesh,Esmail,Fest,Ja,Ja,2025-09-01,5.00,40.00,0.00,20,24,202.0833,0,0,0,0,24,202.08333333333,21.667,173.333,28.75033333333,0.00033333332999064,28.75,24,0,0,21,70.416666666667,9,20.6,1,9.5,4,17.816666666667,0,0,0,0,28.75033333333,28.75033333333,28.75033333333,0,12,0,0,12,0.00033333332999064,28.75,0.00,24,24,70.416666666667,20.6,9.5,17.816666666667,0,0
|
|
||||||
187,"Sajaei Khouzestani",Farid,Fest,Ja,Ja,2025-04-07,5.00,40.00,0.00,20,22,197.4333,0,0,0,0,22,197.43333333333,21.667,173.333,24.10033333333,0.00033333332999064,24.1,22,0,0,0,0,0,0,0,0,2,17.316666666667,18,2,16.366666666667,0,24.10033333333,24.10033333333,24.10033333333,0,19,0,0,19,0.00033333332999064,24.1,0.00,22,22,0,0,0,17.316666666667,19.75,16.366666666667
|
|
||||||
191,"Faridani Rad",Farzad,Fest,Ja,Ja,2025-02-01,5.00,40.00,0.00,20,21,174.0833,0,0,2,16,23,190.08333333333,21.667,173.333,16.75033333333,0.00033333332999064,16.75,21,0,0,14,44.5,2,5.6666666666667,0,0,3,16.15,5,0,0,0,16.75033333333,16.75033333333,16.75033333333,0,0,0,0,0,0.00033333332999064,16.75,0.00,21,21,44.5,5.6666666666667,0,16.15,1.7666666666667,0
|
|
||||||
,Movafagh,"Farzad ",Fest,Ja,Ja,2025-02-03,5.00,40.00,0.00,20,23,202.6167,0,0,1,8,24,210.61666666667,21.667,173.333,37.28366666667,0.00033333332999064,37.28333333334,23,0,0,0,0,0,0,0,0,0,0,20,3,24.55,0,37.28366666667,37.28366666667,37.28366666667,0,17,0,0,17,0.00033333332999064,37.28333333334,0.00,23,23,0,0,0,0,18.066666666667,24.55
|
|
||||||
89,Hashimazada,Firuz,Fest,Ja,Ja,2025-01-01,5.00,40.00,0.00,20,18,155.35,0,0,3,24,21,179.35,21.667,173.333,6.017,0.00033333332999064,6.01666666667,18,1,8,0,0,0,0,0,0,1,8.5333333333333,17,0,0,0,6.017,6.017,6.017,0,8,0,0,8,0.00033333332999064,6.01666666667,0.00,18,18,0,0,0,8.5333333333333,10.816666666667,0
|
|
||||||
,Saeedpour,Fouad,Fest,Ja,Ja,2025-09-01,5.00,40.00,0.00,,23,203.2833,0,0,0,0,23,203.28333333333,21.667,173.333,29.95033333333,0.00033333332999064,29.95,23,0,0,2,4.25,0,0,3,26.8,1,9,16,3,25.25,0,29.95033333333,29.95033333333,29.95033333333,0,26,0,0,26,0.00033333332999064,29.95,0.00,23,23,4.25,0,26.8,9,9.9833333333333,25.25
|
|
||||||
55,Khodayaran,Hossein,Fest,Ja,Ja,2025-01-01,5.00,40.00,0.00,20,13,105.3,10,80,0,0,23,185.3,21.667,173.333,11.967,0.00033333332999064,11.96666666667,13,0,0,11,31,2,5.6666666666667,0,0,2,8.1333333333333,0,0,0,0,11.967,11.967,11.967,0,16,10,0,6,0.00033333332999064,11.96666666667,0.00,12,13,31,5.6666666666667,0,8.1333333333333,0,0
|
|
||||||
206,Rasulkhani,Hossein,Fest,Ja,Ja,2025-03-06,5.00,40.00,0.00,20,23,194.8667,0,0,0,0,23,194.86666666667,21.667,173.333,21.53366666667,0.00033333332999064,21.53333333334,23,0,0,4,10.433333333333,0,0,1,9.25,1,9,13,4,32.366666666667,0,21.53366666667,21.53366666667,21.53366666667,0,29,0,0,29,0.00033333332999064,21.53333333334,0.00,23,23,10.433333333333,0,9.25,9,7.8166666666667,32.366666666667
|
|
||||||
,"Mohamed Salah","Hussin Noureldin",Fest,Ja,Ja,2025-06-06,5.00,40.00,0.00,20,22,186.5833,0,0,0,0,22,186.58333333333,21.667,173.333,13.25033333333,0.00033333332999064,13.25,22,0,0,0,0,0,0,0,0,1,8.5166666666667,18,3,24.55,0,13.25033333333,13.25033333333,13.25033333333,0,-11,0,11,0,0.00033333332999064,13.25,0.00,21,22,0,0,0,8.5166666666667,9.5166666666667,24.55
|
|
||||||
50,"Rohany Oskoee",Iman,Fest,Nein,Ja,2025-01-01,5.00,40.00,0.00,20,22,190.3833,0,0,0,0,22,190.38333333333,21.667,173.333,17.05033333333,0.00033333332999064,17.05,,0,0,0,0,0,0,0,0,1,8.7333333333333,20,1,8.0333333333333,0,17.05033333333,17.05033333333,17.05033333333,0,36,0,0,36,0.00033333332999064,17.05,0.00,22,0,0,0,0,8.7333333333333,13.616666666667,8.0333333333333
|
|
||||||
7,Salehi,Iman,Fest,Ja,Ja,2025-02-01,5.00,40.00,0.00,20,26,220.1,0,0,0,0,26,220.1,21.667,173.333,46.767,0.00033333332999064,46.76666666667,26,0,0,21,68.766666666667,7,13.483333333333,2,18.2,2,16.383333333333,0,1,8.0166666666667,-14.233,46.767,46.767,32.534,7.105427357601E-15,0,0,0,0,0.00033333332999064,32.53366666667,0.00,26,26,68.766666666667,13.483333333333,18.2,16.383333333333,0,8.0166666666667
|
|
||||||
,Krüger,Julian,Fest,Ja,Ja,2025-01-15,5.00,40.00,0.00,20,23,197.35,0,0,0,0,23,197.35,21.667,173.333,24.017,0.00033333332999064,24.01666666667,23,0,0,0,0,0,0,0,0,2,14.283333333333,0,2,15.116666666667,0,24.017,24.017,24.017,0,-30,0,38,8,0.00033333332999064,24.01666666667,0.00,19,23,0,0,0,14.283333333333,0,15.116666666667
|
|
||||||
,Hazrati,Kamyar,Fest,,Ja,2025-02-24,5.00,40.00,0.00,20,21,182.75,0,0,0,0,21,182.75,21.667,173.333,9.417,0.00033333332999064,9.41666666667,,0,0,0,0,0,0,0,0,0,0,19,2,16.616666666667,0,9.417,9.417,9.417,0,10,0,0,10,0.00033333332999064,9.41666666667,0.00,20,0,0,0,0,0,14.133333333333,16.616666666667
|
|
||||||
,Saei,Kasra,Fest,Nein,Ja,2025-08-01,5.00,40.00,0.00,,6,37.2667,10,80,0,0,16,117.26666666667,21.667,173.333,-56.06633333333,0,0,,0,0,0,0,0,0,0,0,0,0,0,0,0,-130.782,-56.06633333333,-56.06633333333,0,-186.84833333333,0,10,10,0,0,0,0.00,,0,0,0,0,0,0,0
|
|
||||||
182,Kalantari,Kaveh,Fest,Ja,Ja,2025-03-01,5.00,40.00,0.00,20,18,159.05,5,40,0,0,23,199.05,21.667,173.333,25.717,0.00033333332999064,25.71666666667,18,0,0,2,4.25,0,0,1,10.25,1,9.9,14,2,16.916666666667,0,25.717,25.717,25.717,0,22,5,0,17,0.00033333332999064,25.71666666667,0.00,18,18,4.25,0,10.25,9.9,5.7333333333333,16.916666666667
|
|
||||||
,Sahem,Khalid,Fest,Ja,Ja,2025-06-16,5.00,40.00,0.00,20,24,204.35,0,0,0,0,24,204.35,21.667,173.333,31.017,0.00033333332999064,31.01666666667,24,0,0,0,0,0,0,0,0,2,16.833333333333,19,3,26.033333333333,0,31.017,31.017,31.017,0,15,0,0,15,0.00033333332999064,31.01666666667,0.00,24,24,0,0,0,16.833333333333,9.4833333333333,26.033333333333
|
|
||||||
194,Saffarnajib,Majid,Fest,Ja,Ja,2025-04-01,3.00,21.00,0.00,16,16,133.3667,0,0,0,0,16,133.36666666667,13,91,42.36666666667,42.36666666667,0,16,0,0,0,0,0,0,0,0,0,0,16,0,0,0,42.36666666667,42.36666666667,42.36666666667,0,0,0,16,16,42.36666666667,0,0.00,16,16,0,0,0,0,5.3666666666667,0
|
|
||||||
177,Juyande,Masoud,Fest,Nein,Ja,2025-01-01,5.00,40.00,0.00,20,22,182.9,0,0,0,0,22,182.9,21.667,173.333,9.567,0.00033333332999064,9.56666666667,,0,0,21,68.1,10,23.783333333333,0,0,2,8.5166666666667,0,0,0,0.009,9.567,9.567,9.567,0.0090000000000003,-7,0,0,-7,0.00033333332999064,9.56666666667,0.00,22,0,68.1,23.783333333333,0,8.5166666666667,0,0
|
|
||||||
53,Eggerstedt,Matthias,Fest,Ja,Ja,2025-01-01,5.00,40.00,0.00,20,22,190.1333,0,0,0,0,22,190.13333333333,21.667,173.333,16.80033333333,0.00033333332999064,16.8,22,0,0,0,0,0,0,0,0,1,8.6333333333333,20,0,0,0,16.80033333333,16.80033333333,16.80033333333,0,8,0,2,10,0.00033333332999064,16.8,0.00,21,22,0,0,0,8.6333333333333,15.233333333333,0
|
|
||||||
,Arabnia,Mehdi,Fest,Ja,Ja,2025-05-05,5.00,40.00,0.00,,22,194.3833,0,0,0,0,22,194.38333333333,21.667,173.333,21.05033333333,0.00033333332999064,21.05,22,0,0,0,0,0,0,0,0,0,0,20,2,15.783333333333,0,21.05033333333,21.05033333333,21.05033333333,0,-5,0,12,7,0.00033333332999064,21.05,0.00,21,22,0,0,0,0,18.6,15.783333333333
|
|
||||||
,"Jalali Wagener",Mehdi,Fest,Ja,Ja,2025-02-01,5.00,40.00,0.00,,24,204.4833,0,0,0,0,24,204.48333333333,21.667,173.333,31.15033333333,0.00033333332999064,31.15,24,0,0,0,0,0,0,0,0,1,8.5333333333333,21,2,16.35,0,31.15033333333,31.15033333333,31.15033333333,0,-2,0,1,-1,0.00033333332999064,31.15,0.00,24,24,0,0,0,8.5333333333333,11.6,16.35
|
|
||||||
,Taghadosi,Mehdi,Fest,Ja,Ja,2025-08-08,5.00,40.00,0.00,,22,188.9333,0,0,0,0,22,188.93333333333,21.667,173.333,15.60033333333,0.00033333332999064,15.6,22,0,0,0,0,0,0,0,0,1,6.3,19,2,16.6,0,15.60033333333,15.60033333333,15.60033333333,0,10,0,0,10,0.00033333332999064,15.6,0.00,21,22,0,0,0,6.3,14.033333333333,16.6
|
|
||||||
,Mazidi,Mehrdad,Fest,Ja,Ja,2025-07-01,5.00,40.00,0.00,20,21,183.1667,0,0,0,0,21,183.16666666667,21.667,173.333,9.83366666667,0.00033333332999064,9.83333333334,21,0,0,0,0,0,0,0,0,1,8.1166666666667,18,2,17.033333333333,0,9.83366666667,9.83366666667,9.83366666667,0,0,0,10,10,0.00033333332999064,9.83333333334,0.00,21,21,0,0,0,8.1166666666667,14.016666666667,17.033333333333
|
|
||||||
165,Koell,"Melanie Nadine",Fest,Nein,Ja,2025-01-01,5.00,40.00,0.00,20,,0,0,0,4,32,4,32,21.667,173.333,-141.333,0,0,,0,0,0,0,0,0,0,0,0,0,0,0,0,-165.263,-141.333,-141.333,0,-306.596,12,0,0,12,0,0,,,0,0,0,0,0,0,0
|
|
||||||
119,Pourhossein,Milad,Fest,Ja,Ja,2025-09-01,5.00,40.00,0.00,20,15,125.6167,7,56,0,0,22,181.61666666667,21.667,173.333,8.28366666667,0.00033333332999064,8.28333333334,15,0,0,0,0,0,0,0,0,1,7.9333333333333,12,2,16.6,-57.848,8.28366666667,8.28366666667,0,-49.56433333333,-6,7,23,10,0,0,0.00,14,15,0,0,0,7.9333333333333,5.0833333333333,16.6
|
|
||||||
144,Maleki,Mohammad,Fest,Ja,Ja,2025-09-01,3.00,24.00,0.00,20,5,41.1167,0,0,0,0,5,41.116666666667,13,104,-62.883333333333,0,0,5,2,16,0,0,0,0,0,0,0,0,3,0,0,-250.962,-62.883333333333,-62.883333333333,0,-313.84533333333,-1,0,0,-1,0,0,0.00,3,5,0,0,0,0,1.4,0
|
|
||||||
217,"Rasul Khani",Mohammad,Fest,Ja,Ja,2025-03-03,5.00,40.00,0.00,20,24,209.4833,0,0,0,0,24,209.48333333333,21.667,173.333,36.15033333333,0.00033333332999064,36.15,24,0,0,1,2.25,0,0,2,17.45,1,8.25,20,1,8.0166666666667,0,36.15033333333,36.15033333333,36.15033333333,0,20,0,0,20,0.00033333332999064,36.15,0.00,24,24,2.25,0,17.45,8.25,13.516666666667,8.0166666666667
|
|
||||||
96,Sabahi,Mohammad,Fest,Ja,Ja,2025-01-01,5.00,40.00,0.00,20,18,152.5833,1,8,4,32,23,192.58333333333,21.667,173.333,19.25033333333,0.00033333332999064,19.25,18,0,0,0,0,0,0,0,0,2,16.583333333333,16,0,0,0,19.25033333333,19.25033333333,19.25033333333,0,10,1,0,9,0.00033333332999064,19.25,0.00,18,18,0,0,0,16.583333333333,8,0
|
|
||||||
78,Tajikzadeh,Mohammad,Fest,Ja,Ja,2025-01-01,5.00,40.00,0.00,20,18,152.3167,5,40,0,0,23,192.31666666667,21.667,173.333,18.98366666667,0.00033333332999064,18.98333333334,18,0,0,0,0,0,0,0,0,1,8.25,16,1,8.0833333333333,0,18.98366666667,18.98366666667,18.98366666667,0,7,5,0,2,0.00033333332999064,18.98333333334,0.00,18,18,0,0,0,8.25,7.9833333333333,8.0833333333333
|
|
||||||
,Atrafi,"Mohammad Nasir",Fest,Ja,Ja,2025-10-01,5.00,4.00,0.00,20,19,162.9667,0,0,0,0,19,162.96666666667,21.667,17.333,145.63366666667,145.63366666667,0,19,0,0,0,0,0,0,0,0,0,0,16,3,22.5,0,145.63366666667,145.63366666667,145.63366666667,0,0,0,5,5,145.63366666667,0,0.00,17,19,0,0,0,0,12.466666666667,22.5
|
|
||||||
,Amiri,"Mohammad Samir",Fest,Ja,Ja,2025-09-01,5.00,40.00,0.00,20,22,190.15,0,0,3,24,25,214.15,21.667,173.333,40.817,0.00033333332999064,40.81666666667,22,0,0,5,17.25,5,12.633333333333,1,10.166666666667,0,0,0,2,12.316666666667,0,40.817,40.817,40.817,0,11,0,0,11,0.00033333332999064,40.81666666667,0.00,20,22,17.25,12.633333333333,10.166666666667,0,0,12.316666666667
|
|
||||||
,"El Moustaiqid",Najlae,Fest,,Ja,2025-09-01,5.00,40.00,0.00,,20,151.7,1,8,0,0,21,159.7,21.667,173.333,-13.633,0,0,,0,0,0,0,0,0,0,0,0,0,0,0,0,-1140.63,-13.633,-13.633,0,-1154.263,-5,1,15,9,0,0,0.00,,0,0,0,0,0,0,0
|
|
||||||
,Jasarevic,Noel,Fest,Nein,Ja,2025-09-15,5.00,40.00,0.00,,14,116.6333,7,56,0,0,21,172.63333333333,21.667,173.333,-0.69966666667,0,0,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0.69966666667,-0.69966666667,0,-0.69966666667,0,7,6,-1,0,0,0.00,12,0,0,0,0,0,0,0
|
|
||||||
,"Sharh Ghaboos",Peyman,Fest,Ja,Ja,2025-03-01,5.00,40.00,0.00,,24,212.6333,0,0,0,0,24,212.63333333333,21.667,173.333,39.30033333333,0.00033333332999064,39.3,24,0,0,6,2.6,0,0,0,0,1,8.25,21,2,16.683333333333,0,39.30033333333,39.30033333333,39.30033333333,0,20,0,0,20,0.00033333332999064,39.3,0.00,24,24,2.6,0,0,8.25,17.1,16.683333333333
|
|
||||||
227,Feilbach,"Raoul Nikolai ",Fest,Nein,Ja,2025-09-01,5.00,40.00,0.00,20,24,215.8833,0,0,0,0,24,215.88333333333,21.667,173.333,42.55033333333,0.00033333332999064,42.55,,0,0,16,55.5,16,40.75,1,8.7,4,17.483333333333,0,0,0,0.007,42.55033333333,42.55033333333,42.55033333333,0.0069999999999979,-14,0,20,6,0.00033333332999064,42.55,0.00,24,0,55.5,40.75,8.7,17.483333333333,0,0
|
|
||||||
,Hatami,Reza,Fest,Ja,Ja,2025-09-15,5.00,40.00,0.00,20,20,173.9667,0,0,0,0,20,173.96666666667,21.667,173.333,0.63366666667,0.00033333332999064,0.63333333334,20,0,0,0,0,0,0,0,0,0,0,18,2,16.6,0,0.63366666667,0.63366666667,0.63366666666999,9.9920072216264E-15,0,0,6,6,0.00033333332999064,0.63333333334,0.00,20,20,0,0,0,0,13.366666666667,16.6
|
|
||||||
137,Pourhossein,Reza,Fest,Ja,Ja,2025-04-01,5.00,40.00,0.00,20,21,181.55,0,0,0,0,21,181.55,21.667,173.333,8.217,0.00033333332999064,8.21666666667,21,0,0,12,36.533333333333,7,15.016666666667,0,0,2,16.316666666667,7,1,8.0166666666667,0,8.217,8.217,8.217,0,29,0,0,29,0.00033333332999064,8.21666666667,0.00,20,21,36.533333333333,15.016666666667,0,16.316666666667,4.1666666666667,8.0166666666667
|
|
||||||
225,"Hosseini Jahed",Sajad,Fest,Ja,Ja,2025-03-03,5.00,40.00,0.00,20,21,193.3833,2,16,0,0,23,209.38333333333,21.667,173.333,36.05033333333,0.00033333332999064,36.05,21,0,0,0,0,0,0,1,8.4666666666667,1,8.7833333333333,18,0,0,0,36.05033333333,36.05033333333,36.05033333333,0,39,2,-17,20,0.00033333332999064,36.05,0.00,20,21,0,0,8.4666666666667,8.7833333333333,24.3,0
|
|
||||||
,Saki,Sara,Fest,Ja,Ja,2025-02-01,5.00,40.00,0.00,,14,117.6333,10,80,0,0,24,197.63333333333,21.667,173.333,24.30033333333,0.00033333332999064,24.3,14,0,0,11,35.05,0,0,1,8.7,2,16.383333333333,0,0,0,0,24.30033333333,24.30033333333,24.30033333333,0,23,10,-2,11,0.00033333332999064,24.3,0.00,14,14,35.05,0,8.7,16.383333333333,0,0
|
|
||||||
,"Perez Y Waldt",Sebastian,Fest,Nein,Ja,2024-09-23,5.00,40.00,0.00,,22,181.9,0,0,0,0,22,181.9,21.667,173.333,8.567,0.00033333332999064,8.56666666667,,0,0,4,14.1,0,0,0,0,1,8.0166666666667,11,3,24.666666666667,-756.446,8.567,8.567,0,-747.879,14,0,0,14,0,0,0.00,17,0,14.1,0,0,8.0166666666667,6.5166666666667,24.666666666667
|
|
||||||
38,Hosseini,"Seyed Hamid",Fest,Ja,Ja,2025-03-10,5.00,40.00,0.00,20,18,153.4167,0,0,5,40,23,193.41666666667,21.667,173.333,20.08366666667,0.00033333332999064,20.08333333334,18,0,0,0,0,0,0,0,0,2,16.5,15,1,8.0833333333333,0,20.08366666667,20.08366666667,20.08366666667,0,26,0,0,26,0.00033333332999064,20.08333333334,0.00,18,18,0,0,0,16.5,8.8333333333333,8.0833333333333
|
|
||||||
,Jabbari,Shahram,Fest,Nein,Ja,2025-04-01,5.00,40.00,0.00,,20,175.2167,0,0,0,0,20,175.21666666667,21.667,173.333,1.88366666667,0.00033333332999064,1.88333333334,,0,0,0,0,0,0,0,0,0,0,18,2,16.95,0,1.88366666667,1.88366666667,1.88366666667,0,-5,0,0,-5,0.00033333332999064,1.88333333334,0.00,20,0,0,0,0,0,14.266666666667,16.95
|
|
||||||
124,Imanian,Shahriyar,Fest,Ja,Ja,2025-03-10,5.00,40.00,0.00,20,12,104.2833,12,96,0,0,24,200.28333333333,21.667,173.333,26.95033333333,0.00033333332999064,26.95,12,0,0,1,0.083333333333333,0,0,1,8.35,0,0,10,1,8.1666666666667,0,26.95033333333,26.95033333333,26.95033333333,0,36,12,0,24,0.00033333332999064,26.95,0.00,12,12,0.083333333333333,0,8.35,0,7.6833333333333,8.1666666666667
|
|
||||||
164,Tokhi,Shokrollah,Fest,Ja,Ja,2025-03-04,5.00,40.00,0.00,20,18,152.6,5,40,0,0,23,192.6,21.667,173.333,19.267,0.00033333332999064,19.26666666667,18,0,0,14,47.75,9,21.483333333333,0,0,2,9.3,2,1,8.6333333333333,0,19.267,19.267,19.267,0,14,5,0,9,0.00033333332999064,19.26666666667,0.00,18,18,47.75,21.483333333333,0,9.3,0.93333333333333,8.6333333333333
|
|
||||||
210,Rahimzadeh,Siamak,Fest,Ja,Ja,2025-03-01,5.00,40.00,0.00,20,23,197.5,0,0,0,0,23,197.5,21.667,173.333,24.167,0.00033333332999064,24.16666666667,23,0,0,0,0,0,0,0,0,2,16.25,18,3,25.016666666667,0.027,24.167,24.167,24.167,0.027000000000001,39,0,0,39,0.00033333332999064,24.16666666667,0.00,23,23,0,0,0,16.25,12.233333333333,25.016666666667
|
|
||||||
,Florescu,Silviu-Cezar,Fest,Nein,Ja,2025-10-01,5.00,40.00,0.00,,20,173.5333,0,0,0,0,20,173.53333333333,21.667,173.333,0.20033333333001,0.00033333332999064,0.20000000000002,,0,0,2,0.28333333333333,0,0,0,0,0,0,19,1,8.35,0,0.20033333333001,0.20033333333001,0.20033333333001,0,9,0,0,9,0.00033333332999064,0.20000000000002,0.00,20,0,0.28333333333333,0,0,0,12.9,8.35
|
|
||||||
,Vafaei,Soheil,Fest,Ja,Ja,2025-04-01,5.00,40.00,0.00,,18,155.4833,3,24,1,8,22,187.48333333333,21.667,173.333,14.15033333333,0.00033333332999064,14.15,18,0,0,0,0,0,0,0,0,0,0,17,1,8.0166666666667,0,14.15033333333,14.15033333333,14.15033333333,0,-10,3,0,-13,0.00033333332999064,14.15,0.00,18,18,0,0,0,0,11.466666666667,8.0166666666667
|
|
||||||
,Toraman,"Tolga Can",Fest,Nein,Ja,2025-09-15,5.00,40.00,0.00,20,22,183.1333,0,0,0,0,22,183.13333333333,21.667,173.333,9.80033333333,0.00033333332999064,9.8,,0,0,0,0,0,0,1,9.5,0,0,17,2,16.3,0,9.80033333333,9.80033333333,9.80033333333,0,0,0,0,0,0.00033333332999064,9.8,0.00,20,0,0,0,9.5,0,6.3666666666667,16.3
|
|
||||||
14,Haugg,Uwe,Fest,Ja,Ja,2025-01-01,4.00,32.00,0.00,18,6,50.6167,8,64,4,32,18,146.61666666667,17.333,138.667,7.94966666667,7.94966666667,0,6,0,0,0,0,0,0,0,0,0,0,5,1,6.9666666666667,-0.2,7.94966666667,7.94966666667,7.74966666667,0,-10,8,0,-18,7.74966666667,0,0.00,5,6,0,0,0,0,3.65,6.9666666666667
|
|
||||||
231,Shokripour,Vahid,Fest,Ja,Ja,2025-01-01,5.00,40.00,0.00,20,24,208.1167,0,0,0,0,24,208.11666666667,21.667,173.333,34.78366666667,0.00033333332999064,34.78333333334,24,0,0,0,0,0,0,1,9.5,2,16.166666666667,18,3,25.333333333333,0,34.78366666667,34.78366666667,34.78366666667,0,35,0,0,35,0.00033333332999064,34.78333333334,0.00,24,24,0,0,9.5,16.166666666667,13.116666666667,25.333333333333
|
|
||||||
226,Konak,Zidar,Fest,Nein,Ja,2025-05-01,5.00,40.00,0.00,20,22,183.65,0,0,0,0,22,183.65,21.667,173.333,10.317,0.00033333332999064,10.31666666667,,0,0,0,0,0,0,2,18.5,1,7,0,2,16.433333333333,0,10.317,10.317,10.317,0,16,0,0,16,0.00033333332999064,10.31666666667,0.00,15,0,0,0,18.5,7,0,16.433333333333
|
|
||||||
,,,,,,,,,,,1293,11086.0499,101,799,32,256.5,1426,12141.55,1438.687,11344.646,970.23699999999,,,,9,73,175,515.91666666667,67,159.08333333333,20,181.8,66,479.58333333333,841,91,738.55,,970.23699999999,970.23699999999,1267.0006666666,-2939.2536666667,,101,241,709,211.53366666651,1055.4670000001,0,1209,,515.91666666667,159.08333333333,181.8,479.58333333333,607.15,738.55
|
|
||||||
|
|
|
@ -211,7 +211,8 @@ CREATE TABLE public."DyflexisEmployee" (
|
||||||
"contractHoursWeek" double precision NOT NULL,
|
"contractHoursWeek" double precision NOT NULL,
|
||||||
"contractSalaryHour" double precision NOT NULL,
|
"contractSalaryHour" double precision NOT NULL,
|
||||||
"contractTypeName" text,
|
"contractTypeName" text,
|
||||||
"internalId" uuid DEFAULT gen_random_uuid() NOT NULL
|
"internalId" uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"contractDaysWeek" integer DEFAULT 0 NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -591,6 +592,23 @@ CREATE TABLE public."Tour" (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: TourFile; Type: TABLE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public."TourFile" (
|
||||||
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"tourId" text NOT NULL,
|
||||||
|
"ticketId" text NOT NULL,
|
||||||
|
"storagePath" text NOT NULL,
|
||||||
|
"originalFilename" text NOT NULL,
|
||||||
|
"mimeType" text NOT NULL,
|
||||||
|
"fileSizeBytes" integer NOT NULL,
|
||||||
|
"dlUploadStatus" text DEFAULT 'pending'::text NOT NULL,
|
||||||
|
"createdAt" timestamp(3) without time zone DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: TourSource; Type: TABLE; Schema: public; Owner: -
|
-- Name: TourSource; Type: TABLE; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
@ -1025,6 +1043,14 @@ ALTER TABLE ONLY public."Ticket"
|
||||||
ADD CONSTRAINT "Ticket_pkey" PRIMARY KEY (id);
|
ADD CONSTRAINT "Ticket_pkey" PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: TourFile TourFile_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."TourFile"
|
||||||
|
ADD CONSTRAINT "TourFile_pkey" PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: TourSource TourSource_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
-- Name: TourSource TourSource_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
@ -1104,6 +1130,13 @@ ALTER TABLE ONLY public._prisma_migrations
|
||||||
CREATE UNIQUE INDEX "CostType_id_key" ON public."CostType" USING btree (id);
|
CREATE UNIQUE INDEX "CostType_id_key" ON public."CostType" USING btree (id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: TourFile_tourId_ticketId_idx; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX "TourFile_tourId_ticketId_idx" ON public."TourFile" USING btree ("tourId", "ticketId");
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: Tour_operationId_key; Type: INDEX; Schema: public; Owner: -
|
-- Name: Tour_operationId_key; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ SELECT
|
||||||
de.surname,
|
de.surname,
|
||||||
de."contractStart",
|
de."contractStart",
|
||||||
de."contractEnd",
|
de."contractEnd",
|
||||||
|
de."contractDaysWeek",
|
||||||
de."contractHoursWeek",
|
de."contractHoursWeek",
|
||||||
de."contractSalaryHour",
|
de."contractSalaryHour",
|
||||||
de."contractTypeName",
|
de."contractTypeName",
|
||||||
|
|
@ -119,6 +120,25 @@ SELECT
|
||||||
COUNT(CASE WHEN was_punctual THEN 1 END) AS punctual_days
|
COUNT(CASE WHEN was_punctual THEN 1 END) AS punctual_days
|
||||||
FROM daily_comparison;
|
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
|
-- name: IsEmployeesDepartmentKTW :one
|
||||||
SELECT COALESCE(
|
SELECT COALESCE(
|
||||||
(
|
(
|
||||||
|
|
@ -152,16 +172,7 @@ WITH ToursInPeriod AS (
|
||||||
CASE
|
CASE
|
||||||
WHEN "occupiedKm" <= 30 THEN 1.0
|
WHEN "occupiedKm" <= 30 THEN 1.0
|
||||||
ELSE ROUND("occupiedKm" / 30.0)
|
ELSE ROUND("occupiedKm" / 30.0)
|
||||||
END AS tour_value,
|
END AS tour_value
|
||||||
CASE
|
|
||||||
WHEN EXTRACT(ISODOW FROM "startDate") = 6 AND "occupiedKm" <= 30 THEN 0.5
|
|
||||||
ELSE 0.0
|
|
||||||
END AS weekend_bonus,
|
|
||||||
"infectionName",
|
|
||||||
CASE
|
|
||||||
WHEN "infectionName" = 'Covid-19' THEN 0.5
|
|
||||||
ELSE 0.0
|
|
||||||
END AS infection_bonus
|
|
||||||
FROM
|
FROM
|
||||||
"Tour"
|
"Tour"
|
||||||
WHERE
|
WHERE
|
||||||
|
|
@ -193,7 +204,7 @@ WITH ToursInPeriod AS (
|
||||||
DailyCounts AS (
|
DailyCounts AS (
|
||||||
SELECT
|
SELECT
|
||||||
day,
|
day,
|
||||||
SUM(tour_value) + SUM(weekend_bonus) + SUM(infection_bonus) AS tour_amount
|
SUM(tour_value) AS tour_amount
|
||||||
FROM
|
FROM
|
||||||
ToursInPeriod
|
ToursInPeriod
|
||||||
GROUP BY
|
GROUP BY
|
||||||
|
|
@ -215,3 +226,14 @@ TourenGeld AS (
|
||||||
SELECT
|
SELECT
|
||||||
COALESCE(tourengeld, 0.0)
|
COALESCE(tourengeld, 0.0)
|
||||||
FROM TourenGeld;
|
FROM TourenGeld;
|
||||||
|
|
||||||
|
-- name: ListSickdaysForEmployee :many
|
||||||
|
SELECT
|
||||||
|
"start",
|
||||||
|
"end",
|
||||||
|
"days",
|
||||||
|
locked
|
||||||
|
FROM "Sickdays"
|
||||||
|
WHERE
|
||||||
|
"employeeId" = @employee_id
|
||||||
|
ORDER BY start asc;
|
||||||
|
|
@ -275,6 +275,7 @@ type DyflexisEmployee struct {
|
||||||
ContractSalaryHour float64 `json:"contractSalaryHour"`
|
ContractSalaryHour float64 `json:"contractSalaryHour"`
|
||||||
ContractTypeName pgtype.Text `json:"contractTypeName"`
|
ContractTypeName pgtype.Text `json:"contractTypeName"`
|
||||||
InternalId pgtype.UUID `json:"internalId"`
|
InternalId pgtype.UUID `json:"internalId"`
|
||||||
|
ContractDaysWeek int32 `json:"contractDaysWeek"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Employee struct {
|
type Employee struct {
|
||||||
|
|
@ -564,6 +565,18 @@ type Tour struct {
|
||||||
Schwerlast bool `json:"schwerlast"`
|
Schwerlast bool `json:"schwerlast"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TourFile struct {
|
||||||
|
ID pgtype.UUID `json:"id"`
|
||||||
|
TourId string `json:"tourId"`
|
||||||
|
TicketId string `json:"ticketId"`
|
||||||
|
StoragePath string `json:"storagePath"`
|
||||||
|
OriginalFilename string `json:"originalFilename"`
|
||||||
|
MimeType string `json:"mimeType"`
|
||||||
|
FileSizeBytes int32 `json:"fileSizeBytes"`
|
||||||
|
DlUploadStatus string `json:"dlUploadStatus"`
|
||||||
|
CreatedAt *time.Time `json:"createdAt"`
|
||||||
|
}
|
||||||
|
|
||||||
type TourSource struct {
|
type TourSource struct {
|
||||||
InternalId pgtype.UUID `json:"internalId"`
|
InternalId pgtype.UUID `json:"internalId"`
|
||||||
InsertedAt time.Time `json:"insertedAt"`
|
InsertedAt time.Time `json:"insertedAt"`
|
||||||
|
|
|
||||||
|
|
@ -309,6 +309,39 @@ func (q *Queries) IsEmployeesDepartmentKTW(ctx context.Context, arg IsEmployeesD
|
||||||
return meets_requirements, err
|
return meets_requirements, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isEmployeesDepartmentNotLeitstelle = `-- 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 = $1::bigint
|
||||||
|
AND "startDate" BETWEEN $2 AND $3
|
||||||
|
AND department IS NOT NULL
|
||||||
|
`
|
||||||
|
|
||||||
|
type IsEmployeesDepartmentNotLeitstelleParams struct {
|
||||||
|
EmployeeID int64 `json:"employee_id"`
|
||||||
|
StartDate *time.Time `json:"start_date"`
|
||||||
|
EndDate *time.Time `json:"end_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) IsEmployeesDepartmentNotLeitstelle(ctx context.Context, arg IsEmployeesDepartmentNotLeitstelleParams) (bool, error) {
|
||||||
|
row := q.db.QueryRow(ctx, isEmployeesDepartmentNotLeitstelle, arg.EmployeeID, arg.StartDate, arg.EndDate)
|
||||||
|
var meets_requirements bool
|
||||||
|
err := row.Scan(&meets_requirements)
|
||||||
|
return meets_requirements, err
|
||||||
|
}
|
||||||
|
|
||||||
const listActiveEmployees = `-- name: ListActiveEmployees :many
|
const listActiveEmployees = `-- name: ListActiveEmployees :many
|
||||||
SELECT
|
SELECT
|
||||||
de.id,
|
de.id,
|
||||||
|
|
@ -316,6 +349,7 @@ SELECT
|
||||||
de.surname,
|
de.surname,
|
||||||
de."contractStart",
|
de."contractStart",
|
||||||
de."contractEnd",
|
de."contractEnd",
|
||||||
|
de."contractDaysWeek",
|
||||||
de."contractHoursWeek",
|
de."contractHoursWeek",
|
||||||
de."contractSalaryHour",
|
de."contractSalaryHour",
|
||||||
de."contractTypeName",
|
de."contractTypeName",
|
||||||
|
|
@ -334,6 +368,7 @@ type ListActiveEmployeesRow struct {
|
||||||
Surname string `json:"surname"`
|
Surname string `json:"surname"`
|
||||||
ContractStart time.Time `json:"contractStart"`
|
ContractStart time.Time `json:"contractStart"`
|
||||||
ContractEnd *time.Time `json:"contractEnd"`
|
ContractEnd *time.Time `json:"contractEnd"`
|
||||||
|
ContractDaysWeek int32 `json:"contractDaysWeek"`
|
||||||
ContractHoursWeek float64 `json:"contractHoursWeek"`
|
ContractHoursWeek float64 `json:"contractHoursWeek"`
|
||||||
ContractSalaryHour float64 `json:"contractSalaryHour"`
|
ContractSalaryHour float64 `json:"contractSalaryHour"`
|
||||||
ContractTypeName pgtype.Text `json:"contractTypeName"`
|
ContractTypeName pgtype.Text `json:"contractTypeName"`
|
||||||
|
|
@ -356,6 +391,7 @@ func (q *Queries) ListActiveEmployees(ctx context.Context) ([]ListActiveEmployee
|
||||||
&i.Surname,
|
&i.Surname,
|
||||||
&i.ContractStart,
|
&i.ContractStart,
|
||||||
&i.ContractEnd,
|
&i.ContractEnd,
|
||||||
|
&i.ContractDaysWeek,
|
||||||
&i.ContractHoursWeek,
|
&i.ContractHoursWeek,
|
||||||
&i.ContractSalaryHour,
|
&i.ContractSalaryHour,
|
||||||
&i.ContractTypeName,
|
&i.ContractTypeName,
|
||||||
|
|
@ -371,3 +407,47 @@ func (q *Queries) ListActiveEmployees(ctx context.Context) ([]ListActiveEmployee
|
||||||
}
|
}
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const listSickdaysForEmployee = `-- name: ListSickdaysForEmployee :many
|
||||||
|
SELECT
|
||||||
|
"start",
|
||||||
|
"end",
|
||||||
|
"days",
|
||||||
|
locked
|
||||||
|
FROM "Sickdays"
|
||||||
|
WHERE
|
||||||
|
"employeeId" = $1
|
||||||
|
ORDER BY start asc
|
||||||
|
`
|
||||||
|
|
||||||
|
type ListSickdaysForEmployeeRow struct {
|
||||||
|
Start time.Time `json:"start"`
|
||||||
|
End time.Time `json:"end"`
|
||||||
|
Days int32 `json:"days"`
|
||||||
|
Locked bool `json:"locked"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) ListSickdaysForEmployee(ctx context.Context, employeeID int32) ([]ListSickdaysForEmployeeRow, error) {
|
||||||
|
rows, err := q.db.Query(ctx, listSickdaysForEmployee, employeeID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []ListSickdaysForEmployeeRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i ListSickdaysForEmployeeRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.Start,
|
||||||
|
&i.End,
|
||||||
|
&i.Days,
|
||||||
|
&i.Locked,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package domain
|
package domain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"business-engine/internal/database"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -12,6 +13,7 @@ type PayrollInput struct {
|
||||||
HourlyRate float64
|
HourlyRate float64
|
||||||
ContractHours int64
|
ContractHours int64
|
||||||
DepartmentIsKtw bool
|
DepartmentIsKtw bool
|
||||||
|
DepartmentNotLeitstelle bool
|
||||||
|
|
||||||
// Erfasste Zeiten
|
// Erfasste Zeiten
|
||||||
WorkedHours float64
|
WorkedHours float64
|
||||||
|
|
@ -21,6 +23,8 @@ type PayrollInput struct {
|
||||||
TotalHours float64
|
TotalHours float64
|
||||||
OvertimeHours float64
|
OvertimeHours float64
|
||||||
|
|
||||||
|
SickdaysYear []database.ListSickdaysForEmployeeRow
|
||||||
|
|
||||||
// Zulagen und Boni
|
// Zulagen und Boni
|
||||||
ZulageTourengeld float64
|
ZulageTourengeld float64
|
||||||
ZulagePassengerTransport int64
|
ZulagePassengerTransport int64
|
||||||
|
|
@ -59,12 +63,15 @@ type PayrollStatement struct {
|
||||||
Tourengeld float64 `json:"tourengeld" csv:"Tourengeld Anzahl"`
|
Tourengeld float64 `json:"tourengeld" csv:"Tourengeld Anzahl"`
|
||||||
TourengeldBonus float64 `json:"tourengeldBonus" csv:"Tourengeld-Bonus (Platz 1-3, EUR)"`
|
TourengeldBonus float64 `json:"tourengeldBonus" csv:"Tourengeld-Bonus (Platz 1-3, EUR)"`
|
||||||
GesundheitsbonusAbzug string `json:"gesundheitsbonusAbzug" csv:"Gesundheitsbonus abzuziehen? (ja/nein)"`
|
GesundheitsbonusAbzug string `json:"gesundheitsbonusAbzug" csv:"Gesundheitsbonus abzuziehen? (ja/nein)"`
|
||||||
|
Gesundheitsbonus float64 `json:"gesundheitsbonus" csv:"Gesundheitsbonus"`
|
||||||
Urlaubsgeld float64 `json:"urlaubsgeld" csv:"Urlaubsgeld (44 EUR pro tag)"`
|
Urlaubsgeld float64 `json:"urlaubsgeld" csv:"Urlaubsgeld (44 EUR pro tag)"`
|
||||||
PScheinZulage float64 `json:"pScheinZulage" csv:"P-schein Zulage"`
|
PScheinZulage float64 `json:"pScheinZulage" csv:"P-schein Zulage"`
|
||||||
Wochenendzuschlag15 float64 `json:"wochenendzuschlag15" csv:"Wochenendzuschlag 15%"`
|
Wochenendzuschlag15 float64 `json:"wochenendzuschlag15" csv:"Wochenendzuschlag 15%"`
|
||||||
Sonntagszuschlag50 float64 `json:"sonntagszuschlag50" csv:"Sonntagszuschlag 50%"`
|
Sonntagszuschlag50 float64 `json:"sonntagszuschlag50" csv:"Sonntagszuschlag 50%"`
|
||||||
Feiertagszuschlag125 float64 `json:"feiertagszuschlag125" csv:"Feiertagszuschlag 125%"`
|
Feiertagszuschlag125 float64 `json:"feiertagszuschlag125" csv:"Feiertagszuschlag 125%,omitempty"`
|
||||||
Feiertagszuschlag150 float64 `json:"feiertagszuschlag150" csv:"Feiertagszuschlag 150%"`
|
Feiertagszuschlag150 float64 `json:"feiertagszuschlag150" csv:"Feiertagszuschlag 150%,omitempty"`
|
||||||
Nachtzuschlag25 float64 `json:"nachtzuschlag25" csv:"Nachtzuschlag 25%"`
|
Nachtzuschlag25 float64 `json:"nachtzuschlag25" csv:"Nachtzuschlag 25%"`
|
||||||
Nachtzuschlag40 float64 `json:"nachtzuschlag40" csv:"Nachtzuschlag 40%"`
|
Nachtzuschlag40 float64 `json:"nachtzuschlag40" csv:"Nachtzuschlag 40%"`
|
||||||
|
|
||||||
|
SickdaysYear []database.ListSickdaysForEmployeeRow `json:"-" csv:"-"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package genpdf
|
package genpdf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"business-engine/internal/database"
|
||||||
domain "business-engine/internal/domain"
|
domain "business-engine/internal/domain"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
|
|
@ -77,6 +78,8 @@ func GenerateSalaryStatement(stmt domain.PayrollStatement, filename string, mont
|
||||||
|
|
||||||
drawSummary(pdf, gesamtbetrag)
|
drawSummary(pdf, gesamtbetrag)
|
||||||
|
|
||||||
|
drawSickdays(pdf, stmt.SickdaysYear)
|
||||||
|
|
||||||
if err := pdf.OutputFileAndClose(filename); err != nil {
|
if err := pdf.OutputFileAndClose(filename); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -147,12 +150,12 @@ func genLineItemsFromStatement(stmt domain.PayrollStatement) []LineItem {
|
||||||
Betrag: 14.0,
|
Betrag: 14.0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if stmt.GesundheitsbonusAbzug == "" {
|
if stmt.Gesundheitsbonus > 0 {
|
||||||
items = append(items, LineItem{
|
items = append(items, LineItem{
|
||||||
Lohnart: "1032",
|
Lohnart: "1032",
|
||||||
Beschreibung: "Gesundheitsbonus",
|
Beschreibung: "Gesundheitsbonus",
|
||||||
Anzahl: 1,
|
Anzahl: 1,
|
||||||
Betrag: 200.0,
|
Betrag: stmt.Gesundheitsbonus,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,6 +298,41 @@ func drawSummary(pdf *fpdf.Fpdf, total float64) {
|
||||||
pdf.CellFormat(30, 8, formatCurrency(total), "T", 0, "R", false, 0, "")
|
pdf.CellFormat(30, 8, formatCurrency(total), "T", 0, "R", false, 0, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func drawSickdays(pdf *fpdf.Fpdf, sickdays []database.ListSickdaysForEmployeeRow) {
|
||||||
|
// 1. Abstand und Überschrift
|
||||||
|
pdf.Ln(10)
|
||||||
|
|
||||||
|
pdf.SetFont("DejaVu", "B", 11)
|
||||||
|
// Kein Rahmen, Zeilenumbruch nach der Zelle
|
||||||
|
pdf.CellFormat(0, 10, "Krankmeldungen", "", 1, "L", false, 0, "")
|
||||||
|
|
||||||
|
// 2. Fallback: Wenn keine Krankmeldungen vorhanden sind
|
||||||
|
if len(sickdays) == 0 {
|
||||||
|
pdf.SetFont("DejaVu", "", 10)
|
||||||
|
text := "- Keine Einträge vorhanden"
|
||||||
|
pdf.CellFormat(0, 6, text, "", 1, "L", false, 0, "")
|
||||||
|
pdf.Ln(5)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Liste zeichne
|
||||||
|
pdf.SetFont("DejaVu", "", 10)
|
||||||
|
|
||||||
|
for _, sick := range sickdays {
|
||||||
|
startStr := sick.Start.Format("02.01.2006")
|
||||||
|
endStr := sick.End.Format("02.01.2006")
|
||||||
|
|
||||||
|
// Formatierung: "- 01.01.2023 bis 05.01.2023: 4 Tage"
|
||||||
|
text := fmt.Sprintf("- %s bis %s: %d Tage", startStr, endStr, sick.Days)
|
||||||
|
|
||||||
|
// Zeichnen der Zeile
|
||||||
|
pdf.CellFormat(0, 6, text, "", 1, "L", false, 0, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kleiner Abstand nach der Liste
|
||||||
|
pdf.Ln(5)
|
||||||
|
}
|
||||||
|
|
||||||
func formatFloat(f float64) string {
|
func formatFloat(f float64) string {
|
||||||
p := message.NewPrinter(language.German)
|
p := message.NewPrinter(language.German)
|
||||||
str := p.Sprintf("%.2f", f)
|
str := p.Sprintf("%.2f", f)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ func NewEmployeeHandler(service Service, logger *slog.Logger) *EmployeeHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *EmployeeHandler) RunPayroll(w http.ResponseWriter, r *http.Request) {
|
func (h *EmployeeHandler) RunPayroll(w http.ResponseWriter, r *http.Request) {
|
||||||
month := time.Date(2025, time.November, 1, 0, 0, 0, 0, time.UTC)
|
month := time.Date(2025, time.December, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
employees, err := h.service.FetchActiveEmployees(r.Context())
|
employees, err := h.service.FetchActiveEmployees(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -85,7 +85,7 @@ func (h *EmployeeHandler) RunPayroll(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if err := json.NewEncoder(w).Encode(data); err != nil {
|
if err := json.NewEncoder(w).Encode(payrollStatements); err != nil {
|
||||||
h.logger.Error("failed to encode response", "error", err)
|
h.logger.Error("failed to encode response", "error", err)
|
||||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,10 @@ type Repository interface {
|
||||||
CountTourengeldAmountInPeriod(ctx context.Context, args database.CountTourengeldAmountInPeriodParams) (float64, error)
|
CountTourengeldAmountInPeriod(ctx context.Context, args database.CountTourengeldAmountInPeriodParams) (float64, error)
|
||||||
GetWeeklyTimeSummaryForEmployee(ctx context.Context, args database.GetWeeklyTimeSummaryForEmployeeParams) ([]database.GetWeeklyTimeSummaryForEmployeeRow, error)
|
GetWeeklyTimeSummaryForEmployee(ctx context.Context, args database.GetWeeklyTimeSummaryForEmployeeParams) ([]database.GetWeeklyTimeSummaryForEmployeeRow, error)
|
||||||
EvaluatePunctualityForEmployee(ctx context.Context, args database.EvaluatePunctualityForEmployeeParams) (int64, error)
|
EvaluatePunctualityForEmployee(ctx context.Context, args database.EvaluatePunctualityForEmployeeParams) (int64, error)
|
||||||
|
IsEmployeesDepartmentNotLeitstelle(ctx context.Context, args database.IsEmployeesDepartmentNotLeitstelleParams) (bool, error)
|
||||||
IsEmployeesDepartmentKTW(ctx context.Context, args database.IsEmployeesDepartmentKTWParams) (bool, error)
|
IsEmployeesDepartmentKTW(ctx context.Context, args database.IsEmployeesDepartmentKTWParams) (bool, error)
|
||||||
CountVerpflegungspauschale(ctx context.Context, args database.CountVerpflegungspauschaleParams) (int64, error)
|
CountVerpflegungspauschale(ctx context.Context, args database.CountVerpflegungspauschaleParams) (int64, error)
|
||||||
|
ListSickdaysForEmployee(ctx context.Context, employeeId int32) ([]database.ListSickdaysForEmployeeRow, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
|
|
@ -55,8 +57,7 @@ func (s *Service) GeneratePayrollStatement(input domain.PayrollInput) domain.Pay
|
||||||
GearbeiteteTage: float64(input.WorkedDays),
|
GearbeiteteTage: float64(input.WorkedDays),
|
||||||
Krankheitstage: float64(input.SickDays),
|
Krankheitstage: float64(input.SickDays),
|
||||||
Ueberstunden: input.OvertimeHours,
|
Ueberstunden: input.OvertimeHours,
|
||||||
|
SickdaysYear: input.SickdaysYear,
|
||||||
Verpflegungspauschale: float64(input.Verpflegungspauschale),
|
|
||||||
|
|
||||||
Wochenendzuschlag15: input.ZuschlagSamstag,
|
Wochenendzuschlag15: input.ZuschlagSamstag,
|
||||||
Sonntagszuschlag50: input.ZuschlagSonntag,
|
Sonntagszuschlag50: input.ZuschlagSonntag,
|
||||||
|
|
@ -66,10 +67,27 @@ func (s *Service) GeneratePayrollStatement(input domain.PayrollInput) domain.Pay
|
||||||
Feiertagszuschlag150: input.ZuschlagFeiertag150,
|
Feiertagszuschlag150: input.ZuschlagFeiertag150,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if input.DepartmentNotLeitstelle {
|
||||||
|
statement.Verpflegungspauschale = float64(input.Verpflegungspauschale)
|
||||||
|
}
|
||||||
|
|
||||||
if input.SickDays > 0 || !input.DepartmentIsKtw {
|
if input.SickDays > 0 || !input.DepartmentIsKtw {
|
||||||
statement.GesundheitsbonusAbzug = "ja"
|
statement.GesundheitsbonusAbzug = "ja"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if input.SickDays <= 0 && input.DepartmentIsKtw {
|
||||||
|
switch {
|
||||||
|
case statement.Vertragsstunden > 173.0:
|
||||||
|
statement.Gesundheitsbonus = 200.0
|
||||||
|
case statement.Vertragsstunden > 120:
|
||||||
|
statement.Gesundheitsbonus = 150.0
|
||||||
|
case statement.Vertragsstunden > 100:
|
||||||
|
statement.Gesundheitsbonus = 100.0
|
||||||
|
default:
|
||||||
|
statement.Gesundheitsbonus = 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if input.DepartmentIsKtw {
|
if input.DepartmentIsKtw {
|
||||||
statement.Urlaubsgeld = float64(input.HolidayDays)
|
statement.Urlaubsgeld = float64(input.HolidayDays)
|
||||||
statement.PScheinZulage = float64(input.ZulagePassengerTransport)
|
statement.PScheinZulage = float64(input.ZulagePassengerTransport)
|
||||||
|
|
@ -107,12 +125,22 @@ func (s *Service) LoadPayrollInput(ctx context.Context, month time.Time, employe
|
||||||
return domain.PayrollInput{}, err
|
return domain.PayrollInput{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNotLeitstelle, err := s.isEmployeesDepartmentNotLeitstelle(ctx, month, int64(employee.ID))
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("could not load employee department", "error", err)
|
||||||
|
return domain.PayrollInput{}, err
|
||||||
|
}
|
||||||
|
|
||||||
isKtw, err := s.isEmployeesDepartmentKTW(ctx, month, int64(employee.ID))
|
isKtw, err := s.isEmployeesDepartmentKTW(ctx, month, int64(employee.ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Error("could not load employee department", "error", err)
|
s.logger.Error("could not load employee department", "error", err)
|
||||||
return domain.PayrollInput{}, err
|
return domain.PayrollInput{}, err
|
||||||
}
|
}
|
||||||
s.logger.Debug("fetched department", "isKtw", isKtw)
|
|
||||||
|
sickdays, err := s.loadSickdays(ctx, int64(employee.ID))
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("could not load sickdays of employee", "employeeId", employee.ID, "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
input := domain.PayrollInput{
|
input := domain.PayrollInput{
|
||||||
Firstname: employee.Firstname,
|
Firstname: employee.Firstname,
|
||||||
|
|
@ -120,6 +148,7 @@ func (s *Service) LoadPayrollInput(ctx context.Context, month time.Time, employe
|
||||||
HourlyRate: employee.ContractSalaryHour,
|
HourlyRate: employee.ContractSalaryHour,
|
||||||
ContractHours: int64(employee.ContractHoursWeek),
|
ContractHours: int64(employee.ContractHoursWeek),
|
||||||
DepartmentIsKtw: isKtw,
|
DepartmentIsKtw: isKtw,
|
||||||
|
DepartmentNotLeitstelle: isNotLeitstelle,
|
||||||
|
|
||||||
WorkedHours: metrics.WorkedHours,
|
WorkedHours: metrics.WorkedHours,
|
||||||
WorkedDays: int64(metrics.WorkedDays),
|
WorkedDays: int64(metrics.WorkedDays),
|
||||||
|
|
@ -128,6 +157,8 @@ func (s *Service) LoadPayrollInput(ctx context.Context, month time.Time, employe
|
||||||
OvertimeHours: metrics.OvertimeHours,
|
OvertimeHours: metrics.OvertimeHours,
|
||||||
TotalHours: metrics.TotalHours,
|
TotalHours: metrics.TotalHours,
|
||||||
|
|
||||||
|
SickdaysYear: sickdays,
|
||||||
|
|
||||||
ZulageTourengeld: tourengeld,
|
ZulageTourengeld: tourengeld,
|
||||||
ZulagePuenktlichkeit: punctuality,
|
ZulagePuenktlichkeit: punctuality,
|
||||||
Verpflegungspauschale: verpflegungsPauschale,
|
Verpflegungspauschale: verpflegungsPauschale,
|
||||||
|
|
@ -150,12 +181,15 @@ func (s *Service) LoadPayrollInput(ctx context.Context, month time.Time, employe
|
||||||
input.ZuschlagVerpflegung = zuschlagData.Verpflegung14
|
input.ZuschlagVerpflegung = zuschlagData.Verpflegung14
|
||||||
} else {
|
} else {
|
||||||
s.logger.Warn("Keine Zuschlag-Daten für Mitarbeiter gefunden", "key", compoundKey)
|
s.logger.Warn("Keine Zuschlag-Daten für Mitarbeiter gefunden", "key", compoundKey)
|
||||||
// (Kein Fehler, der Mitarbeiter hatte vielleicht keine Zuschläge)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return input, nil
|
return input, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) loadSickdays(ctx context.Context, employeeId int64) ([]database.ListSickdaysForEmployeeRow, error) {
|
||||||
|
return s.repo.ListSickdaysForEmployee(ctx, int32(employeeId))
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) countVerpflegungspauschale(ctx context.Context, month time.Time, employeeId int64) (int64, error) {
|
func (s *Service) countVerpflegungspauschale(ctx context.Context, month time.Time, employeeId int64) (int64, error) {
|
||||||
startOfMonth := beginningOfMonth(month)
|
startOfMonth := beginningOfMonth(month)
|
||||||
endOfMonth := endOfMonth(month)
|
endOfMonth := endOfMonth(month)
|
||||||
|
|
@ -172,6 +206,22 @@ func (s *Service) countVerpflegungspauschale(ctx context.Context, month time.Tim
|
||||||
return verpflegungsPauschale, nil
|
return verpflegungsPauschale, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) isEmployeesDepartmentNotLeitstelle(ctx context.Context, month time.Time, employeeId int64) (bool, error) {
|
||||||
|
startOfMonth := beginningOfMonth(month)
|
||||||
|
endOfMonth := endOfMonth(month)
|
||||||
|
s.logger.Info("fetching department for employee", "employeeId", employeeId, "startDate", startOfMonth, "endDate", endOfMonth)
|
||||||
|
|
||||||
|
isNotLeitstelle, err := s.repo.IsEmployeesDepartmentNotLeitstelle(ctx, database.IsEmployeesDepartmentNotLeitstelleParams{
|
||||||
|
StartDate: &startOfMonth,
|
||||||
|
EndDate: &endOfMonth,
|
||||||
|
EmployeeID: employeeId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to fetch department for employee %d: %w", employeeId, err)
|
||||||
|
}
|
||||||
|
return isNotLeitstelle, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) isEmployeesDepartmentKTW(ctx context.Context, month time.Time, employeeId int64) (bool, error) {
|
func (s *Service) isEmployeesDepartmentKTW(ctx context.Context, month time.Time, employeeId int64) (bool, error) {
|
||||||
startOfMonth := beginningOfMonth(month)
|
startOfMonth := beginningOfMonth(month)
|
||||||
endOfMonth := endOfMonth(month)
|
endOfMonth := endOfMonth(month)
|
||||||
|
|
@ -217,7 +267,13 @@ type payrollMetrics struct {
|
||||||
func (s *Service) calculatePayrollMetrics(weeklyTimeData []domain.WeeklyTimeData, employee database.ListActiveEmployeesRow) payrollMetrics {
|
func (s *Service) calculatePayrollMetrics(weeklyTimeData []domain.WeeklyTimeData, employee database.ListActiveEmployeesRow) payrollMetrics {
|
||||||
var m payrollMetrics
|
var m payrollMetrics
|
||||||
|
|
||||||
employeeDailyContractHours := employee.ContractHoursWeek / 5
|
employeeDailyContractHours := 0.0
|
||||||
|
switch {
|
||||||
|
case employee.ContractDaysWeek <= 0:
|
||||||
|
employeeDailyContractHours = employee.ContractHoursWeek / 5
|
||||||
|
default:
|
||||||
|
employeeDailyContractHours = employee.ContractHoursWeek / float64(employee.ContractDaysWeek)
|
||||||
|
}
|
||||||
|
|
||||||
for _, week := range weeklyTimeData {
|
for _, week := range weeklyTimeData {
|
||||||
m.WorkedHours += week.WorkedHours
|
m.WorkedHours += week.WorkedHours
|
||||||
|
|
@ -261,6 +317,7 @@ func (s *Service) getWeeklyTimeData(ctx context.Context, month time.Time, employ
|
||||||
func (s *Service) fetchTourengeld(ctx context.Context, month time.Time, dlEmployeeId string) (float64, error) {
|
func (s *Service) fetchTourengeld(ctx context.Context, month time.Time, dlEmployeeId string) (float64, error) {
|
||||||
startOfMonth := beginningOfMonth(month)
|
startOfMonth := beginningOfMonth(month)
|
||||||
endOfMonth := endOfMonth(month)
|
endOfMonth := endOfMonth(month)
|
||||||
|
s.logger.Info("fetching tourengeld for employee", "employeeId", dlEmployeeId, "startDate", startOfMonth, "endDate", endOfMonth)
|
||||||
|
|
||||||
tourengeld, err := s.repo.CountTourengeldAmountInPeriod(ctx, database.CountTourengeldAmountInPeriodParams{
|
tourengeld, err := s.repo.CountTourengeldAmountInPeriod(ctx, database.CountTourengeldAmountInPeriodParams{
|
||||||
StartDate: startOfMonth,
|
StartDate: startOfMonth,
|
||||||
|
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
Nachname;Vorname;Verpflegungspauschale;Vertr. Stundenlohn;Arbeitsstunden lt. Vertrag;Gearbeitet Stunden;Gearbeitet Tage;Pünktlichkeitsprämie anzahl;Krankheitstage x 8 Stunden;davon Überstunden;Tourengeld Anzahl;Tourengeld-Bonus (Platz 1-3;Gesundheitsbonus abzuziehen? (ja/nein);Urlaubsgeld (44 EUR pro tag);P-schein Zulage;Wochenendzuschlag 15%;Sonntagszuschlag 50%;Feiertagszuschlag 125%;Feiertagszuschlag 150%;Nachtzuschlag 25%;Nachtzuschlag 40%
|
|
||||||
Malani Karizi;Arasch;24;14.42;173.32;211.98333333333332;24;24;0;38.651333333333305;41.5;500;;0;0;24.7;0;8.25;0;2.6;0
|
|
||||||
Saeedpour;Fouad;23;14.42;173.32;203.28333333333333;23;23;0;29.951333333333316;41;400;;0;23;25.25;26.8;9;0;4.25;0
|
|
||||||
Sharh Ghaboos;Peyman;24;14.42;173.32;212.63333333333333;24;24;0;39.30133333333331;37;300;;0;24;16.683333333333;0;8.25;0;2.6;0
|
|
||||||
Kalantari;Kaveh;18;14.42;173.32;159.05;18;18;0;25.717999999999996;31;0;;5;18;16.916666666667;10.25;9.9;0;4.25;0
|
|
||||||
Ahmadpour;Amirhossein;21;14.42;173.32;193.63333333333333;21;21;0;36.30133333333331;31;0;;2;21;0;8.4666666666667;8.7833333333333;0;0;0
|
|
||||||
Hosseini Jahed;Sajad;20;14.42;173.32;193.38333333333333;21;21;0;44.05133333333331;30;0;;3;21;0;8.4666666666667;8.7833333333333;0;0;0
|
|
||||||
Rasul Khani;Mohammad;24;14.42;173.32;209.48333333333332;24;24;0;36.151333333333305;29.5;0;;0;24;8.0166666666667;17.45;8.25;0;2.25;0
|
|
||||||
Moshtagh Askari;Adel;25;15.58;173.32;218.41666666666666;25;23;0;45.08466666666664;29;0;;0;25;24.95;0;18.65;0;0;0
|
|
||||||
Rasulkhani;Hossein;23;14.42;173.32;194.86666666666667;23;22;0;21.53466666666666;28;0;;0;23;32.366666666667;9.25;9;0;10.433333333333;0
|
|
||||||
Sajaei Khouzestani;Farid;22;14.42;173.32;197.43333333333334;22;22;0;24.101333333333322;26;0;;0;22;16.366666666667;0;17.316666666667;0;0;0
|
|
||||||
Perez Y Waldt;Sebastian;17;14.42;173.32;181.89999999999998;22;15;0;8.567999999999962;25;0;;0;0;24.666666666667;0;8.0166666666667;0;14.1;0
|
|
||||||
Rahimzadeh;Siamak;23;14.42;173.32;197.5;23;23;0;24.167999999999985;25;0;;0;23;25.016666666667;0;16.25;0;0;0
|
|
||||||
Shokripour;Vahid;24;15;173.32;208.11666666666667;24;24;0;34.78466666666666;23.5;0;;0;24;25.333333333333;9.5;16.166666666667;0;0;0
|
|
||||||
Hosseini;Seyed Hamid;18;14.42;173.32;153.41666666666666;18;18;5;20.084666666666642;23;0;ja;0;18;8.0833333333333;0;16.5;0;0;0
|
|
||||||
Safari;Abdul Latif ;20;14.42;173.32;180.41666666666669;20;20;0;47.08466666666667;23;0;;5;20;17.35;0;16.166666666667;0;0;0
|
|
||||||
Pourhossein;Reza;20;14.42;173.32;181.55;21;21;0;8.217999999999996;20.5;0;;0;21;8.0166666666667;0;16.316666666667;0;36.533333333333;15.016666666667
|
|
||||||
Salehi;Iman;26;17.31;173.32;220.1;26;26;0;46.76799999999998;20;0;;0;26;8.0166666666667;18.2;16.383333333333;0;68.766666666667;13.483333333333
|
|
||||||
Rohany Oskoee;Iman;22;16.15;173.32;190.38333333333333;22;10;0;17.05133333333331;20;0;;0;0;8.0333333333333;0;8.7333333333333;0;0;0
|
|
||||||
Sahem;Khalid;24;14.42;173.32;204.35000000000002;24;24;0;31.018000000000008;18.5;0;;0;24;26.033333333333;0;16.833333333333;0;0;0
|
|
||||||
Toraman;Tolga Can;20;14.42;173.32;183.13333333333333;22;19;0;9.80133333333331;18;0;;0;0;16.3;9.5;0;0;0;0
|
|
||||||
Tokhi;Shokrollah;18;14.42;173.32;152.6;18;18;0;19.26799999999998;17;0;;5;18;8.6333333333333;0;9.3;0;47.75;21.483333333333
|
|
||||||
Eggerstedt;Matthias;21;15.58;173.32;190.13333333333333;22;22;0;16.80133333333331;16;0;;0;22;0;0;8.6333333333333;0;0;0
|
|
||||||
Mihailescu;Adrian Lucian;18;16.73;173.32;177.56666666666666;21;4;0;4.234666666666648;14.5;0;;0;21;24.116666666667;0;8.6333333333333;0;0;0
|
|
||||||
Hastedt;David;11;14.93;138.656;112.31666666666666;14;11;4;5.651066666666651;14;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Faridani Rad;Farzad;21;15;173.32;174.08333333333334;21;21;2;16.751333333333328;13.5;0;ja;0;21;0;0;16.15;0;44.5;5.6666666666667
|
|
||||||
Tajikzadeh;Mohammad;18;16.15;173.32;152.31666666666666;18;18;0;18.984666666666648;13.5;0;;5;18;8.0833333333333;0;8.25;0;0;0
|
|
||||||
Saki;Sara;14;15;173.32;117.63333333333333;14;14;0;32.30133333333331;13;0;;11;14;0;8.7;16.383333333333;0;35.05;0
|
|
||||||
Imanian;Shahriyar;12;14.42;173.32;104.28333333333333;12;12;0;26.951333333333316;12.5;0;;12;12;8.1666666666667;8.35;0;0;0.083333333333333;0
|
|
||||||
Sabahi;Mohammad;18;16.15;173.32;152.58333333333334;18;17;4;19.251333333333328;11;0;ja;1;18;0;0;16.583333333333;0;0;0
|
|
||||||
Florescu;Silviu-Cezar;20;15;173.32;173.53333333333336;20;20;0;0.2013333333333449;10.5;0;;0;0;8.35;0;0;0;0.28333333333333;0
|
|
||||||
Florescu;Silviu-Cezar;20;15;173.32;173.53333333333336;20;20;0;0.2013333333333449;10.5;0;;0;0;8.35;0;0;0;0.28333333333333;0
|
|
||||||
Altner;Christian Van Manh;21;15;173.32;184.08333333333334;22;22;0;10.751333333333328;9;0;;0;22;8.0166666666667;0;7.9333333333333;0;0.2;0
|
|
||||||
Pourhossein;Milad;14;14.42;173.32;125.61666666666665;15;15;0;8.28466666666663;8.5;0;;7;15;16.6;0;7.9333333333333;0;0;0
|
|
||||||
Pouzesh;Esmail;24;16.15;173.32;202.08333333333334;24;24;0;28.751333333333328;7;0;;0;24;0;9.5;17.816666666667;0;70.416666666667;20.6
|
|
||||||
Khodayaran;Hossein;12;16.15;173.32;105.30000000000001;13;13;0;11.967999999999996;7;0;;10;13;0;0;8.1333333333333;0;31;5.6666666666667
|
|
||||||
Juyande;Masoud;22;15;173.32;182.9;22;22;0;9.56799999999999;7;0;;0;0;0;0;8.5166666666667;0;68.1;23.783333333333
|
|
||||||
Maleki;Mohammad;3;14.44;103.992;41.11666666666667;5;1;2;-46.88253333333334;3.5;0;ja;0;5;0;0;0;0;0;0
|
|
||||||
Saffarnajib;Majid;16;15.38;90.99300000000001;133.36666666666665;16;16;0;42.36736666666664;1;0;;0;16;0;0;0;0;0;0
|
|
||||||
Jasarevic;Noel;12;14.42;173.32;116.63333333333333;14;0;0;-0.6986666666666892;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Movafagh;Farzad ;23;12.82;173.32;202.61666666666667;23;0;1;37.28466666666666;0;0;ja;0;0;24.55;0;0;0;0;0
|
|
||||||
Haralambous;Martin;0;12.41;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Hazrati;Kamyar;20;12.82;173.32;182.75;21;0;0;9.417999999999985;0;0;ja;0;0;16.616666666667;0;0;0;0;0
|
|
||||||
Krüger;Julian;19;22.5;173.32;197.35;23;0;0;24.01799999999998;0;0;ja;0;0;15.116666666667;0;14.283333333333;0;0;0
|
|
||||||
Arabnia;Mehdi;21;12.82;173.32;194.38333333333333;22;0;0;21.05133333333331;0;0;ja;0;0;15.783333333333;0;0;0;0;0
|
|
||||||
Taghadosi;Mehdi;21;12.82;173.32;188.93333333333334;22;0;0;15.601333333333322;0;0;ja;0;0;16.6;0;6.3;0;0;0
|
|
||||||
Jalali Wagener;Mehdi;24;12.82;173.32;204.48333333333332;24;0;0;31.151333333333305;0;0;ja;0;0;16.35;0;8.5333333333333;0;0;0
|
|
||||||
Mazidi;Mehrdad;21;12.82;173.32;183.16666666666666;21;0;0;9.834666666666642;0;0;ja;0;0;17.033333333333;0;8.1166666666667;0;0;0
|
|
||||||
Koell;Melanie Nadine;0;15.58;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Esmaeili Miandehi;Milad;0;12.82;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Mohamed Salah;Hussin Noureldin;21;12.82;173.32;186.58333333333334;22;0;0;13.251333333333328;0;0;ja;0;0;24.55;0;8.5166666666667;0;0;0
|
|
||||||
Tokhi;Haroun;0;14.42;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Feilbach;Raoul Nikolai ;24;19.62;173.32;215.88333333333335;24;0;0;42.55133333333334;0;0;ja;0;0;0;8.7;17.483333333333;0;55.5;40.75
|
|
||||||
Hashimazada;Firuz;18;12.82;173.32;155.35;18;0;4;14.01799999999998;0;0;ja;0;0;0;0;8.5333333333333;0;0;0
|
|
||||||
Esser;Detlef;0;12;121.32400000000001;0;0;0;0;-121.3324;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Atrafi;Mohammad Nasir;17;12.82;17.332;162.96666666666667;19;0;0;145.63346666666666;0;0;ja;0;0;22.5;0;0;0;0;0
|
|
||||||
Amiri;Mohammad Samir;20;19.62;173.32;190.14999999999998;22;0;0;16.817999999999962;0;0;ja;0;0;12.316666666667;10.166666666667;0;0;17.25;12.633333333333
|
|
||||||
Babaei Dezghi;Mojtaba;0;15;160.321;0;0;0;0;-162.49875;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Aydin;Muhammet Ali;0;14.51;73.661;0;0;0;0;-73.6661;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
El Moustaiqid;Najlae;9;12.82;173.32;151.7;20;0;0;-5.632000000000026;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Heucke;Niklas;0;15;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Saei;Kasra;0;5.65;173.32;37.266666666666666;6;0;0;-56.06533333333335;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Latza;Lelia Eleonore;0;6.35;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Karimloo;Hamidreza;0;12.82;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Hatami;Reza;20;12.82;173.32;173.9666666666667;20;0;0;0.634666666666682;0;0;ja;0;0;16.6;0;0;0;0;0
|
|
||||||
Abdallah;Delshad;0;12.82;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Sidiqi;Sahel;0;14.42;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Golmohammadi;Davood ;20;12.82;173.32;182.2166666666667;20;0;0;8.884666666666682;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Shahrasebi;David;0;0;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Lolies;Danny;17;12.82;173.32;158.9;19;0;4;18.06799999999999;0;0;ja;0;0;17.05;0;5.55;0;0;0
|
|
||||||
Emkani;Daniel;12;22.48;108.325;118.45;14;0;0;10.117499999999993;0;0;ja;0;0;13.3;0;8.6833333333333;0;0;0
|
|
||||||
Askarian Pour;Seyed Hosein;0;15.58;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Jabbari;Shahram;20;12.82;173.32;175.21666666666667;20;0;0;1.8846666666666536;0;0;ja;0;0;16.95;0;0;0;0;0
|
|
||||||
Haghighivand;Danial;19;12.82;173.32;166.03333333333333;19;0;0;8.701333333333316;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Alami;Shoaib;0;12.82;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Mohammadi;Danial;20;12.82;173.32;182.86666666666665;21;0;0;9.53466666666663;0;0;ja;0;0;16.616666666667;0;8.3333333333333;0;0;0
|
|
||||||
Aba;Cuan;0;5.65;173.32;50.25;8;0;0;-75.08200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Modrau;Cara Marleen;0;14.42;173.32;0;0;0;0;-173.33200000000002;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Rahmati;Behnam;20;12.82;173.32;176.04999999999998;20;0;1;11.217999999999968;0;0;ja;0;0;0;0;0;0;0;0
|
|
||||||
Vafaei;Soheil;18;12.82;173.32;155.48333333333332;18;0;1;14.151333333333305;0;0;ja;0;0;8.0166666666667;0;0;0;0;0
|
|
||||||
Ziaudin;Atiq;21;12.82;173.32;194.31666666666666;23;0;0;20.984666666666648;0;0;ja;0;0;15.05;0;6.4333333333333;0;0;0
|
|
||||||
Haugg;Uwe;5;12.82;138.656;50.616666666666674;6;0;4;-4.848933333333349;0;0;ja;0;0;6.9666666666667;0;0;0;0;0
|
|
||||||
Esmaeili Dashtbayaz;Amin;20;12.82;173.32;171.26666666666665;20;0;0;-2.0653333333333634;0;0;ja;0;0;16.083333333333;0;0;0;0;0
|
|
||||||
Konak;Zidar;15;22.5;173.32;183.65000000000003;22;0;0;10.31800000000002;0;0;ja;0;0;16.433333333333;18.5;7;0;0;0
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "DyflexisEmployee" ADD COLUMN "contractDaysWeek" INTEGER NOT NULL DEFAULT 0;
|
||||||
|
|
@ -553,6 +553,7 @@ model DyflexisEmployee {
|
||||||
surname String
|
surname String
|
||||||
contractStart DateTime
|
contractStart DateTime
|
||||||
contractEnd DateTime?
|
contractEnd DateTime?
|
||||||
|
contractDaysWeek Int @default(0)
|
||||||
contractHoursWeek Float
|
contractHoursWeek Float
|
||||||
contractSalaryHour Float
|
contractSalaryHour Float
|
||||||
contractTypeName String?
|
contractTypeName String?
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ export type DyflexisEmployee = {
|
||||||
surname: string;
|
surname: string;
|
||||||
contractStart: Timestamp;
|
contractStart: Timestamp;
|
||||||
contractEnd: Timestamp | null;
|
contractEnd: Timestamp | null;
|
||||||
|
contractDaysWeek: Generated<number>;
|
||||||
contractHoursWeek: number;
|
contractHoursWeek: number;
|
||||||
contractSalaryHour: number;
|
contractSalaryHour: number;
|
||||||
contractTypeName: string | null;
|
contractTypeName: string | null;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { HttpService } from '@nestjs/axios';
|
import { HttpService } from '@nestjs/axios';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { SourceRepository } from './source.repository';
|
import { format, Interval } from 'date-fns';
|
||||||
import { ConfigService } from 'src/core/config/config.service';
|
|
||||||
import {
|
import {
|
||||||
catchError,
|
catchError,
|
||||||
|
combineLatest,
|
||||||
EMPTY,
|
EMPTY,
|
||||||
expand,
|
expand,
|
||||||
forkJoin,
|
forkJoin,
|
||||||
|
|
@ -12,11 +12,15 @@ import {
|
||||||
Observable,
|
Observable,
|
||||||
of,
|
of,
|
||||||
reduce,
|
reduce,
|
||||||
switchMap,
|
switchMap
|
||||||
tap,
|
|
||||||
} from 'rxjs';
|
} from 'rxjs';
|
||||||
import { format, Interval } from 'date-fns';
|
import { ConfigService } from 'src/core/config/config.service';
|
||||||
import { HolidayRaw, SickDaysRaw } from './source.interface';
|
import {
|
||||||
|
EmployeeContractRaw,
|
||||||
|
HolidayRaw,
|
||||||
|
SickDaysRaw,
|
||||||
|
} from './source.interface';
|
||||||
|
import { SourceRepository } from './source.repository';
|
||||||
|
|
||||||
interface DyflexisAuthHeader {
|
interface DyflexisAuthHeader {
|
||||||
Cookie: string;
|
Cookie: string;
|
||||||
|
|
@ -40,11 +44,72 @@ export class DyflexisUserAccessExtractorsService {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
loadData(): Observable<any> {
|
loadData(): Observable<any> {
|
||||||
// return this.extractSicknessDays({
|
return combineLatest([
|
||||||
|
// this.extractWorkdays(),
|
||||||
|
// this.extractSicknessDays({
|
||||||
// start: new Date('2025-01-01T00:00:00.000Z'),
|
// start: new Date('2025-01-01T00:00:00.000Z'),
|
||||||
// end: new Date('2025-12-31T23:59:59.999Z'),
|
// end: new Date('2025-12-31T23:59:59.999Z'),
|
||||||
// });
|
// }),
|
||||||
return this.extractHolidays(new Date('2025-01-01T00:00:00.000Z'));
|
this.extractHolidays(new Date('2025-01-01T00:00:00.000Z')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
extractWorkdays(): Observable<any> {
|
||||||
|
return this.dyflexisLogin(
|
||||||
|
this.config.dyflexisAppUsername(),
|
||||||
|
this.config.dyflexisAppPassword(),
|
||||||
|
).pipe(
|
||||||
|
switchMap((authHeader) =>
|
||||||
|
forkJoin({
|
||||||
|
authHeader: of(authHeader),
|
||||||
|
employees: this.fetchEmployees(authHeader),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
switchMap(({ authHeader, employees }) =>
|
||||||
|
forkJoin(
|
||||||
|
employees.map((employee) =>
|
||||||
|
this.fetchWorkdaysForEmployee(authHeader, employee.id),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
map((workdaysPerEmployee) => workdaysPerEmployee.flat(1)),
|
||||||
|
switchMap((workdays) => from(this.repository.createWorkdays(workdays))),
|
||||||
|
map((res) => {
|
||||||
|
return { count: Number(res.at(0).numUpdatedRows) };
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private fetchWorkdaysForEmployee(
|
||||||
|
authHeader: DyflexisAuthHeader,
|
||||||
|
employeeId: number,
|
||||||
|
): Observable<{ employeeId: number; daysPerWeek: number }> {
|
||||||
|
const endpoint = (employeeId: number) =>
|
||||||
|
`hamburg/employees/contract/data/${employeeId}`;
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get<{
|
||||||
|
contracts: EmployeeContractRaw[];
|
||||||
|
}>(`${this.config.dyflexisAppBaseUrl()}${endpoint(employeeId)}`, {
|
||||||
|
headers: {
|
||||||
|
...authHeader,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.pipe(
|
||||||
|
map((response) =>
|
||||||
|
response.data.contracts
|
||||||
|
.sort(
|
||||||
|
({ startDate: dateA }, { startDate: dateB }) =>
|
||||||
|
new Date(dateB).getTime() - new Date(dateA).getTime(),
|
||||||
|
)
|
||||||
|
.map(({ daysPerWeek }) => daysPerWeek)
|
||||||
|
.at(0),
|
||||||
|
),
|
||||||
|
map((daysPerWeek) => ({
|
||||||
|
employeeId,
|
||||||
|
daysPerWeek,
|
||||||
|
})),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
extractHolidays(year: Date): Observable<any> {
|
extractHolidays(year: Date): Observable<any> {
|
||||||
|
|
@ -101,6 +166,9 @@ export class DyflexisUserAccessExtractorsService {
|
||||||
return { bookDate, isLocked, isExcludedFromPayroll, employeeId };
|
return { bookDate, isLocked, isExcludedFromPayroll, employeeId };
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
catchError(() => {
|
||||||
|
return [[]];
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +183,6 @@ export class DyflexisUserAccessExtractorsService {
|
||||||
employees: this.fetchEmployees(authHeader),
|
employees: this.fetchEmployees(authHeader),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
tap(({ employees }) => console.log(employees.length)),
|
|
||||||
switchMap(({ authHeader, employees }) =>
|
switchMap(({ authHeader, employees }) =>
|
||||||
forkJoin(
|
forkJoin(
|
||||||
employees.map((employee) =>
|
employees.map((employee) =>
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,6 @@ export interface FahrzeugItemDto {
|
||||||
verordnungsart: string;
|
verordnungsart: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface SickDaysRaw {
|
export interface SickDaysRaw {
|
||||||
startDate: string;
|
startDate: string;
|
||||||
endDate: string;
|
endDate: string;
|
||||||
|
|
@ -199,3 +198,24 @@ export interface HolidayRaw {
|
||||||
isLocked: boolean;
|
isLocked: boolean;
|
||||||
isExcludedFromPayroll: boolean;
|
isExcludedFromPayroll: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface EmployeeContractRaw {
|
||||||
|
id: number;
|
||||||
|
officeId: number;
|
||||||
|
employeeId: number;
|
||||||
|
typeId: number;
|
||||||
|
serial: string;
|
||||||
|
daysPerWeek: number;
|
||||||
|
hoursPerWeek: number;
|
||||||
|
upperLimit: any;
|
||||||
|
startDate: string;
|
||||||
|
endDate: any;
|
||||||
|
salaryAmount: number;
|
||||||
|
salaryPeriod: number;
|
||||||
|
salaryType: number;
|
||||||
|
hourlySalary: number;
|
||||||
|
active: boolean;
|
||||||
|
workingPattern: any;
|
||||||
|
isSyncedWithPayroll: boolean;
|
||||||
|
lastLockDate: string;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import {
|
||||||
TourRaw,
|
TourRaw,
|
||||||
WorkTimeRaw,
|
WorkTimeRaw,
|
||||||
} from './source.interface';
|
} from './source.interface';
|
||||||
import { Kysely } from 'kysely';
|
import { Kysely, sql } from 'kysely';
|
||||||
import { KYSELY_CLIENT_PROVIDER_TOKEN } from 'src/core/database/database.module';
|
import { KYSELY_CLIENT_PROVIDER_TOKEN } from 'src/core/database/database.module';
|
||||||
import { DB } from 'src/core/database/types';
|
import { DB } from 'src/core/database/types';
|
||||||
|
|
||||||
|
|
@ -112,6 +112,23 @@ export class SourceRepository {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createWorkdays(workdays: { employeeId: number; daysPerWeek: number }[]) {
|
||||||
|
const values = workdays.map(
|
||||||
|
({ employeeId, daysPerWeek }) =>
|
||||||
|
sql`(${employeeId}::int4, ${daysPerWeek}::int4)`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.db
|
||||||
|
.with('v(id, days)', () => sql`(VALUES ${sql.join(values)})`)
|
||||||
|
.updateTable('DyflexisEmployee as e')
|
||||||
|
.set({
|
||||||
|
contractDaysWeek: sql.ref('v.days'),
|
||||||
|
})
|
||||||
|
.from('v')
|
||||||
|
.whereRef('e.id', '=', 'v.id')
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
createPatients(
|
createPatients(
|
||||||
patients: PatientRaw[],
|
patients: PatientRaw[],
|
||||||
jobId: string,
|
jobId: string,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue