mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
68 lines
3.6 KiB
Markdown
68 lines
3.6 KiB
Markdown
# Mesin Stok FIFO
|
||
|
||
Utilitas FIFO bersifat reusable dan dibagi menjadi dua lapis:
|
||
|
||
1. **Registry (`internal/utils/fifo`)** – mendeklarasikan tabel mana yang bersifat `Stockable` (sumber stok) atau `Usable` (pemakai stok). Setiap modul cukup menyebutkan nama tabel dan kolom wajib:
|
||
- Stockable: `id`, `product_warehouse_id`, `total_qty`, `total_used_qty`, `created_at`
|
||
- Usable: `id`, `product_warehouse_id`, `usage_qty`, `pending_qty`, `created_at`
|
||
2. **Service (`internal/common/service/common.fifo.service.go`)** – memakai registry tersebut untuk:
|
||
- Menambah stok baru (`Replenish`).
|
||
- Menyinkronkan total pemakaian (`Consume`). Method ini idempotent: panggil dengan *total kuantitas yang diinginkan* (mis. saat create/update/delete). Service menghitung selisih terhadap `usage_qty + pending_qty`, kemudian otomatis mengalokasikan tambahan atau melepaskan selisihnya.
|
||
- Membatalkan pemakaian (`ReleaseUsage`) yang mengembalikan stok lalu memicu alokasi ulang ke antrian pending.
|
||
- Baik `Replenish` maupun pelepasan stok akan menjalankan `resolvePendingForWarehouse`, sehingga pending tertua langsung terisi ketika stok tersedia.
|
||
|
||
## Registrasi tabel
|
||
|
||
```go
|
||
import (
|
||
commonservice "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||
"gitlab.com/mbugroup/lti-api.git/internal/utils/fifo"
|
||
)
|
||
|
||
func init() {
|
||
fifoSvc := commonservice.NewFifoService(db, stockAllocRepo, productWarehouseRepo, utils.Log)
|
||
|
||
fifoSvc.RegisterStockable(fifo.StockableConfig{
|
||
Key: fifo.StockableKey("PURCHASE_DETAIL"),
|
||
Table: "purchase_details",
|
||
Columns: fifo.StockableColumns{
|
||
ID: "id",
|
||
ProductWarehouseID: "product_warehouse_id",
|
||
TotalQuantity: "total_qty",
|
||
TotalUsedQuantity: "total_used_qty",
|
||
CreatedAt: "created_at",
|
||
},
|
||
})
|
||
|
||
fifoSvc.RegisterUsable(fifo.UsableConfig{
|
||
Key: fifo.UsableKey("RECORDING_STOCK"),
|
||
Table: "recording_stocks",
|
||
Columns: fifo.UsableColumns{
|
||
ID: "id",
|
||
ProductWarehouseID: "product_warehouse_id",
|
||
UsageQuantity: "usage_qty",
|
||
PendingQuantity: "pending_qty",
|
||
CreatedAt: "created_at",
|
||
},
|
||
})
|
||
}
|
||
```
|
||
|
||
Each registration optionally accepts an order clause or base scope (e.g. to exclude drafts).
|
||
|
||
Setiap registrasi bisa diberi klausa urutan atau scope dasar (mis. untuk mengecualikan draft).
|
||
|
||
## Menggunakan service di modul
|
||
|
||
1. **Saat stok masuk** (mis. purchase selesai): panggil `fifoSvc.Replenish(...)` dengan key stockable, id record, id product warehouse, dan kuantitas yang baru tersedia. Service akan:
|
||
- Menambah `total_qty` pada tabel stockable,
|
||
- Menambah `product_warehouses.quantity`,
|
||
- Mencoba membersihkan `pending_qty` dari semua usable yang terdaftar (sesuai urutan FIFO).
|
||
2. **Saat modul memakai stok** (recording, marketing, dsb.) panggil `fifoSvc.Consume(...)` dengan total qty terbaru.
|
||
- Jika qty baru lebih besar, service mengambil stok FIFO dan menambah `usage_qty`; kekurangan dicatat sebagai `pending_qty`.
|
||
- Jika qty baru lebih kecil, service otomatis menurunkan `pending_qty` lebih dulu, lalu melepaskan alokasi aktif (stok kembali ke gudang) dan langsung dipakai untuk mengisi pending milik entitas lain.
|
||
- Hapus data? panggil `Consume` dengan qty 0 atau gunakan `ReleaseUsage`.
|
||
3. **Jika dibatalkan penuh**: `fifoSvc.ReleaseUsage(...)` mengosongkan `usage_qty/pending_qty` dan menandai baris pivot sebagai `RELEASED`.
|
||
|
||
Tabel pivot (`stock_allocations`) menyimpan asal pemakaian secara presisi, sehingga audit trail dan rollback stok menjadi deterministik.
|