# Abonnementets livscyklus

Et abonnement i Alunta bevæger sig gennem et lille antal tilstande, og de fleste supportspørgsmål om
"hvorfor ser det her abonnement forkert ud" er i virkeligheden spørgsmål om hvilken tilstand det er
i, og hvad den tilstand gør ved faktureringen.

## De fire tilstande: pending, active, under_cancellation og cancelled

Et abonnements status er altid én af fire. Begreberne abonnementsstatus og abonnementsstatusser
dækker disse fire tilstande; der findes ikke andre statusser.

- **pending** - startdatoen ligger i fremtiden, og der er ingen slutdato. Abonnementet findes, men er
  ikke begyndt. Det kan godt allerede være faktureret: et fakturabetalt abonnement med en negativ
  dagsforskydning faktureres forud for sin første periode.
- **active** - det er begyndt og har ingen slutdato. Status siger intet om fornyelse, så et
  abonnement på en plan der ikke fornyes automatisk, er også `active` helt frem til sin sidste
  periode.
- **under_cancellation** - det er opsagt, men ikke ophørt endnu. Slutdatoen er i dag eller senere,
  og abonnementet kører og faktureres frem til den dato.
- **cancelled** - slutdatoen er passeret. Det er tilstanden ophørt, ikke tilstanden "nogen har
  trykket opsig".

Forskellen mellem `under_cancellation` og `cancelled` er den integratorer oftest tager fejl af. En
kunde der opsiger i dag, beholder som regel sit abonnement i flere uger, og det er et betalende
abonnement hele den tid.

## Prøveperiode og pause er ikke tilstande

En prøveperiode og en pause er perioder på abonnementet, ikke statusser på det. Begge optræder i
tidslinjen som perioder til prisen nul, og begge lader abonnementet selv være `active`.

Det er med vilje: tidslinjen må ikke have uforklarede huller, så en paused måned er en rigtig periode
til prisen nul frem for et hul mellem to fakturaer. Det er også derfor et paused abonnement tæller
som aktivt, men ikke som fakturerbart, og hvorfor de to tal godt kan være forskellige for den samme
kunde.

## Opsigelse

Uden opsigelsesvarsel træder en opsigelse som udgangspunkt i kraft ved udgangen af den indeværende
faktureringsperiode: slutdatoen sættes normalt til dagen før næste fornyelse, og abonnementet står i
`under_cancellation` indtil da. Har abonnementet et opsigelsesvarsel (se næste afsnit), kan
slutdatoen ligge senere. Er en senere periode allerede faktureret eller trukket, eller har den
et korttræk undervejs, rykkes slutdatoen frem til udgangen af den beskyttede periode. Kunden beholder
det, der er betalt for. Beskyttelsen gælder almindelige perioder uden afdrag. Ved afdrag bevares og
faktureres hver afregnet del for sig, men den holder ikke abonnementet aktivt gennem hele den
overordnede periode.

En øjeblikkelig opsigelse er også mulig, men slutdatoen er ikke altid i dag. Perioder der allerede
er faktureret eller trukket, eller som har et korttræk undervejs, er beskyttet, så slutdatoen rykkes
frem til udgangen af den sidste beskyttede periode. En øjeblikkelig opsigelse kan aldrig slette en
almindelig periode kunden allerede har betalt for. Afdragsdele følger den særskilte regel ovenfor og
forlænger ikke abonnementet gennem hele deres overordnede periode.

En opsigelse kan også få en bestemt slutdato (i teamets dialog og med `end_date` i API'et). Den dag
er sidste aktive dag; den kan ikke ligge før en beskyttet periode slutter, og i API'et kan den ikke
ligge i fortiden. En dato midt i en faktureringsperiode giver en forholdsmæssig sidste periode.

Perioder der endnu ikke er faktureret eller trukket, og som ligger efter slutdatoen, fjernes, fordi
de aldrig vil blive faktureret. Det er derfor et opsagt abonnement som regel har færre fremtidige
perioder end det havde et øjeblik før.

Et planlagt planskift følger samme regel som perioderne: træder det i kraft efter slutdatoen, fjernes
det sammen med dem. Træder det i kraft på eller før slutdatoen, hvilket et opsigelsesvarsel ofte
medfører, fordi abonnementet løber forbi næste fornyelse, bliver det stående. Perioderne frem til
slutdatoen faktureres så på den nye plan og dens interval, og skiftet gennemføres på sin ikrafttrædelsesdato,
selv om abonnementet er under opsigelse. Det har ingen betydning for slutdatoen, om sådan et skift
findes. Et nyt planskift kan ikke planlægges på et abonnement, der allerede er opsagt.

## Opsigelsesvarsel

Et abonnement kan have et opsigelsesvarsel: en regel for, hvor længe det løber efter en opsigelse.
Teamet indstiller varslet på planen, og det kopieres til hvert abonnement, når abonnementet oprettes.
Uden varsel gælder reglerne i afsnittet ovenfor uændret. Varslet er ikke en bindingsperiode; det
sætter ikke en mindsteperiode fra abonnementets start.

**Varslet kan kun forlænge.** Slutdatoen er den seneste af varslets slutdato, udgangen af den
igangværende periode og udgangen af eventuelle beskyttede perioder (en senere periode, der allerede
er faktureret eller trukket). Et varsel kan derfor aldrig give en tidligere slutdato end en
opsigelse uden varsel, og en beskyttet periode kan stadig give en senere slutdato end varslet.
Opsigelsesdagen er dags dato i teamets tidszone.

Der er fire typer. Eksemplerne gælder en opsigelse 10. oktober 2026 på et månedligt abonnement med
faste perioder (1. til sidste dag i måneden), hvor oktober allerede er faktureret.

- **Indeværende periode + N perioder** (`billing_periods`, N fra 1 til 12). Slutdatoen er udgangen af
  den N'te periode efter den indeværende. Med N = 1 er sidste dag 30. november 2026.
- **Løbende måned + N måneder** (`calendar_months`, N fra 0 til 24; 0 er "løbende måned"). Slutdatoen
  er sidste dag i den kalendermåned, der ligger N måneder efter opsigelsesmåneden. Med N = 1 er sidste
  dag 30. november 2026. Har abonnementet perioder fra den 15. til den 14., ender det stadig 30.
  november, og den sidste periode (15. til 30. november) prissættes forholdsmæssigt.
- **N måneders varsel til udgangen af en periode** (`months_to_period_end`, N fra 1 til 24).
  Slutdatoen er udgangen af den første periode, der slutter på eller efter opsigelsesdagen
  plus N måneder. Med N = 3 er opsigelsesdagen plus tre måneder 10. januar 2027, og sidste dag er
  derfor 31. januar 2027.
- **N dage eller måneder fra opsigelsesdagen** (`fixed_length`, 1 til 365 dage eller 1 til 24
  måneder). Slutdatoen er opsigelsesdagen plus N dage, eller plus N måneder uden overløb, så 31.
  januar plus én måned giver 28. februar. Med 30 dage er sidste dag 9. november 2026, og perioden 1.
  til 9. november prissættes forholdsmæssigt (9 af 30 dage).

De to periodebaserede typer (`billing_periods` og `months_to_period_end`) læser periodegrænserne fra
den samme beregning, som fakturerer abonnementet, så faste og fleksible perioder, samlede fornyelser
og planlagte intervalskift tages med. Pause- og prøveperioder tæller ikke som perioder, så en pause
forbruger ikke varslet og forkorter det heller ikke. Med faste perioder tæller en periode, som en
pause deler i to (1. til 4. oktober, en pause, så 26. til 31. oktober), kun som én periode. Et
periodefragment, som en pause afbryder, før perioden er fuld, og som intet efter pausen fuldender (fx
en fleksibel periode, eller en pause der løber forbi månedsskiftet), er ikke betalt i sin helhed og
tæller ikke; i stedet tæller den næste periode efter pausen. Med fleksible perioder er den første
periode efter en pause en ny, fuld periode, så kunden stadig betaler for det samme antal perioder.
Slutdatoen kan til gengæld ligge senere eller tidligere end uden pausen, fordi gitteret af perioder flytter sig; det er antallet af betalte perioder, der bevares. De to kalenderbaserede typer (`calendar_months` og
`fixed_length`) er almindelig datoregning fra opsigelsesdagen, så en pause påvirker dem slet ikke.

Varslet er aldrig kortere end den indeværende periode, uanset type: på et årligt abonnement med
kalenderårsperioder giver et varsel på 30 dage, opsagt 10. oktober 2026, stadig 31. december 2026,
fordi den indeværende periode ikke kan forkortes.

**Ender abonnementet midt i en periode,** prissættes den sidste periode forholdsmæssigt efter dage:
periodens fulde pris gange de dage abonnementet løber, delt med dagene i en fuld periode. Det gælder
perioder der endnu ikke er faktureret eller trukket. En periode der allerede er faktureret eller
trukket, bliver ikke omprissat; den er beskyttet.

**Varslet gælder ikke i en prøveperiode og ikke for et abonnement, der ikke er startet endnu.**
Opsiges abonnementet, mens opsigelsesdagen ligger i en prøveperiode, eller før abonnementets
startdato, bruges varslet ikke, og abonnementet slutter som uden varsel, typisk ved prøveperiodens
udløb. Ellers ville kunden blive opkrævet for en periode, de aldrig valgte; det gælder fx et
pakkeabonnement, der aldrig er startet.

**Et varsel, der ikke kan anvendes, giver en fejl, ikke et kortere varsel.** Der er to årsager. Kan
det varsel, der er gemt på abonnementet, ikke læses, vises abonnementet uden varsel (API'et viser
`notice_period: null`, så `null` betyder ikke altid, at en opsigelse ikke bruger et varsel). Og løber
en pause så langt frem, at varslet ikke kan lægges på rigtige faktureringsperioder inden for ti år,
kan datoen ikke beregnes. I begge tilfælde afvises en opsigelse "med varsel" i stedet for at give en
tidligere slutdato end aftalt: API'et svarer 422 og anbefaler `immediate: true`, og portalen viser
en forklaring i opsigelsesdialogen. Det gælder også en pakkeopsigelse, hvor ét sådant abonnement
afviser hele opsigelsen (intet opsiges, og beskeden nævner abonnementet, så det kan opsiges for sig
først). Øjeblikkelig opsigelse virker stadig, og teamets egen dialog forklarer problemet og tilbyder
stadig udgangen af indeværende periode, en bestemt dato og i dag, så teamet selv kan vælge slutdato.

**Varslet låses ved oprettelsen.** Abonnementet får planens varsel i det øjeblik det oprettes, uanset
om det sker fra grænsefladen, API'et, checkout eller en pakke. Ændrer teamet planens varsel senere,
gælder det kun nye abonnementer. Eksisterende abonnementer beholder deres varsel, og abonnementer
oprettet før funktionen findes har intet varsel. Et planskift beholder abonnementets varsel, og en
overdragelse gør det også. Abonnementer, der er importeret
fra Stripe eller e-conomic, får aldrig et varsel, heller ikke selv om den plan, de matches til, har
et, fordi aftalen eksisterede før Alunta og ikke må få vilkår med tilbagevirkende kraft. En køber i checkout får det varsel, vedkommende blev vist (se checkout-guiden). API'et viser
varslet som `notice_period` på abonnementet: enten `null` (intet varsel) eller et objekt med `type`,
`length`, `unit` og en læsbar `label`.

**Hvem er bundet af varslet:**

- Kundeportalen anvender altid abonnementets varsel, når slutkunden opsiger selv. Kunden kan ikke
  fravælge det, og dialogen viser slutdatoen før kunden bekræfter. Abonnementskortet viser varslet,
  med "(gælder efter prøveperioden)" eller "(gælder, når abonnementet er startet)", når det endnu
  ikke gælder. Har slutdatoen ændret sig, siden siden blev åbnet (fx henover midnat), gemmes intet:
  portalen viser den nye dato, og kunden bekræfter igen. Portalen kan kun opsige, hvis teamet har
  slået selvbetjent opsigelse til.
- API'et (`POST /subscriptions/{uuid}/cancel`) anvender varslet som standard. `immediate=true`
  tilsidesætter det og giver en slutdato i dag; også her kan beskyttede perioder skubbe datoen
  frem. Slutdatoen i svaret er den gældende.
  `GET /subscriptions/{uuid}/cancel-preview` (samme valgfri `immediate` som query-parameter) returnerer
  den slutdato, en opsigelse ville gemme, uden at opsige noget: ingen skrivning og ingen events. Den
  beregnes af den samme kode som selve opsigelsen og afvises med de samme `422`-beskeder. Den
  returnerer også abonnementets `notice_period` og `notice_applied`, som kun er sand, når varslet
  bestemmer datoen (det løber længere end udgangen af den indeværende eller en beskyttet periode);
  den er falsk uden varsel, med `immediate=true`, i en prøveperiode eller før start, og når datoen
  ville være den samme uden varslet.
- Teamets egen opsigelsesdialog tilbyder, når abonnementet har et varsel, fire valg: med varsel
  (standard), ved udgangen af indeværende periode (teamet giver afkald på varslet), en bestemt dato
  eller i dag. De to valg med en beregnet dato (med varsel og ved udgangen af indeværende periode) viser den dato, der bliver gemt; ved "i dag" og "en bestemt dato" er det teamet, der vælger. Ændrer datoen sig, mens dialogen er
  åben (fx henover midnat), gemmes intet, og dialogen viser den nye dato til bekræftelse. En bestemt dato kan ligge før varslets
  udløb (dialogen advarer om, at kundens varsel så frafaldes), men ikke før en beskyttet periode
  slutter. Uden varsel er dialogen som før, og "ved udgangen af indeværende periode" viser den dato,
  der gemmes, også når en senere periode er beskyttet.
- En opsigelse af en pakke fra teamet eller via API'et anvender hvert abonnements eget varsel, så
  abonnementerne i pakken kan få forskellige slutdatoer.
- Systemopsigelser følger ikke varslet. En opsigelse på grund af betalingsfejl bruger sin egen
  regel, og deaktivering af Leverandørservice opsiger abonnementerne ved udgangen af den indeværende
  periode.
- Slutkunden får en opsigelsesbekræftelse på e-mail med abonnementets navn og sidste dag (og
  varslet, når det bestemte datoen), når kunden opsiger i portalen, eller teamet eller API'et opsiger.
  En pakkeopsigelse giver én samlet mail med alle de abonnementer, den opsagde, og deres slutdatoer.
  Rettes slutdatoen senere, sendes en ny bekræftelse med den nye dato. Der sendes ingen bekræftelse
  ved betalingsfejl (den har sin egen mail), ved sletning eller ved deaktivering af Leverandørservice.
  Mailen er slået til som standard og kan slås fra under Indstillinger → Kundemails (den er dog
  slået fra for teams, der havde slået abonnementsbekræftelsen fra, og for API-oprettede teams, indtil
  de slår den til); den sendes kun til en kunde med e-mailadresse, som ikke selv har fravalgt
  mailtypen. Ændres slutdatoen på et abonnement, der er afsluttet af en anden årsag end en opsigelse,
  eller gemmes den samme dato igen, sendes der ingen ny bekræftelse.

## Hvordan opsiger jeg et abonnement?

Åbn abonnementets handlinger og vælg opsigelse. En normal opsigelse gælder uden varsel som regel ved
udgangen af den indeværende faktureringsperiode; har abonnementet et opsigelsesvarsel, er varslet
standardvalget, og slutdatoen kan ligge senere. Status er `under_cancellation` indtil slutdatoen.
Vælg kun øjeblikkelig opsigelse, hvis det er ønsket. For almindelige perioder uden rater er perioder,
der allerede er faktureret eller betalt, eller har et korttræk undervejs, beskyttede og kan flytte
slutdatoen. Ved ratebetaling bevares og faktureres en afregnet rate, men den forlænger ikke
abonnementet gennem hele hovedperioden. Fortryd opsigelsen før slutdatoen for at rydde slutdatoen
og genopbygge fremtidige perioder. En opsigelse giver ikke automatisk refundering; refundering eller
kreditering håndteres som en separat økonomisk handling.

## Ændring af vilkår og genberegning af perioder

Når abonnementets faktureringsperioder genberegnes, bevares eksisterende perioder, der er udløbet
i teamets tidszone, også selv om de endnu ikke er faktureret. En senere ændring af pris, antal,
interval eller samling af fornyelser omskriver ikke disse perioder. Manglende perioder kan stadig
gendannes.

Antalsændringer og øjeblikkelige opgraderinger af prisniveau midt i en faktureringsperiode bevarer
periodens aftalte grundbeløb og afregner de resterende dage med en separat forholdsmæssig
regulering. Senere perioder bruger de nye vilkår.

En opsigelse kan stadig forkorte en ufaktureret periode, der krydser abonnementets nye slutdato.
Deaktivering af en kunde rydder også ufakturerede perioder på kundens frosne abonnementer, så de
ikke faktureres. Disse handlinger har et andet formål end at ændre et kørende abonnements vilkår.

## Genoptagelse af et opsagt abonnement

Der er to forskellige handlinger her, og de er nemme at forveksle.

**At fortryde en opsigelse.** Mens abonnementet stadig kører frem mod sin slutdato, kan opsigelsen
trækkes tilbage. Slutdatoen ryddes, status vender tilbage til `active`, og de fremtidige perioder
bygges op igen. Det er det `POST /subscriptions/{uuid}/resume` gør, og det virker kun på et
abonnement der ikke er ophørt endnu.

**At genstarte et abonnement der allerede er ophørt.** Det kan man også i Alunta, men kun for
fakturabetalte abonnementer, og kun fra grænsefladen, ikke fra API'et. Du vælger datoen det skal
begynde igen, og efterlader det et hul efter den gamle slutdato, registreres hullet som en pause, så
tidslinjen ikke brydes. Et kortbetalt abonnement der er ophørt, kan ikke genstartes på den måde; den
kunde skal have et nyt abonnement.

## Livscyklus-webhooks

Alunta behandler livscyklushændelser hver time, så `subscription.started` og `subscription.ended`
normalt ankommer kort efter det tidspunkt de beskriver, ikke præcis på sekundet. Hændelserne
oprettes med et atomisk database-claim, så samtidige livscykluskørsler ikke kan oprette hver sin
hændelse for den samme logiske overgang. Det committede claim er holdbart, og en reconciler prøver
igen, hvis den oprindelige proces eller queue-vej fejler før completion. Webhook-levering sker stadig
mindst én gang, ikke præcis én gang: et genforsøg eller en manuel genafspilning kan levere den samme
overgang flere gange. Begge hændelser indeholder et stabilt `data.event_id`, som bevares ved retries
og recovery; brug det som idempotency key.

Hændelserne er heller ikke en komplet strøm. Den timevise kørsel springer et abonnement over, hvis
det oprettes efter sin egen startdato, så den udløser ikke `subscription.started` bagudrettet. Den
springer kun hændelsen for et ophørt abonnement over, når abonnementets seneste opdateringsdato
ligger efter slutdatoen, hvilket markerer at slutningen er registreret bagudrettet. Det springes ikke
over alene fordi en normalt planlagt slutdato først scannes efter udløb. Den normale
opsigelseshandling er en særskilt vej: ender den på en dato der allerede er udløbet, udløser den
straks `subscription.ended`. Læs abonnementet når du har brug for det fulde billede.

Prøveperioder følges på den samme timevise kørsel, men de har ingen offentlig webhook. Har du brug
for at reagere på at en prøveperiode begynder eller slutter, skal du spørge på abonnementet frem for
at vente på en hændelse der ikke kommer.

`subscription.ended` bærer desuden en `reason`, som skelner en almindelig opsigelse fra en der
skyldes betalingsfejl, at kunden selv har opsagt, eller at abonnementet eller kunden er slettet.

## Pakker har ikke en livscyklus

En pakke er en registrering af et køb, ikke en beholder der ejer sine abonnementer. Hvert abonnement
i en pakke er selvstændigt fra det øjeblik det oprettes, og kan opsiges, ophøre, overdrages eller
genoptages for sig. En pakke kan derfor have alle, nogle eller ingen af sine oprindelige abonnementer
tilbage, og dens status udledes af de abonnementer der stadig findes, frem for at være gemt på
pakken.

Har du brug for at kende tilstanden på et bestemt abonnement, så læs det abonnement. Udled den
aldrig fra pakken.

## Sådan tjekker du det for dit eget team

Reglerne ovenfor er de samme for alle teams. Den konkrete tilstand på en given kundes abonnementer er
data: brug `get_customer_subscription_overview` eller `list_subscription_customers` for det team du
er forbundet til.

## Abonnementsbekræftelse

Når teamet selv opretter et abonnement, kan kunden få mailen med abonnementsbekræftelsen (Indstillinger > Kundemails): abonnement, startdato, pris, fornyelse og opsigelsesvarsel, uden faktura - den første faktura er sin egen mail. I appen er det et valg under Opret abonnement, som teamet sætter flueben i for hver oprettelse (det er ikke sat på forhånd, så kunder, der flyttes over fra et andet system, ikke får en velkomstmail); via API'et sendes den kun, når forespørgslen har `send_confirmation: true`. En pakke får én bekræftelse med hvert abonnement. Den sendes aldrig for et abonnement, hvis startdato ligger før den dag, det blev oprettet, når teamet har slået mailen fra, eller når kunden har fravalgt den. Et køb gennem checkout får ordrebekræftelsen i stedet.

## Afbrudt manuel oprettelse

Når du tilføjer abonnementer på en kundes side, gemmes bestillingen, så du kan fortsætte efter en
afbrydelse. Åbn oprettelsen igen for samme kunde med samme bruger for at se den gemte bestilling.
Allerede oprettede abonnementer genbruges, og eventuel fakturering genoptages med det gemte
fakturagrundlag. En bestilling med flere elementer kan være delvist gennemført; en fejl betyder
derfor ikke nødvendigvis, at intet er oprettet.

Hvis et produkt eller fakturagrundlaget har ændret sig, kan fortsættelsen kræve din gennemgang.
"Start en ny bestilling" beholder allerede oprettede abonnementer og stopper oprettelsen af de
resterende elementer og deres fakturering. Notifikationer og statusopdateringer for allerede
gennemførte køb kan stadig blive færdige i baggrunden. Det opsiger ikke abonnementer og krediterer
ikke fakturaer.

## Fornyelse og kommende fakturering

En fornyelsesdato er den dato, hvor en ny periode kan begynde. Kommende perioder viser forventet dato, valuta og pris, men er ikke en betaling eller garanti for, at en ekstern bogføring er gennemført. En plan kan være aktiv uden automatisk fornyelse, og en automatisk fornyelse kan have en afventende eller afvist betaling.

## Prøve, intropris og pause

En prøveperiode er en pris-nul-periode før den normale fakturering. Et introtilbud er en tidsbegrænset pris på nye køb, og en individuel rabat er en ændring af én aftale. En pause er også en pris-nul-periode, men den indsættes i et eksisterende abonnements tidslinje. Ingen af dem er ekstra abonnementsstatusser.

## Pakker og rater

En pakke samler købet, men hvert oprettet abonnement har sin egen livscyklus. Pakkens engangsbeløb kommer på samme faktura som første periode, ligesom et enkelt abonnements engangslinjer. Kun når intet abonnement i pakken har en fast betalt periode fra startdatoen (prøveperiode, forbrug eller gratis), får engangsbeløbet sin egen faktura, tidligst på startdatoen. Det samme sker, hvis det abonnement, der skulle bære engangsbeløbet, opsiges eller slettes før sin første faktura, mens pakkens øvrige abonnementer fortsætter; opsiges hele pakken, faktureres engangsbeløbet ikke. Har en mislykket betaling afsluttet et af pakkens abonnementer, faktureres og trækkes et endnu ubetalt engangsbeløb heller ikke; genoptages abonnementet, opkræves det igen som normalt. Ved et manuelt køb med startdato i dag eller tidligere følger engangsbeløbet i stedet pakkens første faktura, som teamet selv opretter. Betalingslinks og tilbud med fast startdato har deres egen regel, se Checkout og selvbetjening. Engangsbeløb for en kunde, der betales af en forhandler, faktureres til forhandleren ligesom abonnementerne. Ved kortbetaling trækkes engangsbeløbet sammen med første periode, så fakturaen svarer til trækket; uden en periode at følge med trækkes det for sig selv på startdatoen. Ratebetaling deler én serviceperiode i rater med hver sin forfaldsdato og betalingslinje; forfaldne linjer i samme valuta kan samles på én faktura. Raterne er ikke separate abonnementer.
