Initial commit - Fire alarm management application
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
722
API.md
Normal file
722
API.md
Normal file
@@ -0,0 +1,722 @@
|
||||
# API Documentation
|
||||
|
||||
The Romanoff Fire Alarm Management System provides a RESTful API for programmatic access to all data. All API endpoints are prefixed with `/api`.
|
||||
|
||||
## Base URL
|
||||
|
||||
```
|
||||
http://localhost:5000/api
|
||||
```
|
||||
|
||||
## Response Format
|
||||
|
||||
All API responses are JSON. Successful responses return the requested data directly. Error responses include appropriate HTTP status codes.
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Dashboard Statistics
|
||||
|
||||
#### Get Dashboard Stats
|
||||
|
||||
```
|
||||
GET /api/stats
|
||||
```
|
||||
|
||||
Returns aggregated statistics for the dashboard.
|
||||
|
||||
**Response**
|
||||
|
||||
```json
|
||||
{
|
||||
"total_jobs": 25,
|
||||
"total_budget": 1500000.00,
|
||||
"total_labor": 450000.00,
|
||||
"total_material": 350000.00,
|
||||
"avg_completion": 65.5,
|
||||
"completed_jobs": 8,
|
||||
"in_progress_jobs": 15,
|
||||
"not_started_jobs": 2,
|
||||
"vendor_budgets": {
|
||||
"Vendor A": 750000.00,
|
||||
"Vendor B": 500000.00,
|
||||
"Unknown": 250000.00
|
||||
},
|
||||
"pm_jobs": {
|
||||
"John Smith": {
|
||||
"count": 10,
|
||||
"budget": 600000.00
|
||||
},
|
||||
"Jane Doe": {
|
||||
"count": 8,
|
||||
"budget": 500000.00
|
||||
}
|
||||
},
|
||||
"jobs_completion": [
|
||||
{
|
||||
"id": 1,
|
||||
"job_number": "JOB-001",
|
||||
"name": "Project Alpha",
|
||||
"completion": 75.0,
|
||||
"budget": 50000.00,
|
||||
"pm_assigned": "John Smith"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Jobs
|
||||
|
||||
#### List All Jobs
|
||||
|
||||
```
|
||||
GET /api/jobs
|
||||
```
|
||||
|
||||
Returns a list of all jobs.
|
||||
|
||||
**Response**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"job_number": "JOB-001",
|
||||
"job_name": "Project Alpha",
|
||||
"location": "123 Main St, Raleigh, NC",
|
||||
"percent_complete": 0.75,
|
||||
"est_starting_qtr": "Q1 2025",
|
||||
"fire_alarm_budget": 50000.00,
|
||||
"labor_estimate": 20000.00,
|
||||
"material_estimate": 15000.00,
|
||||
"amount_left_on_contract": 15000.00,
|
||||
"pm_assigned": "John Smith",
|
||||
"aor": "Region A",
|
||||
"fire_vendor": "Vendor A",
|
||||
"install_partner": "Partner Inc",
|
||||
"ps_or_install": "Install",
|
||||
"subcontractor": "Sub Co",
|
||||
"pci": "Yes",
|
||||
"voip_or_phone": "VoIP",
|
||||
"plans": "Approved",
|
||||
"notes": "Project notes here",
|
||||
"issues": "No major issues",
|
||||
"milestone_1": "Permits obtained",
|
||||
"milestone_2": "Rough-in complete",
|
||||
"milestone_3": null,
|
||||
"milestone_4": null,
|
||||
"milestone_5": null,
|
||||
"milestone_6": null,
|
||||
"milestone_7": null,
|
||||
"elevator_final": "2025-03-15",
|
||||
"pretest": "2025-04-01",
|
||||
"final_date": "2025-04-15",
|
||||
"co_drop_dead_date": "2025-04-30",
|
||||
"number_of_units": 150,
|
||||
"sep_club_house": "Yes",
|
||||
"created_at": "2025-01-01T00:00:00",
|
||||
"updated_at": "2025-01-15T12:30:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Get Single Job
|
||||
|
||||
```
|
||||
GET /api/jobs/<id>
|
||||
```
|
||||
|
||||
Returns a single job by ID.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| id | integer | Job ID (path parameter) |
|
||||
|
||||
**Response**
|
||||
|
||||
Returns a job object (same structure as list item above).
|
||||
|
||||
**Errors**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 404 | Job not found |
|
||||
|
||||
#### Create Job
|
||||
|
||||
```
|
||||
POST /api/jobs
|
||||
```
|
||||
|
||||
Creates a new job.
|
||||
|
||||
**Request Body**
|
||||
|
||||
```json
|
||||
{
|
||||
"job_number": "JOB-002",
|
||||
"job_name": "Project Beta",
|
||||
"location": "456 Oak Ave, Raleigh, NC",
|
||||
"percent_complete": 0,
|
||||
"est_starting_qtr": "Q2 2025",
|
||||
"fire_alarm_budget": 75000.00,
|
||||
"labor_estimate": 30000.00,
|
||||
"material_estimate": 25000.00,
|
||||
"amount_left_on_contract": 75000.00,
|
||||
"pm_assigned": "Jane Doe",
|
||||
"aor": "Region B",
|
||||
"fire_vendor": "Vendor B",
|
||||
"install_partner": "Partner Corp",
|
||||
"ps_or_install": "PS",
|
||||
"subcontractor": "Sub LLC",
|
||||
"pci": "No",
|
||||
"voip_or_phone": "Phone",
|
||||
"plans": "Pending",
|
||||
"notes": "New project",
|
||||
"issues": "",
|
||||
"milestone_1": "Site survey",
|
||||
"number_of_units": 200,
|
||||
"sep_club_house": "No",
|
||||
"elevator_final": "2025-06-15",
|
||||
"pretest": "2025-07-01",
|
||||
"final_date": "2025-07-15",
|
||||
"co_drop_dead_date": "2025-07-31"
|
||||
}
|
||||
```
|
||||
|
||||
**Required Fields**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| job_number | string | Unique job identifier |
|
||||
| job_name | string | Job name/title |
|
||||
|
||||
**Optional Fields**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| location | string | Job location address |
|
||||
| percent_complete | float | Completion percentage (0.0 - 1.0) |
|
||||
| est_starting_qtr | string | Estimated starting quarter |
|
||||
| fire_alarm_budget | float | Total fire alarm budget |
|
||||
| labor_estimate | float | Labor cost estimate |
|
||||
| material_estimate | float | Material cost estimate |
|
||||
| amount_left_on_contract | float | Remaining contract amount |
|
||||
| pm_assigned | string | Project manager name |
|
||||
| aor | string | Area of responsibility |
|
||||
| fire_vendor | string | Fire alarm vendor |
|
||||
| install_partner | string | Installation partner |
|
||||
| ps_or_install | string | PS or Install designation |
|
||||
| subcontractor | string | Subcontractor name |
|
||||
| pci | string | PCI status |
|
||||
| voip_or_phone | string | Communication type |
|
||||
| plans | string | Plans status |
|
||||
| notes | string | General notes |
|
||||
| issues | string | Known issues |
|
||||
| milestone_1 - milestone_7 | string | Project milestones |
|
||||
| elevator_final | date | Elevator final date (YYYY-MM-DD) |
|
||||
| pretest | date | Pretest date (YYYY-MM-DD) |
|
||||
| final_date | date | Final date (YYYY-MM-DD) |
|
||||
| co_drop_dead_date | date | CO drop dead date (YYYY-MM-DD) |
|
||||
| number_of_units | integer | Number of units |
|
||||
| sep_club_house | string | Separate club house indicator |
|
||||
|
||||
**Response**
|
||||
|
||||
Returns the created job object with status `201 Created`.
|
||||
|
||||
#### Update Job
|
||||
|
||||
```
|
||||
PUT /api/jobs/<id>
|
||||
```
|
||||
|
||||
Updates an existing job.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| id | integer | Job ID (path parameter) |
|
||||
|
||||
**Request Body**
|
||||
|
||||
Include only the fields you want to update. Same fields as create.
|
||||
|
||||
```json
|
||||
{
|
||||
"percent_complete": 0.85,
|
||||
"notes": "Updated project notes"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**
|
||||
|
||||
Returns the updated job object.
|
||||
|
||||
**Errors**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 404 | Job not found |
|
||||
|
||||
#### Delete Job
|
||||
|
||||
```
|
||||
DELETE /api/jobs/<id>
|
||||
```
|
||||
|
||||
Deletes a job and all associated phases and materials.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| id | integer | Job ID (path parameter) |
|
||||
|
||||
**Response**
|
||||
|
||||
Returns `204 No Content` on success.
|
||||
|
||||
**Errors**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 404 | Job not found |
|
||||
|
||||
---
|
||||
|
||||
### Phases
|
||||
|
||||
#### List Phases for Job
|
||||
|
||||
```
|
||||
GET /api/jobs/<job_id>/phases
|
||||
```
|
||||
|
||||
Returns all phases for a specific job.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| job_id | integer | Job ID (path parameter) |
|
||||
|
||||
**Response**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"job_id": 1,
|
||||
"phase_type": "rough_in",
|
||||
"phase_number": 1,
|
||||
"points": 500,
|
||||
"mobilization_date": "2025-02-01",
|
||||
"start_date": "2025-02-05",
|
||||
"due_date": "2025-02-28",
|
||||
"completion_date": "2025-02-25",
|
||||
"men_on_site": 5,
|
||||
"completed": true,
|
||||
"due_date_met": true,
|
||||
"pci_man_hours": 120.5,
|
||||
"rer_fire_mgmt_hours": 40.0,
|
||||
"rer_fire_mgmt_hours_avl": 50.0
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Create Phase
|
||||
|
||||
```
|
||||
POST /api/jobs/<job_id>/phases
|
||||
```
|
||||
|
||||
Creates a new phase for a job.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| job_id | integer | Job ID (path parameter) |
|
||||
|
||||
**Request Body**
|
||||
|
||||
```json
|
||||
{
|
||||
"phase_type": "trim",
|
||||
"phase_number": 2,
|
||||
"points": 300,
|
||||
"mobilization_date": "2025-03-01",
|
||||
"start_date": "2025-03-05",
|
||||
"due_date": "2025-03-31",
|
||||
"men_on_site": 4,
|
||||
"completed": false,
|
||||
"pci_man_hours": 0,
|
||||
"rer_fire_mgmt_hours": 0,
|
||||
"rer_fire_mgmt_hours_avl": 30.0
|
||||
}
|
||||
```
|
||||
|
||||
**Fields**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| phase_type | string | Phase type: `rough_in`, `trim`, `commissioning`, `final`, `turnover` |
|
||||
| phase_number | integer | Phase sequence number |
|
||||
| points | integer | Points assigned to phase |
|
||||
| mobilization_date | date | Mobilization date (YYYY-MM-DD) |
|
||||
| start_date | date | Start date (YYYY-MM-DD) |
|
||||
| due_date | date | Due date (YYYY-MM-DD) |
|
||||
| completion_date | date | Completion date (YYYY-MM-DD) |
|
||||
| men_on_site | integer | Number of workers on site |
|
||||
| completed | boolean | Whether phase is complete |
|
||||
| due_date_met | boolean | Whether due date was met |
|
||||
| pci_man_hours | float | PCI man hours |
|
||||
| rer_fire_mgmt_hours | float | RER fire management hours |
|
||||
| rer_fire_mgmt_hours_avl | float | RER fire management hours available |
|
||||
|
||||
**Response**
|
||||
|
||||
Returns the created phase object with status `201 Created`.
|
||||
|
||||
**Errors**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 404 | Job not found |
|
||||
|
||||
#### Update Phase
|
||||
|
||||
```
|
||||
PUT /api/phases/<phase_id>
|
||||
```
|
||||
|
||||
Updates an existing phase.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| phase_id | integer | Phase ID (path parameter) |
|
||||
|
||||
**Request Body**
|
||||
|
||||
Include only the fields you want to update.
|
||||
|
||||
```json
|
||||
{
|
||||
"completed": true,
|
||||
"completion_date": "2025-03-28",
|
||||
"due_date_met": true
|
||||
}
|
||||
```
|
||||
|
||||
**Response**
|
||||
|
||||
Returns the updated phase object.
|
||||
|
||||
**Errors**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 404 | Phase not found |
|
||||
|
||||
#### Delete Phase
|
||||
|
||||
```
|
||||
DELETE /api/phases/<phase_id>
|
||||
```
|
||||
|
||||
Deletes a phase.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| phase_id | integer | Phase ID (path parameter) |
|
||||
|
||||
**Response**
|
||||
|
||||
Returns `204 No Content` on success.
|
||||
|
||||
**Errors**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 404 | Phase not found |
|
||||
|
||||
---
|
||||
|
||||
### Materials
|
||||
|
||||
#### List All Materials
|
||||
|
||||
```
|
||||
GET /api/materials
|
||||
```
|
||||
|
||||
Returns all materials across all jobs.
|
||||
|
||||
**Response**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"job_id": 1,
|
||||
"part_number": "FA-SENSOR-001",
|
||||
"quantity": 50,
|
||||
"ordered": true,
|
||||
"received": true,
|
||||
"received_qty": 50,
|
||||
"received_by": "John Doe",
|
||||
"delivered_qty": 45,
|
||||
"delivered_to": "Site A - Building 1"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### List Materials for Job
|
||||
|
||||
```
|
||||
GET /api/jobs/<job_id>/materials
|
||||
```
|
||||
|
||||
Returns all materials for a specific job.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| job_id | integer | Job ID (path parameter) |
|
||||
|
||||
**Response**
|
||||
|
||||
Returns an array of material objects (same structure as above).
|
||||
|
||||
#### Create Material
|
||||
|
||||
```
|
||||
POST /api/jobs/<job_id>/materials
|
||||
```
|
||||
|
||||
Creates a new material record for a job.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| job_id | integer | Job ID (path parameter) |
|
||||
|
||||
**Request Body**
|
||||
|
||||
```json
|
||||
{
|
||||
"part_number": "FA-PANEL-002",
|
||||
"quantity": 10,
|
||||
"ordered": false,
|
||||
"received": false,
|
||||
"received_qty": 0,
|
||||
"received_by": "",
|
||||
"delivered_qty": 0,
|
||||
"delivered_to": ""
|
||||
}
|
||||
```
|
||||
|
||||
**Fields**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| part_number | string | Part/item number |
|
||||
| quantity | integer | Quantity needed |
|
||||
| ordered | boolean | Whether order has been placed |
|
||||
| received | boolean | Whether items have been received |
|
||||
| received_qty | integer | Quantity received |
|
||||
| received_by | string | Person who received items |
|
||||
| delivered_qty | integer | Quantity delivered to site |
|
||||
| delivered_to | string | Delivery location |
|
||||
|
||||
**Response**
|
||||
|
||||
Returns the created material object with status `201 Created`.
|
||||
|
||||
**Errors**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 404 | Job not found |
|
||||
|
||||
#### Update Material
|
||||
|
||||
```
|
||||
PUT /api/materials/<material_id>
|
||||
```
|
||||
|
||||
Updates an existing material record.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| material_id | integer | Material ID (path parameter) |
|
||||
|
||||
**Request Body**
|
||||
|
||||
Include only the fields you want to update.
|
||||
|
||||
```json
|
||||
{
|
||||
"ordered": true,
|
||||
"received": true,
|
||||
"received_qty": 10,
|
||||
"received_by": "Jane Smith"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**
|
||||
|
||||
Returns the updated material object.
|
||||
|
||||
**Errors**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 404 | Material not found |
|
||||
|
||||
#### Delete Material
|
||||
|
||||
```
|
||||
DELETE /api/materials/<material_id>
|
||||
```
|
||||
|
||||
Deletes a material record.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| material_id | integer | Material ID (path parameter) |
|
||||
|
||||
**Response**
|
||||
|
||||
Returns `204 No Content` on success.
|
||||
|
||||
**Errors**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 404 | Material not found |
|
||||
|
||||
---
|
||||
|
||||
## Data Types
|
||||
|
||||
### Date Format
|
||||
|
||||
All dates use ISO 8601 format: `YYYY-MM-DD`
|
||||
|
||||
Examples:
|
||||
- `2025-01-15`
|
||||
- `2025-12-31`
|
||||
|
||||
### DateTime Format
|
||||
|
||||
All timestamps use ISO 8601 format: `YYYY-MM-DDTHH:MM:SS`
|
||||
|
||||
Examples:
|
||||
- `2025-01-15T14:30:00`
|
||||
- `2025-12-31T23:59:59`
|
||||
|
||||
### Phase Types
|
||||
|
||||
Valid values for `phase_type`:
|
||||
- `rough_in` - Initial rough-in phase
|
||||
- `trim` - Trim phase
|
||||
- `commissioning` - System commissioning
|
||||
- `final` - Final inspection
|
||||
- `turnover` - Project turnover
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
The API uses standard HTTP status codes:
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Success |
|
||||
| 201 | Created |
|
||||
| 204 | No Content (successful deletion) |
|
||||
| 400 | Bad Request (invalid input) |
|
||||
| 404 | Not Found |
|
||||
| 500 | Internal Server Error |
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### cURL Examples
|
||||
|
||||
**Get all jobs:**
|
||||
```bash
|
||||
curl http://localhost:5000/api/jobs
|
||||
```
|
||||
|
||||
**Create a job:**
|
||||
```bash
|
||||
curl -X POST http://localhost:5000/api/jobs \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"job_number": "JOB-003", "job_name": "New Project"}'
|
||||
```
|
||||
|
||||
**Update a job:**
|
||||
```bash
|
||||
curl -X PUT http://localhost:5000/api/jobs/1 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"percent_complete": 0.5}'
|
||||
```
|
||||
|
||||
**Delete a job:**
|
||||
```bash
|
||||
curl -X DELETE http://localhost:5000/api/jobs/1
|
||||
```
|
||||
|
||||
### JavaScript Fetch Examples
|
||||
|
||||
**Get all jobs:**
|
||||
```javascript
|
||||
const response = await fetch('/api/jobs');
|
||||
const jobs = await response.json();
|
||||
```
|
||||
|
||||
**Create a job:**
|
||||
```javascript
|
||||
const response = await fetch('/api/jobs', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
job_number: 'JOB-003',
|
||||
job_name: 'New Project'
|
||||
})
|
||||
});
|
||||
const newJob = await response.json();
|
||||
```
|
||||
|
||||
**Update a job:**
|
||||
```javascript
|
||||
const response = await fetch('/api/jobs/1', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ percent_complete: 0.5 })
|
||||
});
|
||||
const updatedJob = await response.json();
|
||||
```
|
||||
|
||||
**Delete a job:**
|
||||
```javascript
|
||||
await fetch('/api/jobs/1', { method: 'DELETE' });
|
||||
```
|
||||
Reference in New Issue
Block a user