Revisionen: C-1, C-2, M-2, M-3, m-1 och m-2 åtgärdade
De fyra fynd som underminerade bevisvärdet sitter i samma kodväg och åtgärdas därför tillsammans. C-1 · Härkomsten sätts av servern. anvandare kommer ur den verifierade token och tidpunkt ur serverns klocka. Klientens tidsstämpel kastas inte — vid offline-arbete är den det enda som finns — utan bevaras som registrerad_tidpunkt bredvid mottagningstiden, så glappet blir synligt i stället för osynligt. C-2 · Kvalitetsgrinden flyttad till services/gemensam/grind.mjs och utvärderas nu på servern vid arende_avslutat. Ett avslut som inte passerar får 409 med de faktiska hindren. Metodikdatan flyttades till services/gemensam/metodiker.mjs och klientens metodiker.ts är en typad återexport, så det finns fortfarande exakt en sanning. M-2 · Högvoltsspärren är ett hinder. Ett nekande svar på behörighets- eller spänningsfrihetsfrågan stoppar metodiken i stället för att räknas som besvarad, och spärrar avslutet på servern. Ett obesvarat säkerhetskrav spärrar också — tystnad är inte ett ja. Reglerna ligger i data så nästa farliga metodik bara behöver en rad. M-3 · Händelser valideras mot schema före skrivning. Loggen är append-only, så en felaktig post kan aldrig rättas — kontrollen måste ske innan, efteråt är det för sent för alltid. Okänd typ avvisas. m-1 · Delningskoden använder förkastningsurval i stället för modulo. m-2 · Id-kollisioner räknas i stället för att passera tyst. 21 nya tester låser varje regel. Ett skräddarsytt test kräver dessutom att varje typ i händelseschemat är klassificerad i delningslistan — en ny typ kan alltså varken läcka eller tappas bort. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
This commit is contained in:
@@ -0,0 +1,196 @@
|
|||||||
|
// @vitest-environment node
|
||||||
|
// Revisionens kritiska fynd, låsta som test.
|
||||||
|
//
|
||||||
|
// De här reglerna är produktens hela värde: utan dem är loggen en
|
||||||
|
// signerad behållare för overifierade påståenden, och kvalitetsgrinden
|
||||||
|
// ett råd. Går något av testerna sönder har den garantin försvunnit —
|
||||||
|
// och det syns inte i gränssnittet förrän någon bestrider ett ärende.
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { granskaHändelse, tillPost } from "../../../../services/gemensam/handelser.mjs";
|
||||||
|
import { SPARRFRAGOR as SPARR_SERVER, grinda, grindaArendetyp } from "../../../../services/gemensam/grind.mjs";
|
||||||
|
import { ALLA_METODIKER } from "../../../../services/gemensam/metodiker.mjs";
|
||||||
|
import { SPARRFRAGOR } from "../metodik";
|
||||||
|
|
||||||
|
const GENERISK = ALLA_METODIKER.at(-1)!;
|
||||||
|
const ANSPRÅK = { sub: "u-1", namn: "Anna Tekniker", org: "o-1", roll: "tekniker" };
|
||||||
|
|
||||||
|
/** Bygger en logg som passerar allt utom det testet handlar om. */
|
||||||
|
function komplettLogg(extra: Record<string, unknown>[] = []) {
|
||||||
|
return [
|
||||||
|
{ typ: "objekt_identifierat", objekt: { identifierare: "ABC123" } },
|
||||||
|
{ typ: "historik_kontrollerad", kontrollerad: true },
|
||||||
|
{ typ: "matarstallning", lage: "ingaende", varde: "14 200" },
|
||||||
|
{ typ: "matarstallning", lage: "utgaende", varde: "14 205" },
|
||||||
|
{ typ: "reproducering", status: "ja", beskrivning: "Reproducerat vid 88 km/h." },
|
||||||
|
{ typ: "felorsak", avvikelse: "Obalans", orsaker: ["Normalt slitage"], underlag: ["Mätvärde"], sakerhet: "hog" },
|
||||||
|
{ typ: "atgard_utford", text: "Balanserade hjulen." },
|
||||||
|
{ typ: "kundbeslut", utfall: "godkant", kanal: "Telefon" },
|
||||||
|
{ typ: "kvalitetskontroll", utfall: "borta", beskrivning: "Provkört, symptomet borta." },
|
||||||
|
{ typ: "matvarde", beskrivning: "Lufttryck", varde: "2,4" },
|
||||||
|
{ typ: "foto", beskrivning: "Objektet" },
|
||||||
|
{ typ: "foto", beskrivning: "Typskylt" },
|
||||||
|
...GENERISK.steg.flatMap((s) =>
|
||||||
|
(s.kontroller ?? []).map((k) => ({
|
||||||
|
typ: "kontroll_utford",
|
||||||
|
stegId: s.id,
|
||||||
|
kontrollId: k.id,
|
||||||
|
text: k.text,
|
||||||
|
resultat: "Utförd och dokumenterad.",
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
...extra,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("C-1 · härkomsten sätts av servern, inte av anroparen", () => {
|
||||||
|
it("kastar klientens användarnamn och använder den verifierade identiteten", () => {
|
||||||
|
const { post } = tillPost(
|
||||||
|
{ id: "h1", anvandare: "Någon annan", tidpunkt: "2020-01-01T00:00:00.000Z", handelse: { typ: "observation", text: "x" } },
|
||||||
|
ANSPRÅK,
|
||||||
|
new Date("2026-08-05T10:00:00.000Z"),
|
||||||
|
);
|
||||||
|
expect(post.anvandare).toBe("Anna Tekniker");
|
||||||
|
expect(post.handelse.anvandarId).toBe("u-1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sätter tidpunkten från serverns klocka men bevarar klientens", () => {
|
||||||
|
const nu = new Date("2026-08-05T10:00:00.000Z");
|
||||||
|
const { post } = tillPost(
|
||||||
|
{ id: "h1", tidpunkt: "2020-01-01T00:00:00.000Z", handelse: { typ: "observation", text: "x" } },
|
||||||
|
ANSPRÅK,
|
||||||
|
nu,
|
||||||
|
);
|
||||||
|
// Backdatering är poängen med angreppet — serverns tid vinner.
|
||||||
|
expect(post.tidpunkt).toBe(nu.toISOString());
|
||||||
|
// Men offline-arbetets tid får inte försvinna; glappet ska synas.
|
||||||
|
expect(post.handelse.registrerad_tidpunkt).toBe("2020-01-01T00:00:00.000Z");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("M-3 · formen kontrolleras före skrivning", () => {
|
||||||
|
it("avvisar okända händelsetyper — append-only gör felet permanent", () => {
|
||||||
|
expect(granskaHändelse({ typ: "pahittad", text: "x" })).toMatch(/okänd händelsetyp/);
|
||||||
|
expect(granskaHändelse(null)).toBeTruthy();
|
||||||
|
expect(granskaHändelse({ typ: "observation" })).toMatch(/observation\.text/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("hypotesen kan aldrig anta hög tillförlitlighet", () => {
|
||||||
|
expect(granskaHändelse({ typ: "hypotes", text: "x", niva: "hog" })).toBeTruthy();
|
||||||
|
expect(granskaHändelse({ typ: "hypotes", text: "x", niva: "medel" })).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("avvisar id med otillåtna tecken", () => {
|
||||||
|
expect(tillPost({ id: "../etc/passwd", handelse: { typ: "observation", text: "x" } }, ANSPRÅK).fel).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("varje typ i schemat är känd av delningslistan — annars läcker eller tappas den", async () => {
|
||||||
|
const { HÄNDELSESCHEMA } = await import("../../../../services/gemensam/handelser.mjs");
|
||||||
|
const { DELBART_KUND, ENDAST_INTERNT } = await import("../../../../services/plattform/server.mjs");
|
||||||
|
for (const typ of Object.keys(HÄNDELSESCHEMA)) {
|
||||||
|
expect([...DELBART_KUND, ...ENDAST_INTERNT], typ).toContain(typ);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("C-2 · kvalitetsgrinden spärrar på servern", () => {
|
||||||
|
it("en tom logg kan inte avslutas", () => {
|
||||||
|
const hinder = grinda([], GENERISK).map((h) => h.id);
|
||||||
|
expect(hinder).toContain("objekt");
|
||||||
|
expect(hinder).toContain("reproducering");
|
||||||
|
expect(hinder).toContain("felorsak");
|
||||||
|
expect(hinder).toContain("evidens");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ett komplett ärende passerar", () => {
|
||||||
|
expect(grinda(komplettLogg(), GENERISK)).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
["objekt_identifierat", "objekt"],
|
||||||
|
["reproducering", "reproducering"],
|
||||||
|
["felorsak", "felorsak"],
|
||||||
|
["kvalitetskontroll", "kvalitetskontroll"],
|
||||||
|
])("saknad %s spärrar avslutet", (typ, id) => {
|
||||||
|
const logg = komplettLogg().filter((h) => h.typ !== typ);
|
||||||
|
expect(grinda(logg, GENERISK).map((h) => h.id)).toContain(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("arbete utfört trots avböjt förslag är ett hårt fel, inte en varning", () => {
|
||||||
|
const logg = komplettLogg().map((h) =>
|
||||||
|
h.typ === "kundbeslut" ? { ...h, utfall: "avbojt" } : h,
|
||||||
|
);
|
||||||
|
expect(grinda(logg, GENERISK).map((h) => h.id)).toContain("avbojt_men_utfort");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("nekad historikkontroll utan motivering spärrar; med motivering passerar", () => {
|
||||||
|
const utan = komplettLogg().map((h) =>
|
||||||
|
h.typ === "historik_kontrollerad" ? { typ: "historik_kontrollerad", kontrollerad: false } : h,
|
||||||
|
);
|
||||||
|
expect(grinda(utan, GENERISK).map((h) => h.id)).toContain("historik");
|
||||||
|
|
||||||
|
const med = komplettLogg().map((h) =>
|
||||||
|
h.typ === "historik_kontrollerad"
|
||||||
|
? { typ: "historik_kontrollerad", kontrollerad: false, kommentar: "Fordonet nytt hos oss." }
|
||||||
|
: h,
|
||||||
|
);
|
||||||
|
expect(grinda(med, GENERISK)).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("en kontroll utan resultat räknas inte som utförd", () => {
|
||||||
|
const logg = komplettLogg().map((h) =>
|
||||||
|
h.typ === "kontroll_utford" ? { ...h, resultat: "" } : h,
|
||||||
|
);
|
||||||
|
expect(grinda(logg, GENERISK).map((h) => h.id)).toContain("metodik_kontroller");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ett dokumenterat undantag ersätter evidens — men bara med orsak", () => {
|
||||||
|
const utan = komplettLogg().map((h) =>
|
||||||
|
h.typ === "kontroll_utford" ? { ...h, resultat: "", undantag: " " } : h,
|
||||||
|
);
|
||||||
|
expect(grinda(utan, GENERISK).map((h) => h.id)).toContain("metodik_kontroller");
|
||||||
|
|
||||||
|
const med = komplettLogg().map((h) =>
|
||||||
|
h.typ === "kontroll_utford" ? { ...h, resultat: "", undantag: "Lyft upptaget hela dagen." } : h,
|
||||||
|
);
|
||||||
|
expect(grinda(med, GENERISK)).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("M-2 · högvoltsspärren är ett hinder, inte en varning", () => {
|
||||||
|
const HOGVOLT = ALLA_METODIKER.find((m) => m.id === "hogvolt")!;
|
||||||
|
|
||||||
|
it("klientens och serverns spärrlistor är identiska", () => {
|
||||||
|
expect(Object.keys(SPARRFRAGOR).sort()).toEqual(Object.keys(SPARR_SERVER).sort());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ett nekande svar på behörighetsfrågan spärrar avslutet", () => {
|
||||||
|
const logg = [
|
||||||
|
...komplettLogg(),
|
||||||
|
{ typ: "fraga_besvarad", stegId: "sakerhet", frageId: "behorighet", fraga: "?", svar: "Nej" },
|
||||||
|
{ typ: "fraga_besvarad", stegId: "sakerhet", frageId: "avstangt", fraga: "?", svar: "Ja" },
|
||||||
|
];
|
||||||
|
expect(grinda(logg, HOGVOLT).map((h) => h.id)).toContain("sparr_behorighet");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ett obesvarat säkerhetskrav spärrar också — tystnad är inte ett ja", () => {
|
||||||
|
expect(grinda(komplettLogg(), HOGVOLT).map((h) => h.id)).toContain("sparr_behorighet");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("ärendetypens regelpaket", () => {
|
||||||
|
const paket = { arendetyper: { Garanti: { krav: [{ typ: "miltal" }, { typ: "historik" }] } } };
|
||||||
|
|
||||||
|
it("garantiärende kräver miltal och historik", () => {
|
||||||
|
const utan = [{ typ: "arendetyp_satt", arendetyp: "Garanti" }];
|
||||||
|
expect(grindaArendetyp(utan, paket).map((h) => h.id)).toEqual([
|
||||||
|
"arendetyp_miltal",
|
||||||
|
"arendetyp_historik",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("en okänd kravtyp spärrar i stället för att tolkas som uppfylld", () => {
|
||||||
|
const trasigt = { arendetyper: { Garanti: { krav: [{ typ: "hittepa" }] } } };
|
||||||
|
const logg = [{ typ: "arendetyp_satt", arendetyp: "Garanti" }];
|
||||||
|
expect(grindaArendetyp(logg, trasigt)[0].rubrik).toMatch(/Okänt krav/);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -146,21 +146,60 @@ export interface NastaSteg {
|
|||||||
fraga?: Fraga;
|
fraga?: Fraga;
|
||||||
kontroll?: Kontroll;
|
kontroll?: Kontroll;
|
||||||
klart: boolean;
|
klart: boolean;
|
||||||
|
/**
|
||||||
|
* Satt när metodiken är stoppad av en säkerhetsspärr. Metodiken går
|
||||||
|
* inte vidare förrän förutsättningen är uppfylld — svaret är inte ett
|
||||||
|
* varningsmeddelande utan ett hinder.
|
||||||
|
*/
|
||||||
|
sparr?: { orsak: string; atgard: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frågor som måste besvaras jakande innan arbetet får fortsätta.
|
||||||
|
*
|
||||||
|
* Revisionen (docs/QUALITY-AUDIT.md, M-2) fann att högvoltssteget gick
|
||||||
|
* att svara nej på och ändå fortsätta: `nastaSteg` gick vidare oavsett
|
||||||
|
* svar. En tekniker som ärligt uppgav sig sakna behörighet leddes alltså
|
||||||
|
* in i nästa steg av en procedur som kan döda.
|
||||||
|
*
|
||||||
|
* Regeln bor i data, inte i en if-sats i vyn, så att den gäller överallt
|
||||||
|
* där metodiken körs — och så att nästa farliga metodik bara behöver en
|
||||||
|
* rad här.
|
||||||
|
*/
|
||||||
|
export const SPARRFRAGOR: Record<string, { orsak: string; atgard: string }> = {
|
||||||
|
"hogvolt/sakerhet/behorighet": {
|
||||||
|
orsak: "Arbete på högvoltsystem kräver dokumenterad behörighet.",
|
||||||
|
atgard: "Lämna över ärendet till en behörig tekniker. Arbetet får inte påbörjas utan behörighet.",
|
||||||
|
},
|
||||||
|
"hogvolt/sakerhet/avstangt": {
|
||||||
|
orsak: "Fordonet är inte spänningslöst enligt tillverkarens rutin.",
|
||||||
|
atgard: "Gör fordonet spänningslöst enligt tillverkarens anvisning innan något ingrepp påbörjas.",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Nästa steg = första obesvarade frågan, därefter första ej utförda kontrollen,
|
// Nästa steg = första obesvarade frågan, därefter första ej utförda kontrollen,
|
||||||
// i metodikens ordning. Helt härlett ur händelseloggen.
|
// i metodikens ordning. Helt härlett ur händelseloggen.
|
||||||
export function nastaSteg(arende: Arende, metodik: Metodik): NastaSteg {
|
export function nastaSteg(arende: Arende, metodik: Metodik): NastaSteg {
|
||||||
const besvarade = new Set<string>();
|
const besvarade = new Set<string>();
|
||||||
|
const svar = new Map<string, string>();
|
||||||
const utforda = new Set<string>();
|
const utforda = new Set<string>();
|
||||||
for (const post of arende.handelser) {
|
for (const post of arende.handelser) {
|
||||||
const h = post.handelse;
|
const h = post.handelse;
|
||||||
if (h.typ === "fraga_besvarad") besvarade.add(`${h.stegId}/${h.frageId}`);
|
if (h.typ === "fraga_besvarad") {
|
||||||
|
besvarade.add(`${h.stegId}/${h.frageId}`);
|
||||||
|
svar.set(`${h.stegId}/${h.frageId}`, h.svar);
|
||||||
|
}
|
||||||
if (h.typ === "kontroll_utford") utforda.add(`${h.stegId}/${h.kontrollId}`);
|
if (h.typ === "kontroll_utford") utforda.add(`${h.stegId}/${h.kontrollId}`);
|
||||||
}
|
}
|
||||||
for (const steg of metodik.steg) {
|
for (const steg of metodik.steg) {
|
||||||
for (const fraga of steg.fragor ?? []) {
|
for (const fraga of steg.fragor ?? []) {
|
||||||
if (!besvarade.has(`${steg.id}/${fraga.id}`)) return { steg, fraga, klart: false };
|
if (!besvarade.has(`${steg.id}/${fraga.id}`)) return { steg, fraga, klart: false };
|
||||||
|
// Säkerhetsspärr: ett nekande svar stoppar metodiken här i stället
|
||||||
|
// för att räknas som besvarat och släppa fram nästa steg.
|
||||||
|
const sparr = SPARRFRAGOR[`${metodik.id}/${steg.id}/${fraga.id}`];
|
||||||
|
if (sparr && svar.get(`${steg.id}/${fraga.id}`) !== "Ja") {
|
||||||
|
return { steg, fraga, klart: false, sparr };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (const kontroll of steg.kontroller ?? []) {
|
for (const kontroll of steg.kontroller ?? []) {
|
||||||
if (!utforda.has(`${steg.id}/${kontroll.id}`)) return { steg, kontroll, klart: false };
|
if (!utforda.has(`${steg.id}/${kontroll.id}`)) return { steg, kontroll, klart: false };
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// Metodikbiblioteket.
|
// Metodikbiblioteket — typad återexport av den delade datan.
|
||||||
//
|
//
|
||||||
// En metodik är inte en checklista över vad som brukar vara fel — det
|
// Innehållet ligger i services/gemensam/metodiker.mjs eftersom servern
|
||||||
// vore att gissa åt teknikern. Den är en ordning för att utesluta:
|
// måste kunna utvärdera kvalitetsgrindens metodikrader. Grinden fanns
|
||||||
// symptomet verifieras först, sedan det billiga och synliga, sedan det
|
// tidigare bara i webbläsaren, vilket gjorde hela ECM till ett råd i
|
||||||
// som kräver mätning, sist det som kräver demontering.
|
// stället för en spärr (docs/QUALITY-AUDIT.md, C-2).
|
||||||
//
|
//
|
||||||
// Tre regler gäller alla metodiker här:
|
// Tre regler gäller alla metodiker där:
|
||||||
//
|
//
|
||||||
// 1. Varje kontroll har ett minimikrav (mätvärde, foto eller
|
// 1. Varje kontroll har ett minimikrav (mätvärde, foto eller
|
||||||
// observation). En kryssruta är inte evidens.
|
// observation). En kryssruta är inte evidens.
|
||||||
@@ -19,881 +19,24 @@
|
|||||||
// system systematiskt och låta GENERISK vara ett strukturellt komplett
|
// system systematiskt och låta GENERISK vara ett strukturellt komplett
|
||||||
// skyddsnät: den fungerar även för det ingen förutsett.
|
// skyddsnät: den fungerar även för det ingen förutsett.
|
||||||
|
|
||||||
|
import * as delade from "../../../services/gemensam/metodiker.mjs";
|
||||||
import type { Metodik } from "./metodik";
|
import type { Metodik } from "./metodik";
|
||||||
|
|
||||||
export const VIBRATION: Metodik = {
|
export const VIBRATION = delade.VIBRATION as Metodik;
|
||||||
id: "vibration",
|
export const BROMSAR = delade.BROMSAR as Metodik;
|
||||||
namn: "Vibration under körning",
|
export const STYRNING_FJADRING = delade.STYRNING_FJADRING as Metodik;
|
||||||
omrade: "Hjul och balans",
|
export const ELSYSTEM = delade.ELSYSTEM as Metodik;
|
||||||
nyckelord: ["vibration", "vibrer", "skak", "obalans", "ojämn gång", "rattvibration"],
|
export const START_LADDNING = delade.START_LADDNING as Metodik;
|
||||||
steg: [
|
export const MOTOR_DRIFT = delade.MOTOR_DRIFT as Metodik;
|
||||||
{
|
export const KYLSYSTEM = delade.KYLSYSTEM as Metodik;
|
||||||
id: "symptom",
|
export const DRIVLINA = delade.DRIVLINA as Metodik;
|
||||||
rubrik: "Verifiera symptom",
|
export const AVGAS_EMISSION = delade.AVGAS_EMISSION as Metodik;
|
||||||
fragor: [
|
export const KLIMAT = delade.KLIMAT as Metodik;
|
||||||
{ id: "hastighetsberoende", text: "Är vibrationen hastighetsberoende?", svarstyp: "janej" },
|
export const HOGVOLT = delade.HOGVOLT as Metodik;
|
||||||
{ id: "var", text: "Var känns vibrationen?", svarstyp: "val", val: ["I ratten", "I stolen", "I hela bilen"] },
|
export const DIAGNOS_NATVERK = delade.DIAGNOS_NATVERK as Metodik;
|
||||||
{
|
export const LACKAGE = delade.LACKAGE as Metodik;
|
||||||
id: "nar",
|
export const MISSLJUD = delade.MISSLJUD as Metodik;
|
||||||
text: "När uppstår vibrationen?",
|
export const ADAS = delade.ADAS as Metodik;
|
||||||
svarstyp: "val",
|
export const GENERISK = delade.GENERISK as Metodik;
|
||||||
val: ["Vid acceleration", "Vid jämn fart", "Vid inbromsning", "Alltid under körning"],
|
|
||||||
},
|
|
||||||
{ id: "intervall", text: "Försvinner den över eller under ett visst hastighetsintervall?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "visuell",
|
|
||||||
rubrik: "Visuell kontroll",
|
|
||||||
beskrivning: "Fotografera samtliga hjul. Skilj på observation och slutsats.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "foto_vf", text: "Fotografera vänster framhjul", krav: "foto" },
|
|
||||||
{ id: "foto_hf", text: "Fotografera höger framhjul", krav: "foto" },
|
|
||||||
{ id: "foto_vb", text: "Fotografera vänster bakhjul", krav: "foto" },
|
|
||||||
{ id: "foto_hb", text: "Fotografera höger bakhjul", krav: "foto" },
|
|
||||||
{ id: "dot", text: "Dokumentera DOT-/tillverkningsdatum", krav: "kommentar" },
|
|
||||||
{ id: "slitage", text: "Kontrollera däckslitage och slitagemönster", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "kontroller",
|
|
||||||
rubrik: "Mätningar",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "lufttryck", text: "Kontrollera lufttryck", krav: "matvarde" },
|
|
||||||
{ id: "hjulmoment", text: "Kontrollera hjulmoment", krav: "matvarde" },
|
|
||||||
{ id: "kast", text: "Kontrollera radial- och sidokast", krav: "matvarde" },
|
|
||||||
{ id: "balansering", text: "Kontrollera hjulbalansering", krav: "kommentar" },
|
|
||||||
{ id: "bussningar", text: "Kontrollera bussningar och leder", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "provkorning",
|
|
||||||
rubrik: "Provkörning",
|
|
||||||
beskrivning: "Verifiera under provkörning:",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "pk_hastighet", text: "Hastighet där vibration uppstår", krav: "kommentar" },
|
|
||||||
{ id: "pk_acc", text: "Förändring vid acceleration", krav: "kommentar" },
|
|
||||||
{ id: "pk_motorbroms", text: "Förändring vid motorbroms", krav: "kommentar" },
|
|
||||||
{ id: "pk_kurva", text: "Förändring vid kurvtagning", krav: "kommentar" },
|
|
||||||
{ id: "pk_var", text: "Om vibration känns i ratt eller kaross", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ELSYSTEM: Metodik = {
|
export const ALLA_METODIKER = delade.ALLA_METODIKER as Metodik[];
|
||||||
id: "elsystem",
|
|
||||||
namn: "Elsystem och strömförsörjning",
|
|
||||||
omrade: "El",
|
|
||||||
nyckelord: ["relä", "rela", "säkring", "elektr", "spänning", "volt", "lampa", "belysning", "ström", "kortslut", "kabel", "kabla", "kontaktdon", "jordfel"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{ id: "reproducerbart", text: "Går felet att reproducera?", svarstyp: "janej" },
|
|
||||||
{
|
|
||||||
id: "omfattning",
|
|
||||||
text: "Är funktionen helt död eller delvis fungerande?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Helt död", "Delvis fungerande", "Intermittent"],
|
|
||||||
},
|
|
||||||
{ id: "funktion", text: "Vilken funktion saknas eller felar?", svarstyp: "text" },
|
|
||||||
{ id: "forandring", text: "Har något åtgärdats eller förändrats nyligen?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "visuell",
|
|
||||||
rubrik: "Visuell kontroll",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "foto_komponent", text: "Fotografera komponenten och dess anslutningar", krav: "foto" },
|
|
||||||
{ id: "skador", text: "Kontrollera synliga skador, korrosion och lösa kontaktdon", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "matningar",
|
|
||||||
rubrik: "Mätningar",
|
|
||||||
beskrivning: "Mät under belastning. En spänning utan last säger nästan ingenting om en dålig förbindelse.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "batterispanning", text: "Mät batterispänning", krav: "matvarde" },
|
|
||||||
{ id: "sakringar", text: "Kontrollera berörda säkringar", krav: "kommentar" },
|
|
||||||
{ id: "matningsspanning", text: "Mät matningsspänning vid komponenten under last", krav: "matvarde" },
|
|
||||||
{ id: "jord", text: "Mät spänningsfall mot jord under last", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "rela",
|
|
||||||
rubrik: "Relä och styrsignal",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "rela_klick", text: "Kontrollera om reläet klickar vid aktivering", krav: "kommentar" },
|
|
||||||
{ id: "styrsignal", text: "Mät styrsignal till reläet", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "funktionstest",
|
|
||||||
rubrik: "Funktionstest",
|
|
||||||
kontroller: [{ id: "test", text: "Genomför funktionstest och dokumentera resultatet", krav: "kommentar" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const START_LADDNING: Metodik = {
|
|
||||||
id: "start_laddning",
|
|
||||||
namn: "Start- och laddningssystem",
|
|
||||||
omrade: "El",
|
|
||||||
nyckelord: ["startar inte", "startproblem", "startmotor", "generator", "laddning", "batteriet dör", "urladdat", "batterilampa", "drar inte runt", "klick vid start"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "beteende",
|
|
||||||
text: "Vad händer vid startförsök?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Ingenting alls", "Ett klick", "Drar runt långsamt", "Drar runt normalt men tänder inte", "Startar ibland"],
|
|
||||||
},
|
|
||||||
{ id: "kallt_varmt", text: "Uppträder felet kallt, varmt eller alltid?", svarstyp: "val", val: ["Kallt", "Varmt", "Alltid"] },
|
|
||||||
{ id: "stillestand", text: "Hur länge har fordonet stått mellan försöken?", svarstyp: "text" },
|
|
||||||
{ id: "laddat", text: "Har batteriet laddats eller bytts nyligen?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "batteri",
|
|
||||||
rubrik: "Batteriets kondition",
|
|
||||||
beskrivning: "Ett svagt batteri ger följdfel i hela fordonet. Uteslut det först.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "vilospanning", text: "Mät vilospänning efter minst en timmes vila", krav: "matvarde" },
|
|
||||||
{ id: "batteritest", text: "Belastningstest — fotografera testarens resultat", krav: "foto" },
|
|
||||||
{ id: "poler", text: "Kontrollera polskor och jordflätor", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "start",
|
|
||||||
rubrik: "Startsystem",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "startspanning", text: "Mät spänning vid startmotorn under startförsök", krav: "matvarde" },
|
|
||||||
{ id: "spanningsfall_plus", text: "Mät spänningsfall i plusledningen under start", krav: "matvarde" },
|
|
||||||
{ id: "spanningsfall_jord", text: "Mät spänningsfall i jordledningen under start", krav: "matvarde" },
|
|
||||||
{ id: "startsignal", text: "Kontrollera styrsignal till startrelä", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "laddning",
|
|
||||||
rubrik: "Laddningssystem",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "laddspanning", text: "Mät laddspänning vid tomgång och vid förhöjt varvtal", krav: "matvarde" },
|
|
||||||
{ id: "rippel", text: "Mät rippel från generatorn", krav: "matvarde" },
|
|
||||||
{ id: "rem", text: "Kontrollera drivrem och spänning", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "krypstrom",
|
|
||||||
rubrik: "Krypström",
|
|
||||||
beskrivning: "Endast relevant när batteriet laddar ur under stillestånd.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "vilostrom", text: "Mät viloström efter att fordonet somnat", krav: "matvarde" },
|
|
||||||
{ id: "sakringsdrag", text: "Lokalisera krets genom successiv säkringsurtagning", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MOTOR_DRIFT: Metodik = {
|
|
||||||
id: "motor_drift",
|
|
||||||
namn: "Motorgång och effekt",
|
|
||||||
omrade: "Motor",
|
|
||||||
nyckelord: ["ryck", "tappar kraft", "effektbrist", "misständ", "ojämn tomgång", "tomgång", "motorlampa", "kraftlös", "hack", "går på tre"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "nar",
|
|
||||||
text: "När uppträder felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Vid kallstart", "Vid tomgång", "Under belastning", "Vid visst varvtal", "Alltid"],
|
|
||||||
},
|
|
||||||
{ id: "varvtal", text: "Vid vilket varvtal eller vilken last?", svarstyp: "text" },
|
|
||||||
{ id: "varningslampa", text: "Lyser eller blinkar motorlampan?", svarstyp: "val", val: ["Lyser fast", "Blinkar", "Slocknad"] },
|
|
||||||
{ id: "brankslebyte", text: "Har bränsle tankats eller service utförts strax innan?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "felkoder",
|
|
||||||
rubrik: "Felkoder och mätdata",
|
|
||||||
beskrivning: "Läs innan något demonteras. En felkod pekar på en krets, inte på en trasig komponent.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "dtc", text: "Läs felkoder — fotografera diagnosskärmen", krav: "foto" },
|
|
||||||
{ id: "frysdata", text: "Dokumentera frysramsdata för koden", krav: "kommentar" },
|
|
||||||
{ id: "misstandning", text: "Läs misständningsräknare per cylinder", krav: "matvarde" },
|
|
||||||
{ id: "branslekorrigering", text: "Läs kort- och långtidsbränslekorrigering", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "mekanik",
|
|
||||||
rubrik: "Motorns grundkondition",
|
|
||||||
beskrivning: "Utan grundkondition är alla givarvärden svåra att tolka.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "kompression", text: "Mät kompression eller relativ kompression", krav: "matvarde" },
|
|
||||||
{ id: "vevhustryck", text: "Kontrollera vevhustryck", krav: "kommentar" },
|
|
||||||
{ id: "insugslackage", text: "Kontrollera insugssystemet för falskluft", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "tandning_bransle",
|
|
||||||
rubrik: "Tändning och bränsle",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "tandstift", text: "Kontrollera tändstift — fotografera samtliga", krav: "foto" },
|
|
||||||
{ id: "spolar", text: "Mät tändspolarnas resistans eller byt mellan cylindrar", krav: "matvarde" },
|
|
||||||
{ id: "bransletryck", text: "Mät bränsletryck under belastning", krav: "matvarde" },
|
|
||||||
{ id: "insprutare", text: "Kontrollera insprutarnas returmängd eller styrning", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "provkorning",
|
|
||||||
rubrik: "Provkörning med loggning",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "logg", text: "Logga mätdata under körning där felet uppträder", krav: "foto" },
|
|
||||||
{ id: "reproducerat", text: "Dokumentera under vilka förhållanden felet uppträdde", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const BROMSAR: Metodik = {
|
|
||||||
id: "bromsar",
|
|
||||||
namn: "Bromssystem",
|
|
||||||
omrade: "Chassi",
|
|
||||||
nyckelord: ["broms", "bromspedal", "skevhet", "gnisslar vid inbromsning", "abs", "bromsvätska", "handbroms", "drar snett vid inbromsning"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "karaktar",
|
|
||||||
text: "Hur yttrar sig felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Skevhet/pulsering", "Missljud", "Lång pedalväg", "Mjuk pedal", "Drar åt sidan", "Bromsen ligger på"],
|
|
||||||
},
|
|
||||||
{ id: "nar", text: "Vid vilken hastighet och bromskraft?", svarstyp: "text" },
|
|
||||||
{ id: "varningslampa", text: "Lyser broms- eller ABS-varning?", svarstyp: "janej" },
|
|
||||||
{ id: "senaste", text: "När byttes bromskomponenter senast?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "visuell",
|
|
||||||
rubrik: "Visuell kontroll",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "foto_belagg", text: "Fotografera belägg och skivor på samtliga hjul", krav: "foto" },
|
|
||||||
{ id: "belaggtjocklek", text: "Mät beläggtjocklek", krav: "matvarde" },
|
|
||||||
{ id: "skivtjocklek", text: "Mät skivtjocklek och jämför med minmått", krav: "matvarde" },
|
|
||||||
{ id: "lackage", text: "Kontrollera slangar, rör och ok för läckage", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "matningar",
|
|
||||||
rubrik: "Mätningar",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "skivkast", text: "Mät skivkast med mätklocka", krav: "matvarde" },
|
|
||||||
{ id: "tjockleksvariation", text: "Mät tjockleksvariation på skivan", krav: "matvarde" },
|
|
||||||
{ id: "vatska", text: "Mät bromsvätskans kokpunkt eller vatteninnehåll", krav: "matvarde" },
|
|
||||||
{ id: "okens_rorlighet", text: "Kontrollera okens och styrbultarnas rörlighet", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "system",
|
|
||||||
rubrik: "System och ABS",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "dtc", text: "Läs felkoder ur ABS-styrenheten", krav: "foto" },
|
|
||||||
{ id: "hjulgivare", text: "Kontrollera hjulhastighetsgivarnas signal", krav: "matvarde" },
|
|
||||||
{ id: "bromsprov", text: "Utför bromsprov i provbänk — fotografera protokollet", krav: "foto" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const STYRNING_FJADRING: Metodik = {
|
|
||||||
id: "styrning_fjadring",
|
|
||||||
namn: "Styrning och fjädring",
|
|
||||||
omrade: "Chassi",
|
|
||||||
nyckelord: ["drar åt", "styrning", "ratt", "glapp", "stötdämpar", "fjäder", "fjädr", "hjulinställning", "spårar", "gungar", "knäpper i kurva", "servostyrning"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "karaktar",
|
|
||||||
text: "Hur yttrar sig felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Drar åt sidan", "Glapp i ratten", "Missljud", "Dålig vägkänsla", "Ojämnt däckslitage", "Gungar/studsar"],
|
|
||||||
},
|
|
||||||
{ id: "underlag", text: "Uppträder det på visst underlag eller i viss kurva?", svarstyp: "text" },
|
|
||||||
{ id: "handelse", text: "Har fordonet kört på något eller varit i kontakt med trottoarkant?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "visuell",
|
|
||||||
rubrik: "Visuell kontroll",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "foto_slitage", text: "Fotografera däckens slitagemönster", krav: "foto" },
|
|
||||||
{ id: "dampare", text: "Kontrollera dämpare för läckage", krav: "kommentar" },
|
|
||||||
{ id: "damask", text: "Kontrollera damasker på styrleder och drivknutar", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "glapp",
|
|
||||||
rubrik: "Glappkontroll",
|
|
||||||
beskrivning: "Utförs med hjulet avlastat. Dokumentera var glappet finns, inte bara att det finns.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "hjullager", text: "Kontrollera hjullagerspel", krav: "kommentar" },
|
|
||||||
{ id: "styrleder", text: "Kontrollera styr- och bärleder", krav: "kommentar" },
|
|
||||||
{ id: "bussningar", text: "Kontrollera bussningar", krav: "kommentar" },
|
|
||||||
{ id: "kuggstang", text: "Kontrollera kuggstång och styrstagsändar", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "installning",
|
|
||||||
rubrik: "Hjulinställning",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "matning", text: "Mät hjulinställning — fotografera protokollet före justering", krav: "foto" },
|
|
||||||
{ id: "avvikelse", text: "Dokumentera avvikelser mot tillverkarens värden", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const KYLSYSTEM: Metodik = {
|
|
||||||
id: "kylsystem",
|
|
||||||
namn: "Kylsystem och överhettning",
|
|
||||||
omrade: "Motor",
|
|
||||||
nyckelord: ["överhett", "koka", "kylvätska", "temperatur", "termostat", "kylare", "vattenpump", "värme i kupén", "expansionskärl"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "nar",
|
|
||||||
text: "När stiger temperaturen?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Vid tomgång", "I låg fart", "I hög fart", "Vid belastning/backe", "Alltid"],
|
|
||||||
},
|
|
||||||
{ id: "kylvatskeforlust", text: "Förloras kylvätska? Hur mycket och hur ofta?", svarstyp: "text" },
|
|
||||||
{ id: "varme", text: "Fungerar kupévärmen?", svarstyp: "janej" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "visuell",
|
|
||||||
rubrik: "Visuell kontroll",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "niva", text: "Kontrollera kylvätskenivå kall — fotografera expansionskärlet", krav: "foto" },
|
|
||||||
{ id: "lackage", text: "Kontrollera synligt läckage vid slangar, kylare och pump", krav: "kommentar" },
|
|
||||||
{ id: "kylarpaket", text: "Kontrollera kylarpaketet för igensättning", krav: "foto" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "matningar",
|
|
||||||
rubrik: "Mätningar",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "trycktest", text: "Trycktesta kylsystemet", krav: "matvarde" },
|
|
||||||
{ id: "lock", text: "Trycktesta expansionskärlets lock", krav: "matvarde" },
|
|
||||||
{ id: "temperatur", text: "Mät temperatur in och ut ur kylaren med IR-termometer", krav: "matvarde" },
|
|
||||||
{ id: "flakt", text: "Kontrollera att kylfläkten startar vid rätt temperatur", krav: "kommentar" },
|
|
||||||
{ id: "givare", text: "Jämför styrenhetens temperaturvärde med uppmätt", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "packning",
|
|
||||||
rubrik: "Topplockspackning",
|
|
||||||
beskrivning: "Görs när kylvätska förloras utan yttre läckage.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "avgastest", text: "Avgastest i kylvätskan (CO2-test)", krav: "foto" },
|
|
||||||
{ id: "kompression_kyl", text: "Kontrollera trycksättning av kylsystemet vid motorgång", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const DRIVLINA: Metodik = {
|
|
||||||
id: "drivlina",
|
|
||||||
namn: "Växellåda och drivlina",
|
|
||||||
omrade: "Drivlina",
|
|
||||||
nyckelord: ["växellåda", "växlar", "koppling", "automatlåda", "rycker vid växling", "slir", "drivknut", "kardan", "differential", "kärvar i växeln"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "karaktar",
|
|
||||||
text: "Hur yttrar sig felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Slirar", "Rycker vid växling", "Går inte i växel", "Missljud", "Vibration vid acceleration", "Läckage"],
|
|
||||||
},
|
|
||||||
{ id: "vaxel", text: "Vilken växel eller vilket varvtal?", svarstyp: "text" },
|
|
||||||
{ id: "kall_varm", text: "Kall eller varm låda?", svarstyp: "val", val: ["Kall", "Varm", "Ingen skillnad"] },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "visuell",
|
|
||||||
rubrik: "Visuell kontroll",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "olja", text: "Kontrollera oljenivå och oljans skick — fotografera", krav: "foto" },
|
|
||||||
{ id: "lackage", text: "Kontrollera läckage vid tätningar och sump", krav: "kommentar" },
|
|
||||||
{ id: "fasten", text: "Kontrollera växellådsfästen", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "matningar",
|
|
||||||
rubrik: "Mätningar och avläsning",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "dtc", text: "Läs felkoder ur växellådsstyrenheten", krav: "foto" },
|
|
||||||
{ id: "adaptioner", text: "Dokumentera adaptionsvärden och kopplingsslitage", krav: "matvarde" },
|
|
||||||
{ id: "oljetemp", text: "Mät oljetemperatur under provkörning", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "provkorning",
|
|
||||||
rubrik: "Provkörning",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "vaxlingspunkter", text: "Dokumentera växlingspunkter och beteende", krav: "kommentar" },
|
|
||||||
{ id: "belastning", text: "Provkör under belastning där felet uppträder", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AVGAS_EMISSION: Metodik = {
|
|
||||||
id: "avgas_emission",
|
|
||||||
namn: "Avgassystem och emissioner",
|
|
||||||
omrade: "Motor",
|
|
||||||
nyckelord: ["partikelfilt", "dpf", "adblue", "katalysator", "lambda", "avgas", "emission", "rökutveckling", "svart rök", "blå rök", "os", "egr", "regenerer", "utsläpp"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "karaktar",
|
|
||||||
text: "Hur yttrar sig felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Varningslampa", "Rök", "Effektbegränsning", "Lukt", "Underkänd besiktning"],
|
|
||||||
},
|
|
||||||
{ id: "rokfarg", text: "Om rök — vilken färg och när?", svarstyp: "text" },
|
|
||||||
{ id: "korprofil", text: "Beskriv fordonets körprofil (mest kort- eller långkörning)?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "avlasning",
|
|
||||||
rubrik: "Avläsning",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "dtc", text: "Läs felkoder — fotografera diagnosskärmen", krav: "foto" },
|
|
||||||
{ id: "sotmangd", text: "Läs beräknad och uppmätt sotmängd i partikelfiltret", krav: "matvarde" },
|
|
||||||
{ id: "regenerering", text: "Dokumentera antal och utfall av senaste regenereringar", krav: "kommentar" },
|
|
||||||
{ id: "lambda", text: "Läs lambdagivarnas signaler före och efter katalysator", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "matningar",
|
|
||||||
rubrik: "Mätningar",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "mottryck", text: "Mät avgasmottryck", krav: "matvarde" },
|
|
||||||
{ id: "differenstryck", text: "Mät differenstryck över partikelfiltret", krav: "matvarde" },
|
|
||||||
{ id: "adblue_niva", text: "Kontrollera AdBlue-nivå och kvalitet där sådant finns", krav: "matvarde" },
|
|
||||||
{ id: "egr", text: "Kontrollera EGR-ventilens funktion och läge", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "orsak",
|
|
||||||
rubrik: "Bakomliggande orsak",
|
|
||||||
beskrivning: "Ett igensatt filter är oftast en följd, inte orsaken. Dokumentera vad som skapade sotet.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "grundorsak", text: "Kontrollera insprutning, turbo och luftflöde", krav: "kommentar" },
|
|
||||||
{ id: "korstrackor", text: "Bedöm om körprofilen tillåter regenerering", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const KLIMAT: Metodik = {
|
|
||||||
id: "klimat",
|
|
||||||
namn: "Klimatanläggning",
|
|
||||||
omrade: "Komfort",
|
|
||||||
nyckelord: ["ac", "luftkonditionering", "klimatanläggning", "kyler inte", "kompressor", "köldmedi", "imma", "immig", "fläkt", "lukt i kupén", "värmepaket"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "karaktar",
|
|
||||||
text: "Hur yttrar sig felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Kyler inte alls", "Kyler dåligt", "Kyler ibland", "Missljud", "Lukt", "Imma på rutorna"],
|
|
||||||
},
|
|
||||||
{ id: "sidor", text: "Skiljer det mellan höger och vänster sida?", svarstyp: "janej" },
|
|
||||||
{ id: "service", text: "När utfördes AC-service senast?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "visuell",
|
|
||||||
rubrik: "Visuell kontroll",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "kondensor", text: "Fotografera kondensorn — kontrollera igensättning och skador", krav: "foto" },
|
|
||||||
{ id: "kupefilter", text: "Kontrollera kupéfiltret", krav: "foto" },
|
|
||||||
{ id: "kompressor_rem", text: "Kontrollera kompressorns drivning och magnetkoppling", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "matningar",
|
|
||||||
rubrik: "Mätningar",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "tryck", text: "Mät hög- och lågtryck vid känd omgivningstemperatur", krav: "matvarde" },
|
|
||||||
{ id: "utblastemp", text: "Mät utblåstemperatur vid mittre munstycke", krav: "matvarde" },
|
|
||||||
{ id: "mangd", text: "Väg upptagen köldmediemängd vid tömning", krav: "matvarde" },
|
|
||||||
{ id: "lackagesok", text: "Läcksök med spårgas eller UV", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "styrning",
|
|
||||||
rubrik: "Styrning",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "dtc", text: "Läs felkoder ur klimatstyrenheten", krav: "foto" },
|
|
||||||
{ id: "spjall", text: "Kontrollera spjällmotorernas rörelse", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const HOGVOLT: Metodik = {
|
|
||||||
id: "hogvolt",
|
|
||||||
namn: "Högvoltsystem — elbil och hybrid",
|
|
||||||
omrade: "Högvolt",
|
|
||||||
nyckelord: ["högvolt", "elbil", "hybrid", "traktionsbatteri", "hv", "laddning av bil", "räckvidd", "laddbox", "orange kabel", "sköldpadda"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "sakerhet",
|
|
||||||
rubrik: "Säkerhet — utförs först",
|
|
||||||
beskrivning:
|
|
||||||
"Högvoltsystem kan vara livsfarliga. Inget arbete på systemet påbörjas innan stegen nedan är dokumenterade. Kräver behörighet för arbete på högvoltsystem.",
|
|
||||||
fragor: [
|
|
||||||
{ id: "behorighet", text: "Har du behörighet för arbete på högvoltsystem?", svarstyp: "janej" },
|
|
||||||
{ id: "avstangt", text: "Är fordonet spänningslöst enligt tillverkarens rutin?", svarstyp: "janej" },
|
|
||||||
],
|
|
||||||
kontroller: [
|
|
||||||
{ id: "service_disconnect", text: "Dokumentera att servicebrytaren är urtagen och säkrad", krav: "foto" },
|
|
||||||
{ id: "vantetid", text: "Dokumentera väntetid enligt tillverkarens anvisning", krav: "kommentar" },
|
|
||||||
{ id: "spanningsfrihet", text: "Mät och dokumentera spänningsfrihet före ingrepp", krav: "matvarde" },
|
|
||||||
{ id: "skyddsutrustning", text: "Dokumentera använd skyddsutrustning och avspärrning", krav: "foto" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "karaktar",
|
|
||||||
text: "Hur yttrar sig felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Laddar inte", "Kortare räckvidd", "Effektbegränsning", "Varningsmeddelande", "Fordonet startar inte"],
|
|
||||||
},
|
|
||||||
{ id: "laddtyp", text: "Vid vilken laddning uppträder felet (AC, DC, vilken laddpunkt)?", svarstyp: "text" },
|
|
||||||
{ id: "temperatur", text: "Vid vilken omgivnings- och batteritemperatur?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "avlasning",
|
|
||||||
rubrik: "Avläsning",
|
|
||||||
beskrivning: "Utförs med diagnosverktyg — inga ingrepp i systemet krävs.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "dtc", text: "Läs felkoder ur samtliga högvoltstyrenheter", krav: "foto" },
|
|
||||||
{ id: "soh", text: "Läs batteriets hälsa (SOH) och laddnivå (SOC)", krav: "matvarde" },
|
|
||||||
{ id: "cellspanning", text: "Läs cellspänningar och dokumentera största avvikelse", krav: "matvarde" },
|
|
||||||
{ id: "isolationsvarde", text: "Läs systemets isolationsvärde", krav: "matvarde" },
|
|
||||||
{ id: "temperaturer", text: "Läs batteriets temperaturgivare", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "laddning",
|
|
||||||
rubrik: "Laddkedjan",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "laddkabel", text: "Kontrollera laddkabel och laddkontakt — fotografera stiften", krav: "foto" },
|
|
||||||
{ id: "laddlogg", text: "Läs laddhistorik och avbrottsorsaker", krav: "kommentar" },
|
|
||||||
{ id: "extern", text: "Testa mot annan laddpunkt för att utesluta yttre orsak", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const DIAGNOS_NATVERK: Metodik = {
|
|
||||||
id: "diagnos_natverk",
|
|
||||||
namn: "Felkoder och kommunikation",
|
|
||||||
omrade: "Diagnos",
|
|
||||||
nyckelord: ["felkod", "dtc", "can", "canbuss", "kommunikationsfel", "ingen kontakt", "styrenhet", "obd", "diagnos", "flera lampor"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "omfattning",
|
|
||||||
text: "Hur många system är berörda?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["En styrenhet", "Flera styrenheter", "Hela fordonet", "Endast diagnosverktyget"],
|
|
||||||
},
|
|
||||||
{ id: "nar", text: "Uppstod felet efter ingrepp, batteribyte eller uppdatering?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "grund",
|
|
||||||
rubrik: "Grundförutsättningar",
|
|
||||||
beskrivning: "Kommunikationsfel beror oftare på matning och jord än på styrenheten.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "batteri", text: "Mät batterispänning under avläsning", krav: "matvarde" },
|
|
||||||
{ id: "obd_matning", text: "Mät matning och jord i diagnosuttaget", krav: "matvarde" },
|
|
||||||
{ id: "sakringar", text: "Kontrollera säkringar till berörda styrenheter", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "buss",
|
|
||||||
rubrik: "Bussmätning",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "terminering", text: "Mät bussens termineringsresistans med systemet spänningslöst", krav: "matvarde" },
|
|
||||||
{ id: "bussignal", text: "Mät CAN-signalen med oscilloskop — fotografera kurvan", krav: "foto" },
|
|
||||||
{ id: "avdelning", text: "Dela av bussen för att lokalisera störande nod", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "koder",
|
|
||||||
rubrik: "Felkoder i sammanhang",
|
|
||||||
beskrivning: "En felkod pekar på en krets, inte på en trasig komponent. Läs alla system innan någon kod raderas.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "helavlasning", text: "Läs samtliga styrenheter — fotografera listan", krav: "foto" },
|
|
||||||
{ id: "frysdata", text: "Dokumentera frysramsdata innan radering", krav: "kommentar" },
|
|
||||||
{ id: "efter_radering", text: "Radera, provkör och dokumentera vilka koder som återkom", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const LACKAGE: Metodik = {
|
|
||||||
id: "lackage",
|
|
||||||
namn: "Läckage",
|
|
||||||
omrade: "Övrigt",
|
|
||||||
nyckelord: ["läck", "läckage", "oljefläck", "dropp", "vatten i bilen", "fukt", "blöt matta", "oljeförbrukning"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "vatska",
|
|
||||||
text: "Vilken vätska misstänks?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Motorolja", "Kylvätska", "Växellådsolja", "Bromsvätska", "Bränsle", "Vatten/kondens", "Okänt"],
|
|
||||||
},
|
|
||||||
{ id: "mangd", text: "Hur mycket och hur ofta?", svarstyp: "text" },
|
|
||||||
{ id: "plats", text: "Var på marken syns fläcken i förhållande till fordonet?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "visuell",
|
|
||||||
rubrik: "Lokalisering",
|
|
||||||
beskrivning: "Rengör först. Ett gammalt läckage döljer var det nya kommer ifrån.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "foto_fore", text: "Fotografera området före rengöring", krav: "foto" },
|
|
||||||
{ id: "rengoring", text: "Rengör området och dokumentera att det är torrt", krav: "foto" },
|
|
||||||
{ id: "provkorning", text: "Provkör eller låt gå och fotografera var vätskan uppträder", krav: "foto" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "metod",
|
|
||||||
rubrik: "Läcksökning",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "uv", text: "Läcksök med UV-spårämne där det är tillämpligt", krav: "kommentar" },
|
|
||||||
{ id: "trycktest", text: "Trycktesta systemet", krav: "matvarde" },
|
|
||||||
{ id: "niva", text: "Mät nivåförändring över tid", krav: "matvarde" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MISSLJUD: Metodik = {
|
|
||||||
id: "missljud",
|
|
||||||
namn: "Missljud",
|
|
||||||
omrade: "Övrigt",
|
|
||||||
nyckelord: ["missljud", "ljud", "knack", "gnissel", "gnissl", "vinande", "brumm", "skram", "väsande", "tjut"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
beskrivning: "Ett missljud som inte reproducerats går inte att åtgärda. Spela in det.",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "karaktar",
|
|
||||||
text: "Vilken karaktär har ljudet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Knack", "Gnissel", "Vinande", "Brummande", "Skrammel", "Väsande", "Tjut"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "nar",
|
|
||||||
text: "När hörs det?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Vid start", "Vid tomgång", "Under körning", "Vid inbromsning", "Vid kurvtagning", "Över ojämnheter"],
|
|
||||||
},
|
|
||||||
{ id: "beroende", text: "Följer ljudet varvtal eller hastighet?", svarstyp: "val", val: ["Varvtal", "Hastighet", "Ingetdera"] },
|
|
||||||
{ id: "temperatur", text: "Skillnad kallt mot varmt?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "inspelning",
|
|
||||||
rubrik: "Dokumentera ljudet",
|
|
||||||
beskrivning: "Video med ljud är evidens. En beskrivning i text är det inte.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "video", text: "Spela in ljudet med video under de förhållanden där det uppträder", krav: "foto" },
|
|
||||||
{ id: "forhallanden", text: "Dokumentera hastighet, varvtal och underlag vid inspelningen", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "lokalisering",
|
|
||||||
rubrik: "Lokalisering",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "stetoskop", text: "Lokalisera med stetoskop eller ljudsond", krav: "kommentar" },
|
|
||||||
{ id: "avlastning", text: "Kontrollera om ljudet ändras vid avlastning eller belastning", krav: "kommentar" },
|
|
||||||
{ id: "uteslutning", text: "Dokumentera vilka källor som uteslutits och hur", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ADAS: Metodik = {
|
|
||||||
id: "adas",
|
|
||||||
namn: "Förarassistans och kalibrering",
|
|
||||||
omrade: "Diagnos",
|
|
||||||
nyckelord: ["adas", "kamera", "radar", "filhållning", "adaptiv farthållare", "kalibrer", "vindruta", "parkeringssensor", "döda vinkeln", "nödbroms"],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{
|
|
||||||
id: "funktion",
|
|
||||||
text: "Vilken funktion felar?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Filhållning", "Adaptiv farthållare", "Automatisk nödbroms", "Döda vinkeln", "Parkeringshjälp", "Backkamera"],
|
|
||||||
},
|
|
||||||
{ id: "ingrepp", text: "Har vindruta, kaross eller fjädring åtgärdats nyligen?", svarstyp: "text" },
|
|
||||||
{ id: "forhallanden", text: "Uppträder felet i visst väder eller ljus?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "forutsattningar",
|
|
||||||
rubrik: "Förutsättningar för kalibrering",
|
|
||||||
beskrivning:
|
|
||||||
"En kalibrering på fel förutsättningar ger ett fel som ser åtgärdat ut. Dokumentera att kraven är uppfyllda innan den utförs.",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "dtc", text: "Läs felkoder ur berörda styrenheter", krav: "foto" },
|
|
||||||
{ id: "hjulinstallning", text: "Kontrollera hjulinställning — bakaxelns spårning påverkar kameran", krav: "matvarde" },
|
|
||||||
{ id: "dacktryck", text: "Kontrollera däcktryck och körhöjd", krav: "matvarde" },
|
|
||||||
{ id: "sikt", text: "Kontrollera kamerans och radarns siktfält för smuts eller skada", krav: "foto" },
|
|
||||||
{ id: "yta", text: "Dokumentera att kalibreringsytan uppfyller kraven på planhet och ljus", krav: "foto" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "kalibrering",
|
|
||||||
rubrik: "Kalibrering",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "utford", text: "Utför kalibrering enligt tillverkarens metod — fotografera resultatet", krav: "foto" },
|
|
||||||
{ id: "provkorning", text: "Provkör och verifiera funktionen under de förhållanden felet uppträdde", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const GENERISK: Metodik = {
|
|
||||||
id: "generisk",
|
|
||||||
namn: "Generell strukturerad felsökning",
|
|
||||||
omrade: "Övrigt",
|
|
||||||
nyckelord: [],
|
|
||||||
steg: [
|
|
||||||
{
|
|
||||||
id: "symptom",
|
|
||||||
rubrik: "Verifiera symptom",
|
|
||||||
fragor: [
|
|
||||||
{ id: "reproducerbart", text: "Går felet att reproducera?", svarstyp: "janej" },
|
|
||||||
{
|
|
||||||
id: "nar",
|
|
||||||
text: "När uppträder felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Alltid", "Ibland", "Endast under drift", "Endast vid start"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "var",
|
|
||||||
text: "Var upplevs felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Fram", "Bak", "Höger", "Vänster", "Motor/drivkälla", "Kupé/förarplats", "Okänt"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "hur",
|
|
||||||
text: "Hur upplevs felet?",
|
|
||||||
svarstyp: "val",
|
|
||||||
val: ["Skakar/vibrerar", "Missljud (knack/gnissel/vinande)", "Rycker", "Tappar kraft", "Stannar helt", "Annat"],
|
|
||||||
},
|
|
||||||
{ id: "forlopp", text: "Beskriv förloppet när felet uppstår", svarstyp: "text" },
|
|
||||||
{ id: "forandring", text: "Har något förändrats nyligen (service, reparation, miljö)?", svarstyp: "text" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "visuell",
|
|
||||||
rubrik: "Visuell kontroll",
|
|
||||||
kontroller: [
|
|
||||||
{ id: "foto_objekt", text: "Fotografera objektet och det berörda området", krav: "foto" },
|
|
||||||
{ id: "skador", text: "Kontrollera synliga skador, läckage eller lösa anslutningar", krav: "kommentar" },
|
|
||||||
{ id: "typskylt", text: "Dokumentera typskylt/märkning", krav: "foto" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "grundkontroller",
|
|
||||||
rubrik: "Grundkontroller",
|
|
||||||
kontroller: [
|
|
||||||
{
|
|
||||||
id: "matning",
|
|
||||||
text: "Utför grundläggande mätningar (spänning, tryck, temperatur — det som är relevant)",
|
|
||||||
krav: "matvarde",
|
|
||||||
},
|
|
||||||
{ id: "sakringar", text: "Kontrollera säkringar/skydd", krav: "kommentar" },
|
|
||||||
{ id: "anslutningar", text: "Kontrollera kontaktdon och anslutningar", krav: "kommentar" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "funktionstest",
|
|
||||||
rubrik: "Funktionstest",
|
|
||||||
kontroller: [{ id: "test", text: "Genomför funktionstest och dokumentera resultatet", krav: "kommentar" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ordningen styr bara hur de visas. Valet görs på nyckelord, inte på
|
|
||||||
// position — GENERISK ligger sist eftersom den är fallback.
|
|
||||||
export const ALLA_METODIKER: Metodik[] = [
|
|
||||||
VIBRATION,
|
|
||||||
BROMSAR,
|
|
||||||
STYRNING_FJADRING,
|
|
||||||
ELSYSTEM,
|
|
||||||
START_LADDNING,
|
|
||||||
MOTOR_DRIFT,
|
|
||||||
KYLSYSTEM,
|
|
||||||
DRIVLINA,
|
|
||||||
AVGAS_EMISSION,
|
|
||||||
KLIMAT,
|
|
||||||
HOGVOLT,
|
|
||||||
DIAGNOS_NATVERK,
|
|
||||||
LACKAGE,
|
|
||||||
MISSLJUD,
|
|
||||||
ADAS,
|
|
||||||
GENERISK,
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -1295,6 +1295,19 @@ function GuideFlik({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
) : steg.sparr ? (
|
||||||
|
// Säkerhetsspärr. Metodiken går inte vidare — svaret är ett
|
||||||
|
// hinder, inte en varning. Enda vägen framåt är att ändra
|
||||||
|
// förutsättningen, inte att klicka förbi.
|
||||||
|
<div className="border-2 border-[#B42318] bg-[#FEF3F2] p-4">
|
||||||
|
<p className="mb-2 text-[15px] font-semibold text-[#B42318]">Arbetet får inte fortsätta</p>
|
||||||
|
<p className="mb-2 text-[#333333]">{steg.sparr.orsak}</p>
|
||||||
|
<p className="mb-3 font-semibold text-[#333333]">{steg.sparr.atgard}</p>
|
||||||
|
<p className="text-[12px] text-[#666666]">
|
||||||
|
Svaret är dokumenterat i loggen. Metodiken öppnas när förutsättningen är uppfylld och frågan besvaras
|
||||||
|
jakande.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
) : steg.fraga ? (
|
) : steg.fraga ? (
|
||||||
<FrageKort key={`${steg.steg.id}/${steg.fraga.id}`} steg={steg} skicka={skicka} />
|
<FrageKort key={`${steg.steg.id}/${steg.fraga.id}`} steg={steg} skicka={skicka} />
|
||||||
) : steg.kontroll ? (
|
) : steg.kontroll ? (
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
// Kvalitetsgrinden på serversidan.
|
||||||
|
//
|
||||||
|
// Revisionen (docs/QUALITY-AUDIT.md, C-2) fann att grinden bara fanns i
|
||||||
|
// webbläsaren. Ett ärende kunde därmed avslutas utan evidens genom ett
|
||||||
|
// anrop till API:t, och rapporten presenterade det som komplett — trots
|
||||||
|
// att dokumentationen påstod att systemet aldrig kan skriva en slutsats
|
||||||
|
// ECM inte godkänt.
|
||||||
|
//
|
||||||
|
// Modulen utvärderar de obligatoriska raderna direkt mot händelseloggen.
|
||||||
|
// Klientens ecm.ts har fler rader (råd, rekommendationer, härledd
|
||||||
|
// evidensnivå per påstående) och fortsätter vara vägledningen i
|
||||||
|
// gränssnittet. Det som blockerar ett avslut bor här.
|
||||||
|
//
|
||||||
|
// Avsiktligt: reglerna är rena funktioner av (händelser, metodik). Ingen
|
||||||
|
// databasåtkomst, ingen tid, inget slumpmässigt — samma logg ger alltid
|
||||||
|
// samma utfall, vilket är vad som gör en spärr granskbar.
|
||||||
|
|
||||||
|
const UNDANTAG_MOTIVERAT = (h) => typeof h.undantag === "string" && h.undantag.trim().length > 0;
|
||||||
|
|
||||||
|
// Frågor som måste besvaras jakande för att arbetet ska få avslutas.
|
||||||
|
// Speglar SPARRFRAGOR i app/src/felsokning/metodik.ts; ett test jämför
|
||||||
|
// listorna så de inte kan glida isär.
|
||||||
|
export const SPARRFRAGOR = {
|
||||||
|
"hogvolt/sakerhet/behorighet": "Behörighet för högvoltsarbete bekräftad",
|
||||||
|
"hogvolt/sakerhet/avstangt": "Fordonet spänningslöst enligt tillverkarens rutin",
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Händelser av en viss typ. */
|
||||||
|
const av = (handelser, typ) => handelser.filter((h) => h.typ === typ);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utvärderar avslutsgrinden.
|
||||||
|
*
|
||||||
|
* @returns lista med hinder; tom lista betyder att ärendet får avslutas.
|
||||||
|
*/
|
||||||
|
export function grinda(handelser, metodik) {
|
||||||
|
const hinder = [];
|
||||||
|
const krav = (id, rubrik, ok, detalj) => {
|
||||||
|
if (!ok) hinder.push(detalj ? { id, rubrik, detalj } : { id, rubrik });
|
||||||
|
};
|
||||||
|
|
||||||
|
krav("objekt", "Fordons-/objektidentifiering verifierad", handelser.some((h) => h.typ === "objekt_identifierat"));
|
||||||
|
|
||||||
|
// Historiken får besvaras nekande, men då krävs en motivering — annars
|
||||||
|
// vore "Nej" ett sätt att hoppa över kontrollen utan att det syns.
|
||||||
|
const historik = av(handelser, "historik_kontrollerad").at(-1);
|
||||||
|
krav(
|
||||||
|
"historik",
|
||||||
|
"Fordonshistorik kontrollerad eller motiverad",
|
||||||
|
Boolean(historik) && (historik.kontrollerad || (historik.kommentar ?? "").trim().length > 0),
|
||||||
|
historik ? "Nekad historikkontroll kräver en motivering." : "Ingen historikkontroll dokumenterad.",
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const [lage, rubrik] of [
|
||||||
|
["ingaende", "Ingående mätarställning dokumenterad"],
|
||||||
|
["utgaende", "Utgående mätarställning dokumenterad"],
|
||||||
|
]) {
|
||||||
|
krav(`matarstallning_${lage}`, rubrik, av(handelser, "matarstallning").some((h) => h.lage === lage));
|
||||||
|
}
|
||||||
|
|
||||||
|
krav(
|
||||||
|
"reproducering",
|
||||||
|
"Symptomverifiering: reproducerat eller dokumenterat ej reproducerbart",
|
||||||
|
handelser.some((h) => h.typ === "reproducering"),
|
||||||
|
);
|
||||||
|
|
||||||
|
krav("felorsak", "Felorsaksanalys dokumenterad", handelser.some((h) => h.typ === "felorsak"));
|
||||||
|
|
||||||
|
// Åtgärdskedjan. En utebliven åtgärd är ett giltigt utfall — men bara
|
||||||
|
// när skälet står i loggen.
|
||||||
|
const atgarder = av(handelser, "atgard_utford");
|
||||||
|
const utfordArbete = atgarder.some((h) => (h.text ?? "").trim().length > 0);
|
||||||
|
krav(
|
||||||
|
"atgard",
|
||||||
|
"Åtgärd dokumenterad eller motiverad",
|
||||||
|
atgarder.length > 0,
|
||||||
|
"Varken utförd åtgärd eller skäl till att den uteblev finns dokumenterat.",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (utfordArbete) {
|
||||||
|
const beslut = av(handelser, "kundbeslut");
|
||||||
|
krav("kundbeslut", "Kundens besked på åtgärdsförslaget registrerat", beslut.length > 0);
|
||||||
|
|
||||||
|
// Hårt fel, inte en varning: arbete utfört trots att kunden avböjt.
|
||||||
|
krav(
|
||||||
|
"avbojt_men_utfort",
|
||||||
|
"Utfört arbete trots avböjt åtgärdsförslag",
|
||||||
|
!beslut.some((h) => h.utfall === "avbojt"),
|
||||||
|
"Kunden avböjde förslaget men arbete har dokumenterats som utfört.",
|
||||||
|
);
|
||||||
|
|
||||||
|
krav(
|
||||||
|
"kvalitetskontroll",
|
||||||
|
"Kvalitetskontroll genomförd — symptomet verifierat",
|
||||||
|
handelser.some((h) => h.typ === "kvalitetskontroll"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metodikens kontroller: varje kontroll ska bära evidens eller ett
|
||||||
|
// dokumenterat undantag. Det är den rad som gör metodiken bindande.
|
||||||
|
const utforda = new Map();
|
||||||
|
for (const h of av(handelser, "kontroll_utford")) utforda.set(`${h.stegId}/${h.kontrollId}`, h);
|
||||||
|
|
||||||
|
const saknade = [];
|
||||||
|
const utanFoto = [];
|
||||||
|
const foton = av(handelser, "foto").length;
|
||||||
|
for (const steg of metodik?.steg ?? []) {
|
||||||
|
for (const kontroll of steg.kontroller ?? []) {
|
||||||
|
const h = utforda.get(`${steg.id}/${kontroll.id}`);
|
||||||
|
if (!h) {
|
||||||
|
saknade.push(`${steg.rubrik} · ${kontroll.text}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (UNDANTAG_MOTIVERAT(h)) continue;
|
||||||
|
if (!(h.resultat ?? "").trim()) saknade.push(`${steg.rubrik} · ${kontroll.text} (utan resultat)`);
|
||||||
|
else if (kontroll.krav === "foto") utanFoto.push(kontroll.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
krav(
|
||||||
|
"metodik_kontroller",
|
||||||
|
"Metodikens kontroller: evidens eller dokumenterat undantag",
|
||||||
|
saknade.length === 0,
|
||||||
|
saknade.slice(0, 5).join(" · "),
|
||||||
|
);
|
||||||
|
krav("foton", "Foton finns för fotokrävande kontroller", utanFoto.length === 0 || foton >= utanFoto.length);
|
||||||
|
|
||||||
|
// Säkerhetsspärrar. Ett nekande svar på en spärrfråga får aldrig
|
||||||
|
// passera som "besvarad" — se SPARRFRAGOR i klientens metodik.ts.
|
||||||
|
// Klientens spärr är vägledning; den här är hindret (QUALITET M-2).
|
||||||
|
for (const [nyckel, text] of Object.entries(SPARRFRAGOR)) {
|
||||||
|
const [metodikId, stegId, frageId] = nyckel.split("/");
|
||||||
|
if (metodik?.id !== metodikId) continue;
|
||||||
|
const svaret = av(handelser, "fraga_besvarad").findLast(
|
||||||
|
(h) => h.stegId === stegId && h.frageId === frageId,
|
||||||
|
);
|
||||||
|
krav(`sparr_${frageId}`, text, svaret?.svar === "Ja", "Säkerhetskravet är inte uppfyllt.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evidensnivån måste överstiga E0 — annars avslutas ett ärende utan
|
||||||
|
// att någonting alls har dokumenterats.
|
||||||
|
krav(
|
||||||
|
"evidens",
|
||||||
|
"Evidensnivå över E0",
|
||||||
|
handelser.some((h) => ["foto", "video", "matvarde", "observation", "kontroll_utford"].includes(h.typ)),
|
||||||
|
"Ingen evidens av något slag finns i loggen.",
|
||||||
|
);
|
||||||
|
|
||||||
|
return hinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra krav som följer av ärendetypen. Reglerna kommer från regelpaketet
|
||||||
|
* (ECM Knowledge Library) och är alltså data, inte kod.
|
||||||
|
*/
|
||||||
|
export function grindaArendetyp(handelser, regelpaket) {
|
||||||
|
const typ = av(handelser, "arendetyp_satt").at(-1)?.arendetyp;
|
||||||
|
const regler = regelpaket?.arendetyper?.[typ]?.krav ?? [];
|
||||||
|
const hinder = [];
|
||||||
|
|
||||||
|
const uppfyllt = {
|
||||||
|
miltal: () => av(handelser, "matarstallning").length > 0,
|
||||||
|
historik: () => av(handelser, "historik_kontrollerad").some((h) => h.kontrollerad),
|
||||||
|
foto: () => av(handelser, "foto").length > 0,
|
||||||
|
claim: () => harReferens(handelser, ["ao_claim", "claim"]),
|
||||||
|
skadenummer: () => harReferens(handelser, ["ao_skadenummer", "skadenummer"]),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const regel of regler) {
|
||||||
|
const kontroll = uppfyllt[regel.typ ?? regel];
|
||||||
|
// En okänd kravtyp får aldrig tolkas som uppfylld. Ett regelpaket som
|
||||||
|
// inte går att utvärdera ska stoppa avslutet, inte släppa igenom det.
|
||||||
|
if (!kontroll) {
|
||||||
|
hinder.push({ id: `arendetyp_${regel.typ ?? regel}`, rubrik: `Okänt krav i regelpaketet: ${regel.typ ?? regel}` });
|
||||||
|
} else if (!kontroll()) {
|
||||||
|
hinder.push({ id: `arendetyp_${regel.typ ?? regel}`, rubrik: regel.rubrik ?? `Krav för ärendetypen: ${regel.typ ?? regel}` });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
function harReferens(handelser, nycklar) {
|
||||||
|
for (const h of av(handelser, "arbetsorder_skannad")) {
|
||||||
|
for (const f of h.falt ?? []) {
|
||||||
|
if (nycklar.includes(f.id) && String(f.varde ?? "").trim()) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
// Händelsevalidering vid API-gränsen.
|
||||||
|
//
|
||||||
|
// Bakgrund: revisionen (docs/QUALITY-AUDIT.md, C-1 och M-3) fann att servern
|
||||||
|
// bara kontrollerade att `anvandare` var *en sträng* och `tidpunkt` *sanningsvärd*
|
||||||
|
// — inte att de var sanna — och att `handelse` togs emot som godtycklig JSON.
|
||||||
|
//
|
||||||
|
// Två skilda problem med samma botemedel:
|
||||||
|
//
|
||||||
|
// Härkomst Vem som utförde arbetet och när är det som gör loggen till en
|
||||||
|
// beviskedja. Sätts de av anroparen är loggen en signerad behållare
|
||||||
|
// för overifierade påståenden. Båda härleds nu ur den verifierade
|
||||||
|
// token respektive serverns klocka.
|
||||||
|
//
|
||||||
|
// Form Loggen är append-only. En felaktig post kan aldrig rättas, bara
|
||||||
|
// kommenteras. Därför måste formen kontrolleras *innan* skrivning —
|
||||||
|
// efteråt är det för sent för alltid.
|
||||||
|
//
|
||||||
|
// Klientens klocka kastas inte bort. Vid offline-arbete är den det enda som
|
||||||
|
// finns, så den bevaras som `registrerad_tidpunkt` bredvid serverns
|
||||||
|
// mottagningstid. Glappet blir synligt i stället för osynligt.
|
||||||
|
|
||||||
|
/** Fält som aldrig får komma från klienten. */
|
||||||
|
export const SERVERÄGDA_FÄLT = ["anvandare", "tidpunkt"];
|
||||||
|
|
||||||
|
// Varje händelsetyp med sina obligatoriska fält. Listan är avsiktligt
|
||||||
|
// fullständig: en typ som inte står här avvisas, eftersom en okänd typ i en
|
||||||
|
// append-only-logg är permanent skräp.
|
||||||
|
export const HÄNDELSESCHEMA = {
|
||||||
|
objekt_identifierat: { objekt: "objekt" },
|
||||||
|
arbetsorder_skannad: { falt: "lista" },
|
||||||
|
felbeskrivning: { text: "text" },
|
||||||
|
arendetyp_satt: { arendetyp: "text" },
|
||||||
|
fraga_besvarad: { stegId: "text", frageId: "text", fraga: "text", svar: "text" },
|
||||||
|
kontroll_utford: { stegId: "text", kontrollId: "text", text: "text" },
|
||||||
|
observation: { text: "text" },
|
||||||
|
matvarde: { beskrivning: "text", varde: "text" },
|
||||||
|
hypotes: { text: "text", niva: ["medel", "lag"] },
|
||||||
|
foto: { beskrivning: "text" },
|
||||||
|
video: { beskrivning: "text" },
|
||||||
|
matarstallning: { lage: ["ingaende", "utgaende"], varde: "text" },
|
||||||
|
historik_kontrollerad: { kontrollerad: "boolean" },
|
||||||
|
reproducering: { status: ["ja", "delvis", "nej"], beskrivning: "text" },
|
||||||
|
felorsak: { avvikelse: "text", orsaker: "lista", underlag: "lista", sakerhet: ["hog", "medel", "lag"] },
|
||||||
|
atgardsforslag: { text: "text" },
|
||||||
|
kundbeslut: { utfall: ["godkant", "avbojt", "delvis"], kanal: "text" },
|
||||||
|
atgard_utford: { text: "text" },
|
||||||
|
kvalitetskontroll: { utfall: ["borta", "kvarstar", "delvis", "ej_verifierat"], beskrivning: "text" },
|
||||||
|
kommentar: { text: "text" },
|
||||||
|
kategori_byte: { kategori: "text" },
|
||||||
|
inaktivitet_forklarad: { text: "text", minuter: "tal" },
|
||||||
|
overlamning: { fran: "text" },
|
||||||
|
ansvarig_satt: { ansvarig: "text" },
|
||||||
|
ai_svar: { rader: "lista" },
|
||||||
|
export_skapad: { format: "text", version: "tal" },
|
||||||
|
arende_avslutat: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hypotesen får aldrig anta hög tillförlitlighet — samma regel som
|
||||||
|
// typsystemet upprätthåller i klienten, upprepad här därför att servern inte
|
||||||
|
// kan lita på att klienten är vår.
|
||||||
|
const GILTIG = {
|
||||||
|
text: (v) => typeof v === "string" && v.length > 0 && v.length <= 20000,
|
||||||
|
tal: (v) => typeof v === "number" && Number.isFinite(v),
|
||||||
|
boolean: (v) => typeof v === "boolean",
|
||||||
|
lista: (v) => Array.isArray(v) && v.length <= 500,
|
||||||
|
objekt: (v) => v !== null && typeof v === "object" && !Array.isArray(v),
|
||||||
|
};
|
||||||
|
|
||||||
|
function fältFel(typ, nyckel, regel, värde) {
|
||||||
|
if (Array.isArray(regel)) {
|
||||||
|
return regel.includes(värde) ? null : `${typ}.${nyckel} måste vara en av: ${regel.join(", ")}`;
|
||||||
|
}
|
||||||
|
return GILTIG[regel](värde) ? null : `${typ}.${nyckel} har fel form (väntade ${regel})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validerar en händelses form. Returnerar null när den duger, annars en
|
||||||
|
* förklaring avsedd att läsas av en människa som felsöker en integration.
|
||||||
|
*/
|
||||||
|
export function granskaHändelse(handelse) {
|
||||||
|
if (handelse === null || typeof handelse !== "object" || Array.isArray(handelse)) {
|
||||||
|
return "handelse måste vara ett objekt";
|
||||||
|
}
|
||||||
|
const schema = HÄNDELSESCHEMA[handelse.typ];
|
||||||
|
if (!schema) {
|
||||||
|
return `okänd händelsetyp: ${JSON.stringify(handelse.typ)}`;
|
||||||
|
}
|
||||||
|
for (const [nyckel, regel] of Object.entries(schema)) {
|
||||||
|
const fel = fältFel(handelse.typ, nyckel, regel, handelse[nyckel]);
|
||||||
|
if (fel) return fel;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bygger den post som faktiskt skrivs.
|
||||||
|
*
|
||||||
|
* Härkomsten kommer härifrån och ingen annanstans: `anvandare` ur den
|
||||||
|
* verifierade token, `tidpunkt` ur serverns klocka. Klientens tidsstämpel
|
||||||
|
* bevaras separat när den finns, eftersom den är det enda som finns vid
|
||||||
|
* offline-arbete — men den avgör aldrig när något anses ha skett.
|
||||||
|
*/
|
||||||
|
export function tillPost(post, anspr, nu = new Date()) {
|
||||||
|
const fel = granskaHändelse(post?.handelse);
|
||||||
|
if (fel) return { fel };
|
||||||
|
if (typeof post.id !== "string" || !/^[A-Za-z0-9_:.-]{1,128}$/.test(post.id)) {
|
||||||
|
return { fel: "id saknas eller har otillåtna tecken" };
|
||||||
|
}
|
||||||
|
|
||||||
|
const klient = typeof post.tidpunkt === "string" ? post.tidpunkt : null;
|
||||||
|
const klientTid = klient && !Number.isNaN(Date.parse(klient)) ? klient : null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
post: {
|
||||||
|
id: post.id,
|
||||||
|
tidpunkt: nu.toISOString(),
|
||||||
|
anvandare: anspr.namn,
|
||||||
|
handelse: {
|
||||||
|
...post.handelse,
|
||||||
|
// Fälten nedan går inte att sätta utifrån; skrivs de över här är det
|
||||||
|
// just poängen.
|
||||||
|
anvandarId: anspr.sub,
|
||||||
|
...(klientTid && klientTid !== nu.toISOString() ? { registrerad_tidpunkt: klientTid } : {}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,902 @@
|
|||||||
|
// Metodikbiblioteket — delad kod.
|
||||||
|
//
|
||||||
|
// Låg tidigare bara i klienten, vilket gjorde att servern inte kunde
|
||||||
|
// utvärdera kvalitetsgrindens metodikrader (QUALITET C-2). Datan bor nu
|
||||||
|
// här; app/src/felsokning/metodiker.ts återexporterar den med typer, så
|
||||||
|
// det finns fortfarande exakt en sanning.
|
||||||
|
//
|
||||||
|
// En metodik är inte en checklista över vad som brukar vara fel — det
|
||||||
|
// vore att gissa åt teknikern. Den är en ordning för att utesluta:
|
||||||
|
// symptomet verifieras först, sedan det billiga och synliga, sedan det
|
||||||
|
// som kräver mätning, sist det som kräver demontering.
|
||||||
|
//
|
||||||
|
// Tre regler gäller alla metodiker här:
|
||||||
|
//
|
||||||
|
// 1. Varje kontroll har ett minimikrav (mätvärde, foto eller
|
||||||
|
// observation). En kryssruta är inte evidens.
|
||||||
|
// 2. Symptomsteget frågar aldrig "vad är fel" utan "vad händer, när,
|
||||||
|
// var". Kundens ord blir ett verifierat symptom först när det
|
||||||
|
// reproducerats.
|
||||||
|
// 3. Där arbetet kan skada någon kommer säkerhetssteget först och kan
|
||||||
|
// inte hoppas över — se HÖGVOLT.
|
||||||
|
//
|
||||||
|
// Att "täcka allt" går inte att lova. Det som går är att täcka fordonets
|
||||||
|
// system systematiskt och låta GENERISK vara ett strukturellt komplett
|
||||||
|
// skyddsnät: den fungerar även för det ingen förutsett.
|
||||||
|
|
||||||
|
export const VIBRATION = {
|
||||||
|
id: "vibration",
|
||||||
|
namn: "Vibration under körning",
|
||||||
|
omrade: "Hjul och balans",
|
||||||
|
nyckelord: ["vibration", "vibrer", "skak", "obalans", "ojämn gång", "rattvibration"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{ id: "hastighetsberoende", text: "Är vibrationen hastighetsberoende?", svarstyp: "janej" },
|
||||||
|
{ id: "var", text: "Var känns vibrationen?", svarstyp: "val", val: ["I ratten", "I stolen", "I hela bilen"] },
|
||||||
|
{
|
||||||
|
id: "nar",
|
||||||
|
text: "När uppstår vibrationen?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Vid acceleration", "Vid jämn fart", "Vid inbromsning", "Alltid under körning"],
|
||||||
|
},
|
||||||
|
{ id: "intervall", text: "Försvinner den över eller under ett visst hastighetsintervall?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "visuell",
|
||||||
|
rubrik: "Visuell kontroll",
|
||||||
|
beskrivning: "Fotografera samtliga hjul. Skilj på observation och slutsats.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "foto_vf", text: "Fotografera vänster framhjul", krav: "foto" },
|
||||||
|
{ id: "foto_hf", text: "Fotografera höger framhjul", krav: "foto" },
|
||||||
|
{ id: "foto_vb", text: "Fotografera vänster bakhjul", krav: "foto" },
|
||||||
|
{ id: "foto_hb", text: "Fotografera höger bakhjul", krav: "foto" },
|
||||||
|
{ id: "dot", text: "Dokumentera DOT-/tillverkningsdatum", krav: "kommentar" },
|
||||||
|
{ id: "slitage", text: "Kontrollera däckslitage och slitagemönster", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "kontroller",
|
||||||
|
rubrik: "Mätningar",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "lufttryck", text: "Kontrollera lufttryck", krav: "matvarde" },
|
||||||
|
{ id: "hjulmoment", text: "Kontrollera hjulmoment", krav: "matvarde" },
|
||||||
|
{ id: "kast", text: "Kontrollera radial- och sidokast", krav: "matvarde" },
|
||||||
|
{ id: "balansering", text: "Kontrollera hjulbalansering", krav: "kommentar" },
|
||||||
|
{ id: "bussningar", text: "Kontrollera bussningar och leder", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "provkorning",
|
||||||
|
rubrik: "Provkörning",
|
||||||
|
beskrivning: "Verifiera under provkörning:",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "pk_hastighet", text: "Hastighet där vibration uppstår", krav: "kommentar" },
|
||||||
|
{ id: "pk_acc", text: "Förändring vid acceleration", krav: "kommentar" },
|
||||||
|
{ id: "pk_motorbroms", text: "Förändring vid motorbroms", krav: "kommentar" },
|
||||||
|
{ id: "pk_kurva", text: "Förändring vid kurvtagning", krav: "kommentar" },
|
||||||
|
{ id: "pk_var", text: "Om vibration känns i ratt eller kaross", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ELSYSTEM = {
|
||||||
|
id: "elsystem",
|
||||||
|
namn: "Elsystem och strömförsörjning",
|
||||||
|
omrade: "El",
|
||||||
|
nyckelord: ["relä", "rela", "säkring", "elektr", "spänning", "volt", "lampa", "belysning", "ström", "kortslut", "kabel", "kabla", "kontaktdon", "jordfel"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{ id: "reproducerbart", text: "Går felet att reproducera?", svarstyp: "janej" },
|
||||||
|
{
|
||||||
|
id: "omfattning",
|
||||||
|
text: "Är funktionen helt död eller delvis fungerande?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Helt död", "Delvis fungerande", "Intermittent"],
|
||||||
|
},
|
||||||
|
{ id: "funktion", text: "Vilken funktion saknas eller felar?", svarstyp: "text" },
|
||||||
|
{ id: "forandring", text: "Har något åtgärdats eller förändrats nyligen?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "visuell",
|
||||||
|
rubrik: "Visuell kontroll",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "foto_komponent", text: "Fotografera komponenten och dess anslutningar", krav: "foto" },
|
||||||
|
{ id: "skador", text: "Kontrollera synliga skador, korrosion och lösa kontaktdon", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "matningar",
|
||||||
|
rubrik: "Mätningar",
|
||||||
|
beskrivning: "Mät under belastning. En spänning utan last säger nästan ingenting om en dålig förbindelse.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "batterispanning", text: "Mät batterispänning", krav: "matvarde" },
|
||||||
|
{ id: "sakringar", text: "Kontrollera berörda säkringar", krav: "kommentar" },
|
||||||
|
{ id: "matningsspanning", text: "Mät matningsspänning vid komponenten under last", krav: "matvarde" },
|
||||||
|
{ id: "jord", text: "Mät spänningsfall mot jord under last", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "rela",
|
||||||
|
rubrik: "Relä och styrsignal",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "rela_klick", text: "Kontrollera om reläet klickar vid aktivering", krav: "kommentar" },
|
||||||
|
{ id: "styrsignal", text: "Mät styrsignal till reläet", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "funktionstest",
|
||||||
|
rubrik: "Funktionstest",
|
||||||
|
kontroller: [{ id: "test", text: "Genomför funktionstest och dokumentera resultatet", krav: "kommentar" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const START_LADDNING = {
|
||||||
|
id: "start_laddning",
|
||||||
|
namn: "Start- och laddningssystem",
|
||||||
|
omrade: "El",
|
||||||
|
nyckelord: ["startar inte", "startproblem", "startmotor", "generator", "laddning", "batteriet dör", "urladdat", "batterilampa", "drar inte runt", "klick vid start"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "beteende",
|
||||||
|
text: "Vad händer vid startförsök?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Ingenting alls", "Ett klick", "Drar runt långsamt", "Drar runt normalt men tänder inte", "Startar ibland"],
|
||||||
|
},
|
||||||
|
{ id: "kallt_varmt", text: "Uppträder felet kallt, varmt eller alltid?", svarstyp: "val", val: ["Kallt", "Varmt", "Alltid"] },
|
||||||
|
{ id: "stillestand", text: "Hur länge har fordonet stått mellan försöken?", svarstyp: "text" },
|
||||||
|
{ id: "laddat", text: "Har batteriet laddats eller bytts nyligen?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "batteri",
|
||||||
|
rubrik: "Batteriets kondition",
|
||||||
|
beskrivning: "Ett svagt batteri ger följdfel i hela fordonet. Uteslut det först.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "vilospanning", text: "Mät vilospänning efter minst en timmes vila", krav: "matvarde" },
|
||||||
|
{ id: "batteritest", text: "Belastningstest — fotografera testarens resultat", krav: "foto" },
|
||||||
|
{ id: "poler", text: "Kontrollera polskor och jordflätor", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "start",
|
||||||
|
rubrik: "Startsystem",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "startspanning", text: "Mät spänning vid startmotorn under startförsök", krav: "matvarde" },
|
||||||
|
{ id: "spanningsfall_plus", text: "Mät spänningsfall i plusledningen under start", krav: "matvarde" },
|
||||||
|
{ id: "spanningsfall_jord", text: "Mät spänningsfall i jordledningen under start", krav: "matvarde" },
|
||||||
|
{ id: "startsignal", text: "Kontrollera styrsignal till startrelä", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "laddning",
|
||||||
|
rubrik: "Laddningssystem",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "laddspanning", text: "Mät laddspänning vid tomgång och vid förhöjt varvtal", krav: "matvarde" },
|
||||||
|
{ id: "rippel", text: "Mät rippel från generatorn", krav: "matvarde" },
|
||||||
|
{ id: "rem", text: "Kontrollera drivrem och spänning", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "krypstrom",
|
||||||
|
rubrik: "Krypström",
|
||||||
|
beskrivning: "Endast relevant när batteriet laddar ur under stillestånd.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "vilostrom", text: "Mät viloström efter att fordonet somnat", krav: "matvarde" },
|
||||||
|
{ id: "sakringsdrag", text: "Lokalisera krets genom successiv säkringsurtagning", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MOTOR_DRIFT = {
|
||||||
|
id: "motor_drift",
|
||||||
|
namn: "Motorgång och effekt",
|
||||||
|
omrade: "Motor",
|
||||||
|
nyckelord: ["ryck", "tappar kraft", "effektbrist", "misständ", "ojämn tomgång", "tomgång", "motorlampa", "kraftlös", "hack", "går på tre"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "nar",
|
||||||
|
text: "När uppträder felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Vid kallstart", "Vid tomgång", "Under belastning", "Vid visst varvtal", "Alltid"],
|
||||||
|
},
|
||||||
|
{ id: "varvtal", text: "Vid vilket varvtal eller vilken last?", svarstyp: "text" },
|
||||||
|
{ id: "varningslampa", text: "Lyser eller blinkar motorlampan?", svarstyp: "val", val: ["Lyser fast", "Blinkar", "Slocknad"] },
|
||||||
|
{ id: "brankslebyte", text: "Har bränsle tankats eller service utförts strax innan?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "felkoder",
|
||||||
|
rubrik: "Felkoder och mätdata",
|
||||||
|
beskrivning: "Läs innan något demonteras. En felkod pekar på en krets, inte på en trasig komponent.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "dtc", text: "Läs felkoder — fotografera diagnosskärmen", krav: "foto" },
|
||||||
|
{ id: "frysdata", text: "Dokumentera frysramsdata för koden", krav: "kommentar" },
|
||||||
|
{ id: "misstandning", text: "Läs misständningsräknare per cylinder", krav: "matvarde" },
|
||||||
|
{ id: "branslekorrigering", text: "Läs kort- och långtidsbränslekorrigering", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "mekanik",
|
||||||
|
rubrik: "Motorns grundkondition",
|
||||||
|
beskrivning: "Utan grundkondition är alla givarvärden svåra att tolka.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "kompression", text: "Mät kompression eller relativ kompression", krav: "matvarde" },
|
||||||
|
{ id: "vevhustryck", text: "Kontrollera vevhustryck", krav: "kommentar" },
|
||||||
|
{ id: "insugslackage", text: "Kontrollera insugssystemet för falskluft", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "tandning_bransle",
|
||||||
|
rubrik: "Tändning och bränsle",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "tandstift", text: "Kontrollera tändstift — fotografera samtliga", krav: "foto" },
|
||||||
|
{ id: "spolar", text: "Mät tändspolarnas resistans eller byt mellan cylindrar", krav: "matvarde" },
|
||||||
|
{ id: "bransletryck", text: "Mät bränsletryck under belastning", krav: "matvarde" },
|
||||||
|
{ id: "insprutare", text: "Kontrollera insprutarnas returmängd eller styrning", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "provkorning",
|
||||||
|
rubrik: "Provkörning med loggning",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "logg", text: "Logga mätdata under körning där felet uppträder", krav: "foto" },
|
||||||
|
{ id: "reproducerat", text: "Dokumentera under vilka förhållanden felet uppträdde", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BROMSAR = {
|
||||||
|
id: "bromsar",
|
||||||
|
namn: "Bromssystem",
|
||||||
|
omrade: "Chassi",
|
||||||
|
nyckelord: ["broms", "bromspedal", "skevhet", "gnisslar vid inbromsning", "abs", "bromsvätska", "handbroms", "drar snett vid inbromsning"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "karaktar",
|
||||||
|
text: "Hur yttrar sig felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Skevhet/pulsering", "Missljud", "Lång pedalväg", "Mjuk pedal", "Drar åt sidan", "Bromsen ligger på"],
|
||||||
|
},
|
||||||
|
{ id: "nar", text: "Vid vilken hastighet och bromskraft?", svarstyp: "text" },
|
||||||
|
{ id: "varningslampa", text: "Lyser broms- eller ABS-varning?", svarstyp: "janej" },
|
||||||
|
{ id: "senaste", text: "När byttes bromskomponenter senast?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "visuell",
|
||||||
|
rubrik: "Visuell kontroll",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "foto_belagg", text: "Fotografera belägg och skivor på samtliga hjul", krav: "foto" },
|
||||||
|
{ id: "belaggtjocklek", text: "Mät beläggtjocklek", krav: "matvarde" },
|
||||||
|
{ id: "skivtjocklek", text: "Mät skivtjocklek och jämför med minmått", krav: "matvarde" },
|
||||||
|
{ id: "lackage", text: "Kontrollera slangar, rör och ok för läckage", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "matningar",
|
||||||
|
rubrik: "Mätningar",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "skivkast", text: "Mät skivkast med mätklocka", krav: "matvarde" },
|
||||||
|
{ id: "tjockleksvariation", text: "Mät tjockleksvariation på skivan", krav: "matvarde" },
|
||||||
|
{ id: "vatska", text: "Mät bromsvätskans kokpunkt eller vatteninnehåll", krav: "matvarde" },
|
||||||
|
{ id: "okens_rorlighet", text: "Kontrollera okens och styrbultarnas rörlighet", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "system",
|
||||||
|
rubrik: "System och ABS",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "dtc", text: "Läs felkoder ur ABS-styrenheten", krav: "foto" },
|
||||||
|
{ id: "hjulgivare", text: "Kontrollera hjulhastighetsgivarnas signal", krav: "matvarde" },
|
||||||
|
{ id: "bromsprov", text: "Utför bromsprov i provbänk — fotografera protokollet", krav: "foto" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const STYRNING_FJADRING = {
|
||||||
|
id: "styrning_fjadring",
|
||||||
|
namn: "Styrning och fjädring",
|
||||||
|
omrade: "Chassi",
|
||||||
|
nyckelord: ["drar åt", "styrning", "ratt", "glapp", "stötdämpar", "fjäder", "fjädr", "hjulinställning", "spårar", "gungar", "knäpper i kurva", "servostyrning"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "karaktar",
|
||||||
|
text: "Hur yttrar sig felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Drar åt sidan", "Glapp i ratten", "Missljud", "Dålig vägkänsla", "Ojämnt däckslitage", "Gungar/studsar"],
|
||||||
|
},
|
||||||
|
{ id: "underlag", text: "Uppträder det på visst underlag eller i viss kurva?", svarstyp: "text" },
|
||||||
|
{ id: "handelse", text: "Har fordonet kört på något eller varit i kontakt med trottoarkant?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "visuell",
|
||||||
|
rubrik: "Visuell kontroll",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "foto_slitage", text: "Fotografera däckens slitagemönster", krav: "foto" },
|
||||||
|
{ id: "dampare", text: "Kontrollera dämpare för läckage", krav: "kommentar" },
|
||||||
|
{ id: "damask", text: "Kontrollera damasker på styrleder och drivknutar", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "glapp",
|
||||||
|
rubrik: "Glappkontroll",
|
||||||
|
beskrivning: "Utförs med hjulet avlastat. Dokumentera var glappet finns, inte bara att det finns.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "hjullager", text: "Kontrollera hjullagerspel", krav: "kommentar" },
|
||||||
|
{ id: "styrleder", text: "Kontrollera styr- och bärleder", krav: "kommentar" },
|
||||||
|
{ id: "bussningar", text: "Kontrollera bussningar", krav: "kommentar" },
|
||||||
|
{ id: "kuggstang", text: "Kontrollera kuggstång och styrstagsändar", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "installning",
|
||||||
|
rubrik: "Hjulinställning",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "matning", text: "Mät hjulinställning — fotografera protokollet före justering", krav: "foto" },
|
||||||
|
{ id: "avvikelse", text: "Dokumentera avvikelser mot tillverkarens värden", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const KYLSYSTEM = {
|
||||||
|
id: "kylsystem",
|
||||||
|
namn: "Kylsystem och överhettning",
|
||||||
|
omrade: "Motor",
|
||||||
|
nyckelord: ["överhett", "koka", "kylvätska", "temperatur", "termostat", "kylare", "vattenpump", "värme i kupén", "expansionskärl"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "nar",
|
||||||
|
text: "När stiger temperaturen?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Vid tomgång", "I låg fart", "I hög fart", "Vid belastning/backe", "Alltid"],
|
||||||
|
},
|
||||||
|
{ id: "kylvatskeforlust", text: "Förloras kylvätska? Hur mycket och hur ofta?", svarstyp: "text" },
|
||||||
|
{ id: "varme", text: "Fungerar kupévärmen?", svarstyp: "janej" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "visuell",
|
||||||
|
rubrik: "Visuell kontroll",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "niva", text: "Kontrollera kylvätskenivå kall — fotografera expansionskärlet", krav: "foto" },
|
||||||
|
{ id: "lackage", text: "Kontrollera synligt läckage vid slangar, kylare och pump", krav: "kommentar" },
|
||||||
|
{ id: "kylarpaket", text: "Kontrollera kylarpaketet för igensättning", krav: "foto" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "matningar",
|
||||||
|
rubrik: "Mätningar",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "trycktest", text: "Trycktesta kylsystemet", krav: "matvarde" },
|
||||||
|
{ id: "lock", text: "Trycktesta expansionskärlets lock", krav: "matvarde" },
|
||||||
|
{ id: "temperatur", text: "Mät temperatur in och ut ur kylaren med IR-termometer", krav: "matvarde" },
|
||||||
|
{ id: "flakt", text: "Kontrollera att kylfläkten startar vid rätt temperatur", krav: "kommentar" },
|
||||||
|
{ id: "givare", text: "Jämför styrenhetens temperaturvärde med uppmätt", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "packning",
|
||||||
|
rubrik: "Topplockspackning",
|
||||||
|
beskrivning: "Görs när kylvätska förloras utan yttre läckage.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "avgastest", text: "Avgastest i kylvätskan (CO2-test)", krav: "foto" },
|
||||||
|
{ id: "kompression_kyl", text: "Kontrollera trycksättning av kylsystemet vid motorgång", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DRIVLINA = {
|
||||||
|
id: "drivlina",
|
||||||
|
namn: "Växellåda och drivlina",
|
||||||
|
omrade: "Drivlina",
|
||||||
|
nyckelord: ["växellåda", "växlar", "koppling", "automatlåda", "rycker vid växling", "slir", "drivknut", "kardan", "differential", "kärvar i växeln"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "karaktar",
|
||||||
|
text: "Hur yttrar sig felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Slirar", "Rycker vid växling", "Går inte i växel", "Missljud", "Vibration vid acceleration", "Läckage"],
|
||||||
|
},
|
||||||
|
{ id: "vaxel", text: "Vilken växel eller vilket varvtal?", svarstyp: "text" },
|
||||||
|
{ id: "kall_varm", text: "Kall eller varm låda?", svarstyp: "val", val: ["Kall", "Varm", "Ingen skillnad"] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "visuell",
|
||||||
|
rubrik: "Visuell kontroll",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "olja", text: "Kontrollera oljenivå och oljans skick — fotografera", krav: "foto" },
|
||||||
|
{ id: "lackage", text: "Kontrollera läckage vid tätningar och sump", krav: "kommentar" },
|
||||||
|
{ id: "fasten", text: "Kontrollera växellådsfästen", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "matningar",
|
||||||
|
rubrik: "Mätningar och avläsning",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "dtc", text: "Läs felkoder ur växellådsstyrenheten", krav: "foto" },
|
||||||
|
{ id: "adaptioner", text: "Dokumentera adaptionsvärden och kopplingsslitage", krav: "matvarde" },
|
||||||
|
{ id: "oljetemp", text: "Mät oljetemperatur under provkörning", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "provkorning",
|
||||||
|
rubrik: "Provkörning",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "vaxlingspunkter", text: "Dokumentera växlingspunkter och beteende", krav: "kommentar" },
|
||||||
|
{ id: "belastning", text: "Provkör under belastning där felet uppträder", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AVGAS_EMISSION = {
|
||||||
|
id: "avgas_emission",
|
||||||
|
namn: "Avgassystem och emissioner",
|
||||||
|
omrade: "Motor",
|
||||||
|
nyckelord: ["partikelfilt", "dpf", "adblue", "katalysator", "lambda", "avgas", "emission", "rökutveckling", "svart rök", "blå rök", "os", "egr", "regenerer", "utsläpp"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "karaktar",
|
||||||
|
text: "Hur yttrar sig felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Varningslampa", "Rök", "Effektbegränsning", "Lukt", "Underkänd besiktning"],
|
||||||
|
},
|
||||||
|
{ id: "rokfarg", text: "Om rök — vilken färg och när?", svarstyp: "text" },
|
||||||
|
{ id: "korprofil", text: "Beskriv fordonets körprofil (mest kort- eller långkörning)?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "avlasning",
|
||||||
|
rubrik: "Avläsning",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "dtc", text: "Läs felkoder — fotografera diagnosskärmen", krav: "foto" },
|
||||||
|
{ id: "sotmangd", text: "Läs beräknad och uppmätt sotmängd i partikelfiltret", krav: "matvarde" },
|
||||||
|
{ id: "regenerering", text: "Dokumentera antal och utfall av senaste regenereringar", krav: "kommentar" },
|
||||||
|
{ id: "lambda", text: "Läs lambdagivarnas signaler före och efter katalysator", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "matningar",
|
||||||
|
rubrik: "Mätningar",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "mottryck", text: "Mät avgasmottryck", krav: "matvarde" },
|
||||||
|
{ id: "differenstryck", text: "Mät differenstryck över partikelfiltret", krav: "matvarde" },
|
||||||
|
{ id: "adblue_niva", text: "Kontrollera AdBlue-nivå och kvalitet där sådant finns", krav: "matvarde" },
|
||||||
|
{ id: "egr", text: "Kontrollera EGR-ventilens funktion och läge", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "orsak",
|
||||||
|
rubrik: "Bakomliggande orsak",
|
||||||
|
beskrivning: "Ett igensatt filter är oftast en följd, inte orsaken. Dokumentera vad som skapade sotet.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "grundorsak", text: "Kontrollera insprutning, turbo och luftflöde", krav: "kommentar" },
|
||||||
|
{ id: "korstrackor", text: "Bedöm om körprofilen tillåter regenerering", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const KLIMAT = {
|
||||||
|
id: "klimat",
|
||||||
|
namn: "Klimatanläggning",
|
||||||
|
omrade: "Komfort",
|
||||||
|
nyckelord: ["ac", "luftkonditionering", "klimatanläggning", "kyler inte", "kompressor", "köldmedi", "imma", "immig", "fläkt", "lukt i kupén", "värmepaket"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "karaktar",
|
||||||
|
text: "Hur yttrar sig felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Kyler inte alls", "Kyler dåligt", "Kyler ibland", "Missljud", "Lukt", "Imma på rutorna"],
|
||||||
|
},
|
||||||
|
{ id: "sidor", text: "Skiljer det mellan höger och vänster sida?", svarstyp: "janej" },
|
||||||
|
{ id: "service", text: "När utfördes AC-service senast?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "visuell",
|
||||||
|
rubrik: "Visuell kontroll",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "kondensor", text: "Fotografera kondensorn — kontrollera igensättning och skador", krav: "foto" },
|
||||||
|
{ id: "kupefilter", text: "Kontrollera kupéfiltret", krav: "foto" },
|
||||||
|
{ id: "kompressor_rem", text: "Kontrollera kompressorns drivning och magnetkoppling", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "matningar",
|
||||||
|
rubrik: "Mätningar",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "tryck", text: "Mät hög- och lågtryck vid känd omgivningstemperatur", krav: "matvarde" },
|
||||||
|
{ id: "utblastemp", text: "Mät utblåstemperatur vid mittre munstycke", krav: "matvarde" },
|
||||||
|
{ id: "mangd", text: "Väg upptagen köldmediemängd vid tömning", krav: "matvarde" },
|
||||||
|
{ id: "lackagesok", text: "Läcksök med spårgas eller UV", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "styrning",
|
||||||
|
rubrik: "Styrning",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "dtc", text: "Läs felkoder ur klimatstyrenheten", krav: "foto" },
|
||||||
|
{ id: "spjall", text: "Kontrollera spjällmotorernas rörelse", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HOGVOLT = {
|
||||||
|
id: "hogvolt",
|
||||||
|
namn: "Högvoltsystem — elbil och hybrid",
|
||||||
|
omrade: "Högvolt",
|
||||||
|
nyckelord: ["högvolt", "elbil", "hybrid", "traktionsbatteri", "hv", "laddning av bil", "räckvidd", "laddbox", "orange kabel", "sköldpadda"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "sakerhet",
|
||||||
|
rubrik: "Säkerhet — utförs först",
|
||||||
|
beskrivning:
|
||||||
|
"Högvoltsystem kan vara livsfarliga. Inget arbete på systemet påbörjas innan stegen nedan är dokumenterade. Kräver behörighet för arbete på högvoltsystem.",
|
||||||
|
fragor: [
|
||||||
|
{ id: "behorighet", text: "Har du behörighet för arbete på högvoltsystem?", svarstyp: "janej" },
|
||||||
|
{ id: "avstangt", text: "Är fordonet spänningslöst enligt tillverkarens rutin?", svarstyp: "janej" },
|
||||||
|
],
|
||||||
|
kontroller: [
|
||||||
|
{ id: "service_disconnect", text: "Dokumentera att servicebrytaren är urtagen och säkrad", krav: "foto" },
|
||||||
|
{ id: "vantetid", text: "Dokumentera väntetid enligt tillverkarens anvisning", krav: "kommentar" },
|
||||||
|
{ id: "spanningsfrihet", text: "Mät och dokumentera spänningsfrihet före ingrepp", krav: "matvarde" },
|
||||||
|
{ id: "skyddsutrustning", text: "Dokumentera använd skyddsutrustning och avspärrning", krav: "foto" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "karaktar",
|
||||||
|
text: "Hur yttrar sig felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Laddar inte", "Kortare räckvidd", "Effektbegränsning", "Varningsmeddelande", "Fordonet startar inte"],
|
||||||
|
},
|
||||||
|
{ id: "laddtyp", text: "Vid vilken laddning uppträder felet (AC, DC, vilken laddpunkt)?", svarstyp: "text" },
|
||||||
|
{ id: "temperatur", text: "Vid vilken omgivnings- och batteritemperatur?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "avlasning",
|
||||||
|
rubrik: "Avläsning",
|
||||||
|
beskrivning: "Utförs med diagnosverktyg — inga ingrepp i systemet krävs.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "dtc", text: "Läs felkoder ur samtliga högvoltstyrenheter", krav: "foto" },
|
||||||
|
{ id: "soh", text: "Läs batteriets hälsa (SOH) och laddnivå (SOC)", krav: "matvarde" },
|
||||||
|
{ id: "cellspanning", text: "Läs cellspänningar och dokumentera största avvikelse", krav: "matvarde" },
|
||||||
|
{ id: "isolationsvarde", text: "Läs systemets isolationsvärde", krav: "matvarde" },
|
||||||
|
{ id: "temperaturer", text: "Läs batteriets temperaturgivare", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "laddning",
|
||||||
|
rubrik: "Laddkedjan",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "laddkabel", text: "Kontrollera laddkabel och laddkontakt — fotografera stiften", krav: "foto" },
|
||||||
|
{ id: "laddlogg", text: "Läs laddhistorik och avbrottsorsaker", krav: "kommentar" },
|
||||||
|
{ id: "extern", text: "Testa mot annan laddpunkt för att utesluta yttre orsak", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DIAGNOS_NATVERK = {
|
||||||
|
id: "diagnos_natverk",
|
||||||
|
namn: "Felkoder och kommunikation",
|
||||||
|
omrade: "Diagnos",
|
||||||
|
nyckelord: ["felkod", "dtc", "can", "canbuss", "kommunikationsfel", "ingen kontakt", "styrenhet", "obd", "diagnos", "flera lampor"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "omfattning",
|
||||||
|
text: "Hur många system är berörda?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["En styrenhet", "Flera styrenheter", "Hela fordonet", "Endast diagnosverktyget"],
|
||||||
|
},
|
||||||
|
{ id: "nar", text: "Uppstod felet efter ingrepp, batteribyte eller uppdatering?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "grund",
|
||||||
|
rubrik: "Grundförutsättningar",
|
||||||
|
beskrivning: "Kommunikationsfel beror oftare på matning och jord än på styrenheten.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "batteri", text: "Mät batterispänning under avläsning", krav: "matvarde" },
|
||||||
|
{ id: "obd_matning", text: "Mät matning och jord i diagnosuttaget", krav: "matvarde" },
|
||||||
|
{ id: "sakringar", text: "Kontrollera säkringar till berörda styrenheter", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "buss",
|
||||||
|
rubrik: "Bussmätning",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "terminering", text: "Mät bussens termineringsresistans med systemet spänningslöst", krav: "matvarde" },
|
||||||
|
{ id: "bussignal", text: "Mät CAN-signalen med oscilloskop — fotografera kurvan", krav: "foto" },
|
||||||
|
{ id: "avdelning", text: "Dela av bussen för att lokalisera störande nod", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "koder",
|
||||||
|
rubrik: "Felkoder i sammanhang",
|
||||||
|
beskrivning: "En felkod pekar på en krets, inte på en trasig komponent. Läs alla system innan någon kod raderas.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "helavlasning", text: "Läs samtliga styrenheter — fotografera listan", krav: "foto" },
|
||||||
|
{ id: "frysdata", text: "Dokumentera frysramsdata innan radering", krav: "kommentar" },
|
||||||
|
{ id: "efter_radering", text: "Radera, provkör och dokumentera vilka koder som återkom", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LACKAGE = {
|
||||||
|
id: "lackage",
|
||||||
|
namn: "Läckage",
|
||||||
|
omrade: "Övrigt",
|
||||||
|
nyckelord: ["läck", "läckage", "oljefläck", "dropp", "vatten i bilen", "fukt", "blöt matta", "oljeförbrukning"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "vatska",
|
||||||
|
text: "Vilken vätska misstänks?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Motorolja", "Kylvätska", "Växellådsolja", "Bromsvätska", "Bränsle", "Vatten/kondens", "Okänt"],
|
||||||
|
},
|
||||||
|
{ id: "mangd", text: "Hur mycket och hur ofta?", svarstyp: "text" },
|
||||||
|
{ id: "plats", text: "Var på marken syns fläcken i förhållande till fordonet?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "visuell",
|
||||||
|
rubrik: "Lokalisering",
|
||||||
|
beskrivning: "Rengör först. Ett gammalt läckage döljer var det nya kommer ifrån.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "foto_fore", text: "Fotografera området före rengöring", krav: "foto" },
|
||||||
|
{ id: "rengoring", text: "Rengör området och dokumentera att det är torrt", krav: "foto" },
|
||||||
|
{ id: "provkorning", text: "Provkör eller låt gå och fotografera var vätskan uppträder", krav: "foto" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "metod",
|
||||||
|
rubrik: "Läcksökning",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "uv", text: "Läcksök med UV-spårämne där det är tillämpligt", krav: "kommentar" },
|
||||||
|
{ id: "trycktest", text: "Trycktesta systemet", krav: "matvarde" },
|
||||||
|
{ id: "niva", text: "Mät nivåförändring över tid", krav: "matvarde" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MISSLJUD = {
|
||||||
|
id: "missljud",
|
||||||
|
namn: "Missljud",
|
||||||
|
omrade: "Övrigt",
|
||||||
|
nyckelord: ["missljud", "ljud", "knack", "gnissel", "gnissl", "vinande", "brumm", "skram", "väsande", "tjut"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
beskrivning: "Ett missljud som inte reproducerats går inte att åtgärda. Spela in det.",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "karaktar",
|
||||||
|
text: "Vilken karaktär har ljudet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Knack", "Gnissel", "Vinande", "Brummande", "Skrammel", "Väsande", "Tjut"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "nar",
|
||||||
|
text: "När hörs det?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Vid start", "Vid tomgång", "Under körning", "Vid inbromsning", "Vid kurvtagning", "Över ojämnheter"],
|
||||||
|
},
|
||||||
|
{ id: "beroende", text: "Följer ljudet varvtal eller hastighet?", svarstyp: "val", val: ["Varvtal", "Hastighet", "Ingetdera"] },
|
||||||
|
{ id: "temperatur", text: "Skillnad kallt mot varmt?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "inspelning",
|
||||||
|
rubrik: "Dokumentera ljudet",
|
||||||
|
beskrivning: "Video med ljud är evidens. En beskrivning i text är det inte.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "video", text: "Spela in ljudet med video under de förhållanden där det uppträder", krav: "foto" },
|
||||||
|
{ id: "forhallanden", text: "Dokumentera hastighet, varvtal och underlag vid inspelningen", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "lokalisering",
|
||||||
|
rubrik: "Lokalisering",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "stetoskop", text: "Lokalisera med stetoskop eller ljudsond", krav: "kommentar" },
|
||||||
|
{ id: "avlastning", text: "Kontrollera om ljudet ändras vid avlastning eller belastning", krav: "kommentar" },
|
||||||
|
{ id: "uteslutning", text: "Dokumentera vilka källor som uteslutits och hur", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ADAS = {
|
||||||
|
id: "adas",
|
||||||
|
namn: "Förarassistans och kalibrering",
|
||||||
|
omrade: "Diagnos",
|
||||||
|
nyckelord: ["adas", "kamera", "radar", "filhållning", "adaptiv farthållare", "kalibrer", "vindruta", "parkeringssensor", "döda vinkeln", "nödbroms"],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{
|
||||||
|
id: "funktion",
|
||||||
|
text: "Vilken funktion felar?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Filhållning", "Adaptiv farthållare", "Automatisk nödbroms", "Döda vinkeln", "Parkeringshjälp", "Backkamera"],
|
||||||
|
},
|
||||||
|
{ id: "ingrepp", text: "Har vindruta, kaross eller fjädring åtgärdats nyligen?", svarstyp: "text" },
|
||||||
|
{ id: "forhallanden", text: "Uppträder felet i visst väder eller ljus?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "forutsattningar",
|
||||||
|
rubrik: "Förutsättningar för kalibrering",
|
||||||
|
beskrivning:
|
||||||
|
"En kalibrering på fel förutsättningar ger ett fel som ser åtgärdat ut. Dokumentera att kraven är uppfyllda innan den utförs.",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "dtc", text: "Läs felkoder ur berörda styrenheter", krav: "foto" },
|
||||||
|
{ id: "hjulinstallning", text: "Kontrollera hjulinställning — bakaxelns spårning påverkar kameran", krav: "matvarde" },
|
||||||
|
{ id: "dacktryck", text: "Kontrollera däcktryck och körhöjd", krav: "matvarde" },
|
||||||
|
{ id: "sikt", text: "Kontrollera kamerans och radarns siktfält för smuts eller skada", krav: "foto" },
|
||||||
|
{ id: "yta", text: "Dokumentera att kalibreringsytan uppfyller kraven på planhet och ljus", krav: "foto" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "kalibrering",
|
||||||
|
rubrik: "Kalibrering",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "utford", text: "Utför kalibrering enligt tillverkarens metod — fotografera resultatet", krav: "foto" },
|
||||||
|
{ id: "provkorning", text: "Provkör och verifiera funktionen under de förhållanden felet uppträdde", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GENERISK = {
|
||||||
|
id: "generisk",
|
||||||
|
namn: "Generell strukturerad felsökning",
|
||||||
|
omrade: "Övrigt",
|
||||||
|
nyckelord: [],
|
||||||
|
steg: [
|
||||||
|
{
|
||||||
|
id: "symptom",
|
||||||
|
rubrik: "Verifiera symptom",
|
||||||
|
fragor: [
|
||||||
|
{ id: "reproducerbart", text: "Går felet att reproducera?", svarstyp: "janej" },
|
||||||
|
{
|
||||||
|
id: "nar",
|
||||||
|
text: "När uppträder felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Alltid", "Ibland", "Endast under drift", "Endast vid start"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "var",
|
||||||
|
text: "Var upplevs felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Fram", "Bak", "Höger", "Vänster", "Motor/drivkälla", "Kupé/förarplats", "Okänt"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "hur",
|
||||||
|
text: "Hur upplevs felet?",
|
||||||
|
svarstyp: "val",
|
||||||
|
val: ["Skakar/vibrerar", "Missljud (knack/gnissel/vinande)", "Rycker", "Tappar kraft", "Stannar helt", "Annat"],
|
||||||
|
},
|
||||||
|
{ id: "forlopp", text: "Beskriv förloppet när felet uppstår", svarstyp: "text" },
|
||||||
|
{ id: "forandring", text: "Har något förändrats nyligen (service, reparation, miljö)?", svarstyp: "text" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "visuell",
|
||||||
|
rubrik: "Visuell kontroll",
|
||||||
|
kontroller: [
|
||||||
|
{ id: "foto_objekt", text: "Fotografera objektet och det berörda området", krav: "foto" },
|
||||||
|
{ id: "skador", text: "Kontrollera synliga skador, läckage eller lösa anslutningar", krav: "kommentar" },
|
||||||
|
{ id: "typskylt", text: "Dokumentera typskylt/märkning", krav: "foto" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "grundkontroller",
|
||||||
|
rubrik: "Grundkontroller",
|
||||||
|
kontroller: [
|
||||||
|
{
|
||||||
|
id: "matning",
|
||||||
|
text: "Utför grundläggande mätningar (spänning, tryck, temperatur — det som är relevant)",
|
||||||
|
krav: "matvarde",
|
||||||
|
},
|
||||||
|
{ id: "sakringar", text: "Kontrollera säkringar/skydd", krav: "kommentar" },
|
||||||
|
{ id: "anslutningar", text: "Kontrollera kontaktdon och anslutningar", krav: "kommentar" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "funktionstest",
|
||||||
|
rubrik: "Funktionstest",
|
||||||
|
kontroller: [{ id: "test", text: "Genomför funktionstest och dokumentera resultatet", krav: "kommentar" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ordningen styr bara hur de visas. Valet görs på nyckelord, inte på
|
||||||
|
// position — GENERISK ligger sist eftersom den är fallback.
|
||||||
|
export const ALLA_METODIKER = [
|
||||||
|
VIBRATION,
|
||||||
|
BROMSAR,
|
||||||
|
STYRNING_FJADRING,
|
||||||
|
ELSYSTEM,
|
||||||
|
START_LADDNING,
|
||||||
|
MOTOR_DRIFT,
|
||||||
|
KYLSYSTEM,
|
||||||
|
DRIVLINA,
|
||||||
|
AVGAS_EMISSION,
|
||||||
|
KLIMAT,
|
||||||
|
HOGVOLT,
|
||||||
|
DIAGNOS_NATVERK,
|
||||||
|
LACKAGE,
|
||||||
|
MISSLJUD,
|
||||||
|
ADAS,
|
||||||
|
GENERISK,
|
||||||
|
];
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../gemensam/grind.mjs
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../gemensam/handelser.mjs
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../gemensam/metodiker.mjs
|
||||||
@@ -27,6 +27,9 @@ import { dirname, join } from "node:path";
|
|||||||
import pg from "pg";
|
import pg from "pg";
|
||||||
import { innehallsHash, mediatypGiltig, valjLager } from "./bilagor.mjs";
|
import { innehallsHash, mediatypGiltig, valjLager } from "./bilagor.mjs";
|
||||||
import { avsluta, logga, mätvärde, spårFrån, starta, traceparent } from "./observation.mjs";
|
import { avsluta, logga, mätvärde, spårFrån, starta, traceparent } from "./observation.mjs";
|
||||||
|
import { tillPost } from "./handelser.mjs";
|
||||||
|
import { grinda, grindaArendetyp } from "./grind.mjs";
|
||||||
|
import { ALLA_METODIKER } from "./metodiker.mjs";
|
||||||
|
|
||||||
// API-first: OpenAPI-specen är en versionerad artefakt och serveras live.
|
// API-first: OpenAPI-specen är en versionerad artefakt och serveras live.
|
||||||
const OPENAPI = readFileSync(join(dirname(fileURLToPath(import.meta.url)), "openapi.yaml"), "utf8");
|
const OPENAPI = readFileSync(join(dirname(fileURLToPath(import.meta.url)), "openapi.yaml"), "utf8");
|
||||||
@@ -296,10 +299,46 @@ async function lasBinart(req, tak) {
|
|||||||
return Buffer.concat(bitar);
|
return Buffer.concat(bitar);
|
||||||
}
|
}
|
||||||
|
|
||||||
function nyKod() {
|
// Delningskod. Förkastningsurval i stället för modulo: 256 är inte jämnt
|
||||||
|
// delbart med 36, så `b % 36` gör de fyra första tecknen ~14 % vanligare.
|
||||||
|
// Entropiförlusten är liten, men en snedfördelad kod i en säkerhetsväg är
|
||||||
|
// inte något man vill behöva förklara i en granskning (QUALITET m-1).
|
||||||
|
function nyKod(langd = 16) {
|
||||||
const tecken = "abcdefghijklmnopqrstuvwxyz0123456789";
|
const tecken = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
const { randomBytes } = crypto;
|
const tak = 256 - (256 % tecken.length); // 252 — värden däröver kastas
|
||||||
return Array.from(randomBytes(16), (b) => tecken[b % 36]).join("");
|
const ut = [];
|
||||||
|
while (ut.length < langd) {
|
||||||
|
for (const b of crypto.randomBytes(langd)) {
|
||||||
|
if (b < tak && ut.length < langd) ut.push(tecken[b % tecken.length]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ut.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Avslutsspärren. Läser hela loggen ur databasen, lägger de inkommande
|
||||||
|
* händelserna ovanpå och utvärderar grinden mot det samlade underlaget —
|
||||||
|
* annars skulle ett avslut i samma anrop som evidensen felaktigt nekas.
|
||||||
|
*/
|
||||||
|
async function grindHinder(pool, arendeId, nya) {
|
||||||
|
const rader = await pool.query(
|
||||||
|
`select h.handelse, a.metodik_id from felsokning_handelser h
|
||||||
|
join felsokning_arenden a on a.id = h.arende_id
|
||||||
|
where h.arende_id = $1 order by h.tidpunkt, h.id`,
|
||||||
|
[arendeId],
|
||||||
|
);
|
||||||
|
const handelser = [...rader.rows.map((r) => r.handelse), ...nya.map((p) => p.handelse)];
|
||||||
|
const metodik =
|
||||||
|
ALLA_METODIKER.find((m) => m.id === rader.rows[0]?.metodik_id) ?? ALLA_METODIKER.at(-1);
|
||||||
|
|
||||||
|
let regelpaket;
|
||||||
|
try {
|
||||||
|
regelpaket = JSON.parse(ECM_REGLER);
|
||||||
|
} catch {
|
||||||
|
// Ett trasigt regelpaket får aldrig tolkas som "inga extra krav".
|
||||||
|
return [{ id: "regelpaket", rubrik: "Regelpaketet gick inte att läsa — avslut spärrat." }];
|
||||||
|
}
|
||||||
|
return [...grinda(handelser, metodik), ...grindaArendetyp(handelser, regelpaket)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function kravAuth(req, hemlighet) {
|
function kravAuth(req, hemlighet) {
|
||||||
@@ -1172,17 +1211,41 @@ export function skapaServer() {
|
|||||||
return svara(res, 400, { error: "Ogiltig händelselista." });
|
return svara(res, 400, { error: "Ogiltig händelselista." });
|
||||||
}
|
}
|
||||||
res.spann.spår.antalHandelser = handelser.length;
|
res.spann.spår.antalHandelser = handelser.length;
|
||||||
|
|
||||||
|
// Härkomst och form avgörs här, inte av anroparen. Se
|
||||||
|
// services/gemensam/handelser.mjs och QUALITET C-1/M-3.
|
||||||
|
const attSkriva = [];
|
||||||
for (const post of handelser) {
|
for (const post of handelser) {
|
||||||
if (typeof post?.id !== "string" || !post.tidpunkt || typeof post.anvandare !== "string" || !post.handelse) {
|
const { post: giltig, fel } = tillPost(post, anspr);
|
||||||
return svara(res, 400, { error: "Ogiltig händelse." });
|
if (fel) return svara(res, 400, { error: `Ogiltig händelse: ${fel}` });
|
||||||
|
attSkriva.push(giltig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avslut passerar kvalitetsgrinden på servern. Grinden fanns
|
||||||
|
// tidigare bara i webbläsaren, vilket gjorde hela ECM till ett
|
||||||
|
// råd i stället för en spärr (QUALITET C-2).
|
||||||
|
if (attSkriva.some((p) => p.handelse.typ === "arende_avslutat")) {
|
||||||
|
const hinder = await grindHinder(pool, handelserVag[1], attSkriva);
|
||||||
|
if (hinder.length > 0) {
|
||||||
|
return svara(res, 409, {
|
||||||
|
error: "Ärendet kan inte avslutas — kvalitetsgrinden är inte passerad.",
|
||||||
|
hinder,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const p of attSkriva) {
|
||||||
// Append-only: on conflict do nothing — en befintlig händelse
|
// Append-only: on conflict do nothing — en befintlig händelse
|
||||||
// skrivs aldrig över, och databastriggern stoppar allt annat.
|
// skrivs aldrig över, och databastriggern stoppar allt annat.
|
||||||
await pool.query(
|
// Kollisionen räknas: ett id som redan finns är antingen en
|
||||||
|
// ofarlig omsändning eller ett försök att blockera en framtida
|
||||||
|
// post, och skillnaden syns bara om den mäts (QUALITET m-2).
|
||||||
|
const skrivet = await pool.query(
|
||||||
`insert into felsokning_handelser (id, arende_id, tidpunkt, anvandare, handelse)
|
`insert into felsokning_handelser (id, arende_id, tidpunkt, anvandare, handelse)
|
||||||
values ($1, $2, $3, $4, $5) on conflict (id) do nothing`,
|
values ($1, $2, $3, $4, $5) on conflict (id) do nothing`,
|
||||||
[post.id, handelserVag[1], post.tidpunkt, post.anvandare, post.handelse],
|
[p.id, handelserVag[1], p.tidpunkt, p.anvandare, p.handelse],
|
||||||
);
|
);
|
||||||
|
if (skrivet.rowCount === 0) res.spann.spår.kollisioner = (res.spann.spår.kollisioner ?? 0) + 1;
|
||||||
}
|
}
|
||||||
return svara(res, 200, { ok: true });
|
return svara(res, 200, { ok: true });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user