17 domain design docs covering architecture, accounts, inventory, rentals, lessons, repairs, POS, payments, batch repairs, delivery, billing, accounting, deployment, licensing, installer, and backend tech architecture. Plus implementation roadmap (doc 18) and personnel management (doc 19). Key design decisions documented: - company/location model (multi-tenant + multi-location) - member entity (renamed from student to support multiple adults) - Stripe vs Global Payments billing ownership differences - User/location/terminal licensing model - Valkey 8 instead of Redis
10 KiB
Forte — Music Store Management Platform
Domain Design: Personnel Management
Version 1.0 | Draft
1. Overview
The Personnel domain manages employee records, time clock, time-off requests, and work schedules. This is foundational infrastructure — every other domain references employees (POS operators, technicians, instructors, drivers). This domain provides the employee entity and workforce management tools.
Personnel management is a licensed module (MOD-PERSONNEL). Without it, the platform still tracks basic user accounts for login and role-based access. The module adds time clock, scheduling, time-off, and labor reporting.
2. Core Concepts
2.1 Employee
An employee is a person who works for the company. They have a user account for system login and an employee record for HR/scheduling purposes. An employee can work at any location within the company — they are not locked to a single location.
- Linked to a
useraccount for authentication - Has a home location (primary work site) but can clock in at any location
- Roles: admin, manager, staff, technician, instructor
- An employee can hold multiple roles (e.g. a technician who also teaches lessons)
- Pay rate tracked for labor cost calculations (repair labor, lesson instructor pay)
- Employment status: active, inactive, terminated
2.2 Time Clock
Employees clock in and out to track hours worked. Clock entries record which location the employee is working at, supporting multi-location operations.
- Clock in/out via desktop app or web UI
- Location recorded at clock-in — employee may work at different locations on different days
- Break tracking — paid and unpaid breaks
- Overtime calculated based on configurable rules (weekly threshold, daily threshold)
- Clock entries editable by managers with audit trail
2.3 Schedules
Work schedules define when employees are expected to work. Schedules are per-location and per-week.
- Weekly recurring schedules with override capability for specific dates
- Shift-based — start time, end time, location, role
- Instructors have dual scheduling: lesson schedule (from Lessons domain) + store shift schedule
- Schedule conflicts detected — cannot schedule same employee at two locations simultaneously
- Published schedules visible to employees (future: via portal or mobile)
2.4 Time Off
Employees can request time off. Managers approve or deny. Approved time off blocks scheduling for those dates.
- Request types: vacation, sick, personal, unpaid
- Accrual tracking — configurable accrual rates per type
- Manager approval workflow with notification
- Approved time off appears on schedule as blocked
- Annual carryover rules configurable per type
3. Database Schema
3.1 employee
Column | Type | Notes id | uuid PK | company_id | uuid FK | Tenant scoping user_id | uuid FK | Linked login account — nullable for employees not yet set up with system access first_name | varchar | last_name | varchar | email | varchar | Work email phone | varchar | home_location_id | uuid FK | Primary work location roles | text[] | Array of roles: admin, manager, staff, technician, instructor hire_date | date | termination_date | date | Nullable — set when terminated employment_status | enum | active, inactive, terminated pay_type | enum | hourly, salary, commission, per_lesson pay_rate | numeric(10,2) | Hourly rate or salary amount overtime_eligible | boolean | notes | text | Internal HR notes legacy_id | varchar | AIM employee ID created_at | timestamptz | updated_at | timestamptz |
3.2 time_clock_entry
Column | Type | Notes id | uuid PK | company_id | uuid FK | employee_id | uuid FK | location_id | uuid FK | Where the employee clocked in clock_in | timestamptz | clock_out | timestamptz | Nullable — null while clocked in break_minutes | integer | Total break time in minutes break_type | enum | paid, unpaid, none total_hours | numeric(6,2) | Computed: clock_out - clock_in - unpaid breaks is_overtime | boolean | Flagged based on overtime rules overtime_hours | numeric(6,2) | Hours beyond overtime threshold edited | boolean | True if entry was modified after clock-out edited_by | uuid FK | Manager who edited edit_reason | text | Required if edited created_at | timestamptz |
3.3 schedule
Column | Type | Notes id | uuid PK | company_id | uuid FK | employee_id | uuid FK | location_id | uuid FK | schedule_date | date | Specific date for this shift start_time | time | end_time | time | role | varchar | What role for this shift (staff, technician, instructor) is_recurring | boolean | True if generated from a recurring template recurring_template_id | uuid FK | Nullable — links to the template that generated this notes | text | created_by | uuid FK | Manager who created created_at | timestamptz | updated_at | timestamptz |
3.4 schedule_recurring_template
Weekly recurring schedule patterns. The system generates concrete schedule entries from these templates.
Column | Type | Notes id | uuid PK | company_id | uuid FK | employee_id | uuid FK | location_id | uuid FK | day_of_week | integer | 0=Sunday through 6=Saturday start_time | time | end_time | time | role | varchar | effective_from | date | When this pattern starts effective_until | date | Nullable — open-ended if null is_active | boolean | created_at | timestamptz |
3.5 time_off_request
Column | Type | Notes id | uuid PK | company_id | uuid FK | employee_id | uuid FK | request_type | enum | vacation, sick, personal, unpaid start_date | date | end_date | date | total_days | numeric(4,1) | Supports half days status | enum | pending, approved, denied, cancelled reason | text | Employee's reason manager_notes | text | Manager's response reviewed_by | uuid FK | Manager who reviewed reviewed_at | timestamptz | created_at | timestamptz |
3.6 time_off_balance
Tracks accrued and used time off per employee per type per year.
Column | Type | Notes id | uuid PK | company_id | uuid FK | employee_id | uuid FK | year | integer | Calendar year request_type | enum | vacation, sick, personal accrued | numeric(5,1) | Days accrued this year used | numeric(5,1) | Days used this year carried_over | numeric(5,1) | Days carried from previous year available | numeric(5,1) | Computed: accrued + carried_over - used created_at | timestamptz | updated_at | timestamptz |
4. Overtime Rules
Overtime configuration is per-company, stored in company settings.
Setting | Default | Notes weekly_overtime_threshold | 40 | Hours per week before overtime kicks in daily_overtime_threshold | null | Nullable — some states require daily overtime (e.g. California = 8 hrs) overtime_multiplier | 1.5 | Pay multiplier for overtime hours double_time_threshold | null | Nullable — hours per day before double time (e.g. California = 12 hrs) double_time_multiplier | 2.0 | Pay multiplier for double time
Overtime is calculated at clock-out based on the current week's total hours. If daily thresholds are configured, both daily and weekly are evaluated and the higher overtime amount applies.
5. Key Workflows
5.1 Clock In / Out
- Employee opens desktop app or web UI
- Selects "Clock In" — system records current time, location, and employee
- On clock out, system records end time, calculates total hours and break time
- If total weekly hours exceed overtime threshold, overtime flagged
- Manager can edit clock entries with required reason — logged in audit trail
5.2 Schedule Creation
- Manager creates recurring schedule templates for each employee
- System generates concrete schedule entries for upcoming weeks
- Manager can override specific dates (e.g. swap shifts, add extra coverage)
- Instructor lesson schedule slots (from Lessons domain) display alongside store shifts for visibility
- Schedule conflicts flagged — same employee at two locations at the same time
5.3 Time Off Request
- Employee submits request specifying dates, type, and reason
- Manager receives notification
- Manager approves or denies with optional notes
- Approved time off deducts from employee's time_off_balance
- Schedule entries for approved dates are flagged or removed
- If employee is an instructor, lesson sessions for those dates can be auto-cancelled or flagged for makeup
5.4 Pay Period Reporting
- Manager selects date range for pay period
- System generates report: employee, regular hours, overtime hours, total hours
- Export to CSV for payroll processing (platform does not run payroll — exports data for external payroll service)
- Includes time-off hours taken by type
6. Integration with Other Domains
Domain | Integration Lessons | Instructors are employees. Lesson schedule_slot.instructor_id references employee. Time off auto-flags affected lesson sessions. Repairs | Technicians are employees. repair_ticket.assigned_technician_id references employee. Labor cost calculated from employee pay_rate. Sales/POS | transaction.processed_by references employee. Drawer sessions linked to employee. Delivery | delivery_event.driver_employee_id references employee. Accounting | Labor costs from repair tickets use employee.pay_rate for margin calculation. Payroll export supports journal entry generation for labor expense.
7. Business Rules
- Employee must have unique email within company
- Clock entries cannot overlap — cannot be clocked in at two locations simultaneously
- Clock-out required before new clock-in (system auto-clocks out at midnight if forgotten — flagged for manager review)
- Time-off requests for past dates require manager approval
- Schedule recurring templates auto-generate entries 4 weeks ahead (configurable)
- Terminated employees retain all historical records (time clock, schedules, time off) — never deleted
- Employee pay_rate changes are effective immediately — historical clock entries retain the rate at time of clock-out
- Per-lesson instructors: pay tracked per lesson session attended, not via time clock
8. Reporting
Report | Description Hours summary | Total regular + overtime hours per employee per period Overtime report | Employees who hit overtime threshold — broken out by daily vs weekly Time-off balances | Current accrued, used, and available days per employee per type Schedule coverage | Shifts per location per day — identifies understaffed days Clock edit audit | All manager edits to time clock entries with reasons Labor cost by department | Hours * pay_rate grouped by role (technician, instructor, staff) Attendance | Scheduled vs actual clock-in times — identifies chronic lateness Payroll export | CSV export formatted for common payroll services (QuickBooks Payroll, Gusto, ADP)