2026-08-02 14:38:12 +00:00
# Cases
Routes in `backend/cases/urls.py` . CRUD and comments/attachments live in `backend/cases/views.py` ;
CSV import in `backend/cases/import_views.py` / `backend/cases/services/csv_import.py` ; approvals in
`backend/cases/approval_views.py` and `backend/cases/approvals.py` ; the knowledge base in
`backend/cases/solution_views.py` . Object-level authorization for the case itself is centralized in
`backend/cases/access.py` ; for knowledge-base articles, `backend/cases/kb_access.py` . See
[Conventions ](conventions.md ) for pagination, filtering and response-shape rules assumed rather than
repeated here, and [Errors ](errors.md ) for the 404-vs-403 principle referenced below.
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
Cases are also the largest module in this codebase: Kanban pipelines, merge/unmerge, parent/child
2026-08-02 14:38:12 +00:00
trees, time tracking, escalation, routing, inbound email and analytics all live under
`/api/cases/...` too. This page covers only the endpoints this documentation task scopes: list,
create, detail, comments/attachments, approvals, the knowledge base, and CSV import.
## A case's read, write and delete rules differ on purpose
Before anything else: **do not collapse a case's access rules into one check.** `cases/access.py`
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
states three explicit, different rules, and its own module docstring explains why, before this
2026-08-02 14:38:12 +00:00
module existed the three verbs had drifted into three different answers by accident, and a watcher's
ticket showed up in their list but answered `403` when they opened it:
```
read admin · creator · assignee · watcher
write admin · creator · assignee
delete admin · creator
```
(`cases/access.py:20-22`.) This is the same "read wide, write narrow" principle
[Architecture: Permissions and roles ](../architecture/permissions-and-roles.md#read-wide-write-narrow )
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
documents in general. That page is the place to read the reasoning; this page just applies it.
2026-08-02 14:38:12 +00:00
Every endpoint under [Retrieve, update, delete ](#retrieve-update-delete ) and
[Comments and attachments ](#comments-and-attachments ) calls one of
`assert_case_read_access` /`assert_case_write_access`/`assert_case_delete_access`
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
(`cases/access.py:90-113`), and the admin check itself is the two-spellings-of-admin form:
`profile.role == "ADMIN" or bool(getattr(profile, "is_admin", False))` (`cases/access.py:38-40`).
2026-09-26 18:03:20 +00:00
That recurs throughout this codebase. The [Approvals ](#approvals ) endpoints use `cases.access` too,
with one deliberate widening for the inbox; see that section.
2026-08-02 14:38:12 +00:00
## List cases
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`GET /api/cases/` (`CaseListView.get`, `cases/views.py:310-312` ) returns one paginated list, ordered
`-created_at, -id` (`case_list_queryset`, `:188-193` ): a comment on the queryset explains the tiebreak exists because `-id`
2026-08-02 14:38:12 +00:00
alone is a random UUID and was, in practice, no ordering at all. Soft-deleted cases
(`is_active=False`) are excluded by default; an org admin can pass `?include_deleted=true` to see them
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
(`:194-198`). Merged duplicates (`merged_into` set, or `status="Duplicate"` ) are excluded by default
too; `?show_merged=true` includes them (`:199-202`). A non-admin caller sees only cases where they are
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
creator, assignee, or watcher, the same `visible_cases_qs` the detail view's read check uses
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
(`:203-209`), so list and detail agree by construction.
2026-08-02 14:38:12 +00:00
```json
{
"cases_count": 42,
"offset": 10,
"cases": [ { "...": "CaseSerializer" } ],
"status": [["New", "New"], ["Assigned", "Assigned"], ["Pending", "Pending"], ["Closed", "Closed"], ["Rejected", "Rejected"], ["Duplicate", "Duplicate"]],
"priority": [["Low", "Low"], ["Normal", "Normal"], ["High", "High"], ["Urgent", "Urgent"]],
"type_of_case": [["Question", "Question"], ["Incident", "Incident"], ["Problem", "Problem"]],
"open_count": 12,
"urgent_count": 2,
"awaiting_first_reply": 5,
"accounts_list": [ { "...": "AccountSerializer" } ],
"contacts_list": [ { "...": "ContactSerializer" } ],
"users": [{"id": "...", "user__email": "..."}]
}
```
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
(`cases/views.py:217-288`.) `open_count` , `urgent_count` and `awaiting_first_reply` are counted over
2026-08-02 14:38:12 +00:00
the whole filtered queryset, not the page. `awaiting_first_reply` counts open cases
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
(`status` in `New` /`Assigned`/`Pending`) with no `first_response_at` yet. It is not the same thing as
2026-08-02 14:38:12 +00:00
an SLA breach, which depends on the org's business calendar and is computed per-row rather than in
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
this aggregate. `accounts_list` /`contacts_list` feed the create form's pickers, org-wide for an admin,
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
but narrowed for a non-admin by the accounts and contacts read rules (`visible_accounts_qs`,
`visible_contacts_qs` , `:224-227` ), the same rules the save path accepts; either way they can be
heavy, and `?slim=true` omits both (`:279-281`).
2026-08-02 14:38:12 +00:00
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
Filters read directly from `request.query_params` (`apply_case_list_filters`, `cases/views.py:97-177` ,
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
shared with `GET /api/cases/watching/` ): `name` (contains), `status` (repeatable. A list applies
2026-08-02 14:38:12 +00:00
`status__in` , a single value applies exact match), `priority` (exact), `account` (exact id),
`case_type` (exact), `assigned_to` (repeatable id list), `tags` (id list), `search` (`name` or
`description` , contains), `created_at__gte` /`created_at__lte` (date range), `sla_breached=true`
(a wall-clock approximation of the SLA badge, Postgres-only raw SQL), `cf_<key>` (custom field equals),
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
and `ordering` : whitelisted to `created_at` , `-created_at` , `priority` , `-priority` , `id` , `-id` ,
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`name` , `-name` (`:83-94,172-175`); anything else is silently ignored rather than erroring.
2026-08-02 14:38:12 +00:00
## Create a case
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`POST /api/cases/` (`CaseListView.post`, `cases/views.py:331-420` ) accepts `multipart/form-data` (for
2026-08-02 14:38:12 +00:00
an optional `case_attachment` file) or JSON, validated by `CaseCreateSerializer`
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
(`cases/serializer.py:284-458`; see [Fields ](#fields )). On success (`200`):
2026-08-02 14:38:12 +00:00
```json
{
"error": false,
"message": "Case Created Successfully",
"id": "< uuid > ",
"cases_obj": { "...": "CaseSerializer" }
}
```
A validation failure returns `400` with `{"error": true, "errors": {...}}` . Two validators worth
knowing:
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
- **`account`, if given, must belong to the caller's org**: `validate_account` rejects a
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
cross-tenant id with `"No such account."` (`cases/serializer.py:304-330`); the comment on it notes
2026-08-02 14:38:12 +00:00
this closes both a cross-tenant *write* and a cross-tenant *read* , since the create response nests
the account back through `CaseSerializer` → `AccountSerializer` .
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
- **`name` must be unique per org, case-insensitive** (`validate_name`, `:399-413` ).
2026-08-02 14:38:12 +00:00
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
`contacts` , `teams` , `assigned_to` and `tags` are **not** part of `CaseCreateSerializer` . The view
2026-08-02 14:38:12 +00:00
reads each from the request body after the serializer succeeds, resolved against
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`org=request.profile.org` (`cases/views.py:351-389`). Unlike [Leads ](leads.md#fields ), which documents a real
2026-08-02 14:38:12 +00:00
per-field, per-verb inconsistency in how these four are *parsed* , cases parses all four identically on
every verb: each is `json.loads` 'd when it arrives as a string (which happens whenever the same
request also uploads `case_attachment` as multipart) before the id list is extracted. `case_attachment`
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
itself is read straight off `request.FILES` (`cases/views.py:391-396`): on `POST` only; see
2026-08-02 14:38:12 +00:00
[Retrieve, update, delete ](#retrieve-update-delete ) for why `PATCH` can't set it at all, and for how
*writing* these four fields (not just parsing them) differs sharply across verbs.
## Retrieve, update, delete
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`GET /api/cases/{id}/` (`CaseDetailView.get`, `cases/views.py:579-747` ) looks the case up through the
read rule first (`get_case_or_404`, `:584` : a malformed UUID, a case in another org and a same-org
case the caller may not open all answer the same `404` , never `500` or `403` , matching
[Errors ](errors.md#not-found-versus-forbidden )). If the
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
case has been merged into another one, the response is a redirect hint instead of the case itself:
`{"redirect_to": "<uuid>", "merged_into": "<uuid>", "source_case_id": "<uuid>", "source_case_name": "..."}` ,
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
unless the caller passes `?show_merged=true` (`:589-601`). The redirect answers only after the read
check, so `source_case_name` never reaches a caller who could not open the duplicate; it used to
answer first and disclosed the name to any org member holding the id. The response nests
2026-08-02 14:38:12 +00:00
the record under `cases_obj` , alongside `attachments` , `comments` (public only), `internal_notes` ,
`contacts` , `solutions` , `activities` (last 20), `email_messages` (last 50, inbound-email threads),
`merged_from_cases` , `custom_field_definitions` , `status` , `priority` , `type_of_case` ,
2026-09-26 18:03:20 +00:00
`comment_permission` , `can_merge` , `approval_rule` and `users_mention` . `approval_rule` is
`{"id", "name"}` of the rule that gates closing this case (`find_matching_rule(case, "pre_close")`,
the rule a `request-approval/` with no `rule_id` binds to), or `null` when none does; clients offer
"Request approval" only when it is set. `comment_permission` is computed with the same
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`has_case_write_access` the comment-post endpoint enforces (`:612`), so the button a client shows and
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
the answer the server gives agree by construction, the comment on this line notes that used to not be
2026-08-02 14:38:12 +00:00
true (`comment_permission` was creator-or-admin while the write endpoint below also allowed assignees).
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`PUT /api/cases/{id}/` (`cases/views.py:452-536`) and `PATCH /api/cases/{id}/` (`:842-860`) both call
2026-08-02 14:38:12 +00:00
`assert_case_write_access` before touching anything. ** `account` cannot be changed by either verb.**
`CaseCreateSerializer.__init__` sets `self.fields["account"].read_only = True` whenever `self.instance`
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
is set (`cases/serializer.py:293-295`) (true for both update calls, never for create), so on `PUT` /
2026-08-02 14:38:12 +00:00
`PATCH` an `account` in the body is silently dropped before validation ever runs; `validate_account`
never executes and no error is returned. `PUT` is a non-partial serializer instantiation, so it still
requires `name` /`status`/`priority` the same as `POST` does; `PATCH` passes `partial=True`
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
(in `update_case` ), so none of the three are required there. A `PATCH` may touch just one field. From
django-crm 1.13.0 the `PATCH` write is `update_case` in `cases/updates.py` , which a macro's actions
([Macros](macros.md#apply)) and the bulk edit also call, so all three run the same validation, the
same org and active filters on assignees and tags, and the same email to anyone newly assigned.
Closing a case is validated as a *transition* , not just a target value. `CaseCreateSerializer.validate()`
(`cases/serializer.py:332-397`) judges only a move into `"Closed"` from any other status, so an
already-closed case can still be edited. Two things happen on that move:
- **The close is dated by the server.** A close that sends no `closed_on` (absent or `null` ) is dated
today in the org's timezone (`Org.timezone`, which the middleware activates for the request), by
`closing_date` in `cases/approvals.py` . A `closed_on` the client sends always wins, and a malformed
one is a `400` against `closed_on` with nothing written. Clients should not compute "today"
themselves: from django-crm 1.13.0 neither the web app nor the phone sends a date for a plain close,
and an org stored under a legacy zone name such as `US/Eastern` is dated like any other. Leaving
`"Closed"` clears `closed_on` (and `resolved_at` ), so a reopened case that is closed again is dated
afresh rather than keeping the old date.
2026-09-27 06:13:51 +00:00
- **A Closed case always has a date.** From django-crm 1.13.0 this holds for every write whose
resulting status is `"Closed"` , not only the move into it. An absent or `null` `closed_on` on a case
that is already Closed keeps the stored date (so `PATCH {"closed_on": null}` is a no-op there rather
than leaving it undated), and only when there is no stored date is it dated today in the org's
timezone. The same rule runs on `PUT` , `PATCH` , bulk update, macro apply, the board move and
close-with-children, and the `Case` pre-save signal applies it to writers that skip the API
serializer (CSV import rows with `status` `Closed` and no `closed_on` , vertical-pack sample
tickets).
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
- **The approval gate runs.** When an active `pre_close` `ApprovalRule` matches the case's
priority/case_type/team (the incoming values, so a request cannot re-target the case out of the
rule and close it at once), an `Approval` row in state `approved` for that case and rule is
required, or the answer is `400` with
`{"errors": {"status": ["An approval is required before this case can be closed (rule: <name>)."]}}`
and nothing is written.
The same dating rule applies on every path that closes a ticket: `POST` (a case created as
`"Closed"` ), `PUT` , `PATCH` , the board move (`PATCH /api/cases/{id}/move/`), the bulk edit
(`POST /api/cases/bulk/update/`), a macro's actions, and `close-with-children` . The approval gate runs
on all of them except `POST` , since an approval can only be recorded against a case that already
exists; the bulk edit reports a gated ticket as `approval_required` and carries on with the rest.
The gate exists because `Case.clean()` (`cases/models.py:193-253`)
states the rules but nothing on the save path calls `full_clean()` (`Case` defines no `save()` of its
own; it inherits `BaseModel.save()` ), so without the serializer-level check a matching rule could be
armed and a `PATCH {"status": "Closed"}` would still return `200` and record zero approvals. `PUT`
and `PATCH` answer success with the identical literal string `{"error": false, "message": "Case
Updated Successfully"}`.
**Parent links.** `Case.clean()` (`cases/models.py:193-253`) states four rules about `parent` : a case
cannot be its own parent, linking cannot create a cycle, the tree is capped at
`Case.PARENT_MAX_DEPTH = 3` levels (`:191`), and nothing is linked to or from a merged (`Duplicate`)
case. Since `Case.clean()` never runs on the API path, all four are enforced by
`check_parent_link` in `cases/parent_guards.py` , which both `CaseCreateSerializer.validate()` (when
the request carries `parent` ) and the link endpoint call. The depth check counts the subtree the case
brings with it. `validate_parent()` (`cases/serializer.py:415-440`) additionally refuses a parent in
another org or one the caller may not open, with the same message as an unknown id.
`DELETE /api/cases/{id}/` (`cases/views.py:552-559`) calls `assert_case_delete_access` , admin or creator only, no
2026-08-02 14:38:12 +00:00
assignee exception (see [above ](#a-cases-read-write-and-delete-rules-differ-on-purpose )).
## Comments and attachments
Adding a comment or an attachment is the same `POST /api/cases/{id}/` route the detail endpoint uses,
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
just with a body (`CaseDetailView.post`, `cases/views.py:765-825` ), gated by
`assert_case_write_access` (`:771`). The same rule `comment_permission` on `GET` reports. Send
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
`comment` (text, and optionally `is_internal` , a truthy string or boolean) and/or `case_attachment`
2026-08-02 14:38:12 +00:00
(multipart file), either or both. A comment created with `is_internal=true` is an internal note, not
visible to a customer-facing surface; the response splits both back out as `comments` (public) and
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`internal_notes` (`:817-822`), and both are returned to any caller with read access; `is_internal` is
2026-08-02 14:38:12 +00:00
a display split, not an access-control split on this endpoint.
Editing or deleting an *existing* comment goes through `PUT` /`PATCH`/`DELETE /api/cases/comment/{id}/`
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
(`CaseCommentView`, `cases/views.py:862-994` ). Restricted to an org admin (`is_org_admin`: the
`ADMIN` role, and a superuser counts), or the comment's own author
(`request.profile == obj.commented_by`, `:900` , `:946` , `:981` ).
`Comment.commented_by` is a `Profile` foreign key (`common/models.py:414-416`), so this comparison is
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
correct, unlike some `created_by` comparisons elsewhere in this codebase; see
2026-08-02 14:38:12 +00:00
[Architecture: Permissions and roles ](../architecture/permissions-and-roles.md#object-level-checks ).
2026-08-15 18:29:44 +00:00
`object_id` , `org` , `content_type` , `commented_by` and `commented_by_contact` are all
`read_only_fields` on `CommentSerializer` (`common/serializer.py:298-304`). Which record a comment
hangs off, which org owns it, and who wrote it are the server's to decide, and leaving the first two
writable had two consequences that are worth recording because both are now closed:
- A comment's own author could `PATCH` `object_id` and `org` to repoint their comment at any record
in the org by id, including a case the access rules would refuse them, or restamp it into another
org. `Comment.clean()` compares the new `org` against the new target's `org` , so a *matching*
cross-org pair passed that check and saved. Only the RLS policy stopped it, and RLS is the safety
net rather than the contract.
- `PUT` could not edit a comment at all. `.put()` builds a non-partial serializer, which requires
every field that is not read-only, so an ordinary `{"comment": "..."}` body failed validation on
the missing `object_id` /`org` and answered `400` . Four PUT handlers shared that defect.
A customer's reply written through the [customer portal ](customer-portal.md ) arrives in `comments`
like any other public comment, with two differences: `commented_by` is `null` , because a customer
has no `Profile` , and `commented_by_contact` names them instead. That null is the same signal an
inbound email reply carries, and it is what `_evaluate_reopen` and the first-response SLA stamp both
test to tell a customer's message from a colleague's.
2026-08-02 14:38:12 +00:00
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`DELETE /api/cases/attachment/{id}/` (`CaseAttachmentView.delete`, `cases/views.py:1013-1055` ) finds
the attachment only on a ticket the caller may open in their org (`get_on_visible_record_or_404`,
`:1036-1038` ), so an attachment on a hidden ticket or on another module's record answers the same
`404` as a missing id, and its ownership check compares `request.profile.user_id` to
`self.object.created_by_id` , both `User` ids, correctly typed (`:1040-1043`). The view's own docstring documents two defects that were live in this exact endpoint
2026-08-02 14:38:12 +00:00
before the fix (unscoped lookup; a `Profile` -to-`User` comparison that made the endpoint silently
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
admin-only). Both are fixed here today. Whether the equivalent endpoint in another app still has
2026-08-02 14:38:12 +00:00
either defect is that app's own question; verify against that app's current source rather than this
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
docstring, which itself goes stale. See
2026-08-02 14:38:12 +00:00
[Architecture: Permissions and roles ](../architecture/permissions-and-roles.md#object-level-checks )
for the current, cross-app answer.
## Approvals
Two kinds of endpoint: admin-configured rules, and per-case requests/decisions against them
(`cases/approval_views.py`). A rule (`ApprovalRule`, `cases/approvals.py:47-116` ) matches a case on
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
`trigger_event` (only `"pre_close"` exists today), and optionally `priority` , `case_type` and `team` .
The most-specific active match wins ties by most recent (`find_matching_rule`, `:119-136` ).
2026-08-02 14:38:12 +00:00
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
- `GET /api/cases/approval-rules/` (`ApprovalRuleListCreateView.get`, `approval_views.py:87-103` ).
Any org member; each rule row carries a `pending_count` computed from the `Approval` log.
- `POST /api/cases/approval-rules/` (`:105-133`), admin only. The approver list and match-team are
2026-08-02 14:38:12 +00:00
each validated to belong to the caller's org before save (`:117-129`).
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
- `GET/PUT/DELETE /api/cases/approval-rules/{id}/` (`ApprovalRuleDetailView`, `:136-194` ); `GET` is
2026-08-02 14:38:12 +00:00
open to any member; `PUT` /`DELETE` are admin only. Deleting a rule with request history soft-disables
it (`is_active=False`) instead of a hard delete (`:183-192`), since `Approval.rule` is
`on_delete=PROTECT` .
2026-09-26 18:03:20 +00:00
- `POST /api/cases/{id}/request-approval/` (`CaseRequestApprovalView.post`). A case the caller may
not read answers `404` (`get_case_or_404`, the same body as a missing id), and filing needs the
case's write rule (`assert_case_write_access`, the rule `comment_permission` reports), so a reader
who may not reply is refused with `403` . The request binds to an explicit `rule_id` (which must be
active and match the case) or, when omitted, the `find_matching_rule` result, which is what the
detail's `approval_rule` names; no matching rule is a `400` . A second request against the same
case+rule while one is `pending` is refused with `409` , not a duplicate row. The `201` response is
`ApprovalSerializer(approval).data` .
- `GET /api/cases/approvals/` (`ApprovalInboxView.get`), the inbox. A row is listed when the caller
is an org admin, may read the case, is in the rule's approver pool, or filed the request
(`_visible_approvals`): an approver routinely has no other stake in the case, and deciding it is the
point of the queue. `?state=` filters (default `pending` ; `all` drops the filter), `?case=<id>`
scopes to one case (the ticket page's panel on both clients), and `?mine=true` restricts to rows the
caller can currently act on, which deliberately excludes the caller's own requests, "mine to
decide" rather than "mine to have filed".
Approve, reject and cancel find the approval through the same visibility rule as the inbox. One the
caller cannot see answers `404` with the body a missing id gets, so these endpoints cannot confirm
that a hidden approval exists; the rules below apply only to approvals the caller can see.
2026-08-02 14:38:12 +00:00
**Approving and rejecting both enforce that the requester cannot be the approver, with no admin
exception.** `ApprovalApproveView.post` (`:354-407`) and `ApprovalRejectView.post` (`:410-475`) both
check, in order: the approval is still `pending` (else `400` ); the caller is in the rule's approver
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
pool via `can_be_acted_on_by` (else `403` ); and, separately,
2026-08-02 14:38:12 +00:00
`approval.requested_by_id == request.profile.id` (else `403` , "You cannot approve/reject your own
request; another approver must decide it.", `:382-390` and `:443-451` ). The comment on both is explicit
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
that this holds even for "an admin who defaults into every rule's pool", being an approver and being
2026-08-02 14:38:12 +00:00
the requester are mutually exclusive for a single decision, regardless of role.
`Approval.can_be_acted_on_by` (`cases/approvals.py:188-196`) itself is: explicitly listed in
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
`rule.approvers` , **or** `profile.role == rule.approver_role` , note this second clause checks only
2026-08-02 14:38:12 +00:00
`role` , not the `is_organization_admin` flag `is_org_admin` elsewhere in this codebase also treats as
admin, so a profile that is only an admin via that flag is not automatically an approver unless
explicitly added to `rule.approvers` .
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`ApprovalSerializer.can_act` and `.is_own_request` (`cases/serializer.py:1359-1384`) mirror the approve
2026-08-02 14:38:12 +00:00
endpoint's checks exactly, so a client rendering the inbox from the list response gets the same answer
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
the action endpoints would give. Both need `context={"request": request}` to resolve; without it they
2026-08-02 14:38:12 +00:00
default to `False` , which the comment on the serializer notes is the safe default rather than a bug.
`POST /api/cases/approvals/{id}/cancel/` (`ApprovalCancelView.post`, `:478-518` ) is a **different**
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
rule from approve/reject: only the original requester or an admin may cancel (`:498-505`). There is no
2026-08-02 14:38:12 +00:00
"not the requester" restriction here, because cancelling your own request is the ordinary case.
## Solutions
The knowledge base (`cases/solution_views.py`, `cases/kb_access.py` ). Read access is org-wide by
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
design. Every member may read every article, "a knowledge base whose articles are hidden from the
agents answering the tickets is not a knowledge base" (`cases/kb_access.py` module docstring), but
2026-08-02 14:38:12 +00:00
write and release are two different, narrower rules:
```
write author · admin title, body, and moving draft ↔ reviewed
release admin status → approved, and publish / unpublish
delete author · admin
```
`release` is deliberately narrower than `write` : the review workflow (`draft → reviewed → approved`,
plus a separate `is_published` flag) only means something if the person who approves an article is not
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
its own author. `assert_solution_release_access` takes no article argument at all. Being the author is
2026-08-16 01:59:38 +00:00
the one thing that must not grant it (`cases/kb_access.py:76-86`).
2026-08-02 14:38:12 +00:00
2026-08-16 01:59:38 +00:00
`GET /api/cases/solutions/` (`SolutionListView.get`, `cases/solution_views.py:120-180` ) is the one
2026-08-02 14:38:12 +00:00
endpoint in this API that calls DRF's `get_paginated_response()` and returns its standard
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
`count` /`next`/`previous`/`results` envelope, [Conventions ](conventions.md#pagination ) names this
2026-08-02 14:38:12 +00:00
exact endpoint as the sole example. It adds one extra top-level key, `totals`
(`count`/`published`/`draft`/`reviewed`/`approved_unpublished`), computed over the *whole* knowledge
base rather than the current filter, so the four status cards stay meaningful under a `?status=`
2026-08-16 01:59:38 +00:00
filter (`:165-177`). Filters: `?status=` , `?is_published=` (accepts `true` /`1`/`yes`/`on`, not just the
literal string `"true"` ), `?search=` (title or description, contains), and `?tags=` (comma-separated
tag ids, matching any of them, `distinct()` so an article carrying two of them is not returned twice).
2026-08-02 14:38:12 +00:00
2026-08-16 01:59:38 +00:00
`POST /api/cases/solutions/` (`:186-208`) is open to any member for an ordinary draft, but is gated by
2026-08-02 14:38:12 +00:00
`assert_solution_release_access` the moment the payload would create an already-`approved` or
2026-08-16 01:59:38 +00:00
already-`is_published` article in one request (`_wants_release`, `:32-50` ): without this, an author
2026-08-02 14:38:12 +00:00
could write and publish an article in a single `POST` , bypassing the review workflow entirely.
2026-08-16 01:59:38 +00:00
`GET/PUT/PATCH/DELETE /api/cases/solutions/{id}/` (`SolutionDetailView`, `:210-278` ): `GET` is open to
2026-08-02 14:38:12 +00:00
any member; `PUT` /`PATCH` require `assert_solution_write_access` (author or admin) plus, again,
`assert_solution_release_access` if the request would move the article to `approved` or flip
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
`is_published` ; `DELETE` requires the same write rule (not a separate, narrower one. Deleting your own
2026-08-02 14:38:12 +00:00
draft is ordinary tidying).
2026-08-16 01:59:38 +00:00
**Tags.** Articles carry the same org-scoped `Tags` as leads, deals and tickets. They are read on
the list and detail payloads as `tags` and written by passing `tags` (a list of tag ids) to `POST`
or `PATCH` . The write is handled in the view rather than on the serializer, so the org filter is
unavoidable: ids are resolved against `Tags.objects.filter(org=…, is_active=True)` , and an id
belonging to another org is not found rather than attached.
Absent means unchanged, and only an explicit `"tags": []` clears them. This differs from the case
endpoints on purpose, where the tag set is cleared and rebuilt whenever the key is handled, so a
`PATCH` that never mentions tags drops them.
Tag names are **agent-facing only** . They drive `related` on the portal article endpoint but never
appear in a portal payload, because the vocabulary is shared with deals and reads like "At Risk"
and "VIP". See [Customer portal ](customer-portal.md#help-articles ).
**Publishing reaches customers.** An article that is both `approved` and `is_published` is readable
by any signed-in portal contact in the org and is suggested to them while they file a request, as
well as feeding the agent suggester. Unpublishing withdraws both.
2026-08-02 14:38:12 +00:00
`POST /api/cases/solutions/{id}/publish/` and `POST /api/cases/solutions/{id}/unpublish/`
2026-08-16 01:59:38 +00:00
(`SolutionPublishView`/`SolutionUnpublishView`, `:281-336` ) both require
2026-08-02 14:38:12 +00:00
`assert_solution_release_access` . Publishing additionally requires `status == "approved"` (`400`
otherwise); the comment on the unpublish view is explicit that pulling a bad answer down is the *same*
switch as giving it to customers and therefore gated the same way, even though the urgency argument
runs the other direction.
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
Reading which solutions are linked to a case is not a separate endpoint. The linked set is returned
2026-08-02 14:38:12 +00:00
as part of `GET /api/cases/{id}/` (`solutions` key, [above ](#retrieve-update-delete )). Linking is
`POST /api/cases/{id}/solutions/` and unlinking is `DELETE /api/cases/{id}/solutions/{solution_id}/`
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
(`CaseSolutionLinkView`, `cases/views.py:1058-1134` ), gated by `assert_case_write_access` on the
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
*case*: the comment on `.post` notes this closes a read-around: before this check, a member refused a
2026-08-02 14:38:12 +00:00
case with `403` could still link an article to it and then read the case's name, description, account
and contacts back out through that article's own `linked_cases` . The read side of the same gap is
closed in `cases/solution_serializers.py` 's `SolutionDetailSerializer.get_linked_cases` , which filters
the cases it returns through the same `visible_cases_qs` the case list and detail views use, rather
than returning every case the article happens to be linked to.
## CSV import
2026-10-20 16:18:14 +00:00
Two endpoints, gated to org admins or members with `has_sales_access` (`can_mass_import` in
`common/permissions.py` ). Anyone else gets `403` .
2026-08-02 14:38:12 +00:00
`POST /api/cases/import/preview/` (`CaseImportPreviewView`, `import_views.py:56-88` ) reads a
`multipart/form-data` upload in a field named `file` (`.csv` extension required). The 5 MB cap is
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
checked against `upload.size` , Django's reported size for the uploaded file, available before
`.read()` is called, **not** the bytes actually read, and the check is skipped entirely when
2026-08-02 14:38:12 +00:00
`upload.size` is falsy (`if upload.size and upload.size > MAX_UPLOAD_BYTES`, `import_views.py:48-51` ).
It then validates every row without writing anything. Row numbers are 1-based over *data* rows, not
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
file lines. The header itself is never counted, so the first row of data is `"row": 1`
2026-08-02 14:38:12 +00:00
(`enumerate(data_rows, start=1)` over `rows[1:]` , `services/csv_import.py:216-217` ):
```json
{
"header_error": null,
"valid": [
{
"row": 1, "name": "Cannot log in", "status": "New", "priority": "High",
"description": "", "case_type": "Incident", "closed_on": null,
"account_id": "< uuid or null > ", "contact_ids": [], "assigned_ids": [],
"team_ids": [], "tag_names": []
}
],
"errors": [{"row": 2, "field": "status", "message": "Status must be one of: New, Assigned, Pending, Closed, Rejected, Duplicate"}],
"summary": {"total": 2, "valid": 1, "invalid": 1}
}
```
`POST /api/cases/import/commit/` (`CaseImportCommitView`, `:91-125` ) re-validates the same file and
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
writes every valid row inside one transaction, **if any row fails validation, nothing is written**
2026-08-02 14:38:12 +00:00
(`services/csv_import.py` `commit_rows` , "Don't write anything if any row failed; users must fix the
file first"). On success (`200`): `{"error": false, "created": 12, "ids": ["<uuid>", "..."]}` .
Required headers: `name` , `status` , `priority` . Recognized optional headers: `description` ,
`case_type` , `account_name` , `contact_emails` , `assigned_emails` , `team_names` , `tags` , `closed_on`
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
(`REQUIRED_HEADERS`/`OPTIONAL_HEADERS`, `services/csv_import.py:36-46` ), an unknown header, or a
2026-08-02 14:38:12 +00:00
missing required one, fails the whole file with `header_error` before any row is checked.
`contact_emails` , `assigned_emails` and `team_names` accept `;` -separated multiple values per cell and
must resolve to an existing contact/active member/team in the caller's org, or the row errors
(`:396-438`). `status` /`priority`/`case_type` are matched case-insensitively against the same choice
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
sets [Fields ](#fields ) documents for the API proper. A case name must be unique per org, checked
2026-08-02 14:38:12 +00:00
against both existing cases and other rows earlier in the same file (`:338-355`). The file is capped
at 5,000 data rows (`MAX_ROWS`, `:49` ).
## Fields
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`CaseCreateSerializer.Meta.fields` (`cases/serializer.py:442-458`) is what `POST /api/cases/` ,
2026-08-02 14:38:12 +00:00
`PUT /api/cases/{id}/` and `PATCH /api/cases/{id}/` accept. "Required" below means required on
`POST` and on `PUT` (which is non-partial); `PATCH` passes `partial=True` , so nothing is required
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
there: see [Retrieve, update, delete ](#retrieve-update-delete ).
2026-08-02 14:38:12 +00:00
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `name` | string, max 64 | **required** (POST/PUT) | Unique per org, case-insensitive |
| `status` | one of `STATUS_CHOICE` | **required** (POST/PUT) | `New` , `Assigned` , `Pending` , `Closed` , `Rejected` , `Duplicate` |
| `priority` | one of `PRIORITY_CHOICE` | **required** (POST/PUT) | `Low` , `Normal` , `High` , `Urgent` |
| `case_type` | one of `CASE_TYPE` | optional | `Question` , `Incident` , `Problem` |
2026-09-27 06:13:51 +00:00
| `closed_on` | date | optional | A Closed case always has one: a sent date wins, an absent or `null` one keeps the stored date, else today in the org's timezone. See [Retrieve, update, delete ](#retrieve-update-delete ) |
2026-08-02 14:38:12 +00:00
| `description` | text | optional | |
| `is_active` | boolean | optional | Defaults `true` ; soft-delete flag, hidden from `GET /api/cases/` by default |
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
| `account` | uuid | optional on create; **write-once** | Must belong to the caller's org; silently `read_only` on `PUT` /`PATCH`. See [Retrieve, update, delete ](#retrieve-update-delete ) |
2026-08-02 14:38:12 +00:00
| `custom_fields` | object | optional | Validated against the org's `CustomFieldDefinition` rows |
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
| `parent` | uuid | optional | Same-org and readable by the caller; no self-parent, no cycle, at most 3 levels, nothing merged on either side. See [above ](#retrieve-update-delete ) |
2026-08-02 14:38:12 +00:00
| `is_problem` | boolean | optional | Defaults `false` ; marks an ITIL "problem" (umbrella) ticket |
Refactor comments for clarity and consistency across multiple screens and services
- Updated comments in LeadsListScreen, MoreScreen, TaskDetailScreen, TaskFormScreen, TasksListScreen, TicketAnalyticsScreen, TicketDetailScreen, TicketsListScreen, ApiService, AuthService, CrashReporting, DealCard, TicketCard, MultiSelectSheet, KanbanColumn, StageStepper, TicketApprovalPanel, TicketPropertiesCard, and TicketTimePanel to improve readability and maintain a consistent style.
- Adjusted punctuation and phrasing for better flow and understanding.
2026-08-03 04:06:48 +00:00
| `org` |. | **read-only** | Server-derived from `request.profile.org` ; listed in `Meta.fields` but not writable |
2026-08-02 14:38:12 +00:00
Not part of the serializer, but accepted in the same request body and resolved by the view (each a
list of ids, org-scoped): `contacts` , `teams` , `assigned_to` , `tags` . Parsing is identical on every
verb (see [Create a case ](#create-a-case )), but *writing* is not, and the difference is a real
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
data-loss trap: `POST` only ever adds. `PUT` replaces all four M2Ms **unconditionally** (`.clear()` on
teams, assignees and tags, and `replace_visible_contacts` for contacts),
before checking whether the request even mentioned them (`views.py:496,500,506,514`), so a `PUT`
2026-08-02 14:38:12 +00:00
that omits `assigned_to` from the body unassigns every assignee on the case, not just leaves them
unchanged. `PATCH` clears a given M2M only when its key is present in the body at all
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
(`if "assigned_to" in data:` in `update_case` , `cases/updates.py` , and identically for the other
three). Omitting a key on
2026-08-02 14:38:12 +00:00
`PATCH` genuinely leaves it untouched. `case_attachment` (a multipart file) is accepted on `POST` and
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`PUT` (`views.py:391,521`) but **not on `PATCH`** ; `CaseDetailView.patch` never reads
2026-08-02 14:38:12 +00:00
`request.FILES` at all, so a multipart `PATCH` carrying `case_attachment` silently drops the file with
no error.
`GET /api/cases/{id}/` and `GET /api/cases/` additionally return, but never accept as input: `id` ,
`created_by` , `created_at` , `escalation_count` , `last_escalation_fired_at` , the SLA fields
(`sla_first_response_hours`, `sla_resolution_hours` , `first_response_at` , `resolved_at` ,
`sla_paused_at` , `first_response_sla_deadline` , `resolution_sla_deadline` ,
`is_sla_first_response_breached` , `is_sla_resolution_breached` ), `parent_summary` , `child_count` , and
Add comprehensive tests for ticket closing, calendar feed, deal board, macros, session caches, and web form models
- Implement tests for closing tickets via menu and status picker, ensuring correct API interactions and error handling.
- Create tests for calendar feed provider, verifying throttling behavior and success responses.
- Add tests for deal board provider, covering reading and moving deals, including edge cases for card movement and filters.
- Enhance macro tests to validate action parsing and application to tickets, including error handling.
- Introduce session cache tests to ensure proper cleanup on sign-out and validate session-scoped providers.
- Extend web form model tests to cover lead rotation functionality, ensuring correct serialization and defaults.
2026-09-27 00:58:09 +00:00
`time_summary` (`CaseSerializer.Meta.fields`, `cases/serializer.py:239-281` ).