# LSM Web Portal - Dokumentasi Desain Sistem

**Versi:** 1.0  
**Tanggal:** 27 Januari 2026  
**Aplikasi:** LSM (Laporan Stok Malam) Web Portal - Bakmi GM

---

## Daftar Isi
1. [Use Case Diagram](#1-use-case-diagram)
2. [Activity Diagram](#2-activity-diagram)
3. [Entity Relationship Diagram (ERD)](#3-entity-relationship-diagram-erd)
4. [Desain Keamanan](#4-desain-keamanan)

---

## 1. Use Case Diagram

### 1.1 Aktor Sistem

| Aktor | Deskripsi | Tanggung Jawab |
|-------|-----------|----------------|
| **Staff Store** | Pengguna di tingkat toko/restoran | Input stok harian, buat permintaan barang ad-hoc |
| **SDP/HO** | Staff Head Office/Supply Distribution Planning | Kelola master data, upload forecast, monitor operasional |
| **PPIC** | Production Planning & Inventory Control | Validasi SPB, monitor pengiriman, approve pembatalan |
| **Admin** | Administrator sistem | Kelola user, role, permission, konfigurasi sistem |
| **Sistem QAD** | Sistem ERP eksternal | Terima order CSV dari LSM |


### 1.2 Use Case Utama

```
┌─────────────────────────────────────────────────────────────────────────┐
│                        LSM WEB PORTAL SYSTEM                            │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌──────────┐                                                          │
│  │  Staff   │                                                          │
│  │  Store   │──────► UC-01: Login & Pilih Store                       │
│  └──────────┘        UC-02: Input Stock Opname Harian                 │
│       │              UC-03: Generate SPB Otomatis                      │
│       │              UC-04: Buat SPB Ad-hoc (Tambahan)                 │
│       │              UC-05: Lihat History SPB                          │
│       │              UC-06: Request Pembatalan SPB                     │
│       │                                                                 │
│  ┌──────────┐                                                          │
│  │ SDP/HO   │──────► UC-07: Kelola Master Raw Material                │
│  └──────────┘        UC-08: Kelola Master Store                       │
│       │              UC-09: Upload Forecast Bulanan                    │
│       │              UC-10: Kelola Item Conversion                     │
│       │              UC-11: Kelola FSTR (Forecast to Stock Ratio)     │
│       │              UC-12: Kelola Range DOI                           │
│       │              UC-13: Kelola Shipment Schedule                   │
│       │              UC-14: Kelola Holiday Calendar                    │
│       │              UC-15: Lihat Laporan LSM                          │
│       │              UC-16: Lihat Laporan DOI                          │
│       │              UC-17: Upload Master Store dari QAD (Excel)      │
│       │              UC-18: Upload Master Menu dari QAD (Excel)       │
│       │                                                                 │
│  ┌──────────┐                                                          │
│  │   PPIC   │──────► UC-19: Approve/Reject Pembatalan SPB             │
│  └──────────┘        UC-20: Monitor Status SPB                        │
│       │              UC-21: Download CSV untuk QAD                     │
│       │              UC-22: Lihat Laporan SPB                          │
│       │                                                                 │
│  ┌──────────┐                                                          │
│  │  Admin   │──────► UC-23: Kelola User                               │
│  └──────────┘        UC-24: Kelola Role & Permission                  │
│       │              UC-25: Assign Store ke User                       │
│       │              UC-26: Session Management                         │
│       │              UC-27: Kelola Parameter Global                    │
│       │              UC-28: Lihat System Log                           │
│       │                                                                 │
│  ┌──────────┐                                                          │
│  │ Sistem   │◄─────  UC-28: Terima CSV Order (SPB)                    │
│  │   QAD    │                                                          │
│  └──────────┘                                                          │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
```


### 1.3 Detail Use Case Kritis

#### UC-02: Input Stock Opname Harian

**Aktor:** Staff Store  
**Prasyarat:** User sudah login dan memilih store  
**Alur Normal:**
1. Staff Store membuka halaman Stock Opname
2. Sistem cek apakah SO hari ini sudah ada
3. Jika belum ada, sistem auto-load raw materials untuk store tersebut
4. Staff input sisa utuh dan sisa pakai untuk setiap item
5. Sistem auto-save setiap field yang diinput (real-time)
6. Staff dapat melihat change history untuk audit
7. Staff klik "Save" untuk menyimpan draft
8. Staff klik "Create SPB" untuk generate SPB otomatis

**Business Rules:**
- Input hanya diizinkan untuk tanggal hari ini (kecuali user punya flag_backdate_so)
- Edit window ditutup jam 11:00 pagi hari berikutnya (H+1)
- Sistem implement locking mechanism untuk prevent concurrent editing
- Heartbeat mechanism untuk maintain lock selama editing


#### UC-03: Generate SPB Otomatis

**Aktor:** Staff Store  
**Prasyarat:** Stock Opname sudah disimpan  
**Alur Normal:**
1. Staff klik "Create SPB" dari halaman Stock Opname
2. Sistem hitung kebutuhan berdasarkan:
   - Forecast quantity untuk periode mendatang
   - Current stock dari SO
   - FSTR (Forecast to Stock Ratio)
   - Minimal order & multiple order constraints
3. Sistem generate SPB dengan status "Draft"
4. Staff review dan adjust quantity jika perlu
5. Staff submit SPB
6. Sistem generate CSV file untuk integrasi QAD
7. Status SPB berubah menjadi "Submitted"

**Business Rules:**
- Hanya 1 SPB Regular per SO
- SPB Tambahan (Ad-hoc) bisa multiple
- Perhitungan order: (Forecast × FSTR) - Current Stock
- Apply minimal_order dan multiple_order constraints
- Gunakan NumberingFormat untuk generate SPB number
- CSV file di-generate untuk dikirim ke QAD

#### UC-17: Upload Master Store dari QAD (Excel)

**Aktor:** SDP/HO  
**Prasyarat:** User memiliki permission untuk manage stores  
**Alur Normal:**
1. SDP download template Excel stores
2. SDP export data stores dari QAD
3. SDP isi/update data di template Excel
4. SDP upload file Excel ke LSM
5. Sistem validasi format dan data
6. Sistem tampilkan preview data
7. SDP confirm import
8. Sistem insert/update master stores

**Business Rules:**
- Store code harus unique
- Validasi mandatory fields
- Update jika store code sudah exist
- Insert jika store code baru

#### UC-18: Upload Master Menu dari QAD (Excel)

**Aktor:** SDP/HO  
**Prasyarat:** User memiliki permission untuk manage menus  
**Alur Normal:**
1. SDP download template Excel menus
2. SDP export data menu dari QAD
3. SDP isi/update data di template Excel
4. SDP upload file Excel ke LSM
5. Sistem validasi format dan data
6. Sistem tampilkan preview data
7. SDP confirm import
8. Sistem insert/update master menus

**Business Rules:**
- Menu code harus unique
- Validasi mandatory fields
- Update jika menu code sudah exist
- Insert jika menu code baru


#### UC-09: Upload Forecast Bulanan

**Aktor:** SDP/HO  
**Prasyarat:** User memiliki permission untuk manage forecast  
**Alur Normal:**
1. SDP download template Excel forecast
2. SDP isi forecast untuk setiap store, raw material, dan tanggal
3. SDP upload file Excel ke sistem
4. Sistem validasi format dan data
5. Sistem tampilkan preview data yang akan diimport
6. SDP confirm import
7. Sistem simpan forecast dengan status "Draft"
8. SDP review dan approve forecast
9. Status berubah menjadi "Confirmed"

**Business Rules:**
- Forecast per store per bulan (tidak boleh duplicate)
- Format: Store, Raw Material, Date, Quantity
- Validasi: Store & Raw Material harus exist di master
- Dapat replace data jika forecast sudah ada
- Hanya forecast "Confirmed" yang digunakan untuk perhitungan SPB

---

## 2. Activity Diagram

### 2.1 Proses Bisnis Utama: Daily Stock Opname & SPB Generation


```
┌─────────────────────────────────────────────────────────────────────────┐
│           ACTIVITY DIAGRAM: Daily Stock Opname & SPB Generation         │
└─────────────────────────────────────────────────────────────────────────┘

    Staff Store                 Sistem                      Database
        │                         │                            │
        │  Login & Pilih Store    │                            │
        ├────────────────────────►│                            │
        │                         │  Cek Session & Permission  │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │  Buka Stock Opname      │                            │
        ├────────────────────────►│                            │
        │                         │  Cek SO Hari Ini           │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │                    ┌────┴────┐                       │
        │                    │ SO Ada? │                       │
        │                    └────┬────┘                       │
        │                         │                            │
        │              ┌──────────┼──────────┐                 │
        │              │ Ya                  │ Tidak           │
        │              │                     │                 │
        │              │                     │  Auto-load      │
        │              │                     │  Raw Materials  │
        │              │                     ├────────────────►│
        │              │                     │◄────────────────┤
        │              │                     │  Create SO      │
        │              │                     ├────────────────►│
        │              │                     │◄────────────────┤
        │              │                     │                 │
        │              └──────────┬──────────┘                 │
        │                         │                            │
        │                         │  Lock SO untuk Editing     │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │  Tampilkan Form SO      │                            │
        │◄────────────────────────┤                            │
        │                         │                            │
        │  Input Sisa Utuh/Pakai  │                            │
        ├────────────────────────►│                            │
        │                         │  Auto-save Field           │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │  Log Change History        │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │  (Ulangi untuk semua item)                          │
        │                         │                            │
        │  Klik "Create SPB"      │                            │
        ├────────────────────────►│                            │
        │                         │  Validasi Data SO          │
        │                         │                            │
        │                         │  Get Forecast Data         │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │                         │  Get FSTR Data             │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │                         │  Hitung Kebutuhan:         │
        │                         │  Order = (Forecast × FSTR) │
        │                         │          - Current Stock   │
        │                         │                            │
        │                         │  Apply Constraints:        │
        │                         │  - Minimal Order           │
        │                         │  - Multiple Order          │
        │                         │                            │
        │                         │  Generate SPB Number       │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │                         │  Create SPB Header         │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │                         │  Create SPB Details        │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │                         │  Update Current Stock      │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │                         │  Unlock SO                 │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │  Tampilkan SPB          │                            │
        │◄────────────────────────┤                            │
        │                         │                            │
        │  Review & Submit SPB    │                            │
        ├────────────────────────►│                            │
        │                         │  Generate CSV File         │
        │                         │                            │
        │                         │  Update Status = Submitted │
        │                         ├───────────────────────────►│
        │                         │◄───────────────────────────┤
        │                         │                            │
        │  Konfirmasi Success     │                            │
        │◄────────────────────────┤                            │
        │                         │                            │
```


### 2.2 Proses: Upload & Approve Forecast

```
┌─────────────────────────────────────────────────────────────────────────┐
│              ACTIVITY DIAGRAM: Upload & Approve Forecast                │
└─────────────────────────────────────────────────────────────────────────┘

    SDP/HO                      Sistem                      Database
        │                         │                            │
        │  Download Template      │                            │
        ├────────────────────────►│                            │
        │◄────────────────────────┤                            │
        │                         │                            │
        │  Isi Data Forecast      │                            │
        │  (Excel)                │                            │
        │                         │                            │
        │  Upload File Excel      │                            │
        ├────────────────────────►│                            │
        │                         │  Validasi Format File      │
        │                         │                            │
        │                    ┌────┴────┐                       │
        │                    │ Valid?  │                       │
        │                    └────┬────┘                       │
        │                         │                            │
        │              ┌──────────┼──────────┐                 │
        │              │ Tidak               │ Ya              │
        │              │                     │                 │
        │  Error Message                    │  Parse Excel    │
        │◄────────────┤                     │                 │
        │              │                     │  Validasi Data: │
        │              │                     │  - Store exist  │
        │              │                     │  - Raw Material │
        │              │                     │  - Date format  │
        │              │                     │  - Qty numeric  │
        │              │                     │                 │
        │              │                ┌────┴────┐            │
        │              │                │ Valid?  │            │
        │              │                └────┬────┘            │
        │              │                     │                 │
        │              │          ┌──────────┼──────────┐      │
        │              │          │ Tidak              │ Ya    │
        │              │          │                    │       │
        │              │  Show Errors                  │       │
        │              │◄─────────┤                    │       │
        │              │                                │       │
        │              └────────────────────────────────┘       │
        │                                              │        │
        │  Tampilkan Preview Data                     │        │
        │◄────────────────────────────────────────────┤        │
        │                                              │        │
        │  Confirm Import                              │        │
        ├─────────────────────────────────────────────►│        │
        │                                              │        │
        │                                         ┌────┴────┐   │
        │                                         │ Forecast│   │
        │                                         │ Exist?  │   │
        │                                         └────┬────┘   │
        │                                              │        │
        │                                   ┌──────────┼────────┐
        │                                   │ Ya               │ Tidak
        │                                   │                  │
        │                                   │  Replace Data    │  Insert New
        │                                   ├─────────────────►│
        │                                   │◄─────────────────┤
        │                                   │                  │
        │                                   └──────────┬───────┘
        │                                              │
        │                                              │  Create Forecast
        │                                              │  Header (Draft)
        │                                              ├────────────────►│
        │                                              │◄────────────────┤
        │                                              │
        │                                              │  Create Forecast
        │                                              │  Details
        │                                              ├────────────────►│
        │                                              │◄────────────────┤
        │                                              │
        │  Success Message                             │
        │◄─────────────────────────────────────────────┤
        │                                              │
        │  Review Forecast                             │
        ├─────────────────────────────────────────────►│
        │                                              │  Get Forecast
        │                                              ├────────────────►│
        │                                              │◄────────────────┤
        │  Tampilkan Data                              │
        │◄─────────────────────────────────────────────┤
        │                                              │
        │  Approve Forecast                            │
        ├─────────────────────────────────────────────►│
        │                                              │  Update Status
        │                                              │  = Confirmed
        │                                              ├────────────────►│
        │                                              │◄────────────────┤
        │  Konfirmasi                                  │
        │◄─────────────────────────────────────────────┤
        │                                              │
```


### 2.3 Proses: Request & Approve Pembatalan SPB

```
┌─────────────────────────────────────────────────────────────────────────┐
│         ACTIVITY DIAGRAM: Request & Approve Pembatalan SPB              │
└─────────────────────────────────────────────────────────────────────────┘

    Staff Store              Sistem                PPIC              Database
        │                      │                     │                  │
        │  Request Cancel SPB  │                     │                  │
        ├─────────────────────►│                     │                  │
        │                      │  Validasi:          │                  │
        │                      │  - Status Submitted │                  │
        │                      │    atau Approved    │                  │
        │                      │                     │                  │
        │                 ┌────┴────┐                │                  │
        │                 │ Valid?  │                │                  │
        │                 └────┬────┘                │                  │
        │                      │                     │                  │
        │           ┌──────────┼──────────┐          │                  │
        │           │ Tidak              │ Ya        │                  │
        │           │                    │           │                  │
        │  Error    │                    │  Create   │                  │
        │◄──────────┤                    │  Cancel   │                  │
        │           │                    │  Request  │                  │
        │           │                    ├──────────────────────────────►│
        │           │                    │◄──────────────────────────────┤
        │           │                    │           │                  │
        │           │                    │  Update   │                  │
        │           │                    │  SPB Status                  │
        │           │                    │  = Cancel │                  │
        │           │                    │  Requested│                  │
        │           │                    ├──────────────────────────────►│
        │           │                    │◄──────────────────────────────┤
        │           │                    │           │                  │
        │           │                    │  Send     │                  │
        │           │                    │  Notif    │                  │
        │           │                    │  to PPIC  │                  │
        │           │                    ├──────────►│                  │
        │           │                    │           │                  │
        │  Success  │                    │           │                  │
        │◄──────────┤                    │           │                  │
        │           │                    │           │                  │
        │           └────────────────────┘           │                  │
        │                                             │                  │
        │                                             │  Review Request  │
        │                                             │                  │
        │                                             │  Get Cancel      │
        │                                             │  Request Details │
        │                                             ├─────────────────►│
        │                                             │◄─────────────────┤
        │                                             │                  │
        │                                        ┌────┴────┐             │
        │                                        │ Approve │             │
        │                                        │ atau    │             │
        │                                        │ Reject? │             │
        │                                        └────┬────┘             │
        │                                             │                  │
        │                                  ┌──────────┼──────────┐       │
        │                                  │ Approve            │ Reject │
        │                                  │                    │       │
        │                                  │  Update Status     │  Update│
        │                                  │  = Cancelled       │  Status│
        │                                  │                    │  = Sub │
        │                                  │  Restore Stock     │  mitted│
        │                                  │  if needed         │       │
        │                                  ├───────────────────►│       │
        │                                  │◄───────────────────┤       │
        │                                  │                    │       │
        │                                  │  Send Notif        │  Send │
        │                                  │  to Store          │  Notif│
        │  Notifikasi Approved             ├────────────────────┤       │
        │◄─────────────────────────────────┤                    │       │
        │                                  │                    │       │
        │                                  └────────────────────┘       │
        │                                                                │
```


---

## 3. Entity Relationship Diagram (ERD)

### 3.1 Entitas Utama

Sistem LSM memiliki 30+ tabel yang dikelompokkan menjadi:

**Master Data:**
- users
- roles
- permissions
- m_stores
- m_raw_materials
- m_item_conversions
- m_menus
- m_range_dois
- m_fstrs & m_fstr_details
- m_reason_adjustments
- m_sales_types
- m_periods
- m_holidays
- m_numbering_formats
- m_shipment_suppliers
- m_shipment_deliveries
- m_armada_types
- m_parameter_globals
- m_target_sisa_malam

**Transactional Data:**
- t_stock_opnames & t_stock_opname_details
- t_item_requests & t_item_request_details
- t_item_request_cancellations
- t_forecasts & t_forecast_details
- t_stock_movements
- t_current_stocks
- t_qad_sync_logs

**Mapping Tables:**
- users_stores (User ↔ Store)
- m_store_raw_materials (Store ↔ Raw Material)
- model_has_roles (User ↔ Role)
- model_has_permissions (User ↔ Permission)
- role_has_permissions (Role ↔ Permission)


### 3.2 ERD - Core Entities

```
┌─────────────────────────────────────────────────────────────────────────┐
│                    ENTITY RELATIONSHIP DIAGRAM                          │
│                         LSM Web Portal                                  │
└─────────────────────────────────────────────────────────────────────────┘

┌──────────────────┐         ┌──────────────────┐
│     users        │         │     roles        │
├──────────────────┤         ├──────────────────┤
│ PK id            │         │ PK id            │
│    username      │         │    name          │
│    password      │         │    guard_name    │
│    fullname      │         │    created_at    │
│    email         │         │    updated_at    │
│    status        │         └──────────────────┘
│    flag_backdate │                │
│    current_sess  │                │ N
│    last_login_at │                │
│    created_by    │         ┌──────┴───────────┐
│    updated_by    │         │ model_has_roles  │
└──────────────────┘         ├──────────────────┤
         │                   │ FK role_id       │
         │ N                 │ FK model_id      │
         │                   │    model_type    │
         ├───────────────────┤                  │
         │                   └──────────────────┘
         │
         │ N                 ┌──────────────────┐
         │                   │  permissions     │
         ├───────────────────┤──────────────────┤
         │                   │ PK id            │
         │                   │    name          │
         │                   │    guard_name    │
         │                   └──────────────────┘
         │
         │ N
         │
┌────────┴─────────┐
│  users_stores    │         ┌──────────────────┐
├──────────────────┤         │    m_stores      │
│ FK user_id       │    N    ├──────────────────┤
│ FK store_id      ├─────────┤ PK id            │
│    created_by    │    1    │    code          │
│    updated_by    │         │    name          │
└──────────────────┘         │    store_type    │
                             │    document_type │
                             │    address       │
                             │    pic           │
                             │    status        │
                             │    created_by    │
                             │    updated_by    │
                             └──────────────────┘
                                      │
                                      │ 1
                                      │
                                      │ N
                             ┌────────┴─────────┐
                             │ t_stock_opnames  │
                             ├──────────────────┤
                             │ PK id            │
                             │    so_number     │
                             │ FK store_id      │
                             │    so_date       │
                             │    status        │
                             │    editing_by    │
                             │    editing_at    │
                             │    created_by    │
                             │    updated_by    │
                             └──────────────────┘
                                      │
                                      │ 1
                                      │
                                      │ N
                             ┌────────┴──────────────┐
                             │ t_stock_opname_details│
                             ├───────────────────────┤
                             │ PK id                 │
                             │ FK so_id              │
                             │ FK raw_material_id    │
                             │    sisa_utuh          │
                             │    sisa_pakai         │
                             │    total_sisa         │
                             │    adjustment_qty     │
                             │    adjustment_reason  │
                             │    notes              │
                             └───────────────────────┘
```


### 3.3 ERD - Transaction Flow

```
┌──────────────────┐
│  m_raw_materials │
├──────────────────┤
│ PK id            │
│    code          │
│    name          │
│    uom           │
│    konversi_*    │
│    inv_matrix    │
│    lsm_flag      │
│    spb_flag      │
│    tipe_barang   │
│ FK period_id     │
│    minimal_order │
│    multiple_order│
│    suggest_ratio │
│    latest_ratio  │
│    created_by    │
│    updated_by    │
└──────────────────┘
         │
         │ 1
         │
         │ N
┌────────┴──────────────┐         ┌──────────────────┐
│ m_store_raw_materials │    N    │    m_stores      │
├───────────────────────┤─────────┤──────────────────┤
│ PK id                 │    1    │ PK id            │
│ FK store_id           │         │    code          │
│ FK raw_material_id    │         │    name          │
│    is_active          │         └──────────────────┘
│    min_stock          │                  │
│    max_stock          │                  │ 1
│    reorder_point      │                  │
│    notes              │                  │ N
│    created_by         │         ┌────────┴─────────┐
│    updated_by         │         │ t_item_requests  │
└───────────────────────┘         ├──────────────────┤
         │                        │ PK id            │
         │                        │    spb_number    │
         │                        │ FK store_id      │
         │                        │ FK stock_opname  │
         │                        │    request_type  │
         │                        │    request_date  │
         │                        │    delivery_date │
         │                        │    status        │
         │                        │    csv_generated │
         │                        │    created_by    │
         │                        │    updated_by    │
         │                        └──────────────────┘
         │                                 │
         │                                 │ 1
         │                                 │
         │                                 │ N
         │                        ┌────────┴──────────────┐
         │                        │ t_item_request_details│
         │                        ├───────────────────────┤
         │                        │ PK id                 │
         │                        │ FK item_request_id    │
         │                        │ FK raw_material_id    │
         │                        │    qty_requested      │
         │                        │    qty_approved       │
         │                        │    uom                │
         │                        │    notes              │
         │                        └───────────────────────┘
         │
         │ N
         │
┌────────┴─────────┐
│   t_forecasts    │
├──────────────────┤
│ PK id            │
│ FK store_id      │
│    year          │
│    month         │
│    forecast_num  │
│    status        │
│    upload_date   │
│    created_by    │
│    updated_by    │
└──────────────────┘
         │
         │ 1
         │
         │ N
┌────────┴──────────────┐
│  t_forecast_details   │
├───────────────────────┤
│ PK id                 │
│ FK forecast_header_id │
│ FK raw_material_id    │
│ FK store_id           │
│    forecast_date      │
│    qty                │
│    notes              │
└───────────────────────┘
```


### 3.4 ERD - Supporting Entities

```
┌──────────────────┐         ┌──────────────────┐
│ m_item_conversions│        │     m_fstrs      │
├──────────────────┤         ├──────────────────┤
│ PK id            │         │ PK id            │
│ FK raw_material  │         │    code          │
│    from_uom      │         │    name          │
│    to_uom        │         │    description   │
│    conversion    │         │    created_by    │
│    is_active     │         │    updated_by    │
│    created_by    │         └──────────────────┘
│    updated_by    │                  │
└──────────────────┘                  │ 1
                                      │
┌──────────────────┐                  │ N
│   m_range_dois   │         ┌────────┴─────────┐
├──────────────────┤         │ m_fstr_details   │
│ PK id            │         ├──────────────────┤
│    min_doi       │         │ PK id            │
│    max_doi       │         │ FK fstr_id       │
│    description   │         │ FK raw_material  │
│    color_code    │         │    ratio         │
│    created_by    │         │    notes         │
│    updated_by    │         │    created_by    │
└──────────────────┘         │    updated_by    │
                             └──────────────────┘

┌──────────────────┐         ┌──────────────────┐
│  m_holidays      │         │   m_periods      │
├──────────────────┤         ├──────────────────┤
│ PK id            │         │ PK id            │
│    holiday_date  │         │    code          │
│    name          │         │    name          │
│    description   │         │    start_date    │
│    is_recurring  │         │    end_date      │
│    created_by    │         │    is_active     │
│    updated_by    │         │    created_by    │
└──────────────────┘         │    updated_by    │
                             └──────────────────┘

┌──────────────────┐         ┌──────────────────┐
│ m_numbering_fmt  │         │ m_sales_types    │
├──────────────────┤         ├──────────────────┤
│ PK id            │         │ PK id            │
│ FK store_id      │         │    code          │
│    doc_type      │         │    name          │
│    prefix        │         │    description   │
│    format        │         │    is_active     │
│    last_number   │         │    created_by    │
│    created_by    │         │    updated_by    │
│    updated_by    │         └──────────────────┘
└──────────────────┘

┌──────────────────┐         ┌──────────────────┐
│ m_shipment_supp  │         │ m_armada_types   │
├──────────────────┤         ├──────────────────┤
│ PK id            │         │ PK id            │
│    code          │         │    code          │
│    name          │         │    name          │
│    contact_name  │         │    capacity      │
│    contact_phone │         │    description   │
│    address       │         │    created_by    │
│    created_by    │         │    updated_by    │
│    updated_by    │         └──────────────────┘
└──────────────────┘
         │
         │ 1
         │
         │ N
┌────────┴─────────┐
│ m_shipment_deliv │
├──────────────────┤
│ PK id            │
│ FK store_id      │
│ FK supplier_id   │
│ FK armada_type   │
│    schedule_day  │
│    schedule_time │
│    type          │
│    created_by    │
│    updated_by    │
└──────────────────┘
```


### 3.5 Relasi Kunci

| Relasi | Kardinalitas | Deskripsi |
|--------|--------------|-----------|
| User → Store | Many-to-Many | User dapat akses multiple stores via users_stores |
| User → Role | Many-to-Many | User dapat memiliki multiple roles via model_has_roles |
| Role → Permission | Many-to-Many | Role memiliki multiple permissions via role_has_permissions |
| Store → StockOpname | One-to-Many | Store memiliki banyak stock opname harian |
| StockOpname → StockOpnameDetail | One-to-Many | SO header memiliki banyak detail items |
| StockOpname → ItemRequest | One-to-Many | SO dapat generate multiple SPB (1 Regular + N Ad-hoc) |
| Store → ItemRequest | One-to-Many | Store memiliki banyak SPB |
| ItemRequest → ItemRequestDetail | One-to-Many | SPB header memiliki banyak detail items |
| Store → Forecast | One-to-Many | Store memiliki forecast per bulan |
| Forecast → ForecastDetail | One-to-Many | Forecast header memiliki detail per item per hari |
| RawMaterial → Store | Many-to-Many | Raw material dapat digunakan di multiple stores via m_store_raw_materials |
| RawMaterial → ItemConversion | One-to-Many | Raw material dapat memiliki multiple konversi UOM |
| RawMaterial → FstrDetail | One-to-Many | Raw material memiliki FSTR ratio |
| Store → ShipmentDelivery | One-to-Many | Store memiliki jadwal pengiriman |
| ShipmentSupplier → ShipmentDelivery | One-to-Many | Supplier handle multiple deliveries |


---

## 4. Desain Keamanan

### 4.1 Authentication System

#### 4.1.1 Login Flow

```
┌─────────────────────────────────────────────────────────────────────────┐
│                      AUTHENTICATION FLOW                                │
└─────────────────────────────────────────────────────────────────────────┘

    User                    System                  Database
     │                        │                         │
     │  Input Username/Pass   │                         │
     ├───────────────────────►│                         │
     │                        │  Validate Credentials   │
     │                        ├────────────────────────►│
     │                        │◄────────────────────────┤
     │                        │                         │
     │                   ┌────┴────┐                    │
     │                   │ Valid?  │                    │
     │                   └────┬────┘                    │
     │                        │                         │
     │             ┌──────────┼──────────┐              │
     │             │ Tidak              │ Ya            │
     │             │                    │               │
     │  Error      │                    │  Check Status │
     │◄────────────┤                    ├──────────────►│
     │             │                    │◄──────────────┤
     │             │                    │               │
     │             │               ┌────┴────┐          │
     │             │               │ Active? │          │
     │             │               └────┬────┘          │
     │             │                    │               │
     │             │         ┌──────────┼──────────┐    │
     │             │         │ Tidak              │ Ya  │
     │             │         │                    │     │
     │  Inactive   │         │                    │     │
     │  Account    │         │                    │     │
     │◄────────────┼─────────┤                    │     │
     │             │         │                    │     │
     │             │         │                    │  Check Session
     │             │         │                    ├────────────────►│
     │             │         │                    │◄────────────────┤
     │             │         │                    │
     │             │         │               ┌────┴────┐
     │             │         │               │ Session │
     │             │         │               │ Active? │
     │             │         │               └────┬────┘
     │             │         │                    │
     │             │         │         ┌──────────┼──────────┐
     │             │         │         │ Ya                 │ Tidak
     │             │         │         │                    │
     │  Session    │         │         │  Kill Old Session  │  Create
     │  Conflict   │         │         │  (Admin only)      │  Session
     │◄────────────┼─────────┼─────────┤                    │
     │             │         │         │                    │  Update:
     │             │         │         │                    │  - session_id
     │             │         │         │                    │  - last_login
     │             │         │         │                    │  - login_ip
     │             │         │         │                    │  - login_device
     │             │         │         │                    ├────────────►│
     │             │         │         │                    │◄────────────┤
     │             │         │         │                    │
     │             │         │         └────────────────────┘
     │             │         │                              │
     │  Success    │         │                              │
     │  + Redirect │         │                              │
     │◄────────────┴─────────┴──────────────────────────────┤
     │                                                       │
```


#### 4.1.2 Session Management

**Fitur Keamanan Session:**

1. **Single Session Enforcement**
   - User hanya boleh login dari 1 device/browser
   - Session baru akan kill session lama
   - Admin dapat force kill session user lain

2. **Session Tracking**
   ```php
   users table:
   - current_session_id: Laravel session ID
   - last_login_at: Timestamp login terakhir
   - last_login_ip: IP address login
   - last_login_device: User agent browser
   ```

3. **Session Timeout**
   - Idle timeout: 120 menit (config/session.php)
   - Absolute timeout: Sesuai konfigurasi Laravel
   - Auto logout jika tidak ada aktivitas

4. **Admin Session Management**
   - Admin dapat melihat semua active sessions
   - Admin dapat kill session user tertentu
   - Log semua session management actions


### 4.2 Authorization System (RBAC)

#### 4.2.1 Role-Based Access Control

Sistem menggunakan **Spatie Laravel Permission** untuk implementasi RBAC.

**Struktur RBAC:**

```
┌─────────────────────────────────────────────────────────────────────────┐
│                    ROLE-BASED ACCESS CONTROL                            │
└─────────────────────────────────────────────────────────────────────────┘

                            ┌──────────┐
                            │   User   │
                            └────┬─────┘
                                 │
                                 │ has many
                                 │
                            ┌────▼─────┐
                            │   Role   │
                            └────┬─────┘
                                 │
                                 │ has many
                                 │
                            ┌────▼────────┐
                            │ Permission  │
                            └─────────────┘
```

#### 4.2.2 Roles Standar

| Role | Deskripsi | Level Akses |
|------|-----------|-------------|
| **Super Admin** | Administrator sistem penuh | Full access ke semua fitur |
| **Admin** | Administrator operasional | Kelola user, master data, reports |
| **SDP/HO** | Supply Distribution Planning | Kelola forecast, master data, monitor |
| **PPIC** | Production Planning | Approve SPB, monitor delivery |
| **Store Manager** | Manager toko | Full access untuk store yang di-assign |
| **Store Staff** | Staff toko | Input SO, buat SPB untuk store yang di-assign |
| **Viewer** | Read-only user | Hanya lihat reports dan data |


#### 4.2.3 Permission Matrix

| Module | Permission | Super Admin | Admin | SDP/HO | PPIC | Store Mgr | Store Staff | Viewer |
|--------|------------|-------------|-------|--------|------|-----------|-------------|--------|
| **Users** | | | | | | | | |
| - View | users.index | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |
| - Create | users.create | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| - Edit | users.edit | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| - Delete | users.destroy | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| - Session Mgmt | users.session_management | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| **Roles & Permissions** | | | | | | | | |
| - View | roles.index | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| - Manage | roles.store | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| **Master Data** | | | | | | | | |
| - Raw Materials | raw_materials.* | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Stores | stores.* | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Stores Upload Excel | stores.upload_excel | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Item Conversions | item_conversions.* | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Menus | menus.* | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Menus Upload Excel | menus.upload_excel | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - FSTR | fstrs.* | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Range DOI | range_dois.* | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Holidays | holidays.* | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Shipment | shipment_*.* | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| **Transactions** | | | | | | | | |
| - Stock Opname View | stock_opnames.index | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| - SO Create/Edit | stock_opnames.store | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ |
| - SO Delete | stock_opnames.destroy | ✓ | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ |
| - Item Request View | item_requests.index | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| - SPB Create | item_requests.store | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ |
| - SPB Cancel Request | item_requests.cancel | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ |
| - SPB Approve Cancel | item_requests.approve_cancel | ✓ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ |
| - CSV Download | item_requests.download_csv | ✓ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ |
| **Forecast** | | | | | | | | |
| - View | forecasts.index | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| - Upload | forecasts.upload_excel | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Approve | forecasts.confirm | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| - Delete | forecasts.destroy | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| **Reports** | | | | | | | | |
| - LSM Report | reports.lsm_report | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| - SPB Report | reports.spb_report | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| - DOI Report | reports.doi_report | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| - System Logs | reports.system_logs | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| **QAD Integration** | | | | | | | | |
| - Download CSV SPB | item_requests.download_csv | ✓ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ |
| - Upload Master Data | stores/menus.upload_excel | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |


#### 4.2.4 Permission Middleware

**Custom Permission Middleware** (`app/Http/Middleware/PermissionMiddleware.php`)

```php
// Implementasi di routes/web.php
Route::group(['middleware' => ['auth', 'permission']], function () {
    // Protected routes
});

// Middleware akan:
1. Cek apakah user sudah login
2. Cek permission berdasarkan route name
3. Jika tidak punya permission → redirect dengan error
4. Log semua unauthorized access attempts
```

**Permission Naming Convention:**
- Format: `{module}.{action}`
- Contoh: `stock_opnames.index`, `item_requests.store`
- Wildcard: `stock_opnames.*` untuk semua aksi di module


### 4.3 Store-Level Access Control

#### 4.3.1 Multi-Store Assignment

User dapat di-assign ke multiple stores melalui tabel `users_stores`:

```sql
CREATE TABLE users_stores (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    store_id INTEGER REFERENCES m_stores(id),
    created_by INTEGER,
    updated_by INTEGER,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);
```

**Business Rules:**
- Super Admin & Admin: Akses semua stores
- SDP/HO: Akses semua stores (read-only untuk transaksi)
- PPIC: Akses semua stores (untuk approval)
- Store Manager/Staff: Hanya stores yang di-assign

#### 4.3.2 Store Selection Flow

```
┌─────────────────────────────────────────────────────────────────────────┐
│                      STORE SELECTION FLOW                               │
└─────────────────────────────────────────────────────────────────────────┘

    User                    System                  Session
     │                        │                         │
     │  Login Success         │                         │
     ├───────────────────────►│                         │
     │                        │  Get User Stores        │
     │                        │                         │
     │                   ┌────┴────┐                    │
     │                   │ Multiple│                    │
     │                   │ Stores? │                    │
     │                   └────┬────┘                    │
     │                        │                         │
     │             ┌──────────┼──────────┐              │
     │             │ Ya                 │ Tidak         │
     │             │                    │               │
     │  Show Store │                    │  Auto Select  │
     │  Selector   │                    │  Single Store │
     │◄────────────┤                    ├──────────────►│
     │             │                    │               │
     │  Select     │                    │               │
     │  Store      │                    │               │
     ├─────────────┤                    │               │
     │             │                    │               │
     │             └────────────────────┘               │
     │                        │                         │
     │                        │  Save to Session        │
     │                        │  store_selected = ID    │
     │                        ├────────────────────────►│
     │                        │                         │
     │  Redirect to Dashboard │                         │
     │◄───────────────────────┤                         │
     │                        │                         │
```

**Session Variable:**
```php
session(['store_selected' => $storeId]);
```

**Store Switching:**
- User dapat switch store kapan saja via dropdown
- Semua query akan filter berdasarkan `store_selected`
- Jika user tidak punya akses ke store → error


### 4.4 Data Security

#### 4.4.1 Soft Delete Pattern

Sistem menggunakan **soft delete** dengan flag `delete_flag`:

```php
// Semua tabel memiliki:
delete_flag BOOLEAN DEFAULT FALSE

// Query selalu filter:
WHERE delete_flag = 0 atau FALSE
```

**Keuntungan:**
- Data tidak benar-benar terhapus
- Audit trail tetap lengkap
- Dapat restore jika diperlukan
- Maintain referential integrity

#### 4.4.2 Audit Trail

Setiap tabel memiliki audit fields:

```php
created_by INTEGER    // User ID yang create
updated_by INTEGER    // User ID yang update
created_at TIMESTAMP  // Waktu create
updated_at TIMESTAMP  // Waktu update terakhir
```

**Change History untuk Transaksi Kritis:**

Tabel `t_stock_opname_change_logs`:
```sql
CREATE TABLE t_stock_opname_change_logs (
    id SERIAL PRIMARY KEY,
    so_detail_id INTEGER,
    field_name VARCHAR(50),
    old_value TEXT,
    new_value TEXT,
    changed_by INTEGER,
    changed_at TIMESTAMP
);
```

Mencatat setiap perubahan pada Stock Opname untuk compliance.


#### 4.4.3 Concurrent Editing Protection

**Locking Mechanism untuk Stock Opname:**

```php
// t_stock_opnames table
editing_by INTEGER       // User ID yang sedang edit
editing_at TIMESTAMP     // Waktu mulai edit
```

**Flow:**
1. User buka SO untuk edit → sistem lock dengan user ID
2. User lain coba edit → ditolak dengan pesan "Sedang diedit oleh [User]"
3. Heartbeat setiap 30 detik untuk maintain lock
4. Auto-unlock jika tidak ada heartbeat selama 5 menit
5. Admin dapat force unlock

**Implementasi:**
```javascript
// Client-side heartbeat
setInterval(function() {
    $.post('/stock_opnames/heartbeat', {
        so_id: currentSOId
    });
}, 30000); // 30 seconds
```

#### 4.4.4 Business Rule Enforcement

**Backdate Protection:**
```php
// User model
flag_backdate_so BOOLEAN DEFAULT FALSE

// Validation
if (!auth()->user()->canBackdateSO()) {
    // Hanya boleh input tanggal hari ini
    if ($soDate != today()) {
        throw new Exception("Tidak boleh backdate");
    }
}
```

**Edit Window Enforcement:**
```php
// Cek apakah masih dalam edit window
$editDeadline = $soDate->addDay()->setTime(11, 0, 0);

if (now() > $editDeadline) {
    throw new Exception("Edit window sudah ditutup");
}
```


### 4.5 Integration Security (QAD)

#### 4.5.1 CSV Export untuk QAD

**SPB CSV Generation:**

```php
// Hanya PPIC yang dapat download CSV
if (!auth()->user()->hasPermissionTo('item_requests.download_csv')) {
    abort(403);
}

// CSV disimpan di storage/app/exports/csv (tidak public)
// Filename: SPB{number}_{timestamp}.csv
// Auto-delete setelah 7 hari
```

**CSV Format:**
- Header: Store Code, Item Code, Quantity, UOM, Delivery Date
- Encoding: UTF-8
- Delimiter: Comma (,)
- Line ending: CRLF

**CSV Content Validation:**
- Validasi format sebelum generate
- Sanitize data untuk prevent injection
- Log setiap CSV generation
- Track CSV download history

**Security Measures:**
- CSV hanya dapat di-download oleh PPIC
- CSV file tidak accessible via public URL
- Automatic cleanup setelah 7 hari
- Log semua download activity

#### 4.5.2 Excel Upload dari QAD

**Master Data Upload (Stores & Menus):**

```php
// Hanya SDP/HO yang dapat upload master data
if (!auth()->user()->hasPermissionTo('stores.upload_excel')) {
    abort(403);
}

// Validasi file:
- Format: .xlsx atau .xls
- Max size: 5MB
- Template validation
```

**Upload Security:**
- File validation sebelum processing
- Virus scanning (jika tersedia)
- Temporary storage di storage/app/uploads
- Auto-delete setelah processing
- Sanitize semua input data

**Data Validation:**
- Mandatory fields check
- Data type validation
- Unique constraint check
- Foreign key validation
- Business rule validation

**Error Handling:**
- Preview data sebelum import
- Show validation errors per row
- Partial import tidak diizinkan (all or nothing)
- Rollback jika ada error
- Log semua import activity


### 4.6 Security Best Practices

#### 4.6.1 Password Security

```php
// User model
public function setPasswordAttribute($value)
{
    $this->attributes['password'] = bcrypt($value);
}

// Password requirements (dapat dikonfigurasi):
- Minimal 8 karakter
- Kombinasi huruf dan angka (opsional)
- Force change password pada first login
```

**Password Reset:**
- Admin dapat reset password user
- User akan dipaksa ganti password pada login berikutnya
- Flag: `f_need_change_password`

#### 4.6.2 Input Validation

**Form Request Validation:**
```php
// app/Http/Requests/StoreUserRequest.php
public function rules()
{
    return [
        'username' => 'required|unique:users|max:50',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:8',
        'fullname' => 'required|max:100',
    ];
}
```

**SQL Injection Prevention:**
- Gunakan Eloquent ORM (prepared statements)
- Hindari raw queries
- Jika perlu raw query, gunakan parameter binding

**XSS Prevention:**
- Blade templating auto-escape output: `{{ $variable }}`
- Untuk HTML: `{!! $html !!}` (hati-hati!)
- Sanitize user input


#### 4.6.3 CSRF Protection

Laravel built-in CSRF protection:

```php
// Middleware: VerifyCsrfToken
// Semua POST/PUT/DELETE request harus include CSRF token

// Blade template:
@csrf

// AJAX:
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});
```

#### 4.6.4 Error Handling & Logging

**Error Logging:**
```php
// app/Exceptions/Handler.php
public function report(Throwable $exception)
{
    if ($this->shouldReport($exception)) {
        Log::error('Application Error', [
            'message' => $exception->getMessage(),
            'file' => $exception->getFile(),
            'line' => $exception->getLine(),
            'user_id' => auth()->id(),
            'url' => request()->fullUrl(),
        ]);
    }
    
    parent::report($exception);
}
```

**Error Notification:**
- Critical errors dikirim via email ke admin
- Menggunakan `ErrorOccurredNotification`
- Konfigurasi di `config/mail.php`

**Log Files:**
- `storage/logs/laravel.log` - Application logs
- Rotate daily
- Retention: 14 hari


### 4.7 Security Checklist

#### Production Deployment Security

- [ ] **Environment Configuration**
  - [ ] `APP_ENV=production`
  - [ ] `APP_DEBUG=false`
  - [ ] `APP_KEY` generated dan secure
  - [ ] Database credentials di `.env`
  - [ ] `.env` tidak di version control

- [ ] **HTTPS/SSL**
  - [ ] Force HTTPS di production
  - [ ] SSL certificate valid
  - [ ] Redirect HTTP ke HTTPS

- [ ] **Database Security**
  - [ ] Database user dengan minimal privileges
  - [ ] Database tidak accessible dari public
  - [ ] Regular backup schedule
  - [ ] Encrypted backup storage

- [ ] **File Permissions**
  - [ ] `storage/` dan `bootstrap/cache/` writable
  - [ ] `.env` file permission 600
  - [ ] Vendor files tidak writable

- [ ] **Session Security**
  - [ ] Session driver: database (bukan file)
  - [ ] Session lifetime configured
  - [ ] Secure session cookies
  - [ ] HttpOnly cookies enabled

- [ ] **Rate Limiting**
  - [ ] Login rate limiting
  - [ ] API rate limiting
  - [ ] Throttle middleware configured

- [ ] **Monitoring & Alerts**
  - [ ] Error monitoring setup
  - [ ] Failed login attempts logged
  - [ ] Unauthorized access logged
  - [ ] Email alerts untuk critical errors

- [ ] **Regular Maintenance**
  - [ ] Update Laravel & dependencies
  - [ ] Security patches applied
  - [ ] Log rotation configured
  - [ ] Database optimization scheduled

---

## 5. Kesimpulan

Dokumentasi ini mencakup desain lengkap sistem LSM Web Portal meliputi:

1. **Use Case Diagram**: 28 use cases untuk 4 aktor utama (Sistem QAD hanya penerima CSV)
2. **Activity Diagram**: 3 proses bisnis kritis (SO & SPB, Forecast, Pembatalan)
3. **ERD**: 30+ tabel dengan relasi lengkap
4. **Desain Keamanan**: Authentication, RBAC, Store-level access, Audit trail, Integration security

**Key Security Features:**
- Single session enforcement
- Role-based access control (7 roles)
- Store-level data isolation
- Concurrent editing protection
- Comprehensive audit trail
- Business rule enforcement
- CSV export security untuk QAD
- Excel upload validation untuk master data

**QAD Integration:**
- **LSM → QAD**: Export SPB dalam format CSV (download oleh PPIC)
- **QAD → LSM**: Upload master data (Stores, Menus) via Excel oleh SDP/HO
- Tidak ada API real-time, semua via file exchange
- Security validation untuk semua file upload/download

**Compliance:**
- Audit trail untuk semua transaksi
- Change history untuk Stock Opname
- Soft delete untuk data retention
- Session tracking untuk accountability
- File upload/download logging

---

**Catatan:**
- Diagram dapat divisualisasikan menggunakan tools seperti PlantUML, Draw.io, atau Lucidchart
- ERD dapat di-generate dari database menggunakan tools seperti DBeaver atau pgAdmin
- Security policies harus direview secara berkala
- Dokumentasi ini harus diupdate seiring evolusi sistem
- QAD integration menggunakan file-based exchange (CSV/Excel), bukan API real-time

