fix: weekbased calculation pdf report

with this change the time calculations for pdf reports should be better
line with the reports send as "week_report"
This commit is contained in:
2026-02-12 16:46:57 +01:00
parent 8911165c4b
commit 46218f9bca
18 changed files with 365 additions and 178 deletions

View File

@@ -63,7 +63,7 @@ func (a *Absence) GetWorktime(u User, base WorktimeBase, includeKurzarbeit bool)
return u.ArbeitszeitProTagFrac(float32(a.AbwesenheitTyp.WorkTime) / 100)
case WorktimeBaseWeek:
if a.AbwesenheitTyp.WorkTime <= 0 && includeKurzarbeit {
return u.ArbeitszeitProTagFrac(0.2)
return u.ArbeitszeitProWocheFrac(0.2)
} else if a.AbwesenheitTyp.WorkTime <= 0 {
return 0
}

View File

@@ -188,7 +188,7 @@ func (b Booking) Save() {
}
func (b *Booking) GetBookingType() string {
debug := (helper.GetEnv("GO_ENV", "production") == "debug")
debug := helper.IsDebug()
switch b.CheckInOut {
case 1: //manuelle Änderung
return "kommen"

View File

@@ -55,7 +55,9 @@ func GetDays(user User, tsFrom, tsTo time.Time, orderedForward bool) []IWorkDay
}
for _, absentDay := range absences {
if weekDay := absentDay.Date().Weekday(); weekDay == time.Saturday || weekDay == time.Sunday {
continue
}
// Check if there is already a day
existingDay, ok := allDays[absentDay.Date().Format(time.DateOnly)]
switch {

View File

@@ -119,6 +119,8 @@ func (p *PublicHoliday) RequiresAction() bool {
}
func (p *PublicHoliday) GetWorktime(u User, base WorktimeBase, includeKurzarbeit bool) time.Duration {
return 0
switch base {
case WorktimeBaseDay:
return u.ArbeitszeitProTagFrac(float32(p.worktime) / 100)

View File

@@ -33,7 +33,7 @@ type User struct {
func GetUserFromSession(Session *scs.SessionManager, ctx context.Context) (User, error) {
var user User
var err error
if helper.GetEnv("GO_ENV", "production") == "debug" {
if helper.IsDebug() {
user, err = GetUserByPersonalNr(123)
} else {
if !Session.Exists(ctx, "user") {
@@ -50,15 +50,15 @@ func GetUserFromSession(Session *scs.SessionManager, ctx context.Context) (User,
}
// Returns the actual overtime for this moment
func (u *User) GetReportedOvertime() (time.Duration, error) {
func (u *User) GetReportedOvertime(startDate time.Time) (time.Duration, error) {
var overtime time.Duration
qStr, err := DB.Prepare("SELECT COALESCE(SUM(EXTRACT(EPOCH FROM ueberstunden) * 1000000000)::BIGINT, 0) AS total_ueberstunden_ns FROM wochen_report WHERE personal_nummer = $1;")
qStr, err := DB.Prepare("SELECT COALESCE(SUM(EXTRACT(EPOCH FROM ueberstunden) * 1000000000)::BIGINT, 0) AS total_ueberstunden_ns FROM wochen_report WHERE personal_nummer = $1 AND woche_start::DATE <= $2::DATE;")
if err != nil {
return 0, err
}
defer qStr.Close()
err = qStr.QueryRow(u.PersonalNummer).Scan(&overtime)
err = qStr.QueryRow(u.PersonalNummer, startDate).Scan(&overtime)
if err != nil {
return 0, err
}

View File

@@ -151,12 +151,21 @@ func (d *WorkDay) Type() DayType {
return DayTypeWorkday
}
func (d *WorkDay) GenerateKurzArbeitBookings(u User) (time.Time, time.Time) {
func (d *WorkDay) GenerateKurzArbeitBookings(u User, weekBase WorktimeBase) (time.Time, time.Time) {
var timeFrom, timeTo time.Time
if d.GetWorktime(u, WorktimeBaseDay, false) >= u.ArbeitszeitProTag() {
return timeFrom, timeTo
}
if d.IsEmpty() {
switch weekBase {
case WorktimeBaseDay:
return d.Day.Add(time.Hour * 8), d.Day.Add(time.Hour * 8).Add(u.ArbeitszeitProTag())
case WorktimeBaseWeek:
return d.Day.Add(time.Hour * 8), d.Day.Add(time.Hour * 8).Add(u.ArbeitszeitProWocheFrac(0.2))
}
}
timeFrom = d.Bookings[len(d.Bookings)-1].Timestamp.Add(time.Minute)
timeTo = timeFrom.Add(u.ArbeitszeitProTag() - d.GetWorktime(u, WorktimeBaseDay, false))
slog.Debug("Added duration as Kurzarbeit", "date", d.Date().String(), "duration", timeTo.Sub(timeFrom).String())
@@ -169,7 +178,7 @@ func (d *WorkDay) GetKurzArbeit() *Absence {
}
func (d *WorkDay) ToString() string {
return fmt.Sprintf("WorkDay: %s with %d bookings and worktime: %s", d.Date().Format(time.DateOnly), len(d.Bookings), helper.FormatDuration(d.workTime))
return fmt.Sprintf("WorkDay: %s with %d bookings and worktime: %s. Is KurzArbeit %v", d.Date().Format(time.DateOnly), len(d.Bookings), helper.FormatDuration(d.workTime), d.IsKurzArbeit())
}
func (d *WorkDay) IsWorkDay() bool {

View File

@@ -6,6 +6,7 @@ package models
// this type is based on the "wochen_report" table
import (
"arbeitszeitmessung/helper"
"database/sql"
"errors"
"log"
@@ -24,10 +25,12 @@ type WorkWeek struct {
Days []IWorkDay
User User
WeekStart time.Time
weekEnd time.Time
Worktime time.Duration
WorktimeVirtual time.Duration
Overtime time.Duration
Status WeekStatus
WeekBase WorktimeBase
}
type WeekStatus int8
@@ -40,10 +43,15 @@ const (
WeekStatusDifferences
)
func NewWorkWeek(user User, tsMonday time.Time, populate bool) WorkWeek {
func NewWorkWeekSimple(user User, tsMonday time.Time, populate bool) WorkWeek {
return NewWorkWeek(user, tsMonday, tsMonday.Add(6*24*time.Hour), populate)
}
func NewWorkWeek(user User, tsStart, tsEnd time.Time, populate bool) WorkWeek {
var week WorkWeek = WorkWeek{
User: user,
WeekStart: tsMonday,
WeekStart: tsStart,
weekEnd: tsEnd,
Status: WeekStatusNone,
}
if populate {
@@ -53,13 +61,20 @@ func NewWorkWeek(user User, tsMonday time.Time, populate bool) WorkWeek {
}
func (w *WorkWeek) PopulateWithDays(worktime time.Duration, overtime time.Duration) {
slog.Debug("Populating Workweek for user", "user", w.User)
slog.Debug("Got Days with overtime and worktime", slog.String("worktime", worktime.String()), slog.String("overtime", overtime.String()))
w.Days = GetDays(w.User, w.WeekStart, w.WeekStart.Add(6*24*time.Hour), false)
w.Days = GetDays(w.User, w.WeekStart, w.weekEnd, false)
slog.Debug("Populating Workweek for user", "user", w.User.Name, "Days", lenWorkDays(w.Days), "Start", w.WeekStart, "End", w.weekEnd, "workdays", helper.GetWorkingDays(w.WeekStart, w.weekEnd))
if lenWorkDays(w.Days) == helper.GetWorkingDays(w.WeekStart, w.weekEnd) {
w.WeekBase = WorktimeBaseWeek
} else {
w.WeekBase = WorktimeBaseDay
}
for _, day := range w.Days {
w.Worktime += day.GetWorktime(w.User, WorktimeBaseDay, false)
w.WorktimeVirtual += day.GetWorktime(w.User, WorktimeBaseDay, true)
w.Worktime += day.GetWorktime(w.User, w.WeekBase, false)
w.WorktimeVirtual += day.GetWorktime(w.User, w.WeekBase, true)
slog.Debug("Calculated Worktime", "Day", day.ToString(), "worktime", w.Worktime.String())
}
slog.Debug("Got worktime for user", "worktime", w.Worktime.String(), "virtualWorkTime", w.WorktimeVirtual.String())
@@ -79,6 +94,16 @@ func (w *WorkWeek) PopulateWithDays(worktime time.Duration, overtime time.Durati
}
}
func lenWorkDays(workDays []IWorkDay) int {
var lenght int
for _, day := range workDays {
if !day.IsEmpty() || day.IsKurzArbeit() {
lenght += 1
}
}
return lenght
}
func (w *WorkWeek) CheckStatus() WeekStatus {
if w.Status != WeekStatusNone {
return w.Status

View File

@@ -20,7 +20,7 @@ func TestNewWorkWeekNoPopulate(t *testing.T) {
if err != nil {
t.Fatal(err)
}
workWeek := models.NewWorkWeek(testUser, monday, false)
workWeek := models.NewWorkWeekSimple(testUser, monday, false)
if workWeek.User != testUser || workWeek.WeekStart != monday {
t.Error("No populate workweek does not have right values!")