Workstation Logo
Solutions IA
Stations de Travail IAAI SME PackagesIA PrivéeClusters GPUIA EdgeLaboratoire IA EntrepriseIA par IndustrieWSL ProxyRing Promoter
Produits
AI SME PackagesCRMMarketingAgents OpenAIWSL ProxyRing Promoter
À Propos
PartenairesTémoignages Clients
Articles
Documentation
Blog
Nous ContacterLogin
Workstation

AI workstations, AI Multi Agentic Software, GPU infrastructure, and intelligent agent solutions for modern businesses.

UK Office: 77-79 Marlowes, Hemel Hempstead HP1 1LF - Directions - Take Junction 20 off M25 Outer London
Company No: 11641870
Mon - Fri: 9:00 AM - 6:00 PM GMT
+44 7515 356 146

Belgium Office: Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, Brussels
BE 0751.518.683
Mon - Fri: 9:00 AM - 6:00 PM CET
+32 492 45 67 46

AI Solutions

AI WorkstationsAI SME PackagesPrivate AIGPU ClustersEdge AIEnterprise AIWSL ProxyRing Promoter

Resources

ArticlesDocumentationBlogSearch

Company

About UsPartnersContact

© 2026 Workstation AI. All rights reserved.

PrivacyCookies
Home / Articles / Technology
IAComptabilitéPythonAutomatisation

Construire un système de retour VAT avec Claude Code à partir de votre base de données de factures et de dépenses

De la base de données factures + dépenses Postgres à HMRC Box 1 à 9 : les invites, le moteur Python déterministe, la soumission OAuth2 MTD et les cas extrêmes (Brexit, protocole NI, autoliquidation, exemption partielle, forfait, multi-devises, notes de crédit)

May 16, 2026Technology23 min read

Il s’agit de la plongée profonde en version longue. Pour une version plus rapide et lisible, consultez le article de blog compagnon.

VAT revient avec Claude Code à partir des factures et couverture des dépenses

1. Pourquoi j'ai construit ça

Chaque petite entreprise britannique dont le chiffre d'affaires imposable dépasse le seuil d'enregistrement VAT doit calculer et soumettre une déclaration VAT - généralement trimestrielle - via le service Making Tax Digital (MTD) de HMRC. Neuf cases numérotées. Sortie VAT moins entrée VAT. Payez le montant net ou demandez le remboursement. Facile en théorie ; punissant en pratique lorsque vos factures résident dans Postgres, vos reçus de dépenses sont des PDF provenant d'une vingtaine de fournisseurs différents, vos relevés bancaires sont au format CSV de Wise et Revolut et vos lignes en devises doivent être retraitées en livres au bon taux mensuel.

Pendant quelques années, je me suis débrouillé avec une feuille de calcul géante, un rappel de calendrier et un petit acte de foi. Chaque trimestre prenait environ une demi-journée, dont la majeure partie était consacrée à la gestion des données : exporter un fichier CSV à partir de la base de données des factures, le coller dans Excel, classer manuellement quelques centaines de lignes, revérifier les formules, copier neuf nombres dans un pont MTD tiers, cliquer sur Soumettre. La piste d'audit était "croyez-moi, j'avais une feuille de calcul". Les changements de taux au milieu du trimestre l’ont brisé. Les reçus ont disparu. Un classement mal placé pourrait pousser Box 5 de plusieurs centaines de livres.

J'ai reconstruit le pipeline cette année en tant que petit Claude Code projet qui communique directement avec ma base de données de factures et de dépenses, classe chaque ligne, calcule Box 1 en Box 9 avec un moteur Python déterministe, exécute à sec le retour sous forme de rapport Markdown, et seulement après la signature d'un humain, le soumet à HMRC MTD. Le trimestre entier me prend maintenant environ une heure, dont la majeure partie est consacrée à la révision des essais avec mon comptable. La piste d'audit est un dépôt git. Les mathématiques sont testées unitairement. Le classificateur est un fichier Markdown documenté. La soumission est fermée.

Cet article est la version longue. Invites, Python, schéma, flux HMRC OAuth, cas extrêmes. Si vous voulez d'abord la version courte, lisez le blog compagnon.

2. Introduction à HMRC MTD (et clause de non-responsabilité)

Making Tax Digital pour VAT est l'exigence de HMRC selon laquelle les entreprises enregistrées sous VAT conservent des enregistrements numériques et soumettent leurs déclarations via un logiciel compatible via un API documenté plutôt que de saisir des chiffres dans le formulaire Web gov.uk. Le API est OAuth2, nécessite des en-têtes HTTP anti-fraude identifiant le périphérique d'origine et est disponible dans un bac à sable gratuit avant même de toucher à la production en direct.

Le retour lui-même est de neuf cases : Box 1 est VAT dû sur les ventes et autres sorties ; Box 2 est VAT dû sur les acquisitions de biens en provenance des États membres de l'UE (pertinent pour les entreprises d'Irlande du Nord dans le cadre du protocole NI) ; Box 3 est le total de VAT dû (Box 1 + Box 2) ; Box 4 est VAT récupérable sur les achats (saisissez VAT) ; Box 5 est le VAT net à payer ou à récupérer (Box 3 - Box 4) ; Box 6 correspond aux ventes totales hors VAT ; Box 7 correspond au total des achats hors VAT ; Box 8 représente la valeur totale des marchandises fournies aux États membres de l'UE (encore une fois, NI uniquement) ; Box 9 correspond à la valeur totale des acquisitions provenant des États membres de l'UE (NI uniquement). Il existe des variantes de régime - régime forfaitaire, comptabilité de caisse, comptabilité annuelle - qui changent comment vous arrivez aux chiffres mais pas à la forme de la boîte.

Clause de non-responsabilité. Je suis ingénieur logiciel, pas expert-comptable. Cet article est pas de conseils fiscaux. Les règles exactes de la classification VAT, de l'exonération partielle, du régime forfaitaire, des règles sur le lieu de fourniture des services numériques, du traitement post-Brexit des biens et services de l'UE et du protocole NI changent toutes au fil du temps et dépendent de votre situation spécifique. Avant d'exécuter quelque chose de ce genre sur un vrai compte HMRC, demandez à un comptable enregistré au Royaume-Uni d'examiner votre première déclaration de bout en bout. Pour connaître la règle faisant autorité sur tout cas limite spécifique, consultez l'avis HMRC VAT 700 et les avis associés sur le site Web gov.uk. Le coût d'une heure du temps de votre comptable est bien inférieur au coût d'une mauvaise soumission.

3. Le modèle de données

Tout en aval dépend de la forme de deux tableaux : les factures émises (ventes) et les dépenses enregistrées (achats). Je garde le mien dans Postgres mais la même forme fonctionne sur MySQL ou SQLite. Le schéma minimum utile :

CREATE TABLE invoices (
  id              BIGSERIAL PRIMARY KEY,
  invoice_number  TEXT NOT NULL UNIQUE,
  issued_at       DATE NOT NULL,
  customer_name   TEXT NOT NULL,
  customer_vat_no TEXT,
  customer_country CHAR(2) NOT NULL,
  net_amount      NUMERIC(14,2) NOT NULL,
  vat_amount      NUMERIC(14,2) NOT NULL,
  gross_amount    NUMERIC(14,2) NOT NULL,
  currency        CHAR(3) NOT NULL DEFAULT 'GBP',
  fx_rate_to_gbp  NUMERIC(18,8) NOT NULL DEFAULT 1,
  vat_rate        NUMERIC(5,2) NOT NULL,
  vat_treatment   TEXT NOT NULL,
  status          TEXT NOT NULL,
  paid_at         DATE,
  notes           TEXT,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE expenses (
  id              BIGSERIAL PRIMARY KEY,
  supplier_name   TEXT NOT NULL,
  supplier_vat_no TEXT,
  supplier_country CHAR(2) NOT NULL,
  incurred_at     DATE NOT NULL,
  net_amount      NUMERIC(14,2) NOT NULL,
  vat_amount      NUMERIC(14,2) NOT NULL,
  gross_amount    NUMERIC(14,2) NOT NULL,
  currency        CHAR(3) NOT NULL DEFAULT 'GBP',
  fx_rate_to_gbp  NUMERIC(18,8) NOT NULL DEFAULT 1,
  vat_rate        NUMERIC(5,2) NOT NULL,
  vat_treatment   TEXT NOT NULL,
  category        TEXT NOT NULL,
  receipt_url     TEXT,
  notes           TEXT,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

Les colonnes non évidentes sont vat_treatment, fx_rate_to_gbp, et les codes pays. Le traitement est une petite énumération utilisée à la fois par le classificateur et par le moteur ; le code du pays détermine la logique d'autoliquidation et d'acquisition dans l'UE ; Le taux de change vous permet de conserver les factures en devises dans leur devise d'origine tout en les ré-étatisant dans GBP pour les totaux des boîtes.

Colonne But Utilisé par
vat_treatmentstandard / réduit / zéro / exonéré / hors champ d'application / autoliquidation / biens européens / services européens / importation reportéeclassificateur + moteur
vat_rate0,00, 5,00, 20,00 (ou tarif spécifique au régime)moteur + somme de contrôle
currency + fx_rate_to_gbpretraitement multidevisesnormalisateur
customer_country / supplier_countryautoliquidation, protocole NI, lieu de fournitureclassificateur
paid_atbranche du système de comptabilité de caissemoteur

Le remplissage de ces colonnes sur une ancienne table de factures est la partie la plus lente du projet. Claude Code peut générer la migration ; vous devez toujours classer manuellement les cas extrêmes délicats.

4. Pourquoi Claude Code (et non Xero/QuickBooks/FreeAgent)

Pour la plupart des petites entreprises britanniques, la réponse est – véritablement – ​​d’utiliser des logiciels packagés. Xero, QuickBooks, FreeAgent, Sage ont tous une soumission MTD certifiée HMRC, des interfaces utilisateur décentes et des comptables qui les connaissent déjà. Vous ne devez pas déployer votre propre système VAT sauf si vous avez une raison claire.

Mes raisons étaient étroites mais réelles. J'utilise déjà Claude Code tous les jours pour le travail logiciel, donc l'effort marginal pour l'utiliser également pour VAT était faible. Ma base de données de factures réside sur ma propre machine ; Je préfère qu'il ne soit pas reflété dans un locataire SaaS. Ma combinaison de fournisseurs est délicate (services de l'UE avec autoliquidation, importation VAT reportée, cas extrêmes occasionnels détaxés) et l'encodage des règles dans un seul fichier Markdown plus un module Python s'est avéré plus rapide que la configuration d'un SaaS pour les gérer. Et la piste d'audit que je reçois d'un dépôt git - chaque invite de classificateur, chaque différence, chaque instantané de période signé - est exactement la piste d'audit que je souhaite.

Claude Code s’y prête bien pour trois raisons. Premièrement, il fonctionne directement sur un projet sur disque : il peut lire mon schéma, les rapports d'exécution à sec du trimestre précédent, le fichier de règles et le moteur Python, et proposer des modifications en contexte. Deuxièmement, il est bon pour les échafaudages ennuyeux : scripts de migration, importateurs CSV, rapports de réconciliation, appareils pytest. Troisièmement, lorsqu'il classe une ligne, il explique son raisonnement dans un anglais simple, ce qui est exactement ce que je souhaite revoir avant de signer la déclaration. La matrice de décision au bas du diagramme de flux de travail ci-dessous est la version honnête de ce compromis.

5. Architecture et flux de travail

VAT renvoie le flux de travail Claude Code : source, ingération, catégorisation, moteur VAT, soumission, voies d'audit et matrice de décision

Le pipeline comporte cinq couloirs de nage. Source est un accès en lecture seule aux factures et aux tableaux de dépenses ainsi qu'à un dossier de dépôt pour CSV à partir de Stripe, Wise et des flux bancaires. Ingérer + Normaliser est un petit script Python généré par Claude qui mappe chaque schéma source en une seule vue canonique, convertit les devises étrangères en GBP au taux mensuel HMRC, applique un filtre de plage de dates et marque chaque ligne avec un idempotent. run_key les rediffusions sont donc sûres. Catégoriser + Réconcilier est le classificateur Claude Code : il parcourt chaque ligne canonique, sélectionne un vat_treatment à partir de l'énumération documentée en utilisant les règles dans vat-rules.md, rapproche les factures avec les paiements et signale les anomalies (net négatif, numéro VAT du fournisseur manquant, incompatibilité de code de pays, fournisseurs qui devraient être enregistrés VAT mais ne le sont pas). Moteur VAT est un module Python pur qui lit les lignes classées et calcule Box 1 en Box 9 de manière déterministe ; les branches des régimes forfaitaires, en espèces et annuels sont des chemins de codes explicites. Soumettre + Audit est l'appel HMRC MTD API (OAuth2, en-têtes de prévention de la fraude, bac à sable d'abord), contrôlé par une étape d'approbation humaine, avec l'instantané de la période signé et le journal complet du classificateur écrit dans un dossier d'audit en annexe uniquement conservé pendant six ans.

6. Construction étape par étape avec Claude Code

C'est le flux de travail que j'ai réellement utilisé. Cinq invites. Je les ai nettoyés pour cet article ; les originaux sont plus compliqués.

Invite 1 - normalisateur. "Regardez le invoices et expenses tableaux dans schema.sql. Générer un module Python normalise.py qui lit les deux tables en utilisant psycopg (rôle en lecture seule vat_reader), se limite à la plage de dates 2026-01-01 à 2026-03-31, et émet une liste de dictées canoniques avec des clés : id, source, date, party, gross, net, vat_amount, vat_rate, vat_treatment, country, currency, fx_rate, run_key. Utiliser Decimal, pas flotter. Incluez une docstring et un __main__ bloc qui imprime un résumé."

Claude a renvoyé un module propre avec Decimal, SQL paramétré, un build_run_key() qui hache (period_start, period_end, Schema, schema_version) en une chaîne hexadécimale stable et une CLI basée sur les clics. J'ai édité deux noms de champs et accepté le reste.

Invite 2 - classificateur. "Lire vat-rules.md et écrire classify.py. Pour chaque ligne canonique de normalise.py, ensemble vat_treatment à l'un des : standard, réduit, zéro, exempter, hors-portée, autoliquidation, produits européens, services européens, importation reportée. Si la ligne a déjà un non vide vat_treatment, laissez-le tranquille et enregistrez-le comme conservé. Sinon, choisissez le code du pays, le numéro VAT du fournisseur, la catégorie et le montant, et écrivez une phrase. reason sur chaque rangée. Les anomalies (net négatif, fournisseur VAT manquant pour un fournisseur britannique au-dessus du seuil d'enregistrement, inadéquation des pays) sont transférées dans une section distincte. anomalies.json pour un examen humain. Ne modifiez pas la base de données source."

Le classificateur lui-même est une petite fonction, principalement basée sur des règles, avec une branche soutenue par LLM pour les catégories de dépenses ambiguës. Surtout, il n'écrit jamais dans la base de données source - il émet un fichier JSON classifié que le moteur lit. Si je ne suis pas d'accord avec une classification, j'édite le JSON ; le prochain essai à sec le récupère.

Invite 3 - moteur. "Écrire engine.py en fonction pure : def compute_boxes(rows: list[Row], scheme: Scheme) -> BoxTotals. Aucune E/S. Pas de LLM. BoxTotals est une classe de données gelée avec Box 1 à Box 9 comme Decimal valeurs à 2 dp. Ajouter des branches explicites pour standard, flat_rate, cash, et annual schémas. Le schéma standard est la comptabilité d'exercice : les ventes de VAT contribuent à Box 1, l'achat de VAT à Box 4. Les factures d'autoliquidation s'ajoutent à la fois au Box 1 et au Box 4. L'importation reportée de VAT s'ajoute à la fois à Box 1 et à Box 4. Les acquisitions européennes pour les activités NI se font dans Box 2 et Box 9. Arrondissez aux totaux de la boîte, jamais par ligne. Écrivez une doctrine reliant chaque branche à sa règle.

Invite 4 - rapport d'essai à sec. "Écrire dryrun.py qui appelle compute_boxes() et émet un rapport Markdown : en-tête avec période et schéma, un tableau de Box 1 à Box 9 avec les étiquettes canoniques, une section par compartiment de classificateur répertoriant les 10 premières lignes par brut, une section d'anomalies et un pied de page avec le run_key et un SHA-256 du JSON classifié. Enregistrer dans ./audit/<period>/dryrun.md."

Invite 5 - émetteur. "Écrire submit.py contre le HMRC MTD VAT API v1.0. Utilisez le flux OAuth2 authorisation_code avec PKCE. Lire le jeton d'accès depuis ~/.vat/token.json; actualiser si expiré. En-têtes de prévention de la fraude requis tels que documentés par HMRC ; tire-les de fraud_headers.py. Par défaut, le bac à sable https://test-api.service.hmrc.gov.uk. Mesures: GET /organisations/vat/{vrn}/obligations?status=O, rechercher la période correspondante, demander à l'opérateur de confirmer en affichant le résumé de la simulation, puis POST /organisations/vat/{vrn}/returns avec finalised: true. Imprimez le receiptId. N'appelez jamais en direct à moins que HMRC_ENV=live est défini et les types d'opérateurs SOUMETTRE."

Cinq invites, quatre fichiers et un petit document de règles Markdown. Le temps total de construction était peut-être d'une semaine de soirées ciblées, dont la plupart étaient les règles du classificateur et la danse HMRC OAuth.

7. Le moteur VAT

Le moteur est la partie délibérément ennuyeuse. C'est une fonction pure avec des tests unitaires et sans IA. Voici la forme réelle :

from dataclasses import dataclass
from decimal import Decimal, ROUND_HALF_UP

D2 = Decimal("0.01")

@dataclass(frozen=True)
class BoxTotals:
    box1: Decimal
    box2: Decimal
    box3: Decimal
    box4: Decimal
    box5: Decimal
    box6: Decimal
    box7: Decimal
    box8: Decimal
    box9: Decimal

def _q(x: Decimal) -> Decimal:
    return x.quantize(D2, rounding=ROUND_HALF_UP)

def compute_boxes(rows, scheme="standard", is_ni_business=False) -> BoxTotals:
    box1 = box2 = box4 = Decimal(0)
    box6 = box7 = box8 = box9 = Decimal(0)

    for r in rows:
        gbp_net = r.net * r.fx_rate
        gbp_vat = r.vat_amount * r.fx_rate

        if r.source == "invoice":
            box6 += gbp_net
            if r.vat_treatment in ("standard", "reduced"):
                box1 += gbp_vat
            elif r.vat_treatment == "eu-goods" and is_ni_business:
                box8 += gbp_net
        else:
            box7 += gbp_net
            if r.vat_treatment in ("standard", "reduced"):
                box4 += gbp_vat
            elif r.vat_treatment == "reverse-charge":
                notional = gbp_net * (r.vat_rate / Decimal(100))
                box1 += notional
                box4 += notional
            elif r.vat_treatment == "postponed-import":
                notional = gbp_net * (r.vat_rate / Decimal(100))
                box1 += notional
                box4 += notional
            elif r.vat_treatment == "eu-goods" and is_ni_business:
                notional = gbp_net * (r.vat_rate / Decimal(100))
                box2 += notional
                box4 += notional
                box9 += gbp_net

    box3 = box1 + box2
    box5 = box3 - box4
    return BoxTotals(
        _q(box1), _q(box2), _q(box3), _q(box4), _q(box5),
        _q(box6), _q(box7), _q(box8), _q(box9),
    )

Deux choses à noter. Tout d’abord, le total de chaque boîte est quantifié une fois à la fin. L'arrondi par ligne perd des centimes et HMRC ne pardonne pas les totaux qui ne se rapprochent pas. Deuxièmement, le moteur est entièrement déterministe : même entrée, même sortie, à chaque fois. C'est la propriété qui me permet de le tester unitairement et de faire confiance au test à sec.

def test_simple_quarter():
    rows = [
        Row("invoice", net=Decimal("24500.00"), vat_amount=Decimal("4900.00"),
            vat_rate=Decimal("20"), vat_treatment="standard", fx_rate=Decimal(1), source="invoice"),
        Row("expense", net=Decimal("3000.00"), vat_amount=Decimal("600.00"),
            vat_rate=Decimal("20"), vat_treatment="standard", fx_rate=Decimal(1), source="expense"),
    ]
    t = compute_boxes(rows)
    assert t.box1 == Decimal("4900.00")
    assert t.box4 == Decimal("600.00")
    assert t.box5 == Decimal("4300.00")
    assert t.box6 == Decimal("24500.00")
    assert t.box7 == Decimal("3000.00")

Une fois cela en place, chaque régression est capturée dans CI avant même qu'elle ne touche le rapport d'essai à sec. Claude peut m'aider à passer d'autres tests ; il ne peut pas changer le moteur sans que ces tests soient réussis.

8. Vidéo de démonstration

Vous trouverez ci-dessous une brève présentation du pipeline exécuté de bout en bout sur une base de données réelle (anonymisée) de factures et de dépenses pour un trimestre : normalisation, classification, essai à sec, puis soumission MTD au bac à sable. La boucle entière dure quelques minutes.

9. Soumission HMRC MTD

C’est la partie que la plupart des articles passent sous silence. Le MTD VAT API lui-même est bien documenté et gratuit, mais il y a trois choses que vous devez faire avant d'appeler POST returns.

OAuth2 et jetons. Enregistrez une application dans le hub des développeurs HMRC ; vous obtenez un ID client, un secret client et un URI de redirection. Le flux est autorisation_code avec PKCE : ouvrez le navigateur sur la page de consentement HMRC, l'utilisateur se connecte avec ses informations d'identification Government Gateway et autorise votre application par rapport à son numéro d'enregistrement VAT (VRN), HMRC redirige avec un code d'autorisation, vous l'échangez contre un jeton d'accès + un jeton d'actualisation. Mettez-les en cache avec des autorisations raisonnables sur le disque. Le jeton d'accès est de courte durée ; le jeton d'actualisation est beaucoup plus long.

En-têtes de prévention de la fraude. HMRC nécessite un ensemble documenté d'en-têtes HTTP identifiant le périphérique d'origine à chaque appel API : fuseau horaire, géométrie de l'écran, identifiants utilisateur, adresse IP publique, adresses MAC, méthode de connexion client, etc. La liste exacte et le format se trouvent dans la documentation du développeur HMRC (voir l'avis HMRC VAT 700 et les spécifications de prévention de la fraude associées pour la règle faisant autorité). Si vous vous trompez, vous obtenez un 403 avec une vague erreur. Faites-les bien et l’appel passe. Je les garde dedans fraud_headers.py et affirmer leur présence dans les tests.

Bac à sable d'abord. HMRC fournit un bac à sable gratuit sur test-api.service.hmrc.gov.uk avec des stub VRN et des obligations de stub. Exécutez l’intégralité de votre pipeline de bout en bout sur le bac à sable jusqu’à ce que vous ayez soumis une fausse déclaration, reçu un faux identifiant de reçu et confirmé le déplacement de vos obligations. Alors seulement tu retournes HMRC_ENV=live. Mon émetteur refuse d'appeler en direct à moins que la variable d'environnement ne soit définie et que l'opérateur tape SUBMIT à l'invite. Il n'y a pas de chemin d'exécution automatique pour vivre. Le coût d’une seule mauvaise soumission en direct est bien plus élevé que le coût d’une itération sandbox supplémentaire.

L’appel du chemin heureux est court : GET obligations avec status=O pour connaître la période ouverte, afficher le rapport de marche à sec, demander à l'opérateur de confirmer, puis POST returns avec les neuf numéros de boîte, le periodKey de l'obligation, et finalised: true. Enregistrez la réponse, écrivez l’ID du reçu dans le dossier d’audit et vous avez terminé.

10. Sécurité, audit et conformité

Trois règles sur lesquelles je ne m'éloignerai pas. D'abord, Claude n'est pas dans l'arithmétique. Le classificateur suggère des traitements et le LLM peut éditer Python et les règles, mais les totaux des cases sont produits par une fonction pure avec des tests unitaires. "L'IA l'a fait" n'est pas une défense sous MTD. Deuxième, chaque soumission est contrôlée par un humain. Le rapport d’essais à sec est la source de vérité pour l’approbation. Si je ne peux pas expliquer un numéro des lignes classées et le code moteur, je ne le soumets pas. Troisième, la piste d'audit est en annexe uniquement. Chaque JSON classifié, chaque rapport d'essai, chaque invite, chaque différence et l'ID de reçu HMRC final pour la période sont écrits dans ./audit/<period>/ et engagé dans un dépôt git privé. HMRC nécessite six années d'enregistrement ; les miens sont des instantanés signés.

Deux autres pratiques que je vous recommanderais même si vous n'adoptez pas le reste. Exécuter la connexion à la base de données source en tant que rôle en lecture seule avec le moindre privilège : non UPDATE, Non DELETE, Non DROP. Conservez le secret du client HMRC et les jetons d'accès hors du référentiel à l'aide d'un gestionnaire de secrets ou d'un fichier 0600 dans votre répertoire personnel. Le but est de rendre les accidents impossibles par la construction, et pas seulement par la politique.

11. Cas extrêmes

VAT est une taxe réglementée qui a été éditée par tous les gouvernements britanniques depuis 1973, avec une superposition post-Brexit et un protocole d'Irlande du Nord en plus. Les cas limites sont réels. Une liste non exhaustive de ceux gérés par mon moteur :

  • Brexit et Irlande du Nord. Les entreprises britanniques ne remplissent plus Box 8 ou Box 9. Les entreprises NI le font toujours pour les biens (et non les services) sous le protocole NI. Le moteur prend is_ni_business comme paramètre et se branche en conséquence. Voir l'avis HMRC VAT 700 pour connaître la règle faisant autorité.
  • Charge inversée. Les services achetés auprès d'un fournisseur en dehors du Royaume-Uni (et certains services nationaux du secteur de la construction) sont comptabilisés en autoliquidation : vous ajoutez une production notionnelle VAT à Box 1 et récupérez le même montant dans Box 4. L'effet net sur la trésorerie est nul ; l'effet net sur le rendement est celui de deux cases qui bougent ensemble.
  • Importation VAT reportée. Pour les marchandises importées de l'extérieur du Royaume-Uni, vous reportez l'importation VAT à votre prochain retour plutôt que de la payer à la frontière. Le traitement ressemble à l’autoliquidation au retour.
  • Exonération partielle. Si vous effectuez à la fois des fournitures taxables et exonérées, vous pouvez récupérer l'intrant VAT uniquement dans la mesure où il se rapporte à des fournitures taxables. Il existe des méthodes standards et spéciales ; c'est le coin qui a le plus souvent besoin d'un comptable. N'essayez pas d'encoder des règles d'exemption partielle dans un fichier Markdown.
  • Régime forfaitaire. Vous facturez VAT au tarif standard mais payez à HMRC un pourcentage fixe du chiffre d'affaires brut, et vous ne pouvez généralement pas récupérer l'entrée VAT. Le moteur a une branche distincte pour cela et ignore la plupart de la classification par ligne.
  • Factures multidevises. Convertissez chaque ligne en GBP au taux en vigueur à la date concernée. HMRC publie les tarifs moyens mensuels ; vous pouvez également utiliser le taux au comptant. Soyez cohérent. Le fx_rate_to_gbp La colonne stocke le taux réel appliqué par ligne.
  • Notes de crédit. Un avoir est une facture négative. Il réduit Box 1 et Box 6 (ou Box 4 et Box 7 s'il s'agit d'un crédit d'achat). Assurez-vous que votre net_amount et vat_amount peuvent devenir négatifs et que le moteur les additionne correctement.
  • Dépôts et paiements échelonnés. Le point d'impôt peut être calculé au moment de la réception de l'acompte et non au moment de l'émission de la facture finale. La comptabilité de caisse peut simplifier cela.
  • Modifications des taux au milieu du trimestre. Historiquement rare, mais possible. Stockez le taux par ligne, et non comme une constante globale.

12. Coût

Des chiffres honnêtes. Temps de construction c'était environ une semaine de soirées ciblées - appelez ça 25 à 30 heures. La majeure partie de cela concernait la normalisation des schémas, les règles du classificateur et la rédaction des tests du moteur ; la danse HMRC OAuth était le deuxième plus gros morceau. Coût de fonctionnement par trimestre est petit : mon abonnement Claude Code existant (déjà payé pour d'autres travaux logiciels), quelques centimes d'utilisation du jeton de classificateur et zéro livre pour le HMRC API. Le moteur et le journal d'audit s'exécutent localement sur mon Mac. Temps de révision par trimestre Cela dure environ une heure, principalement consacrée à la lecture des essais avec mon comptable. Comparez cela à environ une demi-journée de travail sur des feuilles de calcul avec l'ancien flux de travail et le temps gagné rembourse le coût de construction au cours de la première année.

Si vous évaluiez cela comme un projet pour lequel vous payiez quelqu'un d'autre, vous seriez dans la fourchette à quatre chiffres en termes de tarifs de conseil - c'est pourquoi un SaaS packagé de vingt à cinquante livres par mois est presque toujours la bonne réponse pour la plupart des entreprises. La question intéressante n’est pas « est-ce moins cher que Xero ? - ce n'est généralement pas le cas - mais "est-ce plus précis, plus vérifiable et plus facile pour moi de raisonner ?". Pour moi, la réponse est oui.

13. Quelle est la prochaine étape et conclusion

Les prochains éléments que je souhaite ajouter sont : l'importation automatique de flux bancaires (Open Banking AISP), l'OCR pour les PDF des fournisseurs afin que l'URL du reçu devienne une véritable ligne numérisée, un flux d'approbation cron + Slack planifié pour que je n'aie pas à me souvenir des délais et une extension d'auto-facturation pour les vendeurs du marché. Aucun de ces éléments ne modifie la forme centrale du pipeline. Ce sont toutes des décorations sur le même diagramme à cinq voies.

La plus grande leçon, du moins pour moi, est la capacité d'un petit projet Claude Code à gérer la moitié ennuyeuse d'un flux de travail réglementé. La moitié ennuyeuse représente l'essentiel du travail : normalisation des schémas, importateurs CSV, rapports de rapprochement, paramètres, règles de cas extrêmes, journalisation d'audit. Claude est excellent dans tout ça. La moitié déterministe - les calculs réels, la soumission réelle - reste en Python simple avec des tests unitaires et une porte d'approbation humaine, exactement à sa place.

Avertissement, encore une fois. Cet article ne constitue pas un conseil fiscal. Avant de pointer quelque chose comme ça sur un vrai compte HMRC, demandez à un comptable enregistré au Royaume-Uni d'examiner votre première déclaration de bout en bout. Exécutez le bac à sable HMRC MTD jusqu'à ce que vous et votre comptable soyez tous les deux confiants. Pour connaître la règle faisant autorité sur tout traitement VAT spécifique, consultez l'avis HMRC VAT 700 et les avis associés sur le site Web gov.uk. Si vous souhaitez la version courte de tout cela, le article de blog compagnon est une lecture de cinq minutes ; sinon, abonnez-vous et je continuerai à écrire à mesure que la pile mûrira.


Aperçu SEO pour cet article

  • Titre SEO : Construisez un système de retour VAT avec Claude Code
  • Méta description : Utilisez Claude Code pour lire la base de données de vos factures et dépenses, classer VAT, calculer HMRC Box 1 à 9, effectuer un essai à sec, puis soumettre à MTD - moteur déterministe, approbation humaine.
  • Mots-clés principaux : claude-code, tva, hmrc, mtd, comptabilité, automatisation, python, ai-agent, finops, petites entreprises
  • Twitter / X (moins de 280 caractères) : J'ai reconstruit mon retour VAT au Royaume-Uni en tant que projet Claude Code : factures Postgres + dépenses DB vers HMRC Box 1 vers 9, moteur Python déterministe, soumission MTD en premier bac à sable, porte d'approbation humaine. Rédaction complète + workflow SVG + vidéo de démonstration. Pas de conseils fiscaux. #ClaudeCode #VAT #HMRC #MTD
  • Publication LinkedIn : J'ai reconstruit mon retour trimestriel VAT au Royaume-Uni en tant que petit projet Claude Code cette année. Il lit ma base de données de factures et de dépenses en lecture seule, classe chaque ligne par traitement VAT à l'aide d'un fichier de règles documenté, calcule HMRC Box 1 à 9 avec un moteur Python déterministe (pas de LLM dans l'arithmétique), et seulement après avoir signé l'essai à sec, il le soumet via le HMRC MTD API - sandbox d'abord, les en-têtes de prévention de la fraude, le flux OAuth2 complet. Le quart entier prend désormais environ une heure. Un article complet avec les invites, le schéma, le code du moteur, les cas extrêmes et l'histoire honnête des coûts se trouve sur Workstation. Pas de conseils fiscaux ; demandez à un comptable d’examiner votre première déclaration.

Watch

Construire un système de retour VAT avec Claude Code à partir de votre base de données de factures et de dépenses
Click to open in new window
Share this article

More in Technology

Health-Gated Promotions from int to prod: Inside Ring Promoter

Health-Gated Promotions from int to prod: Inside Ring Promoter

Technical deep dive: promotion protocol, version-verified health, deployers, gates, production password, auto-promote, and the CI REST API

Read more
Ring Promoter — Portes d'assurance qualité avant la production

Ring Promoter — Portes d'assurance qualité avant la production

Brief technique : portes de promotion, promotion automatique par anneau, vérification de l'état/version, porte humaine acc→prod, restauration et politique de l'équipe IA

Read more
Découvrir les goulots d'étranglement du LLM : observabilité, OTEL et contrôle des coûts

Découvrir les goulots d'étranglement du LLM : observabilité, OTEL et contrôle des coûts

Fiche technique : OTEL couvre les schémas, les collecteurs, FinOps PromQL, les budgets d'agent, la notation et les plates-formes LLM pour les agents de production

Read more