From 5428684cca44e66be46e005f72a02476c970ac54 Mon Sep 17 00:00:00 2001
From: Claude
Date: Mon, 3 Aug 2026 10:34:44 +0000
Subject: [PATCH] =?UTF-8?q?Kundgodk=C3=A4nnande=20f=C3=B6re=20arbete=20?=
=?UTF-8?q?=E2=80=94=20f=C3=B6rslag,=20besked=20och=20sp=C3=A4rrat=20arbet?=
=?UTF-8?q?e?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
---
docs/MVP.md | 1 +
docs/moduler/evidensmotor.md | 24 ++++
services/plattform/openapi.yaml | 2 +
src/felsokning/DelatArendeVy.tsx | 33 ++++-
src/felsokning/__tests__/ecm.test.ts | 56 +++++++++
src/felsokning/demo.ts | 13 ++
src/felsokning/domain.ts | 27 ++++
src/felsokning/ecm.ts | 41 ++++++
src/pages/felsokning/ArendeSida.tsx | 181 ++++++++++++++++++++++++++-
9 files changed, 375 insertions(+), 3 deletions(-)
diff --git a/docs/MVP.md b/docs/MVP.md
index 740856f..219acd7 100644
--- a/docs/MVP.md
+++ b/docs/MVP.md
@@ -38,6 +38,7 @@ Demomanus för visning: [DEMO.md](DEMO.md). Knappen **Skapa demoärende** på st
| Pre-diagnostik | ✅ Ingen felsökning förrän grundkontrollerna är gjorda eller motiverade: fordonshistorik — tidigare ärenden på samma fordon hämtas automatiskt med sina felorsaker (server i inloggat läge, lokala storen annars) och orsakskedjan kopplas med ett tryck; Ja/Nej med obligatorisk orsak → kvalitetsvarning, **ingående mätarställning** (foto av instrumentpanelen, bildtolkningen föreslår värdet), kundens felbeskrivning verifierad och tidiga observationer hanterade. Metodiken låses upp först därefter. **Utgående mätarställning** fotograferas inför avslut och blir obligatorisk i grinden när ärendet stängs. |
| Symptomverifiering (SVP) | ✅ Kundens beskrivning ≠ konstaterat fel: beskrivningen dokumenteras ordagrant, förtydligas via metodikens symptomfrågor (generiska metodiken har SVP-setet när/var/hur) och reproduceras — Ja (hur/förhållanden), Delvis (vad kunde/kunde inte) eller Nej (obligatorisk motivering). Rapportens beviskedja skiljer kundens beskrivning, verifierad observation, felorsaksanalys och rekommenderad åtgärd; formuleringen "kunde inte reproduceras under de förhållanden som rådde" används i stället för "felet konstaterat" (kodat även i orkesterns grundprompt). |
| Felorsaksanalys | ✅ Obligatorisk före avslut: konstaterad avvikelse (kvalitetsregeln avvisar "trasig/defekt/sliten" utan förklaring), orsakskategorier (inkl. Okänd orsak med krav på motivering), minst en evidenskälla som valideras mot loggen, säkerhetsnivå (medel/låg kräver stärkande kontroller) och rekommenderad åtgärd. Avslutsknappen spärrad tills SVP + felorsak finns; kvalitetsgrinden gör båda obligatoriska vid stängning. Eget avsnitt i slutrapporten. |
+| Kundgodkännande | ✅ Åtgärdsförslag lämnas till kund innan arbetet påbörjas (förifyllt ur felorsaksanalysen, med uppskattad kostnad) och **visas i Live Share** — kunden ser vad som föreslås. Kundens besked registreras med utfall, kanal (telefon/på plats/e-post/SMS/delningslänk) och motivering vid avböjt. Åtgärdsknappen är låst tills beskedet finns och förblir låst vid avböjt; kvalitetsgrinden flaggar hårt om arbete utförts trots avböjt förslag. Publikt godkännande direkt i delningslänken är en medveten avgränsning. |
| Åtgärd och kvalitetskontroll | ✅ Arbetsflödets sista led: åtgärden dokumenteras (vad som gjordes + delar) eller motiveras varför den uteblev (kunden avböjde, väntar på reservdel …). Har en åtgärd utförts krävs **kvalitetskontroll** — symptomet borta / kvarstår / delvis / kunde inte verifieras, med beskrivning av hur det verifierades under samma förhållanden som symptomet reproducerades. Kvarstående symptom flaggas i grinden i stället för att döljas. Avslutsknappen är spärrad tills hela kedjan symptomverifiering → felorsak → åtgärd → kvalitetskontroll är komplett; rapporten har ett eget avsnitt ”Utförd åtgärd och verifiering”. |
| Ärendeidentitet | ✅ Fordonsobjektet som röd tråd: identiteten (AO-nummer, claim-/garantinummer, skadenummer, regnr, VIN, miltal, kund) registreras en gång — normalt via arbetsorderskanningen — och återanvänds i identitetsraden i arbetsytan (med ärendetypsval), låst panel överst i Live Share, slutrapportens första sida (Ärendeinformation + Fordonsinformation) och exporten. |
| Instrumentavläsning (visual-first) | ✅ Kameran som universellt gränssnitt: `📷 Instrument` i Dokumentera-panelen fotograferar multimetrar, diagnosskärmar, batteritestare m.m. — bildtolkningen identifierar instrumenttyp och extraherar värden/enheter/felkoder med konfidens per värde; teknikern bekräftar innan något loggas. Originalbilden loggas alltid tillsammans med de strukturerade mätvärdena — strukturerad data ersätter aldrig originalevidensen. Ingen integration mot diagnossystem krävs. |
diff --git a/docs/moduler/evidensmotor.md b/docs/moduler/evidensmotor.md
index 7c5e466..a4f4a3a 100644
--- a/docs/moduler/evidensmotor.md
+++ b/docs/moduler/evidensmotor.md
@@ -76,6 +76,7 @@ alla obligatoriska rader är gröna:
| Fordonshistorik kontrollerad eller motiverad | Obligatorisk |
| Ingående mätarställning dokumenterad | Obligatorisk |
| Kundens felbeskrivning verifierad | Rekommenderas |
+| Kundens besked på åtgärdsförslaget | Obligatoriskt när arbete utförts |
| Åtgärd dokumenterad eller motiverad | Obligatorisk vid avslut |
| Kvalitetskontroll genomförd | Obligatorisk vid avslut efter utförd åtgärd |
| Utgående mätarställning | Obligatorisk vid avslut |
@@ -161,6 +162,29 @@ Flottdatan är redan igång: **felorsaksstatistiken** i arbetsledarvyn
organisationen — vilka komponenter fallerar av slitage, vilka efter
tidigare reparationer, vilka tyder på konstruktionsproblem.
+## Kundgodkännande före arbete
+
+Verkstaden får aldrig utföra föreslaget arbete utan att kundens besked är
+registrerat och spårbart:
+
+- **Åtgärdsförslaget** skrivs i guiden (förifyllt ur felorsaksanalysens
+ rekommenderade åtgärd) med eventuell uppskattad kostnad, och **visas
+ för kunden i Live Share** — det är kunddelbart material.
+- **Kundens besked** registreras med utfall (godkänt/avböjt/delvis),
+ **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 och när.
+- **Knappen "Dokumentera utförd åtgärd" är låst** så länge ett förslag
+ saknar besked — och förblir låst vid avböjt besked. Vägen "Ingen
+ åtgärd utförd" är öppen och hänvisar till det registrerade beskedet.
+- Kvalitetsgrinden kräver registrerat besked när arbete utförts, och
+ flaggar konflikten *"Utfört arbete trots avböjt åtgärdsförslag"* som
+ ett hårt fel.
+
+Avgränsning: kunden godkänner i dagsläget genom kontakt med verkstaden —
+plattformen registrerar beskedet. Publikt godkännande direkt i
+delningslänken kräver en skrivande publik endpoint och hanteras separat.
+
## Åtgärdsfasen (Repair & Verification)
Loopen som symptomverifieringen öppnade sluts här — ett ärende kan inte
diff --git a/services/plattform/openapi.yaml b/services/plattform/openapi.yaml
index dec0d5b..75b3fa2 100644
--- a/services/plattform/openapi.yaml
+++ b/services/plattform/openapi.yaml
@@ -654,6 +654,8 @@ components:
- historik_kontrollerad
- matarstallning
- video
+ - atgardsforslag
+ - kundbeslut
- atgard_utford
- kvalitetskontroll
- reproducering
diff --git a/src/felsokning/DelatArendeVy.tsx b/src/felsokning/DelatArendeVy.tsx
index 9dc5242..4bcbf47 100644
--- a/src/felsokning/DelatArendeVy.tsx
+++ b/src/felsokning/DelatArendeVy.tsx
@@ -5,7 +5,7 @@
// bort även lokalt.
import type { Arende } from "./domain";
-import { handelseRubrik } from "./domain";
+import { KUNDBESLUT_LABEL, handelseRubrik } from "./domain";
import { arAvslutat, arendeidentitet, brief, foton, tidsfordelningsRader, videor } from "./projektioner";
import { metodikForArende } from "./store";
import { tidDatum, tidKlockslag } from "./format";
@@ -59,6 +59,10 @@ export function DelatArendeVy({
const avslutat = arAvslutat(arende);
const bilder = foton(arende);
const klipp = videor(arende);
+ // Åtgärdsförslaget är avsett för kunden — det visas alltid överst i
+ // delningsvyn, tillsammans med det besked som registrerats.
+ const forslag = arende.handelser.filter((p) => p.handelse.typ === "atgardsforslag");
+ const beslut = [...arende.handelser].reverse().find((p) => p.handelse.typ === "kundbeslut");
const matvarden = arende.handelser.filter((p) => p.handelse.typ === "matvarde");
const kundposter = redanFiltrerad
? arende.handelser
@@ -93,6 +97,33 @@ export function DelatArendeVy({
)}
+ {forslag.length > 0 && (
+
+ {forslag.map((p) => {
+ const h = p.handelse;
+ if (h.typ !== "atgardsforslag") return null;
+ return (
+