2.6 KiB
2.6 KiB
Organizational ticketing rollout
The organizational layer is additive: legacy tickets with no unit keep their existing visibility rules, while every ticket assigned to a unit is isolated by unit membership and database-managed Django permissions.
Admin setup order
- Create organizational units under Staff → Organizational units.
- Select the Django permissions inherited by every member of each unit.
- Assign staff through unit memberships and choose one primary unit.
- Classify external contacts as customer, supplier, carrier, or other.
- Create unit-owned contact groups when useful. Group membership is optional, including for customers who registered themselves or existed before this rollout.
- Create optional unit-specific SMS templates. A template with no unit is the global
fallback. Supported variables include
recipient_name,unit_name,company_name,magic_link,ticket_number, andsubject. - Grant
tickets.dispatch_group_ticketsto units allowed to create bulk dispatches. Grantaccounts.view_all_magic_linksonly to senior auditors who may inspect every unit; other Admin users see only links from their active unit memberships.
Useful unit permissions include tickets.view_ticket, tickets.claim_ticket,
tickets.transfer_ticket, tickets.share_ticket, tickets.change_ticket,
tickets.change_ticket_priority, tickets.delete_ticket, and
messaging.add_message.
Security invariants
- Each group recipient gets a separate
Ticket, notification job, and magic link. - External users can access only tickets whose
customer_idis their own user ID. - Unit filtering happens in both list querysets and object-level policy checks.
- The staff contact directory and editor include every customer account, regardless of group membership or ticket ownership. Existing customer accounts without a profile receive one in a one-time data migration; the editor also repairs any later account missing its profile. Staff can edit contact details; each edit records the actor and changed values. Group membership editing remains limited to groups in units the staff member may manage. Contact access does not grant access to tickets in another unit.
- Every valid magic-link opening appends an immutable access-log row and atomically increments its view counter.
- Raw magic-link tokens are never stored; only SHA-256 digests are persisted.
- Group dispatch runs inside a database transaction, preventing partially-created batches when validation or ticket creation fails.
Apply schema changes with:
.\.venv\Scripts\python.exe manage.py migrate