Commit graph

6 commits

Author SHA1 Message Date
d9b01a5981 Add lead time to recurring templates — generate before actually due
task_templates.lead_days (default 0): scheduler now spawns the task
when (next_due - lead_days) <= today instead of next_due <= today, but
due_date on the created task is still the real next_due — so overdue
and priority handling are unaffected, the task just becomes visible
earlier for prep/booking. Small jobs (AC filter clean) can stay at 0;
bigger ones needing advance notice (septic tank empty-out, contractor
booking) can set 2-3 days or 30 days as needed.

- db.js: lead_days INT NOT NULL DEFAULT 0 (inline for fresh installs,
  ALTER for existing).
- scheduler.js: WHERE (next_due - lead_days) <= $1 — next_due itself
  and the fixed/floating rollover logic are untouched by this.
- templates.js: accept + validate lead_days (>= 0) on create/update.
- Recurring.tsx: lead time field in the template form with contextual
  hint text, plus a small 'generates Nd early' note on list rows that
  have one set.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 12:20:50 +00:00
763e7be6ca Add delete action for recurring templates
There was no way to remove a template once created (e.g. test/scratch
recurring tasks) - only edit/pause via active. DELETE /api/templates/:id
detaches any tasks already spawned from it (template_id cleared) rather
than blocking on the FK or cascading, so existing task history survives
as ordinary one-off tasks while the recurring schedule itself is removed.
Delete button in the edit modal footer, only shown when editing an
existing template - not on new/duplicate.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 11:58:52 +00:00
690de73172 Fix duplicate template due date being silently cleared
duplicate() blanked next_due along with location/asset, but title/
description/notes/etc. all stayed filled in — so a duplicated
template looked fully populated while due date was actually empty,
and the combined 'Title and first due date are required' error didn't
say which field was missing. Adding another room to an existing
schedule normally wants the same due date as the rest of the group
anyway, so carry it over from the source template instead of clearing
it; only location/asset genuinely need re-picking. Error messages now
name the specific missing field.
2026-08-26 11:53:54 +00:00
ee23cb1b16 Add template groups: bulk multi-location creation + duplicate action
For recurring jobs that repeat identically across many locations (e.g.
clean AC filter in every room), one task_templates row per location is
still required — schedule/completion tracking is per-location, which
matters especially for floating mode — but creating and organising
that many rows by hand didn't scale.

- New template_groups table (id, unique name) + task_templates.group_id.
  POST /api/template-groups upserts by name so picking an existing
  group from the UI never creates a duplicate folder.
- Recurring template form: optional group name (datalist-autocompleted
  from existing groups) plus a "create for multiple locations" toggle
  that reveals a checkbox list of locations; saving loops one
  createTemplate() call per selected location, all sharing the
  resolved group_id.
- Duplicate button on each template row pre-fills the New Template
  form from that row (location/asset/next-due cleared for repicking),
  landing in the same group automatically — the lightweight path for
  adding one more room later without the bulk picker.
- Recurring.tsx list now groups rows under a collapsible folder header
  per group_name; ungrouped templates render as flat rows as before.
2026-08-26 10:33:19 +00:00
a661a06a8f Add fixed/floating schedule mode to recurring task templates
Fixed mode keeps the existing behavior: next_due always advances from
the previous scheduled date, regardless of when a task is actually
completed. Floating mode instead computes the next occurrence from
the completion date of the current task, so early/late completion
shifts the whole schedule.

- task_templates gains schedule_mode ('fixed'|'floating', default
  'fixed') and pending_task_id, tracking the open task spawned from a
  floating template so the hourly sweep doesn't respawn duplicates
  before it's resolved.
- scheduler.js: floating templates set pending_task_id instead of
  advancing next_due at spawn time.
- tasks.js /resolve: floating templates recompute next_due from
  completed_at once the task is marked fixed (not temporary_fix,
  since that isn't really done yet); pending_task_id is always
  cleared on fixed resolution so a stale flag can't wedge the
  template if the mode changed mid-cycle.
- addInterval/isoDate pulled out of scheduler.js into a shared
  lib/recurrence.js used by both the scheduler and the resolve route.
- Recurring.tsx: schedule mode toggle in the template form, and the
  list shows "awaiting completion" instead of a stale next-due date
  for floating templates with an open occurrence.
2026-08-26 10:14:03 +00:00
6ca395097e Maintenance log book app — initial scaffold
Multi-department fault log: NewBook-synced room locations + manual
locations with categories, six-state task flow (submitted/in progress/
hold-parts/hold-later/temporary fix/fixed), photos per stage, priorities
with unusable flag and per-task NewBook out-of-order push, costs on
resolve, comment/audit thread, recurring task templates with
note-to-template carryover, asset register, contractor register with
document attachments, staff/contractor allocation, occupancy-aware
summary filter, searchable history with CSV export, email notifications.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 21:28:57 +00:00