# Daily Report — Kanban & skema `reports.body`

Spesifikasi lengkap (sumber di repo FE): [`../FE/docs/BE_SPEC_REPORT_KANBAN_BODY_SCHEMA.md`](../FE/docs/BE_SPEC_REPORT_KANBAN_BODY_SCHEMA.md).

Ringkasan: tugas Kanban diserialisasi sebagai **JSON** di kolom **`reports.body`** (`schema: workpulse.report.v1`). **Tidak wajib** mengubah BE untuk MVP; `POST` / `PATCH` laporan yang ada sudah menerima **`body`** sebagai string.

Opsional backlog: kolom **`JSONB`**, tabel **`report_tasks`**, validasi server — lihat file FE di atas.

---

**Hubungan dengan Kalender / Team Monitoring:** tugas Kanban **tidak** otomatis muncul sebagai acara kalender atau kartu di Team Monitoring — lihat [`BE_SPEC_DAILY_REPORT_TASKS_VS_CALENDAR_AND_TEAM.md`](./BE_SPEC_DAILY_REPORT_TASKS_VS_CALENDAR_AND_TEAM.md).

---

## Ringkasan

| Pertanyaan | Jawaban |
|------------|---------|
| Apakah BE wajib diubah untuk Kanban? | **Tidak wajib** untuk MVP: `POST` / `PATCH /api/v1/reports` menerima **`body`** string; FE menyimpan JSON dengan schema di bawah. |
| Kapan BE perlu diperluas? | Query / indeks per tugas, notifikasi per kartu, atau **validasi server** struktur → pertimbangkan **`JSONB`** atau tabel **`report_tasks`**. |
| Kompatibilitas mundur | Laporan lama dengan `body` teks bebas (bukan JSON) tetap valid; FE memperlakukannya sebagai **tanpa tugas Kanban**. |

---

## Schema JSON (`workpulse.report.v1`)

Disimpan utuh di **`reports.body`** (string JSON satu root object).

```json
{
  "schema": "workpulse.report.v1",
  "workHours": "08:00 - 17:00",
  "blockers": "Teks bebas…",
  "tomorrow": "Rencana besok…",
  "tasks": [
    { "id": "uuid-v4", "title": "Ringkas tugas", "column": "todo" },
    { "id": "…", "title": "…", "column": "doing" },
    { "id": "…", "title": "…", "column": "done" }
  ]
}
```

| Field | Wajib | Keterangan |
|-------|--------|------------|
| `schema` | Ya | Harus persis **`workpulse.report.v1`** agar FE mem-parse sebagai Kanban. |
| `workHours` | Tidak | String satu baris. |
| `blockers` | Tidak | Teks panjang. |
| `tomorrow` | Tidak | Teks panjang. |
| `tasks` | Ya (array, boleh kosong) | Tiap item: **`id`** unik (string), **`title`** non-kosong, **`column`** ∈ `todo` \| `doing` \| `done`. |

**Judul (`reports.title`):** FE dapat memakai judul human-readable, mis. `Daily report · YYYY-MM-DD` — tetap memenuhi **`title` required** di BE.

**Divisi (`reports.division`):** tetap mengikuti kontrak laporan (`normalizeReportDivision` bila master divisi aktif).

---

## Endpoint yang dipakai (tanpa ubah kontrak)

| Metode | Path | Catatan |
|--------|------|---------|
| `GET` | `/api/v1/reports` | Muat draf; FE memilih `status === 'draft'` terbaru. |
| `GET` | `/api/v1/reports/:id` | Muat satu laporan. |
| `POST` | `/api/v1/reports` | Buat draf (`body` = string JSON). |
| `PATCH` | `/api/v1/reports/:id` | Autosave `body`, `title`, `division`; submit via `status` non-`draft`. |

**Kode BE:** `internal/api/rest.go` — `createReport`, `patchReport`, `getReport`, `listReports`.

---

## Peningkatan BE (opsional — backlog)

1. **`reports.body_json JSONB`** + sinkron dari `body` teks — query GIN.
2. **Tabel `report_tasks`** + `report_id` — sumber kebenaran per kartu.
3. **Validasi PATCH:** tolak `body` jika JSON tidak valid / schema tidak dikenal (saat ini BE menyimpan string apa pun).

---

*Mendampingi kontrak laporan umum; tidak mengganti aturan `division` / master organisasi — lihat [`BE_SPEC_ORG_DIVISIONS_MASTER_AND_CRUD.md`](./BE_SPEC_ORG_DIVISIONS_MASTER_AND_CRUD.md).*
