adding more logging + working on displaying if a workday was submitted
Some checks failed
Tests / Run Go Tests (push) Failing after 1m55s
Some checks failed
Tests / Run Go Tests (push) Failing after 1m55s
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -87,6 +88,27 @@ func (b *Booking) Verify() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (b *Booking) IsSubmittedAndChecked() bool {
|
||||
qStr, err := DB.Prepare(`SELECT bestaetigt from wochen_report WHERE $1 = ANY(anwesenheiten);`)
|
||||
if err != nil {
|
||||
slog.Warn("Error when preparing SQL Statement", "error", err)
|
||||
return false
|
||||
}
|
||||
defer qStr.Close()
|
||||
var isSubmittedAndChecked bool = false
|
||||
|
||||
err = qStr.QueryRow(b.CounterId).Scan(&isSubmittedAndChecked)
|
||||
if err == sql.ErrNoRows {
|
||||
// No rows found ==> not even submitted
|
||||
return false
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
slog.Warn("Unexpected error when executing SQL Statement", "error", err)
|
||||
}
|
||||
return isSubmittedAndChecked
|
||||
}
|
||||
|
||||
func (b *Booking) Insert() error {
|
||||
if !checkLastBooking(*b) {
|
||||
return SameBookingError{}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
@@ -110,6 +111,7 @@ func (d *WorkDay) TimeWorkReal(u User) time.Duration {
|
||||
if helper.IsSameDate(d.Date(), time.Now()) && len(d.Bookings)%2 == 1 {
|
||||
d.realWorkTime += time.Since(lastBooking.Timestamp.Local())
|
||||
}
|
||||
slog.Debug("Calculated RealWorkTime for user", "user", u, slog.String("worktime", d.realWorkTime.String()))
|
||||
return d.realWorkTime
|
||||
}
|
||||
|
||||
|
||||
@@ -4,23 +4,25 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"log"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
// Workweeks are
|
||||
|
||||
type WorkWeek struct {
|
||||
Id int
|
||||
WorkDays []WorkDay
|
||||
Absences []Absence
|
||||
Days []IWorkDay
|
||||
User User
|
||||
WeekStart time.Time
|
||||
Worktime time.Duration
|
||||
Overtime time.Duration
|
||||
Status WeekStatus
|
||||
overtimeDiff time.Duration
|
||||
worktimeDiff time.Duration
|
||||
Id int
|
||||
WorkDays []WorkDay
|
||||
Absences []Absence
|
||||
Days []IWorkDay
|
||||
User User
|
||||
WeekStart time.Time
|
||||
Worktime time.Duration
|
||||
WorkTimeVirtual time.Duration
|
||||
Overtime time.Duration
|
||||
Status WeekStatus
|
||||
}
|
||||
|
||||
type WeekStatus int8
|
||||
@@ -45,16 +47,17 @@ func NewWorkWeek(user User, tsMonday time.Time, populate bool) WorkWeek {
|
||||
}
|
||||
|
||||
func (w *WorkWeek) PopulateWithDays(worktime time.Duration, overtime time.Duration) {
|
||||
log.Println("Got Days with overtime and worktime", worktime, overtime)
|
||||
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)
|
||||
log.Println(w.Worktime)
|
||||
|
||||
for _, day := range w.Days {
|
||||
log.Println(day.TimeWorkVirtual(w.User))
|
||||
w.Worktime += day.TimeWorkVirtual(w.User)
|
||||
work, _ := day.TimePauseReal(w.User)
|
||||
w.Worktime += work
|
||||
w.WorkTimeVirtual += day.TimeWorkVirtual(w.User)
|
||||
}
|
||||
log.Println("Calculated new worktime", w.Worktime)
|
||||
w.Overtime = w.Worktime - w.User.ArbeitszeitProWoche()
|
||||
slog.Debug("Got worktime for user", "user", w.User, "worktime", w.Worktime.String(), "virtualWorkTime", w.WorkTimeVirtual.String())
|
||||
|
||||
w.Overtime = w.WorkTimeVirtual - w.User.ArbeitszeitProWoche()
|
||||
|
||||
w.Worktime = w.Worktime.Round(time.Minute)
|
||||
w.Overtime = w.Overtime.Round(time.Minute)
|
||||
@@ -65,8 +68,6 @@ func (w *WorkWeek) PopulateWithDays(worktime time.Duration, overtime time.Durati
|
||||
|
||||
if overtime != w.Overtime || worktime != w.Worktime {
|
||||
w.Status = WeekStatusDifferences
|
||||
w.overtimeDiff = overtime
|
||||
w.worktimeDiff = worktime
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,30 +150,70 @@ func (w *WorkWeek) GetSendWeeks(user User) []WorkWeek {
|
||||
|
||||
var ErrRunningWeek = errors.New("Week is in running week")
|
||||
|
||||
func (w *WorkWeek) GetBookingIds() (anwesenheitsIds, abwesenheitsIds []int64, err error) {
|
||||
qStr, err := DB.Prepare(`
|
||||
SELECT
|
||||
(SELECT array_agg(counter_id ORDER BY counter_id)
|
||||
FROM anwesenheit
|
||||
WHERE card_uid = $1
|
||||
AND timestamp::DATE >= $2
|
||||
AND timestamp::DATE < $3) AS anwesenheit,
|
||||
|
||||
(SELECT array_agg(counter_id ORDER BY counter_id)
|
||||
FROM abwesenheit
|
||||
WHERE card_uid = $1
|
||||
AND datum_from < $3
|
||||
AND datum_to >= $2) AS abwesenheit;
|
||||
`)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer qStr.Close()
|
||||
|
||||
slog.Debug("Inserting parameters into qStr:", "user card_uid", w.User.CardUID, "week_start", w.WeekStart, "week_end", w.WeekStart.AddDate(0, 0, 5))
|
||||
|
||||
err = qStr.QueryRow(w.User.CardUID, w.WeekStart, w.WeekStart.AddDate(0, 0, 5)).Scan(pq.Array(&anwesenheitsIds), pq.Array(&abwesenheitsIds))
|
||||
if err != nil {
|
||||
return anwesenheitsIds, abwesenheitsIds, err
|
||||
}
|
||||
return anwesenheitsIds, abwesenheitsIds, nil
|
||||
}
|
||||
|
||||
// creates a new entry in the woche_report table with the given workweek
|
||||
func (w *WorkWeek) SendWeek() error {
|
||||
var qStr *sql.Stmt
|
||||
var err error
|
||||
|
||||
slog.Info("Sending workWeek to team head", "week", w.WeekStart.String())
|
||||
|
||||
anwBookings, awBookings, err := w.GetBookingIds()
|
||||
if err != nil {
|
||||
slog.Warn("Error querying bookings from work week", slog.Any("error", err))
|
||||
return err
|
||||
}
|
||||
|
||||
slog.Debug("Recieved Booking Ids", "anwesenheiten", anwBookings)
|
||||
|
||||
if time.Since(w.WeekStart) < 5*24*time.Hour {
|
||||
log.Println("Cannot send week, because it's the running week!")
|
||||
slog.Warn("Cannot send week, because it's the running week!")
|
||||
return ErrRunningWeek
|
||||
}
|
||||
|
||||
if w.CheckStatus() != WeekStatusNone {
|
||||
qStr, err = DB.Prepare(`UPDATE "wochen_report" SET bestaetigt = FALSE, arbeitszeit = make_interval(secs => $3::numeric / 1000000000), ueberstunden = make_interval(secs => $4::numeric / 1000000000) WHERE personal_nummer = $1 AND woche_start = $2;`)
|
||||
qStr, err = DB.Prepare(`UPDATE "wochen_report" SET bestaetigt = FALSE, arbeitszeit = make_interval(secs => $3::numeric / 1000000000), ueberstunden = make_interval(secs => $4::numeric / 1000000000), anwesenheiten=$5, abwesenheiten=$6 WHERE personal_nummer = $1 AND woche_start = $2;`)
|
||||
if err != nil {
|
||||
log.Println("Error preparing SQL statement", err)
|
||||
slog.Warn("Error preparing SQL statement", "error", err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
qStr, err = DB.Prepare(`INSERT INTO wochen_report (personal_nummer, woche_start, arbeitszeit, ueberstunden) VALUES ($1, $2, make_interval(secs => $3::numeric / 1000000000), make_interval(secs => $4::numeric / 1000000000));`)
|
||||
qStr, err = DB.Prepare(`INSERT INTO wochen_report (personal_nummer, woche_start, arbeitszeit, ueberstunden, anwesenheiten, abwesenheiten) VALUES ($1, $2, make_interval(secs => $3::numeric / 1000000000), make_interval(secs => $4::numeric / 1000000000), $5, $6);`)
|
||||
if err != nil {
|
||||
log.Println("Error preparing SQL statement", err)
|
||||
slog.Warn("Error preparing SQL statement", "error", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = qStr.Exec(w.User.PersonalNummer, w.WeekStart, int64(w.Worktime), int64(w.Overtime))
|
||||
|
||||
_, err = qStr.Exec(w.User.PersonalNummer, w.WeekStart, int64(w.Worktime), int64(w.Overtime), pq.Array(anwBookings), pq.Array(awBookings))
|
||||
if err != nil {
|
||||
log.Println("Error executing query!", err)
|
||||
return err
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.943
|
||||
// templ: version: v0.3.924
|
||||
package templates
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.943
|
||||
// templ: version: v0.3.924
|
||||
package templates
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.943
|
||||
// templ: version: v0.3.924
|
||||
package templates
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
@@ -81,7 +81,7 @@ templ weekDayComponent(user models.User, day models.WorkDay) {
|
||||
templ workWeekComponent(week models.WorkWeek, onlyAccept bool) {
|
||||
{{
|
||||
year, kw := week.WeekStart.ISOWeek()
|
||||
progress := (float32(week.Worktime.Hours()) / week.User.ArbeitszeitPerWoche) * 100
|
||||
progress := (float32(week.WorkTimeVirtual.Hours()) / week.User.ArbeitszeitPerWoche) * 100
|
||||
}}
|
||||
<div class="employeComponent grid-sub responsive lg:divide-x-1 max-md:divide-y-1 @container">
|
||||
<div class="grid-cell flex flex-col max-md:bg-neutral-300 gap-2">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.943
|
||||
// templ: version: v0.3.924
|
||||
package templates
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@@ -346,7 +346,7 @@ func workWeekComponent(week models.WorkWeek, onlyAccept bool) templ.Component {
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
|
||||
year, kw := week.WeekStart.ISOWeek()
|
||||
progress := (float32(week.Worktime.Hours()) / week.User.ArbeitszeitPerWoche) * 100
|
||||
progress := (float32(week.WorkTimeVirtual.Hours()) / week.User.ArbeitszeitPerWoche) * 100
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<div class=\"employeComponent grid-sub responsive lg:divide-x-1 max-md:divide-y-1 @container\"><div class=\"grid-cell flex flex-col max-md:bg-neutral-300 gap-2\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
|
||||
@@ -120,6 +120,9 @@ templ bookingComponent(booking models.Booking) {
|
||||
<input disabled name={ "booking_" + strconv.Itoa(booking.CounterId) } type="time" value={ booking.Timestamp.Format("15:04") } class="text-neutral-700 group-[.edit]:inline hidden bg-neutral-100 text-sm px-3 py-2 cursor-pointer"/>
|
||||
{ booking.GetBookingType() }
|
||||
</p>
|
||||
if booking.IsSubmittedAndChecked() {
|
||||
<p>submitted</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.943
|
||||
// templ: version: v0.3.924
|
||||
package templates
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@@ -568,7 +568,17 @@ func bookingComponent(booking models.Booking) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</p></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</p>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if booking.IsSubmittedAndChecked() {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<p>submitted</p>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -597,7 +607,7 @@ func LegendComponent() templ.Component {
|
||||
templ_7745c5c3_Var31 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<div class=\"flex flex-row gap-4 md:mx-[10%] print:hidden\"><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-red-600\"></div><span>Fehler</span></div><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-orange-500\"></div><span>Arbeitszeit unter regulär</span></div><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-accent\"></div><span>Arbeitszeit vollständig</span></div><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-purple-600\"></div><span>Überstunden</span></div><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-neutral-400\"></div><span>Keine Buchungen</span></div></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<div class=\"flex flex-row gap-4 md:mx-[10%] print:hidden\"><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-red-600\"></div><span>Fehler</span></div><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-orange-500\"></div><span>Arbeitszeit unter regulär</span></div><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-accent\"></div><span>Arbeitszeit vollständig</span></div><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-purple-600\"></div><span>Überstunden</span></div><div class=\"flex flex-row items-center gap-2\"><div class=\"rounded-full size-4 bg-neutral-400\"></div><span>Keine Buchungen</span></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.943
|
||||
// templ: version: v0.3.924
|
||||
package templates
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
@@ -22,7 +22,7 @@ COMMENT ON COLUMN "anwesenheit"."geraet_id" IS 'ID des Lesegerätes';
|
||||
DROP TABLE IF EXISTS "s_anwesenheit_typen";
|
||||
CREATE TABLE "s_anwesenheit_typen" (
|
||||
"anwesenheit_id" int2 PRIMARY KEY,
|
||||
"anwesenheit_name" varchar(255)
|
||||
"anwesenheit_name" varchar(255) NOT NULL
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
@@ -78,30 +78,34 @@ EXECUTE FUNCTION update_zuletzt_geandert();
|
||||
DROP TABLE IF EXISTS "wochen_report";
|
||||
CREATE TABLE "wochen_report" (
|
||||
"id" serial PRIMARY KEY,
|
||||
"personal_nummer" int4,
|
||||
"woche_start" date,
|
||||
"personal_nummer" int4 NOT NULL,
|
||||
"woche_start" date NOT NULL,
|
||||
"bestaetigt" bool DEFAULT FALSE,
|
||||
"arbeitszeit" interval,
|
||||
"ueberstunden" interval,
|
||||
"arbeitszeit" interval NOT NULL,
|
||||
"ueberstunden" interval NOT NULL,
|
||||
"anwesenheiten" int ARRAY,
|
||||
"abwesenheiten" int ARRAY,
|
||||
UNIQUE ("personal_nummer", "woche_start")
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS "abwesenheit";
|
||||
CREATE TABLE "abwesenheit" (
|
||||
"counter_id" bigserial PRIMARY KEY,
|
||||
"card_uid" varchar(255),
|
||||
"abwesenheit_typ" int2,
|
||||
"datum_from" timestamptz DEFAULT NOW()::DATE,
|
||||
"datum_to" timestamptz
|
||||
"card_uid" varchar(255) NOT NULL,
|
||||
"abwesenheit_typ" int2 NOT NULL,
|
||||
"datum_from" timestamptz DEFAULT NOW()::DATE NOT NULL,
|
||||
"datum_to" timestamptz NOT NULL
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS "s_abwesenheit_typen";
|
||||
CREATE TABLE "s_abwesenheit_typen" (
|
||||
"abwesenheit_id" int2 PRIMARY KEY,
|
||||
"abwesenheit_name" varchar(255),
|
||||
"arbeitszeit_equivalent" float4
|
||||
"abwesenheit_id" int2 PRIMARY KEY NOT NULL,
|
||||
"abwesenheit_name" varchar(255) NOT NULL,
|
||||
"arbeitszeit_equivalent" float4 NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN "s_abwesenheit_typen"."arbeitszeit_equivalent" IS '0=keine Arbeitszeit; 1=Arbeitszeit auffüllen; 2=Arbeitszeit austauschen';
|
||||
|
||||
-- Adds crypto extension
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
4
migrations/20251013212224_buchungs_array.down.sql
Normal file
4
migrations/20251013212224_buchungs_array.down.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- reverse: modify "wochen_report" table
|
||||
ALTER TABLE "wochen_report" DROP COLUMN "abwesenheiten", DROP COLUMN "anwesenheiten", ALTER COLUMN "arbeitszeit" DROP NOT NULL, ALTER COLUMN "ueberstunden" DROP NOT NULL, ALTER COLUMN "woche_start" DROP NOT NULL;
|
||||
-- reverse: modify "abwesenheit" table
|
||||
ALTER TABLE "abwesenheit" ALTER COLUMN "datum_to" DROP NOT NULL;
|
||||
4
migrations/20251013212224_buchungs_array.up.sql
Normal file
4
migrations/20251013212224_buchungs_array.up.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- modify "abwesenheit" table
|
||||
ALTER TABLE "abwesenheit" ALTER COLUMN "datum_to" SET NOT NULL;
|
||||
-- modify "wochen_report" table
|
||||
ALTER TABLE "wochen_report" ALTER COLUMN "woche_start" SET NOT NULL, ALTER COLUMN "ueberstunden" SET NOT NULL, ALTER COLUMN "arbeitszeit" SET NOT NULL, ADD COLUMN "anwesenheiten" integer[] NULL, ADD COLUMN "abwesenheiten" integer[] NULL;
|
||||
@@ -1,15 +1,9 @@
|
||||
h1:3AxgD8mnu/F+JGtJu9FZvA9Ro0UUtGPgyjskKtfTYUQ=
|
||||
20250901201159_initial.down.sql h1:cmF5CvNGqEfcmbRgiqaqDWERdNNRaMzarbNLJ/Y35o4=
|
||||
20250901201159_initial.up.sql h1:Yrak/+wfQ4Tu/dVR/cUZ/75DlAcv4G/OJXDqpgSw47U=
|
||||
20250901201250_control_tables.down.sql h1:f/KmhO9pOI45J8ZRjFonvD3CypB+rOoGOPN2WMFHvOw=
|
||||
20250901201250_control_tables.up.sql h1:of5E07p0N1aen9CdQNEOrO7ffbKZC6kp4oK5KPzU9+g=
|
||||
20250901201710_triggers_extension.down.sql h1:a9va3FSfHBWzODJSJO+ywNa2hiZwjG/vmvYGb3L1lnM=
|
||||
20250901201710_triggers_extension.up.sql h1:nUBPd2eDssi/TwMVF/nOJkIM5rUM0iINdg1K9pZRZN0=
|
||||
20250903221313_overtime.down.sql h1:X+jJESqcZ6ZTd2H563z6kRaXb4dn4sA02D3ck2795v8=
|
||||
20250903221313_overtime.up.sql h1:C3DSiNVpe9v0Un1DEQ0lsy5yToR8iqcggv91GSr6tRE=
|
||||
20250903233030_non_null_contraints.down.sql h1:42TZzPsji2Ze50k6sLwgIuNo4Trk3m3ni/aIfQJ97dE=
|
||||
20250903233030_non_null_contraints.up.sql h1:k6zR5YNSAP4fo5QEc58KZ0LxvEz1nl0X/AAcZ+TG3I4=
|
||||
20250904114004_intervals.down.sql h1:SquJAPinzFIRN6fJjLLIRsz59Tyr4RwGiGuOFI/N1SQ=
|
||||
20250904114004_intervals.up.sql h1:AFqncTGOiEZVBbhWFqN2zlQ7DyhybB5wJr6a36Atk1E=
|
||||
20250916093608_kurzarbeit.down.sql h1:ljM1a1pQCxOQiXRaXU04GC4V9yy2y20x5eUNQ/zyx+o=
|
||||
20250916093608_kurzarbeit.up.sql h1:pTiw0VfGaf26mhJg4wf98Fqwn1kShJ+PiN2PiM4q1kk=
|
||||
h1:gE7ikkZS7bQbedAjVspQKftSo5ODij2eiQGWbfQEYmI=
|
||||
20250901201159_initial.up.sql h1:Mb1RlVdFvcxqU9HrSK6oNeURqFa3O4KzB3rDa+6+3gc=
|
||||
20250901201250_control_tables.up.sql h1:a5LATgR/CRiC4GsqxkJ94TyJOxeTcW74eCnodIy+c1E=
|
||||
20250901201710_triggers_extension.up.sql h1:z9b6Hk9btE2Ns4mU7B16HjvYBP6EEwHAXVlvPpkn978=
|
||||
20250903221313_overtime.up.sql h1:t/B435ShW5ZEnzC81jRABWVZ5gNm7tPZPnOO6/ZY6ow=
|
||||
20250903233030_non_null_contraints.up.sql h1:YKeYgazfh+jPyh7hFT/pV+By8eHnk1taXnlgSLyXSA0=
|
||||
20250904114004_intervals.up.sql h1:gDdN8cJ4xH1vQhAbbhqD5lwdyEO1N9EIqEYkmWGiWIU=
|
||||
20250916093608_kurzarbeit.up.sql h1:yDAAMLyUXz6b7+MI6XK/HZMPzutKoT2NNNOCjFaqSts=
|
||||
20251013212224_buchungs_array.up.sql h1:mbhvnwMUkEFFQQ41NC47auqxbtvNkztziWvpLDFm6tA=
|
||||
|
||||
Reference in New Issue
Block a user