1286 lines
32 KiB
Markdown
1286 lines
32 KiB
Markdown
|
|
# SAG MODULE IMPLEMENTATION PLAN
|
|||
|
|
## Professional Sub-Agent Task Breakdown
|
|||
|
|
|
|||
|
|
**Document Version:** 2.0
|
|||
|
|
**Created:** 2026-01-30
|
|||
|
|
**Module Location:** `/app/modules/sag/`
|
|||
|
|
**API Path:** `/api/v1/cases`
|
|||
|
|
**Database Prefix:** `sag_`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## EXECUTIVE SUMMARY
|
|||
|
|
|
|||
|
|
The Sag (Case) Module is the **process backbone** of BMC Hub. It implements a universal entity model where tickets, tasks, and (eventually) orders are all represented as Cases differentiated by:
|
|||
|
|
- **Relations** (directional, transitive connections between cases)
|
|||
|
|
- **Tags** (workflow state and categorization)
|
|||
|
|
- **Attached modules** (billing, hardware, etc.)
|
|||
|
|
|
|||
|
|
This plan provides a phased, task-based approach to complete the implementation with architectural constraints preserved.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1️⃣ CURRENT STATE ASSESSMENT
|
|||
|
|
|
|||
|
|
### ✅ What's Already Implemented
|
|||
|
|
|
|||
|
|
#### Database Schema (COMPLETE)
|
|||
|
|
- ✅ `sag_sager` table (cases) - `/migrations/001_init.sql`
|
|||
|
|
- Binary status: `åben` / `lukket` (constraint enforced)
|
|||
|
|
- `template_key` as nullable field (creation-time only)
|
|||
|
|
- `deleted_at` for soft-deletes
|
|||
|
|
- Proper indexes on customer_id, status, ansvarlig_bruger_id
|
|||
|
|
- Auto-update trigger for `updated_at`
|
|||
|
|
|
|||
|
|
- ✅ `sag_relationer` table (relations)
|
|||
|
|
- Directional: `kilde_sag_id` → `målsag_id`
|
|||
|
|
- `relationstype` for categorization
|
|||
|
|
- Soft-delete support
|
|||
|
|
- Constraint preventing self-relations
|
|||
|
|
|
|||
|
|
- ✅ `sag_tags` table (tags)
|
|||
|
|
- `tag_navn` for categorization
|
|||
|
|
- `state` field: `open` / `closed` (constraint enforced)
|
|||
|
|
- `closed_at` timestamp
|
|||
|
|
- Soft-delete support
|
|||
|
|
|
|||
|
|
- ✅ `sag_kontakter` table (case-contact links) - `/migrations/002_sag_contacts_relations.sql`
|
|||
|
|
- Many-to-many with roles
|
|||
|
|
|
|||
|
|
- ✅ `sag_kunder` table (case-customer links)
|
|||
|
|
- Many-to-many with roles
|
|||
|
|
|
|||
|
|
#### Backend API (MOSTLY COMPLETE)
|
|||
|
|
✅ **Cases CRUD** - `router.py` lines 1-671
|
|||
|
|
- `GET /api/v1/cases` - List with filters (status, tag, customer_id, ansvarlig)
|
|||
|
|
- `POST /api/v1/cases` - Create case
|
|||
|
|
- `GET /api/v1/cases/{id}` - Get case details
|
|||
|
|
- `PATCH /api/v1/cases/{id}` - Update case
|
|||
|
|
- `DELETE /api/v1/cases/{id}` - Soft-delete
|
|||
|
|
|
|||
|
|
✅ **Relations CRUD**
|
|||
|
|
- `GET /api/v1/cases/{id}/relations` - List relations with titles
|
|||
|
|
- `POST /api/v1/cases/{id}/relations` - Create relation
|
|||
|
|
- `DELETE /api/v1/cases/{id}/relations/{relation_id}` - Soft-delete
|
|||
|
|
|
|||
|
|
✅ **Tags CRUD**
|
|||
|
|
- `GET /api/v1/cases/{id}/tags` - List tags
|
|||
|
|
- `POST /api/v1/cases/{id}/tags` - Add tag (with state support)
|
|||
|
|
- `DELETE /api/v1/cases/{id}/tags/{tag_id}` - Soft-delete
|
|||
|
|
|
|||
|
|
✅ **Contact/Customer Links**
|
|||
|
|
- `POST /api/v1/cases/{id}/contacts` - Link contact
|
|||
|
|
- `GET /api/v1/cases/{id}/contacts` - List contacts
|
|||
|
|
- `DELETE /api/v1/cases/{id}/contacts/{contact_id}` - Remove contact
|
|||
|
|
- `POST /api/v1/cases/{id}/customers` - Link customer
|
|||
|
|
- `GET /api/v1/cases/{id}/customers` - List customers
|
|||
|
|
- `DELETE /api/v1/cases/{id}/customers/{customer_id}` - Remove customer
|
|||
|
|
|
|||
|
|
✅ **Search**
|
|||
|
|
- `GET /api/v1/search/cases` - Full-text search
|
|||
|
|
- `GET /api/v1/search/customers` - Customer search
|
|||
|
|
- `GET /api/v1/search/contacts` - Contact search
|
|||
|
|
|
|||
|
|
#### Frontend Views (MOSTLY COMPLETE)
|
|||
|
|
✅ **List View** - `frontend/views.py`
|
|||
|
|
- `/cases` and `/sag` routes (dual paths)
|
|||
|
|
- Filter by status, tag, customer_id
|
|||
|
|
- Fetches statuses and tags for filters
|
|||
|
|
|
|||
|
|
✅ **Detail View**
|
|||
|
|
- `/cases/{id}` and `/sag/{id}` routes
|
|||
|
|
- Shows case, tags, relations, customer
|
|||
|
|
- Fetches contacts and customers (partially implemented)
|
|||
|
|
|
|||
|
|
✅ **Create Form**
|
|||
|
|
- `/cases/new` and `/sag/new` routes
|
|||
|
|
- Template exists (`create.html`)
|
|||
|
|
|
|||
|
|
❌ **Edit Form** - Template exists (`edit.html`) but no backend route
|
|||
|
|
|
|||
|
|
#### Templates (COMPLETE)
|
|||
|
|
✅ All four templates exist:
|
|||
|
|
- `index.html` - Case list with Nordic Top design, filters, dark mode
|
|||
|
|
- `detail.html` - Case details with relations, tags, info sections
|
|||
|
|
- `create.html` - Create form with customer search, validation
|
|||
|
|
- `edit.html` - Edit form (needs backend route)
|
|||
|
|
|
|||
|
|
### 🔴 Architectural Violations Found
|
|||
|
|
|
|||
|
|
#### VIOLATION 1: Duplicate API Paths
|
|||
|
|
**Issue:** Router has both `/sag/*` and `/cases/*` endpoints doing identical things.
|
|||
|
|
- Lines 14-157: `/sag` prefix endpoints
|
|||
|
|
- Lines 327-671: `/cases` prefix endpoints (duplicates)
|
|||
|
|
|
|||
|
|
**Fix Required:** Remove `/sag/*` endpoints, keep only `/cases/*` (architectural standard).
|
|||
|
|
|
|||
|
|
#### VIOLATION 2: Missing Tag State Management
|
|||
|
|
**Issue:** Tag closing endpoint missing.
|
|||
|
|
- `PATCH /api/v1/cases/{id}/tags/{tag_id}` should allow closing tags (set `state='closed'`, `closed_at=NOW()`)
|
|||
|
|
- Currently only delete (soft) exists
|
|||
|
|
|
|||
|
|
**Fix Required:** Add tag state update endpoint.
|
|||
|
|
|
|||
|
|
#### VIOLATION 3: Missing Edit Route
|
|||
|
|
**Issue:** `edit.html` template exists but no backend route to serve it.
|
|||
|
|
|
|||
|
|
**Fix Required:** Add `GET /cases/{id}/edit` view route.
|
|||
|
|
|
|||
|
|
### ⚠️ What Needs Enhancement
|
|||
|
|
|
|||
|
|
1. **Tag State Workflow** - Endpoint to close tags (not delete)
|
|||
|
|
2. **Edit View Route** - Backend route for edit form
|
|||
|
|
3. **Relation Type Validation** - Should validate allowed relation types
|
|||
|
|
4. **Bulk Operations** - Close multiple tags, archive cases
|
|||
|
|
5. **Activity Log** - Track who changed what (future phase)
|
|||
|
|
6. **Order Integration** - Link cases to orders (future phase)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2️⃣ PHASE OVERVIEW
|
|||
|
|
|
|||
|
|
### Phase 1: Database Schema Validation (30 min)
|
|||
|
|
- Verify all tables match architectural constraints
|
|||
|
|
- Add any missing indexes
|
|||
|
|
- Validate soft-delete coverage
|
|||
|
|
|
|||
|
|
### Phase 2: Backend API Enhancement (2-3 hours)
|
|||
|
|
- Remove duplicate `/sag/*` endpoints
|
|||
|
|
- Add tag state management endpoint
|
|||
|
|
- Add edit view route
|
|||
|
|
- Improve error handling
|
|||
|
|
- Add relation type validation
|
|||
|
|
|
|||
|
|
### Phase 3: Frontend Enhancement (2-3 hours)
|
|||
|
|
- Wire up edit form
|
|||
|
|
- Add tag closing UI
|
|||
|
|
- Improve relation visualization
|
|||
|
|
- Add bulk operations UI
|
|||
|
|
- Enhance mobile responsiveness
|
|||
|
|
|
|||
|
|
### Phase 4: Order Integration Planning (1 hour)
|
|||
|
|
- Define order-case relation types
|
|||
|
|
- Document order creation workflow
|
|||
|
|
- Plan order table schema
|
|||
|
|
- Define API contract
|
|||
|
|
|
|||
|
|
### Phase 5: Documentation (1 hour)
|
|||
|
|
- Update module README
|
|||
|
|
- Create API documentation
|
|||
|
|
- Document relation types
|
|||
|
|
- Create workflow examples
|
|||
|
|
|
|||
|
|
### Phase 6: QA & Testing (1-2 hours)
|
|||
|
|
- Unit tests for CRUD operations
|
|||
|
|
- Integration tests for relations
|
|||
|
|
- Frontend E2E tests
|
|||
|
|
- Soft-delete verification
|
|||
|
|
- Module disable/enable test
|
|||
|
|
|
|||
|
|
**Total Estimate:** 8-12 hours
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3️⃣ SUB-AGENT TASK BREAKDOWN
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### PHASE 1: DATABASE SCHEMA VALIDATION
|
|||
|
|
|
|||
|
|
#### DB-001: Schema Compliance Audit
|
|||
|
|
**Assigned:** DB-Agent
|
|||
|
|
**Estimated Time:** 30 minutes
|
|||
|
|
**Dependencies:** None
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Audit all `sag_*` tables against architectural constraints. Verify:
|
|||
|
|
- Binary status constraint on `sag_sager`
|
|||
|
|
- Tag state constraint on `sag_tags`
|
|||
|
|
- Soft-delete columns present
|
|||
|
|
- No missing indexes
|
|||
|
|
- Trigger functions working
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- `/migrations/001_init.sql`
|
|||
|
|
- `/migrations/002_sag_contacts_relations.sql`
|
|||
|
|
- Database connection
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Validation report (pass/fail for each constraint)
|
|||
|
|
- SQL script for any missing indexes/constraints
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- All constraints match architectural rules
|
|||
|
|
- All soft-delete columns present
|
|||
|
|
- All indexes exist and performant
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### PHASE 2: BACKEND API ENHANCEMENT
|
|||
|
|
|
|||
|
|
#### BE-001: Remove Duplicate `/sag/*` Endpoints
|
|||
|
|
**Assigned:** Backend-Agent
|
|||
|
|
**Estimated Time:** 45 minutes
|
|||
|
|
**Dependencies:** None
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Remove duplicate endpoints with `/sag` prefix (lines 14-330). Keep only `/cases` prefix endpoints. Update any internal references.
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- `/app/modules/sag/backend/router.py`
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Modified `router.py` with only `/cases` endpoints
|
|||
|
|
- Updated imports if needed
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- No `/sag` prefix endpoints remain
|
|||
|
|
- All functionality preserved under `/cases`
|
|||
|
|
- No broken internal references
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### BE-002: Add Tag State Management Endpoint
|
|||
|
|
**Assigned:** Backend-Agent
|
|||
|
|
**Estimated Time:** 45 minutes
|
|||
|
|
**Dependencies:** BE-001
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Add `PATCH /api/v1/cases/{id}/tags/{tag_id}` endpoint to close tags without deleting. Should:
|
|||
|
|
- Accept `{"state": "closed"}` payload
|
|||
|
|
- Set `closed_at = NOW()`
|
|||
|
|
- NOT set `deleted_at` (tags are closed, not deleted)
|
|||
|
|
- Return updated tag
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- `/app/modules/sag/backend/router.py`
|
|||
|
|
- `sag_tags` table schema
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- New endpoint in `router.py`
|
|||
|
|
- Proper error handling
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Endpoint closes tag (state='closed', closed_at set)
|
|||
|
|
- Returns 404 if tag not found
|
|||
|
|
- Doesn't soft-delete
|
|||
|
|
- Logs action with emoji prefix
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### BE-003: Add Edit View Route
|
|||
|
|
**Assigned:** Backend-Agent
|
|||
|
|
**Estimated Time:** 30 minutes
|
|||
|
|
**Dependencies:** BE-001
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Add `GET /cases/{id}/edit` route in `frontend/views.py` to serve the edit form. Should fetch case and render `edit.html` template.
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- `/app/modules/sag/frontend/views.py`
|
|||
|
|
- `/app/modules/sag/templates/edit.html`
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- New route in `views.py`
|
|||
|
|
- Template receives case data
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Route returns edit form
|
|||
|
|
- Form pre-populated with case data
|
|||
|
|
- Returns 404 if case not found
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### BE-004: Add Relation Type Validation
|
|||
|
|
**Assigned:** Backend-Agent
|
|||
|
|
**Estimated Time:** 45 minutes
|
|||
|
|
**Dependencies:** BE-001
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Add validation for allowed relation types when creating relations. Define allowed types:
|
|||
|
|
- `derived` (spawned from)
|
|||
|
|
- `blocks` (prevents progress)
|
|||
|
|
- `executes` (performs work for)
|
|||
|
|
- `relates_to` (generic link)
|
|||
|
|
|
|||
|
|
Reject other types with 400 error.
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- `/app/modules/sag/backend/router.py` (relation creation endpoint)
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Updated `POST /api/v1/cases/{id}/relations` with validation
|
|||
|
|
- Error message listing allowed types
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Only allowed types accepted
|
|||
|
|
- 400 error with clear message for invalid types
|
|||
|
|
- Logged validation failures
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### BE-005: Improve Error Handling
|
|||
|
|
**Assigned:** Backend-Agent
|
|||
|
|
**Estimated Time:** 45 minutes
|
|||
|
|
**Dependencies:** BE-001, BE-002, BE-003, BE-004
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Standardize error responses across all endpoints:
|
|||
|
|
- Use consistent HTTPException format
|
|||
|
|
- Include helpful error messages
|
|||
|
|
- Log all errors with context
|
|||
|
|
- Return proper status codes
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- All endpoint functions in `router.py` and `views.py`
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Consistent error handling pattern
|
|||
|
|
- Improved logging
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- All errors return proper status codes
|
|||
|
|
- Error messages are user-friendly
|
|||
|
|
- All errors logged with context
|
|||
|
|
- No uncaught exceptions
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### PHASE 3: FRONTEND ENHANCEMENT
|
|||
|
|
|
|||
|
|
#### FE-001: Wire Up Edit Form Backend Connection
|
|||
|
|
**Assigned:** Frontend-Agent
|
|||
|
|
**Estimated Time:** 45 minutes
|
|||
|
|
**Dependencies:** BE-003
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Complete the edit form JavaScript to:
|
|||
|
|
- Load case data into form
|
|||
|
|
- Submit to `PATCH /api/v1/cases/{id}`
|
|||
|
|
- Handle success/error responses
|
|||
|
|
- Redirect to detail view on success
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- `/app/modules/sag/templates/edit.html`
|
|||
|
|
- Backend edit route
|
|||
|
|
- PATCH endpoint
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Functional edit form with submission
|
|||
|
|
- Success/error feedback
|
|||
|
|
- Redirect on success
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Form loads case data
|
|||
|
|
- Submission calls PATCH endpoint
|
|||
|
|
- Success redirects to `/cases/{id}`
|
|||
|
|
- Errors displayed to user
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### FE-002: Add Tag Closing UI
|
|||
|
|
**Assigned:** Frontend-Agent
|
|||
|
|
**Estimated Time:** 60 minutes
|
|||
|
|
**Dependencies:** BE-002
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Add UI to close tags (not delete) in detail view:
|
|||
|
|
- Add "Close Tag" button next to each open tag
|
|||
|
|
- Call `PATCH /api/v1/cases/{id}/tags/{tag_id}` with `state='closed'`
|
|||
|
|
- Update UI to show closed state (greyed out, strikethrough)
|
|||
|
|
- Keep closed tags visible in UI
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- `/app/modules/sag/templates/detail.html`
|
|||
|
|
- Tag closing endpoint
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Close button on each open tag
|
|||
|
|
- Visual distinction for closed tags
|
|||
|
|
- AJAX call to close endpoint
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Closed tags remain visible
|
|||
|
|
- Visual feedback on state change
|
|||
|
|
- No page reload needed
|
|||
|
|
- Error handling for failures
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### FE-003: Improve Relation Visualization
|
|||
|
|
**Assigned:** Frontend-Agent
|
|||
|
|
**Estimated Time:** 90 minutes
|
|||
|
|
**Dependencies:** None
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Enhance relation display in detail view:
|
|||
|
|
- Group relations by type (derived, blocks, executes, relates_to)
|
|||
|
|
- Show directionality clearly (this case → target vs. source → this case)
|
|||
|
|
- Add visual indicators (arrows, colors)
|
|||
|
|
- Make relation targets clickable links
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- `/app/modules/sag/templates/detail.html`
|
|||
|
|
- Relation data from backend
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Updated relation section with grouping
|
|||
|
|
- Visual indicators for direction
|
|||
|
|
- Clickable links to related cases
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Relations grouped by type
|
|||
|
|
- Direction clear (outgoing vs incoming)
|
|||
|
|
- All targets are clickable
|
|||
|
|
- Mobile-responsive
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### FE-004: Add Bulk Operations UI
|
|||
|
|
**Assigned:** Frontend-Agent
|
|||
|
|
**Estimated Time:** 90 minutes
|
|||
|
|
**Dependencies:** BE-002
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Add bulk operations to list view:
|
|||
|
|
- Checkboxes to select multiple cases
|
|||
|
|
- "Close Selected" button (set status='lukket')
|
|||
|
|
- "Archive Selected" button (soft-delete)
|
|||
|
|
- Confirmation dialogs
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- `/app/modules/sag/templates/index.html`
|
|||
|
|
- Update/delete endpoints
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Selection UI in list view
|
|||
|
|
- Bulk action buttons
|
|||
|
|
- Confirmation dialogs
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Multiple cases selectable
|
|||
|
|
- Bulk close works
|
|||
|
|
- Bulk archive works (soft-delete)
|
|||
|
|
- Confirmation required
|
|||
|
|
- Success feedback shown
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### FE-005: Enhance Mobile Responsiveness
|
|||
|
|
**Assigned:** Frontend-Agent
|
|||
|
|
**Estimated Time:** 60 minutes
|
|||
|
|
**Dependencies:** FE-001, FE-002, FE-003, FE-004
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Ensure all views work on mobile:
|
|||
|
|
- Stack filters vertically on small screens
|
|||
|
|
- Make tables scrollable or card-based
|
|||
|
|
- Touch-friendly buttons (min 44px)
|
|||
|
|
- Collapsible sections for detail view
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- All template files
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Updated CSS with media queries
|
|||
|
|
- Mobile-optimized layouts
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- All views usable on 375px width
|
|||
|
|
- No horizontal scroll needed
|
|||
|
|
- Touch targets large enough
|
|||
|
|
- Text readable without zoom
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### PHASE 4: ORDER INTEGRATION PLANNING
|
|||
|
|
|
|||
|
|
#### INT-001: Define Order-Case Relation Model
|
|||
|
|
**Assigned:** Integration-Agent
|
|||
|
|
**Estimated Time:** 30 minutes
|
|||
|
|
**Dependencies:** None
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Document how orders integrate with cases:
|
|||
|
|
- Orders CAN be created independently
|
|||
|
|
- Orders MUST be linkable to one or more cases
|
|||
|
|
- When order created from case → create relation
|
|||
|
|
- Define relation type for order links (e.g., `fulfills`, `invoices_for`)
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Architectural constraints document
|
|||
|
|
- Current relation types
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Design document: `docs/ORDER_CASE_INTEGRATION.md`
|
|||
|
|
- Relation type definitions
|
|||
|
|
- Workflow diagrams
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Clear definition of order independence
|
|||
|
|
- Relation type defined
|
|||
|
|
- Creation workflow documented
|
|||
|
|
- No violation of "orders are not cases" rule
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### INT-002: Plan Order Table Schema
|
|||
|
|
**Assigned:** Integration-Agent
|
|||
|
|
**Estimated Time:** 45 minutes
|
|||
|
|
**Dependencies:** INT-001
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Design order tables with case linking:
|
|||
|
|
- `orders` table (id, title, description, status, etc.)
|
|||
|
|
- `order_case_relations` table (order_id, case_id, relation_type)
|
|||
|
|
- NO embedding of case logic in orders
|
|||
|
|
- Soft-delete everywhere
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Order-case relation model (INT-001)
|
|||
|
|
- Existing `sag_*` schema
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- SQL migration draft: `migrations/XXX_orders.sql`
|
|||
|
|
- Schema documentation
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Order table defined
|
|||
|
|
- Many-to-many relation to cases
|
|||
|
|
- No parent/child embedding
|
|||
|
|
- Soft-delete columns present
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### INT-003: Define Order API Contract
|
|||
|
|
**Assigned:** Integration-Agent
|
|||
|
|
**Estimated Time:** 45 minutes
|
|||
|
|
**Dependencies:** INT-002
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Define order API endpoints:
|
|||
|
|
- `GET /api/v1/orders` - List orders
|
|||
|
|
- `POST /api/v1/orders` - Create order (optionally from case)
|
|||
|
|
- `POST /api/v1/orders/{id}/cases` - Link to case
|
|||
|
|
- `GET /api/v1/cases/{id}/orders` - Get orders for case
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Order schema (INT-002)
|
|||
|
|
- Case API patterns
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- API specification document
|
|||
|
|
- Example requests/responses
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- All CRUD operations defined
|
|||
|
|
- Case linking endpoints defined
|
|||
|
|
- Consistent with case API patterns
|
|||
|
|
- Examples provided
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### PHASE 5: DOCUMENTATION
|
|||
|
|
|
|||
|
|
#### DOC-001: Update Module README
|
|||
|
|
**Assigned:** Docs-Agent
|
|||
|
|
**Estimated Time:** 30 minutes
|
|||
|
|
**Dependencies:** BE-001 through BE-005
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Update `/app/modules/sag/README.md` with:
|
|||
|
|
- Current implementation status
|
|||
|
|
- All API endpoints with examples
|
|||
|
|
- Relation types and meanings
|
|||
|
|
- Tag workflow explanation
|
|||
|
|
- Architectural constraints summary
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Current implementation
|
|||
|
|
- Backend router
|
|||
|
|
- Templates
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Updated `README.md`
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- All endpoints documented
|
|||
|
|
- Examples provided
|
|||
|
|
- Architectural rules explained
|
|||
|
|
- Easy to understand for new developers
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### DOC-002: Create API Documentation
|
|||
|
|
**Assigned:** Docs-Agent
|
|||
|
|
**Estimated Time:** 45 minutes
|
|||
|
|
**Dependencies:** BE-001 through BE-005
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Create OpenAPI-style documentation for all endpoints:
|
|||
|
|
- Request/response schemas
|
|||
|
|
- Status codes
|
|||
|
|
- Error responses
|
|||
|
|
- Example curl commands
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Backend router
|
|||
|
|
- Pydantic models (if any)
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- `docs/SAG_API_REFERENCE.md`
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- All endpoints documented
|
|||
|
|
- Schemas defined
|
|||
|
|
- Examples provided
|
|||
|
|
- Status codes listed
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### DOC-003: Document Relation Types
|
|||
|
|
**Assigned:** Docs-Agent
|
|||
|
|
**Estimated Time:** 30 minutes
|
|||
|
|
**Dependencies:** BE-004
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Create reference guide for relation types:
|
|||
|
|
- `derived` - Target case spawned from source
|
|||
|
|
- `blocks` - Source blocks target from progressing
|
|||
|
|
- `executes` - Target performs work for source
|
|||
|
|
- `relates_to` - Generic association
|
|||
|
|
|
|||
|
|
Include use cases and examples.
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Relation type validation (BE-004)
|
|||
|
|
- Existing use patterns
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- `docs/CASE_RELATION_TYPES.md`
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- All types explained
|
|||
|
|
- Use cases provided
|
|||
|
|
- Examples given
|
|||
|
|
- Directionality clear
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### DOC-004: Create Workflow Examples
|
|||
|
|
**Assigned:** Docs-Agent
|
|||
|
|
**Estimated Time:** 45 minutes
|
|||
|
|
**Dependencies:** DOC-001, DOC-002, DOC-003
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Document common workflows:
|
|||
|
|
1. Customer calls → create support case → derive hardware order case → execute fulfillment case
|
|||
|
|
2. Billing cycle → create invoice case → relate to completed support cases
|
|||
|
|
3. Project → create project case → derive task cases → track via tags
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- All documentation
|
|||
|
|
- Current implementation
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- `docs/SAG_WORKFLOWS.md`
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- At least 3 workflows documented
|
|||
|
|
- Step-by-step instructions
|
|||
|
|
- API calls shown
|
|||
|
|
- Relation chains visualized
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### PHASE 6: QA & TESTING
|
|||
|
|
|
|||
|
|
#### QA-001: Backend CRUD Tests
|
|||
|
|
**Assigned:** QA-Agent
|
|||
|
|
**Estimated Time:** 90 minutes
|
|||
|
|
**Dependencies:** BE-001 through BE-005
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Write integration tests for all CRUD operations:
|
|||
|
|
- Create case
|
|||
|
|
- Read case
|
|||
|
|
- Update case
|
|||
|
|
- Delete case (soft)
|
|||
|
|
- Verify deleted_at set correctly
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Backend router
|
|||
|
|
- Test database
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Test file: `tests/test_sag_crud.py`
|
|||
|
|
- At least 20 test cases
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- All CRUD operations tested
|
|||
|
|
- Soft-delete verified
|
|||
|
|
- Error cases tested
|
|||
|
|
- All tests pass
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### QA-002: Relation Tests
|
|||
|
|
**Assigned:** QA-Agent
|
|||
|
|
**Estimated Time:** 60 minutes
|
|||
|
|
**Dependencies:** BE-001, BE-004
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Test relation operations:
|
|||
|
|
- Create relation between cases
|
|||
|
|
- List relations (both directions)
|
|||
|
|
- Validate relation type validation
|
|||
|
|
- Delete relation (soft)
|
|||
|
|
- Prevent self-relations
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Relation endpoints
|
|||
|
|
- Test database
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Test file: `tests/test_sag_relations.py`
|
|||
|
|
- At least 10 test cases
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Create/delete tested
|
|||
|
|
- Type validation tested
|
|||
|
|
- Self-relation prevention tested
|
|||
|
|
- Directionality correct
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### QA-003: Tag Workflow Tests
|
|||
|
|
**Assigned:** QA-Agent
|
|||
|
|
**Estimated Time:** 60 minutes
|
|||
|
|
**Dependencies:** BE-002
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Test tag lifecycle:
|
|||
|
|
- Add tag to case
|
|||
|
|
- Close tag (state='closed', closed_at set)
|
|||
|
|
- Verify closed tags not deleted
|
|||
|
|
- Delete tag (soft)
|
|||
|
|
- List tags (filter by state)
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Tag endpoints
|
|||
|
|
- Test database
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Test file: `tests/test_sag_tags.py`
|
|||
|
|
- At least 8 test cases
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Add/close/delete tested
|
|||
|
|
- State transitions verified
|
|||
|
|
- Soft-delete vs close distinction tested
|
|||
|
|
- All tests pass
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### QA-004: Frontend E2E Tests
|
|||
|
|
**Assigned:** QA-Agent
|
|||
|
|
**Estimated Time:** 90 minutes
|
|||
|
|
**Dependencies:** FE-001 through FE-005
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Test frontend user flows:
|
|||
|
|
- Navigate to case list
|
|||
|
|
- Filter by status/tag
|
|||
|
|
- Create new case
|
|||
|
|
- View case details
|
|||
|
|
- Edit case
|
|||
|
|
- Add/close tag
|
|||
|
|
- Add relation
|
|||
|
|
- Delete case
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- All frontend templates
|
|||
|
|
- Browser automation tool (Playwright/Selenium)
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Test file: `tests/test_sag_frontend.py`
|
|||
|
|
- At least 10 E2E scenarios
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- All major flows tested
|
|||
|
|
- Form submissions work
|
|||
|
|
- Navigation works
|
|||
|
|
- Error handling tested
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### QA-005: Module Disable/Enable Test
|
|||
|
|
**Assigned:** QA-Agent
|
|||
|
|
**Estimated Time:** 30 minutes
|
|||
|
|
**Dependencies:** QA-001, QA-002, QA-003, QA-004
|
|||
|
|
|
|||
|
|
**Description:**
|
|||
|
|
Test module deactivation:
|
|||
|
|
1. Create test cases/relations/tags
|
|||
|
|
2. Disable module (enabled=false in module.json)
|
|||
|
|
3. Verify endpoints return 404
|
|||
|
|
4. Verify database data intact
|
|||
|
|
5. Re-enable module
|
|||
|
|
6. Verify data still accessible
|
|||
|
|
|
|||
|
|
**Inputs:**
|
|||
|
|
- Module loader
|
|||
|
|
- Test database
|
|||
|
|
|
|||
|
|
**Outputs:**
|
|||
|
|
- Test file: `tests/test_sag_module_lifecycle.py`
|
|||
|
|
|
|||
|
|
**Done Criteria:**
|
|||
|
|
- Disable prevents access
|
|||
|
|
- Data preserved
|
|||
|
|
- Re-enable restores access
|
|||
|
|
- No data loss
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4️⃣ DEPENDENCY GRAPH
|
|||
|
|
|
|||
|
|
### Sequential Dependencies (Critical Path)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
DB-001 (30m)
|
|||
|
|
↓
|
|||
|
|
BE-001 (45m) ← MUST complete before any backend work
|
|||
|
|
↓
|
|||
|
|
├→ BE-002 (45m)
|
|||
|
|
├→ BE-003 (30m)
|
|||
|
|
├→ BE-004 (45m)
|
|||
|
|
└→ BE-005 (45m) ← Touches all other BE tasks
|
|||
|
|
↓
|
|||
|
|
┌────┴────┐
|
|||
|
|
↓ ↓
|
|||
|
|
FE-001 QA-001 (90m)
|
|||
|
|
(45m) ↓
|
|||
|
|
↓ QA-002 (60m)
|
|||
|
|
FE-002 ↓
|
|||
|
|
(60m) QA-003 (60m)
|
|||
|
|
↓ ↓
|
|||
|
|
FE-003 QA-004 (90m)
|
|||
|
|
(90m) ↓
|
|||
|
|
↓ QA-005 (30m)
|
|||
|
|
FE-004
|
|||
|
|
(90m)
|
|||
|
|
↓
|
|||
|
|
FE-005
|
|||
|
|
(60m)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Parallel Opportunities
|
|||
|
|
|
|||
|
|
**Wave 1 (after BE-001):**
|
|||
|
|
- BE-002, BE-003, BE-004 can run in parallel
|
|||
|
|
- Saves ~90 minutes
|
|||
|
|
|
|||
|
|
**Wave 2 (after BE-005):**
|
|||
|
|
- FE-001, FE-003, QA-001, QA-002 can run in parallel
|
|||
|
|
- DOC-001, DOC-002, DOC-003 can run in parallel
|
|||
|
|
- Saves ~2 hours
|
|||
|
|
|
|||
|
|
**Wave 3 (after FE-004):**
|
|||
|
|
- FE-005, QA-004, DOC-004 can run in parallel
|
|||
|
|
- Saves ~1 hour
|
|||
|
|
|
|||
|
|
**Wave 4 (order integration):**
|
|||
|
|
- INT-001, INT-002, INT-003 can run in parallel (independent of other work)
|
|||
|
|
|
|||
|
|
### Critical Path Time
|
|||
|
|
If executed sequentially: **~12 hours**
|
|||
|
|
If parallelized optimally: **~6-7 hours**
|
|||
|
|
|
|||
|
|
### Where Orders Integrate
|
|||
|
|
|
|||
|
|
**Order Integration is PARALLEL to Case Enhancement:**
|
|||
|
|
- INT-001, INT-002, INT-003 can start immediately
|
|||
|
|
- Do NOT block case module completion
|
|||
|
|
- Orders gain meaning when linked to cases via relations
|
|||
|
|
- No architectural changes to cases needed
|
|||
|
|
|
|||
|
|
**Order-Case Interface:**
|
|||
|
|
```
|
|||
|
|
Cases Module (Complete)
|
|||
|
|
↓
|
|||
|
|
Orders Module (New)
|
|||
|
|
↓
|
|||
|
|
order_case_relations table
|
|||
|
|
↓
|
|||
|
|
Relation type: "fulfills" / "invoices_for"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5️⃣ VALIDATION CHECKLIST
|
|||
|
|
|
|||
|
|
### Phase 1: Database Schema
|
|||
|
|
- [ ] Binary status constraint verified (`åben` / `lukket`)
|
|||
|
|
- [ ] Tag state constraint verified (`open` / `closed`)
|
|||
|
|
- [ ] All soft-delete columns present
|
|||
|
|
- [ ] All indexes exist and performant
|
|||
|
|
- [ ] Triggers working (updated_at auto-update)
|
|||
|
|
- [ ] No foreign key errors
|
|||
|
|
- [ ] Relation self-reference prevented
|
|||
|
|
|
|||
|
|
### Phase 2: Backend API
|
|||
|
|
- [ ] No duplicate `/sag/*` endpoints exist
|
|||
|
|
- [ ] Only `/cases` prefix used
|
|||
|
|
- [ ] Tag closing endpoint works (PATCH tags/{id})
|
|||
|
|
- [ ] Edit view route serves form
|
|||
|
|
- [ ] Relation type validation enforces allowed types
|
|||
|
|
- [ ] All endpoints return consistent error format
|
|||
|
|
- [ ] All errors logged with context
|
|||
|
|
- [ ] Soft-deletes set `deleted_at`, not physical delete
|
|||
|
|
|
|||
|
|
### Phase 3: Frontend
|
|||
|
|
- [ ] Edit form loads case data
|
|||
|
|
- [ ] Edit form submits to PATCH endpoint
|
|||
|
|
- [ ] Tag closing UI doesn't delete tags
|
|||
|
|
- [ ] Closed tags remain visible (greyed out)
|
|||
|
|
- [ ] Relations grouped by type
|
|||
|
|
- [ ] Directionality clear (in/out)
|
|||
|
|
- [ ] Bulk operations work
|
|||
|
|
- [ ] All views mobile-responsive (375px)
|
|||
|
|
|
|||
|
|
### Phase 4: Order Integration
|
|||
|
|
- [ ] Order-case relation model documented
|
|||
|
|
- [ ] Orders can be created independently
|
|||
|
|
- [ ] Orders linkable to multiple cases
|
|||
|
|
- [ ] No case logic embedded in orders
|
|||
|
|
- [ ] Order table schema has soft-deletes
|
|||
|
|
- [ ] API contract consistent with case API
|
|||
|
|
|
|||
|
|
### Phase 5: Documentation
|
|||
|
|
- [ ] README updated with current state
|
|||
|
|
- [ ] All endpoints documented
|
|||
|
|
- [ ] Relation types explained
|
|||
|
|
- [ ] Workflows documented
|
|||
|
|
- [ ] Examples provided
|
|||
|
|
|
|||
|
|
### Phase 6: Testing
|
|||
|
|
- [ ] All CRUD operations tested
|
|||
|
|
- [ ] Relation creation/deletion tested
|
|||
|
|
- [ ] Tag state transitions tested
|
|||
|
|
- [ ] Frontend flows tested
|
|||
|
|
- [ ] Module disable/enable tested
|
|||
|
|
- [ ] Data preserved after disable
|
|||
|
|
- [ ] All tests pass
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ARCHITECTURAL CONSTRAINT RE-VALIDATION
|
|||
|
|
|
|||
|
|
After each phase, validate these rules:
|
|||
|
|
|
|||
|
|
### Core Entity Rule
|
|||
|
|
- ✅ Only one entity: Case
|
|||
|
|
- ✅ Tickets/tasks are cases with different tags/relations
|
|||
|
|
- ⚠️ Orders are transactional objects, NOT cases (separate table)
|
|||
|
|
|
|||
|
|
### Orders Exception
|
|||
|
|
- ⚠️ Orders can be created independently (INT-002)
|
|||
|
|
- ⚠️ Orders linkable to cases via relations (INT-002)
|
|||
|
|
- ⚠️ No case logic in order workflow (INT-001)
|
|||
|
|
|
|||
|
|
### Template Usage
|
|||
|
|
- ✅ `template_key` only used at creation
|
|||
|
|
- ✅ No business logic depends on it
|
|||
|
|
|
|||
|
|
### Case Status
|
|||
|
|
- ✅ Binary only: `åben` / `lukket`
|
|||
|
|
- ✅ Workflow state via tags
|
|||
|
|
|
|||
|
|
### Tags
|
|||
|
|
- ✅ Represent work to be done
|
|||
|
|
- ✅ Have state: `open` / `closed`
|
|||
|
|
- ✅ Never deleted when completed (closed instead)
|
|||
|
|
- ✅ Closing = completion of responsibility
|
|||
|
|
|
|||
|
|
### Relations
|
|||
|
|
- ✅ First-class data (own table)
|
|||
|
|
- ✅ Directional (kilde → mål)
|
|||
|
|
- ✅ Transitive (chains allowed)
|
|||
|
|
- ✅ No parent/child duality in stored data
|
|||
|
|
- ✅ UI derives parent/child views
|
|||
|
|
|
|||
|
|
### Deletion Policy
|
|||
|
|
- ✅ All deletes are soft-deletes
|
|||
|
|
- ✅ `deleted_at` mandatory everywhere
|
|||
|
|
|
|||
|
|
### Modeling Rule
|
|||
|
|
- ✅ If you think you need a new table → use relations instead
|
|||
|
|
- ⚠️ Exception: Orders (per architectural rule)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## TEST SCENARIOS BY PHASE
|
|||
|
|
|
|||
|
|
### Phase 1: Database
|
|||
|
|
1. Insert case with status='other' → constraint violation
|
|||
|
|
2. Insert tag with state='pending' → constraint violation
|
|||
|
|
3. Create relation with kilde_sag_id = målsag_id → constraint violation
|
|||
|
|
4. Soft-delete case → deleted_at set, not physical delete
|
|||
|
|
5. Query cases WHERE deleted_at IS NULL → deleted cases excluded
|
|||
|
|
|
|||
|
|
### Phase 2: Backend
|
|||
|
|
1. Call `/sag/cases` → 404 (removed endpoint)
|
|||
|
|
2. Call `/cases` → 200 with case list
|
|||
|
|
3. PATCH tag state to 'closed' → closed_at set, deleted_at NULL
|
|||
|
|
4. DELETE tag → deleted_at set, state unchanged
|
|||
|
|
5. POST relation with type='invalid' → 400 error
|
|||
|
|
6. POST relation with type='derived' → 201 created
|
|||
|
|
|
|||
|
|
### Phase 3: Frontend
|
|||
|
|
1. Edit case form → loads current values
|
|||
|
|
2. Submit edit form → case updated, redirect to detail
|
|||
|
|
3. Click "Close Tag" → tag state='closed', remains visible, greyed
|
|||
|
|
4. Add relation → dropdown shows allowed types
|
|||
|
|
5. Bulk close cases → all selected closed
|
|||
|
|
6. View on 375px screen → no horizontal scroll
|
|||
|
|
|
|||
|
|
### Phase 4: Order Integration
|
|||
|
|
1. Create order without case → success
|
|||
|
|
2. Link order to case → relation created
|
|||
|
|
3. View case → shows linked orders
|
|||
|
|
4. View order → shows linked cases
|
|||
|
|
5. Delete case → order remains (independent)
|
|||
|
|
|
|||
|
|
### Phase 5: Documentation
|
|||
|
|
1. Developer reads README → understands architecture
|
|||
|
|
2. Developer reads API docs → can call endpoints
|
|||
|
|
3. Developer reads relation types → understands usage
|
|||
|
|
4. Developer reads workflows → can implement feature
|
|||
|
|
|
|||
|
|
### Phase 6: QA
|
|||
|
|
1. All CRUD operations → success
|
|||
|
|
2. Soft-delete case → data preserved
|
|||
|
|
3. Module disabled → endpoints return 404
|
|||
|
|
4. Module re-enabled → data accessible again
|
|||
|
|
5. Tag closed → not deleted
|
|||
|
|
6. Relation created → directionality correct
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ANTI-PATTERNS TO AVOID
|
|||
|
|
|
|||
|
|
### DO NOT:
|
|||
|
|
- ❌ Create `tickets` or `tasks` tables (use cases with tags)
|
|||
|
|
- ❌ Embed workflow logic in orders
|
|||
|
|
- ❌ Introduce parent/child trees outside relations
|
|||
|
|
- ❌ Add state machines (use tags)
|
|||
|
|
- ❌ Optimize prematurely (no Redis, no caching yet)
|
|||
|
|
- ❌ Physical delete anything (always soft-delete)
|
|||
|
|
- ❌ Skip validation (enforce constraints)
|
|||
|
|
- ❌ Duplicate endpoints (one path per resource)
|
|||
|
|
|
|||
|
|
### DO:
|
|||
|
|
- ✅ Use relations to express connections
|
|||
|
|
- ✅ Use tags to express workflow state
|
|||
|
|
- ✅ Keep orders independent but relatable
|
|||
|
|
- ✅ Soft-delete everything
|
|||
|
|
- ✅ Log all actions with emoji prefixes
|
|||
|
|
- ✅ Return user-friendly errors
|
|||
|
|
- ✅ Preserve data on module disable
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ROLLOUT PLAN
|
|||
|
|
|
|||
|
|
### Development Environment
|
|||
|
|
1. Complete Phases 1-3 in dev
|
|||
|
|
2. Test with test data
|
|||
|
|
3. Verify module disable/enable
|
|||
|
|
|
|||
|
|
### Staging/QA
|
|||
|
|
1. Run full QA suite (Phase 6)
|
|||
|
|
2. Performance test with 10k+ cases
|
|||
|
|
3. Load test endpoints
|
|||
|
|
4. Verify soft-deletes work at scale
|
|||
|
|
|
|||
|
|
### Production
|
|||
|
|
1. Run schema validation (DB-001)
|
|||
|
|
2. Deploy backend changes (Phase 2)
|
|||
|
|
3. Deploy frontend changes (Phase 3)
|
|||
|
|
4. Monitor logs for errors
|
|||
|
|
5. Verify no downtime
|
|||
|
|
6. Roll back if issues (soft-deletes preserve data)
|
|||
|
|
|
|||
|
|
### Post-Deployment
|
|||
|
|
1. Monitor case creation rate
|
|||
|
|
2. Track relation usage patterns
|
|||
|
|
3. Identify most-used tags
|
|||
|
|
4. Plan order integration (Phase 4)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## SUCCESS CRITERIA
|
|||
|
|
|
|||
|
|
The Sag Module implementation is COMPLETE when:
|
|||
|
|
|
|||
|
|
✅ **Database**
|
|||
|
|
- All constraints enforced
|
|||
|
|
- Soft-deletes everywhere
|
|||
|
|
- Indexes performant
|
|||
|
|
|
|||
|
|
✅ **Backend**
|
|||
|
|
- No duplicate endpoints
|
|||
|
|
- Tag closing works
|
|||
|
|
- Relations validated
|
|||
|
|
- Edit route exists
|
|||
|
|
- Errors consistent
|
|||
|
|
|
|||
|
|
✅ **Frontend**
|
|||
|
|
- Edit form works
|
|||
|
|
- Tag closing UI works
|
|||
|
|
- Relations visualized
|
|||
|
|
- Bulk operations work
|
|||
|
|
- Mobile responsive
|
|||
|
|
|
|||
|
|
✅ **Order Integration**
|
|||
|
|
- Model documented
|
|||
|
|
- Schema planned
|
|||
|
|
- API defined
|
|||
|
|
- No constraint violations
|
|||
|
|
|
|||
|
|
✅ **Documentation**
|
|||
|
|
- README complete
|
|||
|
|
- API documented
|
|||
|
|
- Relation types explained
|
|||
|
|
- Workflows documented
|
|||
|
|
|
|||
|
|
✅ **Testing**
|
|||
|
|
- All CRUD tested
|
|||
|
|
- Relations tested
|
|||
|
|
- Tags tested
|
|||
|
|
- Frontend tested
|
|||
|
|
- Module lifecycle tested
|
|||
|
|
|
|||
|
|
✅ **Architectural Compliance**
|
|||
|
|
- One entity: Case
|
|||
|
|
- Orders separate but linkable
|
|||
|
|
- Template key not used in logic
|
|||
|
|
- Status binary
|
|||
|
|
- Tags never deleted (closed)
|
|||
|
|
- Relations directional
|
|||
|
|
- Soft-deletes everywhere
|
|||
|
|
- No new tables (except orders)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## APPENDIX A: TASK TIME SUMMARY
|
|||
|
|
|
|||
|
|
| Phase | Task Count | Sequential Time | Parallel Time |
|
|||
|
|
|-------|-----------|----------------|---------------|
|
|||
|
|
| Phase 1: Database | 1 | 30m | 30m |
|
|||
|
|
| Phase 2: Backend | 5 | 3h 30m | 1h 45m |
|
|||
|
|
| Phase 3: Frontend | 5 | 5h 45m | 2h 30m |
|
|||
|
|
| Phase 4: Orders | 3 | 2h | 30m (parallel) |
|
|||
|
|
| Phase 5: Docs | 4 | 2h 30m | 45m (parallel) |
|
|||
|
|
| Phase 6: QA | 5 | 4h 30m | 2h |
|
|||
|
|
| **TOTAL** | **23** | **18h 45m** | **~8h** |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## APPENDIX B: RELATION TYPE REFERENCE
|
|||
|
|
|
|||
|
|
| Type | Direction | Meaning | Example |
|
|||
|
|
|------|-----------|---------|---------|
|
|||
|
|
| `derived` | A → B | B spawned from A | Support call → hardware order |
|
|||
|
|
| `blocks` | A → B | A prevents B | Missing part → installation task |
|
|||
|
|
| `executes` | A → B | A performs work for B | Packing task → customer order |
|
|||
|
|
| `relates_to` | A ↔ B | Generic association | Related support tickets |
|
|||
|
|
|
|||
|
|
**Validation:** Only these four types allowed in `POST /api/v1/cases/{id}/relations`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## APPENDIX C: TAG STATE LIFECYCLE
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Tag Created (state='open', closed_at=NULL)
|
|||
|
|
↓
|
|||
|
|
[Work happens]
|
|||
|
|
↓
|
|||
|
|
Tag Closed (state='closed', closed_at=NOW(), deleted_at=NULL)
|
|||
|
|
↓
|
|||
|
|
Tag Remains Visible (greyed out in UI)
|
|||
|
|
↓
|
|||
|
|
[Optional: Technical cleanup]
|
|||
|
|
↓
|
|||
|
|
Tag Soft-Deleted (deleted_at=NOW())
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Key Rule:** Closing ≠ Deleting. Tags are closed when work is done, deleted only if added by mistake.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## APPENDIX D: ORDER-CASE INTEGRATION EXAMPLE
|
|||
|
|
|
|||
|
|
**Scenario:** Customer needs new laptop
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. Support Call (Case ID: 1001)
|
|||
|
|
- Type: Case
|
|||
|
|
- Tags: [support, hardware]
|
|||
|
|
- Status: åben
|
|||
|
|
|
|||
|
|
2. Create Hardware Order (Order ID: 5001)
|
|||
|
|
- Type: Order (separate table)
|
|||
|
|
- Items: [Laptop, Charger]
|
|||
|
|
- Status: pending
|
|||
|
|
|
|||
|
|
3. Link Order to Case
|
|||
|
|
- POST /api/v1/orders/5001/cases
|
|||
|
|
- Body: {"case_id": 1001, "relation_type": "fulfills"}
|
|||
|
|
- Creates entry in order_case_relations
|
|||
|
|
|
|||
|
|
4. Fulfillment Task (Case ID: 1002)
|
|||
|
|
- Type: Case
|
|||
|
|
- Tags: [fulfillment]
|
|||
|
|
- Status: åben
|
|||
|
|
- Relation: 1002 executes 1001
|
|||
|
|
|
|||
|
|
5. Query Cases for Order
|
|||
|
|
- GET /api/v1/orders/5001/cases
|
|||
|
|
- Returns: [Case 1001]
|
|||
|
|
|
|||
|
|
6. Query Orders for Case
|
|||
|
|
- GET /api/v1/cases/1001/orders
|
|||
|
|
- Returns: [Order 5001]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Architecture Preserved:**
|
|||
|
|
- Order is NOT a case
|
|||
|
|
- Order is independent (can exist without case)
|
|||
|
|
- Order gains context through case relation
|
|||
|
|
- Cases remain the process backbone
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## DOCUMENT CONTROL
|
|||
|
|
|
|||
|
|
**Version History:**
|
|||
|
|
|
|||
|
|
| Version | Date | Author | Changes |
|
|||
|
|
|---------|------|--------|---------|
|
|||
|
|
| 1.0 | 2026-01-30 | GitHub Copilot | Initial plan |
|
|||
|
|
| 2.0 | 2026-01-30 | GitHub Copilot | Sub-agent task breakdown added |
|
|||
|
|
|
|||
|
|
**Approval:**
|
|||
|
|
- [ ] Architect Review
|
|||
|
|
- [ ] Technical Lead Review
|
|||
|
|
- [ ] Project Manager Approval
|
|||
|
|
|
|||
|
|
**Next Review Date:** After Phase 2 completion
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**END OF IMPLEMENTATION PLAN**
|