Nattlig bokföringskontroll med GitHub Actions
Förra veckan demonstrerade jag live för en kompis hur jag kollar status på mina butiker. Jag skriver “kolla status på butikerna” och får tillbaka ett svar inom sekunder. Inga avvikelser hittade. Allt stämmer.
Det är inte magi. Det är en GitHub Actions-körning som sker varje natt kl 07:00 och kontrollerar 8 saker mot databasen. Om något är fel får jag ett rött email. Om allt ser bra ut får jag ett grönt.
Den här artikeln är mer för dig som bygger något eget än för en vanlig butiksägare. Det är ett konkret exempel på hur man sätter upp automatisk datavalidering i ett SaaS med 7 kunder.
Vad som kontrolleras varje natt
Jag kör ett kommissionssystem som heter Konsign. 7 aktiva butiker, alla hanterar in- och utlämning av secondhand-plagg. Det innebär dagliga försäljningar, kvitton, returhantering, utbetalningar och bokföring.
Varje natt kl 07:00 kontrollerar systemet det här:
1. SIE-balans. Genererar SIE-verifikat med exakt samma kod som exportfunktionen och verifierar att debet och kredit balanserar. Om det uppstår ett fel i bokföringslogiken syns det direkt.
2. Kvitton har försäljningsrader. Varje kvitto ska ha minst en rad kopplad till sig. Finns det “överblivna” kvitton utan matchande produktrader är något galet i flödet.
3. Beloppsavstämning. Summan av alla försäljningsrader ska matcha kvittots totalbelopp. Avvikelser på mer än 10 öre flaggas.
4. Matched amount-konsistens. För nyare kvitton används ett fält som heter matched_amount. Det ska stämma överens med summan av raderna inom 2 öre. En tätare tolerans, för det är ett fält vi sätter programmatiskt.
5. Synkfel mot Zettle. Betalterminaldata synkas automatiskt mot databasen. Olösta synkfel från de senaste 7 dagarna flaggas. Gamla historiska fel filtreras bort, de är bara brus.
6. Emaillogg. Kontrollerar att transaktionsmejl faktiskt skickades. Misslyckade mejlförsök de senaste 7 dagarna lyfts fram.
7. Zettle mot databas. Hämtar gårdagens köp direkt från Zettle API och jämför beloppen mot vad som finns i databasen. Om diff inte är noll, eller om kvitton saknas, är det ett fel.
8. Avgiftsverifikat. Verifierar att verifikat för avgiftsavdrag balanserar korrekt.
Hur det är byggt
Själva workflow-filen schemalägger körningen och hanterar notifieringen:
on:
schedule:
- cron: '0 6 * * *' # 07:00 svensk tid
workflow_dispatch: # manuell trigger vid behov
Valideringsskriptet körs som ett TypeScript-skript via npx tsx. Det anropar databasen direkt med service role-nyckeln, genererar SIE-verifikat med samma funktioner som exportflödet och jämför resultaten.
Om validering misslyckas händer två saker. Först skickas ett rött email med hela rapporten. Sen anropas en webhook som pingar ett AI-verktyg med felmeddelandet, så att diagnostiken kan börja utan att jag ens suttit ner.
Om allt är OK skickas ett grönt email. Enkelt.
- name: Send failure email via Resend
if: failure()
# ... skickar rapport med exakt felmeddelande
- name: Notify Claude via webhook
if: failure()
# ... skickar validation output direkt för diagnostik
Det som faktiskt hände under en live-session
Under en demo med en kompis öppnade jag terminalen och körde en statuskontroll mot butikerna. Systemet svarade direkt. Inga avvikelser.
Sedan dök det upp ett äldre undantag i loggarna: ett matched_amount satt till null på ett webshop-kvitto. Det var inget egentligt fel, utan ett känt beteende för en viss typ av order. Systemet flaggade det ändå.
Det intressanta hände sen. Jag bad AI-verktyget att undersöka och förklara. Det grävde i koden, hittade orsaken och uppdaterade sedan sina egna instruktioner för framtiden. Nästa gång samma situation uppstår vet det att det inte är ett fel.
Det är vad som skiljer ett passivt övervakningssystem från ett som faktiskt lär sig.
Varför det är värt att bygga
Jag behöver inte logga in i databasen varje morgon. Jag behöver inte komma ihåg att kolla. Systemet tar ansvaret för att säga till om något är fel.
7 kunder. 8 valideringspunkter. Varje dag. Det är inte en stor grej att sätta upp, men det är en stor grej att ha.
Det frigör mental kapacitet. Jag vet när jag vaknar om något är fel. Annars är allt OK.
Vanliga frågor
Behöver jag betala för GitHub Actions?
Nej, för privata repon ingår 2 000 minuter per månad i gratisplanen. En nattlig valideringskörning tar under en minut, så det ryms gott.
Hur svårt är det att sätta upp?
Workflow-filen är ungefär 100 rader YAML. Valideringsskriptet beror på hur komplex din datamodell är. Om du har en enkel databas med transaktioner och kvitton kan du ha något fungerande på en dag.
Vad skickar ni till AI-tjänsten vid fel?
Hela valideringsoutputen: vilka kontroller som misslyckades, för vilken tenant och med vilket felmeddelande. Inget kunddata, bara aggregerade siffror och tekniska identifierare.
Kan man göra samma sak utan AI-kopplingen?
Ja. Email-notifieringen fungerar helt fristående. AI-kopplingen är ett lager ovanpå som påskyndar diagnostiken. Du kan lägga till det när du redan har grundflödet på plats.