mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
adjust export recording jumlah sapronak
This commit is contained in:
@@ -79,8 +79,6 @@ func setRecordingExportColumns(file *excelize.File, sheet string) error {
|
|||||||
"AB": 18,
|
"AB": 18,
|
||||||
"AC": 24,
|
"AC": 24,
|
||||||
"AD": 18,
|
"AD": 18,
|
||||||
"AE": 18,
|
|
||||||
"AF": 18,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for col, width := range columnWidths {
|
for col, width := range columnWidths {
|
||||||
@@ -100,7 +98,7 @@ func setRecordingExportColumns(file *excelize.File, sheet string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setRecordingExportHeaders(file *excelize.File, sheet string) error {
|
func setRecordingExportHeaders(file *excelize.File, sheet string) error {
|
||||||
verticalHeaderCols := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF"}
|
verticalHeaderCols := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "Y", "Z", "AA", "AB", "AC", "AD"}
|
||||||
for _, col := range verticalHeaderCols {
|
for _, col := range verticalHeaderCols {
|
||||||
if err := file.MergeCell(sheet, col+"1", col+"2"); err != nil {
|
if err := file.MergeCell(sheet, col+"1", col+"2"); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -121,10 +119,8 @@ func setRecordingExportHeaders(file *excelize.File, sheet string) error {
|
|||||||
"Z1": "Catatan Approval",
|
"Z1": "Catatan Approval",
|
||||||
"AA1": "Dibuat Oleh",
|
"AA1": "Dibuat Oleh",
|
||||||
"AB1": "Tanggal Submit",
|
"AB1": "Tanggal Submit",
|
||||||
"AC1": "Nama Pakan",
|
"AC1": "Nama Sapronak",
|
||||||
"AD1": "Jumlah Input Pakan",
|
"AD1": "Jumlah Input Sapronak",
|
||||||
"AE1": "Jumlah Penggunaan",
|
|
||||||
"AF1": "Pending Qty",
|
|
||||||
}
|
}
|
||||||
for cell, value := range headerValues {
|
for cell, value := range headerValues {
|
||||||
if err := file.SetCellValue(sheet, cell, value); err != nil {
|
if err := file.SetCellValue(sheet, cell, value); err != nil {
|
||||||
@@ -238,7 +234,7 @@ func setRecordingExportHeaders(file *excelize.File, sheet string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return file.SetCellStyle(sheet, "A1", "AF2", headerStyle)
|
return file.SetCellStyle(sheet, "A1", "AD2", headerStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setRecordingExportRows(file *excelize.File, sheet string, items []dto.RecordingListDTO) error {
|
func setRecordingExportRows(file *excelize.File, sheet string, items []dto.RecordingListDTO) error {
|
||||||
@@ -249,12 +245,14 @@ func setRecordingExportRows(file *excelize.File, sheet string, items []dto.Recor
|
|||||||
columns := []string{
|
columns := []string{
|
||||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
|
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
|
||||||
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB",
|
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB",
|
||||||
"AC", "AD", "AE", "AF",
|
"AC", "AD",
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, item := range items {
|
currentRow := 3
|
||||||
rowNumber := i + 3
|
type rowRange struct{ start, end int }
|
||||||
|
itemRanges := make([]rowRange, 0, len(items))
|
||||||
|
|
||||||
|
for i, item := range items {
|
||||||
fcrStd := 0.0
|
fcrStd := 0.0
|
||||||
if item.ProjectFlock.Fcr != nil {
|
if item.ProjectFlock.Fcr != nil {
|
||||||
fcrStd = item.ProjectFlock.Fcr.FcrStd
|
fcrStd = item.ProjectFlock.Fcr.FcrStd
|
||||||
@@ -292,73 +290,79 @@ func setRecordingExportRows(file *excelize.File, sheet string, items []dto.Recor
|
|||||||
createdBy = safeExportText(item.Approval.ActionBy.Name)
|
createdBy = safeExportText(item.Approval.ActionBy.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build feed usage columns — concatenate multiple feeds with newline
|
// Expand recordings into one row per sapronak
|
||||||
feedNames := make([]string, 0, len(item.FeedUsage))
|
type sapronakRow struct {
|
||||||
usageAmounts := make([]string, 0, len(item.FeedUsage))
|
name string
|
||||||
pendingQtys := make([]string, 0, len(item.FeedUsage))
|
input string
|
||||||
inputQtys := make([]string, 0, len(item.FeedUsage))
|
|
||||||
for _, fu := range item.FeedUsage {
|
|
||||||
feedNames = append(feedNames, safeExportText(fu.ProductName))
|
|
||||||
usageAmounts = append(usageAmounts, formatNumberID(fu.UsageAmount, 2, true))
|
|
||||||
pendingQtys = append(pendingQtys, formatNumberID(fu.PendingQty, 2, true))
|
|
||||||
inputQtys = append(inputQtys, formatNumberID(fu.UsageAmount+fu.PendingQty, 2, true))
|
|
||||||
}
|
}
|
||||||
|
sapronaks := make([]sapronakRow, 0)
|
||||||
feedNameCol := "-"
|
if len(item.FeedUsage) > 0 {
|
||||||
usageCol := "-"
|
for _, fu := range item.FeedUsage {
|
||||||
pendingCol := "-"
|
sapronaks = append(sapronaks, sapronakRow{
|
||||||
inputCol := "-"
|
name: safeExportText(fu.ProductName),
|
||||||
if len(feedNames) > 0 {
|
input: formatNumberID(fu.UsageAmount+fu.PendingQty, 2, true),
|
||||||
feedNameCol = strings.Join(feedNames, "\n")
|
})
|
||||||
usageCol = strings.Join(usageAmounts, "\n")
|
|
||||||
pendingCol = strings.Join(pendingQtys, "\n")
|
|
||||||
inputCol = strings.Join(inputQtys, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
rowValues := []interface{}{
|
|
||||||
i + 1,
|
|
||||||
locationName,
|
|
||||||
safeExportText(item.ProjectFlock.FlockName),
|
|
||||||
kandangName,
|
|
||||||
item.ProjectFlock.Period,
|
|
||||||
formatCategoryLabel(item.ProjectFlock.ProjectFlockCategory),
|
|
||||||
formatAgeLabel(item),
|
|
||||||
formatDateIndonesian(item.RecordDatetime),
|
|
||||||
formatNumberID(item.ProjectFlock.TotalChickQty, 0, false),
|
|
||||||
formatNumberID(item.FcrValue, 2, true),
|
|
||||||
formatNumberID(fcrStd, 2, true),
|
|
||||||
formatNumberID(item.FeedIntake, 2, true),
|
|
||||||
formatNumberID(feedIntakeStd, 2, true),
|
|
||||||
formatPercentID(item.CumDepletionRate, 2),
|
|
||||||
formatPercentID(maxDepletionStd, 2),
|
|
||||||
formatNumberID(item.TotalDepletionQty, 2, true),
|
|
||||||
formatNumberID(item.EggMass, 2, true),
|
|
||||||
formatNumberID(eggMassStd, 2, true),
|
|
||||||
formatNumberID(item.EggWeight, 2, true),
|
|
||||||
formatNumberID(eggWeightStd, 2, true),
|
|
||||||
formatPercentID(item.HenDay, 2),
|
|
||||||
formatPercentID(henDayStd, 2),
|
|
||||||
formatPercentID(item.HenHouse, 2),
|
|
||||||
formatPercentID(henHouseStd, 2),
|
|
||||||
formatApprovalStatus(item),
|
|
||||||
safeExportText(pointerString(item.Approval.Notes)),
|
|
||||||
createdBy,
|
|
||||||
formatDateIndonesian(item.CreatedAt),
|
|
||||||
feedNameCol, // AC
|
|
||||||
inputCol, // AD - Jumlah Input Pakan
|
|
||||||
usageCol, // AE - Jumlah Penggunaan
|
|
||||||
pendingCol, // AF - Pending Qty
|
|
||||||
}
|
|
||||||
|
|
||||||
for idx, col := range columns {
|
|
||||||
cell := fmt.Sprintf("%s%d", col, rowNumber)
|
|
||||||
if err := file.SetCellValue(sheet, cell, rowValues[idx]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
sapronaks = append(sapronaks, sapronakRow{name: "-", input: "-"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groupStart := currentRow
|
||||||
|
|
||||||
|
for sIdx, s := range sapronaks {
|
||||||
|
if sIdx == 0 {
|
||||||
|
rowValues := []interface{}{
|
||||||
|
i + 1, // A
|
||||||
|
locationName, // B
|
||||||
|
safeExportText(item.ProjectFlock.FlockName), // C
|
||||||
|
kandangName, // D
|
||||||
|
item.ProjectFlock.Period, // E
|
||||||
|
formatCategoryLabel(item.ProjectFlock.ProjectFlockCategory), // F
|
||||||
|
formatAgeLabel(item), // G
|
||||||
|
formatDateIndonesian(item.RecordDatetime), // H
|
||||||
|
formatNumberID(item.ProjectFlock.TotalChickQty, 0, false), // I
|
||||||
|
formatNumberID(item.FcrValue, 2, true), // J
|
||||||
|
formatNumberID(fcrStd, 2, true), // K
|
||||||
|
formatNumberID(item.FeedIntake, 2, true), // L
|
||||||
|
formatNumberID(feedIntakeStd, 2, true), // M
|
||||||
|
formatPercentID(item.CumDepletionRate, 2), // N
|
||||||
|
formatPercentID(maxDepletionStd, 2), // O
|
||||||
|
formatNumberID(item.TotalDepletionQty, 2, true), // P
|
||||||
|
formatNumberID(item.EggMass, 2, true), // Q
|
||||||
|
formatNumberID(eggMassStd, 2, true), // R
|
||||||
|
formatNumberID(item.EggWeight, 2, true), // S
|
||||||
|
formatNumberID(eggWeightStd, 2, true), // T
|
||||||
|
formatPercentID(item.HenDay, 2), // U
|
||||||
|
formatPercentID(henDayStd, 2), // V
|
||||||
|
formatPercentID(item.HenHouse, 2), // W
|
||||||
|
formatPercentID(henHouseStd, 2), // X
|
||||||
|
formatApprovalStatus(item), // Y
|
||||||
|
safeExportText(pointerString(item.Approval.Notes)), // Z
|
||||||
|
createdBy, // AA
|
||||||
|
formatDateIndonesian(item.CreatedAt), // AB
|
||||||
|
s.name, // AC
|
||||||
|
s.input, // AD
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, col := range columns {
|
||||||
|
cell := fmt.Sprintf("%s%d", col, currentRow)
|
||||||
|
if err := file.SetCellValue(sheet, cell, rowValues[idx]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
file.SetCellValue(sheet, fmt.Sprintf("AC%d", currentRow), s.name)
|
||||||
|
file.SetCellValue(sheet, fmt.Sprintf("AD%d", currentRow), s.input)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentRow++
|
||||||
|
}
|
||||||
|
|
||||||
|
itemRanges = append(itemRanges, rowRange{groupStart, currentRow - 1})
|
||||||
}
|
}
|
||||||
|
|
||||||
lastRow := len(items) + 2
|
lastRow := currentRow - 1
|
||||||
|
|
||||||
dataCenterStyle, err := file.NewStyle(&excelize.Style{
|
dataCenterStyle, err := file.NewStyle(&excelize.Style{
|
||||||
Alignment: &excelize.Alignment{
|
Alignment: &excelize.Alignment{
|
||||||
Horizontal: "center",
|
Horizontal: "center",
|
||||||
@@ -375,7 +379,7 @@ func setRecordingExportRows(file *excelize.File, sheet string, items []dto.Recor
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := file.SetCellStyle(sheet, "A3", fmt.Sprintf("AF%d", lastRow), dataCenterStyle); err != nil {
|
if err := file.SetCellStyle(sheet, "A3", fmt.Sprintf("AD%d", lastRow), dataCenterStyle); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,6 +407,55 @@ func setRecordingExportRows(file *excelize.File, sheet string, items []dto.Recor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply bottom border on the last sapronak row of each recording group
|
||||||
|
// Separate styles to preserve alignment (AC=left, AD=center) and thin borders
|
||||||
|
borderBottomLeftStyle, err := file.NewStyle(&excelize.Style{
|
||||||
|
Alignment: &excelize.Alignment{
|
||||||
|
Horizontal: "left",
|
||||||
|
Vertical: "center",
|
||||||
|
WrapText: true,
|
||||||
|
},
|
||||||
|
Border: []excelize.Border{
|
||||||
|
{Type: "left", Color: "E6E6E6", Style: 1},
|
||||||
|
{Type: "top", Color: "E6E6E6", Style: 1},
|
||||||
|
{Type: "bottom", Color: "999999", Style: 2},
|
||||||
|
{Type: "right", Color: "E6E6E6", Style: 1},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
borderBottomCenterStyle, err := file.NewStyle(&excelize.Style{
|
||||||
|
Alignment: &excelize.Alignment{
|
||||||
|
Horizontal: "center",
|
||||||
|
Vertical: "center",
|
||||||
|
WrapText: true,
|
||||||
|
},
|
||||||
|
Border: []excelize.Border{
|
||||||
|
{Type: "left", Color: "E6E6E6", Style: 1},
|
||||||
|
{Type: "top", Color: "E6E6E6", Style: 1},
|
||||||
|
{Type: "bottom", Color: "999999", Style: 2},
|
||||||
|
{Type: "right", Color: "E6E6E6", Style: 1},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeCols := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
|
||||||
|
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB",
|
||||||
|
}
|
||||||
|
for _, rng := range itemRanges {
|
||||||
|
if rng.end > rng.start {
|
||||||
|
for _, col := range mergeCols {
|
||||||
|
file.MergeCell(sheet, fmt.Sprintf("%s%d", col, rng.start), fmt.Sprintf("%s%d", col, rng.end))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.SetCellStyle(sheet, fmt.Sprintf("AC%d", rng.end), fmt.Sprintf("AC%d", rng.end), borderBottomLeftStyle)
|
||||||
|
file.SetCellStyle(sheet, fmt.Sprintf("AD%d", rng.end), fmt.Sprintf("AD%d", rng.end), borderBottomCenterStyle)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user