feat(zeit): Check-In/Check-Out + Kimai-Sync-Naht (ENTWICKLUN-9)
Arbeitsantritt = bestehender Lock-in (setzt checkedInAt); neu dazu: - Check-Out / Feierabend: dayEntry.checkedOutAt + Endpoint dayEntry.checkOut; Heute-Seite zeigt „Arbeitsantritt HH:MM" und einen „Feierabend / Check-Out"- Button, danach Antritt/Feierabend/Dauer. - Kimai-Anbindung (config-gated, best-effort, nicht blockierend): lib/kimai.ts mit clockIn/clockOut. Check-In startet ein Kimai-Timesheet, Check-Out stoppt es; ID + Sync-Status auf dem dayEntry (kimaiTimesheetId, kimaiSynced). No-Op solange KIMAI_BASE_URL/API_TOKEN/PROJECT_ID/ACTIVITY_ID nicht gesetzt. Migration 0014 (checkedOutAt, kimaiTimesheetId, kimaiSynced). Env-Vars als optional ergänzt + in .env.example dokumentiert. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
9942cd8e88
commit
5bbb4abffa
9 files changed
+3542
-2
No files matched your search
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE "day_entry" ADD COLUMN "checked_out_at" timestamp with time zone;--> statement-breakpoint
|
||||
ALTER TABLE "day_entry" ADD COLUMN "kimai_timesheet_id" integer;--> statement-breakpoint
|
||||
ALTER TABLE "day_entry" ADD COLUMN "kimai_synced" boolean DEFAULT false NOT NULL;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -99,6 +99,13 @@
|
||||
"when": 1780763141548,
|
||||
"tag": "0013_parallel_timers",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"version": "7",
|
||||
"when": 1780764129593,
|
||||
"tag": "0014_checkout_kimai",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -219,6 +219,11 @@ export const dayEntry = pgTable(
|
||||
date: date('date').notNull(), // YYYY-MM-DD im Europe/Berlin
|
||||
status: text('status', { enum: ['begun', 'full', 'absent'] }).notNull(),
|
||||
checkedInAt: timestamp('checked_in_at', { withTimezone: true }),
|
||||
// Arbeitsende (Check-Out) — markiert das Ende der Arbeits-Session des Tages.
|
||||
checkedOutAt: timestamp('checked_out_at', { withTimezone: true }),
|
||||
// Kimai-Sync: ID des bei Check-In gestarteten Timesheets + Sync-Status.
|
||||
kimaiTimesheetId: integer('kimai_timesheet_id'),
|
||||
kimaiSynced: boolean('kimai_synced').notNull().default(false),
|
||||
reflectedAt: timestamp('reflected_at', { withTimezone: true }),
|
||||
reflectionText: text('reflection_text'),
|
||||
ampel: text('ampel', { enum: ['green', 'amber', 'red'] }),
|
||||
|
||||
Reference in new issue
Block a user