Skip to content

/admin/invoices

Path: /admin/invoices
Namespace: admin
Resource: invoices

Overview

The Invoice resource represents all business documents in ERPax using a unified model. The invoice_type field determines the document's role in the workflow.

Relationships

Model Associations

Invoice connects to the following resources:

Domain
  • Type: belongs_to via host_id
  • Field: host_id (tenant domain)
  • Description: Tenant domain for multi-tenant scoping. All invoices belong to a domain.
  • Reverse: Domain has many invoices (domain.invoices)
  • API Access:
    • Direct: Included in invoice response as host_id
    • Filter: GET /admin/invoices.json?q[host_id_eq]=1
  • Related Documentation: Domains
Address (Multiple Roles)
  • Type: belongs_to via multiple foreign keys
  • Description: Business partner relationships. Addresses can serve multiple roles in an invoice.
  • Roles:
    • seller_id - Seller address (defaults to domain.address if omitted in admin namespace)
    • buyer_id - Buyer/customer address
    • supplier_id - Supplier address (for purchase documents)
    • seller_agent_id - Seller's agent address
    • buyer_agent_id - Buyer's agent address
    • consignee_id - Delivery consignee address
  • Reverse: Address has many invoices in different roles (accessed via filtering):
    • Invoices where address is seller - Filter by seller_id
    • Invoices where address is buyer - Filter by buyer_id
    • Invoices where address is supplier - Filter by supplier_id
  • API Access:
    • Direct: invoice.seller_id, invoice.buyer_id, etc.
    • Filter:
      • GET /admin/invoices.json?q[seller_id_eq]=1 - Invoices where address is seller
      • GET /admin/invoices.json?q[buyer_id_eq]=1 - Invoices where address is buyer
      • GET /admin/invoices.json?q[supplier_id_eq]=1 - Invoices where address is supplier
  • Related Documentation: Addresses
Invoice (Self-Referential)
  • Type: belongs_to / has_many via parent_id
  • Field: parent_id
  • Description: Parent document for document hierarchies (quotation → invoice, purchase_order → protocol → bill)
  • Reverse: Invoice has many child invoices (invoice.children)
  • API Access:
    • Direct: invoice.parent_id (parent invoice ID)
    • Filter: GET /admin/invoices.json?q[parent_id_eq]=123 (child invoices for parent 123; there is no nested /admin/invoices/:id/children route)
  • Example: Create invoice from quotation:
    javascript
    const invoice = await fetch('/admin/invoices.json', {
      method: 'POST',
      body: JSON.stringify({
        invoice: {
          parent_id: 123, // quotation ID
          invoice_type: 'invoice'
        }
      })
    }).then(r => r.json());
InvoiceLine[]
  • Type: has_many via invoice_id
  • Description: Line items for this invoice. Contains products, quantities, prices, and totals.
  • Reverse: InvoiceLine belongs to Invoice (invoice_line.invoice)
  • API Access:
    • Direct: Included in invoice response as invoice_lines array
    • Nested: GET /admin/invoices/:id/invoice_lines.json
    • Filter: GET /admin/invoice_lines.json?q[invoice_id_eq]=123
  • Related Documentation: Invoice Lines
  • Example: Get invoice lines for an invoice:
    javascript
    const invoiceLines = await fetch('/admin/invoices/123/invoice_lines.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
AccountingAccount
  • Type: belongs_to via credit_account_id and debit_account_id
  • Fields: credit_account_id, debit_account_id
  • Description: Accounting accounts for credit and debit entries. Used when invoice is confirmed and accounted.
  • Reverse: AccountingAccount has many invoices (via credit/debit account assignments)
  • API Access:
    • Direct: invoice.credit_account_id, invoice.debit_account_id
    • Filter: GET /admin/invoices.json?q[credit_account_id_eq]=10
  • Related Documentation: Accounting
PackingLine[]
  • Type: has_many via invoice_id
  • Description: Shipping and packing information for delivery tracking
  • Reverse: PackingLine belongs to Invoice (packing_line.invoice)
  • API Access:
    • Direct: Included in invoice response as packing_lines array (if present)
    • Nested: GET /admin/invoices/:id/packing_lines.json
  • Related Documentation: Packing Lines

Reverse Associations

The following resources connect to Invoice:

Payment[]
  • Type: has_many on Invoice via invoice_id
  • Description: Payments recorded against this invoice. Track payment amounts, dates, and methods.
  • API Access:
    • Direct: Included in invoice response as payments array (if present)
    • Nested: GET /admin/invoices/:id/payments.json
    • Filter: GET /admin/payments.json?q[invoice_id_eq]=123
  • Related Documentation: Payments
  • Example: Get all payments for an invoice:
    javascript
    const payments = await fetch('/admin/invoices/123/payments.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
AccountingEquation[]
  • Type: has_many on Invoice via polymorphic accountable association
  • Description: Double-entry accounting transactions created automatically when invoice is confirmed and accounted. Ensures debits equal credits.
  • API Access:
    • Direct: Included in invoice response as accounting_equations array (if present)
    • Nested: GET /admin/invoices/:id/accounting_equations.json
    • Filter (top-level index): GET /admin/accounting_equations.json?q[accountable_id_eq]=123&q[accountable_type_eq]=Invoice (equations are linked via polymorphic accountable, not an invoice_id column on the equation)
  • Related Documentation: Accounting
  • Example: Get accounting equations for an invoice:
    javascript
    const equations = await fetch('/admin/invoices/123/accounting_equations.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());

Relationship Patterns

Creating an invoice and lines (two requests)
  • Use Case: Create the invoice, then add lines using the nested invoice-lines route
  • Example:
    javascript
    const { invoice } = await fetch('/admin/invoices.json', {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify({
        invoice: {
          invoice_type: 'invoice',
          seller_id: 1,
          buyer_id: 2,
          date: '2026-03-15',
          currency_code: 'USD'
        }
      })
    }).then(r => r.json());
    
    await fetch(`/admin/invoices/${invoice.id}/invoice_lines.json`, {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify({
        invoice_line: {
          seller_item_id: 1,
          quantity: 10,
          unit_price: '100.00',
          description: 'Product description'
        }
      })
    }).then(r => r.json());
Filtering Invoices by Address
  • Use Case: Get all invoices where a specific address is the seller, buyer, or supplier
  • Example: Get invoices where address is seller:
    javascript
    const sellerInvoices = await fetch('/admin/invoices.json?q[seller_id_eq]=123', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
  • Example: Get invoices where address is buyer:
    javascript
    const buyerInvoices = await fetch('/admin/invoices.json?q[buyer_id_eq]=123', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
  • Use Case: Get invoice lines for an invoice without loading the full invoice
  • Example:
    javascript
    const invoiceLines = await fetch('/admin/invoices/123/invoice_lines.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Document Hierarchy Navigation
  • Use Case: Create a child invoice from a parent (e.g., invoice from quotation)
  • Example:
    javascript
    const invoice = await fetch('/admin/invoices.json', {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify({
        invoice: {
          parent_id: 123, // quotation ID
          invoice_type: 'invoice',
          // Other fields inherited from parent
        }
      })
    }).then(r => r.json());

Key Features

  • Unified Document Model - One model handles all document types (invoices, purchase orders, quotations, etc.)
  • Automatic Lifecycle Transitions - Documents automatically transition through workflow stages
  • Automatic Accounting - Accounting entries created automatically when invoice is confirmed
  • Multi-Currency Support - Full currency conversion and exchange rate management
  • Namespace-Specific Behavior - Different default behaviors in admin, sales, and client namespaces
  • Document Hierarchies - Support for parent-child relationships (quotation → invoice, purchase_order → protocol → bill)

Document Types

ERPax supports multiple invoice types:

Sales Documents:

  • cart - Shopping cart for online purchases (draft state, no number)
  • request - Customer purchase request
  • quotation - Price quote for potential sales
  • proforma_invoice - Preliminary invoice before final invoice
  • invoice - Final sales invoice (must have number and date)
  • credit_note - Document for refunds or adjustments (reduces amount owed)
  • debit_note - Document for additional charges (increases amount owed)

Purchase Documents:

  • purchase_order - Order to suppliers
  • protocol - Goods receipt confirmation (has protocol_number and protocol_date)
  • bill - Supplier invoice

Recurring Documents:

  • subscription - Recurring service agreement
  • lease - Equipment or property lease

Document Lifecycle

Documents automatically transition through lifecycle stages:

Sales Process:

cart → request → quotation → proforma_invoice → invoice

                            credit_note / debit_note

Purchase Process:

purchase_order → protocol → bill

Documents inherit context from parent documents and automatically handle field normalization, account assignment, exchange rate updates, and number generation.

Namespace-Specific Behavior

Invoice creation behaves differently across namespaces, particularly regarding automatic seller/buyer assignment:

Admin Namespace:

  • Default Seller: Domain address is automatically used as seller if seller_id is omitted.

Sales Namespace:

  • Fixed Seller: Host address is automatically set as seller. Domain address is used as supplier.

Client Namespace:

  • Default Buyer: User address is automatically used as buyer. Seller must be from host addresses.

Available Operations

List Invoices (GET)

Endpoint: GET /admin/invoices.json

Query Parameters:

  • q[field_predicate]=value - Ransack query filters for advanced filtering
  • scope=name - Apply named scope (e.g., unpaid, due, confirmed)
  • page=N - Page number for pagination
  • per_page=N - Items per page (default: 25)

Request Examples:

bash
curl -X GET "https://your-company.erpax.com/admin/invoices.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"
bash
curl -X GET "https://your-company.erpax.com/admin/invoices.json?q[invoice_type_eq]=invoice" \
  -H "Accept: application/json"
bash
curl -X GET "https://your-company.erpax.com/admin/invoices.json?q[date_gteq]=2024-01-01&q[date_lteq]=2024-12-31" \
  -H "Accept: application/json"
bash
curl -X GET "https://your-company.erpax.com/admin/invoices.json?q[seller_id_eq]=1&q[buyer_id_eq]=2" \
  -H "Accept: application/json"
bash
curl -X GET "https://your-company.erpax.com/admin/invoices.json?scope=unpaid&page=1&per_page=25" \
  -H "Accept: application/json"

JavaScript Example:

javascript
const response = await fetch('/admin/invoices.json', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});
const data = await response.json();

Response (200 OK):

json
{
  "invoices": [
    {
      "id": 1,
      "invoice_type": "invoice",
      "number": "INV-2024-001",
      "date": "2024-01-15",
      "seller_id": 1,
      "buyer_id": 2,
      "currency_code": "USD",
      "total_amount_cents": 100000,
      "total_amount": "1000.00",
      "confirmed": true,
      "created_at": "2024-01-15T10:00:00Z",
      "updated_at": "2024-01-15T10:30:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total_pages": 5,
    "total_count": 123
  }
}

Show Invoice (GET /:id)

Endpoint: GET /admin/invoices/:id.json

Request Example:

bash
curl -X GET "https://your-company.erpax.com/admin/invoices/123.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

JavaScript Example:

javascript
const response = await fetch('/admin/invoices/123.json', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});
const invoice = await response.json();

Response (200 OK):

json
{
  "invoice": {
    "id": 123,
    "invoice_type": "invoice",
    "number": "INV-2024-001",
    "date": "2024-01-15",
    "seller_id": 1,
    "buyer_id": 2,
    "currency_code": "USD",
    "total_amount_cents": 100000,
    "confirmed": true,
    "invoice_lines": [
      {
        "id": 1,
        "seller_item_id": 1,
        "quantity": 10,
        "unit_price": "100.00",
        "total_amount_cents": 100000
      }
    ],
    "payments": [],
    "accounting_equations": []
  }
}

Response (404 Not Found):

json
{
  "error": "Invoice not found"
}

Create Invoice (POST)

Endpoint: POST /admin/invoices.json

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/invoices.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "invoice": {
      "invoice_type": "invoice",
      "seller_id": 1,
      "buyer_id": 2,
      "date": "2026-03-15",
      "currency_code": "USD",
      "invoice_lines_attributes": [
        {
          "seller_item_id": 1,
          "quantity": 10,
          "unit_price": "100.00",
          "description": "Product description"
        }
      ]
    }
  }'

Line items: You can send invoice_lines_attributes on create as above (correct keys: seller_item_id, quantity, unit_price, description). If the server ignores nested lines, create the invoice first, then POST /admin/invoices/:id/invoice_lines.json with an invoice_line object using the same fields (see Invoice lines).

JavaScript Example:

javascript
const response = await fetch('/admin/invoices.json', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    invoice: {
      invoice_type: 'invoice',
      seller_id: 1,
      buyer_id: 2,
      date: '2026-03-15',
      currency_code: 'USD',
      invoice_lines_attributes: [
        {
          seller_item_id: 1,
          quantity: 10,
          unit_price: '100.00',
          description: 'Product description'
        }
      ]
    }
  })
});
const invoice = await response.json();

Response (201 Created):

json
{
  "invoice": {
    "id": 123,
    "invoice_type": "invoice",
    "number": null,
    "date": "2026-03-15",
    "seller_id": 1,
    "buyer_id": 2,
    "currency_code": "USD",
    "total_amount_cents": 100000,
    "confirmed": false,
    "created_at": "2026-03-15T14:30:00Z"
  }
}

Response (422 Unprocessable Entity):

json
{
  "errors": {
    "seller_id": ["can't be blank"],
    "buyer_id": ["can't be blank"],
    "date": ["can't be blank"]
  }
}

Update Invoice (PATCH /:id)

Endpoint: PATCH /admin/invoices/:id.json

Request Example:

bash
curl -X PATCH "https://your-company.erpax.com/admin/invoices/123.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "invoice": {
      "confirmed": true
    }
  }'

JavaScript Example:

javascript
const response = await fetch('/admin/invoices/123.json', {
  method: 'PATCH',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    invoice: {
      confirmed: true
    }
  })
});
const invoice = await response.json();

Response (200 OK):

json
{
  "invoice": {
    "id": 123,
    "number": "INV-2024-001",
    "confirmed": true,
    "updated_at": "2024-01-15T15:00:00Z"
  }
}

Note: Once an invoice is confirmed, most fields become read-only. Only users with specific permissions can modify confirmed invoices.

Delete Invoice (DELETE /:id)

Endpoint: DELETE /admin/invoices/:id.json

Request Example:

bash
curl -X DELETE "https://your-company.erpax.com/admin/invoices/123.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

JavaScript Example:

javascript
const response = await fetch('/admin/invoices/123.json', {
  method: 'DELETE',
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});

Response (204 No Content):

(empty response)

Response (422 Unprocessable Entity):

json
{
  "error": "Cannot delete confirmed invoice"
}

Batch Actions

Endpoint: POST /admin/invoices/batch_action.json

Available batch actions:

  • filter - Filter collection to show only selected records
  • update - Update selected records with form fields (domain, debit_code, credit_code, next_billing_date, delivered_at, confirmed)
  • renew - Renew selected renewable invoices (available when scope is 'renewable')
  • cancel - Cancel selected invoices (sets cancelled_at to current time)
  • confirm - Confirm selected invoices (sets confirmed to true)
  • account - Create accounting entries for selected unaccounted invoices (available when scope is 'unaccounted')

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/invoices/batch_action.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "batch_action": "confirm",
    "collection_selection": [1, 2, 3]
  }'

Member Actions

Custom actions available on individual invoices via API:

Endpoint: GET /admin/invoices/:id/print

Description: Generate and return a printable version of the invoice.

Request Example:

bash
curl -X GET "https://your-company.erpax.com/admin/invoices/123/print" \
  -H "Accept: application/pdf" \
  -H "Cookie: session_cookie"

Response: Returns PDF or HTML printable version of the invoice.

Email Invoice

Endpoint: GET /admin/invoices/:id/email

Description: Send the invoice via email to the buyer.

Request Example:

bash
curl -X GET "https://your-company.erpax.com/admin/invoices/123/email" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (200 OK):

json
{
  "message": "Email sent successfully"
}

Duplicate Invoice

Endpoint: POST /admin/invoices/:id/duplicate

Description: Create a duplicate copy of the invoice.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/invoices/123/duplicate" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (201 Created):

json
{
  "invoice": {
    "id": 124,
    "invoice_type": "invoice",
    "number": null,
    "date": "2024-01-15",
    ...
  }
}

Renew Invoice

Endpoint: POST /admin/invoices/:id/renew

Description: Renew a recurring invoice (subscription or lease).

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/invoices/123/renew" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (200 OK):

json
{
  "invoice": {
    "id": 123,
    "next_billing_date": "2024-02-15",
    ...
  }
}

Create Backorder

Endpoint: POST /admin/invoices/:id/backorder

Description: Create a backorder for items that are out of stock.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/invoices/123/backorder" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (201 Created):

json
{
  "invoice": {
    "id": 125,
    "invoice_type": "backorder",
    ...
  }
}

Create Payment

Endpoint: POST /admin/invoices/:id/create_payment

Description: Create a payment record for the invoice.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/invoices/123/create_payment" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "payment": {
      "amount_cents": 100000,
      "payment_method_id": 1,
      "date": "2024-01-15"
    }
  }'

Response (201 Created):

json
{
  "payment": {
    "id": 1,
    "invoice_id": 123,
    "amount_cents": 100000,
    ...
  }
}

Create Credit Note

Endpoint: POST /admin/invoices/:id/create_credit_note

Description: Create a credit note (refund or adjustment) for the invoice.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/invoices/123/create_credit_note" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "credit_note": {
      "reason": "Returned items",
      "amount_cents": 50000
    }
  }'

Response (201 Created):

json
{
  "invoice": {
    "id": 126,
    "invoice_type": "credit_note",
    "parent_id": 123,
    ...
  }
}

Create Debit Note

Endpoint: POST /admin/invoices/:id/create_debit_note

Description: Create a debit note (additional charge) for the invoice.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/invoices/123/create_debit_note" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "debit_note": {
      "reason": "Additional charges",
      "amount_cents": 25000
    }
  }'

Response (201 Created):

json
{
  "invoice": {
    "id": 127,
    "invoice_type": "debit_note",
    "parent_id": 123,
    ...
  }
}

Create Protocol

Endpoint: POST /admin/invoices/:id/create_protocol

Description: Create a protocol (goods receipt) for a purchase order.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/invoices/123/create_protocol" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "protocol": {
      "protocol_number": "PROT-2024-001",
      "protocol_date": "2024-01-15"
    }
  }'

Response (201 Created):

json
{
  "invoice": {
    "id": 128,
    "invoice_type": "protocol",
    "parent_id": 123,
    "protocol_number": "PROT-2024-001",
    ...
  }
}

Scopes

Scopes are organized into groups for better navigation:

  • active (default, group: status) - Active invoices only
  • pending (group: shipping) - Active undelivered invoices
  • renewable (group: recurring) - Active renewable invoices
  • leads (group: document) - Active lead documents
  • orders (group: document) - Active order documents
  • accountable (group: accounting) - Active invoices that can be accounted
  • accounted (group: accounting) - Active invoices that have been accounted
  • unaccounted (group: accounting) - Active invoices that have not been accounted
  • paid (group: billing) - Active paid invoices
  • unpaid (group: billing) - Active unpaid invoices
  • due (group: billing) - Active invoices that are due
  • cancelled (group: status) - Cancelled invoices

Usage Example:

bash
GET /admin/invoices.json?scope=unpaid
GET /admin/invoices.json?scope=due
GET /admin/invoices.json?scope=renewable

Filters

Available filters for searching and filtering invoices:

Address Filters

  • domain - Select filter (multiple) - Filter by domain
  • seller - Select filter (multiple) - Filter by seller address
  • seller_agent - Select filter (multiple) - Filter by seller agent
  • buyer - Select filter (multiple) - Filter by buyer address
  • buyer_agent - Select filter (multiple) - Filter by buyer agent
  • supplier - Select filter (multiple) - Filter by supplier address
  • consignee - Select filter (multiple) - Filter by consignee address

Document Filters

  • document_number (label) - Text filter - Search by number, parent_number, protocol_number, purchase_order, or sales_order
  • line_search (label) - Text filter - Search by invoice_lines code, name, or description
  • invoice_type - Select filter (multiple) - Filter by invoice type
  • number - Text filter - Filter by invoice number
  • period - Date filter - Filter by period

Date Filters

  • date - Date filter
  • order_date - Date filter
  • proforma_date - Date filter
  • payment_date - Date filter
  • delivery_date - Date filter
  • delivered_at - Date filter
  • cancelled_at - Date filter
  • created_at - Date filter
  • updated_at - Date filter
  • next_billing_date - Date filter (shown when scope is 'renewable')

Currency and Financial Filters

  • currency_code - Select filter (multiple) - Filter by currency code
  • item_total_cents - Numeric range filter
  • discount_total_cents - Numeric range filter
  • net_total_cents - Numeric range filter
  • tax_total_cents - Numeric range filter
  • total_amount_cents - Numeric range filter
  • total_paid_cents - Numeric range filter
  • total_due_cents - Numeric range filter

Accounting Filters

  • debit_account - Filter by debit account
  • credit_account - Filter by credit account

Status Filters

  • confirmed - Boolean filter - Filter by confirmation status

Filtering Examples:

bash
# Text search
GET /admin/invoices.json?q[number_cont]=INV-2024

# Date range
GET /admin/invoices.json?q[date_gteq]=2024-01-01&q[date_lteq]=2024-12-31

# Multiple conditions
GET /admin/invoices.json?q[invoice_type_eq]=invoice&q[confirmed_eq]=true&q[total_amount_cents_gteq]=100000

# Association filters
GET /admin/invoices.json?q[seller_code_cont]=CUST&q[buyer_name_cont]=Supplier

See API Reference for complete Ransack query syntax.

Business Rules

Automatic Behaviors

  • Number Generation: Invoice numbers are automatically generated when invoice is confirmed
  • Accounting Integration: Accounting entries are automatically created when invoice is confirmed
  • Field Normalization: Fields are automatically normalized based on invoice type
  • Account Assignment: Accounting accounts are automatically assigned based on invoice type and configuration
  • Exchange Rate Updates: Exchange rates are automatically updated based on currency and date

Document Lifecycle Rules

  • Confirmation: Once confirmed, most fields become read-only
  • Parent-Child Relationships: Child documents inherit context from parent documents
  • Automatic Transitions: Documents automatically transition through workflow stages

EU VAT Compliance

For EU VAT invoices, ensure:

  • Seller and buyer addresses have tax_code (VAT ID) populated
  • tax_type is set to 'vat'
  • Tax rates are correctly configured
  • Invoice has all mandatory fields (number, date, seller, buyer, line items with tax)

Workflow Examples

Creating a Sales Invoice:

  1. Create quotation with invoice_type: 'quotation'
  2. Add invoice lines with products, quantities, and prices
  3. Confirm quotation (triggers automatic transitions)
  4. Convert to proforma_invoice or invoice as needed
  5. Confirm invoice to generate invoice number
  6. Invoice becomes read-only after confirmation

Creating a Purchase Order:

  1. Create purchase_order
  2. Set buyer to your company, seller to supplier
  3. Add purchase order lines
  4. Confirm purchase order
  5. Create protocol when goods are received
  6. Create bill when supplier invoice is received

Nested Resources

The Invoice resource has the following nested resources:

  • Addresses - Manage seller/buyer addresses
  • Items - Manage products for invoice lines
  • Payments - Manage payments
  • Accounting - Chart of accounts and accounting resources

Released under an open source license.