bmc_hub/SAG_MODULE_IMPLEMENTATION_PLAN.md
Christian 29acdf3e01 Add tests for new SAG module endpoints and module deactivation
- Implement test script for new SAG module endpoints BE-003 (Tag State Management) and BE-004 (Bulk Operations).
- Create test cases for creating, updating, and bulk operations on cases and tags.
- Add a test for module deactivation to ensure data integrity is maintained.
- Include setup and teardown for tests to clear database state before and after each test.
2026-01-31 23:16:24 +01:00

1286 lines
32 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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**