218 lines
4.9 KiB
Markdown
218 lines
4.9 KiB
Markdown
# Purchase Realization Design
|
|
|
|
## Tujuan
|
|
|
|
Menyediakan model data dan alur kalkulasi untuk melacak satu purchase dari:
|
|
|
|
- pembelian awal
|
|
- receipt menjadi lot
|
|
- washing
|
|
- regrade / mix / split
|
|
- regular sale
|
|
- consignment
|
|
- office buyout
|
|
|
|
sampai status akhir purchase dapat dinyatakan `CLOSED` dan laba/rugi agent dapat dihitung final.
|
|
|
|
## Prinsip
|
|
|
|
- `Purchase Analysis` tetap dipakai sebagai snapshot awal pembelian.
|
|
- `Purchase Realization` dipakai sebagai hasil aktual setelah barang bergerak dan terjual.
|
|
- Setiap lot harus bisa dilacak asal purchase-nya, termasuk jika hasil mix atau regrade.
|
|
- Setiap event yang memengaruhi qty atau nilai harus menulis jurnal realization.
|
|
|
|
## Model Baru
|
|
|
|
### `lot_purchase_allocations`
|
|
|
|
Menyimpan komposisi asal purchase untuk setiap lot.
|
|
|
|
Contoh:
|
|
|
|
- Lot `LOT-A` berasal 100% dari purchase `P-1`
|
|
- Lot `LOT-B` hasil mix dari `P-1` 40% dan `P-2` 60%
|
|
|
|
Maka `LOT-B` memiliki 2 allocation rows.
|
|
|
|
Kolom penting:
|
|
|
|
- `lot_id`
|
|
- `purchase_id`
|
|
- `purchase_line_id`
|
|
- `source_type`
|
|
- `source_ref_id`
|
|
- `qty_allocated`
|
|
- `cost_total_allocated`
|
|
- `unit_cost_snapshot`
|
|
- `agent_id_snapshot`
|
|
- `profit_share_scheme_id_snapshot`
|
|
|
|
### `purchase_realization_entries`
|
|
|
|
Ledger event yang memengaruhi hasil akhir purchase.
|
|
|
|
Kolom penting:
|
|
|
|
- `purchase_id`
|
|
- `lot_id`
|
|
- `allocation_id`
|
|
- `event_type`
|
|
- `reference_type`
|
|
- `reference_id`
|
|
- `occurred_at`
|
|
- `qty_in`
|
|
- `qty_out`
|
|
- `qty_shrinkage`
|
|
- `amount_cost`
|
|
- `amount_revenue`
|
|
- `amount_expense`
|
|
- `amount_profit`
|
|
- `agent_share_percent_snapshot`
|
|
- `agent_amount`
|
|
|
|
Event type awal yang direkomendasikan:
|
|
|
|
- `OPENING_COST`
|
|
- `WASHING_COST`
|
|
- `WASHING_SHRINKAGE`
|
|
- `TRANSFORMATION_SHRINKAGE`
|
|
- `SALE_REVENUE`
|
|
- `SALE_RETURN`
|
|
- `SALE_SHRINKAGE`
|
|
- `CONSIGNMENT_REVENUE`
|
|
- `CONSIGNMENT_RETURN`
|
|
- `CONSIGNMENT_SHRINKAGE`
|
|
- `OFFICE_BUYOUT_REVENUE`
|
|
- `OFFICE_BUYOUT_TRANSFER_OUT`
|
|
- `STOCK_ADJUSTMENT_LOSS`
|
|
- `STOCK_ADJUSTMENT_GAIN`
|
|
- `MANUAL_ADJUSTMENT`
|
|
|
|
### `purchase_realization_summaries`
|
|
|
|
Cache summary per purchase untuk kebutuhan UI dan closing.
|
|
|
|
Kolom penting:
|
|
|
|
- `status`
|
|
- `qty_opening`
|
|
- `qty_remaining`
|
|
- `qty_sold`
|
|
- `qty_returned`
|
|
- `qty_shrinkage`
|
|
- `cost_opening_total`
|
|
- `cost_additional_total`
|
|
- `revenue_total`
|
|
- `profit_loss_total`
|
|
- `agent_share_percent`
|
|
- `agent_profit_total`
|
|
- `closed_at`
|
|
|
|
Status yang direkomendasikan:
|
|
|
|
- `OPEN`
|
|
- `PARTIAL`
|
|
- `READY_TO_CLOSE`
|
|
- `CLOSED`
|
|
|
|
## Aturan Alokasi
|
|
|
|
### Purchase submit
|
|
|
|
- Buat lot seperti implementasi saat ini.
|
|
- Buat 1 allocation row per lot:
|
|
- `source_type = PURCHASE`
|
|
- `qty_allocated = lot.original_qty`
|
|
- `cost_total_allocated = qty * unit_cost`
|
|
- Buat 1 realization entry:
|
|
- `event_type = OPENING_COST`
|
|
|
|
### Washing selesai
|
|
|
|
- Allocation lot tidak berubah.
|
|
- Jika ada biaya cuci, tulis `WASHING_COST`.
|
|
- Jika ada susut, tulis `WASHING_SHRINKAGE`.
|
|
- Semua entry dibagi ke purchase asal berdasarkan allocation aktif lot tersebut.
|
|
|
|
### Transformation / regrade / mix
|
|
|
|
- Baca allocation dari semua source lots.
|
|
- Bentuk allocation baru pada output lots dengan distribusi proporsional terhadap qty / cost input.
|
|
- Jika ada processing loss, buat `TRANSFORMATION_SHRINKAGE`.
|
|
- Output lot mewarisi allocation campuran dari input.
|
|
|
|
### Regular sale close
|
|
|
|
- Baca allocation lot pada line yang dijual.
|
|
- Revenue aktual dibagi ke purchase asal sesuai allocation.
|
|
- Tulis:
|
|
- `SALE_REVENUE`
|
|
- `SALE_RETURN`
|
|
- `SALE_SHRINKAGE`
|
|
|
|
### Consignment close
|
|
|
|
- Perlakuan sama seperti regular sale, tetapi sumber event adalah consignment line.
|
|
|
|
### Office buyout
|
|
|
|
Untuk purchase lama:
|
|
|
|
- Tulis `OFFICE_BUYOUT_REVENUE`
|
|
- `qty_out` sebesar qty yang dibeli kantor
|
|
- `amount_revenue = qty * buyout_unit_price`
|
|
|
|
Untuk lot baru hasil buyout:
|
|
|
|
- Buat allocation baru yang menunjuk purchase buyout / jalur kantor
|
|
- Setelah itu hasil jual berikutnya tidak lagi menjadi hak agent lama
|
|
|
|
## Rumus Summary
|
|
|
|
- `cost_opening_total` = total opening cost
|
|
- `cost_additional_total` = washing cost + biaya tambahan + adjustment
|
|
- `revenue_total` = sale + consignment + office buyout
|
|
- `profit_loss_total = revenue_total - cost_opening_total - cost_additional_total`
|
|
- `agent_profit_total = akumulasi agent_amount` atau fallback `profit_loss_total * share_agent / 100`
|
|
|
|
## Rule Closing Purchase
|
|
|
|
Purchase dapat `CLOSED` jika seluruh qty asal purchase sudah terselesaikan menjadi salah satu:
|
|
|
|
- terjual
|
|
- susut
|
|
- dibuyout kantor
|
|
- habis masuk transformasi dan seluruh descendant lots-nya selesai
|
|
|
|
Artinya closing harus melihat seluruh lineage lot, bukan hanya lot awal purchase.
|
|
|
|
## Scope Implementasi Bertahap
|
|
|
|
### Tahap 1
|
|
|
|
- Tambah schema baru
|
|
- Isi allocation + opening realization saat purchase submit
|
|
- Tambah summary recalculation dasar
|
|
|
|
### Tahap 2
|
|
|
|
- Integrasi office buyout
|
|
- Integrasi washing cost dan shrinkage
|
|
|
|
### Tahap 3
|
|
|
|
- Integrasi transformation / mix / regrade allocation propagation
|
|
|
|
### Tahap 4
|
|
|
|
- Integrasi regular sale dan consignment revenue realization
|
|
|
|
### Tahap 5
|
|
|
|
- UI `Purchase Realization`
|
|
- closing otomatis
|
|
|
|
### Tahap 6
|
|
|
|
- JIT sale, jika nanti ingin ditautkan ke lineage purchase
|