Update purchase analytics
This commit is contained in:
parent
c3db919531
commit
d0c090a657
@ -106,7 +106,11 @@ type PurchasingAnalyticsResponse struct {
|
||||
|
||||
type PurchasingSummary struct {
|
||||
TotalPurchases float64 `json:"total_purchases"`
|
||||
RawMaterialPurchases float64 `json:"raw_material_purchases"`
|
||||
NonInventoryPurchases float64 `json:"non_inventory_purchases"`
|
||||
TotalPurchaseOrders int64 `json:"total_purchase_orders"`
|
||||
RawMaterialPurchaseOrders int64 `json:"raw_material_purchase_orders"`
|
||||
NonInventoryExpenseCount int64 `json:"non_inventory_expense_count"`
|
||||
TotalQuantity float64 `json:"total_quantity"`
|
||||
AveragePurchaseOrderValue float64 `json:"average_purchase_order_value"`
|
||||
TotalIngredients int64 `json:"total_ingredients"`
|
||||
@ -116,7 +120,11 @@ type PurchasingSummary struct {
|
||||
type PurchasingAnalyticsData struct {
|
||||
Date time.Time `json:"date"`
|
||||
Purchases float64 `json:"purchases"`
|
||||
RawMaterialPurchases float64 `json:"raw_material_purchases"`
|
||||
NonInventoryPurchases float64 `json:"non_inventory_purchases"`
|
||||
PurchaseOrders int64 `json:"purchase_orders"`
|
||||
RawMaterialPurchaseOrders int64 `json:"raw_material_purchase_orders"`
|
||||
NonInventoryExpenseCount int64 `json:"non_inventory_expense_count"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
Ingredients int64 `json:"ingredients"`
|
||||
Vendors int64 `json:"vendors"`
|
||||
|
||||
@ -38,7 +38,11 @@ type PurchasingAnalytics struct {
|
||||
|
||||
type PurchasingSummary struct {
|
||||
TotalPurchases float64 `json:"total_purchases"`
|
||||
RawMaterialPurchases float64 `json:"raw_material_purchases"`
|
||||
NonInventoryPurchases float64 `json:"non_inventory_purchases"`
|
||||
TotalPurchaseOrders int64 `json:"total_purchase_orders"`
|
||||
RawMaterialPurchaseOrders int64 `json:"raw_material_purchase_orders"`
|
||||
NonInventoryExpenseCount int64 `json:"non_inventory_expense_count"`
|
||||
TotalQuantity float64 `json:"total_quantity"`
|
||||
AveragePurchaseOrderValue float64 `json:"average_purchase_order_value"`
|
||||
TotalIngredients int64 `json:"total_ingredients"`
|
||||
@ -48,7 +52,11 @@ type PurchasingSummary struct {
|
||||
type PurchasingAnalyticsData struct {
|
||||
Date time.Time `json:"date"`
|
||||
Purchases float64 `json:"purchases"`
|
||||
RawMaterialPurchases float64 `json:"raw_material_purchases"`
|
||||
NonInventoryPurchases float64 `json:"non_inventory_purchases"`
|
||||
PurchaseOrders int64 `json:"purchase_orders"`
|
||||
RawMaterialPurchaseOrders int64 `json:"raw_material_purchase_orders"`
|
||||
NonInventoryExpenseCount int64 `json:"non_inventory_expense_count"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
Ingredients int64 `json:"ingredients"`
|
||||
Vendors int64 `json:"vendors"`
|
||||
|
||||
@ -113,7 +113,11 @@ type PurchasingAnalyticsResponse struct {
|
||||
// PurchasingSummary represents the summary of purchasing analytics
|
||||
type PurchasingSummary struct {
|
||||
TotalPurchases float64 `json:"total_purchases"`
|
||||
RawMaterialPurchases float64 `json:"raw_material_purchases"`
|
||||
NonInventoryPurchases float64 `json:"non_inventory_purchases"`
|
||||
TotalPurchaseOrders int64 `json:"total_purchase_orders"`
|
||||
RawMaterialPurchaseOrders int64 `json:"raw_material_purchase_orders"`
|
||||
NonInventoryExpenseCount int64 `json:"non_inventory_expense_count"`
|
||||
TotalQuantity float64 `json:"total_quantity"`
|
||||
AveragePurchaseOrderValue float64 `json:"average_purchase_order_value"`
|
||||
TotalIngredients int64 `json:"total_ingredients"`
|
||||
@ -124,7 +128,11 @@ type PurchasingSummary struct {
|
||||
type PurchasingAnalyticsData struct {
|
||||
Date time.Time `json:"date"`
|
||||
Purchases float64 `json:"purchases"`
|
||||
RawMaterialPurchases float64 `json:"raw_material_purchases"`
|
||||
NonInventoryPurchases float64 `json:"non_inventory_purchases"`
|
||||
PurchaseOrders int64 `json:"purchase_orders"`
|
||||
RawMaterialPurchaseOrders int64 `json:"raw_material_purchase_orders"`
|
||||
NonInventoryExpenseCount int64 `json:"non_inventory_expense_count"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
Ingredients int64 `json:"ingredients"`
|
||||
Vendors int64 `json:"vendors"`
|
||||
|
||||
@ -187,7 +187,11 @@ func (p *AnalyticsProcessorImpl) GetPurchasingAnalytics(ctx context.Context, req
|
||||
data[i] = models.PurchasingAnalyticsData{
|
||||
Date: item.Date,
|
||||
Purchases: item.Purchases,
|
||||
RawMaterialPurchases: item.RawMaterialPurchases,
|
||||
NonInventoryPurchases: item.NonInventoryPurchases,
|
||||
PurchaseOrders: item.PurchaseOrders,
|
||||
RawMaterialPurchaseOrders: item.RawMaterialPurchaseOrders,
|
||||
NonInventoryExpenseCount: item.NonInventoryExpenseCount,
|
||||
Quantity: item.Quantity,
|
||||
Ingredients: item.Ingredients,
|
||||
Vendors: item.Vendors,
|
||||
@ -227,7 +231,11 @@ func (p *AnalyticsProcessorImpl) GetPurchasingAnalytics(ctx context.Context, req
|
||||
GroupBy: req.GroupBy,
|
||||
Summary: models.PurchasingSummary{
|
||||
TotalPurchases: result.Summary.TotalPurchases,
|
||||
RawMaterialPurchases: result.Summary.RawMaterialPurchases,
|
||||
NonInventoryPurchases: result.Summary.NonInventoryPurchases,
|
||||
TotalPurchaseOrders: result.Summary.TotalPurchaseOrders,
|
||||
RawMaterialPurchaseOrders: result.Summary.RawMaterialPurchaseOrders,
|
||||
NonInventoryExpenseCount: result.Summary.NonInventoryExpenseCount,
|
||||
TotalQuantity: result.Summary.TotalQuantity,
|
||||
AveragePurchaseOrderValue: result.Summary.AveragePurchaseOrderValue,
|
||||
TotalIngredients: result.Summary.TotalIngredients,
|
||||
|
||||
@ -75,7 +75,23 @@ func TestAnalyticsProcessorGetPurchasingAnalyticsPassesOutletName(t *testing.T)
|
||||
purchasingResult: &entities.PurchasingAnalytics{
|
||||
OutletName: &outletName,
|
||||
Summary: entities.PurchasingSummary{
|
||||
TotalPurchases: 125,
|
||||
TotalPurchases: 300,
|
||||
RawMaterialPurchases: 125,
|
||||
NonInventoryPurchases: 175,
|
||||
TotalPurchaseOrders: 3,
|
||||
RawMaterialPurchaseOrders: 1,
|
||||
NonInventoryExpenseCount: 2,
|
||||
},
|
||||
Data: []entities.PurchasingAnalyticsData{
|
||||
{
|
||||
Date: now,
|
||||
Purchases: 300,
|
||||
RawMaterialPurchases: 125,
|
||||
NonInventoryPurchases: 175,
|
||||
PurchaseOrders: 3,
|
||||
RawMaterialPurchaseOrders: 1,
|
||||
NonInventoryExpenseCount: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, expenseRepositoryStub{})
|
||||
@ -92,7 +108,16 @@ func TestAnalyticsProcessorGetPurchasingAnalyticsPassesOutletName(t *testing.T)
|
||||
require.Equal(t, &outletID, result.OutletID)
|
||||
require.NotNil(t, result.OutletName)
|
||||
require.Equal(t, outletName, *result.OutletName)
|
||||
require.Equal(t, float64(125), result.Summary.TotalPurchases)
|
||||
require.Equal(t, float64(300), result.Summary.TotalPurchases)
|
||||
require.Equal(t, float64(125), result.Summary.RawMaterialPurchases)
|
||||
require.Equal(t, float64(175), result.Summary.NonInventoryPurchases)
|
||||
require.Equal(t, int64(3), result.Summary.TotalPurchaseOrders)
|
||||
require.Equal(t, int64(1), result.Summary.RawMaterialPurchaseOrders)
|
||||
require.Equal(t, int64(2), result.Summary.NonInventoryExpenseCount)
|
||||
require.Len(t, result.Data, 1)
|
||||
require.Equal(t, float64(300), result.Data[0].Purchases)
|
||||
require.Equal(t, float64(125), result.Data[0].RawMaterialPurchases)
|
||||
require.Equal(t, float64(175), result.Data[0].NonInventoryPurchases)
|
||||
}
|
||||
|
||||
func TestAnalyticsProcessorGetProfitLossAnalyticsMapsOverviewAndReportFields(t *testing.T) {
|
||||
|
||||
@ -145,68 +145,179 @@ func (r *AnalyticsRepositoryImpl) GetPurchasingAnalytics(ctx context.Context, or
|
||||
}
|
||||
}
|
||||
|
||||
summaryQuery := r.db.WithContext(ctx).
|
||||
Table("inventory_movements im").
|
||||
Select(`
|
||||
COALESCE(SUM(im.total_cost), 0) as total_purchases,
|
||||
COUNT(DISTINCT im.reference_id) as total_purchase_orders,
|
||||
rawMaterialOutletFilter := ""
|
||||
nonInventoryOutletFilter := ""
|
||||
rawMaterialSummaryArgs := []interface{}{
|
||||
organizationID,
|
||||
entities.InventoryMovementTypePurchase,
|
||||
"INGREDIENT",
|
||||
entities.InventoryMovementReferenceTypePurchaseOrder,
|
||||
dateFrom,
|
||||
dateTo,
|
||||
}
|
||||
nonInventorySummaryArgs := []interface{}{
|
||||
organizationID,
|
||||
entities.PurchaseCategoryTypeNonInventory,
|
||||
"approved",
|
||||
dateFrom,
|
||||
dateTo,
|
||||
}
|
||||
if outletID != nil {
|
||||
rawMaterialOutletFilter = "AND im.outlet_id = ?"
|
||||
nonInventoryOutletFilter = "AND e.outlet_id = ?"
|
||||
rawMaterialSummaryArgs = append(rawMaterialSummaryArgs, *outletID)
|
||||
nonInventorySummaryArgs = append(nonInventorySummaryArgs, *outletID)
|
||||
}
|
||||
summaryArgs := append(rawMaterialSummaryArgs, nonInventorySummaryArgs...)
|
||||
|
||||
summaryQuery := `
|
||||
WITH raw_material AS (
|
||||
SELECT
|
||||
COALESCE(SUM(im.total_cost), 0) as raw_material_purchases,
|
||||
COUNT(DISTINCT im.reference_id) as raw_material_purchase_orders,
|
||||
COALESCE(SUM(im.quantity), 0) as total_quantity,
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT im.reference_id) > 0
|
||||
THEN COALESCE(SUM(im.total_cost), 0) / COUNT(DISTINCT im.reference_id)
|
||||
ELSE 0
|
||||
END as average_purchase_order_value,
|
||||
COUNT(DISTINCT im.item_id) as total_ingredients,
|
||||
COUNT(DISTINCT po.vendor_id) as total_vendors
|
||||
`).
|
||||
Joins("LEFT JOIN purchase_orders po ON im.reference_id = po.id").
|
||||
Where("im.organization_id = ?", organizationID).
|
||||
Where("im.movement_type = ?", entities.InventoryMovementTypePurchase).
|
||||
Where("im.item_type = ?", "INGREDIENT").
|
||||
Where("im.reference_type = ?", entities.InventoryMovementReferenceTypePurchaseOrder).
|
||||
Where("im.created_at >= ? AND im.created_at <= ?", dateFrom, dateTo)
|
||||
FROM inventory_movements im
|
||||
LEFT JOIN purchase_orders po ON im.reference_id = po.id
|
||||
WHERE im.organization_id = ?
|
||||
AND im.movement_type = ?
|
||||
AND im.item_type = ?
|
||||
AND im.reference_type = ?
|
||||
AND im.created_at >= ? AND im.created_at <= ?
|
||||
` + rawMaterialOutletFilter + `
|
||||
),
|
||||
non_inventory AS (
|
||||
SELECT
|
||||
COALESCE(SUM(ei.amount), 0) as non_inventory_purchases,
|
||||
COUNT(DISTINCT e.id) as non_inventory_expense_count
|
||||
FROM expense_items ei
|
||||
JOIN expenses e ON ei.expense_id = e.id
|
||||
JOIN purchase_categories pc ON ei.purchase_category_id = pc.id
|
||||
WHERE e.organization_id = ?
|
||||
AND pc.type = ?
|
||||
AND e.status = ?
|
||||
AND e.transaction_date >= ? AND e.transaction_date <= ?
|
||||
` + nonInventoryOutletFilter + `
|
||||
)
|
||||
SELECT
|
||||
rm.raw_material_purchases + ni.non_inventory_purchases as total_purchases,
|
||||
rm.raw_material_purchases,
|
||||
ni.non_inventory_purchases,
|
||||
rm.raw_material_purchase_orders + ni.non_inventory_expense_count as total_purchase_orders,
|
||||
rm.raw_material_purchase_orders,
|
||||
ni.non_inventory_expense_count,
|
||||
rm.total_quantity,
|
||||
CASE
|
||||
WHEN rm.raw_material_purchase_orders + ni.non_inventory_expense_count > 0
|
||||
THEN (rm.raw_material_purchases + ni.non_inventory_purchases) / (rm.raw_material_purchase_orders + ni.non_inventory_expense_count)
|
||||
ELSE 0
|
||||
END as average_purchase_order_value,
|
||||
rm.total_ingredients,
|
||||
rm.total_vendors
|
||||
FROM raw_material rm
|
||||
CROSS JOIN non_inventory ni
|
||||
`
|
||||
|
||||
summaryQuery = r.resolveOutletID(summaryQuery, outletID, "im.outlet_id")
|
||||
|
||||
if err := summaryQuery.Scan(&summary).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Raw(summaryQuery, summaryArgs...).Scan(&summary).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dateFormat string
|
||||
switch groupBy {
|
||||
case "hour":
|
||||
dateFormat = "DATE_TRUNC('hour', im.created_at)"
|
||||
dateFormat = "DATE_TRUNC('hour', im.created_at)::timestamp"
|
||||
case "week":
|
||||
dateFormat = "DATE_TRUNC('week', im.created_at)"
|
||||
dateFormat = "DATE_TRUNC('week', im.created_at)::timestamp"
|
||||
case "month":
|
||||
dateFormat = "DATE_TRUNC('month', im.created_at)"
|
||||
dateFormat = "DATE_TRUNC('month', im.created_at)::timestamp"
|
||||
default:
|
||||
dateFormat = "DATE_TRUNC('day', im.created_at)"
|
||||
dateFormat = "DATE_TRUNC('day', im.created_at)::timestamp"
|
||||
}
|
||||
|
||||
nonInventoryDateFormat := "DATE_TRUNC('day', e.transaction_date)::timestamp"
|
||||
switch groupBy {
|
||||
case "hour":
|
||||
nonInventoryDateFormat = "DATE_TRUNC('hour', e.transaction_date)::timestamp"
|
||||
case "week":
|
||||
nonInventoryDateFormat = "DATE_TRUNC('week', e.transaction_date)::timestamp"
|
||||
case "month":
|
||||
nonInventoryDateFormat = "DATE_TRUNC('month', e.transaction_date)::timestamp"
|
||||
}
|
||||
|
||||
rawMaterialDataArgs := []interface{}{
|
||||
organizationID,
|
||||
entities.InventoryMovementTypePurchase,
|
||||
"INGREDIENT",
|
||||
entities.InventoryMovementReferenceTypePurchaseOrder,
|
||||
dateFrom,
|
||||
dateTo,
|
||||
}
|
||||
nonInventoryDataArgs := []interface{}{
|
||||
organizationID,
|
||||
entities.PurchaseCategoryTypeNonInventory,
|
||||
"approved",
|
||||
dateFrom,
|
||||
dateTo,
|
||||
}
|
||||
if outletID != nil {
|
||||
rawMaterialDataArgs = append(rawMaterialDataArgs, *outletID)
|
||||
nonInventoryDataArgs = append(nonInventoryDataArgs, *outletID)
|
||||
}
|
||||
dataArgs := append(rawMaterialDataArgs, nonInventoryDataArgs...)
|
||||
|
||||
var data []entities.PurchasingAnalyticsData
|
||||
dataQuery := r.db.WithContext(ctx).
|
||||
Table("inventory_movements im").
|
||||
Select(`
|
||||
dataQuery := `
|
||||
WITH raw_material AS (
|
||||
SELECT
|
||||
` + dateFormat + ` as date,
|
||||
COALESCE(SUM(im.total_cost), 0) as purchases,
|
||||
COUNT(DISTINCT im.reference_id) as purchase_orders,
|
||||
COALESCE(SUM(im.total_cost), 0) as raw_material_purchases,
|
||||
COUNT(DISTINCT im.reference_id) as raw_material_purchase_orders,
|
||||
COALESCE(SUM(im.quantity), 0) as quantity,
|
||||
COUNT(DISTINCT im.item_id) as ingredients,
|
||||
COUNT(DISTINCT po.vendor_id) as vendors
|
||||
`).
|
||||
Joins("LEFT JOIN purchase_orders po ON im.reference_id = po.id").
|
||||
Where("im.organization_id = ?", organizationID).
|
||||
Where("im.movement_type = ?", entities.InventoryMovementTypePurchase).
|
||||
Where("im.item_type = ?", "INGREDIENT").
|
||||
Where("im.reference_type = ?", entities.InventoryMovementReferenceTypePurchaseOrder).
|
||||
Where("im.created_at >= ? AND im.created_at <= ?", dateFrom, dateTo).
|
||||
Group(dateFormat).
|
||||
Order(dateFormat)
|
||||
FROM inventory_movements im
|
||||
LEFT JOIN purchase_orders po ON im.reference_id = po.id
|
||||
WHERE im.organization_id = ?
|
||||
AND im.movement_type = ?
|
||||
AND im.item_type = ?
|
||||
AND im.reference_type = ?
|
||||
AND im.created_at >= ? AND im.created_at <= ?
|
||||
` + rawMaterialOutletFilter + `
|
||||
GROUP BY 1
|
||||
),
|
||||
non_inventory AS (
|
||||
SELECT
|
||||
` + nonInventoryDateFormat + ` as date,
|
||||
COALESCE(SUM(ei.amount), 0) as non_inventory_purchases,
|
||||
COUNT(DISTINCT e.id) as non_inventory_expense_count
|
||||
FROM expense_items ei
|
||||
JOIN expenses e ON ei.expense_id = e.id
|
||||
JOIN purchase_categories pc ON ei.purchase_category_id = pc.id
|
||||
WHERE e.organization_id = ?
|
||||
AND pc.type = ?
|
||||
AND e.status = ?
|
||||
AND e.transaction_date >= ? AND e.transaction_date <= ?
|
||||
` + nonInventoryOutletFilter + `
|
||||
GROUP BY 1
|
||||
)
|
||||
SELECT
|
||||
COALESCE(rm.date, ni.date) as date,
|
||||
COALESCE(rm.raw_material_purchases, 0) + COALESCE(ni.non_inventory_purchases, 0) as purchases,
|
||||
COALESCE(rm.raw_material_purchases, 0) as raw_material_purchases,
|
||||
COALESCE(ni.non_inventory_purchases, 0) as non_inventory_purchases,
|
||||
COALESCE(rm.raw_material_purchase_orders, 0) + COALESCE(ni.non_inventory_expense_count, 0) as purchase_orders,
|
||||
COALESCE(rm.raw_material_purchase_orders, 0) as raw_material_purchase_orders,
|
||||
COALESCE(ni.non_inventory_expense_count, 0) as non_inventory_expense_count,
|
||||
COALESCE(rm.quantity, 0) as quantity,
|
||||
COALESCE(rm.ingredients, 0) as ingredients,
|
||||
COALESCE(rm.vendors, 0) as vendors
|
||||
FROM raw_material rm
|
||||
FULL OUTER JOIN non_inventory ni ON rm.date = ni.date
|
||||
ORDER BY date
|
||||
`
|
||||
|
||||
dataQuery = r.resolveOutletID(dataQuery, outletID, "im.outlet_id")
|
||||
|
||||
if err := dataQuery.Scan(&data).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Raw(dataQuery, dataArgs...).Scan(&data).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@ -171,7 +171,11 @@ func PurchasingAnalyticsModelToContract(resp *models.PurchasingAnalyticsResponse
|
||||
data[i] = contract.PurchasingAnalyticsData{
|
||||
Date: item.Date,
|
||||
Purchases: item.Purchases,
|
||||
RawMaterialPurchases: item.RawMaterialPurchases,
|
||||
NonInventoryPurchases: item.NonInventoryPurchases,
|
||||
PurchaseOrders: item.PurchaseOrders,
|
||||
RawMaterialPurchaseOrders: item.RawMaterialPurchaseOrders,
|
||||
NonInventoryExpenseCount: item.NonInventoryExpenseCount,
|
||||
Quantity: item.Quantity,
|
||||
Ingredients: item.Ingredients,
|
||||
Vendors: item.Vendors,
|
||||
@ -211,7 +215,11 @@ func PurchasingAnalyticsModelToContract(resp *models.PurchasingAnalyticsResponse
|
||||
GroupBy: resp.GroupBy,
|
||||
Summary: contract.PurchasingSummary{
|
||||
TotalPurchases: resp.Summary.TotalPurchases,
|
||||
RawMaterialPurchases: resp.Summary.RawMaterialPurchases,
|
||||
NonInventoryPurchases: resp.Summary.NonInventoryPurchases,
|
||||
TotalPurchaseOrders: resp.Summary.TotalPurchaseOrders,
|
||||
RawMaterialPurchaseOrders: resp.Summary.RawMaterialPurchaseOrders,
|
||||
NonInventoryExpenseCount: resp.Summary.NonInventoryExpenseCount,
|
||||
TotalQuantity: resp.Summary.TotalQuantity,
|
||||
AveragePurchaseOrderValue: resp.Summary.AveragePurchaseOrderValue,
|
||||
TotalIngredients: resp.Summary.TotalIngredients,
|
||||
|
||||
@ -52,17 +52,47 @@ func TestPurchasingAnalyticsContractToModelIgnoresInvalidOutlet(t *testing.T) {
|
||||
func TestPurchasingAnalyticsModelToContractCopiesOutletName(t *testing.T) {
|
||||
outletID := uuid.New()
|
||||
outletName := "Main Outlet"
|
||||
now := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
result := PurchasingAnalyticsModelToContract(&models.PurchasingAnalyticsResponse{
|
||||
OrganizationID: uuid.New(),
|
||||
OutletID: &outletID,
|
||||
OutletName: &outletName,
|
||||
Summary: models.PurchasingSummary{
|
||||
TotalPurchases: 300,
|
||||
RawMaterialPurchases: 125,
|
||||
NonInventoryPurchases: 175,
|
||||
TotalPurchaseOrders: 3,
|
||||
RawMaterialPurchaseOrders: 1,
|
||||
NonInventoryExpenseCount: 2,
|
||||
},
|
||||
Data: []models.PurchasingAnalyticsData{
|
||||
{
|
||||
Date: now,
|
||||
Purchases: 300,
|
||||
RawMaterialPurchases: 125,
|
||||
NonInventoryPurchases: 175,
|
||||
PurchaseOrders: 3,
|
||||
RawMaterialPurchaseOrders: 1,
|
||||
NonInventoryExpenseCount: 2,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, result)
|
||||
require.Equal(t, &outletID, result.OutletID)
|
||||
require.NotNil(t, result.OutletName)
|
||||
require.Equal(t, outletName, *result.OutletName)
|
||||
require.Equal(t, float64(300), result.Summary.TotalPurchases)
|
||||
require.Equal(t, float64(125), result.Summary.RawMaterialPurchases)
|
||||
require.Equal(t, float64(175), result.Summary.NonInventoryPurchases)
|
||||
require.Equal(t, int64(3), result.Summary.TotalPurchaseOrders)
|
||||
require.Equal(t, int64(1), result.Summary.RawMaterialPurchaseOrders)
|
||||
require.Equal(t, int64(2), result.Summary.NonInventoryExpenseCount)
|
||||
require.Len(t, result.Data, 1)
|
||||
require.Equal(t, float64(300), result.Data[0].Purchases)
|
||||
require.Equal(t, float64(125), result.Data[0].RawMaterialPurchases)
|
||||
require.Equal(t, float64(175), result.Data[0].NonInventoryPurchases)
|
||||
}
|
||||
|
||||
func TestPurchasingAnalyticsModelToContractOmitsNilOutletName(t *testing.T) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user