# DoliMiddlewareApi - API Reference

BFF (Backend For Frontend) between the Vue.js frontend and Dolibarr ERP.

Base URL: `http://localhost:5269` (dev) / `http://localhost:5000` (Docker)

Auth: All endpoints except `POST /api/Auth/login` require a JWT Bearer token.

---

## Authentication

### POST /api/Auth/login
Login and get JWT token.

**Request:**
```json
{
  "username": "admin",
  "password": "12345678"
}
```

**Response:** `200 OK`
```json
{
  "token": "eyJhbGciOiJIUzI1NiIs..."
}
```

After login, include the token in all requests: `Authorization: Bearer <token>`

---

## Clients

### GET /api/Clients
List clients with their contacts.

**Query params:** `limit` (default 50), `page` (default 1)

**Response:** `200 OK`
```json
[
  {
    "id": 1,
    "name": "Client Name",
    "codeClient": "CU0001",
    "typentCode": null,
    "status": "1",
    "email": "client@example.com",
    "phone": "+34600000000",
    "contacts": [
      { "id": 1, "lastname": "Garcia", "firstname": "Ana", "email": "ana@example.com", "phonePro": "...", "phonePerso": "...", "phoneMobile": "...", "clientId": 1 }
    ]
  }
]
```

### GET /api/Clients/{id}
Get client detail with contacts and full address info.

**Response:** `200 OK`
```json
{
  "id": 1,
  "name": "Client Name",
  "codeClient": "CU0001",
  "typentCode": null,
  "status": "1",
  "email": "client@example.com",
  "phone": "+34600000000",
  "address": "Calle Mayor 1",
  "town": "Madrid",
  "zip": "28001",
  "countryCode": "ES",
  "vatNumber": "B12345678",
  "url": null,
  "notePublic": null,
  "notePrivate": null,
  "contacts": [...]
}
```

### POST /api/Clients
Create a new client.

**Request:**
```json
{
  "name": "New Client",
  "address": "Calle Example 5",
  "zip": "28001",
  "town": "Madrid",
  "phone": "+34600000000",
  "email": "client@example.com",
  "countryCode": "ES",
  "vatNumber": null,
  "url": null,
  "notePublic": null,
  "notePrivate": null
}
```

**Response:** `201 Created` → Returns new client ID (int)

### PUT /api/Clients/{id}
Update a client. Only send fields you want to change.

**Request:**
```json
{
  "name": "Updated Name",
  "phone": "+34611111111"
}
```

**Response:** `204 No Content`

### DELETE /api/Clients/{id}
Delete a client.

**Response:** `204 No Content`

---

## Contacts

### GET /api/Contacts
List contacts. Optionally filter by client.

**Query params:** `limit` (default 50), `page` (default 1), `thirdpartyIds` (comma-separated client IDs)

Example: `GET /api/Contacts?thirdpartyIds=1,2&limit=100`

**Response:** `200 OK`
```json
[
  { "id": 1, "lastname": "Garcia", "firstname": "Ana", "email": "ana@example.com", "phonePro": "...", "phonePerso": null, "phoneMobile": "...", "clientId": 1 }
]
```

### GET /api/Contacts/{id}
Get contact detail with address and civility info.

**Response:** `200 OK`
```json
{
  "id": 1,
  "lastname": "Garcia",
  "firstname": "Ana",
  "email": "ana@example.com",
  "phonePro": "+34910000000",
  "phonePerso": null,
  "phoneMobile": "+34600000001",
  "clientId": 1,
  "address": "Calle Example 5",
  "town": "Madrid",
  "zip": "28001",
  "civilityCode": null,
  "status": "active"
}
```

### GET /api/Contacts/email/{email}
Find a contact by email address.

**Response:** `200 OK` → Same as `GET /api/Contacts/{id}`

### POST /api/Contacts
Create a contact.

**Request:**
```json
{
  "lastname": "Garcia",
  "firstname": "Ana",
  "clientId": 1,
  "email": "ana@example.com",
  "phonePro": "+34910000000",
  "phoneMobile": "+34600000001",
  "address": "Calle Example 5",
  "zip": "28001",
  "town": "Madrid"
}
```

**Response:** `201 Created` → Returns new contact ID (int)

### PUT /api/Contacts/{id}
Update a contact. Only send fields to change.

**Response:** `204 No Content`

### DELETE /api/Contacts/{id}
Delete a contact.

**Response:** `204 No Content`

---

## Invoices

### GET /api/Invoices
List invoices.

**Query params:** `limit` (default 50), `page` (default 1), `status` (draft/unpaid/paid), `search` (ref search)

### GET /api/Invoices/{id}
Get invoice detail with lines, totals, and payment info.

### POST /api/Invoices
Create invoice. See existing frontend for request body format.

### PUT /api/Invoices/{id}
Update invoice (expireDate, notePublic, notePrivate, number).

### PATCH /api/Invoices/{id}/status
Change invoice status: `{ "status": "draft" | "unpaid" | "paid" }`

### POST /api/Invoices/{id}/validate
Validate (confirm) a draft invoice.

### DELETE /api/Invoices/{id}
Delete a draft invoice.

### POST /api/Invoices/{id}/lines
Add a line to a draft invoice.

**Request:**
```json
{ "description": "Service", "quantity": 1, "unitPrice": 100, "taxRate": 21 }
```

### PUT /api/Invoices/{invoiceId}/lines/{lineId}
Update a line in a draft invoice.

**Request:**
```json
{ "description": "Updated desc", "quantity": 2, "unitPrice": 150, "taxRate": 10 }
```
All fields optional — only send what you want to change.

### DELETE /api/Invoices/{invoiceId}/lines/{lineId}
Delete a line from a draft invoice.

### GET /api/Invoices/{id}/payments
List payments for an invoice.

### POST /api/Invoices/{id}/payments
Add payment to an invoice.

### GET /api/Invoices/templates
List invoice templates (recurring invoices in Dolibarr).

---

## Documents

### GET /api/Document/invoice/{invoiceRef}/pdf
Download/build a PDF for an invoice. Returns `application/pdf` file.

### GET /api/Document/list
List documents for an element.

**Query params:** `modulePart` (default "invoice"), `refId` (required — invoice ref or societe id)

### GET /api/Document/download
Download a document file.

**Query params:** `modulePart` (default "invoice"), `file` (required — file path in Dolibarr)

---

## Setup (Reference Data)

These endpoints return dictionary/reference data from Dolibarr, useful for populating dropdowns and selectors.

### GET /api/Setup/payment-types
Returns payment type options (Cash, Cheque, Credit card, etc.)

```json
[
  { "id": "4", "code": "LIQ", "label": "Cash", "type": "2" },
  { "id": "6", "code": "CB", "label": "Credit card", "type": "2" },
  { "id": "7", "code": "CHQ", "label": "Cheque", "type": "2" }
]
```

### GET /api/Setup/countries
Returns country list with ISO codes.

### GET /api/Setup/civilities
Returns civility titles (Mr, Mrs, etc.).

### GET /api/Setup/contact-types
Returns contact type labels.

### GET /api/Setup/payment-terms
Returns payment terms (Due on receipt, 30 days, etc.).

### GET /api/Setup/company
Returns your company info (name, address, VAT number, etc.).

---

## Deployment

### Docker Compose

1. Copy `.env.example` to `.env` and set `JWT_SECRET` to a long random string
2. Run: `docker compose up -d`
3. BFF will be available at `http://localhost:5000`
4. Swagger UI at `http://localhost:5000/swagger`

### Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `Jwt__Secret` | Yes | JWT signing key, min 32 chars |
| `Dolibarr__ApiUrl` | Yes | Dolibarr API base URL (e.g. `http://dolibarr/api/index.php`) |
| `Cors__AllowedOrigins` | No | Semicolon-separated CORS origins. Empty = allow all |
| `ASPNETCORE_ENVIRONMENT` | No | `Production` or `Development` |

### Frontend .env

```
VITE_API_BASE_URL=http://localhost:5000
```

When connecting to the BFF in Docker, use `http://localhost:5000` (the BFF port), not the Dolibarr port directly.