# Analytics — Perubahan untuk Tim Frontend Commit: `aca7870` (branch `dev`). Semua perubahan di tiga layar analytics. **Angka desimal sekarang 2 angka di belakang koma** (integer ter-render tanpa koma, tipe tetap number). --- ## 1. Analytics Action Plan (project) `GET /api/action-plans/projects/:projectId/analytics` ### Query params | Param | Status | Nilai | Default | |---|---|---|---| | `layout` | — | `detailed` \| `simplified` | `detailed` | | `granularity` | — | `daily` \| `weekly` \| `monthly` | `weekly` | | `percentage_by` | **BARU** | `work_weight` \| `completion_of_work` \| `duration_day` | `work_weight` | | `search`, `activityName`, `startDate`, `endDate` | — | sama seperti sebelumnya | — | ### Response - **BARU** echo `data.percentageBy` (camelCase di layar project). - Semua angka (cards, tabular, s-curve) kini **round 2 desimal** (sebelumnya 3). ### Semantik `percentage_by` | Mode | Cara hitung | |---|---| | `work_weight` | Rupiah `workWeight` sebagai bobot — leaf `workWeight` kosong/0 **tetap tidak dihitung** (perilaku lama) | | `completion_of_work` | Semua leaf bobot sama (1) — murni rata-rata % progress | | `duration_day` | Bobot = jumlah hari `startDate`→`endDate` (ceil, min. 1 hari) — leaf tanpa tanggal tidak dihitung | > Leaf dengan `workWeight` kosong tapi `startDate`+`endDate` terisi = **work berbasis durasi/timeline** (penanda: weight 0/kosong). Data `workWeight` tidak di-unpack dari durasi — hitungannya derived on-the-fly di backend. --- ## 2. Analytics Agenda `GET /api/agendas/:agendaId/analytics` ### Query params | Param | Status | Nilai | Default | |---|---|---|---| | `granularity` | **DIUBAH** | hanya `weekly` \| `monthly` (⚡ `daily` dihapus → 400) | `weekly` | | `start_date`, `end_date` | — | RFC date string, snake_case | tanpa batas | | `project_type` | **BARU** | `all` \| `self_managed` \| `consultant` | `all` | | `percentage_by` | **BARU** | `work_weight` \| `completion_of_work` \| `duration_day` | `work_weight` | | `program_name` | **BARU** | string; mempersempit SELURUH report (cards + curve + tabel) ke program yang cocok | — | | `activity_name` | **BARU** | string; khusus memfilter `data.action_plan_tabular` saja | — | | `q` | **DIHAPUS** | → diganti `activity_name` / `program_name` | — | ### Response ```jsonc data: { "scope": { "id": "...", "name": "...", "type": "agenda" }, "percentage_by": "work_weight", // 🆕 echo (camelCase island ada di project analytics) "project_type": "all", // 🆕 echo "overview": { "total_children", "total_action_plan", "total_plan", "total_realization", "overall_deviation" }, "s_curve": { "granularity": "weekly", "plan": [...], "realization": [...] }, "tabular": { "unit": "program", "total": { "plan", "realization", "deviation" }, "rows": [ // ⚠️ SEMANTIK BARU: lihat §4 { "id", "name", "plan", "realization", "deviation", "total_action_plan" } ] }, "action_plan_tabular": [ // 🆕 KHUSUS agenda (undefined di program) { "name": "Pondasi", "plan": 25.2, "realization": 18.3, "deviation": -6.9, "total_action_plan": 22, "tasks": [ { "name", "plan", "realization", "deviation", "total_action_plan" } ] } ] } ``` - `action_plan_tabular` = action plan 2 level (activity → task), sama seperti tabular di analytics action plan. `activity_name` hanya memfilter tabel ini; activity yang match membawa semua task-nya. - `tabular.total` / `overview` = weighted mean 0–100 seluruh node; `action_plan_tabular` tidak punya baris Total — Total-nya itu (`overview.total_plan` dst.), jangan cari di dalam tabel. --- ## 3. Analytics Program `GET /api/programs/:programId/analytics` Sama seperti agenda, dengan perbedaan: | Perbedaan | Nilai | |---|---| | Filter nama | `project_name` (whole-report) menggantikan `program_name` | | Tabular | 1 baris per **project** (`unit: "project"`) — seperti sebelumnya | | `action_plan_tabular` | **tidak ada** (dan `activity_name` tidak berlaku) | `granularity=weekly|monthly` (serupa agenda, `daily` dihapus), `start_date`/`end_date`, `project_type`, `percentage_by` sama. --- ## 4. ⚠️ Perubahan semantik tabular (BREAKING) **Tabular agenda & program sekarang PRORATA (kontribusi)**, seperti tabular project-tier: - Sebelumnya: tiap baris = weighted mean 0–100 leaves program/project itu sendiri (Σ baris bisa melebihi 100). - Sekarang: tiap baris = **share kontribusi terhadap total node** (bobot baris ÷ total bobot seluruh node). **Σ baris = `total`**, tidak akan lebih dari 100 — mengakumulasi kumulatif aman. - `deviation` tetap dihitung dari operand RAW lalu di-round. - Baris child tanpa action plan → `plan/realization/deviation = null` (bukan `0`). Jika layar lama menganggap row `plan` sebagai progress 0–100 child, harus disesuaikan (atau render share). ### Contoh Node dengan 2 program masing-masing leaf 100% : baris kini `50 / 50` (bukan `100 / 100`), dan `total = 100`. --- ## 5. Ringkasan breaking changes 1. `q` pada agenda/program analytics **dihapus** → pakai `activity_name` (agenda) / `program_name` (agenda) / `project_name` (program). 2. `granularity=daily` di agenda/program → sekarang **400**. Gunakan `weekly`|`monthly`. 3. Nilai `tabular.rows` agenda/program berubah makna (kontribusi, bukan 0–100). 4. Semua angka rounded 2 desimal (sebelumnya 3). 5. Echo baru: `data.percentageBy` (project tier), `data.percentage_by` + `data.project_type` (agenda/program). 6. Field baru: `data.action_plan_tabular` (agenda). ## 6. Referensi - Contoh payload lengkap per endpoint: `.markdown/ANALYTICS_RESPONSE_SHAPES.md` - Query params ditulis snake_case di agenda/program (`start_date`, `percentage_by`, `project_type`) dan camelCase di project analytics (`startDate`, `percentage_by`→`percentage_by` snake juga tapi `activityName`/`search` camelCase) — perhatikan beda konvensi antar endpoint.