# Sag Module Documentation

## Overview
The Sag Module is a universal case management system where tickets, tasks, and orders are all represented as cases with different tags and relations. The core idea is that there is only one entity: a case. All other attributes are metadata, tags, and relations.

## Database Schema

### `sag_sager` (Main Table for Cases)
- **Columns**:
  - `id`: Primary key
  - `titel`: `VARCHAR` - Title of the case
  - `beskrivelse`: `TEXT` - Detailed description
  - `template_key`: `VARCHAR, NULL` - Used only during creation, no business logic
  - `status`: `VARCHAR` - Allowed values: `'åben'`, `'lukket'`
  - `customer_id`: Foreign key, nullable
  - `ansvarlig_bruger_id`: Foreign key, nullable
  - `created_by_user_id`: Foreign key, not nullable
  - `deadline`: `TIMESTAMP`, nullable
  - `created_at`: `TIMESTAMP`
  - `updated_at`: `TIMESTAMP`
  - `deleted_at`: `TIMESTAMP` (soft-delete)

### `sag_relationer` (Relations Between Cases)
- **Columns**:
  - `id`: Primary key
  - `kilde_sag_id`: Foreign key (source case)
  - `målsag_id`: Foreign key (target case)
  - `relationstype`: `VARCHAR` - Examples: `'derived'`, `'blocks'`, `'executes'`
  - `created_at`: `TIMESTAMP`
  - `deleted_at`: `TIMESTAMP`

### `sag_tags` (Process and Categorization)
- **Columns**:
  - `id`: Primary key
  - `sag_id`: Foreign key (case reference)
  - `tag_navn`: `VARCHAR` - Name of the tag
  - `state`: `VARCHAR DEFAULT 'open'` - `'open'` (not completed), `'closed'` (completed)
  - `closed_at`: `TIMESTAMP`, nullable
  - `created_at`: `TIMESTAMP`
  - `deleted_at`: `TIMESTAMP`

## API Endpoints

### Cases
- `GET    /api/v1/cases` - List all cases with optional filters.
- `POST   /api/v1/cases` - Create a new case.
- `GET    /api/v1/cases/{id}` - Retrieve a specific case by ID.
- `PATCH  /api/v1/cases/{id}` - Update a specific case.
- `DELETE /api/v1/cases/{id}` - Soft-delete a specific case.

### Relations
- `GET    /api/v1/cases/{id}/relations` - List all relations for a specific case.
- `POST   /api/v1/cases/{id}/relations` - Create a new relation for a case.
- `DELETE /api/v1/cases/{id}/relations/{relation_id}` - Soft-delete a specific relation.

### Tags
- `GET    /api/v1/cases/{id}/tags` - List all tags for a specific case.
- `POST   /api/v1/cases/{id}/tags` - Add a tag to a case.
- `DELETE /api/v1/cases/{id}/tags/{tag_id}` - Soft-delete a specific tag.

## Frontend Views

### Case List
- **Route**: `/cases`
- **Description**: Displays a list of all cases with filters for status and tags.
- **Template**: `index.html`

### Case Details
- **Route**: `/cases/{case_id}`
- **Description**: Displays detailed information about a specific case, including its tags and relations.
- **Template**: `detail.html`

## Features
1. **Soft-Delete**: Cases, relations, and tags are not permanently deleted. Instead, they are marked with a `deleted_at` timestamp.
2. **Tag-Based Workflow**: Tags represent tasks or categories and can be marked as `open` or `closed`.
3. **Relations**: Cases can be related to each other with directional and transitive relations.

## Development Notes
- All database queries use `execute_query()` from `app.core.database`.
- Queries are parameterized with `%s` placeholders to prevent SQL injection.
- `RealDictCursor` is used for dict-like row access.
- Triggers automatically update the `updated_at` column.
- Relations are first-class citizens and are not just links.

## Example Workflows

### Example 1: Support Ticket
1. A customer calls to request a new monitor.
2. A case is created with the tag `support` and marked as `urgent`.
3. The case is assigned to a support agent.

### Example 2: Order Processing
1. A case is created for purchasing a monitor with the tag `indkøb`.
2. The case is related to the support ticket as `derived`.
3. The purchasing manager is assigned to the case.

### Example 3: Shipping
1. A case is created for packaging and shipping the monitor with the tag `ompakning`.
2. The case is related to the order case as `executes`.
3. The shipping department is assigned to the case.

## Module Deactivation
- When the module is deactivated, all data is preserved.
- Soft-deleted data remains in the database for potential rollback.
- Ensure no active cases are left in an inconsistent state before deactivation.