PCS Job Tracking
Field-service scheduling & job history
Next.jsPrismaPostgresNextAuthDockerDigitalOcean
- Status
- In production
- Stack
- Next.js, Prisma, Postgres, NextAuth, Chakra UI, Docker
- Code
- Private repo — happy to walk through it
Problem
A service crew works out of a truck. The schedule lives on a clipboard, the history of a site lives in whoever visited it last, and the proof that the work happened lives in a text message someone sent from the parking lot.
That holds together until it doesn’t. Recurring visits get missed because nobody remembered they were due. Supplies run out at a location before anyone notices they were low. A customer asks what was done in March and the honest answer is that nobody wrote it down.
Solution
One system that models the work the way the crew actually talks about it — customers, then the locations they own, then the jobs that happen at those locations.
- Recurring job series that generate the visits that are due, instead of depending on someone’s memory
- Delivery jobs and service jobs kept as separate types, because dropping off supplies and performing a service call need to capture different things
- Chemical par levels tracked per location, with back-order status when something can’t be supplied
- Severity on emergency jobs, so a genuine emergency sorts above routine work rather than joining the queue
- Photos attached to the job record, so the site condition is documented where the job history lives
- Role-based accounts with an invite flow, and regions so work dispatches by area
Worth noting
The deployment is the part I’m happiest with. A push to
main triggers a GitHub Actions workflow that SSHes into a
single DigitalOcean droplet, resets to origin/main, and
rebuilds the Docker stack in place: Postgres, a one-shot container that
runs the Prisma migrations and exits, then the app. The database lives in
a named volume, so it survives every deploy.
One droplet, one compose file, no orchestration layer to babysit. For a crew this size that is the right amount of infrastructure, and it means a fix reaches the field about ninety seconds after I commit it.