Sales (Proforma Lines and Credits)
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:
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"
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()
$response = Http::withToken('YOUR_API_TOKEN')
->get('https://your-instance.bluerocktel.net/api/v1/sales-proforma', [
'invoice_proforma_id' => 15,
]);
$sales = $response->json();
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:
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
}'
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()
$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();
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:
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}'
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()
$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();
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:
curl -X POST "https://your-instance.bluerocktel.net/api/v1/sales/credit" \
-H "Content-Type: application/json" \
-d '{"sale_id": 200, "amount": 50.00}'
import requests
response = requests.post(
"https://your-instance.bluerocktel.net/api/v1/sales/credit",
json={"sale_id": 200, "amount": 50.00}
)
result = response.json()
$response = Http::post('https://your-instance.bluerocktel.net/api/v1/sales/credit', [
'sale_id' => 200,
'amount' => 50.00,
]);
$result = $response->json();
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();
On this page