Investigation Packages (باقات الفحوصات)
Commercial test packages are discounted bundles of investigations sold at a reduced price. They are a pricing concept — distinct from panels (which are atomic test units defined via is_panel on investigations).
Entity Attributes
| Field | Type | Description |
|---|---|---|
id | bigint | Primary key |
company_id | FK | Company |
name | string | English name |
name_ar | string | Arabic name |
code | string(50) | Auto-generated or manual (unique per company) |
description | text | Optional description |
total_price | decimal(12,3) | Sum of member investigation prices (auto-calculated) |
package_price | decimal(12,3) | Discounted bundle price |
savings_percentage | decimal(5,2) | Auto-calculated: (total_price - package_price) / total_price * 100 |
is_active | boolean | Whether package is available for selection |
valid_from | date | Start of validity period (nullable) |
valid_to | date | End of validity period (nullable) |
created_by | FK | Creator user |
updated_by | FK | Last updater |
ER Diagram
API Endpoints
| Method | Path | Description | Permission |
|---|---|---|---|
| GET | /api/lis/packages | List packages | lis.packages.view |
| POST | /api/lis/packages | Create package | lis.packages.create |
| GET | /api/lis/packages/{id} | Show package | lis.packages.view |
| PUT | /api/lis/packages/{id} | Update package | lis.packages.update |
| DELETE | /api/lis/packages/{id} | Delete package | lis.packages.delete |
Query Parameters (index)
| Parameter | Type | Description |
|---|---|---|
search | string | Filter by name, name_ar, or code |
is_active | boolean | Filter by active status |
Create / Update Request
bash
curl -X POST /api/lis/packages \
-H "Authorization: Bearer {token}" \
-d '{
"name": "Comprehensive Panel",
"name_ar": "باقة شاملة",
"package_price": 80.000,
"investigations": [
{"investigation_id": 1, "sort_order": 0},
{"investigation_id": 2, "sort_order": 1},
{"investigation_id": 3, "sort_order": 2}
]
}'dart
final response = await dio.post('/api/lis/packages', data: {
'name': 'Comprehensive Panel',
'name_ar': 'باقة شاملة',
'package_price': 80.0,
'investigations': [
{'investigation_id': 1, 'sort_order': 0},
{'investigation_id': 2, 'sort_order': 1},
{'investigation_id': 3, 'sort_order': 2},
],
});Using Packages in Request Creation
When creating a lab request, you can include packages[] alongside investigations[]:
bash
curl -X POST /api/lis/requests \
-H "Authorization: Bearer {token}" \
-d '{
"patient_id": 1,
"investigations": [
{"investigation_id": 10, "price": 15.000}
],
"packages": [
{"package_id": 1}
]
}'dart
final response = await dio.post('/api/lis/requests', data: {
'patient_id': 1,
'investigations': [
{'investigation_id': 10, 'price': 15.0},
],
'packages': [
{'package_id': 1},
],
});Business Rules
- Auto-calculation:
total_priceis computed as the sum of member investigation prices;savings_percentageis derived from the difference. - Duplicate prevention: When a package is added to a request, investigations already present (from individual selection or another package) are skipped.
- Inactive/expired rejection: Only active packages within their validity period are processed; invalid packages are silently skipped.
- Price snapshot: When a package is selected on a request,
package_priceanddiscount_amountare snapshotted tolab_request_packages. - Net amount formula:
net_amount = total_amount - discount_amount - package_discount - Delete guard: Packages used in non-cancelled requests cannot be deleted.
- Code auto-generation: If
codeis not provided, it is auto-generated via the PKG sequence.