From b90a3cde4a86a83efd8fecf1f74394f462c47b73 Mon Sep 17 00:00:00 2001 From: ryan Date: Wed, 3 Jun 2026 13:00:50 +0700 Subject: [PATCH] Fix coa summary zero --- internal/processor/analytics_processor.go | 43 ++++++++++++++--- .../processor/analytics_processor_test.go | 46 ++++++++++--------- .../processor/product_recipe_processor.go | 4 +- internal/processor/split_bill_processor.go | 2 - internal/repository/analytics_repository.go | 6 +-- .../ingredient_unit_converter_repository.go | 1 - 6 files changed, 67 insertions(+), 35 deletions(-) diff --git a/internal/processor/analytics_processor.go b/internal/processor/analytics_processor.go index 5950023..013acdf 100644 --- a/internal/processor/analytics_processor.go +++ b/internal/processor/analytics_processor.go @@ -3,6 +3,7 @@ package processor import ( "context" "fmt" + "strings" "time" "apskel-pos-be/internal/models" @@ -480,7 +481,14 @@ func (p *AnalyticsProcessorImpl) GetProfitLossAnalytics(ctx context.Context, req var todayTotalOps float64 var mtdTotalOps float64 + var todayGaji float64 + var mtdGaji float64 for _, cat := range categoryMap { + if isSalaryExpenseCategory(cat.Name) { + todayGaji += cat.TodayAmt + mtdGaji += cat.MtdAmt + continue + } todayTotalOps += cat.TodayAmt mtdTotalOps += cat.MtdAmt } @@ -488,8 +496,11 @@ func (p *AnalyticsProcessorImpl) GetProfitLossAnalytics(ctx context.Context, req todayGrossProfit := result.TodayRevenue - result.TodayCost mtdGrossProfit := result.MtdRevenue - result.MtdCost - todayNetProfit := todayGrossProfit - todayTotalOps - mtdNetProfit := mtdGrossProfit - mtdTotalOps + todayProfitBeforeGaji := todayGrossProfit - todayTotalOps + mtdProfitBeforeGaji := mtdGrossProfit - mtdTotalOps + + todayNetProfit := todayProfitBeforeGaji - todayGaji + mtdNetProfit := mtdProfitBeforeGaji - mtdGaji todayPct := func(nominal float64) float64 { if result.TodayRevenue == 0 { @@ -505,11 +516,16 @@ func (p *AnalyticsProcessorImpl) GetProfitLossAnalytics(ctx context.Context, req } opsSubItems := make([]models.ProfitLossSummaryRow, 0, len(categoryOrder)+1) - for i, name := range categoryOrder { + opsCategoryCount := 0 + for _, name := range categoryOrder { cat := categoryMap[name] + if isSalaryExpenseCategory(cat.Name) { + continue + } + opsCategoryCount++ opsSubItems = append(opsSubItems, models.ProfitLossSummaryRow{ ID: fmt.Sprintf("by_%s", slugify(name)), - Label: fmt.Sprintf("%d. %s", i+1, cat.Name), + Label: fmt.Sprintf("%d. %s", opsCategoryCount, cat.Name), TodayNominal: cat.TodayAmt, TodayPct: todayPct(cat.TodayAmt), MtdNominal: cat.MtdAmt, @@ -518,7 +534,7 @@ func (p *AnalyticsProcessorImpl) GetProfitLossAnalytics(ctx context.Context, req } opsSubItems = append(opsSubItems, models.ProfitLossSummaryRow{ ID: "total_biaya_ops", - Label: fmt.Sprintf("Total Biaya OPS (%d kategori)", len(categoryOrder)), + Label: fmt.Sprintf("Total Biaya OPS (%d kategori)", opsCategoryCount), IsBold: true, TodayNominal: todayTotalOps, TodayPct: todayPct(todayTotalOps), @@ -549,7 +565,17 @@ func (p *AnalyticsProcessorImpl) GetProfitLossAnalytics(ctx context.Context, req SubItems: opsSubItems, }, { - ID: "laba_rugi", Label: "Laba/Rugi Bersih (3-4)", IsBold: true, + ID: "laba_rugi_sblm_gaji", Label: "Laba/Rugi sblm Gaji (3-4)", + TodayNominal: todayProfitBeforeGaji, TodayPct: todayPct(todayProfitBeforeGaji), + MtdNominal: mtdProfitBeforeGaji, MtdPct: mtdPct(mtdProfitBeforeGaji), + }, + { + ID: "biaya_gaji", Label: "BIAYA GAJI", + TodayNominal: todayGaji, TodayPct: todayPct(todayGaji), + MtdNominal: mtdGaji, MtdPct: mtdPct(mtdGaji), + }, + { + ID: "laba_rugi", Label: "Laba/Rugi (5-6)", IsBold: true, TodayNominal: todayNetProfit, TodayPct: todayPct(todayNetProfit), MtdNominal: mtdNetProfit, MtdPct: mtdPct(mtdNetProfit), }, @@ -592,6 +618,11 @@ func (p *AnalyticsProcessorImpl) GetProfitLossAnalytics(ctx context.Context, req }, nil } +func isSalaryExpenseCategory(name string) bool { + name = strings.ToLower(name) + return strings.Contains(name, "gaji") || strings.Contains(name, "salary") +} + func slugify(s string) string { result := make([]byte, 0, len(s)) for i := 0; i < len(s); i++ { diff --git a/internal/processor/analytics_processor_test.go b/internal/processor/analytics_processor_test.go index 620c3db..78fe121 100644 --- a/internal/processor/analytics_processor_test.go +++ b/internal/processor/analytics_processor_test.go @@ -200,7 +200,7 @@ func TestAnalyticsProcessorGetProfitLossAnalyticsDynamicExpenseCategories(t *tes require.NoError(t, err) require.NotNil(t, result) - require.Len(t, result.MainSummary, 5) + require.Len(t, result.MainSummary, 7) require.Equal(t, "total_omset", result.MainSummary[0].ID) require.Equal(t, float64(10000), result.MainSummary[0].TodayNominal) @@ -215,29 +215,33 @@ func TestAnalyticsProcessorGetProfitLossAnalyticsDynamicExpenseCategories(t *tes require.Equal(t, float64(12000), result.MainSummary[2].MtdNominal) require.Equal(t, "biaya_ops", result.MainSummary[3].ID) - require.Equal(t, float64(2300), result.MainSummary[3].TodayNominal) - require.Equal(t, float64(4600), result.MainSummary[3].MtdNominal) - require.Len(t, result.MainSummary[3].SubItems, 4) // 3 categories + 1 total + require.Equal(t, float64(800), result.MainSummary[3].TodayNominal) + require.Equal(t, float64(1600), result.MainSummary[3].MtdNominal) + require.Len(t, result.MainSummary[3].SubItems, 3) // 2 operational categories + 1 total - require.Equal(t, "by_gaji", result.MainSummary[3].SubItems[0].ID) - require.Equal(t, float64(1500), result.MainSummary[3].SubItems[0].TodayNominal) - require.Equal(t, float64(3000), result.MainSummary[3].SubItems[0].MtdNominal) + require.Equal(t, "by_promosi", result.MainSummary[3].SubItems[0].ID) + require.Equal(t, float64(300), result.MainSummary[3].SubItems[0].TodayNominal) + require.Equal(t, float64(600), result.MainSummary[3].SubItems[0].MtdNominal) - require.Equal(t, "by_promosi", result.MainSummary[3].SubItems[1].ID) - require.Equal(t, float64(300), result.MainSummary[3].SubItems[1].TodayNominal) - require.Equal(t, float64(600), result.MainSummary[3].SubItems[1].MtdNominal) + require.Equal(t, "by_sewa", result.MainSummary[3].SubItems[1].ID) + require.Equal(t, float64(500), result.MainSummary[3].SubItems[1].TodayNominal) + require.Equal(t, float64(1000), result.MainSummary[3].SubItems[1].MtdNominal) - require.Equal(t, "by_sewa", result.MainSummary[3].SubItems[2].ID) - require.Equal(t, float64(500), result.MainSummary[3].SubItems[2].TodayNominal) - require.Equal(t, float64(1000), result.MainSummary[3].SubItems[2].MtdNominal) + require.Equal(t, "total_biaya_ops", result.MainSummary[3].SubItems[2].ID) + require.True(t, result.MainSummary[3].SubItems[2].IsBold) + require.Equal(t, float64(800), result.MainSummary[3].SubItems[2].TodayNominal) + require.Equal(t, float64(1600), result.MainSummary[3].SubItems[2].MtdNominal) - require.Equal(t, "total_biaya_ops", result.MainSummary[3].SubItems[3].ID) - require.True(t, result.MainSummary[3].SubItems[3].IsBold) - require.Equal(t, float64(2300), result.MainSummary[3].SubItems[3].TodayNominal) - require.Equal(t, float64(4600), result.MainSummary[3].SubItems[3].MtdNominal) + require.Equal(t, "laba_rugi_sblm_gaji", result.MainSummary[4].ID) + require.Equal(t, float64(5200), result.MainSummary[4].TodayNominal) + require.Equal(t, float64(10400), result.MainSummary[4].MtdNominal) - require.Equal(t, "laba_rugi", result.MainSummary[4].ID) - require.Equal(t, float64(3700), result.MainSummary[4].TodayNominal) - require.Equal(t, float64(7400), result.MainSummary[4].MtdNominal) - require.True(t, result.MainSummary[4].IsBold) + require.Equal(t, "biaya_gaji", result.MainSummary[5].ID) + require.Equal(t, float64(1500), result.MainSummary[5].TodayNominal) + require.Equal(t, float64(3000), result.MainSummary[5].MtdNominal) + + require.Equal(t, "laba_rugi", result.MainSummary[6].ID) + require.Equal(t, float64(3700), result.MainSummary[6].TodayNominal) + require.Equal(t, float64(7400), result.MainSummary[6].MtdNominal) + require.True(t, result.MainSummary[6].IsBold) } diff --git a/internal/processor/product_recipe_processor.go b/internal/processor/product_recipe_processor.go index 831257e..5f63fa1 100644 --- a/internal/processor/product_recipe_processor.go +++ b/internal/processor/product_recipe_processor.go @@ -235,7 +235,7 @@ func (p *ProductRecipeProcessorImpl) entityToResponse(entity *entities.ProductRe CreatedAt: entity.Ingredient.CreatedAt, UpdatedAt: entity.Ingredient.UpdatedAt, } - + // Add unit if available if entity.Ingredient.Unit != nil { symbol := "" @@ -253,4 +253,4 @@ func (p *ProductRecipeProcessorImpl) entityToResponse(entity *entities.ProductRe } return response -} \ No newline at end of file +} diff --git a/internal/processor/split_bill_processor.go b/internal/processor/split_bill_processor.go index da7759c..5559125 100644 --- a/internal/processor/split_bill_processor.go +++ b/internal/processor/split_bill_processor.go @@ -22,8 +22,6 @@ const ( MetadataKeyLastSplitQuantities = "last_split_quantities" ) - - type SplitBillValidation struct { OrderItems map[uuid.UUID]*entities.OrderItem PaidQuantities map[uuid.UUID]int diff --git a/internal/repository/analytics_repository.go b/internal/repository/analytics_repository.go index b250dc9..5f90e0f 100644 --- a/internal/repository/analytics_repository.go +++ b/internal/repository/analytics_repository.go @@ -637,7 +637,7 @@ func (r *AnalyticsRepositoryImpl) getExpenseByCategory(ctx context.Context, orga query := r.db.WithContext(ctx). Table("expense_items ei"). - Select(`COALESCE(parent_coa.name, 'Lain-lain') as category_name, COALESCE(SUM(ei.amount), 0) as amount`). + Select(`COALESCE(parent_coa.name, coa.name, 'Lain-lain') as category_name, COALESCE(SUM(ei.amount), 0) as amount`). Joins("JOIN expenses e ON ei.expense_id = e.id"). Joins("JOIN chart_of_accounts coa ON ei.chart_of_account_id = coa.id"). Joins("LEFT JOIN chart_of_accounts parent_coa ON coa.parent_id = parent_coa.id"). @@ -650,8 +650,8 @@ func (r *AnalyticsRepositoryImpl) getExpenseByCategory(ctx context.Context, orga } err := query. - Group("parent_coa.name"). - Order("parent_coa.name"). + Group("COALESCE(parent_coa.name, coa.name, 'Lain-lain')"). + Order("COALESCE(parent_coa.name, coa.name, 'Lain-lain')"). Scan(&results).Error return results, err diff --git a/internal/repository/ingredient_unit_converter_repository.go b/internal/repository/ingredient_unit_converter_repository.go index 88ae55a..a8d723e 100644 --- a/internal/repository/ingredient_unit_converter_repository.go +++ b/internal/repository/ingredient_unit_converter_repository.go @@ -173,4 +173,3 @@ func (r *IngredientUnitConverterRepositoryImpl) ConvertQuantity(ctx context.Cont // If no converter found, return error return 0, fmt.Errorf("no conversion found between units %s and %s for ingredient %s", fromUnitID, toUnitID, ingredientID) } -