How to Calculate Weekly Deputy Overtime and Alert Managers
Build a scheduled Spojit workflow that totals each employee's Deputy timesheet hours for the past week, flags anyone over an overtime threshold, and posts a single summary alert to your managers in Slack.
What This Integration Does
Workforce managers rarely notice overtime until it lands on the payroll bill. This workflow runs on its own every week, pulls approved timesheets from Deputy, groups them by employee, sums the hours, and compares each total against a threshold you set (for example 38 hours). Anyone above the line is collected into a short list, and that list is posted to a Slack channel so the right people can act before the pay run closes. No one has to open Deputy, export a report, or do the maths by hand.
The run model is fully unattended. A Schedule trigger fires on a cron expression (for example every Monday morning), so the workflow always reports on the week that just ended. It reads timesheet data, computes totals in memory, and either posts an alert or finishes quietly when no one is over the threshold. It writes nothing back to Deputy, so it is safe to re-run: running it twice for the same week produces the same alert, never a duplicate timesheet or a changed record. If you want a fresh check at any time, you can press Run manually and it behaves identically.
Prerequisites
- A Deputy connection added under Connections -> Add connection, authorized for the account whose timesheets you want to read.
- A Slack connection with access to the channel where managers receive alerts.
- The exact channel ID or channel name for the destination Slack channel.
- An agreed overtime threshold in hours (for example
38) and the day-of-week your pay week ends on. - A rough idea of how Deputy stores time: timesheet records expose total minutes and the employee they belong to, which this workflow converts to hours.
Step 1: Start with a Schedule trigger
Add a Trigger node and set its type to Schedule. Enter a 5-field Unix cron expression and an IANA timezone so the run lands when you expect. To run every Monday at 7am Sydney time, use:
0 7 * * 1
Australia/Sydney
A Schedule trigger can hold more than one schedule if you operate across regions, and its output is simply { scheduledAt }. You will use that timestamp in the next step to define the week you are reporting on. To verify the workflow while you build it, you can also press Run at any time without waiting for the schedule.
Step 2: Compute last week's date range
Add a Connector node in Direct mode using the date utility connector so you have concrete start and end dates to bound the query. First call subtract to step back 7 days from {{ trigger.scheduledAt }}, then call start-of and end-of (unit week) to snap to whole-week boundaries. Format both with format into the YYYY-MM-DD shape Deputy expects, and store them as {{ weekStart }} and {{ weekEnd }}. Computing the range as a step (rather than hard-coding dates) keeps the report correct every week and across daylight-saving changes.
Step 3: Pull the week's timesheets from Deputy
Add a Connector node in Direct mode and select the Deputy connector. To return only the timesheets inside your week, use the raw-api-request tool, which lets you post a date-bounded query to Deputy's timesheet resource. Set method to POST, path to /resource/Timesheet/QUERY, and a body that filters on the start time and asks for approved entries only:
{
"search": {
"f1": { "field": "Date", "type": "ge", "data": "{{ weekStart }}" },
"f2": { "field": "Date", "type": "le", "data": "{{ weekEnd }}" }
},
"sort": { "Employee": "asc" }
}
Save the result as {{ timesheets }}. If your account is small and you do not need date filtering at the source, you can instead use the plain list-timesheets tool (it takes no inputs and returns every timesheet) and filter by date in the next step. The query approach is preferred once you have more than a few weeks of history, because it keeps the payload small.
Step 4: Sum hours per employee and find overtime
Add a Connector node in Direct mode using the code connector and the execute-javascript tool to group the timesheets by employee and total their minutes. Pass {{ timesheets }} and your threshold in, convert each record's total time to hours, sum per employee, and emit only those over the line. For example:
const rows = input.timesheets || [];
const thresholdHours = 38;
const totals = {};
for (const t of rows) {
const id = t.Employee;
const mins = t.TotalTime || 0;
totals[id] = totals[id] || { employeeId: id, name: t._DisplayName || String(id), hours: 0 };
totals[id].hours += mins / 60;
}
const overtime = Object.values(totals)
.map(e => ({ ...e, hours: Math.round(e.hours * 100) / 100 }))
.filter(e => e.hours > thresholdHours)
.sort((a, b) => b.hours - a.hours);
return { overtime, count: overtime.length };
Save the output as {{ overtime }}. If your Deputy field names differ, open the result of Step 3 in the run logs to confirm the exact keys before finalizing the field references. You can also ask Miraxa, the intelligent layer across your automation, to adjust this step ("Group {{ timesheets }} by employee and total the hours") and it will edit the node for you.
Step 5: Skip the alert when no one is over
Add a Condition node so the workflow stays quiet on calm weeks. Configure the condition to check whether {{ overtime.count }} is greater than 0. Wire the true branch to the Slack alert in the next step, and leave the false branch empty so the run simply finishes. This prevents a noisy "no overtime this week" message every Monday and keeps the channel meaningful.
Step 6: Format the message and post to Slack
On the true branch, add a Transform node to turn {{ overtime.overtime }} into a readable list, building one line per person such as {{ employee.name }}: {{ employee.hours }}h. Store the assembled text as {{ messageText }}.
Then add a Connector node in Direct mode using the Slack connector and the send-message tool. Set the channel field to your managers' channel and the text field to a short header plus the body, for example:
Weekly overtime alert ({{ weekStart }} to {{ weekEnd }})
{{ overtime.count }} employee(s) over 38 hours:
{{ messageText }}
That single post gives managers the full picture for the week in one glance. If you would rather email the same summary, you can add a Send Email node instead of (or alongside) the Slack step, since it sends from Spojit's built-in mail service with no extra connection.
Tips
- Set the threshold as a variable in the Step 4 code (or in the Schedule step) so changing your overtime rule later is a one-line edit, not a rebuild.
- If different teams have different overtime rules, add a second Condition branch or compute per-team thresholds inside the
execute-javascriptstep rather than running two separate workflows. - Use Slack's
get-channel-infoorlookup-user-by-emailtools once during setup to confirm you have the correct channel ID before scheduling the workflow. - Keep the Deputy query bounded by date (Step 3) once history grows; pulling every timesheet with
list-timesheetsand filtering later gets slower over time.
Common Pitfalls
- Timezone drift. If the cron timezone and your Deputy account timezone differ, your "week" boundaries can land on the wrong day. Match the IANA timezone in Step 1 to the region your roster operates in.
- Field-name assumptions. Deputy timesheet records may name the total-minutes and employee fields differently than the example. Always open a real run's Step 3 output in the logs and confirm keys like
TotalTimeandEmployeebefore trusting the totals. - Draft vs approved time. Unapproved or in-progress timesheets can inflate totals. Decide whether to include them and filter accordingly in the Step 3 query or the Step 4 code.
- Silent empty weeks look broken. Because the Condition node intentionally posts nothing when no one is over, confirm via the execution history that the run completed, rather than assuming a missing Slack message means a failure.
Testing
Before scheduling, press Run manually and inspect each step in the execution history. Confirm Step 2 produced the date range you expect, Step 3 returned timesheets only inside that range, and Step 4's {{ overtime }} matches a hand-count for one or two known employees. Temporarily lower the threshold (for example to 1) so the Condition branch fires and a test message reaches a private Slack channel. Once the totals and the message read correctly, restore the real threshold, point the Slack step at the managers' channel, and let the Schedule trigger take over.