Invoicing Payments Blueprint

Invoicing and payment lifecycle: customer invoices, vendor bills, credit notes, receipts, payment registration, multi-currency, and follow-up.

   
Feature invoicing-payments
Category Payment
Version 1.0.0
Tags invoicing, payments, billing, credit-notes, multi-currency, accounting
YAML Source View on GitHub
JSON API invoicing-payments.json

Actors

ID Name Type Description
accountant Accountant human Creates, validates, and posts invoices; registers payments
customer Customer human Receives invoices, makes payments via portal or bank transfer
vendor Vendor human Sends bills that are recorded and paid
system Accounting System system Computes balances, reconciles payments, tracks due dates

Fields

Name Type Required Label Description
move_type select Yes Document Type  
invoice_state select Yes State  
payment_state select Yes Payment State  
partner_id text Yes Customer/Vendor  
invoice_date date Yes Invoice Date  
invoice_date_due date Yes Due Date  
amount_untaxed number Yes Untaxed Amount  
amount_tax number Yes Tax Amount  
amount_total number Yes Total Amount  
amount_residual number Yes Amount Due  
currency_id text Yes Currency  
journal_id text Yes Journal  
payment_term_id text No Payment Terms  
fiscal_position_id text No Fiscal Position  
invoice_lines json Yes Invoice Lines  
payment_amount number Yes Payment Amount  
payment_method select Yes Payment Method  
payment_reference text No Payment Reference  

States

State field: invoice_state

Values:

State Initial Terminal
draft Yes  
posted    
cancel   Yes

Transitions:

Name From To Actor Condition
  draft posted accountant All required fields populated, amounts balanced
  posted draft accountant Must not be in a state requiring cancellation request
  draft,posted cancel accountant  

Rules

  • balanced_journal_entry:
    • description: Total debits must equal total credits in every journal entry
  • draft_only_editable:
    • description: Only draft invoices can be edited; posted invoices are locked
  • reset_clears_attachments:
    • description: Resetting to draft removes generated PDFs and report attachments
  • payment_term_computes_due_date:
    • description: Due date automatically calculated from invoice date and payment terms
  • fiscal_position_maps_taxes:
    • description: Fiscal position automatically remaps tax lines based on customer jurisdiction
  • multi_currency_rate_at_date:
    • description: Multi-currency invoices use the exchange rate at invoice date for conversion. Payment reconciliation computes exchange differences.
  • lock_date_prevents_posting:
    • description: Cannot post entries dated before the company accounting lock date
  • sequence_numbering:
    • description: Posted invoices receive a sequential number that cannot be reused

Outcomes

Invoice_posted (Priority: 1) — Error: INVOICE_ALREADY_POSTED

Given:

  • accountant creates a draft invoice with lines
  • all lines have valid accounts and amounts

Then:

  • transition_state field: invoice_state from: draft to: posted
  • set_field target: invoice_number — Sequential number assigned from journal sequence
  • emit_event event: account.invoice.posted

Result: Invoice posted to accounting, number assigned, available on customer portal

Posting_blocked_lock_date (Priority: 1) — Error: INVOICE_BEFORE_LOCK_DATE

Given:

  • invoice date is before the company accounting lock date

Then:

  • notify — Show lock date and prevent posting

Result: Invoice cannot be posted until date is after lock date

Payment_registered (Priority: 2)

Given:

  • invoice is posted with outstanding balance
  • accountant registers a payment

Then:

  • create_record target: payment — Payment record created and linked to invoice
  • set_field target: amount_residual — Residual amount reduced by payment
  • set_field target: payment_state — Updated to partial, in_payment, or paid based on remaining balance
  • emit_event event: account.payment.registered

Result: Payment recorded, invoice balance updated accordingly

Invoice_fully_paid (Priority: 3)

Given:

  • total payments match or exceed invoice amount

Then:

  • set_field target: payment_state value: paid
  • emit_event event: account.invoice.paid

Result: Invoice marked as fully paid, no remaining balance

Credit_note_created (Priority: 4)

Given:

  • accountant reverses a posted invoice

Then:

  • create_record target: credit_note — Credit note (out_refund or in_refund) created referencing original
  • emit_event event: account.credit_note.created

Result: Credit note created and optionally reconciled against original invoice

Given:

  • invoice is posted with outstanding balance
  • accountant generates a payment link

Then:

  • emit_event event: account.payment_link.sent

Result: Customer receives link to pay online via portal

Errors

Code Status Message Retry
INVOICE_BEFORE_LOCK_DATE 400 Cannot post an entry dated before the accounting lock date. No
INVOICE_UNBALANCED 400 The journal entry is not balanced. Debits must equal credits. No
INVOICE_NO_LINES 400 Cannot post an invoice with no lines. No
INVOICE_ALREADY_POSTED 403 This invoice has already been posted and cannot be edited. No
PAYMENT_EXCEEDS_BALANCE 400 Payment amount exceeds the remaining balance on this invoice. No

Events

Event Description Payload
account.invoice.posted Invoice validated and posted to the ledger invoice_id, move_type, partner_id, amount_total
account.invoice.paid Invoice fully paid invoice_id, partner_id, amount_total
account.payment.registered Payment recorded against an invoice payment_id, invoice_id, amount, payment_method
account.credit_note.created Credit note created to reverse an invoice credit_note_id, original_invoice_id, amount
account.payment_link.sent Payment link generated and sent to customer invoice_id, payment_link_url, partner_id
Feature Relationship Reason
tax-engine required Tax computation on every invoice line
bank-reconciliation required Bank statement lines reconciled against invoice payments
quotation-order-management optional Invoices generated from confirmed sales orders
pos-core optional POS session closing generates accounting entries

AGI Readiness

Goals

Reliable Invoicing Payments

Invoicing and payment lifecycle: customer invoices, vendor bills, credit notes, receipts, payment registration, multi-currency, and follow-up.

Success Metrics:

Metric Target Measurement
policy_violation_rate 0% Operations that violate defined policies
audit_completeness 100% All decisions have complete audit trails

Constraints:

  • regulatory (non-negotiable): All operations must be auditable and traceable

Autonomy

Level: supervised

Human Checkpoints:

  • before transitioning to a terminal state

Escalation Triggers:

  • error_rate > 5
  • consecutive_failures > 3

Verification

Invariants:

  • error messages never expose internal system details
  • state transitions follow the defined state machine — no illegal transitions

Tradeoffs

Prefer Over Reason
accuracy speed financial transactions must be precise and auditable

Coordination

Protocol: orchestrated

Consumes:

Capability From Fallback
tax_engine tax-engine fail
bank_reconciliation bank-reconciliation fail

Safety

Action Permission Cooldown Max Auto
invoice_posted autonomous - -
payment_registered autonomous - -
invoice_fully_paid autonomous - -
credit_note_created supervised - -
payment_link_sent autonomous - -
posting_blocked_lock_date human_required - -
Extensions (framework-specific hints) ```yaml source: repo: https://github.com/odoo/odoo.git project: Odoo tech_stack: Python + JavaScript/OWL files_traced: 40 entry_points: - addons/account/models/account_move.py - addons/account/models/account_payment.py - addons/account_payment/models/account_payment.py - addons/account/models/account_move_line.py ```