# 🔢 Update Format Nomor Pembelian (Purchase Number)

## ✅ Status: SELESAI

---

## 🎯 Perubahan Format

### **BEFORE (Format Lama):**
```
PO202512190002
│ │       │
│ │       └─ Nomor urut pembelian hari ini (semua operator)
│ └───────── Tanggal (YYYYMMDD)
└─────────── Prefix tetap "PO"
```

**Masalah:**
- ❌ Tidak tahu siapa yang input
- ❌ Nomor urut global (semua operator)
- ❌ Sulit tracking per operator

---

### **AFTER (Format Baru):**
```
DZUL202512190002
│  │       │
│  │       └─ Nomor urut pembelian operator ini hari ini
│  └───────── Tanggal (YYYYMMDD)
└──────────── 3 huruf pertama nama operator (uppercase)
```

**Keuntungan:**
- ✅ Langsung tahu siapa yang input (DZUL, FAR, etc)
- ✅ Nomor urut per operator (setiap operator mulai dari 0001)
- ✅ Mudah tracking dan audit
- ✅ Unique per operator per hari

---

## 📋 Detail Implementasi

### **File Modified:**
`app/Http/Controllers/Transaction/PurchaseController.php` (Lines 306-339)

### **Kode Baru:**

```php
/**
 * Generate unique purchase number based on operator
 * Format: OPERATOR(3 huruf) + YYYYMMDD + URUT(4 digit)
 * Example: DZUL202512190002
 */
private function generatePurchaseNumber()
{
    // Get current user name
    $userName = Auth::user()->name;

    // Get 3 huruf pertama dari nama, convert ke uppercase
    $prefix = strtoupper(substr($userName, 0, 3));

    // Get date format YYYYMMDD
    $date = date('Ymd');

    // Get last purchase number for THIS operator on TODAY
    $lastPurchase = Purchase::whereDate('created_at', today())
        ->where('user_id', Auth::id())  // ← FILTER BY OPERATOR
        ->orderBy('id', 'desc')
        ->first();

    if ($lastPurchase) {
        // Extract last 4 digits from purchase_number
        $lastNumber = intval(substr($lastPurchase->purchase_number, -4));
        $newNumber = $lastNumber + 1;
    } else {
        // First purchase for this operator today
        $newNumber = 1;
    }

    // Format: OPERATOR + YYYYMMDD + 4 digit number
    return $prefix . $date . str_pad($newNumber, 4, '0', STR_PAD_LEFT);
}
```

---

## 🔍 Cara Kerja

### **Step by Step:**

1. **Ambil Nama Operator**
   ```php
   $userName = Auth::user()->name;  // Contoh: "Dzul Farikin"
   ```

2. **Ambil 3 Huruf Pertama (Uppercase)**
   ```php
   $prefix = strtoupper(substr($userName, 0, 3));  // Result: "DZU"
   ```

3. **Ambil Tanggal (YYYYMMDD)**
   ```php
   $date = date('Ymd');  // Contoh: "20251219"
   ```

4. **Cari Pembelian Terakhir Operator Ini Hari Ini**
   ```php
   $lastPurchase = Purchase::whereDate('created_at', today())
       ->where('user_id', Auth::id())  // Filter by current operator
       ->orderBy('id', 'desc')
       ->first();
   ```

5. **Hitung Nomor Urut**
   ```php
   if ($lastPurchase) {
       // Ada pembelian sebelumnya hari ini
       $lastNumber = intval(substr($lastPurchase->purchase_number, -4));  // Ambil 4 digit terakhir
       $newNumber = $lastNumber + 1;  // Increment
   } else {
       // Pembelian pertama hari ini
       $newNumber = 1;
   }
   ```

6. **Gabung Semua**
   ```php
   return $prefix . $date . str_pad($newNumber, 4, '0', STR_PAD_LEFT);
   // Result: "DZU202512190002"
   ```

---

## 📊 Contoh Penggunaan

### **Scenario 1: Operator DZUL - Pembelian Pertama Hari Ini**

```
Input:
- Nama Operator: "Dzul Farikin"
- Tanggal: 2025-12-19
- Pembelian terakhir DZUL hari ini: TIDAK ADA

Process:
- Prefix: "DZU" (3 huruf pertama dari "Dzul")
- Date: "20251219"
- Nomor urut: 0001 (pembelian pertama)

Output:
DZU202512190001
```

### **Scenario 2: Operator DZUL - Pembelian Kedua Hari Ini**

```
Input:
- Nama Operator: "Dzul Farikin"
- Tanggal: 2025-12-19
- Pembelian terakhir DZUL hari ini: DZU202512190001

Process:
- Prefix: "DZU"
- Date: "20251219"
- Nomor urut: 0002 (increment dari 0001)

Output:
DZU202512190002
```

### **Scenario 3: Operator FARIKIN - Pembelian Pertama Hari Ini**

```
Input:
- Nama Operator: "Farikin"
- Tanggal: 2025-12-19
- Pembelian terakhir FARIKIN hari ini: TIDAK ADA

Process:
- Prefix: "FAR" (3 huruf pertama dari "Farikin")
- Date: "20251219"
- Nomor urut: 0001 (pembelian pertama operator ini)

Output:
FAR202512190001
```

**Note:** Meskipun DZUL sudah input 2x hari ini, FARIKIN tetap mulai dari 0001 karena nomor urut per operator!

### **Scenario 4: Multiple Operators - Same Day**

```
Timeline hari ini (2025-12-19):
09:00 - DZUL input   → DZU202512190001
10:00 - FARIKIN input → FAR202512190001
11:00 - DZUL input   → DZU202512190002
12:00 - FARIKIN input → FAR202512190002
13:00 - AGUS input   → AGU202512190001
14:00 - DZUL input   → DZU202512190003

Summary hari ini:
- DZUL: 3 pembelian (0001, 0002, 0003)
- FARIKIN: 2 pembelian (0001, 0002)
- AGUS: 1 pembelian (0001)
```

---

## 🎨 Format Breakdown

### **Format Lengkap:**
```
OPERATOR + YYYYMMDD + NNNN
   3        8        4     = Total 15 karakter
```

### **Components:**

| Component | Length | Type | Example | Description |
|-----------|--------|------|---------|-------------|
| **OPERATOR** | 3 | String | DZU | 3 huruf pertama nama (uppercase) |
| **YYYY** | 4 | Digit | 2025 | Tahun |
| **MM** | 2 | Digit | 12 | Bulan |
| **DD** | 2 | Digit | 19 | Tanggal |
| **NNNN** | 4 | Digit | 0002 | Nomor urut (per operator per hari) |

### **Examples:**

| Operator Name | Date | Urut | Purchase Number |
|--------------|------|------|----------------|
| Dzul Farikin | 2025-12-19 | 1 | DZU202512190001 |
| Dzul Farikin | 2025-12-19 | 2 | DZU202512190002 |
| Farikin | 2025-12-19 | 1 | FAR202512190001 |
| Agus | 2025-12-19 | 1 | AGU202512190001 |
| Dzul Farikin | 2025-12-20 | 1 | DZU202512200001 ← Reset di hari baru |

---

## 🔄 Database Query Logic

### **Query untuk Cari Nomor Terakhir:**

```sql
SELECT * FROM purchases
WHERE DATE(created_at) = CURDATE()
  AND user_id = ?  -- Current operator ID
ORDER BY id DESC
LIMIT 1;
```

**Filter Criteria:**
1. **Same Date:** `DATE(created_at) = CURDATE()`
2. **Same Operator:** `user_id = Auth::id()`
3. **Latest First:** `ORDER BY id DESC`

**Result:**
- Jika ADA → Ambil 4 digit terakhir, increment
- Jika TIDAK ADA → Mulai dari 0001

---

## ✅ Benefits

### **1. Tracking Per Operator**
```
Query: SELECT * FROM purchases WHERE purchase_number LIKE 'DZU%'
Result: Semua pembelian oleh DZUL
```

### **2. Audit Trail**
```
- Siapa yang input? → Lihat 3 huruf pertama
- Kapan input? → Lihat 8 digit tanggal
- Berapa kali input hari ini? → Lihat 4 digit terakhir
```

### **3. Performance Monitoring**
```sql
-- Count pembelian per operator hari ini
SELECT
    LEFT(purchase_number, 3) as operator,
    COUNT(*) as total_purchases
FROM purchases
WHERE DATE(created_at) = CURDATE()
GROUP BY LEFT(purchase_number, 3);

Result:
+-----------+------------------+
| operator  | total_purchases  |
+-----------+------------------+
| DZU       | 3                |
| FAR       | 2                |
| AGU       | 1                |
+-----------+------------------+
```

### **4. Unique & Readable**
```
✅ DZU202512190002 → Jelas: DZUL, 19 Des 2025, ke-2
❌ PO202512190002 → Tidak jelas siapa yang input
```

---

## 🎯 Use Cases

### **Use Case 1: Manager Check Daily Performance**
```
Manager: "Berapa pembelian DZUL hari ini?"

Query:
SELECT * FROM purchases
WHERE purchase_number LIKE 'DZU20251219%'

Result:
- DZU202512190001
- DZU202512190002
- DZU202512190003

Kesimpulan: DZUL input 3 pembelian hari ini
```

### **Use Case 2: Kasir Cek Input Sendiri**
```
DZUL: "Sudah berapa kali saya input hari ini?"

Query:
SELECT * FROM purchases
WHERE user_id = ?
  AND DATE(created_at) = CURDATE()

Result: 3 records

Atau lihat nomor terakhir: DZU202512190003 → Sudah 3x
```

### **Use Case 3: Admin Audit**
```
Admin: "Siapa yang paling banyak input bulan ini?"

Query:
SELECT
    LEFT(purchase_number, 3) as operator,
    COUNT(*) as total
FROM purchases
WHERE YEAR(created_at) = 2025
  AND MONTH(created_at) = 12
GROUP BY LEFT(purchase_number, 3)
ORDER BY total DESC;

Result:
DZU - 45 pembelian
FAR - 32 pembelian
AGU - 28 pembelian
```

---

## 🔧 Technical Details

### **String Functions Used:**

1. **`Auth::user()->name`**
   - Get current logged in user name

2. **`substr($userName, 0, 3)`**
   - Extract first 3 characters
   - Example: "Dzul Farikin" → "Dzu"

3. **`strtoupper()`**
   - Convert to uppercase
   - Example: "Dzu" → "DZU"

4. **`date('Ymd')`**
   - Format date as YYYYMMDD
   - Example: 2025-12-19 → "20251219"

5. **`str_pad($newNumber, 4, '0', STR_PAD_LEFT)`**
   - Pad number to 4 digits with leading zeros
   - Example: 2 → "0002"

6. **`substr($purchase_number, -4)`**
   - Extract last 4 characters
   - Example: "DZU202512190002" → "0002"

7. **`intval()`**
   - Convert string to integer
   - Example: "0002" → 2

---

## 📝 Testing Scenarios

### **Test 1: First Purchase Today**
```
GIVEN:
- User: "Dzul Farikin"
- Date: 2025-12-19
- No previous purchase today

WHEN: Create purchase

THEN:
- Purchase Number: DZU202512190001 ✅
```

### **Test 2: Second Purchase Today**
```
GIVEN:
- User: "Dzul Farikin"
- Date: 2025-12-19
- Last purchase: DZU202512190001

WHEN: Create purchase

THEN:
- Purchase Number: DZU202512190002 ✅
```

### **Test 3: Different Operator Same Day**
```
GIVEN:
- User 1 (DZUL) has: DZU202512190002
- User 2 (FARIKIN) has: No purchase today
- Date: 2025-12-19

WHEN: FARIKIN creates purchase

THEN:
- Purchase Number: FAR202512190001 ✅
- NOT FAR202512190003 (tidak lanjut dari DZUL)
```

### **Test 4: New Day Reset**
```
GIVEN:
- User: "Dzul Farikin"
- Yesterday (2025-12-18): DZU202512180005
- Today (2025-12-19): No purchase yet

WHEN: Create purchase today

THEN:
- Purchase Number: DZU202512190001 ✅
- Reset ke 0001 karena hari baru
```

### **Test 5: Name with Less Than 3 Characters**
```
GIVEN:
- User name: "Jo"
- Date: 2025-12-19

WHEN: Create purchase

THEN:
- Purchase Number: JO202512190001 ✅
- substr() akan ambil apa adanya (2 char saja)
```

---

## ⚠️ Important Notes

### **1. Nama Operator Harus Unique Identifier**
- Jika ada 2 operator dengan nama sama (misal: "Dzul A" dan "Dzul B")
- Keduanya akan dapat prefix "DZU"
- Solusi: Pastikan nama operator unique atau gunakan field lain (username, employee_id)

### **2. Reset Setiap Hari**
- Nomor urut reset ke 0001 setiap hari baru
- Ini normal dan expected behavior
- Tracking tetap akurat karena ada tanggal di nomor

### **3. Max 9999 Pembelian Per Operator Per Hari**
- Format 4 digit: 0001 - 9999
- Jika lebih dari 9999, akan jadi 5 digit (10000)
- Realistically, ini tidak akan terjadi

### **4. Case Sensitivity**
- Prefix selalu UPPERCASE (DZU, FAR, AGU)
- Untuk konsistensi dan readability

---

## 🎉 Conclusion

**Format nomor pembelian berhasil diupdate!**

**Old Format:**
```
PO202512190002
```

**New Format:**
```
DZU202512190002
```

**Benefits:**
- ✅ Tracking per operator
- ✅ Audit trail jelas
- ✅ Performance monitoring
- ✅ Unique & readable
- ✅ Easy to query

**Status:** SELESAI & SIAP DIGUNAKAN! 🚀

---

**Created:** 15 Desember 2025
**Version:** 2.0
**Feature:** Operator-Based Purchase Number
**Format:** OPERATOR(3) + YYYYMMDD(8) + URUT(4)
