Finance Centre · Invoice Compliance
Proving HMRC-grade durability for every invoice
processed through the Finance Centre
AR Controls ERP · June 2026 · Concept Specification
The Problem
A previous server cleanup wiped locally-stored invoice PDFs. The system recovered — but only by luck. Three active failure paths remain today.
Risk 1 — DO Spaces bypass: When DigitalOcean Spaces is configured, invoices upload there and the SharePoint backup never fires. A billing lapse or outage loses files permanently.
Risk 2 — Silent failure: SharePoint upload is fire-and-forget (asyncio.create_task()). Failures are logged but never surfaced — no retry, no alert, no status on the receipt record.
Risk 3 — DB backup ≠ PDF backup: The daily encrypted MongoDB backup covers document metadata only. PDF files are excluded. Restoring the database returns broken receipt records with missing attachments.
Current State
✓ In Place
ERP Backups/ (encrypted)ERP Receipts/{YYYY}/{MM}/✗ Unverified / Missing
⚠ HMRC requires 6-year invoice retention. Until the backup chain is proven end-to-end, this obligation is not demonstrably met.
Gap Analysis
Path A — DigitalOcean Spaces configured (production)
Path B — Local storage (fallback)
Bottom line: In neither path is it currently guaranteed that every invoice PDF is safely in SharePoint. The daily DB backup exists but does not include PDF bytes — only metadata. A server wipe today would recover database records but leave PDFs permanently lost.
The Solution
ERP Receipts/{YYYY}/{MM}/.
Finance Centre Settings gains a Backup & Recovery tab with health stats and restore wizard.
UI Design
Last backup: 15 Jun 2026 14:32 · Last DB backup: 15 Jun 2026 02:01 ✓
Failed Backups (8)
#1042 Travis Perkins — SharePoint timeout [Retry]
#1037 Würth UK — Token refresh failed [Retry]
Travis Perkins
INV-2026-0041 · 14 Jun 2026
Backed up · 14 Jun 2026 at 14:32
Path: ERP Receipts/2026/06/abc123.pdf
Disaster Recovery
Step 1 — Wipe
Delete local files in uploads/receipts/ and storage/email_attachments/ on DEV only
Step 2 — Restore DB
Upload latest .json.enc via POST /api/backup/restore. Receipt records return to MongoDB.
Step 3 — Restore PDFs
Call POST /api/receipts/restore-from-sharepoint. Downloads PDFs from ERP Receipts/.
Step 4 — Verify
Finance Centre renders all receipts. Same IDs, amounts, and PDF attachments as before the wipe.
⚠ Safety constraint: All destructive steps run on DEV (100.68.36.49:3080) only. Production (erp.ar-controls.co.uk) is never touched. Drill transcript written to evidence/OP-DEXT-B/restore-drill-transcript.md.
Implementation
Files Modified
| File | Change |
|---|---|
| storage_service.py | Plug DO_SPACES bypass; write status back to receipt doc |
| receipts.py | New restore endpoint; surface backup status in responses |
| sharepoint_service.py | Fix error paths; return structured result with path |
| ReceiptsSettings.jsx | Add "Backup & Recovery" tab |
| ReceiptDetail.jsx | Add SharePoint backup status badge |
Data Model Change
Stack
Done When…
sharepoint_backup_status: success.orch-done.json written after end-to-end proofDelivery Plan
▶ This Slice — OP-DEXT-B Audit
◯ Later Slices — OP-DEXT-B Full Scope
Questions before implementation → see concept.md §Open Questions (SharePoint DEV credentials, DO_SPACES config, backup timing preference)