What you get in the generated ZIP
A typical invoicing generation includes:
app/blueprints/
├── invoice_bp.py # CRUD + state machine: draft → sent → paid → overdue → cancelled
├── customer_bp.py # billing entity, separate from auth user
├── line_item_bp.py
├── payment_bp.py # immutable payment attempt log
├── refund_bp.py
├── tax_rate_bp.py # per-jurisdiction matrix
├── webhook_bp.py # provider webhook signature verification
└── reporting_bp.py # AR aging, revenue by period, top customers
app/models/
├── invoice.py # immutable once sent (regenerate creates v2)
├── payment.py # idempotency_key UNIQUE, status: pending/succeeded/failed
└── audit_log.py # every charge attempt, refund, manual edit
docs/compliance/
├── pci-scope-statement.md # SAQ-A or SAQ-D depending on whether you touch raw PAN
├── sox-controls.md # §404 controls if SOX overlay flagged
└── audit-trail-policy.md
What's already wired
- Idempotency: every payment attempt requires an idempotency key; the model enforces uniqueness; replays return the original outcome instead of double-charging.
- Webhook signature verification: Stripe / Paystack / Flutterwave webhooks all verify the signature before processing. Replay protection via webhook event-ID dedup.
- Refund flow: refunds go through the same payment provider, with a reverse transaction recorded against the original. Full and partial refunds supported.
- Tax-rate matrix: per-jurisdiction lookup; rates are versioned with effective dates so historical invoices keep their original tax even when current rates change.
- Multi-currency: amounts stored in minor units (cents/kobo) as integers, never floats. Currency is part of the invoice, locked at issue time.
- Audit log: every state transition, every payment attempt, every manual override is logged with actor, timestamp, before/after, and reason. SOC 2 sampling-ready.
- AR aging report: standard 0-30 / 31-60 / 61-90 / 90+ buckets, exportable to CSV.
PCI-DSS scope
If your PRD touches card data, the generated docs/compliance/pci-scope-statement.md documents your SAQ category. Most generated invoicing systems land at SAQ-A (you tokenise via the provider, never touch raw PAN) — the scope statement explains why and references the specific code paths that handle the tokens. SAQ-D scope (if you ever store raw PAN) is generated only if your PRD explicitly requires it; we recommend against it.
The scope statement is auditor-ready as a starting evidence package. It references the Archiet-generated routes that handle payment data and the controls in place at each.
Internal links
- Stripe integration, Paystack integration, Flutterwave integration cover provider wiring
- for/fintech covers the broader compliance overlay
CTA
Try it — free plan, no credit card. archiet.com.
Generate an invoicing system, look at the idempotency handling and the audit log, decide if that's the shape your auditor would accept.