Jobs Module¶
FSM (Field Service Management) job management and digital signature capture.
Overview¶
The Jobs module provides field technicians with:
- Active job list with stage filtering
- Job details with customer information
- Stage workflow management
- Digital signature capture with S3 storage
- Activity logging and comments
- Parts and warranty acknowledgments
Routes¶
Job List¶
GET /jobs/active
Lists all active (non-closed) FSM orders grouped by stage.
| Parameter | Type | Description |
|---|---|---|
| type | string | Filter by job type: install or service |
| period | string | Filter by date: today, this_week, next_week |
Job Detail¶
GET /jobs/{fsm_id}
Displays full job details including:
- Customer information
- Scheduled date/time
- Stage and signature status
- Parts summary
- Activity log
Signature Page¶
GET /jobs/{fsm_id}/signature
Digital signature capture page for customer sign-off.
API Endpoints¶
Change Stage¶
POST /api/jobs/{fsm_id}/stage
Move job to a different stage.
Response:
Complete Job¶
POST /api/jobs/{fsm_id}/complete
Mark job as done using Odoo's action_complete.
Response:
Submit Signature¶
POST /api/jobs/{fsm_id}/signature
Submit customer signature and complete the job.
{
"signer_name": "John Doe",
"signer_relationship": "Owner",
"signature_image": "data:image/png;base64,...",
"warranty_ack": true,
"parts_ack": true,
"payment_method": "Credit Card",
"completion_notes": "Job completed successfully"
}
Response:
Load Parts Summary¶
POST /api/jobs/{fsm_id}/load-parts
Load parts summary from linked sale order.
Response:
{
"success": true,
"parts_summary": "2x Window Blinds 48x72\n1x Motorized System",
"removed_items_summary": "1x Old blinds removed"
}
Load Warranty¶
POST /api/jobs/{fsm_id}/load-warranty
Load warranty text from template.
Response:
Post Comment¶
POST /api/jobs/{fsm_id}/comment
Add a comment to the job's activity log.
Response:
Get Stages¶
GET /api/stages
Get all FSM stages for workflow buttons.
Response:
{
"success": true,
"stages": [
{"id": 1, "name": "New", "sequence": 1, "is_closed": false},
{"id": 2, "name": "Scheduled", "sequence": 2, "is_closed": false},
{"id": 3, "name": "In Progress", "sequence": 3, "is_closed": false},
{"id": 4, "name": "Done", "sequence": 10, "is_closed": true}
]
}
Signature Flow¶
sequenceDiagram
participant Tech as Technician
participant PWA
participant S3
participant Odoo
Tech->>PWA: Open signature page
PWA->>Odoo: Load parts/warranty
Odoo-->>PWA: Display data
Tech->>Tech: Customer signs on canvas
Tech->>PWA: Submit signature
PWA->>S3: Upload PNG image
S3-->>PWA: bucket/key path
PWA->>Odoo: Update FSM fields
Note over Odoo: x_signature_url<br/>x_signed_name<br/>x_signed_datetime<br/>x_warranty_ack<br/>x_parts_ack
PWA->>Odoo: mark_signature_complete()
PWA->>Odoo: send_completion_report()
Odoo-->>PWA: Email sent
PWA-->>Tech: Success message
FSM Custom Fields¶
The signature flow uses these custom fields on fsm.order:
| Field | Type | Description |
|---|---|---|
x_signature_url |
Char | S3 path (bucket/key) |
x_signed_name |
Char | Signer's name |
x_signer_relationship |
Char | Relationship (Owner, Tenant, etc.) |
x_signed_datetime |
Datetime | When signed |
x_signature_state |
Selection | pending or signed |
x_warranty_text |
Text | Warranty terms |
x_warranty_ack |
Boolean | Warranty acknowledged |
x_warranty_ack_datetime |
Datetime | When acknowledged |
x_parts_summary |
Text | Parts list from SO |
x_removed_items_summary |
Text | Removed items |
x_parts_ack |
Boolean | Parts acknowledged |
x_parts_ack_datetime |
Datetime | When acknowledged |
x_completion_notes |
Text | Tech notes |
x_payment_method |
Char | Payment method used |
Job Type Filtering¶
Jobs are categorized as:
- Install: Regular installation jobs
- Service (A/S): After-service/warranty jobs
Detection logic:
def _is_service_job(job):
type_name = job.get('type', [None, ''])[1] if job.get('type') else ''
return 'A/S' in type_name or 'AS' in type_name or 'Service' in type_name
Period Filtering¶
Jobs can be filtered by scheduled date:
| Period | Range |
|---|---|
today |
Current date only |
this_week |
Monday to Sunday of current week |
next_week |
Monday to Sunday of next week |
Stage Grouping¶
Jobs are displayed grouped by stage, sorted by stage sequence:
# Sort stages by sequence (priority)
stages_list = sorted(stages.values(), key=lambda s: s['sequence'])
Activity Attribution¶
Stage changes and comments are properly attributed to the user:
# Use write_as_user for proper activity attribution
odoo_api.write_as_user('fsm.order', fsm_id, {'stage_id': stage_id}, partner_id)
This ensures the activity log shows the correct user who made the change, not the service account.
S3 Signature Storage¶
Signatures are stored in S3 with the path format:
The path is stored in Odoo's x_signature_url field. To display the signature, a pre-signed URL is generated:
Pre-signed URLs expire after 1 hour.
Completion Report¶
After signature submission, a completion report email is sent:
This calls action_send_completion_report_auto on the FSM order, which:
- Generates a PDF report
- Sends email to customer
- Sets
x_completion_report_sent = True
Email sending is non-blocking - signature is saved even if email fails.
Attachment Downloads¶
Job attachments can be downloaded through the PWA:
GET /api/attachment/{attachment_id}
Proxies attachment download from Odoo with proper content type.
Offline Support¶
Job list and detail pages are cached by the service worker:
- API GET requests: Network-first with 1-hour cache fallback
- Static assets: Cache-first with 30-day TTL
- HTML pages: Network-first with offline fallback
This allows technicians to view job information even without connectivity.