Objekt Ärendehantering · Alkohol & Tobak

Alkohol och tobak i Draken

En myndighetsprocess byggd på supportspåret. Hur ärendetyp, formulär, fas, process och handläggning hänger ihop – följt genom tre ärenden, i verksamheten och under huven – och hur AoT samsas med Avvikelse i samma kodbas.

Status PoC på feature-branch, ej driftsatt Namespace AOT · 2281 Uppdaterad 2026-09-15

Verksamheten

Alkohol & Tobak beslutar om serveringstillstånd och tillstånd för försäljning av tobak, e-cigaretter och folköl — och utövar tillsyn över att villkoren fortsatt uppfylls.

Arbetet har tre delar. Tillståndsgivning — ansökningar kommer via e-tjänst, men ett stort antal ärenden är fortfarande blanketter eller direktkontakt med handläggare. Lämplighetsprövning — ekonomisk och personlig granskning där kommunen begär yttranden från Polisen, Skatteverket och Kronofogden, och där varje person med betydande inflytande i bolaget måste prövas. Löpande tillsyn — kontroll av att tillståndshavaren fortsatt uppfyller kraven.

Organisation
Under IAF, flyttar 2026 till kommande Samhällsförvaltningen
Målgrupp
Restauranger, krogar, butiker, folkölsförsäljare
Remissinstanser
Polismyndigheten, Skatteverket, Kronofogden, Räddningstjänsten, Miljökontoret, Syna
Tillsyn ovanför
Länsstyrelsen Västernorrland, Folkhälsomyndigheten
Dagens system
OpenE, Alk-T (alkohol), OL2 (tobak), Public 360 (diarium), syna.se
Det ovanliga med AoT

Det här är ett myndighetsärende byggt på supportspåret. Ansökan, utredning, beslut och tillsyn har CaseDatas karaktär — men ett principiellt beslut säger att inga nya drakar byggs i CaseData-miljön. AoT byggs därför på SupportManagement, och myndighetsspårets processtruktur måste bäras över dit. Det är den enskilt viktigaste förutsättningen att förstå.

Systembilden

Fyra applikationer runt ett ärendelager. Ingen av dem integrerar mot någon annan — de skriver och läser i samma namespace.

Katla AoT medborgaren ansöker Business Center medborgaren följer AOT-namespacet support-management-alkt-sprint ärenden · jsonParameters Draken AoT handläggaren PartyAssets tillståndet, efter beslut extern gateway intern gateway via CaseStatus processmotorn
Ingen integration, ett delat namespace. Katla skriver via den externa gatewayen eftersom appen är medborgarvänd; Draken läser och skriver via den interna. Båda når samma instans — gatewayen avgör vem som får anropa, inte vilken data som nås. Business Center hämtar ärendet via CaseStatus för att visa det för sökanden. Tillståndet självt blir en asset i PartyAssets, men först när beslut fattats, och det är processmotorn som skapar den.
ApplikationRepoAnvändareIdentitet uppströms
Katla AoTweb-app-katla-aotMedborgaretype=partyId
Draken AoTweb-app-drakenHandläggaretype=adAccount
Business Centerweb-app-business-centerMedborgare och företagare

Katla loggar in medborgare, inte medarbetare. IdP:n skickar inga roll- eller gruppclaims — bara ett personnummer, som växlas mot ett partyId redan vid inloggning. Det id:t är identiteten i varje efterföljande anrop. Förväxla den inte med web-app-katla-sm, som är färdtjänst och AD-skyddad.

Så hänger delarna ihop

Ärendetypen är navet. Den väljs som en label, och ur den följer vilket formulär sökanden fyller i, vilken process ärendet kör och vilka steg handläggaren går igenom.

Sex begrepp brukar blandas ihop: kategori, ärendetyp, ärendeuppgifter, status, fas och process. De bor på olika ställen och sätts av olika aktörer, men de hänger ihop i en kedja som börjar i labelträdet.

Labelträdet metadata · CATEGORYROOT · TAGROOT JsonSchema aot_{kategori}_{typ}_{subtyp} Ärendet labels[] jsonParameters[] status phases · activePhaseId stakeholders · conversations Processmotorn pw-alkt · alkt-ansokan Fasmodellen metadata/phases · allowedStatuses Handläggningsartefakter investigations · statements decisions · measures PartyAssets tillståndet · validTo Drakens flikar Utredning · Beslut · Uppföljning sökvägen blir schemanamnet · i Katla väljs som labels sparas som jsonParameters attribut processKey händelser aktivitet tillåtna statusar låser upp flikar utredning · yttrande · beslut visas i skapar efter beslut
Ärendetypen är navet. Samma label gör tre saker: den klassificerar ärendet, dess sökväg blir namnet på formuläret Katla visar, och dess attribut processKey avgör vilken process som startar. Fasmodellen står vid sidan av och säger vilka statusar som är tillåtna i varje steg och vilka flikar handläggaren når. De rostfärgade pilarna är kedjan från ärendetypen.
  • Byggt finns i Draken, Katla eller på AoT-grenen
  • På gren byggt i SupportManagement eller hos Avvikelse, inte i bruk för AoT
  • Målbild i verksamhetens skiss, inte byggt
  • Kvar känd lucka
BegreppBor iSätts avStyrLäge
Kategori och ärendetyp errand.labels, trädet under CATEGORYROOT Sökanden i Katla, eller handläggaren i Grundinformation Formulär, process, filter, statistik Byggt
Fri etikett errand.labels under TAGROOT, med classification: "TAG" Handläggaren Filter och statistik Kvaringen yta
Ärendeuppgifter errand.jsonParameters, validerade mot schemat Katla, vid inskick Fliken Ärendeuppgifter, skrivskyddad Byggt
Status errand.status, namespacets statusar Handläggaren Vänstermenyn. Sökanden ser externalDisplayName Byggt
Fas errand.phases, activePhaseId, metadata/phases Handläggaren med fasknappar, eller processen Fasraden, vilka flikar som låses upp, tillåtna statusar På grenAvvikelse
Process errands/{id}/processes, labelns attribut processKey SupportManagement startar, processtjänsten driver Aktiviteter, och tillståndet efter beslut På grenalkt-sprint
Utredning, yttrande, beslut investigations, statements, decisions under ärendet Handläggaren Flikarna Utredning och Beslut På grendraken-4892
Tillstånd PartyAssets Processmotorn, efter beslut Kundbildens Tillstånd, underlag för tillsyn Målbild
Fas och status svarar på olika frågor

Status säger vad som händer med ärendet just nu: inkommet, tilldelat, väntar på komplettering. Fas säger var i processen det befinner sig: granskning, utredning, beslut. Fasmodellen kopplar ihop dem med allowedStatuses, där varje fas anger vilka statusar som är tillåtna. Ett ärende kan alltså vänta på komplettering både under granskning och under utredning.

Vägar in

Ett AoT-ärende kan börja på fem sätt. Två finns i dag, och de ger ärendet olika mycket från start.

Skillnaden märks längre fram. Ett ärende från Katla bär sitt ifyllda formulär, medan ett som registreras manuellt har en tom flik för Ärendeuppgifter. Ett åtgärdsärende har dessutom en koppling tillbaka till tillsynen det kom ur.

Väg inVem startarÄrendet får från startLäge
E-tjänsten Katlasökanden följer sedan ärendet på Mina sidor Sökanden, för sig själv eller för sitt bolag Ärendetypen som labels på alla nivåer, formuläret som jsonParameters, bilagor och sökanden som intressent via partyId. Ingen classification, så ärendet är låst tills handläggaren sparat kategori Byggt
Nytt ärende i Drakenblankett, telefon, besök Handläggaren Förval ur NEW_ERRAND_DEFAULTS. Ärendetypen väljs i Grundinformation. Inga ärendeuppgifter Byggt
Kundbilden”Skapa ärende” vid ett serveringsställe Handläggaren Som Nytt ärende, med ärendeägaren förifylld med bolaget och serveringsstället Målbildsidan är ett tomt skal bakom useCustomerPages
Från en tillsyn”Skapa åtgärdsärende och avsluta tillsynen” Handläggaren, när tillsynen hittat brister Ärendetypen INSPECTION / MEASURES, ärendeägare och ställe från tillsynen, bristerna och en koppling till tillsynsärendet Målbild
Överlämning från Kontakt Sundsvall Handläggare i KS-draken Ärendet flyttas med useHandover. Trädet har typen ERRAND_FROM_KONTAKT_SUNDSVALL för dem MålbildKS behöver AoT som mottagare
Nytt ärende efter sammanslagningen

Nytt ärende förväljer kategori ur NEW_ERRAND_DEFAULTS. På Avvikelse-grenen kastar det uppslaget 502 när sökvägen inte finns i trädet, och AOT/UNCATEGORIZED finns inte under CATEGORYROOT. Förvalet måste pekas mot en verklig sökväg innan grenarna förs samman. Annars slutar manuell registrering att fungera.

Ansökan · Alkohol

Stadigvarande serveringstillstånd

En restaurang ansöker om att få servera alkohol året runt. Det är AoT:s mest omfattande flöde, med lämplighetsprövning av varje person med betydande inflytande, remisser till sex instanser och ett beslut som blir ett tillstånd.

Ärendetyp
CATEGORYROOT/ALCOHOL/SERVING_PERMIT_APPLICATION/PERMANENT_SERVINGAlkohol › Ansökan om serveringstillstånd › Stadigvarande servering
Formulär
aot_alcohol_serving_permit_application_permanent_servingEtt schema per ärendetyp, valt av Katla
Process
alkt-ansokanExempelnyckel ur tjänstens spec. Vilken label som bär den är inte bestämt
Beslutsutfall
Bifall · Bifall med villkor · AvslagUtfallen för en ansökan, inte en anmälan

Varje rad är ett steg i processen. I mitten står det verksamheten gör och ser, till höger det som händer i datat.

FÖREUtkastKatla

Sökanden

Loggar in, väljer att söka för sitt bolag och väljer ärendetyp. Guiden visar formuläret för just stadigvarande servering: verksamhetens inriktning, vilka alkoholdrycker, hur verksamheten finansieras. Bilagor laddas upp i samma flöde, och ett påbörjat utkast kan återupptas.

  • labelsCATEGORY, TYPE och SUBTYPE ur CATEGORYROOT. Utfasade noder erbjuds inte
  • jsonParameters{ key, schemaId, value }. Schemanamnet byggs ur ärendetypens sökväg, och bara den valda typens svar skickas
  • IntressentSökanden via partyId, aldrig personnummer
  • AnropetExtern gateway, X-Sent-By: type=partyId
Byggt
1 / 6RegistreradDraken

Handläggaren

Ärendet dyker upp under Nya ärenden, där tabellen visar den mest specifika ärendetypen. I ärendet syns det ifyllda formuläret under Ärendeuppgifter. Bolagets företrädare och verksamhetsbeskrivning hämtas ur bolagsregistret.

Innan något annat går att göra måste handläggaren spara kategori och typ.

  • StatusNEW, Inkommet
  • ÄrendeuppgifterJsonParametersDisplay hämtar schemat per schemaId och renderar det skrivskyddat
  • Bolagsdata/legalentity/{partyId} och /engagements. BFF:en släpper bara igenom de fält vyn behöver, så funktionärernas personnummer når aldrig webbläsaren
  • LåsetsupportErrandIsEmpty() läser bara classification, som Katla inte sätter
  • ProcessenLabeln med processKey ger startbehörighet på första ärendehändelsen (AUTOMATIC)
ByggtKvar · låsetPå gren · processen
2 / 6GranskningDraken

Handläggaren

Startar handläggningen och blir tilldelad ärendet. Går igenom uppgifter, bilagor och intressenter, markerar vilka personer som har betydande inflytande och begär komplettering om något saknas.

Sökanden

Ser att handläggning pågår och svarar på kompletteringen på Mina sidor.

  • FasbytePATCH …/phase sätter activePhaseId. Fashistoriken läses ur phases
  • StatusASSIGNED, sedan PENDING vid komplettering. Båda måste finnas i fasens allowedStatuses
  • Sökanden serexternalDisplayName, till exempel ”Handläggning pågår”
  • KompletteringenEn EXTERNAL-konversation som Business Center visar. Kräver AOT i namespace-whitelisten
  • PBIRoller på intressenterna, useRolesForStakeholders
På gren · fasbyteKvar · whitelistMålbild · PBI
3 / 6UtredningDraken

Handläggaren

Lämplighetsprövningen. Vandeln prövas för varje person med betydande inflytande, kunskapsprov bokas och rättas, och ekonomi och lokal granskas.

Remisser går till Polisen, Skatteverket, Kronofogden, Räddningstjänsten, Miljökontoret och Syna, med påminnelse om svaret dröjer. Utredningen slutar i ett förslag till beslut: Tillstyrker, Tillstyrker med villkor, Ingen erinran eller Avstyrker.

  • UtredningenPOST …/investigations med investigatorUserId och status: ACTIVE
  • PrövningarnaEn sektion per prövning, med assessment PENDING, APPROVED, DEFICIENCY eller NOT_APPLICABLE. Resultat per person som JSON-parameter på sektionen
  • RemissernaEn statement per instans: sentAt, remindedAt, respondedAt. Skissens Skapad → Skickad → Påmind → Svar inkommet är samma livscykel
  • Förslagetrecommendation ska vara ett av namespacets beslutsutfall. Skissens fyra förslag passar inte in utan vidare
  • I DrakenUtredningsfliken kommer från AoT-varianten i sömmen. Den är i dag en platshållare
På gren · modellenMålbild · gränssnittet
4 / 6BeslutDraken

Beslutsfattaren

Den som delegationsordningen pekar ut fattar beslutet: handläggare, utskottet, nämndsordföranden eller nämnden. Utfallet blir Bifall med villkor, och villkoren skrivs in rad för rad. Beslutet skickas till sökanden.

  • BeslutetPOST …/decisions med outcome, method: MANUAL och vem som beslutade
  • Villkorenterms, numrerade rader med kategori
  • UtfallenRegistreras per namespace under metadata/decisionoutcomes. Ansökan och anmälan behöver olika uppsättningar
  • OmprövningsingleDecisionPerErrand: false, eftersom beslutet kan överklagas och omprövas
  • BeslutsdokumentetBilaga med syftet DECISION
På gren · modellenMålbild · Beslutsfliken
5 / 6Uppföljningefter beslut

Verksamheten

Tillståndet börjar gälla. Beslutsbeviset går ut, avgiften faktureras och tillståndet syns i kundbilden under Tillstånd. Löpande tillsyn av att villkoren följs blir egna tillsynsärenden.

  • TillståndetProcessmotorn skapar det som asset i PartyAssets. Varken Draken eller Katla gör det
  • AssetenvalidTo för giltighetstiden, villkoren som jsonParameters
  • ProcessenErrandProcess rapporterar aktiviteten tillbaka till ärendet
Målbild
6 / 6AvslutDraken

Handläggaren

Avslutar ärendet. Sökanden ser beslutet och att ärendet är avslutat på Mina sidor.

  • StatusSOLVED. resolution är fri text för tjänsten
  • ProcessenprocessStatus: COMPLETED
Byggt · avslutaPå gren · processen

Tillsyn

Tillsyn av ett serveringsställe

Kommunen kontrollerar att en restaurang följer villkoren i sitt tillstånd. Ärendet har ingen sökande och inget formulär. Handläggaren startar det, och det kan sluta på tre sätt.

Ärendetyp
CATEGORYROOT/INSPECTION/INSPECTIONTilllsyn › Tillsyn. Stavfelet finns i datan
Etiketter
TAGROOT/EXTERNAL_INSPECTION
TAGROOT/ALCOHOL_INSPECTIONFlera per ärende: yttre tillsyn av alkoholservering
Formulär
ingetKatla har inget schema för tillsyn, och sökanden är kommunen själv
Process
ej bestämdManuell start är det rimliga. Öppen fråga
1 / 6RegistreradKundbilden

Handläggaren

Öppnar bolaget i kundbilden, väljer serveringsstället och skapar ett ärende därifrån. Ärendeägaren fylls i med bolaget och stället. Vad tillsynen gäller sätts som etiketter: yttre tillsyn, alkoholtillsyn.

  • labelsINSPECTION / INSPECTION ur kategoriträdet, plus etiketter ur TAGROOT
  • EtiketternaBehålls när ärendet sparas, men går inte att sätta i dag
  • ÄrendeuppgifterTomma, eftersom ingen e-tjänst har skrivit något
Målbild · kundbildenKvar · etikettyta
2 / 6Granskningförberedelse

Handläggaren

Förbereder tillsynen: väljer protokollmall för servering, folköl, tobak eller nikotin, anger vilka tillstånd som ingår och vilka myndigheter som medverkar.

  • UtredningenSkapas som utkast, status: DRAFT, med en typ registrerad för tillsyn
  • ProtokolletEn sektion per kontrollpunkt i mallen. sectionKey är stabil över tid, så punkterna går att jämföra mellan tillsyner
  • Tillstånd och myndigheterJSON-parameter på utredningen
På gren · modellen
3 / 6Utredningtillsynsbesöket

Handläggaren

Gör tillsynsbesöket. Varje kontrollpunkt i protokollet bedöms som Godkänt, Brist eller Ej aktuellt, med noteringar.

  • Bedömningenassessment på sektionen: APPROVED, DEFICIENCY, NOT_APPLICABLE. Skissens tre värden, plus PENDING för ej bedömd
  • Vem och närcompletedBy, completedAt
  • StatistikBedömningen är det enda strukturerade fältet, så antalet brister går att räkna över alla tillsyner
På gren · modellen
4 / 6Utfalltre vägar ut

Handläggaren

  • Avsluta utan anmärkningInga brister.
  • Skapa åtgärdsärende och avsluta tillsynenBrister som kunden ska rätta. Se nästa ärende.
  • Starta tillsynsutredningAllvarliga brister. Leder till ett eget beslut under fliken Beslut.
  • Utan anmärkningUtredningen COMPLETED, ärendet SOLVED. Inget beslut
  • ÅtgärdsärendeNytt ärende INSPECTION / MEASURES, kopplat via Relation. Tillsynen SOLVED
  • TillsynsutredningUtredningen fortsätter och slutar i en decision. En återkallelse gör asseten BLOCKED med statusReason
På gren · modellenMålbild · flödet
5 / 6Uppföljningkundbilden

Verksamheten

Serveringsställets senaste tillsyn uppdateras och syns i kundbilden inför nästa planering.

  • Senaste tillsynVar datumet lagras är inte bestämt. Det kan ligga på asseten, i ett register eller härledas ur ärendena
Kvar · öppen fråga

Uppföljning efter tillsyn

Åtgärdsärende

Tillsynen hittade brister som kunden ska rätta. Åtgärdsärendet bär kraven ut till kunden och följer upp dem ett i taget, och det pekar hela tiden tillbaka på tillsynen det kom ur.

Ärendetyp
CATEGORYROOT/INSPECTION/MEASURESTilllsyn › Åtgärder
Kommer från
tillsynsärendetKopplat i båda riktningar
Startar i
GranskningRegistreringen är redan gjord i tillsynen
Kunden ser
Mina sidorKraven skickas som meddelande på ärendet
SKAPASFrån tillsynenDraken

Handläggaren

Skriver en rubrik och listar bristerna, minst en. Ärendet skapas med samma ärendeägare och serveringsställe, och kunden får ett meddelande.

  • ÄrendetNytt ärende med INSPECTION / MEASURES, samma intressent och partyId som tillsynen
  • KopplingenEn relation från tillsynsärendet, som syns under Kopplade ärenden i båda
  • MeddelandetEXTERNAL-konversation till Mina sidor. Kräver AOT i whitelisten
MålbildKvar · whitelist
2 / 6GranskningMina sidor

Kunden

Ser kraven, rättar bristerna och svarar med underlag, till exempel ett nytt egenkontrollprogram.

  • SvaretMeddelande i samma konversation
  • UnderlagetBilaga med channel: MY_PAGES och syftet RESPONSE
Målbild
5 / 6UppföljningDraken

Handläggaren

Går igenom svaret och skriver av bristerna en i taget.

  • BristernaEn measure per brist, med title, dueAt, status ACTIVECOMPLETED samt result och resultText
  • GränssnittetAvvikelse har byggt flikarna Åtgärder och Uppföljning bakom useMeasures
På gren
6 / 6AvslutDraken

Handläggaren

Avslutar ärendet när alla brister är avskrivna. Kopplingen till tillsynen står kvar i båda ärendena.

  • StatusSOLVED
  • KopplingenKopplade ärenden, useRelations
Byggt

Två verksamheter, en kodbas

Avvikelse och Alkohol & Tobak bygger båda myndighetsprocess ovanpå samma SupportManagement och samma Draken, samtidigt. Överlappet sitter i utredning, beslut och faser.

Avvikelsehanteringen, IAF och VOF med lex Sarah och HSL-avvikelser, har kommit längre. Dess gren ska in i develop först, och AoT-grenen förs in ovanpå och anpassar sig. Utvecklarna har en regel som styr resten:

Vi kan inte blanda investigation på flera ställen.

Utvecklare i Draken-teamet, om utredning i errand.investigation och errand.jsonParameters

Var utredningen lagras

I dag lagrar Avvikelse sin utredning och sitt beslut som JSON-dokument i jsonParameters, bredvid den inkomna avvikelsen. AoT har ingen utredning ännu. SupportManagement bygger nu en gemensam handläggningsmodell där utredning, yttrande och beslut är egna resurser på ärendet, med verksamhetens detaljer som JSON inuti dem.

I DAG MÅLBILD · SUPPORTMANAGEMENT DRAKEN-4892 Avvikelse-ärende IAF · VOF jsonParameters inkommen avvikelse utredning-hsl beslut-hsl investigations · decisions används inte AoT-ärende AOT jsonParameters aot_alcohol_serving_… utredning · beslut finns inte ännu Avvikelse-ärende IAF · VOF jsonParameters inkommen avvikelse investigations utredning decisions beslut · lex Sarah, IVO AoT-ärende AOT jsonParameters aot_alcohol_serving_… investigations utredning + sektioner statements sex remisser decisions beslut + villkor
Samma fack för båda verksamheterna. Rostfärgat är det som flyttar eller tillkommer. I målbilden bär jsonParameters bara det som kom in. Utredning, yttrande och beslut blir egna resurser med livscykeln DRAFTACTIVECOMPLETED, och skillnaden mellan verksamheterna ligger i typer och utfall som registreras per namespace, inte i var datan hamnar. Om och när Avvikelse flyttar är deras beslut, och det ska synkas med AoT. AoT har inget att flytta och ska börja direkt i den nya modellen.

Sömmen i Draken

Avvikelse-grenen har redan byggt den struktur AoT ska in i. Utredningsfliken är en söm: delad kod frågar ett register efter en variant, och varje verksamhet är en egen modul bakom en egen flagga. En AoT-variant finns redan där, som platshållare.

Flikomslaget delad kod useInvestigation = huvudströmbrytare Registret första påslagna flaggan vinner avvikelse/ useAvvikelseInvestigation aot/ useAotInvestigation · platshållare vilken variant? flagga på flagga på inga importer
Delad kod frågar vilken funktion som är påslagen, aldrig vilken app som kör. Registret är det enda stället som känner till implementationerna. AoT-varianten fyller bara de obligatoriska delarna och lämnar Grundinformations vanliga kategorisering orörd, så AoT ser ut som vilken drake som helst tills utredningen byggs.
  • Inga importer mellan aot/ och avvikelse/. Ett kontraktstest bygger två varianter utan att röra avvikelsekoden och slutar kompilera om kontraktet får ett beroende.
  • Utredningslogik grenar aldrig på applikation – inte på NEXT_PUBLIC_APPLICATION och inte på isAOT().
  • Fliken väljs på flagga, inte på profilstatus. AoT har ingen utredningsprofil i BFF:en och skulle annars försvinna tyst.
  • Ändras delad kod körs både vof- och aot-sviten. ”Skipped” betyder fel dev-server, inte godkänt.

Samma problem, två lösningar

ProblemAoT-grenenAvvikelse-grenenVälj
Peka mot sprint-API:etFältet service i APIS, globalt för alla drakarSUPPORTMANAGEMENT_API_TARGET per drakeAvvikelses, som också löser att versionen är global
Utredning, beslut, uppföljningTre egna flikar och tre flaggorVariantsömmen med fasgrindSömmen
FaserHårdkodad mappning från statusFasmodellen ur namespacets metadataFasmodellen
Frontend-testerIngaVitest, och e2e för både vof och aotAvvikelses

När grenarna förs samman

En simulerad sammanslagning, utan att röra grenarna, ger en konflikt när Avvikelse går in i develop och 23 filer i konflikt när AoT läggs ovanpå. Grundorsaken är att Avvikelse redan har byggt AoT:s env-filer, skript och testprojekt på sitt eget sätt. De farligaste felen är ändå de som slås samman utan konflikt:

FällaVad som händerGör så här
Dubbla flikarBåda grenarnas Utredning- och Beslutsflikar finns kvar med samma nycklar, så AoT får två Utredningsflikar och flikvalet går sönder. CI märker inget, eftersom matrisen inte sätter AoT:s flikflaggorStryk AoT:s tre flikflaggor och flikfiler. AoT-varianten tar över
Två fasraderuseUiPhases är en statusmappning på AoT-grenen men fasmodellen hos Avvikelse, där flaggan också byter sidopanelens knapparLägg in faser i AOT-namespacet och använd Avvikelses fasflöde
MetadatafiltretAoT:s rotnodsfilter ligger i den delade metadata-controllern och ger 502 för ett träd med ROOT-noder utan exakt en CATEGORYROOTProva mot IAF:s och VOF:s träd, eller begränsa filtret till AOT
ÄrendeuppgifterAoT-grenen visar alla jsonParameters. Avvikelse filtrerar bort utredningsdokument användaren inte får läsaBehåll filtret och lägg bolagsblocket ovanpå
RadslutOmkring 45 filer på Avvikelse-grenen har CRLF. Fem av dem blir helfilskonflikterNormalisera till LF innan Avvikelse förs in

Hela konfliktlistan med lösning per fil, och checklistan i elva steg, finns i Draken-skillen under references/flera-namespace.md.

Vad som är uppsatt

Uppsättningen berör fyra lager. Tre av dem ligger utanför repot, och det är där de flesta blockeringarna har suttit.

LagerVadLäge
Namespace namespace-config med shortCode: AOT — ärendenummer blir AOT-{yyMM}{NNNN} Klart
Metadata Sju statusar, och labelträdet med två rotnoder: CATEGORYROOT för ärendetyperna och TAGROOT för fria etiketter Klart
WSO2 Två applikationer: katla-aot på externa gatewayen, Draken-appen på den interna Klart
Draken Env-filer, byggskript, isAOT(), NEW_ERRAND_DEFAULTS, ResolutionLabelAOT Klart
Katla Registreringsguide med företagsväljare, ärendetyp ur CATEGORYROOT och ett formulär per ärendetyp Klart
Kategorisering i Draken Trenivåkontrollen påslagen. BFF:en skickar bara underträdet under CATEGORYROOT, och fria etiketter behålls vid sparning Klart
Bolagsdata Förenklad bolagsdata och verksamhetsbeskrivning ur LegalEntity, med genererade typer och persondata bortfiltrerad i BFF:en Klart
Utredning, remiss, beslut Handläggningsmodellen i SupportManagement, grenen draken-4892. I Draken en platshållare i utredningssömmen På gren
Processmotorn ErrandProcess och processnyckel ur labels i SupportManagement, grenen alkt-sprint På gren
Business Center AOT i namespace-whitelisten caseIsAllowed — annat repo, egen driftsättning Ej gjort
Två saker som stoppar helt om de saknas

Utan namespace-config svarar ärendelistan 404, inte tom lista — åtkomstkontrollen måste läsa konfigurationen innan den kan filtrera. Utan statusar i metadatan avvisas ärendeskapandet med 400, eftersom status valideras mot namespacets metadata. Båda felen ser ut som fel i Draken men är det inte.

Utöver det: utan en kategori får ärendet ingen klassificering, och då är supportErrandIsEmpty() sant för ärendets hela livstid. Det låser flikarna, avsluta-knappen och tilldelningen. Ett ärende som ser halvfärdigt ut i gränssnittet beror nästan alltid på det.

Sprint-API:et är tillfälligt

AoT går mot support-management-alkt-sprint/15.3 i stället för ordinarie supportmanagement. Det är ett eget API-namn i WSO2, inte bara en annan version, vilket krävde ett service-fält i Drakens APIS som skiljer uppslagsnyckeln från URL-segmentet.

Versionen i APIS är global, så alla elva drakar går mot sprint-klonen så länge det står kvar. Det är försvarbart bara för att branchen är en PoC som aldrig driftsätts. När sprint-instansens ändringar synkats in i ordinarie SupportManagement blir det en vanlig versionsbump och service-fältet utgår.

Hur ärendet klassificeras

Två träd i samma struktur: ett för vad ärendet är, ett för fria etiketter man sätter flera av. Båda ligger inlagda, och sedan DRAKEN-4895 läser Draken kategoriträdet rätt.

Klassificeringen bärs av labels — plattformsteamets besked är att det är den mekanismen som gäller nu, oavsett om verksamheten behöver två nivåer eller tre. Den äldre categories + types-strukturen lever kvar i drakar som ännu inte migrerat; nya drakar sätts upp med labels.

KategoriÄrendetypUnderkategori
ALCOHOL SERVING_PERMIT_APPLICATION PERMANENT_SERVING · TEMPORARY_SERVING_PUBLIC · TEMPORARY_SERVING_PRIVATE · FARM_SALES · PERMANENT_CATERING · TASTING
SERVING_PERMIT_CHANGE
SERVING_PERMIT_ADDITION
FOLKOL_SERVING_NOTIFICATION
FOLKOL_SALES_NOTIFICATION
TOBACCO SALES_PERMIT_APPLICATION
SALES_PERMIT_CHANGE
SALES_PERMIT_TERMINATION
ECIGARETTE_SALES_NOTIFICATION
TOBACCO_FREE_NICOTINE_SALES_NOTIFICATION
INSPECTION INSPECTION
MEASURES
DOCUMENTATION DOCUMENTATION
COMPLIANCE_TIP
ERRAND_FROM_KONTAKT_SUNDSVALL

Underkategorierna finns av en enda anledning. Stadigvarande servering, tillfälligt tillstånd till allmänheten, tillfälligt till slutet sällskap, gårdsförsäljning och catering till slutna sällskap är fem separata e-tjänster i OpenE som alla landar i samma ärendetyp. Tredje nivån är det som skiljer dem åt när de väl kommit in.

Tillsyn blev en egen kategori, och etiketter vid sidan av. Alkohol- och tobakstillsyn låg först som ärendetyper under Alkohol respektive Tobak. Nu är kategoriseringen en enda INSPECTION med typerna INSPECTION och MEASURES, medan vad tillsynen gällde uttrycks med fria etiketter.

Det andra trädet: fria etiketter

Strukturen har två rotnoder, båda med classification: "ROOT". Den ena bär ärendekategoriseringen, den andra etiketter som sätts flera per ärende — ungefär som etiketter i Jira.

CATEGORYROOT
Kategori-rot — Alkohol, Tobak, Tillsyn, Dokumentation
TAGROOT
Etikett-rot — Inre tillsyn, Yttre tillsyn, Alkoholtillsyn, Tobakstillsyn. Bär classification: "TAG"

Det löser en fråga som stått öppen: inre kontra yttre tillsyn behövde varken bli en tredje nivå eller en egen ärendetyp. Ett tillsynsärende klassificeras som tillsyn och taggas sedan med vad det gällde och hur det gick till.

Skissen och trädet är inte samma modell

Modellerna har närmat sig varandra: tillsyn är nu en egen kategori i trädet, och åtgärdsärende finns som typen MEASURES under den. Kvar skiljer sig två saker — Överklagan är en egen grupp i skissen men saknas i trädet, och Dokumentation är en kategori i trädet men saknas i skissen. Skissen plattar dessutom ut tredje nivån: stadigvarande och tillfälliga tillstånd är egna ärendetyper där trädet har dem som underkategorier.

Vad tjänsten tillåter, och vad Draken klarar

Label-noden har inget fast nivåbegrepp. classification är en fri sträng med enda kravet att den inte är tom — ingen enum. Plattformsteamet: "man kan skapa hur många nivåer som helst med vilka classification-värden ni vill, utan kodändringar från vår sida."

classification
Fri sträng. Nodens nivå, i praktiken CATEGORY / TYPE / SUBTYPE
resourceName
Nodens eget namn, versaler och understreck
resourcePath
Read-only, sätts av tjänsten. Inte garanterat kedjan av namnen ovanför
attributes
Fri nyckel/värde. Bär bland annat funktionsbrevlådan
deprecated
Får inte väljas, men får finnas kvar

För AoT valdes samma lösning som avvikelsehanteringen använder: ärendekategoriseringen ligger under en rotnod, så att andra rotnoder kan bära labels för helt andra syften — statistik, taggning av myndigheter, inre kontra yttre tillsyn. Rotnoden är en markör som säger "allt under mig är ärendetyper". Trädet ovan ligger i AOT-namespacet under CATEGORYROOT.

SOM TRÄDET SER UT I DAG labelStructure Alkohol CATEGORY Tobak CATEGORY Ärendetyper TYPE Draken läser toppnivån som kategori. Det stämmer. MED EN ROTNOD OVANFÖR labelStructure Ärendekategorisering läses som CATEGORY Statistik annan rotnod Alkohol blir TYPE Allt förskjuts ett steg. Ärendetyperna hamnar utanför.
Rotnoderna är inte gratis — och de är redan lagda. ThreeLevelCategorization.tsx hårdkodar de tre nivåerna och tar toppnivån i labelStructure som kategori, rakt av. Med två rotnoder på plats blir Kategori-rot och Etikett-rot de enda valbara verksamheterna, Alkohol, Tobak, Tillsyn och Dokumentation blir ärendetyper, och underkategorierna faller utanför modellen. Det är precis den inbyggda treställighet plattformsteamet varnar för: tjänsten är agnostisk, konsumenterna är det inte. Löst på AoT-grenen: BFF:en skickar bara underträdet under CATEGORYROOT, så trenivåkontrollen ser Alkohol, Tobak, Tillsyn och Dokumentation som kategorier igen.

Kedjan som låste varje inkommet ärende

Ett ärende bär två klassificeringar. Draken skriver båda när en handläggare klassificerar: labels med de valda noderna, och samtidigt classification med samma värden i den äldre tvåfältsmodellen. Det är bakåtkompatibilitet — men supportErrandIsEmpty() tittar bara på classification, aldrig på labels.

Katla skickar labels men ingen classification. Verkliga ärenden i AOT har classification: {}. Fem fel hakade i varandra, och tre av dem är lösta:

LedVad som händerLäge
Katlas etikettSkickade UNCATEGORIZED, som är utfasad och ligger utanför CATEGORYROOT. Nu väljer sökanden ärendetyp ur trädet, och utfasade noder erbjuds inteLöst
Ingen classificationKatla sätter den inte, och tjänsten kräver den inteKvar
Draken låserTomt ärende: flikarna utom den första, tilldelning, avsluta, pausa, återuppta och vidarebefordra är alla inaktiverade tills handläggaren sparat kategoriKvar
Ingen väg ut.env.aot saknade kategoriseringsflaggorna, och trenivåflaggan föll på rotnoderna. Nu är flaggan på och BFF:en filtrerar till CATEGORYROOT, så handläggaren kan klassificera och därmed låsa upp ärendetLöst
Etikett läses som kategoriDe fria etiketterna hade classification: "CATEGORY", precis som de riktiga kategorierna. Nu bär de "TAG", och Draken behåller dem när ärendet sparasLöst

Kvar är beslutet om classification. Antingen sätter Katla den, eller så slutar Draken grunda låsningen på den. Det senare är rimligare på sikt, men rör delad kod och alla drakar. BFF-filtret ligger dessutom i den delade metadata-controllern och måste provas mot Avvikelses labelträd innan grenarna förs samman, se Två verksamheter, en kodbas.

Djupet styr åtkomsten — men inte hos oss, än

I namespaces med åtkomstkontroll är ärendets access labels trädets lövnoder: tjänsten räknar bort varje label vars sökväg är prefix till en annan vald. Behörigheterna matchas sedan som Ant-mönster mot sökvägen, och NS/A/* täcker bara en nivå. En fjärde nivå gör alltså att en användare som var beviljad NS/A/* plötsligt inte når ärendet — det löses med ** i AccessMapper, inte med kod. AoT använder inte AccessMapper, inte initialt, men det är värt att veta innan trädet växer.

Ett fel i underlaget

Confluence-tabellen ger "Ansökan om försäljning av tobaksvaror" samma techname som avslutsraden, SALES_PERMIT_TERMINATION. Rätt värde enligt tråden är SALES_PERMIT_APPLICATION. Dubbletten behöver rättas i Confluence innan någon sätter upp trädet efter tabellen.

Ansökningsdata

Serveringsyta, öppettider, egenkontrollprogram, uppgifter om varje person med betydande inflytande — inget av det har någon plats i den gemensamma ärendemodellen.

Lösningen är jsonParameters: fri JSON på ärendet, validerad mot ett registrerat JSON Schema. Katla skriver dem, Draken visar dem skrivskyddat under Ärendeuppgifter. Ett schema definierar formuläret i båda ändar, så en ny blankett kräver inget nytt gränssnitt.

JsonSchema-tjänsten 2281_namn_version Katla medborgaren fyller i Ärendet jsonParameters[] key · schemaId · value Draken handläggaren läser definierar formuläret renderar samma schema skriver valideras läser
Ett schema, två ändar. Vid skrivning validerar ärendetjänsten värdet mot schemat — bryter det mot definitionen blir det 400 med schemats eget felmeddelande. Schema-id:t är {municipalityId}_{namn}_{version} och immutabelt: en ändrad blankett blir en ny version, och redan inskickade ansökningar fortsätter renderas med den version de fylldes i med.

Vem äger vad

AktörRoll
API-teametÄger schemat. Registrerar det i JsonSchema-tjänsten
KatlaSkriver parametrarna vid registrering. Formuläret väljs ur ärendetypen, aot_{kategori}_{typ}_{subtyp} i gemener — ingen kod per schema
DrakenLäser och renderar skrivskyddat, bakom flaggan useDetailsTab

Schemaregistret är delat mellan gatewayerna — samma instans bakom både den externa och den interna — så ett schema registrerat från endera sidan syns för båda.

Luckan

Draken renderar parametrarna skrivskyddat. Behöver en handläggare rätta en uppgift under utredningen finns ingen yta för det, trots att API:et stödjer skrivning med If-Match mot parameterns version. För en process som pågår i månader och där uppgifter kompletteras längs vägen är det en fråga som behöver besvaras tidigt.

Processen framåt

Myndighetsspårets processtruktur ska bäras över till SupportManagement. Sju steg, där Utkast tillkommer i och med registreringsgränssnittet.

MEDBORGAREN SER Utkast Inskickat Handläggning pågår Avslutat Utkast Registrering Granskning Utredning Beslut Uppföljning Avslut STATUSAR SOM SAKNAS I DAG DRAFT Granska Utreda Remiss
Remiss är AoT:s egen. Statusen motsvarar precis yttrandena från Polisen, Skatteverket och Kronofogden — den enda av de nya som är driven av just den här verksamheten. Stegen Beslut, Uppföljning och Avslut är ännu inte specificerade i underlaget.

Vad verksamhetens skiss lägger till

Projektledaren har tillsammans med administratörerna som ska arbeta i draken tagit fram en interaktiv skiss av hela handläggargränssnittet. Den bekräftar processen ovan — sex steg, utan Utkast, eftersom det steget hör hemma i Katla. Och den mappar faser till flikar: utredning, beslut och uppföljning är varsin flik som låses upp när ärendet når fasen. Det är ett argument för att realisera processen med tjänstens fasmodell snarare än som statusgrupper.

Skissen fyller också i de steg processdokumentet lämnade öppna. Beslut fattas enligt delegationsordning — handläggare, utskott, nämndsordförande eller nämnd. Verkställande ger ett beslutsbevis och skapar tillståndet som asset. Uppföljning är tillsyn av att villkoren fortsatt uppfylls. Överklagande är ett eget ärende.

Utfallen är inte längre en gissning

SammanhangUtfall
Beslut på ansökanBifall · Bifall med villkor · Avslag
Beslut på anmälanRegistrera · Förelägg om komplettering
Utredningens förslagTillstyrker · Tillstyrker med villkor · Ingen erinran · Avstyrker

Att utfallen skiljer sig mellan ansökan och anmälan är nytt för Draken. Varje ärendetyp i skissen bär en axel — ansokan eller anmalan — och det är den som avgör vilka koder som erbjuds. Utredningens förslag är dessutom ett eget fält, satt innan beslutet fattas, inte en lösningskod.

Tre flöden som inte finns i Draken alls

  • Tillsyn — protokoll ur fyra mallar (servering, folköl, tobak, nikotin), tillsynsbesök, och tre vägar ut: avsluta utan anmärkning, skapa åtgärdsärende, eller starta en tillsynsutredning som leder till eget beslut. Med egna avsnitt för medverkande myndigheter och för vilka tillstånd som ingår.
  • Åtgärdsärende — uppföljning av krav efter tillsyn, skapat från tillsynsärendet. Förutsätter ärendekopplingar i båda riktningarna.
  • Överklagan — omprövning enligt 38 § förvaltningslagen, rättidsprövning enligt 45 §, överlämnande till överinstans enligt 46 §, och verkställande.

Därtill förutsätter kundbilden uppslag Draken inte har: bolagsordning, styrelse och ägare, aktuella fullmakter, serveringsställen per bolag, ärenden i externa system och ärenden i andra drakar. Plus fakturering som egen sektion och PDF-export av ärendet.

Byggt men oanvänt

SupportManagement har redan en fasmodell: faser med inbördes ordning och tillåtna statusar per fas, explicita övergångar, samt fashistorik och aktiv fas på ärendet. Statusarna har dessutom ett separat externalDisplayName för det medborgaren ska se. Draken använder ingenting av det — useUiPhases ritar bara en fasrad utan koppling till API:et. Processen behöver alltså inte modelleras från grunden.

Utredning och beslut får egna bärare. SupportManagement-grenen draken-4892 bygger investigations, statements och decisions som underresurser på ärendet, och alkt-sprint bygger processmotorn. Hur de används visas i de tre ärendena.

Dyrköpta lärdomar

Sju fel som kostade tid under uppsättningen. Gemensamt för de flesta: symptomet pekar på fel ställe.

SymptomVerklig orsak
Allt mot gatewayen ger 500, tokenet är färskt WSO2-tokenet delas med Swagger. Hämtar du token där med samma klientnycklar blir backendens cachade token ogiltigt — i upp till en timme
Utloggad ur Draken när du loggar in i Katla Båda apparna hette connect.sid. Kakor isoleras inte per port på localhost
Inloggningen dör tyst efter GET /saml/login SAML_IDP_PUBLIC_CERT lämnad som platshållare — assertionen kan inte verifieras
Ärendelistan ger 404 fast ärenden finns namespace-config saknas. Åtkomstkontrollen läser den innan den filtrerar
Ärendeuppgiftsfliken är tom, inget felmeddelande Drakens WSO2-app saknar jsonschema-prenumeration. Komponenten returnerar null vid fel
Formuläret visar gamla fält efter schemaändring Schema-id är namn plus version och immutabelt. Samma namn och version skapar ingenting nytt
Ärendet ser halvfärdigt ut, flikar låsta supportErrandIsEmpty() grundas på classification, inte på labels. Ett ärende från en e-tjänst som bara sätter labels är därför alltid "tomt"

Mönstret är värt att internalisera: när något ser trasigt ut i Draken ligger orsaken oftast i konfiguration utanför repot — namespace, metadata, WSO2-prenumerationer. Koden är sällan felet.

Öppna frågor

  1. När landar handläggningsmodellen? investigations, statements och decisions finns på SupportManagement-grenen draken-4892, som bygger på main och inte på AoT:s sprintgren. Utredningen kan inte byggas förrän modellen finns på support-management-alkt-sprint.
  2. Förslag till beslut kontra beslutsutfall. Modellens recommendation ska vara ett av namespacets beslutsutfall. Skissens förslag – Tillstyrker, Tillstyrker med villkor, Ingen erinran, Avstyrker – är en annan vokabulär.
  3. Utfall per ärendetyp. Utfallen registreras per namespace, men en ansökan och en anmälan ska erbjuda olika uppsättningar. Något behöver avgöra vilka som visas för vilket ärende.
  4. Vad Uppföljning betyder. För Avvikelse är det uppföljning av åtgärder bakom useMeasures. För AoT är det tillsyn av att tillståndets villkor följs. Samma flik, eller två?
  5. Processnyckeln. Vilka labels i AOT-trädet ska bära processKey, och med vilken startmod? Ansökningar kan rimligen starta automatiskt, tillsyn och åtgärdsärende manuellt.
  6. Faser i AOT-namespacet. Fasraden, fasgrinden för flikarna och Avvikelses fasknappar förutsätter att namespacet har faser med tillåtna statusar.
  7. Var classification ska sättas. Antingen börjar Katla sätta den, eller så slutar Draken grunda låsningen av ärendet på den. Det senare är riktigare när draken kör på labels, men ändringen träffar alla drakar.
  8. Ytan för fria etiketter. Etiketterna under TAGROOT behålls när ärendet sparas, men de går varken att sätta, visa eller filtrera på.
  9. Var senaste tillsyn lagras. Kundbilden visar den per serveringsställe, men ingen bärare är bestämd.
  10. Alk-T och OL2. Dagens handläggningssystem för alkohol respektive tobak – ersätts de, speglas de, eller samexisterar de med Draken?
  11. Diarieföring i Public 360. Allt ska diarieföras oavsett delegationsordning. Ingen sådan integration finns i Draken.
  12. Redigering av ansökningsdata. Ska handläggaren kunna rätta uppgifter under utredningen? API:et stödjer det, gränssnittet inte.
  13. Ansökan som privatperson. Egen ärendetyp, eller samma process där partyId skiljer sökandena åt?

Sammanställt under uppsättningen av AoT-draken, augusti–september 2026. Bygger på verksamhetsdokumentationen för Objekt Ärendehantering, källkoden i web-app-draken, web-app-katla-aot, web-app-business-center och api-service-support-management med grenarna alkt-sprint, avvikelse-sprint och draken-4892, Avvikelse-grenen feature/utvecklingssprint-start, verksamhetens UI-skiss, samt verifiering direkt mot API:erna i testmiljön. Beskriver nuläget där inget annat anges; avsnitt märkta som målbild är under arbete och inte byggda. Fristående kopia av artefakten, version 6, 2026-09-15.