Fix purchase analytic by outlet
This commit is contained in:
parent
d5216e7994
commit
f4172fcea7
@ -124,7 +124,6 @@ func (r *AnalyticsRepositoryImpl) GetSalesAnalytics(ctx context.Context, organiz
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *AnalyticsRepositoryImpl) GetPurchasingAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, groupBy string) (*entities.PurchasingAnalytics, error) {
|
func (r *AnalyticsRepositoryImpl) GetPurchasingAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, groupBy string) (*entities.PurchasingAnalytics, error) {
|
||||||
var summary entities.PurchasingSummary
|
|
||||||
var outletName *string
|
var outletName *string
|
||||||
|
|
||||||
if outletID != nil {
|
if outletID != nil {
|
||||||
@ -144,142 +143,10 @@ func (r *AnalyticsRepositoryImpl) GetPurchasingAnalytics(ctx context.Context, or
|
|||||||
outletName = &outlet.Name
|
outletName = &outlet.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if outletID == nil {
|
return r.getPurchaseOrderPurchasingAnalytics(ctx, organizationID, outletID, outletName, dateFrom, dateTo, groupBy)
|
||||||
return r.getPurchaseOrderPurchasingAnalytics(ctx, organizationID, dateFrom, dateTo, groupBy)
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
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)
|
|
||||||
|
|
||||||
summaryQuery = r.resolveOutletID(summaryQuery, outletID, "im.outlet_id")
|
|
||||||
|
|
||||||
if err := summaryQuery.Scan(&summary).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var dateFormat string
|
|
||||||
switch groupBy {
|
|
||||||
case "hour":
|
|
||||||
dateFormat = "DATE_TRUNC('hour', im.created_at)"
|
|
||||||
case "week":
|
|
||||||
dateFormat = "DATE_TRUNC('week', im.created_at)"
|
|
||||||
case "month":
|
|
||||||
dateFormat = "DATE_TRUNC('month', im.created_at)"
|
|
||||||
default:
|
|
||||||
dateFormat = "DATE_TRUNC('day', im.created_at)"
|
|
||||||
}
|
|
||||||
|
|
||||||
var data []entities.PurchasingAnalyticsData
|
|
||||||
dataQuery := r.db.WithContext(ctx).
|
|
||||||
Table("inventory_movements im").
|
|
||||||
Select(`
|
|
||||||
`+dateFormat+` as date,
|
|
||||||
COALESCE(SUM(im.total_cost), 0) as purchases,
|
|
||||||
COUNT(DISTINCT im.reference_id) as 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)
|
|
||||||
|
|
||||||
dataQuery = r.resolveOutletID(dataQuery, outletID, "im.outlet_id")
|
|
||||||
|
|
||||||
if err := dataQuery.Scan(&data).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var ingredientData []entities.PurchasingIngredientData
|
|
||||||
ingredientQuery := r.db.WithContext(ctx).
|
|
||||||
Table("inventory_movements im").
|
|
||||||
Select(`
|
|
||||||
i.id as ingredient_id,
|
|
||||||
i.name as ingredient_name,
|
|
||||||
COALESCE(SUM(im.quantity), 0) as quantity,
|
|
||||||
COALESCE(SUM(im.total_cost), 0) as total_cost,
|
|
||||||
CASE
|
|
||||||
WHEN SUM(im.quantity) > 0
|
|
||||||
THEN COALESCE(SUM(im.total_cost), 0) / SUM(im.quantity)
|
|
||||||
ELSE 0
|
|
||||||
END as average_unit_cost,
|
|
||||||
COUNT(DISTINCT im.reference_id) as purchase_order_count
|
|
||||||
`).
|
|
||||||
Joins("JOIN ingredients i ON im.item_id = i.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("i.id, i.name").
|
|
||||||
Order("total_cost DESC")
|
|
||||||
|
|
||||||
ingredientQuery = r.resolveOutletID(ingredientQuery, outletID, "im.outlet_id")
|
|
||||||
|
|
||||||
if err := ingredientQuery.Scan(&ingredientData).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var vendorData []entities.PurchasingVendorData
|
|
||||||
vendorQuery := r.db.WithContext(ctx).
|
|
||||||
Table("inventory_movements im").
|
|
||||||
Select(`
|
|
||||||
v.id as vendor_id,
|
|
||||||
v.name as vendor_name,
|
|
||||||
COALESCE(SUM(im.total_cost), 0) as total_cost,
|
|
||||||
COUNT(DISTINCT im.reference_id) as purchase_order_count,
|
|
||||||
COUNT(DISTINCT im.item_id) as ingredient_count,
|
|
||||||
COALESCE(SUM(im.quantity), 0) as quantity
|
|
||||||
`).
|
|
||||||
Joins("JOIN purchase_orders po ON im.reference_id = po.id").
|
|
||||||
Joins("JOIN vendors v ON po.vendor_id = v.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("v.id, v.name").
|
|
||||||
Order("total_cost DESC")
|
|
||||||
|
|
||||||
vendorQuery = r.resolveOutletID(vendorQuery, outletID, "im.outlet_id")
|
|
||||||
|
|
||||||
if err := vendorQuery.Scan(&vendorData).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &entities.PurchasingAnalytics{
|
|
||||||
OutletName: outletName,
|
|
||||||
Summary: summary,
|
|
||||||
Data: data,
|
|
||||||
IngredientData: ingredientData,
|
|
||||||
VendorData: vendorData,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx context.Context, organizationID uuid.UUID, dateFrom, dateTo time.Time, groupBy string) (*entities.PurchasingAnalytics, error) {
|
func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, outletName *string, dateFrom, dateTo time.Time, groupBy string) (*entities.PurchasingAnalytics, error) {
|
||||||
var summary entities.PurchasingSummary
|
var summary entities.PurchasingSummary
|
||||||
summaryQuery := r.db.WithContext(ctx).
|
summaryQuery := r.db.WithContext(ctx).
|
||||||
Table("purchase_orders po").
|
Table("purchase_orders po").
|
||||||
@ -292,13 +159,16 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx contex
|
|||||||
THEN COALESCE(SUM(poi.amount), 0) / COUNT(DISTINCT po.id)
|
THEN COALESCE(SUM(poi.amount), 0) / COUNT(DISTINCT po.id)
|
||||||
ELSE 0
|
ELSE 0
|
||||||
END as average_purchase_order_value,
|
END as average_purchase_order_value,
|
||||||
COUNT(DISTINCT poi.ingredient_id) as total_ingredients,
|
COUNT(DISTINCT i.id) as total_ingredients,
|
||||||
COUNT(DISTINCT po.vendor_id) as total_vendors
|
COUNT(DISTINCT po.vendor_id) as total_vendors
|
||||||
`).
|
`).
|
||||||
Joins("LEFT JOIN purchase_order_items poi ON poi.purchase_order_id = po.id").
|
Joins("LEFT JOIN purchase_order_items poi ON poi.purchase_order_id = po.id").
|
||||||
|
Joins("LEFT JOIN ingredients i ON poi.ingredient_id = i.id").
|
||||||
|
Joins("LEFT JOIN units u ON poi.unit_id = u.id").
|
||||||
Where("po.organization_id = ?", organizationID).
|
Where("po.organization_id = ?", organizationID).
|
||||||
Where("po.status != ?", "cancelled").
|
Where("po.status != ?", "cancelled").
|
||||||
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo)
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo)
|
||||||
|
summaryQuery = r.applyPurchaseOrderItemOutletFilter(summaryQuery, outletID)
|
||||||
|
|
||||||
if err := summaryQuery.Scan(&summary).Error; err != nil {
|
if err := summaryQuery.Scan(&summary).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -324,15 +194,18 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx contex
|
|||||||
COALESCE(SUM(poi.amount), 0) as purchases,
|
COALESCE(SUM(poi.amount), 0) as purchases,
|
||||||
COUNT(DISTINCT po.id) as purchase_orders,
|
COUNT(DISTINCT po.id) as purchase_orders,
|
||||||
COALESCE(SUM(poi.quantity), 0) as quantity,
|
COALESCE(SUM(poi.quantity), 0) as quantity,
|
||||||
COUNT(DISTINCT poi.ingredient_id) as ingredients,
|
COUNT(DISTINCT i.id) as ingredients,
|
||||||
COUNT(DISTINCT po.vendor_id) as vendors
|
COUNT(DISTINCT po.vendor_id) as vendors
|
||||||
`).
|
`).
|
||||||
Joins("LEFT JOIN purchase_order_items poi ON poi.purchase_order_id = po.id").
|
Joins("LEFT JOIN purchase_order_items poi ON poi.purchase_order_id = po.id").
|
||||||
|
Joins("LEFT JOIN ingredients i ON poi.ingredient_id = i.id").
|
||||||
|
Joins("LEFT JOIN units u ON poi.unit_id = u.id").
|
||||||
Where("po.organization_id = ?", organizationID).
|
Where("po.organization_id = ?", organizationID).
|
||||||
Where("po.status != ?", "cancelled").
|
Where("po.status != ?", "cancelled").
|
||||||
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
||||||
Group(dateFormat).
|
Group(dateFormat).
|
||||||
Order(dateFormat)
|
Order(dateFormat)
|
||||||
|
dataQuery = r.applyPurchaseOrderItemOutletFilter(dataQuery, outletID)
|
||||||
|
|
||||||
if err := dataQuery.Scan(&data).Error; err != nil {
|
if err := dataQuery.Scan(&data).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -355,11 +228,13 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx contex
|
|||||||
`).
|
`).
|
||||||
Joins("JOIN purchase_orders po ON poi.purchase_order_id = po.id").
|
Joins("JOIN purchase_orders po ON poi.purchase_order_id = po.id").
|
||||||
Joins("JOIN ingredients i ON poi.ingredient_id = i.id").
|
Joins("JOIN ingredients i ON poi.ingredient_id = i.id").
|
||||||
|
Joins("LEFT JOIN units u ON poi.unit_id = u.id").
|
||||||
Where("po.organization_id = ?", organizationID).
|
Where("po.organization_id = ?", organizationID).
|
||||||
Where("po.status != ?", "cancelled").
|
Where("po.status != ?", "cancelled").
|
||||||
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
||||||
Group("i.id, i.name").
|
Group("i.id, i.name").
|
||||||
Order("total_cost DESC")
|
Order("total_cost DESC")
|
||||||
|
ingredientQuery = r.applyPurchaseOrderItemOutletFilter(ingredientQuery, outletID)
|
||||||
|
|
||||||
if err := ingredientQuery.Scan(&ingredientData).Error; err != nil {
|
if err := ingredientQuery.Scan(&ingredientData).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -373,22 +248,26 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx contex
|
|||||||
v.name as vendor_name,
|
v.name as vendor_name,
|
||||||
COALESCE(SUM(poi.amount), 0) as total_cost,
|
COALESCE(SUM(poi.amount), 0) as total_cost,
|
||||||
COUNT(DISTINCT po.id) as purchase_order_count,
|
COUNT(DISTINCT po.id) as purchase_order_count,
|
||||||
COUNT(DISTINCT poi.ingredient_id) as ingredient_count,
|
COUNT(DISTINCT i.id) as ingredient_count,
|
||||||
COALESCE(SUM(poi.quantity), 0) as quantity
|
COALESCE(SUM(poi.quantity), 0) as quantity
|
||||||
`).
|
`).
|
||||||
Joins("JOIN vendors v ON po.vendor_id = v.id").
|
Joins("JOIN vendors v ON po.vendor_id = v.id").
|
||||||
Joins("LEFT JOIN purchase_order_items poi ON poi.purchase_order_id = po.id").
|
Joins("LEFT JOIN purchase_order_items poi ON poi.purchase_order_id = po.id").
|
||||||
|
Joins("LEFT JOIN ingredients i ON poi.ingredient_id = i.id").
|
||||||
|
Joins("LEFT JOIN units u ON poi.unit_id = u.id").
|
||||||
Where("po.organization_id = ?", organizationID).
|
Where("po.organization_id = ?", organizationID).
|
||||||
Where("po.status != ?", "cancelled").
|
Where("po.status != ?", "cancelled").
|
||||||
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
||||||
Group("v.id, v.name").
|
Group("v.id, v.name").
|
||||||
Order("total_cost DESC")
|
Order("total_cost DESC")
|
||||||
|
vendorQuery = r.applyPurchaseOrderItemOutletFilter(vendorQuery, outletID)
|
||||||
|
|
||||||
if err := vendorQuery.Scan(&vendorData).Error; err != nil {
|
if err := vendorQuery.Scan(&vendorData).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &entities.PurchasingAnalytics{
|
return &entities.PurchasingAnalytics{
|
||||||
|
OutletName: outletName,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
Data: data,
|
Data: data,
|
||||||
IngredientData: ingredientData,
|
IngredientData: ingredientData,
|
||||||
@ -396,6 +275,13 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx contex
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *AnalyticsRepositoryImpl) applyPurchaseOrderItemOutletFilter(query *gorm.DB, outletID *uuid.UUID) *gorm.DB {
|
||||||
|
if outletID == nil {
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
return query.Where("(i.outlet_id = ? OR u.outlet_id = ?)", *outletID, *outletID)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, limit int) ([]*entities.ProductAnalytics, error) {
|
func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, limit int) ([]*entities.ProductAnalytics, error) {
|
||||||
var results []*entities.ProductAnalytics
|
var results []*entities.ProductAnalytics
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user