# Analisis Alur: ORDER BARU DARI CRM → Shopping Cart

> **Sumber:** Sesi Codex (15 Mei 2026 17:36) — "Cari proses CRM ke shopping cart"
> **Lokasi history:** `C:\Users\vansgare\.codex\sessions\2026\05\15\rollout-2026-05-15T17-36-32-019e2b35-...jsonl`

---

## 📋 Ringkasan Alur

```
ORDER BARU DARI CRM (TransaksiCrm)
       │
       ▼  klik "followup" button
Create::previewCrm()
       │
       ▼  tampilkan preview + tombol "To Shopping Cart"
Create::previewCrm() → view create.php
       │
       ▼  klik "To Shopping Cart"
followupCrmToShoppingCart() [JS]
       │
       ▼  POST ke _processSelectProduct/selectCrm
_processSelectProduct::selectCrm()
       │
       ▼  simpan ke session
$_SESSION[$cCode]['items'][$sessionItemKey]
       │
       ▼  refresh shopping cart
$_shoppingCart/viewCart
       │
       ▼  redirect ke Create/index
```

---

## 🔍 File & Kode yang Terlibat

### 1. Halaman Daftar: `TransaksiCrm.php` (controller)

**File:** `application/modules/penjualan/controllers/TransaksiCrm.php`

**Line 83** — Button followup mengarah ke `Create/previewCrm`:
```php
$link = MODUL_PATH . "Create/previewCrm/" . $this->jenisTr . "/" . $tmp_0->estimate_id;
```

**Line 102** — Tombol followup di tampilan lama:
```php
$maindatas[$tmp_0->estimate_id]['action'] = "<button ... onclick=\"showModal('$link' ,'view CRM Orders')\">followup</button>";
```

**Line 128** — Tombol followup dari halaman index:
```php
$maindatas[$tmp_0->estimate_id]['action'] = "<button ... onclick=\"indexToCreate('$link')\">followup</button>";
```

**Line 232-234** — Tombol followup di tampilan baru (refactored):
```php
// $target = MODUL_PATH . "_processSelectProduct/selectCrm/..." (OLD)
$target = MODUL_PATH . "Create/previewCrm/" . $this->jenisTr . "/" . $estimateId;
```

---

### 2. Preview CRM: `Create.php` (controller)

**File:** `application/modules/penjualan/controllers/Create.php`

**Method `previewCrm()` (~line 18192-18671):**
- Membaca data dari tabel `penjualan_transaksi_data_crm_bridge`
- Lookup customer: `$tempCust[0]->id` dari `per_customers`
- Build array produk dari bridge rows

**Line 18649-18657** — Simpan payload ke session untuk digunakan nanti oleh `selectCrm`:
```php
if (!isset($_SESSION[$this->cCode]["crmPreviewPayload"]) || !is_array($_SESSION[$this->cCode]["crmPreviewPayload"])) {
    $_SESSION[$this->cCode]["crmPreviewPayload"] = array();
}
$_SESSION[$this->cCode]["crmPreviewPayload"][$estimate_id] = array(
    "estimate_id" => (int)$estimate_id,
    "pihak_id" => isset($tempCust[0]->id) ? (int)$tempCust[0]->id : 0,
    "items" => $listProduk,
    "updated_at" => dtimeNow(),
);
```

**Line 18671** — Target untuk `_processSelectProduct/selectCrm`:
```php
"target" => MODUL_PATH . "_processSelectProduct/selectCrm/" . $this->jenisTr . "/$estimate_id?pihakID=" . $tempCust[0]->id,
```

---

### 3. Tombol "To Shopping Cart": `create.php` (view)

**File:** `application/modules/penjualan/views/create.php`

**Line 16** — Komen kode lama:
```php
// $btn_group .= "<button type='button' id='btn-to-shopping-cart' disabled class='btn btn-primary' ...>To Shopping Cart</button>";
```

**Line 297** — Tombol aktif yang memanggil `followupCrmToShoppingCart`:
```php
$btn_group .= "<button type='button' $allow_followup id='btn-to-shopping-cart' disabled class='btn btn-primary' data-dismis='modal' onclick=\"if(typeof followupCrmToShoppingCart==='function'){followupCrmToShoppingCart('$target');}\">To Shopping Cart</button>";
```

**Line 722-746** — Fungsi JavaScript `followupCrmToShoppingCart`:
```javascript
function followupCrmToShoppingCart(baseUrl) {
    var targetUrl = buildShoppingCartTarget(baseUrl);
    if (targetUrl === '') return;
    var postPayload = {
        pihakMainExec: currentMainExec,
        use_session_payload: 1
    };
    syncMainExec(currentMainExec, true);
    if (typeof top.handleToShoppingCartWithMissingPrice === 'function') {
        top.__crmToCartPostPayload = postPayload;
        top.handleToShoppingCartWithMissingPrice(targetUrl, postPayload);
    } else if (typeof handleToShoppingCartWithMissingPrice === 'function') {
        window.__crmToCartPostPayload = postPayload;
        handleToShoppingCartWithMissingPrice(targetUrl, postPayload);
    }
}

// Ekspos fungsi ke global scope
window.followupCrmToShoppingCart = followupCrmToShoppingCart;
top.followupCrmToShoppingCart = followupCrmToShoppingCart;
```

**Line 512** — `buildShoppingCartTarget` menambahkan parameter `pihakMainExec`:
```javascript
function buildShoppingCartTarget(baseUrl) {
    var glue = baseUrl.indexOf('?') === -1 ? '?' : '&';
    return baseUrl + glue + 'pihakMainExec=' + encodeURIComponent(currentMainExec);
}
```

---

### 4. Select CRM → Shopping Cart: `_processSelectProduct.php`

**File:** `application/modules/penjualan/controllers/_processSelectProduct.php`

**Line 5208** — Method `selectCrm()`:
```php
public function selectCrm(){
```

**Line 5225-5231** — Baca data dari GET/POST `enc` atau dari session `crmPreviewPayload`:
```php
$encPayload = ...; // dari $_POST atau $_GET
$storedCrmPayload = isset($_SESSION[$cCode]["crmPreviewPayload"][$estimate_id]) 
    ? $_SESSION[$cCode]["crmPreviewPayload"][$estimate_id] 
    : array();
```

**Line 5234-5235** — Fallback customer_id dari session payload:
```php
if ($custID < 1 && isset($storedCrmPayload["pihak_id"])) {
    $custID = (int)$storedCrmPayload["pihak_id"];
}
```

**Line 5245-5246** — Fallback items dari session payload:
```php
if (count($lsitProduk) < 1 && isset($storedCrmPayload["items"])) {
    $lsitProduk = $storedCrmPayload["items"];
}
```

**Line 5316-5327** — Set `pihakMainExec` (san/local) berdasarkan request:
```php
$requestedPihakMainExec = ...; // dari POST/GET
$_SESSION[$cCode]["main"]["pihakMainExec"] = $requestedPihakMainExec;
$_SESSION[$cCode]["main"]["pihakMainExec_deskripsi"] = "san: dikirim oleh cabang nya san, local: dikirim sendiri";
```

**Line 5589-5590** — Set referensi order ke CRM:
```php
$_SESSION[$cCode]["main"]["ref_order"] = "crm";
$_SESSION[$cCode]["main"]["ref_order_estimate_id"] = $estimate_id;
```

**Line 5591-5611** — Loop untuk setiap item dari CRM → $lsitProduk:
```php
foreach($lsitProduk as $pid => $pidData){
    $produk_id = ...;
    $variantId = ...;
    $variantLabel = ...;
    $sessionItemKey = $variantId > 0 ? "variant:" . $variantId : (string)$produk_id;
    // ...
}
```

**Line 5928-5940** — Inisialisasi item ke session (jika belum ada):
```php
if (!isset($_SESSION[$cCode]['items']) || !array_key_exists($sessionItemKey, $_SESSION[$cCode]['items'])) {
    $tmp = array(
        "handler" => $this->modul . "/" . $this->uri->segment(2),
        "id" => $produk_id,
        "jml" => $tmpJml,
        "harga" => 0,
        "subtotal" => 0,
        "satuan" => ...,
        "discount_persen" => ...,
        "discount_qty" => ...,
        "harga_jasa" => 0,
    );
    // ...
}
```

**Line 6094-6102** — Simpan harga CRM sebagai `crm_harga` di session item:
```php
$hargaDasar = isset($tmp["harga"]) ? ... : 0;
$hasHargaCrm = is_array($pidData) && array_key_exists("harga", $pidData);
$hargaCrm = $hasHargaCrm ? ... : 0;
if ($hasHargaCrm) {
    if (!isset($tmp["harga_ori"]) || (float)$tmp["harga_ori"] <= 0) {
        $tmp["harga_ori"] = $hargaDasar;
    }
    $tmp["crm_harga"] = $hargaCrm;
}
```

**Line 6124** — Simpan ke session:
```php
$_SESSION[$cCode]['items'][$sessionItemKey] = $tmp;
```

**Line 6267-6268** — Set referensi order per-item:
```php
$tmp['ref_order'] = "crm";
$tmp['ref_order_estimate_id'] = $estimate_id;
```

**Line 6722-6723** — Hapus session payload setelah diproses:
```php
if (isset($_SESSION[$cCode]["crmPreviewPayload"][$estimate_id])) {
    unset($_SESSION[$cCode]["crmPreviewPayload"][$estimate_id]);
}
```

**Line 6756-6769** — Redirect ke halaman Create/index setelah selesai:
```php
$redirectCreateUrl = MODUL_PATH . "Create/index/" . $this->jenisTr;
echo "try{ root.location.href='" . $redirectCreateUrl . "'; }catch(e){ ... }";
```

**Line 5203** — Refresh shopping cart:
```php
echo "top.$('#shopping_cart').load('" . base_url() . $this->modul . "/_shoppingCart/viewCart/" . $this->jenisTr . "?selID=$id');";
```

---

### 5. Tampilan `transaksi.php` — ORDER BARU DARI CRM

**File:** `application/modules/penjualan/views/transaksi.php`

**Line 15316** — Header tabel:
```php
$strOnprog .= "<h3 class='box-title text-uppercase' style='font-weight: bold; font-size: 19px; color: #000;'><i class='fa fa-rocket blink'> </i> &nbsp;ORDER BARU DARI CRM <label class='badge badge-danger'>$jml_data</label></h3>";
```

**Line 15427** — Button followup class:
```php
$btnClass = "btn btn-xs btn-" . $variant . " btn-crm-followup";
```

**Line 15594-15609** — Fungsi JS `runAction`:
```javascript
function runAction(action){
    if(action.context === 'index'){
        if(typeof root.indexToCreate === 'function'){
            root.indexToCreate(action.target);
        } else if(typeof indexToCreate === 'function'){
            indexToCreate(action.target);
        } else {
            window.location.href = action.target;
        }
        return;
    }
    // ... handle result context (showModal)
}
```

**Line 15962** — Event handler klik followup:
```javascript
$('#arrayOnProgress_crm').on('click', '.btn-crm-followup', handleFollowUp);
```

---

## 📊 Data Flow Diagram

```
┌─────────────────────────────────────────────────────────┐
│                    ORDER BARU DARI CRM                    │
│             TransaksiCrm::viewOrderCrm()                  │
│         (read from penjualan_transaksi_data_crm_bridge)   │
└──────────────────────────┬──────────────────────────────┘
                           │ klik "followup"
                           ▼
┌─────────────────────────────────────────────────────────┐
│              Create::previewCrm()                         │
│  - Baca bridge data per estimate_id                       │
│  - Resolve customer name (per_customers)                  │
│  - Build array $listProduk                                │
│  - Simpan ke session:                                      │
│    $_SESSION['crmPreviewPayload'][$estimate_id]            │
│    { pihak_id, items, updated_at }                        │
│  - Render view create.php dengan data + tombol             │
└──────────────────────────┬──────────────────────────────┘
                           │ klik "To Shopping Cart"
                           ▼
┌─────────────────────────────────────────────────────────┐
│  JS: followupCrmToShoppingCart(targetUrl)                │
│  - buildShoppingCartTarget → tambah ?pihakMainExec=...   │
│  - POST ke _processSelectProduct/selectCrm                │
│    { pihakMainExec, use_session_payload: 1 }              │
└──────────────────────────┬──────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────┐
│  _processSelectProduct::selectCrm()                      │
│  - Baca enc payload dari POST/GET                        │
│  - Fallback ke storedCrmPayload dari session              │
│  - Set pihakMainExec ke session                          │
│  - Loop items:                                            │
│    • Init session items entry                             │
│    • Set crm_harga, ref_order = "crm"                     │
│    • ref_order_estimate_id                                │
│  - Hapus session payload                                  │
│  - Refresh shopping cart view                             │
│  - Redirect ke Create/index                               │
└─────────────────────────────────────────────────────────┘
```

---

## ⚠️ Poin Penting

| Poin | Detail |
|------|--------|
| **Estimasi sudah ada di SAN** | Data sudah masuk ke `penjualan_transaksi_data_crm_bridge` |
| **Customer sudah terdaftar** | Customer_id sudah ada di `per_customers` SAN |
| **Harga CRM** | Harga dari CRM disimpan di `$tmp['crm_harga']` — ada mekanisme lock harga |
| **pihakMainExec** | Ada 2 mode: `"san"` (dikirim oleh cabang SAN) atau `"local"` (dikirim sendiri) |
| **Session sebagai media** | Data sementara disimpan di session `$_SESSION[$cCode]` |
| **Payload session** | `crmPreviewPayload` hanya hidup antara Preview → SelectCrm, lalu dihapus |
| **Redirect after process** | Setelah sukses, redirect ke `Create/index` |
