# DO by SO (ZFM_RF_GET_DOBYSO) - Feature Documentation

## Overview

Fitur **DO by SO** menambahkan pull data **delivery order by sales order** dari SAP ke database lokal, dengan konsep pull yang sama dengan `rpt_et_getonhand` (per `prompts/prompt2.txt`). Data disimpan pada tabel baru **`rpt_et_getdobyso`** dan diproses melalui mekanisme `rpt_sync_status` + queue job yang sama dengan endpoint SAP lainnya (ZVBILLING, ZFFINANCE_YIELD, Z_GET_NEW_CUST, Z_GET_PAYMENT, Z_GET_ONHAND) di menu **SAP Sync** (`rptsap`).

### Endpoint SAP

```
GET /ZFM_RF_GET_DOBYSO?sap-client={client}&sap-user={user}&sap-password={pass}&sap-language=EN&format=json&IP_YEAR={year}&IP_MONTH={month}
```

| Parameter | Keterangan |
|---|---|
| `IP_YEAR` | Tahun fiskal (4 digit) |
| `IP_MONTH` | Bulan fiskal (2 digit, `01`-`12`) |

### Struktur Response (`ET_DATA[]`)

| Field | Tipe (SAP) | Kolom DB | Keterangan |
|---|---|---|---|
| `SALESDOCUMENT` | char(20) | `SALESDOCUMENT` | Nomor sales order |
| `DELIVERYDATE` | date | `DELIVERYDATE` | Tanggal delivery (dapat bernilai zero-date `0000-00-00`) |
| `REQUIREDQUANTITY` | decimal | `REQUIREDQUANTITY` | Quantity yang dibutuhkan |
| `FISCALYEAR` | char(4) | `FISCALYEAR` | Tahun fiskal |
| `FISCALMONTH` | char(2) | `FISCALMONTH` | Bulan fiskal (2 digit dari filter API) |

Kolom tambahan `FISYR` (tahun sync) disimpan untuk keperluan filtering tahunan, mengikuti pola tabel SAP lain.

---

## File Structure

```
app/
  Jobs/
    SapDoBySoSyncJob.php              # NEW: Sync job untuk Z_GET_DOBYSO (bulanan)
  Http/
    Controllers/
      RptsapController.php            # Updated: REPORT_TYPES, monthly types, dispatch job, data preview

  Console/
    Commands/
      SapDailySync.php                # Updated: info report types + bulan
      DispatchPendingSync.php         # Updated: tambah case Z_GET_DOBYSO

resources/
  views/
    report/
      rptsap/
        filter.blade.php              # Updated: catatan endpoint bulanan
        status_list.blade.php         # Updated: label 'DO by SO' (PHP + JS)
        status.blade.php              # Updated: data preview kolom DO by SO

database/
  migrations/
    2026_08_06_100000_create_rpt_et_getdobyso_table.php   # NEW: tabel rpt_et_getdobyso

docs/
  rptptr_getdobyso.md                # NEW: dokumentasi ini
```

---

## Database Table: `rpt_et_getdobyso`

```sql
CREATE TABLE `rpt_et_getdobyso` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `SALESDOCUMENT` varchar(20) DEFAULT NULL COMMENT 'Sales Document',
  `DELIVERYDATE` varchar(10) DEFAULT NULL COMMENT 'Delivery Date (raw dari SAP, bisa 0000-00-00)',
  `REQUIREDQUANTITY` decimal(20,3) DEFAULT NULL COMMENT 'Required Quantity',
  `FISCALYEAR` varchar(4) DEFAULT NULL COMMENT 'Fiscal Year',
  `FISCALMONTH` varchar(2) DEFAULT NULL COMMENT 'Fiscal Month (2 digit dari API filter)',
  `FISYR` varchar(4) DEFAULT NULL COMMENT 'Fiscal Year of Sync',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_dobyso_salesdoc` (`SALESDOCUMENT`),
  KEY `idx_dobyso_fiscalmonth` (`FISCALMONTH`),
  KEY `idx_dobyso_fisyr` (`FISYR`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
```

Catatan: `DELIVERYDATE` sengaja bertipe **varchar(10)** (bukan `date`) karena SAP mengembalikan zero-date `0000-00-00` untuk dokumen yang belum punya tanggal delivery; strict SQL mode MySQL menolak `0000-00-00` pada kolom bertipe `date`. Nilai disimpan apa adanya dari SAP.

---

## Alur Sync

### 1. Sync Manual (RptsapController `store()`)

1. User memilih tahun + checklist **DO by SO (ZFM_RF_GET_DOBYSO)** di halaman filter `rptsap`, lalu klik Execute.
2. `RptsapController::runYearlySync()` membuat record `rpt_sync_status` baru dengan `report_type = 'Z_GET_DOBYSO'` dan `sync_month` (status `pending`).
3. Dispatch `SapDoBySoSyncJob` dengan parameter bulan ke queue `default`.
4. User diarahkan ke halaman status (`rptsap.status`).

### 2. Sync Harian (SapDailySync)

Command `sap:daily-sync` memanggil `runYearlySync()` dengan **bulan berjalan**, sehingga `SapDoBySoSyncJob` hanya mengambil data bulan tersebut.

### 3. Auto Dispatch (DispatchPendingSync)

Command `sap:dispatch-pending` mengenali `report_type = 'Z_GET_DOBYSO'` dan me-redispatch `SapDoBySoSyncJob` untuk sync yang stuck dalam status `pending`.

### 4. SapDoBySoSyncJob

Mengikuti pola `SapOnHandSyncJob` (bulanan):

1. Cek status sync masih `pending` (jika tidak, exit).
2. Update status menjadi `processing`.
3. **Delete data `rpt_et_getdobyso`** untuk `FISYR` tahun tersebut (atau `FISYR` + `FISCALMONTH` untuk sync per bulan) — simple replace logic.
4. Loop bulan (`01`-`12`, atau satu bulan jika `sync_month` diberikan), panggil endpoint `ZFM_RF_GET_DOBYSO` dengan `IP_YEAR` + `IP_MONTH`, retry 3x (backoff 2s/4s).
5. Ekstrak baris dari key `ET_DATA` (fallback: `data`, atau array penuh).
6. Insert ber-batch (chunk 100) dengan pembersihan memori tiap 10 chunk.
7. Update progres `rpt_sync_status` (total_records / processed_records).
8. Update status menjadi `completed` (atau `failed` jika semua bulan gagal).

Konfigurasi job: `timeout = 3600`, `tries = 3`, `backoff = 60`.

Mapping kolom di `convertSapRowToDbFormat`: `SALESDOCUMENT`, `DELIVERYDATE` (raw, string kosong → null), `REQUIREDQUANTITY` (parseDecimal), `FISCALYEAR`, `FISCALMONTH`, `FISYR`.

---

## Perubahan UI

### `rptsap` Filter Page

Checklist endpoint bertambah: **DO by SO (ZFM_RF_GET_DOBYSO)**. Catatan bulanan diperbarui menjadi "Sales On Hand, DO by SO & Customer Master".

### `rptsap` Status Page (`status.blade.php`)

Data preview menampilkan kolom DO by SO (Sales Document, Deliver Date, Required Qty, Fiscal Year, Fiscal Month) ketika `report_type === 'Z_GET_DOBYSO'`. Deliver date `0000-00-00` / kosong ditampilkan sebagai `-`.

### `rptsap` Status List (`status_list.blade.php`)

Label `DO by SO` untuk `report_type = 'Z_GET_DOBYSO'` (di PHP array dan JS object).

---

## Catatan Penting

- **Belum bisa di-test karena function belum rilis di SAP** (per `prompts/prompt2.txt`): endpoint `ZFM_RF_GET_DOBYSO` pada SAP produksi (client 300) kemungkinan masih mengembalikan error `Invalid Function. FL-E-046` seperti `ZFM_RF_GET_ONHAND` saat awal. Job membaca kredensial dari `.env` (`SAP_BASE_URL`, `SAP_CLIENT`, `SAP_USER`, `SAP_PASSWORD`) — pastikan function sudah di-deploy ke server produksi sebelum sync produksi dijalankan.
- Endpoint yang diberikan user untuk uji manual:
  `https://fiori.spunindo.com/sap/bc/zsr_jsonhd/ZFM_RF_GET_DOBYSO?sap-client=300&sap-user=JKT-1&sap-password=jabaran123!&sap-language=EN&format=json&IP_YEAR=2026&IP_MONTH=06`
- Pola penyimpanan memakai **simple replace** per tahun (data lama untuk `FISYR` yang sama dihapus dulu), konsisten dengan job SAP lain.
- `FISCALMONTH` di-response SAP berupa 2 digit (`09`) — kolom DB varchar(2), nilai disimpan apa adanya.

---

## Status Verifikasi

- `php -l` pass (job, controller, commands, migration).
- Migration `2026_08_06_100000_create_rpt_et_getdobyso_table` berhasil dijalankan; struktur tabel diverifikasi via query DB.
- `php artisan view:cache` pass.
- Test jalur dispatch (tinker): `runYearlySync(2026, 'system', ['Z_GET_DOBYSO'], '08')` membuat record `rpt_sync_status` (`report_type=Z_GET_DOBYSO`, `sync_month=08`, `status=pending`) dan me-queue `SapDoBySoSyncJob`; record test dibersihkan.
- **Pull data SAP belum diuji** karena function belum rilis di SAP.
