louispaulb
|
f4a6d07a8b
|
feat(ops): reason → skill → skill-aware availability module
Bridge reason → required skill → availability so the occupancy denominator
reflects the skill a job needs ("70 h installation" vs "150 h all techs").
Hub:
- lib/skill-resolver.js (NEW, SOURCE UNIQUE): shared techHasSkill(s) predicate,
deptToSkill (moved here, re-exported from roster.js — no cycle),
DEPARTMENT_SKILLS bridge, resolveSkills({text,department,jobType,useAI})
(chip → rule → Gemini fallback, reusing classifyEmail pattern).
- roster.js: capacityByDay(start,days,skills) filters denominator to qualified
techs (+ guards used/due). New POST /roster/resolve-skills, /roster/capacity?skill=.
Backward-compatible (no skill = prior behavior).
- dispatch.js: techOccupancy/suggestSlots reuse the shared predicate.
SPA:
- config/departments.js: skills[]+dur per department + skillsForDepartment();
added Réparation reason.
- components/shared/OccupancyBands.vue (NEW): vertical-strip grid extracted from
SuggestSlotsDialog (now reuses it).
- components/shared/AvailabilityByReason.vue (NEW): reason chips + dictate→AI →
resolved skill → skill-filtered bands + adjusted-denominator summary.
Mounted in ClientDetailPage, IssueDetail, ConversationPanel.
- api/roster.js: getCapacity(start,days,skill) + resolveSkills().
- Planif + Dashboard capacity bands pass skill to /roster/capacity.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
2026-07-08 18:33:30 -04:00 |
|