- Added FastAPI views for supplier invoices in the billing frontend. - Created EconomicService for handling e-conomic API interactions, including safety modes for read-only and dry-run operations. - Developed database migration for supplier invoices, including tables for invoices, line items, and settings. - Documented kassekladde module features, architecture, API endpoints, and usage guide in KASSEKLADDE.md. - Implemented views for overdue invoices and pending e-conomic sync.
9.3 KiB
Kassekladde (Supplier Invoices) - BMC Hub
Overview
BMC Hub's kassekladde module enables management of supplier invoices (incoming invoices that the company must pay) with full integration to e-conomic accounting system via the journals/vouchers API.
Features
✅ Complete CRUD Operations
- Create, view, update, and delete supplier invoices
- Multi-line invoice support with VAT breakdown
- Vendor linking and automatic creation in e-conomic
✅ Approval Workflow
- Pending → Approved → Sent to e-conomic → Paid
- Approval tracking with user and timestamp
✅ e-conomic Integration
- Automatic supplier matching and creation
- Journal/voucher posting to kassekladde
- PDF attachment upload to vouchers
- Configurable journal number and default accounts
✅ VAT Handling
- Support for multiple VAT codes (I25, I0, IY25, etc.)
- Automatic VAT calculation per line
- VAT breakdown in e-conomic entries
✅ Nordic Top UI
- Modern, clean design
- Real-time statistics dashboard
- Filter and search functionality
- Responsive mobile support
Architecture
Database Schema
Main Tables:
supplier_invoices- Invoice headers with e-conomic trackingsupplier_invoice_lines- Line items with VAT and account detailssupplier_invoice_settings- System configurationvendors- Supplier information with e-conomic IDs
Views:
overdue_supplier_invoices- All overdue unpaid invoicespending_economic_sync- Approved invoices ready for e-conomic
Backend Structure
app/
billing/
backend/
supplier_invoices.py # FastAPI router with endpoints
frontend/
supplier_invoices.html # Nordic Top UI
views.py # Frontend routes
services/
economic_service.py # e-conomic API integration
API Endpoints
CRUD Operations:
GET /api/v1/supplier-invoices- List invoices with filtersGET /api/v1/supplier-invoices/{id}- Get invoice detailsPOST /api/v1/supplier-invoices- Create new invoicePUT /api/v1/supplier-invoices/{id}- Update invoiceDELETE /api/v1/supplier-invoices/{id}- Delete invoice
Workflow Actions:
POST /api/v1/supplier-invoices/{id}/approve- Approve invoicePOST /api/v1/supplier-invoices/{id}/send-to-economic- Send to e-conomic
Statistics:
GET /api/v1/supplier-invoices/stats/overview- Payment overviewGET /api/v1/supplier-invoices/stats/by-vendor- Stats by vendor
e-conomic Integration:
GET /api/v1/supplier-invoices/economic/journals- Available kassekladder
Installation & Setup
1. Database Migration
Run the migration to create tables:
# Execute migration SQL
psql -U bmc_hub -d bmc_hub < migrations/008_supplier_invoices.sql
Or via Docker:
docker-compose exec postgres psql -U bmc_hub -d bmc_hub < /app/migrations/008_supplier_invoices.sql
2. Configure e-conomic Credentials
Add to .env file:
# e-conomic Integration
ECONOMIC_API_URL=https://restapi.e-conomic.com
ECONOMIC_APP_SECRET_TOKEN=your_app_secret_token
ECONOMIC_AGREEMENT_GRANT_TOKEN=your_agreement_grant_token
# Safety switches (ALWAYS start with these enabled)
ECONOMIC_READ_ONLY=true
ECONOMIC_DRY_RUN=true
3. Configure Default Settings
The default journal number and accounts can be configured via database:
-- Update default kassekladde number
UPDATE supplier_invoice_settings
SET setting_value = '1'
WHERE setting_key = 'economic_default_journal';
-- Update default expense account
UPDATE supplier_invoice_settings
SET setting_value = '5810'
WHERE setting_key = 'economic_default_contra_account';
4. Restart Application
docker-compose restart api
Usage Guide
Creating a Supplier Invoice
- Navigate to
/billing/supplier-invoices - Click "Ny Faktura" button
- Fill in required fields:
- Invoice number (from supplier)
- Vendor (select from dropdown)
- Invoice date
- Total amount (incl. VAT)
- Add line items with:
- Description
- Quantity & price
- VAT code (25%, 0%, reverse charge, etc.)
- Click "Gem" to save
Approval Workflow
Status Flow:
pending → approved → sent_to_economic → paid
Steps:
- Invoice created → Status:
pending - Review and approve → Status:
approved - Send to e-conomic → Status:
sent_to_economic(voucher created) - Mark as paid → Status:
paid
Sending to e-conomic
Prerequisites:
- Invoice must be
approved - Vendor must exist (auto-created if needed)
- At least one line item
Process:
- Click "Send til e-conomic" button
- System will:
- Check/create vendor in e-conomic
- Build VAT breakdown from lines
- Create journal voucher entry
- Upload PDF attachment (if available)
- Update invoice with voucher number
Result:
- Voucher created in e-conomic kassekladde
- Invoice status →
sent_to_economic - Voucher number stored for reference
e-conomic Integration Details
Safety Modes
READ_ONLY Mode (default: true)
- Blocks ALL write operations to e-conomic
- Only GET requests allowed
- Use for testing API connection
DRY_RUN Mode (default: true)
- Logs all operations but doesn't send to e-conomic
- Full payload preview in logs
- Safe for development/testing
Production Mode (both false)
- Actually sends data to e-conomic
- ⚠️ Use with caution!
- Always test with dry-run first
Journal Voucher Structure
e-conomic vouchers use this format:
{
"accountingYear": {"year": "2025"},
"journal": {"journalNumber": 1},
"entries": {
"supplierInvoices": [
{
"supplier": {"supplierNumber": 123},
"amount": 1250.00,
"contraAccount": {"accountNumber": 5810},
"currency": {"code": "DKK"},
"date": "2025-12-06",
"dueDate": "2026-01-05",
"supplierInvoiceNumber": "INV-12345",
"text": "Invoice description",
"contraVatAccount": {"vatCode": "I25"},
"contraVatAmount": 250.00
}
]
}
}
VAT Code Mapping
| VAT Code | Description | Rate | Use Case |
|---|---|---|---|
I25 |
Indenlandsk købsmoms 25% | 25% | Standard Danish purchases |
I0 |
Momsfri køb | 0% | VAT exempt |
IY25 |
Omvendt betalingspligt 25% | 25% | Reverse charge |
IYEU |
Omvendt EU | 0% | EU reverse charge |
IVEU |
Erhvervelse EU | 25% | EU acquisition |
Account Number Mapping
Default expense accounts (can be customized per line):
5810- Drift og materialer (default)5820- IT og software5830- Telefoni og internet5840- Kontorartikler6000- Løn og honorarer
Development Guide
Adding New Features
1. Backend Endpoint:
# app/billing/backend/supplier_invoices.py
@router.post("/supplier-invoices/{invoice_id}/custom-action")
async def custom_action(invoice_id: int):
# Your logic here
return {"success": True}
2. Frontend Integration:
// supplier_invoices.html
async function customAction(invoiceId) {
const response = await fetch(`/api/v1/supplier-invoices/${invoiceId}/custom-action`, {
method: 'POST'
});
// Handle response
}
Testing e-conomic Integration
1. Test Connection:
from app.services.economic_service import get_economic_service
economic = get_economic_service()
result = await economic.test_connection()
# Should return True if credentials are valid
2. Test Dry-Run Mode:
# In .env
ECONOMIC_READ_ONLY=false
ECONOMIC_DRY_RUN=true
Then create and approve an invoice, send to e-conomic. Check logs for full payload without actually posting.
3. Production Test:
# WARNING: This will create real data in e-conomic!
ECONOMIC_READ_ONLY=false
ECONOMIC_DRY_RUN=false
Start with a small test invoice to verify everything works.
Troubleshooting
Issue: "No journals found"
Solution: Check e-conomic credentials and ensure user has access to journals/kassekladder.
Issue: "Supplier not found in e-conomic"
Solution: System will auto-create supplier if ECONOMIC_DRY_RUN=false. Verify vendor name is correct.
Issue: "VAT validation failed"
Solution: Ensure VAT codes match e-conomic settings. Check vat_code in line items (I25, I0, etc.).
Issue: "Voucher creation failed"
Solution:
- Check e-conomic API logs in application logs
- Verify journal number exists in e-conomic
- Ensure all required fields are present (supplier, amount, date)
- Check contra account number is valid
Integration with OmniSync
This module is based on OmniSync's proven kassekladde implementation with the following enhancements:
- ✅ PostgreSQL instead of SQLite
- ✅ Nordic Top design instead of custom CSS
- ✅ Integrated with BMC Hub's vendor system
- ✅ Simplified approval workflow
- ✅ Better error handling and logging
References
- e-conomic API Docs: https://restdocs.e-conomic.com/
- Journals API: https://restdocs.e-conomic.com/#journals
- Vouchers API: https://restdocs.e-conomic.com/#vouchers
- Suppliers API: https://restdocs.e-conomic.com/#suppliers
Support
For issues or questions:
- Check application logs:
docker-compose logs -f api - Review e-conomic API response in logs
- Test with DRY_RUN mode first
- Contact system administrator
Last Updated: December 6, 2025
Version: 1.0.0
Maintained by: BMC Networks Development Team