Files
company_site/company_site/financial/urls.py
T
westfarn 7dd5ec3be1
Unit Tests / test (push) Successful in 16s
Add Employee vs Client user type and filter time/reports by employee (#14) (#15)
## Summary

- Adds `UserProfile` model with mutually exclusive **Employee** / **Client** types
- Replaces auto-Employee signal with auto-Client profile on user creation
- Data migration: users with time log entries → Employee; others → Client (orphan Employee rows removed)
- Admin UI at `/financial/manage_users` to set any user's type; profile page shows current type
- **Employees** can log time; **Clients** get read-only access to reports and time logs
- Time logs, reports, and dashboard filter to employees only
- 14 new tests covering signals, type switching, access control, and filtering

## Design decisions (from issue Q&A)

1. Client login = read-only financial access (reports + time logs, no edit/log time)
2. Employee and Client are strictly mutually exclusive
3. Admins (superusers) can change type via Manage Users
4. Bulk migration applied for existing users

## Test plan

- [x] `python manage.py test financial.tests` (14 tests pass)
- [x] `python manage.py test public.tests` (21 tests pass)
- [ ] Run migration on staging: `python manage.py migrate`
- [ ] Verify admin can set user types at `/financial/manage_users`
- [ ] Verify employee can log time at `/financial/timekeeping`
- [ ] Verify client sees reports/time logs read-only, cannot log time
- [ ] Verify employee filter dropdown excludes clients

Closes #14

Reviewed-on: #15
2026-07-05 12:54:50 +00:00

24 lines
1.4 KiB
Python

from django.urls import path
from . import views
urlpatterns = [
path("", views.financial_home, name="financial_home"),
path("dashboard", views.index, name="financial_index"),
path("timekeeping", views.timekeeping, name="Timekeeping"),
path("time_logs", views.time_logs, name="time_logs"),
path("time_logs/<int:log_id>/edit", views.edit_time_log, name="edit_time_log"),
path("time_logs/<int:log_id>/delete", views.delete_time_log, name="delete_time_log"),
path("timeapproval", views.timeapproval, name="Timeapproval"),
path("contracts", views.contracts, name="contracts"),
path("<str:contract_slug>/contract_detail", views.contract_detail, name="contract_detail"),
path("new_contract", views.new_contract, name="new_contract"),
path("new_employee", views.new_employee, name="new_employee"),
path("<str:contract_slug>/new_charge_number", views.new_charge_number, name="new_charge_number"),
path("<str:charge_number_slug>/update_charge_number", views.update_charge_number, name="update_charge_number"),
#path("contracts/<int:contract_id>/", views.contract_detail, name="contract"),
path("procurements", views.procurement, name="procurements"),
path("profile", views.profile, name="profile"),
path("manage_users", views.manage_users, name="manage_users"),
path("client_reports", views.client_reports, name="client_reports"),
]