m-invoice: Core Invoice Module
Reusable invoice DocTypes for any Framework M application.
Depends on: m-core
Overview
Section titled “Overview”This module provides:
- Purchase Invoice (uses
Supplierfrom m-core) - Sales Invoice (uses
Customerfrom m-core) - Invoice Item (uses
Itemfrom m-core) - Tax handling (generic, not country-specific)
- Payment linkage
DocTypes
Section titled “DocTypes”1. Purchase Invoice
Section titled “1. Purchase Invoice”class PurchaseInvoice(BaseDocType): """Invoice from Supplier for goods/services received."""
invoice_number: str = Field(max_length=50) supplier: str # FK to Supplier
posting_date: date due_date: date | None = None
# Items items: list["InvoiceItem"] = Field(default_factory=list)
# Totals total_qty: Decimal = Decimal("0") total_amount: Decimal = Decimal("0") tax_amount: Decimal = Decimal("0") grand_total: Decimal = Decimal("0")
# Payment paid_amount: Decimal = Decimal("0") outstanding_amount: Decimal = Decimal("0")
# Status status: str = "Draft" # Draft, Submitted, Paid, Cancelled
class Meta: table_name = "purchase_invoice"2. Sales Invoice
Section titled “2. Sales Invoice”class SalesInvoice(BaseDocType): """Invoice to Customer for goods/services sold."""
invoice_number: str = Field(max_length=50) customer: str # FK to Customer (generic)
posting_date: date due_date: date | None = None
# Items items: list["InvoiceItem"] = Field(default_factory=list)
# Totals total_qty: Decimal = Decimal("0") total_amount: Decimal = Decimal("0") tax_amount: Decimal = Decimal("0") grand_total: Decimal = Decimal("0")
# Payment paid_amount: Decimal = Decimal("0") outstanding_amount: Decimal = Decimal("0")
# Status status: str = "Draft"
class Meta: table_name = "sales_invoice"3. Invoice Item
Section titled “3. Invoice Item”class InvoiceItem(BaseDocType): """Line item in an invoice."""
parent: str # FK to PurchaseInvoice or SalesInvoice parent_type: str # "PurchaseInvoice" or "SalesInvoice"
item: str # FK to Item item_name: str
qty: Decimal rate: Decimal amount: Decimal # qty * rate
# Tax (generic) tax_rate: Decimal = Decimal("0") tax_amount: Decimal = Decimal("0")
# Warehouse/Location warehouse: str | None = None
class Meta: table_name = "invoice_item" child_of = ["PurchaseInvoice", "SalesInvoice"]Tax Handling
Section titled “Tax Handling”m-invoice provides generic tax fields. Country-specific tax logic is in separate modules:
| Region | Module | What It Adds |
|---|---|---|
| India | m-india | CGST, SGST, IGST, HSN, E-Invoice |
| UAE | m-uae (future) | VAT |
| EU | m-eu (future) | VAT |
Book Keeper Integration
Section titled “Book Keeper Integration”Invoices post to Book Keeper ledger on submit:
async def on_submit(invoice: PurchaseInvoice): # Debit: Stock/Expense account # Credit: Supplier payable account await book_keeper.transfer( debit_account=invoice.expense_account, credit_account=invoice.supplier_account, amount=invoice.grand_total, ledger="gl", reference_type="PurchaseInvoice", reference_id=invoice.id, )Events Published
Section titled “Events Published”| Event | When |
|---|---|
invoice.created |
Invoice saved as draft |
invoice.submitted |
Invoice submitted (GL posted) |
invoice.paid |
Full payment received |
invoice.cancelled |
Invoice cancelled |
- Create
PurchaseInvoiceDocType - Create
SalesInvoiceDocType - Create
InvoiceItemchild DocType - Book Keeper GL posting on submit
- Payment linkage
- Event publishing
Time Estimate
Section titled “Time Estimate”| Task | Duration |
|---|---|
| DocTypes | 0.5 day |
| Book Keeper integration | 0.5 day |
| Tests | 0.5 day |
| Total | 1.5 days |