reinstate profit loss overview

This commit is contained in:
2026-06-01 13:13:40 +07:00
parent dc13bb5f93
commit 47fa21d739
10 changed files with 541 additions and 25 deletions
+55 -4
View File
@@ -450,6 +450,7 @@ func ProfitLossAnalyticsContractToModel(req *contract.ProfitLossAnalyticsRequest
OutletID: parseOutletID(req.OutletID),
DateFrom: *dateFrom,
DateTo: *dateTo,
GroupBy: req.GroupBy,
}, nil
}
@@ -463,6 +464,40 @@ func ProfitLossAnalyticsModelToContract(resp *models.ProfitLossAnalyticsResponse
mainSummary[i] = profitLossSummaryRowModelToContract(row)
}
data := make([]contract.ProfitLossData, len(resp.Data))
for i, item := range resp.Data {
data[i] = contract.ProfitLossData{
Date: item.Date,
Revenue: item.Revenue,
Cost: item.Cost,
GrossProfit: item.GrossProfit,
GrossProfitMargin: item.GrossProfitMargin,
Tax: item.Tax,
Discount: item.Discount,
NetProfit: item.NetProfit,
NetProfitMargin: item.NetProfitMargin,
Orders: item.Orders,
}
}
productData := make([]contract.ProductProfitData, len(resp.ProductData))
for i, item := range resp.ProductData {
productData[i] = contract.ProductProfitData{
ProductID: item.ProductID,
ProductName: item.ProductName,
CategoryID: item.CategoryID,
CategoryName: item.CategoryName,
QuantitySold: item.QuantitySold,
Revenue: item.Revenue,
Cost: item.Cost,
GrossProfit: item.GrossProfit,
GrossProfitMargin: item.GrossProfitMargin,
AveragePrice: item.AveragePrice,
AverageCost: item.AverageCost,
ProfitPerUnit: item.ProfitPerUnit,
}
}
opsItems := make([]contract.OperationalExpenseItem, len(resp.OperationalExpenses))
for i, item := range resp.OperationalExpenses {
opsItems[i] = contract.OperationalExpenseItem{
@@ -472,10 +507,26 @@ func ProfitLossAnalyticsModelToContract(resp *models.ProfitLossAnalyticsResponse
}
return &contract.ProfitLossAnalyticsResponse{
OrganizationID: resp.OrganizationID,
OutletID: resp.OutletID,
DateFrom: resp.DateFrom,
DateTo: resp.DateTo,
OrganizationID: resp.OrganizationID,
OutletID: resp.OutletID,
DateFrom: resp.DateFrom,
DateTo: resp.DateTo,
GroupBy: resp.GroupBy,
Summary: contract.ProfitLossSummary{
TotalRevenue: resp.Summary.TotalRevenue,
TotalCost: resp.Summary.TotalCost,
GrossProfit: resp.Summary.GrossProfit,
GrossProfitMargin: resp.Summary.GrossProfitMargin,
TotalTax: resp.Summary.TotalTax,
TotalDiscount: resp.Summary.TotalDiscount,
NetProfit: resp.Summary.NetProfit,
NetProfitMargin: resp.Summary.NetProfitMargin,
TotalOrders: resp.Summary.TotalOrders,
AverageProfit: resp.Summary.AverageProfit,
ProfitabilityRatio: resp.Summary.ProfitabilityRatio,
},
Data: data,
ProductData: productData,
MainSummary: mainSummary,
OperationalExpenses: opsItems,
OperationalExpensesTotal: resp.OperationalExpensesTotal,
@@ -84,12 +84,14 @@ func TestProfitLossAnalyticsContractToModelParsesDateRange(t *testing.T) {
OutletID: &outletID,
DateFrom: "01-05-2026",
DateTo: "29-05-2026",
GroupBy: "week",
})
require.NoError(t, err)
require.Equal(t, orgID, result.OrganizationID)
require.NotNil(t, result.OutletID)
require.Equal(t, outletID, result.OutletID.String())
require.Equal(t, "week", result.GroupBy)
location, err := time.LoadLocation("Asia/Jakarta")
require.NoError(t, err)
@@ -100,14 +102,53 @@ func TestProfitLossAnalyticsContractToModelParsesDateRange(t *testing.T) {
func TestProfitLossAnalyticsModelToContractCopiesDateRange(t *testing.T) {
dateFrom := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC)
dateTo := time.Date(2026, 5, 29, 23, 59, 59, int(time.Second-time.Nanosecond), time.UTC)
productID := uuid.New()
categoryID := uuid.New()
result := ProfitLossAnalyticsModelToContract(&models.ProfitLossAnalyticsResponse{
OrganizationID: uuid.New(),
DateFrom: dateFrom,
DateTo: dateTo,
GroupBy: "month",
Summary: models.ProfitLossSummary{
TotalRevenue: 1000,
NetProfit: 500,
},
Data: []models.ProfitLossData{
{
Date: dateFrom,
Revenue: 1000,
NetProfit: 500,
},
},
ProductData: []models.ProductProfitData{
{
ProductID: productID,
ProductName: "Nasi",
CategoryID: categoryID,
CategoryName: "Food",
Revenue: 1000,
GrossProfit: 500,
},
},
MainSummary: []models.ProfitLossSummaryRow{
{
ID: "total_omset",
Label: "TOTAL OMSET",
TodayNominal: 1000,
},
},
})
require.NotNil(t, result)
require.Equal(t, dateFrom, result.DateFrom)
require.Equal(t, dateTo, result.DateTo)
require.Equal(t, "month", result.GroupBy)
require.Equal(t, float64(1000), result.Summary.TotalRevenue)
require.Len(t, result.Data, 1)
require.Equal(t, float64(500), result.Data[0].NetProfit)
require.Len(t, result.ProductData, 1)
require.Equal(t, productID, result.ProductData[0].ProductID)
require.Len(t, result.MainSummary, 1)
require.Equal(t, "total_omset", result.MainSummary[0].ID)
}