add purchasing in analytics endpoint
This commit is contained in:
@@ -138,6 +138,91 @@ func SalesAnalyticsModelToContract(resp *models.SalesAnalyticsResponse) *contrac
|
||||
}
|
||||
}
|
||||
|
||||
// PurchasingAnalyticsContractToModel converts contract request to model
|
||||
func PurchasingAnalyticsContractToModel(req *contract.PurchasingAnalyticsRequest) *models.PurchasingAnalyticsRequest {
|
||||
var dateFrom, dateTo time.Time
|
||||
|
||||
if fromTime, toTime, err := util.ParseDateRangeToJakartaTime(req.DateFrom, req.DateTo); err == nil {
|
||||
if fromTime != nil {
|
||||
dateFrom = *fromTime
|
||||
}
|
||||
if toTime != nil {
|
||||
dateTo = *toTime
|
||||
}
|
||||
}
|
||||
|
||||
return &models.PurchasingAnalyticsRequest{
|
||||
OrganizationID: req.OrganizationID,
|
||||
OutletID: parseOutletID(req.OutletID),
|
||||
DateFrom: dateFrom,
|
||||
DateTo: dateTo,
|
||||
GroupBy: req.GroupBy,
|
||||
}
|
||||
}
|
||||
|
||||
// PurchasingAnalyticsModelToContract converts model response to contract
|
||||
func PurchasingAnalyticsModelToContract(resp *models.PurchasingAnalyticsResponse) *contract.PurchasingAnalyticsResponse {
|
||||
if resp == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
data := make([]contract.PurchasingAnalyticsData, len(resp.Data))
|
||||
for i, item := range resp.Data {
|
||||
data[i] = contract.PurchasingAnalyticsData{
|
||||
Date: item.Date,
|
||||
Purchases: item.Purchases,
|
||||
PurchaseOrders: item.PurchaseOrders,
|
||||
Quantity: item.Quantity,
|
||||
Ingredients: item.Ingredients,
|
||||
Vendors: item.Vendors,
|
||||
}
|
||||
}
|
||||
|
||||
ingredientData := make([]contract.PurchasingIngredientData, len(resp.IngredientData))
|
||||
for i, item := range resp.IngredientData {
|
||||
ingredientData[i] = contract.PurchasingIngredientData{
|
||||
IngredientID: item.IngredientID,
|
||||
IngredientName: item.IngredientName,
|
||||
Quantity: item.Quantity,
|
||||
TotalCost: item.TotalCost,
|
||||
AverageUnitCost: item.AverageUnitCost,
|
||||
PurchaseOrderCount: item.PurchaseOrderCount,
|
||||
}
|
||||
}
|
||||
|
||||
vendorData := make([]contract.PurchasingVendorData, len(resp.VendorData))
|
||||
for i, item := range resp.VendorData {
|
||||
vendorData[i] = contract.PurchasingVendorData{
|
||||
VendorID: item.VendorID,
|
||||
VendorName: item.VendorName,
|
||||
TotalCost: item.TotalCost,
|
||||
PurchaseOrderCount: item.PurchaseOrderCount,
|
||||
IngredientCount: item.IngredientCount,
|
||||
Quantity: item.Quantity,
|
||||
}
|
||||
}
|
||||
|
||||
return &contract.PurchasingAnalyticsResponse{
|
||||
OrganizationID: resp.OrganizationID,
|
||||
OutletID: resp.OutletID,
|
||||
OutletName: resp.OutletName,
|
||||
DateFrom: resp.DateFrom,
|
||||
DateTo: resp.DateTo,
|
||||
GroupBy: resp.GroupBy,
|
||||
Summary: contract.PurchasingSummary{
|
||||
TotalPurchases: resp.Summary.TotalPurchases,
|
||||
TotalPurchaseOrders: resp.Summary.TotalPurchaseOrders,
|
||||
TotalQuantity: resp.Summary.TotalQuantity,
|
||||
AveragePurchaseOrderValue: resp.Summary.AveragePurchaseOrderValue,
|
||||
TotalIngredients: resp.Summary.TotalIngredients,
|
||||
TotalVendors: resp.Summary.TotalVendors,
|
||||
},
|
||||
Data: data,
|
||||
IngredientData: ingredientData,
|
||||
VendorData: vendorData,
|
||||
}
|
||||
}
|
||||
|
||||
// ProductAnalyticsContractToModel converts contract request to model
|
||||
func ProductAnalyticsContractToModel(req *contract.ProductAnalyticsRequest) *models.ProductAnalyticsRequest {
|
||||
var dateFrom, dateTo time.Time
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package transformer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/models"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPurchasingAnalyticsContractToModelParsesDateRangeAndOutlet(t *testing.T) {
|
||||
orgID := uuid.New()
|
||||
outletID := uuid.New().String()
|
||||
|
||||
req := &contract.PurchasingAnalyticsRequest{
|
||||
OrganizationID: orgID,
|
||||
OutletID: &outletID,
|
||||
DateFrom: "01-05-2026",
|
||||
DateTo: "02-05-2026",
|
||||
GroupBy: "week",
|
||||
}
|
||||
|
||||
result := PurchasingAnalyticsContractToModel(req)
|
||||
|
||||
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)
|
||||
require.Equal(t, time.Date(2026, 5, 1, 0, 0, 0, 0, location), result.DateFrom)
|
||||
require.Equal(t, time.Date(2026, 5, 2, 23, 59, 59, int(time.Second-time.Nanosecond), location), result.DateTo)
|
||||
}
|
||||
|
||||
func TestPurchasingAnalyticsContractToModelIgnoresInvalidOutlet(t *testing.T) {
|
||||
outletID := "not-a-uuid"
|
||||
|
||||
result := PurchasingAnalyticsContractToModel(&contract.PurchasingAnalyticsRequest{
|
||||
OutletID: &outletID,
|
||||
DateFrom: "01-05-2026",
|
||||
DateTo: "02-05-2026",
|
||||
})
|
||||
|
||||
require.Nil(t, result.OutletID)
|
||||
}
|
||||
|
||||
func TestPurchasingAnalyticsModelToContractCopiesOutletName(t *testing.T) {
|
||||
outletID := uuid.New()
|
||||
outletName := "Main Outlet"
|
||||
|
||||
result := PurchasingAnalyticsModelToContract(&models.PurchasingAnalyticsResponse{
|
||||
OrganizationID: uuid.New(),
|
||||
OutletID: &outletID,
|
||||
OutletName: &outletName,
|
||||
})
|
||||
|
||||
require.NotNil(t, result)
|
||||
require.Equal(t, &outletID, result.OutletID)
|
||||
require.NotNil(t, result.OutletName)
|
||||
require.Equal(t, outletName, *result.OutletName)
|
||||
}
|
||||
|
||||
func TestPurchasingAnalyticsModelToContractOmitsNilOutletName(t *testing.T) {
|
||||
result := PurchasingAnalyticsModelToContract(&models.PurchasingAnalyticsResponse{
|
||||
OrganizationID: uuid.New(),
|
||||
})
|
||||
|
||||
payload, err := json.Marshal(result)
|
||||
require.NoError(t, err)
|
||||
require.NotContains(t, string(payload), "outlet_name")
|
||||
}
|
||||
Reference in New Issue
Block a user