feat(portal): customer ticket comments (PMS-449 phase 1) #339
No reviewers
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
psa-systems/mokosh-server!339
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/PMS-449-portal-ticket-comments"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Adds
GET/POST /api/v1/portal/tickets/{id}/notes, the missing leg of the customer comment loop. A portal contact can now follow up on an open ticket without having to email the helpdesk and have an agent re-paste the reply into the ticket; the comment lands directly on the sameticket_notestrack agents use, so the existing notifications dispatcher fans it out and the agent sees it on their normal queue.Schema: a new
ticket_notes.created_by_contact_id UUID NULL REFERENCES contacts(id) ON DELETE SET NULLplus a partial index on(tenant_id, created_by_contact_id) WHERE created_by_contact_id IS NOT NULL.created_by_idstays NOT NULL: portal-originated notes set it to the tenant's fallback admin/manager (mirrorscreate_portal_ticket's attribution pattern) and populatecreated_by_contact_idwith the real author. That keeps the existingmokosh_types::tickets::TicketNote.created_by_id: Uuidshape intact - making it Optional would ripple across every consumer for marginal value when the SPA can already tell "Customer:" vs "Agent:" fromnote_type='public'+ a non-nullcreated_by_contact_id.Guarantees, all pinned by
tests/portal_ticket_notes.rs:note_type='public', sointernal/resolution/time_entryagent back-channel never leaks to the customer;created_by_contact_idequal to the authenticated contact, so downstream UI / reporting can attribute the comment correctly;created_atso the agent + customer comments render as a thread.Phase 2 follow-ups, tracked under PMS-449:
created_by_contact_idonTicketNoteResponse(currently lossy in the wire shape; the SPA distinguishes fromcreated_by_name+ heuristics for now);#PMS-449
Adds `GET` / `POST /api/v1/portal/tickets/{id}/notes`, the missing leg of the customer comment loop. A portal contact can now follow up on an open ticket without having to email the helpdesk and have an agent re-paste the reply into the ticket; the comment lands directly on the same `ticket_notes` track agents use, so the existing notifications dispatcher fans it out and the agent sees it on their normal queue. Schema: a new `ticket_notes.created_by_contact_id UUID NULL REFERENCES contacts(id) ON DELETE SET NULL` plus a partial index on `(tenant_id, created_by_contact_id) WHERE created_by_contact_id IS NOT NULL`. `created_by_id` stays NOT NULL: portal-originated notes set it to the tenant's fallback admin/manager (mirrors `create_portal_ticket`'s attribution pattern) and populate `created_by_contact_id` with the real author. That keeps the existing `mokosh_types:🎟️:TicketNote.created_by_id: Uuid` shape intact - making it Optional would ripple across every consumer for marginal value when the SPA can already tell "Customer:" vs "Agent:" from `note_type='public'` + a non-null `created_by_contact_id`. Guarantees, all pinned by `tests/portal_ticket_notes.rs`: - the portal feed filters server-side on `note_type='public'`, so `internal` / `resolution` / `time_entry` agent back-channel never leaks to the customer; - a contact cannot read OR write a ticket in another company within the same tenant - both surfaces 404 (not 403), so the response never confirms the existence of another company's ticket; - the DB row carries `created_by_contact_id` equal to the authenticated contact, so downstream UI / reporting can attribute the comment correctly; - list ordering is ascending by `created_at` so the agent + customer comments render as a thread. Phase 2 follow-ups, tracked under PMS-449: - expose `created_by_contact_id` on `TicketNoteResponse` (currently lossy in the wire shape; the SPA distinguishes from `created_by_name` + heuristics for now); - portal attachment upload (POST a file alongside the comment); - the agent UI's "show me all comments from this customer" feed, which the new index lights up cheaply. #PMS-449