add purchasing in analytics endpoint
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
type AnalyticsRepository interface {
|
||||
GetPaymentMethodAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time) ([]*entities.PaymentMethodAnalytics, error)
|
||||
GetSalesAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, groupBy string) ([]*entities.SalesAnalytics, error)
|
||||
GetPurchasingAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, groupBy string) (*entities.PurchasingAnalytics, error)
|
||||
GetProductAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, limit int) ([]*entities.ProductAnalytics, error)
|
||||
GetProductAnalyticsPerCategory(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time) ([]*entities.ProductAnalyticsPerCategory, error)
|
||||
GetDashboardOverview(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time) (*entities.DashboardOverview, error)
|
||||
@@ -122,6 +123,159 @@ func (r *AnalyticsRepositoryImpl) GetSalesAnalytics(ctx context.Context, organiz
|
||||
return results, err
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
if outletID != nil {
|
||||
var outlet struct {
|
||||
Name string
|
||||
}
|
||||
result := r.db.WithContext(ctx).
|
||||
Table("outlets").
|
||||
Select("name").
|
||||
Where("id = ? AND organization_id = ?", *outletID, organizationID).
|
||||
Limit(1).
|
||||
Scan(&outlet)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
if result.RowsAffected > 0 {
|
||||
outletName = &outlet.Name
|
||||
}
|
||||
}
|
||||
|
||||
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) GetProductAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, limit int) ([]*entities.ProductAnalytics, error) {
|
||||
var results []*entities.ProductAnalytics
|
||||
|
||||
|
||||
Reference in New Issue
Block a user