package controller import ( "bytes" "testing" "time" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "github.com/xuri/excelize/v2" ) func TestBuildPurchaseExportWorkbookHeadersAndRows(t *testing.T) { content, err := buildPurchaseExportWorkbook([]entity.Purchase{ buildPurchaseForExportTest( 1, "PR-00011", "PO-00011", time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC), "Supplier A", "Manager Purchase", nil, "catatan", []entity.PurchaseItem{ buildPurchaseItemForExportTest(11, "Pakan Starter", 1000000, "Location A"), buildPurchaseItemForExportTest(12, "Vitamin A", 350000, "Location B"), buildPurchaseItemForExportTest(11, "Pakan Starter", 0, ""), }, ), buildPurchaseForExportTest( 2, "PR-00012", "", time.Time{}, "Supplier B", "Manager Purchase", ptrApprovalAction(entity.ApprovalActionRejected), "", []entity.PurchaseItem{ buildPurchaseItemForExportTest(21, "Obat X", 75000, ""), }, ), }) if err != nil { t.Fatalf("buildPurchaseExportWorkbook returned error: %v", err) } file, err := excelize.OpenReader(bytes.NewReader(content)) if err != nil { t.Fatalf("failed to open workbook bytes: %v", err) } defer file.Close() expectedHeaders := map[string]string{ "A1": "PR Number", "B1": "PO Number", "C1": "Tanggal PO", "D1": "Supplier", "E1": "Lokasi", "F1": "Status", "G1": "Grand Total", "H1": "Products", "I1": "Notes", } for cell, expected := range expectedHeaders { got, err := file.GetCellValue(purchaseExportSheetName, cell) if err != nil { t.Fatalf("GetCellValue(%s) failed: %v", cell, err) } if got != expected { t.Fatalf("expected %s=%q, got %q", cell, expected, got) } } assertPurchaseCellEquals(t, file, "A2", "PR-00011") assertPurchaseCellEquals(t, file, "B2", "PO-00011") assertPurchaseCellEquals(t, file, "C2", "22-04-2026") assertPurchaseCellEquals(t, file, "D2", "Supplier A") assertPurchaseCellEquals(t, file, "E2", "Location A") assertPurchaseCellEquals(t, file, "F2", "Manager Purchase") assertPurchaseCellEquals(t, file, "G2", "Rp 1.350.000") assertPurchaseCellEquals(t, file, "H2", "Pakan Starter, Vitamin A") assertPurchaseCellEquals(t, file, "I2", "catatan") assertPurchaseCellEquals(t, file, "A3", "PR-00012") assertPurchaseCellEquals(t, file, "B3", "-") assertPurchaseCellEquals(t, file, "C3", "-") assertPurchaseCellEquals(t, file, "E3", "-") assertPurchaseCellEquals(t, file, "F3", "Ditolak") assertPurchaseCellEquals(t, file, "G3", "Rp 75.000") assertPurchaseCellEquals(t, file, "H3", "Obat X") assertPurchaseCellEquals(t, file, "I3", "-") } func assertPurchaseCellEquals(t *testing.T, file *excelize.File, cell, expected string) { t.Helper() got, err := file.GetCellValue(purchaseExportSheetName, cell) if err != nil { t.Fatalf("GetCellValue(%s) failed: %v", cell, err) } if got != expected { t.Fatalf("expected %s=%q, got %q", cell, expected, got) } } func buildPurchaseForExportTest( id uint, prNumber, poNumber string, poDate time.Time, supplierName, stepName string, action *entity.ApprovalAction, notes string, items []entity.PurchaseItem, ) entity.Purchase { var poNumberRef *string if poNumber != "" { poNumberRef = &poNumber } var poDateRef *time.Time if !poDate.IsZero() { poDateRef = &poDate } var notesRef *string if notes != "" { notesRef = ¬es } return entity.Purchase{ Id: id, PrNumber: prNumber, PoNumber: poNumberRef, PoDate: poDateRef, Notes: notesRef, Supplier: entity.Supplier{ Id: id + 100, Name: supplierName, }, LatestApproval: &entity.Approval{ Id: id + 1000, StepName: stepName, Action: action, }, Items: items, } } func buildPurchaseItemForExportTest(productID uint, productName string, totalPrice float64, locationName string) entity.PurchaseItem { item := entity.PurchaseItem{ ProductId: productID, TotalPrice: totalPrice, Product: &entity.Product{ Id: productID, Name: productName, }, } if locationName != "" { locationID := productID + 1000 warehouseID := productID + 500 item.Warehouse = &entity.Warehouse{ Id: warehouseID, Location: &entity.Location{ Id: locationID, Name: locationName, }, } } return item } func ptrApprovalAction(value entity.ApprovalAction) *entity.ApprovalAction { return &value }