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 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.
| Applikation | Repo | Användare | Identitet uppströms |
|---|---|---|---|
| Katla AoT | web-app-katla-aot | Medborgare | type=partyId |
| Draken AoT | web-app-draken | Handläggare | type=adAccount |
| Business Center | web-app-business-center | Medborgare 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.
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
| Begrepp | Bor i | Sätts av | Styr | Lä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 |
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 in | Vem startar | Ärendet får från start | Lä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 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.
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.
- labels
CATEGORY,TYPEochSUBTYPEurCATEGORYROOT. 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
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.
- Status
NEW, Inkommet - Ärendeuppgifter
JsonParametersDisplayhämtar schemat perschemaIdoch 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åset
supportErrandIsEmpty()läser baraclassification, som Katla inte sätter - ProcessenLabeln med
processKeyger startbehörighet på första ärendehändelsen (AUTOMATIC)
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.
- Fasbyte
PATCH …/phasesätteractivePhaseId. Fashistoriken läses urphases - Status
ASSIGNED, sedanPENDINGvid komplettering. Båda måste finnas i fasensallowedStatuses - Sökanden ser
externalDisplayName, till exempel ”Handläggning pågår” - KompletteringenEn
EXTERNAL-konversation som Business Center visar. Kräver AOT i namespace-whitelisten - PBIRoller på intressenterna,
useRolesForStakeholders
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.
- Utredningen
POST …/investigationsmedinvestigatorUserIdochstatus: ACTIVE - PrövningarnaEn sektion per prövning, med
assessmentPENDING,APPROVED,DEFICIENCYellerNOT_APPLICABLE. Resultat per person som JSON-parameter på sektionen - RemissernaEn
statementper instans:sentAt,remindedAt,respondedAt. Skissens Skapad → Skickad → Påmind → Svar inkommet är samma livscykel - Förslaget
recommendationska 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
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.
- Beslutet
POST …/decisionsmedoutcome,method: MANUALoch vem som beslutade - Villkoren
terms, numrerade rader med kategori - UtfallenRegistreras per namespace under
metadata/decisionoutcomes. Ansökan och anmälan behöver olika uppsättningar - Omprövning
singleDecisionPerErrand: false, eftersom beslutet kan överklagas och omprövas - BeslutsdokumentetBilaga med syftet
DECISION
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
- Asseten
validToför giltighetstiden, villkoren somjsonParameters - Processen
ErrandProcessrapporterar aktiviteten tillbaka till ärendet
Handläggaren
Avslutar ärendet. Sökanden ser beslutet och att ärendet är avslutat på Mina sidor.
- Status
SOLVED.resolutionär fri text för tjänsten - Processen
processStatus: COMPLETED
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
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.
- labels
INSPECTION / INSPECTIONur kategoriträdet, plus etiketter urTAGROOT - 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
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
Handläggaren
Gör tillsynsbesöket. Varje kontrollpunkt i protokollet bedöms som Godkänt, Brist eller Ej aktuellt, med noteringar.
- Bedömningen
assessmentpå sektionen:APPROVED,DEFICIENCY,NOT_APPLICABLE. Skissens tre värden, plusPENDINGför ej bedömd - Vem och när
completedBy,completedAt - StatistikBedömningen är det enda strukturerade fältet, så antalet brister går att räkna över alla tillsyner
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, ärendetSOLVED. Inget beslut - ÅtgärdsärendeNytt ärende
INSPECTION / MEASURES, kopplat via Relation. TillsynenSOLVED - TillsynsutredningUtredningen fortsätter och slutar i en
decision. En återkallelse gör assetenBLOCKEDmedstatusReason
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
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
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 ochpartyIdsom tillsynen - KopplingenEn relation från tillsynsärendet, som syns under Kopplade ärenden i båda
- Meddelandet
EXTERNAL-konversation till Mina sidor. Kräver AOT i whitelisten
Kunden
Ser kraven, rättar bristerna och svarar med underlag, till exempel ett nytt egenkontrollprogram.
- SvaretMeddelande i samma konversation
- UnderlagetBilaga med
channel: MY_PAGESoch syftetRESPONSE
Handläggaren
Går igenom svaret och skriver av bristerna en i taget.
- BristernaEn
measureper brist, medtitle,dueAt,statusACTIVE→COMPLETEDsamtresultochresultText - GränssnittetAvvikelse har byggt flikarna Åtgärder och Uppföljning bakom
useMeasures
Handläggaren
Avslutar ärendet när alla brister är avskrivna. Kopplingen till tillsynen står kvar i båda ärendena.
- Status
SOLVED - KopplingenKopplade ärenden,
useRelations
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.
jsonParameters bara det som kom in. Utredning, yttrande och beslut blir egna resurser med livscykeln DRAFT → ACTIVE → COMPLETED, 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.
- Inga importer mellan
aot/ochavvikelse/. 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_APPLICATIONoch 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- ochaot-sviten. ”Skipped” betyder fel dev-server, inte godkänt.
Samma problem, två lösningar
| Problem | AoT-grenen | Avvikelse-grenen | Välj |
|---|---|---|---|
| Peka mot sprint-API:et | Fältet service i APIS, globalt för alla drakar | SUPPORTMANAGEMENT_API_TARGET per drake | Avvikelses, som också löser att versionen är global |
| Utredning, beslut, uppföljning | Tre egna flikar och tre flaggor | Variantsömmen med fasgrind | Sömmen |
| Faser | Hårdkodad mappning från status | Fasmodellen ur namespacets metadata | Fasmodellen |
| Frontend-tester | Inga | Vitest, och e2e för både vof och aot | Avvikelses |
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älla | Vad som händer | Gör så här |
|---|---|---|
| Dubbla flikar | Bå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 flikflaggor | Stryk AoT:s tre flikflaggor och flikfiler. AoT-varianten tar över |
| Två fasrader | useUiPhases är en statusmappning på AoT-grenen men fasmodellen hos Avvikelse, där flaggan också byter sidopanelens knappar | Lägg in faser i AOT-namespacet och använd Avvikelses fasflöde |
| Metadatafiltret | AoT:s rotnodsfilter ligger i den delade metadata-controllern och ger 502 för ett träd med ROOT-noder utan exakt en CATEGORYROOT | Prova mot IAF:s och VOF:s träd, eller begränsa filtret till AOT |
| Ärendeuppgifter | AoT-grenen visar alla jsonParameters. Avvikelse filtrerar bort utredningsdokument användaren inte får läsa | Behåll filtret och lägg bolagsblocket ovanpå |
| Radslut | Omkring 45 filer på Avvikelse-grenen har CRLF. Fem av dem blir helfilskonflikter | Normalisera 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.
| Lager | Vad | Lä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 |
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 | Ärendetyp | Underkategori |
|---|---|---|
| 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.
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.
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:
| Led | Vad som händer | Läge |
|---|---|---|
| Katlas etikett | Skickade UNCATEGORIZED, som är utfasad och ligger utanför CATEGORYROOT. Nu väljer sökanden ärendetyp ur trädet, och utfasade noder erbjuds inte | Löst |
| Ingen classification | Katla sätter den inte, och tjänsten kräver den inte | Kvar |
| Draken låser | Tomt ärende: flikarna utom den första, tilldelning, avsluta, pausa, återuppta och vidarebefordra är alla inaktiverade tills handläggaren sparat kategori | Kvar |
| 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 ärendet | Löst |
| Etikett läses som kategori | De fria etiketterna hade classification: "CATEGORY", precis som de riktiga kategorierna. Nu bär de "TAG", och Draken behåller dem när ärendet sparas | Lö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.
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.
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.
{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ör | Roll |
|---|---|
| API-teamet | Äger schemat. Registrerar det i JsonSchema-tjänsten |
| Katla | Skriver parametrarna vid registrering. Formuläret väljs ur ärendetypen, aot_{kategori}_{typ}_{subtyp} i gemener — ingen kod per schema |
| Draken | Lä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.
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.
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
| Sammanhang | Utfall |
|---|---|
| Beslut på ansökan | Bifall · Bifall med villkor · Avslag |
| Beslut på anmälan | Registrera · Förelägg om komplettering |
| Utredningens förslag | Tillstyrker · 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.
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.
| Symptom | Verklig 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
- När landar handläggningsmodellen?
investigations,statementsochdecisionsfinns på SupportManagement-grenendraken-4892, som bygger påmainoch inte på AoT:s sprintgren. Utredningen kan inte byggas förrän modellen finns påsupport-management-alkt-sprint. - Förslag till beslut kontra beslutsutfall. Modellens
recommendationska vara ett av namespacets beslutsutfall. Skissens förslag – Tillstyrker, Tillstyrker med villkor, Ingen erinran, Avstyrker – är en annan vokabulär. - 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.
- 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å? - 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. - Faser i AOT-namespacet. Fasraden, fasgrinden för flikarna och Avvikelses fasknappar förutsätter att namespacet har faser med tillåtna statusar.
- Var
classificationska 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. - Ytan för fria etiketter. Etiketterna under
TAGROOTbehålls när ärendet sparas, men de går varken att sätta, visa eller filtrera på. - Var senaste tillsyn lagras. Kundbilden visar den per serveringsställe, men ingen bärare är bestämd.
- Alk-T och OL2. Dagens handläggningssystem för alkohol respektive tobak – ersätts de, speglas de, eller samexisterar de med Draken?
- Diarieföring i Public 360. Allt ska diarieföras oavsett delegationsordning. Ingen sådan integration finns i Draken.
- Redigering av ansökningsdata. Ska handläggaren kunna rätta uppgifter under utredningen? API:et stödjer det, gränssnittet inte.
- Ansökan som privatperson. Egen ärendetyp, eller samma process där
partyIdskiljer 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.