Documentation/Reference apps/FieldOps runs a field service job from booking to captured payment
FieldOps runs a field service job from booking to captured payment
FieldOps is an open-source field service management app: quotes, dispatch, parts, signed work orders, payment. Source on GitHub, with a live demo.
- apps
- field-service
- scheduling
- workflows
- payments
Overview
An open-source field service management app in twelve schemas, ten of them borrowing a lifecycle, with a customer signature between the technician finishing and the card being captured.
FieldOps takes a repair job from booking to payment. A customer books, a dispatcher assigns a technician, the customer signs the finished work order and then pays. The code, twelve schemas in all, is in the fieldops folder of the supero-apps repo on GitHub.
A schema is the definition of one table. Ten of the twelve in
apps/field-service/fieldops/schemas.py carry an extends key, which borrows a ready-made lifecycle from the platform. The two that extend nothing are CustomerProfile and Technician, plain records about people. Every schema that describes work or money takes its states from the platform.Seven platform services supply those states. In the order a job meets them: the service catalogue, quote approval, the appointment, parts inventory, the signed document, payment, then the recurring plan that follows. No other app among the 19 in the repo draws on as many. None has more than these twelve schemas. FieldOps is also alone in extending
document_signature or inventory.What one `extends` key brings with it
python
WorkOrderSignature = {
"schema_type": "object", "name": "WorkOrderSignature", "namespace": "fieldops",
"parent_type": "work_order", "extends": "document_signature:base_signature",
"description": "A customer signature line on a work order confirming the job is done.",
"attributes": [
{"name": "owner_username", "type": "string"},
{"name": "document_uuid", "type": "string"},
{"name": "signer_name", "type": "string"},
{"name": "signer_role", "type": "string"},
# base_signature requires: status (initial 'pending'), document_uuid.
],
}The app adds four attributes. That is all it adds. The closing comment records what the base supplies: a
status that starts at pending. The other schemas follow that shape. Quote gets draft then pending from approval:base_approval. Appointment starts at requested. Payment starts at pending and requires an amount and a currency. No state machine is written in this folder.The front end asks for transitions by name, as in
transition('payment', 'capture', …).From a booked drain cleaning to a captured payment
A customer picks one of nine seeded services (the seed is the demo data loaded at setup) and books a slot.
BookModal in ui/app.js creates an Appointment at requested and a Payment at pending in one promise chain. The dispatcher finds the job in the first of four columns on the board and assigns one of four seeded technicians. The "Confirm & dispatch" button stays disabled until somebody is assigned. Pressing it runs the appointment's schedule transition and then the appointment_dispatch workflow, whose steps post to a #dispatch Slack channel and send the technician an SMS.The technician opens the job and ticks the parts used from the
PartItem stock list. Then comes the densest button in the app: completing a job finishes the appointment, creates a WorkOrder in draft holding the chosen parts with the labour notes, attaches a WorkOrderSignature child to it, and asks the document_signature service to move the order to awaiting_signatures so that it lands in front of the customer.The customer signs.
Then the customer pays, with authorize and capture sent as two separate calls.
Three personas on two roles
setup.py writes policies for two roles only. The dispatcher is tenant_admin. Customers and technicians share tenant_user, told apart by a persona value on their CustomerProfile row, and the shell chooses an interface from it. The login screen has one button per persona.A customer and a technician have to work on the same job, so the policy leaves quotes, appointments and work orders, together with their approval steps and signature lines, readable and writable by every signed-in user in the tenant. Money is different. Payments and maintenance contracts stay private, as do profiles: their rules carry
filter_field="owner_username", policy-based row scoping, and a customer reads only their own.A settlement that knows how to undo itself
job_settlement has four steps. It opens a Stripe checkout session, creates a QuickBooks invoice, sends an email and stamps the appointment settled. The workflow is declared with "on_error": "compensate", and its first step says how to reverse itself:python
{"id": "capture", "type": "service_call", "service": "stripe_checkout",
"operation": "create_checkout_session",
"input_map": {"amount": "{{input.amount}}", "currency": "{{input.currency}}",
"product": "FieldOps job"},
"compensate": {"kind": "automatic", "service": "stripe_checkout", "operation": "refund_payment",
"input_map": {"payment_intent": "{{steps.capture.output.id}}"}}},The invoice and the email are marked
skip_acknowledged with a written reason, so the definition itself records that they are best-effort.A second workflow,
job_settlement_failtest, exists to demonstrate the mechanism. It runs the same capture step and then tries to update a payment whose id does not exist. The run fails after the capture step has succeeded, and the compensation is what is left to execute. The dispatcher console has a panel with a button for each workflow and prints the engine's result underneath.Run the field service management app with all twelve schemas
The live demo at fieldops.supero.live runs this code, from the fieldops folder. Four commands start your own copy:
bash
git clone https://github.com/supero-platform/supero-apps
cd supero-apps/apps/field-service/fieldops
cp .env.example .env # set SUPERO_DOMAIN and SUPERO_PASSWORD
./run.shThere is nothing to sign up for first. The script registers whatever free domain name you put in
.env, and the app is running in about two minutes. The seed gives it five users and six jobs spread over four states. Two quotes and two maintenance plans come with them. The app source is MIT. The platform is a hosted service, not open source. For comparison, the hosted demo is at fieldops.supero.live.Six jobs is enough to press every button once. A schema file for your own trade starts at https://www.supero.dev.
On this page