# Gusto/Payroll Integration Status

**Branch:** `csdecatur`
**Last Updated:** 2026-04-07

---

## DONE (Fully Built)

| Component | Count | Details |
|-----------|-------|---------|
| **Migrations** | 12 | All run (batch 107) — positions, salary_schedules, salary_schedule_steps, employee_salary_placements, pay_calendars, pay_periods, payroll_runs, paychecks, employee_fund_allocations, payroll_journal_entries, gusto_settings, employee_details enhancements |
| **Models** | 11 | Position, SalarySchedule, SalaryScheduleStep, EmployeeSalaryPlacement, PayCalendar, PayPeriod, PayrollRun, Paycheck, EmployeeFundAllocation, PayrollJournalEntry, GustoSetting — all with real relationships, scopes, computed attributes |
| **Controllers** | 9 | PayrollController, PositionController, SalaryScheduleController, PayCalendarController, PaycheckController, EmployeeFundAllocationController, PayrollJournalEntryController, GustoSettingsController, BenefitPlanController |
| **Services** | 8 | GustoClient (OAuth + HTTP), GustoEmployeeService, GustoPayrollService, GustoBenefitsService, GustoWebhookHandler, PayrollOrchestrationService, PayrollJournalEntryService, TimesheetAggregationService |
| **Jobs** | 7 | SyncEmployeeToGusto, SyncEmployeeFromGusto, SubmitPayrollToGusto, FetchPayrollResults, GeneratePayrollJournalEntries, PostPayrollToQuickBooks, AggregateTimesheetHours |
| **Views** | 22 | Dashboard, run detail, reports, positions (index/create-edit/show), salary grid, pay calendars, paychecks, fund allocations, journal entries, gusto settings, benefits enrollment |
| **Routes** | 78 lines | All routes in `routes/payroll.php` |
| **Config** | `config/gusto.php` | OAuth credentials, environment, webhook |
| **Observer** | PayrollRunObserver | Auto-dispatches jobs on status changes |
| **Seeder** | PayrollPermissionSeeder | 12 permissions across 3 modules |
| **Menu** | 9 sub-items | Under Payroll sidebar |
| **.env** | Set | GUSTO_CLIENT_ID, GUSTO_CLIENT_SECRET |

---

## File Inventory

### Migrations (12 files)
- `database/migrations/2026_04_07_100000_create_positions_table.php`
- `database/migrations/2026_04_07_100001_create_salary_schedules_table.php`
- `database/migrations/2026_04_07_100002_create_salary_schedule_steps_table.php`
- `database/migrations/2026_04_07_100003_create_employee_salary_placements_table.php`
- `database/migrations/2026_04_07_100004_create_pay_calendars_table.php`
- `database/migrations/2026_04_07_100005_create_pay_periods_table.php`
- `database/migrations/2026_04_07_100006_create_payroll_runs_table.php`
- `database/migrations/2026_04_07_100007_create_paychecks_table.php`
- `database/migrations/2026_04_07_100008_create_employee_fund_allocations_table.php`
- `database/migrations/2026_04_07_100009_create_payroll_journal_entries_table.php`
- `database/migrations/2026_04_07_100010_create_gusto_settings_table.php`
- `database/migrations/2026_04_07_100011_add_payroll_fields_to_employee_details_table.php`

### Models (11 files)
- `app/Models/Position.php`
- `app/Models/SalarySchedule.php`
- `app/Models/SalaryScheduleStep.php`
- `app/Models/EmployeeSalaryPlacement.php`
- `app/Models/PayCalendar.php`
- `app/Models/PayPeriod.php`
- `app/Models/PayrollRun.php`
- `app/Models/Paycheck.php`
- `app/Models/EmployeeFundAllocation.php`
- `app/Models/PayrollJournalEntry.php`
- `app/Models/GustoSetting.php`
- `app/Models/EmployeeDetails.php` (enhanced with payroll relationships)

### Controllers (9 files)
- `app/Http/Controllers/PayrollController.php`
- `app/Http/Controllers/PositionController.php`
- `app/Http/Controllers/SalaryScheduleController.php`
- `app/Http/Controllers/PayCalendarController.php`
- `app/Http/Controllers/PaycheckController.php`
- `app/Http/Controllers/EmployeeFundAllocationController.php`
- `app/Http/Controllers/PayrollJournalEntryController.php`
- `app/Http/Controllers/GustoSettingsController.php`
- `app/Http/Controllers/BenefitPlanController.php`

### Services (8 files)
- `app/Services/Gusto/GustoClient.php` — OAuth HTTP client with token refresh, retry on 429
- `app/Services/Gusto/GustoEmployeeService.php` — Create/update/sync employees to Gusto
- `app/Services/Gusto/GustoPayrollService.php` — Submit payroll, fetch results, store paychecks
- `app/Services/Gusto/GustoBenefitsService.php` — List company benefits, employee enrollments
- `app/Services/Gusto/GustoWebhookHandler.php` — Signature verification, event handling
- `app/Services/PayrollOrchestrationService.php` — Full payroll run lifecycle
- `app/Services/PayrollJournalEntryService.php` — GL journal entries split by fund allocations
- `app/Services/TimesheetAggregationService.php` — Aggregates attendance + timelogs + leave hours

### Jobs (7 files)
- `app/Jobs/SyncEmployeeToGusto.php`
- `app/Jobs/SyncEmployeeFromGusto.php`
- `app/Jobs/SubmitPayrollToGusto.php`
- `app/Jobs/FetchPayrollResults.php`
- `app/Jobs/GeneratePayrollJournalEntries.php`
- `app/Jobs/PostPayrollToQuickBooks.php`
- `app/Jobs/AggregateTimesheetHours.php`

### Views (22 files)
- `resources/views/payroll/index.blade.php` — Dashboard
- `resources/views/payroll/show.blade.php` — Run detail
- `resources/views/payroll/reports.blade.php` — Reports
- `resources/views/payroll/demo.blade.php` — Demo (static)
- `resources/views/positions/index.blade.php` — Position list
- `resources/views/positions/create-edit.blade.php` — Position form
- `resources/views/positions/show.blade.php` — Position detail
- `resources/views/salary-schedules/index.blade.php` — Schedule list
- `resources/views/salary-schedules/create-edit.blade.php` — Schedule form
- `resources/views/salary-schedules/grid.blade.php` — Step/lane grid editor
- `resources/views/payroll/pay-calendars/index.blade.php` — Calendar list
- `resources/views/payroll/pay-calendars/create-edit.blade.php` — Calendar form
- `resources/views/payroll/pay-calendars/show.blade.php` — Calendar detail with periods
- `resources/views/payroll/paychecks/index.blade.php` — Paycheck list
- `resources/views/payroll/paychecks/show.blade.php` — Pay stub detail
- `resources/views/payroll/paychecks/my-stubs.blade.php` — Employee self-service
- `resources/views/payroll/paychecks/pdf.blade.php` — Print-friendly pay stub
- `resources/views/payroll/fund-allocations/index.blade.php` — Fund allocation list + form
- `resources/views/payroll/fund-allocations/show.blade.php` — Allocation detail
- `resources/views/payroll/journal-entries/index.blade.php` — GL entries list
- `resources/views/payroll/journal-entries/show.blade.php` — Entry detail
- `resources/views/payroll/gusto-settings/index.blade.php` — OAuth connect/disconnect
- `resources/views/benefits/enrollment.blade.php` — Benefits enrollment placeholder

### Other
- `config/gusto.php` — Gusto API configuration
- `app/Observers/PayrollRunObserver.php` — Status change event handler
- `database/seeders/PayrollPermissionSeeder.php` — Permission seeder
- `resources/views/sections/menus/payroll.blade.php` — Sidebar menu
- `routes/payroll.php` — All payroll routes

---

## What the System Can Do End-to-End

1. Create positions with fund codes and salary schedule assignments
2. Build salary schedule step/lane grids (e.g., certified teacher salary table)
3. Set up pay calendars and auto-generate pay periods
4. Initiate payroll runs → aggregate timesheet hours → submit for review → approve → submit to Gusto
5. Receive Gusto webhook when payroll is processed → store paychecks with full tax breakdowns
6. Generate GL journal entries split by employee fund allocations (debit salary expense, credit tax payables, etc.)
7. Employee self-service: view own pay stubs
8. OAuth connect/disconnect with Gusto

---

## Remaining / Gaps

| Item | Priority | Details |
|------|----------|---------|
| **QuickBooks API posting** | Medium | `PostPayrollToQuickBooks` job marks entries as posted but doesn't actually call QB API — needs to hook into existing QB integration |
| **PDF pay stub generation** | Low | `downloadPdf()` returns a printable view, not an actual PDF. Needs a PDF library (e.g. DomPDF/Snappy) |
| **Benefits management** | Low | `BenefitPlanController::index()` still serves the demo view. Real benefit sync from Gusto works but no local CRUD |
| **GUSTO_WEBHOOK_SECRET** | Medium | Not set in `.env` — needed before going to production with webhooks |
| **GUSTO_REDIRECT_URI** | Low | Not explicitly set, using default. Should be set for production |
| **Gusto sandbox testing** | High | Need to actually test OAuth flow with Gusto developer sandbox account |
| **Seed demo data** | Medium | Tables are empty — no sample positions, salary schedules, pay calendars exist yet for the CSD demo |
| **Permission gating** | Low | Permission checks removed from PayrollController (was causing errors). Other controllers have no permission checks either — fine for demo, needs adding for production |
