commit working state

Too many changes to split them up. This commit contains roughly two months worth of work.

This commit introduces the first aggregate and rewrites the ticket system to follow DDD patterns.
It adds Spartan NG as the new component library. TanStack Query to replace GraphQL. Oh and Prisma is
almost over as well.
This commit is contained in:
Marcel Arndt
2026-01-19 12:21:48 +01:00
parent 62e663d053
commit ce676f20a4
334 changed files with 64333 additions and 52554 deletions
@@ -205,13 +205,13 @@ type Anomaly struct {
Description string `json:"description"`
GroupKey string `json:"groupKey"`
GroupDescription string `json:"groupDescription"`
AssociatedEntities []byte `json:"associatedEntities"`
WorkedOnBy string `json:"workedOnBy"`
SleepTimer int32 `json:"sleepTimer"`
SleepSince *time.Time `json:"sleepSince"`
ResolvedAt *time.Time `json:"resolvedAt"`
ManuallyResolved bool `json:"manuallyResolved"`
CreatedAt time.Time `json:"createdAt"`
AssociatedEntities []byte `json:"associatedEntities"`
}
type AttendanceRegistration struct {
@@ -266,16 +266,16 @@ type CostType struct {
}
type DyflexisEmployee struct {
InternalId pgtype.UUID `json:"internalId"`
ID int32 `json:"id"`
Firstname string `json:"firstname"`
Surname string `json:"surname"`
ContractStart time.Time `json:"contractStart"`
ContractEnd *time.Time `json:"contractEnd"`
ContractDaysWeek int32 `json:"contractDaysWeek"`
ContractHoursWeek float64 `json:"contractHoursWeek"`
ContractSalaryHour float64 `json:"contractSalaryHour"`
ContractTypeName pgtype.Text `json:"contractTypeName"`
InternalId pgtype.UUID `json:"internalId"`
ContractDaysWeek int32 `json:"contractDaysWeek"`
}
type Employee struct {
@@ -438,19 +438,8 @@ type PlannedTimeStaging struct {
EndDate time.Time `json:"endDate"`
Deleted bool `json:"deleted"`
Mark pgtype.Text `json:"mark"`
Duration int32 `json:"duration"`
Pause int32 `json:"pause"`
}
type PrismaMigration struct {
ID string `json:"id"`
Checksum string `json:"checksum"`
FinishedAt *time.Time `json:"finished_at"`
MigrationName string `json:"migration_name"`
Logs pgtype.Text `json:"logs"`
RolledBackAt *time.Time `json:"rolled_back_at"`
StartedAt time.Time `json:"started_at"`
AppliedStepsCount int32 `json:"applied_steps_count"`
Duration int32 `json:"duration"`
}
type Sickday struct {
@@ -490,15 +479,25 @@ type TariffGroup struct {
}
type Ticket struct {
ID pgtype.UUID `json:"id"`
CurrentState TicketValidationState `json:"currentState"`
Notes []string `json:"notes"`
Errors []string `json:"errors"`
IsUrgent bool `json:"isUrgent"`
Urgency time.Time `json:"urgency"`
ApprovalState NullApprovalState `json:"approvalState"`
DocumentInfo []byte `json:"documentInfo"`
CreatedAt time.Time `json:"createdAt"`
ID pgtype.UUID `json:"id"`
PatientId pgtype.UUID `json:"patientId"`
Stage string `json:"stage"`
ApprovalRequirement string `json:"approvalRequirement"`
ApprovalStatus string `json:"approvalStatus"`
ApprovalRequestedAt *time.Time `json:"approvalRequestedAt"`
ApprovalLastInteractionAt *time.Time `json:"approvalLastInteractionAt"`
ApprovalReminderCount int32 `json:"approvalReminderCount"`
HasPhysicalTransportDocument bool `json:"hasPhysicalTransportDocument"`
HasDigitalTransportDocument bool `json:"hasDigitalTransportDocument"`
UpdatedAt *time.Time `json:"updatedAt"`
CreatedAt time.Time `json:"createdAt"`
CurrentState NullTicketValidationState `json:"currentState"`
Notes []string `json:"notes"`
Errors []string `json:"errors"`
IsUrgent bool `json:"isUrgent"`
Urgency time.Time `json:"urgency"`
ApprovalState NullApprovalState `json:"approvalState"`
DocumentInfo []byte `json:"documentInfo"`
}
type TicketStateHistory struct {
@@ -556,13 +555,13 @@ type Tour struct {
Revenue float64 `json:"revenue"`
ConsumptionCosts float64 `json:"consumptionCosts"`
RevenueDeviation float64 `json:"revenueDeviation"`
OverRTW bool `json:"overRTW"`
CompanyName pgtype.Text `json:"companyName"`
Schwerlast bool `json:"schwerlast"`
CreatedAt *time.Time `json:"createdAt"`
UpdatedAt *time.Time `json:"updatedAt"`
DeletedAt *time.Time `json:"deletedAt"`
TicketId pgtype.UUID `json:"ticketId"`
UpdatedAt *time.Time `json:"updatedAt"`
CompanyName pgtype.Text `json:"companyName"`
OverRTW bool `json:"overRTW"`
Schwerlast bool `json:"schwerlast"`
}
type TourFile struct {
@@ -584,6 +583,7 @@ type TourSource struct {
ID pgtype.Text `json:"id"`
Check pgtype.Text `json:"check"`
CreateTime pgtype.Text `json:"createTime"`
LastUpdate pgtype.Text `json:"lastUpdate"`
EmpfangenVonId pgtype.Text `json:"empfangenVonId"`
Endgen pgtype.Text `json:"endgen"`
SerienId pgtype.Text `json:"serienId"`
@@ -645,9 +645,8 @@ type TourSource struct {
FahrerName pgtype.Text `json:"fahrerName"`
Fahrer pgtype.Text `json:"fahrer"`
Color pgtype.Text `json:"color"`
LastUpdate pgtype.Text `json:"lastUpdate"`
CompanyName pgtype.Text `json:"companyName"`
OverRTW pgtype.Text `json:"overRTW"`
CompanyName pgtype.Text `json:"companyName"`
Schwerlast pgtype.Text `json:"schwerlast"`
}
@@ -700,11 +699,11 @@ type TourStaging struct {
Revenue float64 `json:"revenue"`
RevenueDeviation float64 `json:"revenueDeviation"`
ConsumptionCosts float64 `json:"consumptionCosts"`
OverRTW bool `json:"overRTW"`
CompanyName pgtype.Text `json:"companyName"`
Schwerlast bool `json:"schwerlast"`
CreatedAt *time.Time `json:"createdAt"`
UpdatedAt *time.Time `json:"updatedAt"`
CompanyName pgtype.Text `json:"companyName"`
OverRTW bool `json:"overRTW"`
Schwerlast bool `json:"schwerlast"`
}
type Trace struct {
@@ -751,6 +750,6 @@ type WorkTimeStaging struct {
DepartmentName pgtype.Text `json:"departmentName"`
StartDate time.Time `json:"startDate"`
EndDate time.Time `json:"endDate"`
Duration int32 `json:"duration"`
Pause int32 `json:"pause"`
Duration int32 `json:"duration"`
}
@@ -21,16 +21,7 @@ WITH ToursInPeriod AS (
CASE
WHEN "occupiedKm" <= 30 THEN 1.0
ELSE ROUND("occupiedKm" / 30.0)
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
END AS tour_value
FROM
"Tour"
WHERE
@@ -62,7 +53,7 @@ WITH ToursInPeriod AS (
DailyCounts AS (
SELECT
day,
SUM(tour_value) + SUM(weekend_bonus) + SUM(infection_bonus) AS tour_amount
SUM(tour_value) AS tour_amount
FROM
ToursInPeriod
GROUP BY
@@ -358,7 +349,7 @@ SELECT
FROM "DyflexisEmployee" as de
INNER JOIN "Employee" as e ON de.id::text = e."personnelNumber"
WHERE de."contractStart" < CURRENT_DATE AND de."contractEnd" > (CURRENT_DATE - INTERVAL '2 months')
AND de.surname <> 'Shahrasebhi'
AND de.surname <> 'Shahrasebi'
ORDER BY de.firstname ASC
`
@@ -194,6 +194,15 @@ func genLineItemsFromStatement(stmt domain.PayrollStatement) []LineItem {
Faktor: 125,
})
}
if stmt.Feiertagszuschlag150 > 0 {
items = append(items, LineItem{
Lohnart: "0124",
Beschreibung: "Feiertagszuschlag 150%",
Anzahl: stmt.Feiertagszuschlag150,
Betrag: stmt.VertragStundenlohn,
Faktor: 150,
})
}
if stmt.Nachtzuschlag25 > 0 {
items = append(items, LineItem{
Lohnart: "0505",
@@ -25,7 +25,7 @@ func NewEmployeeHandler(service Service, logger *slog.Logger) *EmployeeHandler {
}
func (h *EmployeeHandler) RunPayroll(w http.ResponseWriter, r *http.Request) {
month := time.Date(2025, time.December, 1, 0, 0, 0, 0, time.UTC)
month := time.Date(2026, time.January, 1, 0, 0, 0, 0, time.UTC)
employees, err := h.service.FetchActiveEmployees(r.Context())
if err != nil {