fix perhitunga sapronak

This commit is contained in:
giovanni
2026-04-21 19:30:03 +07:00
parent 1e34a0e7b2
commit ded8be198a
8 changed files with 433 additions and 35 deletions
@@ -153,6 +153,20 @@ func ToSapronakProjectAggregatedFromReport(report *SapronakReportDTO, flag strin
}
return normalized
}
normalizeCutOverToken := func(raw string) string {
normalized := strings.ToUpper(strings.TrimSpace(raw))
normalized = strings.ReplaceAll(normalized, "-", "")
normalized = strings.ReplaceAll(normalized, " ", "")
return normalized
}
containsCutOver := func(values ...string) bool {
for _, value := range values {
if strings.Contains(normalizeCutOverToken(value), "CUTOVER") {
return true
}
}
return false
}
filter := normalizeFlag(flag)
byFlag := map[string]**SapronakCategoryDTO{}
@@ -258,6 +272,7 @@ func ToSapronakProjectAggregatedFromReport(report *SapronakReportDTO, flag strin
UnitPrice: item.Harga,
Notes: "-",
}
isCutOver := containsCutOver(baseRow.ProductCategory, baseRow.Description, item.ProductName)
row := getOrCreateRow(productKey, baseRow)
@@ -289,11 +304,21 @@ func ToSapronakProjectAggregatedFromReport(report *SapronakReportDTO, flag strin
}
row.QtyUsed += item.QtyKeluar
row.TotalAmount += item.QtyKeluar * price
case "adjustment keluar", "mutasi keluar", "penjualan":
case "adjustment keluar":
price := row.UnitPrice
if price == 0 {
price = item.Harga
}
if row.UnitPrice == 0 {
row.UnitPrice = price
}
if isCutOver {
row.QtyUsed += item.QtyKeluar
row.TotalAmount += item.QtyKeluar * price
continue
}
row.QtyOut += item.QtyKeluar
case "mutasi keluar", "penjualan":
row.QtyOut += item.QtyKeluar
if strings.ToLower(item.JenisTransaksi) == "mutasi keluar" {
ref := strings.ToUpper(strings.TrimSpace(item.NoReferensi))
@@ -0,0 +1,124 @@
package dto
import "testing"
func TestToSapronakProjectAggregatedFromReportMovesCutOverAdjustmentOutToQtyUsed(t *testing.T) {
tests := []struct {
name string
groupFlag string
filter string
productFlag string
}{
{
name: "pakan cut-over",
groupFlag: "PAKAN",
filter: "PAKAN",
productFlag: "PAKAN CUT-OVER",
},
{
name: "ovk cut over",
groupFlag: "OVK",
filter: "OVK",
productFlag: "OVK CUT OVER",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
report := &SapronakReportDTO{
Groups: []SapronakGroupDTO{
{
Flag: tc.groupFlag,
Items: []SapronakDetailDTO{
{
ProductID: 1,
ProductName: "CUTOVER ITEM",
NoReferensi: "ADJ-CUT-01",
JenisTransaksi: "Adjustment Keluar",
QtyKeluar: 5,
Harga: 15000,
},
},
},
},
}
result := ToSapronakProjectAggregatedFromReport(
report,
tc.filter,
map[uint][]string{
1: {tc.productFlag},
},
)
var cat *SapronakCategoryDTO
if tc.groupFlag == "PAKAN" {
cat = result.Pakan
} else {
cat = result.Ovk
}
if cat == nil {
t.Fatalf("expected category payload for %s", tc.groupFlag)
}
if len(cat.Rows) != 1 {
t.Fatalf("expected 1 row, got %d", len(cat.Rows))
}
row := cat.Rows[0]
if row.QtyOut != 0 {
t.Fatalf("expected qty_out 0 for cut-over adjustment, got %.2f", row.QtyOut)
}
if row.QtyUsed != 5 {
t.Fatalf("expected qty_used 5 for cut-over adjustment, got %.2f", row.QtyUsed)
}
if row.UnitPrice != 15000 {
t.Fatalf("expected unit_price 15000, got %.2f", row.UnitPrice)
}
if row.TotalAmount != 75000 {
t.Fatalf("expected total_amount 75000, got %.2f", row.TotalAmount)
}
})
}
}
func TestToSapronakProjectAggregatedFromReportKeepsNonCutOverAdjustmentOutInQtyOut(t *testing.T) {
report := &SapronakReportDTO{
Groups: []SapronakGroupDTO{
{
Flag: "PAKAN",
Items: []SapronakDetailDTO{
{
ProductID: 7,
ProductName: "PAKAN REGULER",
NoReferensi: "ADJ-REG-01",
JenisTransaksi: "Adjustment Keluar",
QtyKeluar: 3,
Harga: 12000,
},
},
},
},
}
result := ToSapronakProjectAggregatedFromReport(
report,
"PAKAN",
map[uint][]string{
7: {"PAKAN"},
},
)
if result.Pakan == nil || len(result.Pakan.Rows) != 1 {
t.Fatalf("expected 1 pakan row, got %+v", result.Pakan)
}
row := result.Pakan.Rows[0]
if row.QtyOut != 3 {
t.Fatalf("expected qty_out 3 for non cut-over adjustment, got %.2f", row.QtyOut)
}
if row.QtyUsed != 0 {
t.Fatalf("expected qty_used 0 for non cut-over adjustment, got %.2f", row.QtyUsed)
}
if row.TotalAmount != 0 {
t.Fatalf("expected total_amount 0 for non cut-over adjustment, got %.2f", row.TotalAmount)
}
}