How Mechanic Clock In/Out and Management Works
Source: mechanics_controller.rb
- The generic labor product is resolved by searching for product codes in this order: LAB, then LABOUR, then LABOR; if none exist, a new LAB product is auto-created
- A mechanic cannot be clocked in to the same invoice they are already clocked in to
- Mobile and desktop have different strictness: mobile blocks clock-in if the mechanic is clocked in ANYWHERE (any invoice); desktop only checks the current invoice
- Clock out sets the end_time to the current UTC time with in_progress set to false — there is no option to specify a custom clock-out time
- Hours worked are calculated as the epoch difference between start and end divided by 3600, rounded to 2 decimal places
- Making a mechanic inactive automatically unassigns all their future event times and destroys their mobile user account
- Mechanic deletion follows a tiered approach: hard delete if no labor_items and no xero_id exist; otherwise the mechanic is set to inactive
- Mechanic colors are assigned sequentially from a predefined palette
Support scenarios
- "A mechanic can't clock in on the mobile app but can on desktop" → Mobile is stricter: it blocks clock-in if the mechanic is clocked in to ANY job. Desktop only checks the current job. The mechanic needs to clock out of their other job on mobile first.
- "I can't set a custom clock-out time" → The system always uses the current UTC time for clock-out. There is no way to backdate or manually set a clock-out time through the standard interface.
- "I made a mechanic inactive and their future bookings disappeared" → Setting a mechanic to inactive automatically unassigns all their future event times. Those bookings still exist but need a new mechanic assigned.
- "I can't delete a mechanic" → If the mechanic has labor items or a Xero ID, they cannot be hard deleted. The system will set them to inactive instead. This preserves historical records.
- "There's no LAB product and mechanics can't clock in" → The system auto-creates a LAB product if none of LAB/LABOUR/LABOR exist. If this failed, manually create a product with code LAB.