Skip to content

/admin/addresses

Path: /admin/addresses
Namespace: admin
Resource: addresses

Overview

The Address resource represents all business parties in ERPax - customers, suppliers, sellers, buyers, agents, consignees, and other business entities. Addresses store contact information, tax settings, currency preferences, and business relationships.

Relationships

Model Associations

Address connects to the following resources:

Domain
  • Type: belongs_to via host_id
  • Field: host_id
  • Description: Tenant domain for multi-tenant scoping. All addresses belong to a domain.
  • Reverse: Domain has many addresses (domain.addresses), and Domain has one address (domain.address - business address)
  • API Access:
    • Direct: Included in address response as host_id
    • Filter: GET /admin/addresses.json?q[host_id_eq]=1 (addresses for a specific domain)
  • Special Case: domain.address - Domain can have a default business address used as seller
  • Related Documentation: Domains
User
  • Type: belongs_to via user_id (optional)
  • Field: user_id
  • Description: Associated user account. Links an address to a user for customer self-service.
  • Reverse: User has one address (user.address)
  • API Access:
    • Direct: address.user_id (may be null)
    • Filter: GET /admin/addresses.json?q[user_id_eq]=1
    • Nested: GET /admin/users/:id/address.json (user's address)
  • Related Documentation: Users
Address (Self-Referential - Hierarchical)
  • Type: belongs_to / has_many via parent_id (using ancestry gem)
  • Field: parent_id, ancestry
  • Description: Hierarchical relationships for parent companies, branches, departments. Addresses can have parent-child relationships.
  • Reverse: Address has many child addresses (address.children)
  • API Access:
    • Direct: address.parent_id (parent address ID)
    • Filter: GET /admin/addresses.json?q[parent_id_eq]=123
    • Nested: GET /admin/addresses/:id/children.json (child addresses)
  • Example: Get all child addresses:
    javascript
    const children = await fetch('/admin/addresses/123/children.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 for customer/vendor-specific accounting treatment.
  • Reverse: AccountingAccount has many addresses (via credit/debit account assignments)
  • API Access:
    • Direct: address.credit_account_id, address.debit_account_id
    • Filter: GET /admin/addresses.json?q[credit_account_id_eq]=10
  • Related Documentation: Accounting
Item[]
  • Type: has_many via seller_id (or address_id)
  • Description: Items owned by this address. Products associated with the address.
  • Reverse: Item belongs to Address (item.address)
  • API Access:
    • Direct: Included in address response as items array (if present)
    • Nested: GET /admin/addresses/:id/items.json
    • Filter: GET /admin/items.json?q[address_id_eq]=123
  • Related Documentation: Items
  • Example: Get all items owned by an address:
    javascript
    const items = await fetch('/admin/addresses/123/items.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
PaymentMethod[]
  • Type: has_many via address_id
  • Description: Payment methods configured for this address. Defines how the address prefers to make/receive payments.
  • Reverse: PaymentMethod belongs to Address (payment_method.address)
  • API Access:
    • Nested: GET /admin/addresses/:id/payment_methods.json
  • Example: Get payment methods for an address:
    javascript
    const paymentMethods = await fetch('/admin/addresses/123/payment_methods.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());

Reverse Associations

The following resources connect to Address:

Invoice (Multiple Roles)
  • Type: has_many on Invoice via multiple foreign keys (seller_id, buyer_id, supplier_id, etc.)
  • Description: Invoices where this address plays different roles (seller, buyer, supplier, agent, consignee).
  • API Access:
    • Filter:
      • GET /admin/invoices.json?q[seller_id_eq]=123 - Invoices where address is seller
      • GET /admin/invoices.json?q[buyer_id_eq]=123 - Invoices where address is buyer
      • GET /admin/invoices.json?q[supplier_id_eq]=123 - Invoices where address is supplier
  • Related Documentation: Invoices
  • Example: Get all 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());
Payment (Multiple Roles)
  • Type: has_many on Payment via sender_id and receiver_id
  • Description: Payments where this address is sender or receiver.
  • API Access:
    • Nested:
      • GET /admin/addresses/:id/payments_sent.json - Payments sent by this address
      • GET /admin/addresses/:id/payments_received.json - Payments received by this address
    • Filter:
      • GET /admin/payments.json?q[sender_id_eq]=123
      • GET /admin/payments.json?q[receiver_id_eq]=123
  • Related Documentation: Payments
  • Example: Get all payments sent by an address:
    javascript
    const paymentsSent = await fetch('/admin/addresses/123/payments_sent.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
AccountingTransaction[]
  • Type: has_many on AccountingTransaction via address_id or partner_id
  • Description: Accounting transactions associated with this address for customer/vendor accounting.
  • API Access:
    • Nested: GET /admin/addresses/:id/accounting_transactions.json
    • Filter: GET /admin/accounting_transactions.json?q[address_id_eq]=123
  • Related Documentation: Accounting
DailySales[]
  • Type: has_many on DailySales via address_id
  • Description: Daily sales reports for this address. Track sales performance by day.
  • API Access:
    • Nested: GET /admin/addresses/:id/daily_sales.json
    • Filter: GET /admin/daily_sales.json?q[address_id_eq]=123
  • Related Documentation: Reports
  • Example: Get daily sales for an address:
    javascript
    const dailySales = await fetch('/admin/addresses/123/daily_sales.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Contact[]
  • Type: has_many on Contact via address_id
  • Description: Contacts associated with this address. Multiple contacts per address for larger organizations.
  • API Access:
    • Nested: GET /admin/addresses/:id/contacts.json
  • Example: Get all contacts for an address:
    javascript
    const contacts = await fetch('/admin/addresses/123/contacts.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());

Relationship Patterns

Address Role in Invoices
  • Use Case: Determine which invoices an address is involved in and in what role
  • Example: Get all 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 all 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());
Domain Address as Default Seller
  • Use Case: Use domain's business address as default seller when creating invoices
  • Example: When seller_id is omitted, domain.address is automatically used:
    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',
          buyer_id: 2,
          // seller_id omitted - domain.address used automatically
          date: '2024-01-15'
        }
      })
    }).then(r => r.json());
Hierarchical Address Relationships
  • Use Case: Navigate parent-child relationships for corporate structures
  • Example: Get all child addresses (branches, departments):
    javascript
    const children = await fetch('/admin/addresses/123/children.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());
Address Payment Methods
  • Use Case: Configure and retrieve payment methods for an address
  • Example: Get payment methods for an address:
    javascript
    const paymentMethods = await fetch('/admin/addresses/123/payment_methods.json', {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    }).then(r => r.json());

Key Features

  • Hierarchical Relationships: Addresses can have parent/child relationships via ancestry
  • Multi-currency Support: Each address can have a preferred currency_code
  • Tax Configuration: tax_code (VAT ID), tax_rate, tax_type (vat/gst)
  • Contact Information: Email, phone, physical address fields
  • Integration Settings: Support for external system integration (e.g., Shopify)
  • User Association: Addresses can be associated with User accounts
  • Domain Scoping: Addresses are scoped to domains in multi-tenant setup

Address Roles

Addresses can serve different roles in transactions:

  • Seller - Party selling goods/services (appears in seller_id field)
  • Buyer - Party purchasing goods/services (appears in buyer_id field)
  • Supplier - Source of purchased goods (appears in supplier_id field)
  • Consignee - Final recipient of goods (appears in consignee_id field)
  • Agent - Intermediary in transactions (seller_agent_id or buyer_agent_id)

EU VAT Compliance

For EU VAT compliance, ensure addresses have:

  • tax_code: VAT identification number in format [Country Code][Number] (e.g., "BG123456789", "DE123456789")
  • tax_type: Set to 'vat' for EU VAT
  • tax_rate: Default VAT rate for this address
  • country_code: ISO country code (required for EU compliance)

Available Operations

List Addresses (GET)

Endpoint: GET /admin/addresses.json

Query Parameters:

  • q[field_predicate]=value - Ransack query filters for advanced filtering
  • scope=name - Apply named scope (e.g., sellers, buyers, suppliers)
  • 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/addresses.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"
bash
curl -X GET "https://your-company.erpax.com/admin/addresses.json?q[name_cont]=Customer" \
  -H "Accept: application/json"
bash
curl -X GET "https://your-company.erpax.com/admin/addresses.json?q[country_code_eq]=US&q[tax_type_eq]=vat" \
  -H "Accept: application/json"
bash
curl -X GET "https://your-company.erpax.com/admin/addresses.json?scope=sellers&page=1&per_page=25" \
  -H "Accept: application/json"

JavaScript Example:

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

Response (200 OK):

json
{
  "addresses": [
    {
      "id": 1,
      "code": "CUST-001",
      "name": "John Doe",
      "company": "Acme Corp",
      "email": "[email protected]",
      "phone": "+1-555-0123",
      "address1": "123 Main St",
      "city": "New York",
      "postal_code": "10001",
      "country_code": "US",
      "currency_code": "USD",
      "tax_code": "US123456789",
      "tax_type": "vat",
      "created_at": "2024-01-10T10:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total_pages": 3,
    "total_count": 67
  }
}

Show Address (GET /:id)

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

Request Example:

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

JavaScript Example:

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

Response (200 OK):

json
{
  "address": {
    "id": 1,
    "code": "CUST-001",
    "name": "John Doe",
    "company": "Acme Corp",
    "email": "[email protected]",
    "phone": "+1-555-0123",
    "address1": "123 Main St",
    "address2": "Suite 100",
    "city": "New York",
    "postal_code": "10001",
    "province_code": "NY",
    "country_code": "US",
    "currency_code": "USD",
    "tax_code": "US123456789",
    "tax_type": "vat",
    "tax_rate": 0.1,
    "debit_account_id": 10,
    "credit_account_id": 20,
    "parent_id": null,
    "created_at": "2024-01-10T10:00:00Z",
    "updated_at": "2024-01-15T12:00:00Z"
  }
}

Response (404 Not Found):

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

Create Address (POST)

Endpoint: POST /admin/addresses.json

Request Example:

bash
curl -X POST "https://your-company.erpax.com/admin/addresses.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "address": {
      "code": "CUST-002",
      "name": "Jane Smith",
      "company": "Tech Solutions Inc",
      "email": "[email protected]",
      "phone": "+1-555-0456",
      "address1": "456 Oak Ave",
      "city": "San Francisco",
      "postal_code": "94102",
      "country_code": "US",
      "currency_code": "USD",
      "tax_code": "US987654321",
      "tax_type": "vat"
    }
  }'

JavaScript Example:

javascript
const response = await fetch('/admin/addresses.json', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    address: {
      code: 'CUST-002',
      name: 'Jane Smith',
      company: 'Tech Solutions Inc',
      email: '[email protected]',
      phone: '+1-555-0456',
      address1: '456 Oak Ave',
      city: 'San Francisco',
      postal_code: '94102',
      country_code: 'US',
      currency_code: 'USD',
      tax_code: 'US987654321',
      tax_type: 'vat'
    }
  })
});
const address = await response.json();

Response (201 Created):

json
{
  "address": {
    "id": 2,
    "code": "CUST-002",
    "name": "Jane Smith",
    "company": "Tech Solutions Inc",
    "email": "[email protected]",
    "created_at": "2024-01-15T14:30:00Z"
  }
}

Response (422 Unprocessable Entity):

json
{
  "errors": {
    "code": ["has already been taken"],
    "email": ["is invalid"]
  }
}

Update Address (PATCH /:id)

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

Request Example:

bash
curl -X PATCH "https://your-company.erpax.com/admin/addresses/1.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "address": {
      "email": "[email protected]",
      "phone": "+1-555-9999"
    }
  }'

JavaScript Example:

javascript
const response = await fetch('/admin/addresses/1.json', {
  method: 'PATCH',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    address: {
      email: '[email protected]',
      phone: '+1-555-9999'
    }
  })
});
const address = await response.json();

Response (200 OK):

json
{
  "address": {
    "id": 1,
    "email": "[email protected]",
    "phone": "+1-555-9999",
    "updated_at": "2024-01-15T15:00:00Z"
  }
}

Delete Address (DELETE /:id)

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

Request Example:

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

JavaScript Example:

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

Response (204 No Content):

(empty response)

Response (422 Unprocessable Entity):

json
{
  "error": "Cannot delete address with associated invoices"
}

Scopes

  • all (default) - All addresses
  • roots - Root addresses (no parent)
  • subtree - Addresses with children (subtree)
  • agents - Addresses that are agents
  • sellers - Addresses that are sellers
  • buyers - Addresses that are buyers
  • suppliers - Addresses that are suppliers
  • consignees - Addresses that are consignees

Usage Example:

bash
GET /admin/addresses.json?scope=sellers
GET /admin/addresses.json?scope=buyers
GET /admin/addresses.json?scope=suppliers

Filters

Available filters for searching and filtering addresses:

  • Quick search (label) - Text filter (autofocus) - Search across code, name, company, phone, nin_code, tax_code, address1, address2, email, or user_email (contains)
  • city - Select filter (multiple) - Filter by city
  • postal_code - Text filter - Filter by postal code
  • province_code - Select filter (multiple) - Filter by province code
  • country - Select filter (multiple) - Filter by country
  • currency_code - Select filter (multiple) - Filter by currency code
  • tax_type - Select filter (multiple) - Filter by tax type
  • created_at - Date filter - Filter by creation date
  • updated_at - Date filter - Filter by update date

Filtering Examples:

bash
# Search by name or company
GET /admin/addresses.json?q[name_or_company_cont]=Acme

# Filter by country and tax type
GET /admin/addresses.json?q[country_code_eq]=US&q[tax_type_eq]=vat

# Filter by currency
GET /admin/addresses.json?q[currency_code_eq]=USD

Business Rules

  • Code Uniqueness: Address codes must be unique within a domain
  • Hierarchical Relationships: Addresses can have parent/child relationships via ancestry gem
  • Domain Scoping: Addresses are automatically scoped to the current domain
  • User Association: Addresses can be associated with User accounts for authentication
  • Tax Configuration: Tax settings are required for EU VAT compliance

Nested Resources

The Address resource has the following nested resources:

Released under an open source license.