---
title: "Sales (Proforma Lines and Credits)"
section: "Billing & Finance"
order: 62
excerpt: "Manage proforma sales lines with automatic price calculation from catalog items, including credit applications."
---

**Auth required:** Yes (`auth:api`) for protected endpoints.

---

## Model Properties

### Sale (Invoiced Line Item)

Sale lines are created automatically by the billing engine when invoices are generated. They are read-only.

| Property | Type | Description |
|---|---|---|
| `id` | integer | Unique identifier |
| `invoice_id` | integer | FK to invoices |
| `customer_file_id` | integer | FK to customer_files |
| `line_key` | string | Links this sale to the source billing item (initial or recurring) |
| `item_id` | integer | FK to items (catalog item) |
| `family_id` | integer | FK to families (product family at time of billing) |
| `sale_type` | string | Type of sale: `initial`, `recurring`, or `consumptions` |
| `description` | string | Item description at time of billing |
| `phone_line_description` | string | Phone line description (for consumption lines) |
| `label` | string | Custom line label |
| `quantity` | decimal | Billed quantity |
| `selling_price_without_tax_before_discount` | decimal | Unit price before discount, excl. tax |
| `tax_before_discount` | decimal | Unit tax before discount |
| `selling_price_with_tax_before_discount` | decimal | Unit price before discount, incl. tax |
| `discount_rate` | decimal | Discount rate applied |
| `selling_price_without_tax` | decimal | Unit price after discount, excl. tax |
| `tax` | decimal | Unit tax after discount |
| `selling_price_with_tax` | decimal | Unit price after discount, incl. tax |
| `line_without_tax` | decimal | Total line amount excl. tax (quantity x unit price) |
| `line_tax` | decimal | Total line tax amount |
| `line_with_tax` | decimal | Total line amount incl. tax |
| `tax_rate` | decimal | Applied VAT rate |
| `created_at` | datetime | Creation timestamp |
| `updated_at` | datetime | Last update timestamp |

---

### Proforma Sale Line

Proforma sale lines are the editable line items within a proforma invoice. Prices are auto-calculated from the catalog item when created.

| Property | Type | Required | Description |
|---|---|---|---|
| `id` | integer | auto | Unique identifier |
| `invoice_proforma_id` | integer | Yes (query param) | FK to invoices_proforma |
| `item_id` | integer | Yes* | FK to items. Required if `bar_code` not provided |
| `bar_code` | string | Yes* | Item barcode. Alternative to `item_id` |
| `quantity` | numeric | Yes | Quantity |
| `discount_rate` | decimal | No | Discount rate (e.g. `0.1` = 10%). Triggers price recalculation on update |
| `selling_price_without_tax` | decimal | auto | Selling price per unit, excl. tax. Auto-calculated from item price list |
| `buying_price_without_tax` | decimal | auto | Buying price per unit, excl. tax. Auto-calculated |
| `line_without_tax` | decimal | auto | Total line amount excl. tax |
| `created_at` | datetime | auto | Creation timestamp |
| `updated_at` | datetime | auto | Last update timestamp |

---

## Proforma Sales Lines

Base URL: `/api/v1/sales-proforma`

Sales lines are the individual line items within a proforma invoice. Prices are automatically calculated from the catalog item.

### GET /v1/sales-proforma

List proforma sales for a specific proforma invoice.

**Query parameters:**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `invoice_proforma_id` | integer | Yes | Filter by proforma invoice ID |

**Response 200:** Array of proforma sale objects.

**Examples:**

```bash
curl -X GET "https://your-instance.bluerocktel.net/api/v1/sales-proforma?invoice_proforma_id=15" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"
```

```python
import requests

response = requests.get(
    "https://your-instance.bluerocktel.net/api/v1/sales-proforma",
    params={"invoice_proforma_id": 15},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"}
)
sales = response.json()
```

```php
$response = Http::withToken('YOUR_API_TOKEN')
    ->get('https://your-instance.bluerocktel.net/api/v1/sales-proforma', [
        'invoice_proforma_id' => 15,
    ]);

$sales = $response->json();
```

```javascript
const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/sales-proforma?invoice_proforma_id=15",
  {
    headers: {
      "Authorization": "Bearer YOUR_API_TOKEN",
      "Accept": "application/json"
    }
  }
);
const sales = await response.json();
```

---

### POST /v1/sales-proforma

Create a new proforma sale line. Prices are auto-calculated: buying price, selling price, taxes, discounts. The item can be identified by `item_id` or `bar_code`.

**Query parameters:**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `invoice_proforma_id` | integer | Yes | Proforma invoice to add the line to |

**Body (JSON):** Validated via `sale_proforma::attributes('common', 'store')`:

| Field | Type | Description |
|---|---|---|
| `item_id` | integer | Catalog item ID (alternatively: `bar_code`) |
| `bar_code` | string | Item barcode (alternative to `item_id`) |
| `quantity` | numeric | Quantity |
| `discount_rate` | numeric | Discount percentage |
| ... | ... | Other proforma sale fields |

Prices are computed from the item's price list adjusted for customer VAT and provided discount.

**Response 201:** Created proforma sale object.
**Response 422:** Invalid item or validation error.

**Examples:**

```bash
curl -X POST "https://your-instance.bluerocktel.net/api/v1/sales-proforma?invoice_proforma_id=15" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "item_id": 100,
    "quantity": 2,
    "discount_rate": 10
  }'
```

```python
import requests

response = requests.post(
    "https://your-instance.bluerocktel.net/api/v1/sales-proforma",
    params={"invoice_proforma_id": 15},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"},
    json={
        "item_id": 100,
        "quantity": 2,
        "discount_rate": 10
    }
)
sale = response.json()
```

```php
$response = Http::withToken('YOUR_API_TOKEN')
    ->post('https://your-instance.bluerocktel.net/api/v1/sales-proforma?invoice_proforma_id=15', [
        'item_id' => 100,
        'quantity' => 2,
        'discount_rate' => 10,
    ]);

$sale = $response->json();
```

```javascript
const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/sales-proforma?invoice_proforma_id=15",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer YOUR_API_TOKEN",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      item_id: 100,
      quantity: 2,
      discount_rate: 10
    })
  }
);
const sale = await response.json();
```

---

### GET /v1/sales-proforma/{id}

Get a single proforma sale line.

**URL parameters:**

| Parameter | Type | Description |
|---|---|---|
| `id` | integer | Proforma sale ID |

**Response 200:** Proforma sale object.
**Response 404:** Not found.

---

### PUT /v1/sales-proforma/{id}

Update a proforma sale line. All pricing fields are recalculated.

**URL parameters:**

| Parameter | Type | Description |
|---|---|---|
| `id` | integer | Proforma sale ID |

**Body (JSON):** Validated via `sale_proforma::attributes('common')`.

**Response 201:** Updated proforma sale object.
**Response 404:** Not found.

**Examples:**

```bash
curl -X PUT "https://your-instance.bluerocktel.net/api/v1/sales-proforma/88" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"quantity": 5, "discount_rate": 15}'
```

```python
import requests

response = requests.put(
    "https://your-instance.bluerocktel.net/api/v1/sales-proforma/88",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"},
    json={"quantity": 5, "discount_rate": 15}
)
sale = response.json()
```

```php
$response = Http::withToken('YOUR_API_TOKEN')
    ->put('https://your-instance.bluerocktel.net/api/v1/sales-proforma/88', [
        'quantity' => 5,
        'discount_rate' => 15,
    ]);

$sale = $response->json();
```

```javascript
const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/sales-proforma/88",
  {
    method: "PUT",
    headers: {
      "Authorization": "Bearer YOUR_API_TOKEN",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ quantity: 5, discount_rate: 15 })
  }
);
const sale = await response.json();
```

---

### DELETE /v1/sales-proforma/{id}

Delete a proforma sale line.

**URL parameters:**

| Parameter | Type | Description |
|---|---|---|
| `id` | integer | Proforma sale ID |

**Response 200:** Success message.
**Response 404:** Not found.

---

## Sale Credit

Base URL: `/api/v1/`

### POST /v1/sales/credit

Apply a credit to a sale. This endpoint does NOT require authentication (`auth:api` middleware is NOT applied).

**Body (JSON):**

Details depend on the `ApiSaleController@credit` implementation.

**Response:** Credit result.

**Examples:**

```bash
curl -X POST "https://your-instance.bluerocktel.net/api/v1/sales/credit" \
  -H "Content-Type: application/json" \
  -d '{"sale_id": 200, "amount": 50.00}'
```

```python
import requests

response = requests.post(
    "https://your-instance.bluerocktel.net/api/v1/sales/credit",
    json={"sale_id": 200, "amount": 50.00}
)
result = response.json()
```

```php
$response = Http::post('https://your-instance.bluerocktel.net/api/v1/sales/credit', [
    'sale_id' => 200,
    'amount' => 50.00,
]);

$result = $response->json();
```

```javascript
const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/sales/credit",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ sale_id: 200, amount: 50.00 })
  }
);
const result = await response.json();
```
