DocsAutomation
Notifications, email and scheduled jobs
The twelve email templates, in-app notifications, staff messaging, and the five nightly sweeps that keep expiry, retention and stalled work visible.
Three separate channels carry information out of the pipeline: templated email to applicants, in-app notifications to staff, and staff-to-staff chat. Behind them a background worker runs five scheduled sweeps that keep expiry, retention and stalled work from going unnoticed.
Email templates#
Twelve templates are seeded, referenced by code from automation rules and from write paths. Each is editable per organization.
| Code | Sent when |
|---|---|
APPLICATION_RECEIVED | An application is created. The default acknowledgement. |
PORTAL_INVITE | A portal account is offered to an applicant or principal contact. |
SCREENING_INVITE | An applicant is asked in for agency screening. |
INTERVIEW_SCHEDULED | An interview is booked. |
OFFER_EXTENDED | A job offer is made. |
MEDICAL_SCHEDULE | On entering the Medical stage, alongside the Liaison Officer task. |
DOCUMENT_REQUEST | A document is being chased. |
DOCUMENT_EXPIRING | A verified document is 30 days from expiry. |
PDOS_SCHEDULE | PDOS attendance is being arranged. |
DEPARTURE_DETAILS | Three days before expected departure. |
BALANCE_REMINDER | An outstanding worker balance is being chased. |
REJECTED_POLITE | An application is declined. |
Sending is queued rather than synchronous: the write path enqueues, and the worker delivers. Each attempt produces an EmailMessage row with a status.
EmailStatus | Meaning |
|---|---|
QUEUED | Accepted, not yet sent. |
SENT | Handed to the provider. Writes email.sent to the audit trail. |
FAILED | Delivery failed. |
BOUNCED | The provider reported a bounce. |
SUPPRESSED | Not sent because the address is on the unsubscribe list. |
Unsubscribes are recorded and honoured. Marketing campaigns are a separate object — EmailCampaign with CampaignRecipient rows and a status of DRAFT, SENDING, SENT or CANCELLED — and dispatching one writes campaign.sent.
In-app notifications#
Notifications are per-user, with a type, a title, an optional body and a link to the thing they concern. The API returns the 50 most recent plus an unread count, and marking one read is a separate call.
The NOTIFY automation action is what creates most of them, optionally scoped to a role so an entire queue is told at once. See Automation rules.
Staff messaging#
Chat is real-time over Socket.IO, sharing the same HTTP server as the API. A client obtains a one-shot handshake ticket and connects with it, rather than sending the session cookie over the socket.
ConversationType | Between |
|---|---|
STAFF_DM | Two staff members. This is what the Messages screen creates. |
STAFF_GROUP | Several staff members. |
APPLICANT_THREAD | Staff and an applicant, through the applicant portal. |
EMPLOYER_THREAD | Staff and a principal contact, through the employer portal. |
Message bodies are between 1 and 4000 characters. Attachments become FileObject records and are subject to the same access rules as documents — a participant in the conversation may open them, and nobody else. See Documents.
The five scheduled sweeps#
A separate worker process consumes the job queue and owns every scheduled sweep. It is deliberately not the web server, so a long résumé parse or a two-thousand-recipient campaign cannot block HTTP requests. Repeatable jobs are keyed, so a redeploy does not duplicate them.
| Time | Job | What it does |
|---|---|---|
| 01:00 daily | document.expiry.scan | Flips verified documents whose expiry has passed to EXPIRED, and feeds the DOCUMENT_EXPIRING trigger for documents approaching their date. |
| 01:15 daily | joborder.expiry.scan | Moves job orders past validUntil to EXPIRED. |
| 01:30 daily | automation.cron | Evaluates the date-driven triggers: DATE_APPROACHING and CHECKLIST_OVERDUE, including the 21-day stale-application nudge. |
| 01:45 daily | retention.scan | Finds applicants past their retention date with no applications and raises a review task. Deliberately does not delete. See Data privacy. |
| 08:00 weekdays | notification.digest | Sends each active organization a morning digest of overdue tasks, linking into the task queue. |
Alongside the crons the worker handles on-demand jobs: resume.parse for résumé extraction, email.send for transactional delivery, and campaign.send for bulk marketing.
Asia/Manila. Set it wrongly and your expiry scans, your retention review and your morning digest all shift — the digest in particular stops arriving in the morning. Check it during setup. See Quickstart.Why expiry is a sweep and not a query#
The gate already refuses a document whose expiry date has passed, so in principle a nightly status change is redundant. It exists for two reasons: the status an officer sees in the documents queue should say EXPIRED rather than VERIFIED, and something has to notice the day a document crosses a warning threshold in order to fire the 30-day and 180-day rules. A sweep does both, once, at a time when nobody is working.
