Kundgodkännande före arbete — förslag, besked och spärrat arbete

Verkstaden kan inte längre utföra föreslaget arbete utan spårbart besked
från kunden.

- Ny händelse atgardsforslag: föreslagen åtgärd (förifylld ur
  felorsaksanalysen) med uppskattad kostnad — kunddelbar och visad i
  Live Share, där kunden ser förslaget och sitt registrerade besked
- Ny händelse kundbeslut: godkänt/avböjt/delvis med obligatorisk kanal
  (telefon, på plats, e-post, SMS, delningslänk) och motivering vid
  avböjt/delvis; loggposten bär vem i verkstaden som tog emot beskedet
- "Dokumentera utförd åtgärd" är låst medan ett förslag saknar besked
  och förblir låst vid avböjt — vägen "Ingen åtgärd utförd" är öppen
  och hänvisar till beskedet
- Kvalitetsgrinden: besked obligatoriskt när arbete utförts, plus hård
  flagga "Utfört arbete trots avböjt åtgärdsförslag"
- Rapporten får avsnittet "Åtgärdsförslag och kundens besked";
  demoärendet visar hela kedjan förslag → godkännande → åtgärd

Avgränsning: kunden lämnar sitt besked via kontakt med verkstaden som
registrerar det. Publikt godkännande direkt i delningslänken kräver en
skrivande publik endpoint och hanteras separat.

69 vitest-tester, integrationstest, OpenAPI-validering och klicktest
(blockerat arbete utan/vid avböjt besked) gröna.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
This commit is contained in:
Claude
2026-08-03 10:34:44 +00:00
parent 636df0559d
commit 5428684cca
9 changed files with 375 additions and 3 deletions
+27
View File
@@ -29,6 +29,13 @@ export const TIDKATEGORI_LABEL: Record<TidKategori, string> = {
paus: "Paus",
};
// Kundens besked på ett lämnat åtgärdsförslag.
export const KUNDBESLUT_LABEL: Record<"godkant" | "avbojt" | "delvis", string> = {
godkant: "Godkänt",
avbojt: "Avböjt",
delvis: "Delvis godkänt",
};
// Kvalitetskontrollens utfall efter utförd åtgärd.
export const KVALITETSKONTROLL_LABEL: Record<
"symptomet_borta" | "kvarstar" | "delvis" | "ej_verifierbar",
@@ -112,6 +119,22 @@ export type Handelse =
motivering?: string;
ytterligareKontroller?: string;
}
// Kundkommunikation: åtgärdsförslag lämnat till kund för godkännande
// innan arbetet påbörjas. Kunddelbart — visas i Live Share.
| {
typ: "atgardsforslag";
beskrivning: string;
uppskattadKostnad?: string;
uppskattadTid?: string;
}
// Kundens besked på förslaget, med kanal och tidpunkt (loggposten bär
// vem i verkstaden som tog emot beskedet).
| {
typ: "kundbeslut";
beslut: "godkant" | "avbojt" | "delvis";
kanal: string;
kommentar?: string;
}
// Åtgärdsfasen: vad som faktiskt gjordes — eller varför ingen åtgärd
// utfördes (kunden avböjde, väntar på delar …). Kopplas till den
// felorsak åtgärden svarar mot.
@@ -222,6 +245,10 @@ export function handelseRubrik(post: LoggPost): string {
: `Symptomet kunde inte reproduceras — ${h.beskrivning}`;
case "felorsak":
return `Felorsak (${TILLFORLITLIGHET_LABEL[h.sakerhet]}): ${h.avvikelse}${h.orsaker.join(", ")}`;
case "atgardsforslag":
return `Åtgärdsförslag till kund: ${h.beskrivning}${h.uppskattadKostnad ? ` — uppskattad kostnad ${h.uppskattadKostnad}` : ""}`;
case "kundbeslut":
return `Kundens besked (${h.kanal}): ${KUNDBESLUT_LABEL[h.beslut]}${h.kommentar ? `${h.kommentar}` : ""}`;
case "atgard_utford":
return h.utford
? `Åtgärd utförd: ${h.beskrivning}${h.delar ? ` (delar: ${h.delar})` : ""}`