Sammanfattning och slutsats i rapport och Live Share; API dokumenterat
Sammanfattningen ligger först i både kundrapporten och Live Share. Mottagaren är oftast inte tekniker — det är kunden, en försäkringshandläggare eller en flottansvarig — och de ska få bilden på fem sekunder och sedan kunna gå djupare, inte tvärtom. I Live Share härleds den ur det NIVÅFILTRERADE underlaget. Det betyder att sammanfattningen aldrig kan avslöja något som delningsnivån döljer: filtret ligger före projektionen, inte efter. Slutsatsen visas som ett eget avsnitt före underlaget. En handläggare läser skälet först och kontrollerar det sedan — den ordningen är hela poängen med att fältet finns. Sju nya vägar dokumenterade i OpenAPI och låsta av paritetstestet: sammanfattning, protokollinläsning, statistik, integrationskategorier, prenumerationer, radering och mätdon. Ett API som inte är dokumenterat är inte ett API någon kan koppla in sig mot — och specen valideras maskinellt så dokumentationen inte kan glida från servern. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
This commit is contained in:
@@ -10,6 +10,7 @@ import { KUNDBESLUT_LABEL, handelseRubrik } from "./domain";
|
||||
import { arAvslutat, arendeidentitet, brief, foton, tidsfordelningsRader, videor } from "./projektioner";
|
||||
import { metodikForArende } from "./store";
|
||||
import { Bild, Klipp } from "./Bilagevisning";
|
||||
import { sammanfatta } from "../../../services/gemensam/sammanfattning.mjs";
|
||||
import { tidDatum, tidKlockslag } from "./format";
|
||||
import { FelsokningSkal, Panel, StorKnapp } from "./ui";
|
||||
import { IkonCheck, IkonKlocka, IkonUppdatera } from "./ikoner";
|
||||
@@ -157,6 +158,41 @@ export function DelatArendeVy({
|
||||
ärende vyn avser. Härledd ur det nivåfiltrerade underlaget. */}
|
||||
<IdentitetsPanel arende={arende} avslutat={avslutat} />
|
||||
|
||||
{/* ALVA-PROC-0030 · Sammanfattningen först. Mottagaren är oftast
|
||||
inte tekniker: kunden, en försäkringshandläggare, en
|
||||
flottansvarig. De ska få bilden på fem sekunder och sedan kunna
|
||||
gå djupare — inte tvärtom. Texten härleds ur det nivåfiltrerade
|
||||
underlaget, så den kan aldrig avslöja något som nivån döljer. */}
|
||||
<Panel rubrik="Sammanfattning">
|
||||
<p className="text-[15px] leading-[24px] text-[#1B1E22]">{sammanfatta(arende).text}</p>
|
||||
</Panel>
|
||||
|
||||
{/* ALVA-RULE-200 · Teknikerns varför. Den enda rad en
|
||||
försäkringsbedömare egentligen behöver, kunddelbar med avsikt. */}
|
||||
{(() => {
|
||||
const post = [...arende.handelser].reverse().find((p) => p.handelse.typ === "slutsats");
|
||||
if (!post || post.handelse.typ !== "slutsats") return null;
|
||||
const h = post.handelse;
|
||||
const rader: [string, string][] = [
|
||||
[h.orsakFastställd === false ? "Skäl till att orsaken inte fastställts" : "Motivering", h.motivering],
|
||||
["Uteslutna alternativ", h.uteslutet],
|
||||
...(h.atgardsval ? ([["Val av åtgärd", h.atgardsval]] as [string, string][]) : []),
|
||||
["Kvarstående osäkerhet", h.kvarstaende],
|
||||
];
|
||||
return (
|
||||
<Panel rubrik="Slutsats och motivering">
|
||||
<dl className="text-[14px] leading-[22px]">
|
||||
{rader.map(([etikett, text]) => (
|
||||
<div key={etikett} className="border-t border-[#D7DCE2] py-2 first:border-t-0">
|
||||
<dt className="text-[11px] font-semibold uppercase tracking-[0.12em] text-[#4D5662]">{etikett}</dt>
|
||||
<dd className="mt-1 text-[#1B1E22]">{text}</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
</Panel>
|
||||
);
|
||||
})()}
|
||||
|
||||
<p className="mb-4 rounded border border-[#C6C6C6] bg-[#F7F7F7] p-3 text-[12px] text-[#4A5560] print:hidden">
|
||||
{notis}
|
||||
</p>
|
||||
|
||||
@@ -101,6 +101,15 @@ describe("AI-orkestern", () => {
|
||||
["/api/arenden/{arendeId}/bilagor", "laddaUppVag"],
|
||||
["/api/bilagor/{bilagaId}", "bilagaVag"],
|
||||
["/api/delad/{delningskod}/bilagor/{bilagaId}", "delatBilaga"],
|
||||
// ALVA: nya vägar. Ett API som inte är dokumenterat är inte ett API
|
||||
// någon kan koppla in sig mot.
|
||||
["/api/arenden/{arendeId}/sammanfattning", "sammanfattningVag"],
|
||||
["/api/arenden/{arendeId}/protokoll", "protokollVag"],
|
||||
["/api/statistik/oversikt", "/api/statistik/oversikt"],
|
||||
["/api/integration/kategorier", "/api/integration/kategorier"],
|
||||
["/api/integration/prenumerationer", "/api/integration/prenumerationer"],
|
||||
["/api/radering", "/api/radering"],
|
||||
["/api/matdon", "/api/matdon"],
|
||||
];
|
||||
for (const [iSpec, iServer] of vagar) {
|
||||
expect(spec).toContain(`${iSpec}:`);
|
||||
|
||||
@@ -7,6 +7,7 @@ import { nastaSteg } from "@/felsokning/metodik";
|
||||
import { fasFor, klaraFaser } from "../../../../services/gemensam/faser.mjs";
|
||||
import { Fasrad } from "@/alva/komponenter";
|
||||
import { Slutsatspanel } from "@/felsokning/Slutsats";
|
||||
import { sammanfatta } from "../../../../services/gemensam/sammanfattning.mjs";
|
||||
import { arendebeteckning, fasDefinition } from "@/alva/system";
|
||||
import {
|
||||
arAvslutat,
|
||||
@@ -2317,6 +2318,33 @@ function RapportFlik({
|
||||
Delningslänken kräver att ärendet är synkat mot molnet (inloggad användare).
|
||||
</p>
|
||||
</Panel>
|
||||
{/* ALVA-PROC-0030 · Sammanfattningen först. Den som öppnar
|
||||
rapporten — kund, handläggare, nästa tekniker — ska få bilden
|
||||
på fem sekunder och sedan kunna gå djupare. Texten är härledd
|
||||
ur loggen, så den kan inte säga något som inte står där. */}
|
||||
<Panel rubrik="Sammanfattning">
|
||||
<p className="text-[15px] leading-[24px] text-[#1B1E22]">{sammanfatta(arende).text}</p>
|
||||
<p className="mt-2 font-mono text-[11px] text-[#4D5662]">ALVA-PROC-0030 · härledd ur händelseloggen</p>
|
||||
</Panel>
|
||||
|
||||
{/* ALVA-RULE-200 · Teknikerns varför. Placerad före underlaget:
|
||||
en handläggare läser skälet först och kontrollerar det sedan. */}
|
||||
{(() => {
|
||||
const s = [...arende.handelser].reverse().find((p) => p.handelse.typ === "slutsats");
|
||||
if (!s || s.handelse.typ !== "slutsats") return null;
|
||||
const h = s.handelse;
|
||||
return (
|
||||
<Panel rubrik="Slutsats och motivering">
|
||||
{identitetsRader([
|
||||
[h.orsakFastställd === false ? "Skäl till att orsaken inte fastställts" : "Motivering", h.motivering],
|
||||
["Uteslutna alternativ", h.uteslutet],
|
||||
["Val av åtgärd", h.atgardsval ?? "—"],
|
||||
["Kvarstående osäkerhet", h.kvarstaende],
|
||||
])}
|
||||
</Panel>
|
||||
);
|
||||
})()}
|
||||
|
||||
{/* Rapportens första sida: ärendeidentiteten — registrerad en gång,
|
||||
återanvänd här automatiskt. */}
|
||||
<Panel rubrik="Ärendeinformation">
|
||||
|
||||
Reference in New Issue
Block a user