Merge lane/einsatz in feature/craftvia-mvp

Konflikte gelöst: processors/index.ts (report-pdf + image-derivatives),
(app)/layout.tsx (Logo, Glocke, AccountInactiveNotice). L5-Mobilseiten
report/sign nach src/app/(field)/m/(core)/orders/[id]/ verschoben.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 12:32:35 +02:00
co-authored by Claude Opus 5
76 changed files with 5608 additions and 66 deletions
+35
View File
@@ -0,0 +1,35 @@
"use server";
import { revalidatePath } from "next/cache";
import { moduleGuard } from "@/server/action-guard";
import { ctxFromGuard, ServiceError } from "@/server/services/context";
import { correctTimeEntry } from "@/server/services/field/time-correction";
const guard = moduleGuard("field");
export type TimeCorrectionResult = { ok: true } | { ok: false; error: "invalid" | "forbidden" | "not_found" | "failed" };
/** Manual time correction (Spec §12.2) — thin adapter over services/field/time-correction. */
export async function correctTime(input: {
workOrderId: string;
timeEntryId: string;
startedAt: string;
endedAt: string | null;
reason: string;
}): Promise<TimeCorrectionResult> {
const g = await guard("field:correct_time");
try {
await correctTimeEntry(ctxFromGuard(g), {
timeEntryId: input.timeEntryId,
startedAt: input.startedAt,
endedAt: input.endedAt,
reason: input.reason,
});
} catch (err) {
if (err instanceof ServiceError && (err.code === "invalid" || err.code === "forbidden" || err.code === "not_found")) return { ok: false, error: err.code };
console.error("[field] time correction failed:", err);
return { ok: false, error: "failed" };
}
revalidatePath(`/m/orders/${input.workOrderId}/time`);
return { ok: true };
}