# D1: Review perubahan persistence Maintenance

Status: DISETUJUI pada 2026-10-14 melalui jawaban pengguna "ya setuju" terhadap review konkret D1. Persetujuan mencakup model, file migration, ERD, generation dan pengujian terisolasi; deployment database aplikasi tetap terpisah.

## Perubahan yang diminta

1. Tambahkan `version Int @default(0) @db.UnsignedInt` pada WorkOrder.
2. Tambahkan field identik pada MaintenancePlan.
3. Tambahkan model MaintenanceRequest di bawah, mengikuti pola InventoryRequest yang sudah ada.
4. Tambahkan relasi balik `maintenanceRequests MaintenanceRequest[]` pada User. Ini hanya relasi Prisma, tidak menambah kolom tabel User.
5. Perbarui ERD untuk dua field version dan relasi User–MaintenanceRequest. Tidak ada field target baru atau penghapusan technicianId.

```prisma
model MaintenanceRequest {
  id          String   @id @default(cuid()) @db.VarChar(30)
  key         String   @unique @db.VarChar(100)
  actorId     String   @db.VarChar(30)
  operation   String   @db.VarChar(100)
  payloadHash String   @db.Char(64)
  result      Json
  createdAt   DateTime @default(now()) @db.DateTime(3)
  actor       User     @relation(fields: [actorId], references: [id], onDelete: Restrict)

  @@index([actorId, createdAt])
}
```

## Rancangan migration SQL

SQL ini bahan review, bukan file migration yang sudah dijalankan.

```sql
ALTER TABLE `WorkOrder`
  ADD COLUMN `version` INTEGER UNSIGNED NOT NULL DEFAULT 0;
ALTER TABLE `MaintenancePlan`
  ADD COLUMN `version` INTEGER UNSIGNED NOT NULL DEFAULT 0;

CREATE TABLE `MaintenanceRequest` (
  `id` VARCHAR(30) NOT NULL,
  `key` VARCHAR(100) NOT NULL,
  `actorId` VARCHAR(30) NOT NULL,
  `operation` VARCHAR(100) NOT NULL,
  `payloadHash` CHAR(64) NOT NULL,
  `result` JSON NOT NULL,
  `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  PRIMARY KEY (`id`),
  UNIQUE INDEX `MaintenanceRequest_key_key` (`key`),
  INDEX `MaintenanceRequest_actorId_createdAt_idx` (`actorId`, `createdAt`),
  CONSTRAINT `MaintenanceRequest_actorId_fkey`
    FOREIGN KEY (`actorId`) REFERENCES `User` (`id`)
    ON DELETE RESTRICT ON UPDATE CASCADE
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

## Perubahan ERD

Tambahkan atribut version pada node WorkOrder dan MaintenancePlan, lalu node/relasi berikut pada diagram yang ada:

```mermaid
erDiagram
  User ||..o{ MaintenanceRequest : actorId
  MaintenanceRequest {
    String id PK
    String key UK
    String actorId FK
    String operation
    String payloadHash
    Json result
    DateTime createdAt
  }
```

## Mengapa dibutuhkan

- Dua pengguna membaca version 0: simpan pertama mensyaratkan version 0 dan menaikkannya ke 1. Simpan kedua dengan version 0 mendapat 409, sehingga tidak menimpa hasil pertama.
- Satu aksi memiliki kunci UUID yang dipertahankan saat retry. MaintenanceRequest menyimpan aktor, operasi, hash payload tervalidasi dan hasil publik; key identik dengan aktor/operasi/payload berbeda mendapat 409.
- Simpan hasil request, domain writes dan audit dalam transaksi yang sama. Bila audit/domain gagal, semuanya rollback; bila respons hilang setelah commit, retry mengembalikan hasil tersimpan tanpa WO/ledger/history baru.
- Kunci disimpan sebagai hash SHA-256 dalam field key agar perbandingan tidak bergantung pada kolasi case-insensitive. Hasil tidak menyimpan cookie, token, password, atau informasi keuangan. Replay dibaca setelah otorisasi dan pemeriksaan akun aktif.
- Unique key menyelesaikan balapan dua request identik: transaksi yang kalah rollback, kemudian baca hasil committed dan cocokkan identitas/payload. Tangani duplicate pada constraint lain sebagai konflik domain, bukan sukses replay sembarang.
- Tidak ada pembersihan otomatis request pada MVP agar retry lama tidak menghasilkan pekerjaan ulang. Data request ini internal dan tidak menjadi tabel daftar pekerjaan.
- WO dari laporan lama tetap berlaku dengan version awal 0. Nilai historis technicianId dipertahankan tetapi tidak menjadi pembatas hak eksekusi. Pembentukan WO PM tetap memakai unique (planId, scheduledFor) yang sudah ada.

## Verifikasi setelah persetujuan

Uji migration pada database terisolasi berisi laporan diterima, WO lama, plan, dan stock movement. Pastikan jumlah/relasi tidak berubah; default version 0; foreign key dan unique request aktif. Uji stale edit, retry setelah commit, payload berbeda, aktor berbeda, audit rollback, serta permintaan bersamaan. Belum ada klaim hasil tes implementasi pada tahap review.

Persetujuan dokumen ini mengizinkan perubahan model, migration file, ERD, generation dan pengujian terisolasi sesuai D1. Penerapan migration pada database aplikasi serta pengaktifan scheduler tetap menunggu instruksi deployment terpisah.
