> ## Documentation Index
> Fetch the complete documentation index at: https://docs.criar.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Write To (Requests) Module

> SKOLE-WRIT — Write To (Requests) Module

# SKOLE-WRIT — Write To (Parent Requests) Module

**Module ID:** `SKOLE-WRIT` | **Version:** 1.0 | **Status:** Active\
**Products:** Parent App (create/view/reply) · Teacher App (manage/reply) · Web App (manage)

***

## 1. Overview

| Field              | Value                                                                                                                                                                                                           |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Module Name**    | Write To (Requests & Tickets)                                                                                                                                                                                   |
| **Module Code**    | WRIT                                                                                                                                                                                                            |
| **Business Value** | Structured parent-to-school communication. Parents submit requests (leave applications, complaints, queries) and track their status. Teachers/staff respond in-thread. Replaces informal phone calls and notes. |

### Scope In

* Parent: Create requests, view own requests by status, view thread with replies, reply to teacher response
* Teacher: View all incoming requests, assign to staff member, change status, add reply, resolve
* Request types: leave, complaint, general, query
* File attachment support (URL-based)

### Scope Out

* Email/SMS notification on status change (planned)
* Escalation workflow to principal

***

## 2. Requirements

### Functional Requirements (FR)

*What the module must DO — actions, behaviors, and outcomes.*

* **SKOLE-WRIT-FR001:** The module shall allow parents to create new requests with type (leave, complaint, general, query), subject, and message.
* **SKOLE-WRIT-FR002:** The module shall enable parents to view their own requests and filter them by status.
* **SKOLE-WRIT-FR003:** The module shall provide a threaded view for single requests, displaying all replies.
* **SKOLE-WRIT-FR004:** The module shall allow both parents and staff to add replies to an existing request thread.
* **SKOLE-WRIT-FR005:** The module shall enable teachers to view all incoming requests and assign them to specific staff members.
* **SKOLE-WRIT-FR006:** The module shall allow staff to update request statuses: pending, in-progress, resolved, or rejected.
* **SKOLE-WRIT-FR007:** The module shall capture resolution details (who resolved it, notes, and timestamp) when a request is marked as resolved.
* **SKOLE-WRIT-FR008:** The module shall allow for soft-deletion of requests and replies.

### Non-Functional Requirements (NFR)

*How well the module must do it — performance, security, and reliability.*

* **SKOLE-WRIT-NFR001:** The module shall behave securely by ensuring parents can only view requests they created (scoped by JWT `parent_id`).
* **SKOLE-WRIT-NFR002:** The module shall perform structured threading by strictly linking all replies to a parent `write_to_id`.
* **SKOLE-WRIT-NFR003:** The module shall behave reliably by tracking the `is_read` status of replies to ensure users are aware of new communications.
* **SKOLE-WRIT-NFR004:** The module shall perform secure data filtering by excluding all soft-deleted records from standard views.

### Constraints

*Rules and boundaries — tech choices and platform restrictions.*

* **C001:** We must implement soft-deletion because the platform's audit policy prevents permanent removal of communication records.
* **C002:** We must use the `skole_id` as the primary partition key for all request and reply lookups to maintain multi-tenancy.

***

## 3. Sub-modules / Backlog

| ID                 | Sub-module                       | Priority | Status  | Estimate | Linked FR   |
| ------------------ | -------------------------------- | -------- | ------- | -------- | ----------- |
| `SKOLE-WRIT-SM001` | Parent request creation          | P0       | Done    | 2d       | FR001–FR002 |
| `SKOLE-WRIT-SM002` | Parent request list & detail     | P0       | Done    | 2d       | FR003–FR005 |
| `SKOLE-WRIT-SM003` | Teacher/staff request management | P0       | Done    | 3d       | FR006–FR009 |
| `SKOLE-WRIT-SM004` | Web admin request management     | P1       | Done    | 2d       | FR006–FR009 |
| `SKOLE-WRIT-SM005` | Unread badge on replies          | P2       | Partial | 1d       | NF003       |

***

## 4. Logical Implementation

### Request Status State Machine

```text theme={null}
[pending] ──assign──→ [in-progress]
[in-progress] ──resolve──→ [resolved]  (captures resolved_by, resolution_notes, resolved_at)
[in-progress] ──reject──→ [rejected]
[pending|in-progress] ──delete──→ [deleted] (deleted_status=1)
```

### Parent Create Flow

```text theme={null}
POST /parent-app/write-to
  ├─ Input: { skole_id, parent_id, student_id, request_type, subject, message,
  │           request_date, leave_from_date?, leave_to_date?, attachment_url?, priority }
  └─ INSERT write_to → return created request
```

### Parent View Thread Flow

```text theme={null}
GET /parent-app/write-to/:id
  ├─ Verify request belongs to this parent (parent_id = jwt.sub)
  ├─ Fetch write_to record
  ├─ Fetch write_to_replies WHERE write_to_id = :id ORDER BY created_at ASC
  └─ Return { request, replies[] }
```

### Teacher Reply Flow

```text theme={null}
POST /teachers-app/write-to/:id/reply
  ├─ Input: { replied_by, replied_by_id, message, attachment_url? }
  └─ INSERT write_to_replies + optionally update write_to.status
```

***

## 5. UI Requirements

### Parent App — Write To Screens

| ID                 | Screen              | Route             | Description                                               |
| ------------------ | ------------------- | ----------------- | --------------------------------------------------------- |
| `SKOLE-WRIT-UI001` | WriteToListScreen   | `/writeto`        | Filterable list of all parent requests with status badges |
| `SKOLE-WRIT-UI002` | WriteToCreateScreen | `/writeto-create` | Form to create a new request                              |
| `SKOLE-WRIT-UI003` | WriteToDetailScreen | `/writeto-detail` | Threaded conversation view for a single request           |

**Components:**

| ID                 | Component             | Props                                                 |             |          |            |
| ------------------ | --------------------- | ----------------------------------------------------- | ----------- | -------- | ---------- |
| `SKOLE-WRIT-UC001` | `RequestCard`         | `request`, `onPress`                                  |             |          |            |
| `SKOLE-WRIT-UC002` | `StatusBadge`         | \`status: pending                                     | in-progress | resolved | rejected\` |
| `SKOLE-WRIT-UC003` | `RequestTypeSelector` | `types[]`, `selected`, `onChange`                     |             |          |            |
| `SKOLE-WRIT-UC004` | `DateRangePicker`     | `fromDate`, `toDate`, `onChange` — for leave requests |             |          |            |
| `SKOLE-WRIT-UC005` | `ReplyBubble`         | `reply`, `isFromParent`                               |             |          |            |
| `SKOLE-WRIT-UC006` | `ReplyInput`          | `onSubmit`, `loading`                                 |             |          |            |
| `SKOLE-WRIT-UC007` | `StatusFilterTabs`    | `statuses[]`, `active`, `onChange`                    |             |          |            |

**UI States:**

* **WriteToListScreen Loading:** Skeleton cards
* **Empty list:** "No requests found. Tap + to create one."
* **WriteToDetailScreen Loading:** Skeleton thread
* **Error:** Toast with retry

### Teacher App — Write To

| ID                 | Screen              | Route      | Description                                            |
| ------------------ | ------------------- | ---------- | ------------------------------------------------------ |
| `SKOLE-WRIT-UI004` | WriteToManageScreen | `/writeto` | All school requests with filter, assign, status change |

### Web App

| ID                 | Screen       | Route               | Description                                               |
| ------------------ | ------------ | ------------------- | --------------------------------------------------------- |
| `SKOLE-WRIT-UI005` | Tickets Page | `/:skoleId/tickets` | Admin full view: all requests, status management, replies |

***

## 6. Conditional Expressions

| ID                 | Expression                                             | Trigger                      | True Action                   | False Action             |
| ------------------ | ------------------------------------------------------ | ---------------------------- | ----------------------------- | ------------------------ |
| `SKOLE-WRIT-CE001` | `request.status === 'resolved'`                        | RequestCard render           | Green badge, lock reply input | Normal style             |
| `SKOLE-WRIT-CE002` | `request.status === 'rejected'`                        | RequestCard render           | Red badge                     | Normal style             |
| `SKOLE-WRIT-CE003` | `request.request_type === 'leave'`                     | CreateScreen render          | Show DateRangePicker          | Hide date range fields   |
| `SKOLE-WRIT-CE004` | `request.parent_id !== jwt.sub`                        | GET /parent-app/write-to/:id | Return 403                    | Return request + replies |
| `SKOLE-WRIT-CE005` | `reply.is_read === 0 && reply.replied_by !== 'parent'` | ReplyBubble render           | Show unread dot               | Normal                   |
| `SKOLE-WRIT-CE006` | `request.deleted_status === 1`                         | DB query                     | Exclude                       | Include                  |
| `SKOLE-WRIT-CE007` | `request.priority === 'high'`                          | RequestCard render           | Red priority icon             | Normal priority icon     |
| `SKOLE-WRIT-CE008` | `request.resolved_at !== null`                         | Timeline render              | Show resolution timestamp     | Hide resolution section  |

***

## 7. Internal Module Connections

| Direction   | Module   | Data / Event                                    | Condition                |
| ----------- | -------- | ----------------------------------------------- | ------------------------ |
| WRIT → AUTH | Auth     | JWT `sub` used as `parent_id` to scope requests | Every parent request     |
| WRIT → STUD | Students | `student_id` links request to a specific child  | Every request            |
| WRIT → STAF | Staff    | `assigned_to` references a `staff.id`           | When request is assigned |

***

## 8. External Connections

| ID                 | Service             | Purpose                                      | Failure Behavior |
| ------------------ | ------------------- | -------------------------------------------- | ---------------- |
| `SKOLE-WRIT-EX001` | PostgreSQL (Prisma) | Read/write `write_to` and `write_to_replies` | 500 error        |
| `SKOLE-WRIT-EX002` | Firebase FCM        | Push notification on new reply (planned)     | Silent fail      |

***

## 9. Database Tables

| ID                 | Table              | Role                         |
| ------------------ | ------------------ | ---------------------------- |
| `SKOLE-WRIT-TB001` | `write_to`         | Parent requests              |
| `SKOLE-WRIT-TB002` | `write_to_replies` | Threaded replies per request |

### `write_to` Key Columns

| Column             | Type         | Notes                                 |
| ------------------ | ------------ | ------------------------------------- |
| `id`               | Int PK       | —                                     |
| `skole_id`         | VarChar(15)  | Tenant                                |
| `parent_id`        | Int          | FK → parent\_details.id               |
| `student_id`       | Int          | FK → students.id                      |
| `request_type`     | VarChar(50)  | leave/complaint/general/query         |
| `subject`          | VarChar(255) | Subject line                          |
| `message`          | Text         | Body                                  |
| `leave_from_date`  | Date?        | Leave period start                    |
| `leave_to_date`    | Date?        | Leave period end                      |
| `status`           | VarChar(25)  | pending/in-progress/resolved/rejected |
| `priority`         | VarChar(25)  | low/medium/high                       |
| `assigned_to`      | Int?         | FK → staff.id                         |
| `resolved_by`      | Int?         | FK → staff.id                         |
| `resolution_notes` | Text?        | Resolution message                    |
| `resolved_at`      | Timestamp?   | Resolution timestamp                  |
| `deleted_status`   | Int          | 0=active, 1=deleted                   |

***

## 10. API Endpoints

| ID                 | Method | Route                              | Auth         | Description                  |
| ------------------ | ------ | ---------------------------------- | ------------ | ---------------------------- |
| `SKOLE-WRIT-EP001` | POST   | `/parent-app/write-to`             | JWT (parent) | Create new request           |
| `SKOLE-WRIT-EP002` | GET    | `/parent-app/write-to`             | JWT (parent) | List parent's requests       |
| `SKOLE-WRIT-EP003` | GET    | `/parent-app/write-to/:id`         | JWT (parent) | Get request + replies        |
| `SKOLE-WRIT-EP004` | POST   | `/parent-app/write-to/:id/reply`   | JWT (parent) | Add reply to request         |
| `SKOLE-WRIT-EP005` | GET    | `/teachers-app/write-to`           | JWT (staff)  | View all school requests     |
| `SKOLE-WRIT-EP006` | GET    | `/teachers-app/write-to/:id`       | JWT (staff)  | Get request detail + replies |
| `SKOLE-WRIT-EP007` | PUT    | `/teachers-app/write-to/:id`       | JWT (staff)  | Update status / assign       |
| `SKOLE-WRIT-EP008` | POST   | `/teachers-app/write-to/:id/reply` | JWT (staff)  | Staff reply to request       |
| `SKOLE-WRIT-EP009` | GET    | `/web-app/write-to`                | JWT (user)   | Admin: all requests          |
| `SKOLE-WRIT-EP010` | PUT    | `/web-app/write-to/:id`            | JWT (user)   | Admin: update request        |
| `SKOLE-WRIT-EP011` | POST   | `/web-app/write-to/:id/reply`      | JWT (user)   | Admin: reply                 |
