> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laportenard.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Customers

> Customer lookup, RNC/Cédula validation via DGII, and assigning customers to orders.

The customer feature integrates with Odoo's `res.partner` model and supports RNC/Cédula validation via DGII (Dominican tax authority).

## Modes

| Mode   | Route                        | Purpose                                           |
| ------ | ---------------------------- | ------------------------------------------------- |
| Browse | `/pos-react/customers/`      | View, search, create, and edit customers          |
| Assign | `/pos-react/order/customer/` | Select and assign a customer to the current order |

## API endpoints

All endpoints under `/pos-react/api/customers/` require authentication and `point_of_sale.group_pos_user` membership:

| Endpoint             | Purpose                                                    |
| -------------------- | ---------------------------------------------------------- |
| `POST /search`       | Search by name, phone, email, or RNC                       |
| `POST /get`          | Get a single customer by ID                                |
| `POST /create`       | Create new customer (automatic DGII validation on save)    |
| `POST /update`       | Update existing customer                                   |
| `POST /validate-rnc` | Validate RNC/Cédula against DGII and retrieve company name |

## RNC/Cédula validation

RNC is the Dominican Republic's tax ID system:

* **RNC** — 9-digit tax ID for companies
* **Cédula** — 11-digit personal ID

The system validates RNCs against DGII (Dirección General de Impuestos Internos):

```
User enters RNC → Frontend calls /validate-rnc
                        ↓
              Backend queries DGII API
                        ↓
                ┌──────┴──────┐
                ↓             ↓
             Valid          Invalid
                ↓             ↓
          Return company   Return error
               name
                ↓
          Auto-fill name
            in form
```

### When RNC is required

| Situation             | Requirement |
| --------------------- | ----------- |
| NCF Types 01, 14, 15  | Required    |
| Invoice ≥ RD\$250,000 | Required    |
| Other cases           | Optional    |

### UI validation states

* **Idle** — No validation icon
* **Validating** — Spinner
* **Valid** — Green checkmark + success message + auto-filled name
* **Invalid** — Red X + error message

Users can proceed with creation even if RNC is invalid (for optional cases), but the backend validates again on save.

## User flow — assigning a customer

<Steps>
  <Step title="Open customer lookup">
    Tap "Select Customer" in the order panel. Navigates to `/pos-react/order/customer/?orderId=X&table=Y`.
  </Step>

  <Step title="Search">
    Type name, phone, email, or RNC. Results appear after 300ms debounce.
  </Step>

  <Step title="Select or create">
    Tap "Select" on an existing customer, or tap "Add Customer" to create one.
  </Step>

  <Step title="If creating (with RNC)">
    Enter RNC → blur or tap "Validate" → name auto-fills from DGII → tap "Save".
  </Step>

  <Step title="Customer assigned">
    Order panel shows "Customer: Name". Data persists with the order in IndexedDB and is sent with the order on checkout.
  </Step>
</Steps>

## Customer select button

The `CustomerSelectButton` component provides a compact way to assign or view the customer on an order. It appears in the order panel header.

* Displays the assigned customer name or a "Select Customer" placeholder
* Shows a pricelist badge (amber) if the customer has a non-default pricelist
* Navigates to the customer lookup screen on tap, preserving return context via `sessionStorage`

## Credit limit

Customers can have a `creditLimit` field (from Odoo's `res.partner.credit_limit`). When assigned to an order, the payment screen enables a credit payment button if the credit limit is greater than zero.

See [Credit payments](/guides/credit-payments) for the full credit payment flow.

## Fiscal position

Each customer can have a `property_account_position_id` (fiscal position) assigned in Odoo. When a customer is selected for an order, their fiscal position overrides the config default and triggers real-time tax remapping on the frontend.

The `Customer` model includes `fiscalPositionId?: number`, populated from `property_account_position_id` in both the bootstrap `partners` array and the customer API responses (search, get, create, update).

See [Tax calculation — Fiscal position tax remapping](/architecture/tax-calculation#fiscal-position-tax-remapping) for the full resolution chain and how order type interacts with customer fiscal positions.

## State management

The `usePOS` hook has a `SET_CUSTOMER` action:

```typescript theme={null}
setCustomer(orderId, partnerId, customerName);
// Sets order.partnerId and order.customerName
// Persists to IndexedDB with order state
```

## Keyboard shortcuts (customer lookup screen)

| Key     | Action               |
| ------- | -------------------- |
| `Esc`   | Go back              |
| `/`     | Focus search         |
| `Enter` | Select single result |

## Known limitations

1. State/country dropdowns not implemented (M2O fields are read-only)
2. `pos.config.default_partner_id` is not auto-selected
3. No customer order history display
4. No duplicate customer detection
5. Offline RNC validation requires internet connection

## Common issues

<AccordionGroup>
  <Accordion title="'Access denied to POS API'">
    Ensure the user has `point_of_sale.group_pos_user` membership in Odoo.
  </Accordion>

  <Accordion title="'CSRF token missing'">
    Check that the CSRF token is cached correctly and the session is valid.
  </Accordion>

  <Accordion title="'RNC validation failed'">
    * Check internet connection (DGII requires external access)
    * Verify the DGII module is installed on Odoo
    * Personal cédulas may not be in the DGII registry — this is expected
  </Accordion>
</AccordionGroup>
