51 KiB
Invoice Expense Tracking - Design Document
Overview
Track expenses paid on behalf of customers directly on invoices, with automatic accounting settlement.
Key Concept: "Customer Fund" is conceptual - it means "expenses we'll charge to the customer". It's a monitoring/tracking mechanism, NOT a deposit account. Customer deposits are handled by a separate module.
Design Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Invoice Line Account | Uses same Asset account (Customer Expenses Receivable) | Directly credits/settles the asset |
| Tax Treatment | No tax on expenses | Pass-through charges, not revenue |
| Currency | Single currency only | Simplified implementation |
| Partial Addition | Not allowed | One expense = One invoice line |
| Expense Splitting | Not allowed | Create multiple expenses instead |
| Payment Source | Always Bank | No need to track source (customer deposits handled separately) |
| Invoice-MO Link | Required | Invoice must be linked to Master Order |
| Settlement | Automatic when added to invoice | Asset account credited |
| Collection | Standard AR process | Sales team follows up with customer |
| Default Expense Type | Customer Expense | invoice_to_customer = True by default |
Business Flow
┌─────────────────────────────────────────────────────────────────────────────────┐
│ EXPENSE TRACKING FLOW │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. PAY EXPENSE 2. TRACK ON INVOICE │
│ ─────────────── ──────────────────── │
│ │
│ Company pays on behalf Record expense on │
│ of customer: customer invoice: │
│ │
│ • Certificate Fee: $100 Invoice #INV/2026/001 │
│ • Customs: $200 ├── Products: $5,000 │
│ • Documentation: $50 ├── Certificate Fee: $100 │
│ ├── Customs: $200 │
│ Paid from: └── Documentation: $50 │
│ Bank / Customer Expenses Fund │
│ TOTAL: $5,350 │
│ │
│ │
│ 3. CUSTOMER PAYS 4. SETTLEMENT │
│ ──────────────── ─────────────── │
│ │
│ Customer pays invoice Expense account is │
│ total: $5,350 automatically settled │
│ │
│ ✅ Products paid ✅ No manual reconciliation │
│ ✅ Expenses reimbursed ✅ Clean accounting │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Accounting Entries
Step 1: Pay Expense (Manual or Bank Transaction)
When company pays expense on behalf of customer:
| Account | Debit | Credit |
|---|---|---|
| Customer Expenses Receivable (Asset) | $100 | |
| Bank Account | $100 |
Step 2: Create Invoice with Expense
When expense is added to customer invoice:
| Account | Debit | Credit |
|---|---|---|
| Accounts Receivable (Customer) | $5,100 | |
| Sales Revenue | $5,000 | |
| Customer Expenses Receivable (Asset) | $100 |
Result: Expense receivable is credited (settled)
Expense Types - Customer vs Company
Two Types of Expenses
| Type | invoice_to_customer |
Account Used | Can Add to Invoice? |
|---|---|---|---|
| Customer Expense (Default) | ✅ True | Customer Expenses Receivable (Asset) | Yes |
| Company Expense | ☐ False | Company Expense Account (P&L) | No |
Default Behavior
┌─────────────────────────────────────────────────────────────────┐
│ CREATE EXPENSE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Expense Type: [Shipping ▼] │
│ Description: [Certificate Fee ] │
│ Amount: [$100 ] │
│ Date: [2026-01-10 ] │
│ │
│ ☑️ Invoice to Customer ← DEFAULT IS CHECKED │
│ └─ Checked: Customer pays (Asset account) │
│ └─ Unchecked: Company absorbs (P&L account) │
│ │
└─────────────────────────────────────────────────────────────────┘
Customer Expense Flow (Default)
Payment: Debit: Customer Expenses Receivable (Asset)
Credit: Bank
Settlement: Add to customer invoice
→ Asset credited (zeroed)
→ Customer owes via AR
Company Expense Flow (Unchecked)
Payment: Debit: Company Expense Account (P&L)
Credit: Bank
No settlement needed - direct expense recognition
Cannot be added to customer invoice
Reclassification: Customer → Company (Company Absorbs)
If expense was created as customer expense but company decides to absorb:
| Expense Status | Action | Accounting |
|---|---|---|
| Not on invoice | Click [Company Absorbs] | Debit P&L, Credit Asset |
| On draft invoice | Remove from invoice first, then reclassify | Remove line + Debit P&L, Credit Asset |
| On posted invoice | Create Credit Note + Reclassify | Reverse AR + Move to P&L |
Step 3: Customer Pays Invoice
When customer pays the full invoice:
| Account | Debit | Credit |
|---|---|---|
| Bank Account | $5,100 | |
| Accounts Receivable (Customer) | $5,100 |
Result: Full settlement complete
Workflows for Adding Expenses to Invoice
Workflow A: Select Existing Pending Expenses
User creates invoice FIRST, then adds expenses that were already paid earlier.
┌─────────────────────────────────────────────────────────────────┐
│ ADD EXISTING EXPENSE TO INVOICE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User is on DRAFT Invoice Form │
│ │
│ 1. Clicks [+ Add Existing Expense] button │
│ │
│ 2. System shows selection wizard: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ SELECT PENDING EXPENSES │ │
│ │ Customer: ABC Trading Co. │ │
│ │ │ │
│ │ ☐ Certificate Fee $100 Paid: Jan 05 │ │
│ │ ☐ Customs Clearance $200 Paid: Jan 07 │ │
│ │ ☐ Documentation $50 Paid: Jan 08 │ │
│ │ │ │
│ │ Filter: Same customer + Status=Pending │ │
│ │ │ │
│ │ [Cancel] [Add Selected to Invoice] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 3. User selects expenses → System adds invoice lines │
│ │
│ 4. Expenses marked as "Added to Invoice" │
│ │
└─────────────────────────────────────────────────────────────────┘
Workflow B: Create New Expense Directly on Invoice (Simplified)
User wants to record an expense and add to invoice. Payment entry is handled separately (manual or already exists).
┌─────────────────────────────────────────────────────────────────┐
│ CREATE & ADD NEW EXPENSE (Simplified) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User is on DRAFT Invoice Form │
│ │
│ 1. Clicks [+ Create New Expense] button │
│ │
│ 2. System shows creation wizard: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ CREATE NEW EXPENSE │ │
│ │ │ │
│ │ Expense Account: [Customer Expenses Receivable ▼] │ │
│ │ (pre-filled from configuration) │ │
│ │ Expense Type: [Shipping / Customs / Other ▼] │ │
│ │ Description: [Certificate Fee ] │ │
│ │ Amount: [$100 ] │ │
│ │ Date: [2026-01-10 ] │ │
│ │ │ │
│ │ ℹ️ Payment entry should be created separately │ │
│ │ │ │
│ │ [Cancel] [Create & Add to Invoice]│ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 3. System creates: │
│ a) Expense record (linked to Master Order from invoice) │
│ b) Invoice line (using Asset account = settlement) │
│ │
│ Note: Payment journal entry is NOT auto-created. │
│ User creates payment entry manually/separately. │
│ │
└─────────────────────────────────────────────────────────────────┘
Note: In this simplified workflow, the expense is created and immediately added to invoice. The payment entry (Debit Asset, Credit Bank) must be handled separately by the user. This keeps the system simple and flexible.
Edge Cases & Business Rules
State-Based Rules
| Invoice State | Add Existing Expense | Create New Expense | Remove Expense |
|---|---|---|---|
| DRAFT | ✅ Allowed | ✅ Allowed | ✅ Allowed |
| POSTED | ❌ Blocked | ❌ Blocked | ❌ Blocked |
| CANCELLED | ❌ Blocked | ❌ Blocked | N/A |
Edge Case Solutions
| Edge Case | Decision | Solution |
|---|---|---|
| Partial expense addition | ❌ Not allowed | Create multiple expenses at start |
| Remove from DRAFT invoice | ✅ Allowed | Reset expense status to "Pending" |
| Remove from POSTED invoice | ❌ Not allowed | Must use Credit Note workflow |
| Split expense across invoices | ❌ Not allowed | Create multiple expense records |
| Add to POSTED invoice | ❌ Not allowed | Create new supplementary invoice |
| Edit amount (not invoiced) | ✅ Allowed | Direct edit on expense |
| Edit amount (on draft invoice) | Requires steps | Remove → Edit → Re-add |
| Edit amount (on posted invoice) | ❌ Not allowed | Credit Note required |
| Invoice cancelled | ✅ Auto-reset | All expenses return to "Pending" |
| Customer mismatch | ❌ Blocked | Validation error prevents action |
Remove Expense from Draft Invoice
┌─────────────────────────────────────────────────────────────────┐
│ REMOVE EXPENSE FROM DRAFT INVOICE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. User clicks [Remove] on expense line │
│ │
│ 2. System actions: │
│ • Delete the corresponding invoice line │
│ • Reset expense: added_to_invoice = False │
│ • Clear links: invoice_id = False, invoice_line_id = False │
│ │
│ 3. Result: │
│ • Expense returns to "Pending" status │
│ • Can be added to different invoice │
│ • Invoice total recalculates automatically │
│ │
└─────────────────────────────────────────────────────────────────┘
Correct Expense on Posted Invoice (Credit Note Flow)
┌─────────────────────────────────────────────────────────────────┐
│ CORRECT EXPENSE ON POSTED INVOICE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Cannot directly modify posted invoice. Steps: │
│ │
│ 1. Create Credit Note for the expense amount only │
│ • Debits: Customer Expenses Receivable (reverses credit) │
│ • Credits: Accounts Receivable (reduces customer balance) │
│ │
│ 2. Post the Credit Note │
│ │
│ 3. Create new invoice with expense on correct customer │
│ (if needed) │
│ │
│ Result: Original expense receivable is restored, can be │
│ properly re-invoiced │
│ │
└─────────────────────────────────────────────────────────────────┘
Invoice Cancellation - Expense Handling
┌─────────────────────────────────────────────────────────────────┐
│ INVOICE CANCELLATION │
├─────────────────────────────────────────────────────────────────┤
│ │
│ When invoice is cancelled, system automatically: │
│ │
│ 1. Resets ALL linked expenses: │
│ • added_to_invoice = False │
│ • invoice_id = False │
│ • invoice_line_id = False │
│ │
│ 2. Expenses return to "Pending" status │
│ │
│ 3. Expenses can be added to new invoice later │
│ │
└─────────────────────────────────────────────────────────────────┘
Customer Validation Rule
Validation: Expense.master_order_id.partner_id == Invoice.partner_id
If mismatch → Block with error:
"Expense belongs to [Customer A] but invoice is for [Customer B]"
Company Absorbs Cost (Reclassification)
When expense should NOT be charged to customer:
Original Entry:
Debit: Customer Expenses Receivable $100
Credit: Bank $100
Reclassification Entry:
Debit: Company Expense Account $100
Credit: Customer Expenses Receivable $100
Result: Cost moved from asset to company expense
Data Model
Expense Model (Simplified)
class MasterOrderExpense(models.Model):
_name = 'at.master.order.expense'
# Links
master_order_id = fields.Many2one('at.master.order')
invoice_id = fields.Many2one('account.move') # NEW - link to invoice
# Expense Details
expense_account_id = fields.Many2one('account.account') # PRIMARY - select from COA
description = fields.Char('Description')
amount = fields.Float('Amount')
date = fields.Date('Date')
# Status
added_to_invoice = fields.Boolean('Added to Invoice') # Track if converted to invoice line
invoice_line_id = fields.Many2one('account.move.line') # Link to created invoice line
Invoice Model (Extended)
class AccountMove(models.Model):
_inherit = 'account.move'
# Expense tracking
expense_ids = fields.One2many('at.master.order.expense', 'invoice_id')
# Computed totals
invoice_total_expenses = fields.Float(compute='_compute_expense_totals')
UI Design
1. Invoice Form - Expenses Tab (DRAFT)
┌───────────────────────────────────────────────────────────────────────────────────┐
│ 📋 CUSTOMER INVOICE (DRAFT) INV/2026/00123 │
├───────────────────────────────────────────────────────────────────────────────────┤
│ Customer: ABC Trading Co. │ Invoice Date: 2026-01-10 │
│ Master Order: MO/2026/00045 │ Due Date: 2026-02-10 │
├───────────────────────────────────────────────────────────────────────────────────┤
│ │
│ [Invoice Lines] [Expenses] [Other Info] │
│ ════════════════════════════════════════════════════════════════════════════════ │
│ │
│ EXPENSES ON THIS INVOICE │
│ ┌────────────────────────┬─────────────────┬──────────┬──────────┬─────────────┐ │
│ │ Type │ Description │ Amount │ Date │ Action │ │
│ ├────────────────────────┼─────────────────┼──────────┼──────────┼─────────────┤ │
│ │ Customs │ Import Duty │ $200 │ Jan 05 │ [Remove] │ │
│ │ Documentation │ Certificate Fee │ $100 │ Jan 07 │ [Remove] │ │
│ │ Shipping │ Air Freight │ $350 │ Jan 08 │ [Remove] │ │
│ └────────────────────────┴─────────────────┴──────────┴──────────┴─────────────┘ │
│ Expenses Total: $650 │
│ │
│ [+ Add Existing Expense] [+ Create New Expense] │
│ │
│ ════════════════════════════════════════════════════════════════════════════════ │
│ │
│ PENDING EXPENSES (Not Yet Added) │
│ ┌────────────────────────┬─────────────────┬──────────┬──────────┬─────────────┐ │
│ │ Type │ Description │ Amount │ Date │ Action │ │
│ ├────────────────────────┼─────────────────┼──────────┼──────────┼─────────────┤ │
│ │ Handling │ Warehouse Fee │ $75 │ Jan 09 │ [+ Add] │ │
│ │ Other │ Inspection │ $50 │ Jan 10 │ [+ Add] │ │
│ └────────────────────────┴─────────────────┴──────────┴──────────┴─────────────┘ │
│ Pending Total: $125 │
│ │
│ ════════════════════════════════════════════════════════════════════════════════ │
│ │
│ SUMMARY │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ Product Lines: $5,000 │ │
│ │ Expenses on Invoice: $650 │ │
│ │ ───────────────────────────────── │ │
│ │ INVOICE TOTAL: $5,650 │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────────────────┘
2. Invoice Form - Expenses Tab (POSTED - Read Only)
┌───────────────────────────────────────────────────────────────────────────────────┐
│ 📋 CUSTOMER INVOICE (POSTED) INV/2026/00123 │
├───────────────────────────────────────────────────────────────────────────────────┤
│ Customer: ABC Trading Co. │ Invoice Date: 2026-01-10 │
│ Master Order: MO/2026/00045 │ Status: Posted ✓ │
├───────────────────────────────────────────────────────────────────────────────────┤
│ │
│ [Invoice Lines] [Expenses] [Other Info] │
│ ════════════════════════════════════════════════════════════════════════════════ │
│ │
│ EXPENSES ON THIS INVOICE (Read-only - Invoice Posted) │
│ ┌────────────────────────┬─────────────────┬──────────┬──────────┬─────────────┐ │
│ │ Type │ Description │ Amount │ Date │ Status │ │
│ ├────────────────────────┼─────────────────┼──────────┼──────────┼─────────────┤ │
│ │ Customs │ Import Duty │ $200 │ Jan 05 │ ✓ Settled │ │
│ │ Documentation │ Certificate Fee │ $100 │ Jan 07 │ ✓ Settled │ │
│ │ Shipping │ Air Freight │ $350 │ Jan 08 │ ✓ Settled │ │
│ └────────────────────────┴─────────────────┴──────────┴──────────┴─────────────┘ │
│ Expenses Total: $650 │
│ │
│ ⚠️ Invoice is posted. To modify expenses, create a Credit Note. │
│ │
└───────────────────────────────────────────────────────────────────────────────────┘
3. Master Order - Expenses Section
┌───────────────────────────────────────────────────────────────────────────────────┐
│ 📦 MASTER ORDER MO/2026/00045 │
├───────────────────────────────────────────────────────────────────────────────────┤
│ │
│ [Order Info] [Lines] [Expenses] [Invoices] [Shipments] │
│ ════════════════════════════════════════════════════════════════════════════════ │
│ │
│ EXPENSES [+ Add Expense] │
│ ┌────────────┬─────────────────┬──────────┬──────────┬───────────┬─────────────┐ │
│ │ Type │ Description │ Amount │ Date │ Invoice │ Status │ │
│ ├────────────┼─────────────────┼──────────┼──────────┼───────────┼─────────────┤ │
│ │ Customs │ Import Duty │ $200 │ Jan 05 │ INV/00123 │ ✓ Invoiced │ │
│ │ Docs │ Certificate Fee │ $100 │ Jan 07 │ INV/00123 │ ✓ Invoiced │ │
│ │ Shipping │ Air Freight │ $350 │ Jan 08 │ INV/00123 │ ✓ Invoiced │ │
│ │ Handling │ Warehouse Fee │ $75 │ Jan 09 │ - │ ⏳ Pending │ │
│ │ Other │ Samples │ $50 │ Jan 10 │ - │ 🏢 Company │ │
│ └────────────┴─────────────────┴──────────┴──────────┴───────────┴─────────────┘ │
│ │
│ ════════════════════════════════════════════════════════════════════════════════ │
│ │
│ EXPENSE SUMMARY │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ Total Customer Expenses: $725 (charged to customer) │ │
│ │ - Invoiced: $650 ✓ │ │
│ │ - Pending: $75 ⏳ │ │
│ │ │ │
│ │ Total Company Expenses: $50 (company absorbed) │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────────────────┘
4. Create Expense Form (Popup/Wizard)
┌─────────────────────────────────────────────────────────────────┐
│ CREATE NEW EXPENSE [X] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Expense Type: [Customs ▼] │
│ │
│ Description: [Import duty for shipment ] │
│ │
│ Amount: [$200.00 ] │
│ │
│ Date: [2026-01-10 ] │
│ │
│ Expense Account: [1300 - Customer Exp. Receivable ▼] │
│ (pre-filled from settings) │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ ☑️ Invoice to Customer │
│ ├─ ✓ Checked: Customer will be charged (default) │
│ └─ ☐ Unchecked: Company absorbs cost │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ [Cancel] [Create Expense] │
│ │
└─────────────────────────────────────────────────────────────────┘
5. Select Existing Expenses Wizard
┌─────────────────────────────────────────────────────────────────┐
│ SELECT EXPENSES TO ADD [X] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Invoice: INV/2026/00123 │
│ Customer: ABC Trading Co. │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ AVAILABLE PENDING EXPENSES │
│ ┌────┬────────────┬─────────────────┬──────────┬────────────┐ │
│ │ ☐ │ Type │ Description │ Amount │ Date │ │
│ ├────┼────────────┼─────────────────┼──────────┼────────────┤ │
│ │ ☑️ │ Handling │ Warehouse Fee │ $75 │ Jan 09 │ │
│ │ ☑️ │ Other │ Inspection │ $50 │ Jan 10 │ │
│ │ ☐ │ Shipping │ Local Delivery │ $30 │ Jan 11 │ │
│ └────┴────────────┴─────────────────┴──────────┴────────────┘ │
│ │
│ Selected Total: $125 │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ [Cancel] [Add Selected to Invoice] │
│ │
└─────────────────────────────────────────────────────────────────┘
6. Company Absorbs Action (Reclassification)
┌─────────────────────────────────────────────────────────────────┐
│ COMPANY ABSORBS EXPENSE [X] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Expense: Samples for client │
│ Amount: $50 │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ ⚠️ This will: │
│ • Move expense from Customer to Company │
│ • Create reclassification journal entry │
│ • Expense will NOT be charged to customer │
│ │
│ Reclassification Entry: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Debit: Company Expense (P&L) $50 │ │
│ │ Credit: Customer Expenses Receivable $50 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ [Cancel] [Confirm - Company Pays] │
│ │
└─────────────────────────────────────────────────────────────────┘
Configuration
Default Customer Expense Account Setting
Use existing settings pattern in models/settings.py:
Parameter: at_master_order.customer_expense_account_id
┌─────────────────────────────────────────────────────────────────┐
│ MASTER ORDER SETTINGS → Account Configuration │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Commission Income Account: [4100 - Commission Income ▼] │
│ Shipping Revenue Account: [4200 - Shipping Revenue ▼] │
│ Shipping Expense Account: [5100 - Shipping Expense ▼] │
│ Other Expense Account: [5200 - Other Expenses ▼] │
│ │
│ ─── NEW ─── │
│ Customer Expense Account: [1300 - Cust. Exp. Receivable ▼]│
│ │
│ ℹ️ Used for expenses paid on behalf of customers. │
│ Debited when expense is paid, credited when added to │
│ customer invoice for settlement. │
│ │
│ Account Filter: Asset accounts only │
│ │
└─────────────────────────────────────────────────────────────────┘
Implementation (Existing Pattern)
File: models/settings.py
| Section | Add |
|---|---|
| Field definition (line ~35) | customer_expense_account_id = fields.Many2one('account.account', ...) |
get_values() (line ~145) |
Read from at_master_order.customer_expense_account_id |
set_values() (line ~190) |
Write to at_master_order.customer_expense_account_id |
File: models/expense_box.py
| Section | Add |
|---|---|
get_expense_account() |
Add fallback to at_master_order.customer_expense_account_id |
| Setting Behavior | Description |
|---|---|
| Pre-fills expense account | When creating expense, this account is selected by default |
| User can override | Default is convenience, not mandatory |
| Follows existing pattern | Same as other account configurations |
Recommended Account Setup
Chart of Accounts
| Account Code | Account Name | Type | Purpose |
|---|---|---|---|
| 1300 | Customer Expenses Receivable | Asset (Receivable) | Track expenses paid on behalf of customers |
Alternative names:
- Customer Advances
- Customer Expense Fund
- Prepaid Customer Expenses
Implementation Tasks
Phase 0: Configuration
| # | Task | File | Status |
|---|---|---|---|
| 0 | Add customer_expense_account_id field to settings |
models/settings.py |
✅ |
| 0b | Add to get_values() method |
models/settings.py |
✅ |
| 0c | Add to set_values() method |
models/settings.py |
✅ |
| 0d | Add field to settings view (if exists) | views/master_order_config_views.xml |
✅ |
Phase 1: Model Changes
| # | Task | File | Status |
|---|---|---|---|
| 1 | Add invoice_id field to expense model |
models/expense_box.py |
✅ |
| 2 | Add added_to_invoice, invoice_line_id fields |
models/expense_box.py |
✅ |
| 3 | Add expense_id field to invoice line (reverse link) |
models/account_move.py |
✅ |
| 4 | Add expense_ids One2many to account.move |
models/account_move.py |
✅ |
| 5 | Add computed expense totals | models/account_move.py |
✅ |
| 6 | Add action_add_to_invoice() method |
models/expense_box.py |
✅ |
| 7 | Add action_remove_from_invoice() method |
models/expense_box.py |
✅ |
| 8 | Override invoice cancel to reset expenses | models/account_move.py |
✅ |
| 9 | Add customer validation on expense add | models/expense_box.py |
✅ |
| 10 | Use default account in expense creation | models/expense_box.py |
✅ |
Phase 2: Wizard Development
| # | Task | File | Status |
|---|---|---|---|
| 10 | Create "Select Existing Expense" wizard | wizard/add_expense_to_invoice_wizard.py |
✅ |
| 11 | Create "Create New Expense" wizard | wizard/create_expense_wizard.py |
✅ |
| 12 | Wizard views | wizard/expense_wizard_views.xml |
✅ |
Phase 3: View Changes
| # | Task | File | Status |
|---|---|---|---|
| 13 | Add Expenses section to invoice form | views/invoice_expense_views.xml |
✅ |
| 14 | Add wizard buttons (draft state only) | views/invoice_expense_views.xml |
✅ |
| 15 | Add pending expenses quick list | views/invoice_expense_views.xml |
✅ |
| 16 | State-based visibility (draft vs posted) | views/invoice_expense_views.xml |
✅ |
Phase 4: Testing & Deployment
| # | Task | Status |
|---|---|---|
| 17 | Test Workflow A: Select existing expense | ⬜ |
| 18 | Test Workflow B: Create new expense on invoice | ⬜ |
| 19 | Test remove expense from draft invoice | ⬜ |
| 20 | Test invoice cancellation resets expenses | ⬜ |
| 21 | Test customer validation | ⬜ |
| 22 | Test accounting entries (settlement) | ⬜ |
| 23 | Deploy to aspir database | ⬜ |
Key Features
| Feature | Description |
|---|---|
| Expense Account Selection | Choose any account from COA |
| Track on Invoice | Link expenses to specific customer invoice |
| Add to Invoice Line | Convert expense to invoice line for billing |
| Auto Settlement | Expense account settles when customer pays |
| Aggregate to MO | Expenses also visible at Master Order level |
Notes
- No Vendor Bills - This is for expenses paid directly, not through vendor bills
- Simple Tracking - Just account + description + amount
- Flexible Accounts - Use any expense/asset account from COA
- Automatic Settlement - Adding to invoice creates the settlement entry
Approval
- Design approved by user
- Option A: Invoice line uses Asset account (settlement)
- No tax treatment
- Single currency only
- Workflow A + B confirmed
- Edge cases reviewed and approved
- Ready for implementation
- Implementation Complete (2026-01-10)