bmc_hub/docs/KASSEKLADDE.md
Christian dcb4d8a280 feat: Implement supplier invoices management with e-conomic integration
- 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.
2025-12-07 03:29:54 +01:00

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 tracking
  • supplier_invoice_lines - Line items with VAT and account details
  • supplier_invoice_settings - System configuration
  • vendors - Supplier information with e-conomic IDs

Views:

  • overdue_supplier_invoices - All overdue unpaid invoices
  • pending_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 filters
  • GET /api/v1/supplier-invoices/{id} - Get invoice details
  • POST /api/v1/supplier-invoices - Create new invoice
  • PUT /api/v1/supplier-invoices/{id} - Update invoice
  • DELETE /api/v1/supplier-invoices/{id} - Delete invoice

Workflow Actions:

  • POST /api/v1/supplier-invoices/{id}/approve - Approve invoice
  • POST /api/v1/supplier-invoices/{id}/send-to-economic - Send to e-conomic

Statistics:

  • GET /api/v1/supplier-invoices/stats/overview - Payment overview
  • GET /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

  1. Navigate to /billing/supplier-invoices
  2. Click "Ny Faktura" button
  3. Fill in required fields:
    • Invoice number (from supplier)
    • Vendor (select from dropdown)
    • Invoice date
    • Total amount (incl. VAT)
  4. Add line items with:
    • Description
    • Quantity & price
    • VAT code (25%, 0%, reverse charge, etc.)
  5. Click "Gem" to save

Approval Workflow

Status Flow:

pending → approved → sent_to_economic → paid

Steps:

  1. Invoice created → Status: pending
  2. Review and approve → Status: approved
  3. Send to e-conomic → Status: sent_to_economic (voucher created)
  4. 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:

  1. Click "Send til e-conomic" button
  2. 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 software
  • 5830 - Telefoni og internet
  • 5840 - Kontorartikler
  • 6000 - 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:

  1. Check e-conomic API logs in application logs
  2. Verify journal number exists in e-conomic
  3. Ensure all required fields are present (supplier, amount, date)
  4. 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

Support

For issues or questions:

  1. Check application logs: docker-compose logs -f api
  2. Review e-conomic API response in logs
  3. Test with DRY_RUN mode first
  4. Contact system administrator

Last Updated: December 6, 2025
Version: 1.0.0
Maintained by: BMC Networks Development Team