bmc_hub/SAG_MODULE_IMPLEMENTATION_PLAN.md

1286 lines
32 KiB
Markdown
Raw Permalink Normal View History

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