diff --git a/docs/MVP.md b/docs/MVP.md index d2d485c..740856f 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. | +| Å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. | | Utskrift | ✅ Kundrapport och Live Share-vy skrivs ut svart på vitt; interaktiva element döljs automatiskt. Utskriften går genom ECM-kvalitetsgrinden. | diff --git a/docs/moduler/evidensmotor.md b/docs/moduler/evidensmotor.md index 5a7e009..7c5e466 100644 --- a/docs/moduler/evidensmotor.md +++ b/docs/moduler/evidensmotor.md @@ -76,6 +76,8 @@ alla obligatoriska rader är gröna: | Fordonshistorik kontrollerad eller motiverad | Obligatorisk | | Ingående mätarställning dokumenterad | Obligatorisk | | Kundens felbeskrivning verifierad | Rekommenderas | +| Å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 | | Metodikens kontroller: evidens eller dokumenterat undantag | Obligatorisk | | Foton för fotokrävande kontroller | Obligatorisk | @@ -159,6 +161,25 @@ Flottdatan är redan igång: **felorsaksstatistiken** i arbetsledarvyn organisationen — vilka komponenter fallerar av slitage, vilka efter tidigare reparationer, vilka tyder på konstruktionsproblem. +## Åtgärdsfasen (Repair & Verification) + +Loopen som symptomverifieringen öppnade sluts här — ett ärende kan inte +avslutas utan att det framgår vad som gjordes och om det hjälpte: + +1. **Åtgärd dokumenterad eller motiverad** — antingen vad som faktiskt + utfördes (med eventuella delar), eller varför ingen åtgärd gjordes + (kunden avböjde, väntar på reservdel, endast utredning beställd, + kostnadsförslag lämnat, åtgärd hos annan verkstad). +2. **Kvalitetskontroll** — obligatorisk när en åtgärd faktiskt utförts: + är symptomet borta, kvarstår det helt eller delvis, eller kunde det + inte verifieras? Utfallet dokumenteras med hur verifieringen gick + till (samma förhållanden som symptomet reproducerades under). + +Kvarstående symptom döljs aldrig: grinden skriver ut att ärendet inte +bör avslutas som åtgärdat. Avslutsknappen är spärrad tills kedjan +**symptomverifiering → felorsaksanalys → åtgärd → kvalitetskontroll** är +komplett, och rapporten redovisar den i egna avsnitt. + ## Ärendeidentitet (Case Identity & Vehicle Context) Fordonsobjektet är den röda tråden: identiteten registreras **en gång** diff --git a/services/plattform/openapi.yaml b/services/plattform/openapi.yaml index a3d6062..dec0d5b 100644 --- a/services/plattform/openapi.yaml +++ b/services/plattform/openapi.yaml @@ -654,6 +654,8 @@ components: - historik_kontrollerad - matarstallning - video + - atgard_utford + - kvalitetskontroll - reproducering - felorsak - export_skapad diff --git a/src/felsokning/__tests__/ecm.test.ts b/src/felsokning/__tests__/ecm.test.ts index e4f8496..4d1d770 100644 --- a/src/felsokning/__tests__/ecm.test.ts +++ b/src/felsokning/__tests__/ecm.test.ts @@ -363,3 +363,85 @@ describe("Videoevidens (E3) och signerat avslut", () => { expect(rad?.detalj).toContain("Erik"); }); }); + +describe("Åtgärdsfasen och kvalitetskontroll", () => { + it("avslut kräver dokumenterad åtgärd — och kvalitetskontroll när åtgärd utförts", async () => { + const { atgarder, kvalitetskontroll } = await import("../ecm"); + const bas: Handelse[] = [ + OBJEKT, + ...PREDIAG, + { typ: "reproducering", status: "ja", beskrivning: "Reproducerad vid provkörning." }, + { + typ: "felorsak", + avvikelse: "Framhjulen uppvisar obalans om 38 g på höger sida.", + orsaker: ["Yttre påverkan"], + underlag: ["Direkt observation"], + sakerhet: "hog", + atgard: "Balansera om hjulet.", + }, + { typ: "observation", text: "Obalans uppmätt" }, + ]; + + // Utan åtgärd: grinden kräver den vid avslut. + const utanAtgard = byggArende([...bas, { typ: "arende_avslutat", signatur: "Erik" }]); + const rad = kvalitetsgrind(utanAtgard, VIBRATION_METODIK).find((r) => r.id === "atgard"); + expect(rad?.kravs).toBe(true); + expect(rad?.ok).toBe(false); + + // Utförd åtgärd utan kvalitetskontroll: kontrollen blir obligatorisk. + const utanKk = byggArende([ + ...bas, + { typ: "atgard_utford", beskrivning: "Balanserade om höger framhjul.", utford: true }, + { typ: "arende_avslutat", signatur: "Erik" }, + ]); + expect(atgarder(utanKk)).toHaveLength(1); + const kkRad = kvalitetsgrind(utanKk, VIBRATION_METODIK).find((r) => r.id === "kvalitetskontroll"); + expect(kkRad?.kravs).toBe(true); + expect(kkRad?.ok).toBe(false); + + // Komplett kedja: åtgärd + verifierat borta. + const komplett = byggArende([ + ...bas, + { typ: "atgard_utford", beskrivning: "Balanserade om höger framhjul.", utford: true }, + { typ: "kvalitetskontroll", resultat: "symptomet_borta", beskrivning: "Ny provkörning utan vibration." }, + { typ: "arende_avslutat", signatur: "Erik" }, + ]); + expect(kvalitetskontroll(komplett)?.resultat).toBe("symptomet_borta"); + const rader = kvalitetsgrind(komplett, VIBRATION_METODIK); + expect(rader.find((r) => r.id === "atgard")?.ok).toBe(true); + expect(rader.find((r) => r.id === "kvalitetskontroll")?.detalj).toContain("verifierat borta"); + }); + + it("motiverat uteblivande godtas utan kvalitetskontroll", () => { + const ingenAtgard = byggArende([ + OBJEKT, + ...PREDIAG, + { typ: "atgard_utford", beskrivning: "Ingen åtgärd utförd", utford: false, motivering: "Kunden avböjde åtgärd" }, + { typ: "arende_avslutat", signatur: "Erik" }, + ]); + const rader = kvalitetsgrind(ingenAtgard, VIBRATION_METODIK); + expect(rader.find((r) => r.id === "atgard")?.ok).toBe(true); + expect(rader.find((r) => r.id === "atgard")?.detalj).toContain("orsaken är dokumenterad"); + // Inget att verifiera → kvalitetskontrollen är inte obligatorisk. + expect(rader.find((r) => r.id === "kvalitetskontroll")?.kravs).toBe(false); + }); + + it("kvarstående symptom flaggas i grinden i stället för att döljas", () => { + const kvarstar = byggArende([ + OBJEKT, + ...PREDIAG, + { typ: "atgard_utford", beskrivning: "Bytte hjullager höger fram.", utford: true }, + { typ: "kvalitetskontroll", resultat: "kvarstar", beskrivning: "Missljudet finns kvar vid 60 km/h." }, + ]); + const rad = kvalitetsgrind(kvarstar, VIBRATION_METODIK).find((r) => r.id === "kvalitetskontroll"); + expect(rad?.detalj).toContain("bör inte avslutas som åtgärdat"); + }); + + it("demoärendet bär hela kedjan symptom → orsak → åtgärd → verifiering", () => { + const demo = byggDemoArende(1); + const typer = demo.handelser.map((p) => p.handelse.typ); + for (const typ of ["reproducering", "felorsak", "atgard_utford", "kvalitetskontroll"]) { + expect(typer, typ).toContain(typ); + } + }); +}); diff --git a/src/felsokning/demo.ts b/src/felsokning/demo.ts index 8b5d993..77aeda9 100644 --- a/src/felsokning/demo.ts +++ b/src/felsokning/demo.ts @@ -130,6 +130,17 @@ export function byggDemoArende(nummer: number, anvandare = "Anna"): Arende { nastaSteg: "Balansera om höger framhjul och genomför ny provkörning i 80–100 km/h.", modell: "demo", }), + post(87, { + typ: "atgard_utford", + beskrivning: "Balanserade om höger framhjul och monterade ny balansvikt på fälgens insida.", + delar: "Balansvikter 40 g", + utford: true, + }), + post(88, { + typ: "kvalitetskontroll", + resultat: "symptomet_borta", + beskrivning: "Ny provkörning 80–110 km/h på samma vägsträcka — ingen vibration i ratten.", + }), post(90, { typ: "overlamning", fran: anvandare, till: "Johan" }), post(92, { typ: "kategori_byte", kategori: "administration" }, "Johan"), post(95, { typ: "kommentar", text: "Balanserat om höger framhjul, ny provkörning planerad." }, "Johan"), diff --git a/src/felsokning/domain.ts b/src/felsokning/domain.ts index cbe04af..d0e0bb0 100644 --- a/src/felsokning/domain.ts +++ b/src/felsokning/domain.ts @@ -29,6 +29,17 @@ export const TIDKATEGORI_LABEL: Record = { paus: "Paus", }; +// Kvalitetskontrollens utfall efter utförd åtgärd. +export const KVALITETSKONTROLL_LABEL: Record< + "symptomet_borta" | "kvarstar" | "delvis" | "ej_verifierbar", + string +> = { + symptomet_borta: "Symptomet är borta", + kvarstar: "Symptomet kvarstår", + delvis: "Symptomet delvis kvar", + ej_verifierbar: "Kunde inte verifieras", +}; + // Fordonsobjektet är den röda tråden genom hela ärendet: identiteten // registreras en gång och återanvänds i felsökning, Live Share, rapport // och export. Ärendereferenserna (AO/claim/skadenummer) hör till objektet @@ -101,6 +112,23 @@ export type Handelse = motivering?: string; ytterligareKontroller?: 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. + | { + typ: "atgard_utford"; + beskrivning: string; + delar?: string; + utford: boolean; + motivering?: string; + } + // Kvalitetskontroll efter åtgärd: är symptomet borta? Slutar loopen + // som symptomverifieringen (SVP) öppnade. + | { + typ: "kvalitetskontroll"; + resultat: "symptomet_borta" | "kvarstar" | "delvis" | "ej_verifierbar"; + beskrivning: string; + } | { typ: "export_skapad"; format: string; version: number } | { typ: "ai_svar"; @@ -194,6 +222,12 @@ 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 "atgard_utford": + return h.utford + ? `Åtgärd utförd: ${h.beskrivning}${h.delar ? ` (delar: ${h.delar})` : ""}` + : `Ingen åtgärd utförd — ${h.motivering ?? "orsak saknas"}`; + case "kvalitetskontroll": + return `Kvalitetskontroll: ${KVALITETSKONTROLL_LABEL[h.resultat]} — ${h.beskrivning}`; case "export_skapad": return `Export skapad: ${h.format}, version ${h.version}`; case "ai_svar": { diff --git a/src/felsokning/ecm.ts b/src/felsokning/ecm.ts index d4dc7d5..339da39 100644 --- a/src/felsokning/ecm.ts +++ b/src/felsokning/ecm.ts @@ -196,6 +196,31 @@ export function felorsaker(arende: Arende) { return arende.handelser.filter((p) => p.handelse.typ === "felorsak"); } +// -- Åtgärdsfasen (Repair & Verification) -- +// Loopen som symptomverifieringen öppnade sluts här: åtgärden +// dokumenteras (eller motiveras varför den uteblev) och kvalitets- +// kontrollen visar om symptomet faktiskt är borta. + +export const INGEN_ATGARD_ORSAKER = [ + "Kunden avböjde åtgärd", + "Väntar på reservdel", + "Åtgärd utförs av annan verkstad", + "Endast utredning beställd", + "Kostnadsförslag lämnat, inväntar besked", +]; + +export function atgarder(arende: Arende) { + return arende.handelser.filter((p) => p.handelse.typ === "atgard_utford"); +} + +export function kvalitetskontroll(arende: Arende) { + let senaste: { resultat: "symptomet_borta" | "kvarstar" | "delvis" | "ej_verifierbar"; beskrivning: string } | undefined; + for (const post of arende.handelser) { + if (post.handelse.typ === "kvalitetskontroll") senaste = post.handelse; + } + return senaste; +} + // -- Symptom Verification Protocol (SVP) -- // Kundens beskrivning → förtydligande (metodikens symptomfrågor) → // reproducering (eller dokumenterat ej reproducerbar). Rapporten skiljer @@ -526,6 +551,42 @@ export function kvalitetsgrind(arende: Arende, metodik: Metodik): GrindRad[] { : "Beskriv varför felet uppstått — eller ange varför orsaken inte kunnat fastställas.", }); + // Åtgärdsfasen: reparationen dokumenterad — eller motiverat varför + // ingen åtgärd utfördes. Obligatoriskt innan ärendet avslutas. + const atgardsposter = atgarder(arende); + const utfordAtgard = atgardsposter.some((p) => p.handelse.typ === "atgard_utford" && p.handelse.utford); + rader.push({ + id: "atgard", + rubrik: "Åtgärd dokumenterad eller motiverad", + ok: atgardsposter.length > 0, + kravs: avslutat, + detalj: + atgardsposter.length === 0 + ? "Dokumentera vad som gjordes — eller varför ingen åtgärd utfördes." + : utfordAtgard + ? undefined + : "Ingen åtgärd utförd; orsaken är dokumenterad.", + }); + + // Kvalitetskontroll: är symptomet borta? Krävs när en åtgärd faktiskt + // utförts — annars finns inget att verifiera. + const kk = kvalitetskontroll(arende); + rader.push({ + id: "kvalitetskontroll", + rubrik: "Kvalitetskontroll genomförd — symptomet verifierat", + ok: !!kk, + kravs: avslutat && utfordAtgard, + detalj: kk + ? kk.resultat === "symptomet_borta" + ? "Symptomet är verifierat borta efter åtgärd." + : kk.resultat === "ej_verifierbar" + ? `Kunde inte verifieras: ${kk.beskrivning}` + : `Symptomet kvarstår helt eller delvis — ärendet bör inte avslutas som åtgärdat.` + : utfordAtgard + ? "Verifiera att symptomet är borta efter åtgärden (provkörning/återtest)." + : "Ingen åtgärd utförd — inget att verifiera.", + }); + // Utgående mätarställning: obligatorisk först när ärendet avslutas. const matUt = handelser.some((h) => h.typ === "matarstallning" && h.lage === "utgaende"); rader.push({ diff --git a/src/pages/felsokning/ArendeSida.tsx b/src/pages/felsokning/ArendeSida.tsx index 0063ca4..ffde872 100644 --- a/src/pages/felsokning/ArendeSida.tsx +++ b/src/pages/felsokning/ArendeSida.tsx @@ -1,7 +1,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { Link, useParams } from "react-router-dom"; import type { Arende, Handelse, TidKategori, Tillforlitlighet } from "@/felsokning/domain"; -import { TIDKATEGORI_LABEL, TILLFORLITLIGHET_LABEL, handelseRubrik } from "@/felsokning/domain"; +import { KVALITETSKONTROLL_LABEL, TIDKATEGORI_LABEL, TILLFORLITLIGHET_LABEL, handelseRubrik } from "@/felsokning/domain"; import type { Metodik, NastaSteg } from "@/felsokning/metodik"; import { nastaSteg } from "@/felsokning/metodik"; import { @@ -44,14 +44,17 @@ import { ECM_VERSION, MARKOR_FELBESKRIVNING_VERIFIERAD, MARKOR_INGA_TIDIGA_OBSERVATIONER, + INGEN_ATGARD_ORSAKER, MARKOR_TIDIGA_OBSERVATIONER_KLARA, aktivtRegelpaket, + atgarder, arendetyp, felorsaker, granskaAvvikelse, grindGodkand, kvalitetsgrind, hamtaRegelpaket, + kvalitetskontroll, preDiagnostik, reproducering, reproduceringsText, @@ -702,6 +705,182 @@ function FelorsaksPanel({ arende, skicka }: { arende: Arende; skicka: (h: Handel ); } + +// Åtgärdsfasen: reparationen dokumenteras (eller motiveras varför den +// uteblev) och kvalitetskontrollen sluter loopen som symptom- +// verifieringen öppnade — är symptomet faktiskt borta? +function AtgardsPanel({ arende, skicka }: { arende: Arende; skicka: (h: Handelse) => void }) { + const poster = atgarder(arende); + const utford = poster.some((p) => p.handelse.typ === "atgard_utford" && p.handelse.utford); + const kk = kvalitetskontroll(arende); + const repro = reproducering(arende); + + const [lage, setLage] = useState<"" | "utford" | "ingen">(""); + const [beskrivning, setBeskrivning] = useState(""); + const [delar, setDelar] = useState(""); + const [orsak, setOrsak] = useState(""); + const [kkResultat, setKkResultat] = useState<"" | "symptomet_borta" | "kvarstar" | "delvis" | "ej_verifierbar">(""); + const [kkText, setKkText] = useState(""); + + return ( + + {poster.map((p) => { + const h = p.handelse; + if (h.typ !== "atgard_utford") return null; + return ( +

+ {h.utford ? ( + <> + Utförd åtgärd: {h.beskrivning} + {h.delar && · Delar: {h.delar}} + + ) : ( + Ingen åtgärd utförd — {h.motivering} + )} +

+ ); + })} + {kk && ( +

+ Kvalitetskontroll: {KVALITETSKONTROLL_LABEL[kk.resultat]} — {kk.beskrivning} +

+ )} + + {poster.length === 0 && !lage && ( +
+ setLage("utford")}> + Dokumentera utförd åtgärd + + setLage("ingen")}> + Ingen åtgärd utförd + +
+ )} + + {lage === "utford" && ( +
+ + +
+ setLage("")}> + Avbryt + + { + skicka({ typ: "atgard_utford", beskrivning: beskrivning.trim(), delar: delar.trim() || undefined, utford: true }); + setLage(""); + setBeskrivning(""); + setDelar(""); + }} + > + Spara åtgärd + +
+
+ )} + + {lage === "ingen" && ( +
+

+ Orsak till att ingen åtgärd utfördes (obligatorisk) +

+
+ {INGEN_ATGARD_ORSAKER.map((val) => ( + + ))} +
+ +
+ setLage("")}> + Avbryt + + { + skicka({ typ: "atgard_utford", beskrivning: "Ingen åtgärd utförd", utford: false, motivering: orsak.trim() }); + setLage(""); + setOrsak(""); + }} + > + Dokumentera + +
+
+ )} + + {utford && !kk && ( +
+

+ Kvalitetskontroll — är symptomet borta efter åtgärden? +

+ {repro?.status === "ja" && ( +

+ Symptomet reproducerades vid undersökningen — återskapa samma förhållanden för att verifiera. +

+ )} +
+ {(["symptomet_borta", "kvarstar", "delvis", "ej_verifierbar"] as const).map((val) => ( + + ))} +
+ {kkResultat && ( + <> + + { + skicka({ typ: "kvalitetskontroll", resultat: kkResultat, beskrivning: kkText.trim() }); + setKkResultat(""); + setKkText(""); + }} + > + Spara kvalitetskontroll + + + )} +
+ )} +
+ ); +} + // Navigationsträd (vänsterkolumnen): ärendets vyer plus metodikens steg // med status — som en mappstruktur i ett klassiskt verkstadssystem. function VyTrad({ @@ -895,8 +1074,16 @@ function GuideFlik({ const senasteAiSvar = [...arende.handelser].reverse().find((p) => p.handelse.typ === "ai_svar"); - // Avslut kräver SVP (reproducering dokumenterad) + felorsaksanalys. - const kanAvslutas = !!reproducering(arende) && felorsaker(arende).length > 0; + // Avslut kräver hela kedjan: symptomverifiering, felorsaksanalys, + // dokumenterad åtgärd (eller motiverat uteblivande) och — när en + // åtgärd faktiskt utförts — kvalitetskontroll av att symptomet är borta. + const atgardsposter = atgarder(arende); + const utfordAtgard = atgardsposter.some((p) => p.handelse.typ === "atgard_utford" && p.handelse.utford); + const kanAvslutas = + !!reproducering(arende) && + felorsaker(arende).length > 0 && + atgardsposter.length > 0 && + (!utfordAtgard || !!kvalitetskontroll(arende)); if (avslutat) { return ( @@ -936,7 +1123,7 @@ function GuideFlik({ {!kanAvslutas && (

- Avslut kräver dokumenterad symptomverifiering och felorsaksanalys — se panelerna nedan. + Avslut kräver symptomverifiering, felorsaksanalys, åtgärd och kvalitetskontroll — se panelerna nedan.

)} @@ -986,6 +1173,10 @@ function GuideFlik({ säkerhetsnivå. Obligatorisk för avslut. */} + {/* Åtgärdsfasen: vad som gjordes — och kvalitetskontrollen som + verifierar att symptomet faktiskt är borta. */} + {felorsaker(arende).length > 0 && } + {/* Utgående mätarställning: obligatorisk för kvalitetsgrinden när ärendet avslutas — erbjuds så fort metodiken är genomarbetad. */} {!arende.handelser.some((p) => p.handelse.typ === "matarstallning" && p.handelse.lage === "utgaende") && ( @@ -996,7 +1187,8 @@ function GuideFlik({ {!kanAvslutas && (

- Avslut kräver dokumenterad symptomverifiering och felorsaksanalys — annars är slutsatsen inte spårbar. + Avslut kräver hela kedjan: symptomverifiering, felorsaksanalys, dokumenterad åtgärd och — vid utförd åtgärd + — kvalitetskontroll av att symptomet är borta.

)}
@@ -1811,6 +2003,8 @@ function RapportFlik({ const typ = arendetyp(arende); const repro = reproducering(arende); const orsakerLista = felorsaker(arende); + const atgardsRader = atgarder(arende); + const kkRad = kvalitetskontroll(arende); let matIn: string | undefined; let matUt: string | undefined; for (const p of arende.handelser) { @@ -1967,6 +2161,30 @@ function RapportFlik({ ); })} + + {atgardsRader.length === 0 &&

Ingen åtgärd dokumenterad ännu.

} + {atgardsRader.map((p) => { + const h = p.handelse; + if (h.typ !== "atgard_utford") return null; + return ( +
+ {h.utford ? ( + identitetsRader([ + ["Utförd åtgärd", h.beskrivning], + ["Delar", h.delar], + ]) + ) : ( +

Ingen åtgärd utförd — {h.motivering}

+ )} +
+ ); + })} + {kkRad && + identitetsRader([ + ["Kvalitetskontroll", KVALITETSKONTROLL_LABEL[kkRad.resultat]], + ["Verifiering", kkRad.beskrivning], + ])} +

Total arbetstid: {b.totalArbetstid}

{fordelning.length > 0 && (