add export excel from api

This commit is contained in:
giovanni
2026-04-22 22:50:20 +07:00
parent ff630a1ed0
commit 3e99caf3a7
5 changed files with 946 additions and 0 deletions
@@ -0,0 +1,281 @@
package controller
import (
"bytes"
"reflect"
"strings"
"testing"
"time"
approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto"
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
nonstockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/nonstocks/dto"
supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto"
"gitlab.com/mbugroup/lti-api.git/internal/modules/repports/dto"
"github.com/xuri/excelize/v2"
)
func TestBuildExpenseReportExportWorkbookHeadersAndRows(t *testing.T) {
realizationDate := time.Date(2026, time.April, 23, 0, 0, 0, 0, time.UTC)
items := []dto.RepportExpenseListDTO{
buildExpenseExportTestItem(
"REF-0001",
"PO-0001",
"BOP",
"UPAH",
"Darawati",
"Darawati C1",
time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC),
&realizationDate,
2,
10000,
20000,
2,
9000,
18000,
"Realisasi",
nil,
),
buildExpenseExportTestItem(
"REF-0002",
"PO-0002",
"BOP",
"TRANSPORT 2",
"",
"",
time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC),
&realizationDate,
1,
50000,
50000,
1,
50000,
50000,
"Pengajuan",
strPtr("REJECTED"),
),
buildExpenseExportTestItem(
"REF-0003",
"PO-0003",
"BOP",
"TRANSPORT",
"Jamali",
"Jamali 1",
time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC),
&realizationDate,
3,
12000,
36000,
2,
11000,
22000,
"Selesai",
nil,
),
buildExpenseExportTestItem(
"REF-0004",
"PO-0004",
"BOP",
"TRANSPORT",
"Jamali",
"Jamali 2",
time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC),
&realizationDate,
1,
8000,
8000,
1,
8000,
8000,
"Realisasi",
nil,
),
buildExpenseExportTestItem(
"REF-0005",
"PO-0005",
"BOP",
"ZZZ CUSTOM",
"",
"",
time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC),
nil,
1,
7000,
7000,
1,
7000,
7000,
"",
nil,
),
}
content, err := buildExpenseReportExportWorkbook(items)
if err != nil {
t.Fatalf("buildExpenseReportExportWorkbook 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()
expectedSheetOrder := []string{"UPAH", "EKSPEDISI ADE", "EKSPEDISI LTI", "ZZZ CUSTOM"}
if got := file.GetSheetList(); !reflect.DeepEqual(got, expectedSheetOrder) {
t.Fatalf("unexpected sheet order: got %v expected %v", got, expectedSheetOrder)
}
expectedHeaders := map[string]string{
"A1": "No",
"B1": "No. PO",
"C1": "No. Referensi",
"D1": "Tanggal Realisasi",
"E1": "Tanggal Transaksi",
"F1": "Kategori",
"G1": "Produk",
"H1": "Lokasi",
"I1": "Kandang",
"J1": "Qty Pengajuan",
"K1": "Harga Pengajuan",
"L1": "Total Pengajuan",
"M1": "Qty Realisasi",
"N1": "Harga Realisasi",
"O1": "Total Realisasi",
"P1": "Status Pencairan",
}
for cell, expected := range expectedHeaders {
assertExpenseSheetCellEquals(t, file, "UPAH", cell, expected)
}
assertExpenseSheetCellEquals(t, file, "UPAH", "A2", "1")
assertExpenseSheetCellEquals(t, file, "UPAH", "B2", "PO-0001")
assertExpenseSheetCellEquals(t, file, "UPAH", "C2", "REF-0001")
assertExpenseSheetCellEquals(t, file, "UPAH", "D2", "23 Apr 2026")
assertExpenseSheetCellEquals(t, file, "UPAH", "E2", "22 Apr 2026")
assertExpenseSheetCellEquals(t, file, "UPAH", "F2", "BOP")
assertExpenseSheetCellEquals(t, file, "UPAH", "G2", "UPAH")
assertExpenseSheetCellEquals(t, file, "UPAH", "H2", "Darawati")
assertExpenseSheetCellEquals(t, file, "UPAH", "I2", "Darawati C1")
assertExpenseSheetCellEquals(t, file, "UPAH", "J2", "2")
assertExpenseSheetCellEquals(t, file, "UPAH", "K2", "10000")
assertExpenseSheetCellEquals(t, file, "UPAH", "L2", "20000")
assertExpenseSheetCellEquals(t, file, "UPAH", "M2", "2")
assertExpenseSheetCellEquals(t, file, "UPAH", "N2", "9000")
assertExpenseSheetCellEquals(t, file, "UPAH", "O2", "18000")
assertExpenseSheetCellEquals(t, file, "UPAH", "P2", "Realisasi")
assertExpenseSheetCellEquals(t, file, "UPAH", "A3", "Total")
assertExpenseSheetCellEquals(t, file, "UPAH", "J3", "2")
assertExpenseSheetCellEquals(t, file, "UPAH", "K3", "0")
assertExpenseSheetCellEquals(t, file, "UPAH", "L3", "20000")
assertExpenseSheetCellEquals(t, file, "UPAH", "M3", "2")
assertExpenseSheetCellEquals(t, file, "UPAH", "N3", "0")
assertExpenseSheetCellEquals(t, file, "UPAH", "O3", "18000")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI ADE", "G2", "TRANSPORT 2")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI ADE", "P2", "Ditolak")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI ADE", "A3", "Total")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI LTI", "A2", "1")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI LTI", "A3", "2")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI LTI", "G2", "TRANSPORT")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI LTI", "G3", "TRANSPORT")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI LTI", "A4", "Total")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI LTI", "J4", "4")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI LTI", "L4", "44000")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI LTI", "M4", "3")
assertExpenseSheetCellEquals(t, file, "EKSPEDISI LTI", "O4", "30000")
assertExpenseSheetCellEquals(t, file, "ZZZ CUSTOM", "H2", "-")
assertExpenseSheetCellEquals(t, file, "ZZZ CUSTOM", "I2", "-")
assertExpenseSheetCellEquals(t, file, "ZZZ CUSTOM", "D2", "-")
assertExpenseSheetCellEquals(t, file, "ZZZ CUSTOM", "P2", "-")
for _, cell := range []string{"K2", "L2", "N2", "O2"} {
val, err := file.GetCellValue("UPAH", cell)
if err != nil {
t.Fatalf("GetCellValue(UPAH,%s) failed: %v", cell, err)
}
if strings.Contains(val, "Rp") {
t.Fatalf("expected numeric plain value in %s, got %q", cell, val)
}
}
}
func assertExpenseSheetCellEquals(t *testing.T, file *excelize.File, sheet, cell, expected string) {
t.Helper()
got, err := file.GetCellValue(sheet, cell)
if err != nil {
t.Fatalf("GetCellValue(%s,%s) failed: %v", sheet, cell, err)
}
if got != expected {
t.Fatalf("expected %s!%s=%q, got %q", sheet, cell, expected, got)
}
}
func buildExpenseExportTestItem(
reference,
poNumber,
category,
product,
location,
kandang string,
transactionDate time.Time,
realizationDate *time.Time,
qtyPengajuan,
hargaPengajuan,
totalPengajuan,
qtyRealisasi,
hargaRealisasi,
totalRealisasi float64,
stepName string,
action *string,
) dto.RepportExpenseListDTO {
item := dto.RepportExpenseListDTO{
RepportExpenseBaseDTO: dto.RepportExpenseBaseDTO{
ReferenceNumber: reference,
PoNumber: poNumber,
Category: category,
TransactionDate: transactionDate,
RealizationDate: realizationDate,
Supplier: &supplierDTO.SupplierRelationDTO{
Name: "Supplier A",
},
},
Pengajuan: dto.RepportExpensePengajuanDTO{
Qty: qtyPengajuan,
Price: hargaPengajuan,
Nonstock: &nonstockDTO.NonstockRelationDTO{
Name: product,
},
},
Realisasi: dto.RepportExpenseRealisasiDTO{
Qty: qtyRealisasi,
Price: hargaRealisasi,
Nonstock: &nonstockDTO.NonstockRelationDTO{
Name: product,
},
},
TotalPengajuan: totalPengajuan,
TotalRealisasi: totalRealisasi,
LatestApproval: &approvalDTO.ApprovalRelationDTO{
StepName: stepName,
Action: action,
},
}
if kandang != "" {
item.Kandang = &kandangDTO.KandangRelationDTO{Name: kandang}
if location != "" {
item.Kandang.Location = &locationDTO.LocationRelationDTO{Name: location}
}
}
return item
}
func strPtr(value string) *string {
return &value
}