fix conflict

This commit is contained in:
Efril 2026-06-11 16:47:03 +07:00
parent d0a548f44e
commit 7a7ac25dcf

View File

@ -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,29 +143,32 @@ func (r *AnalyticsRepositoryImpl) GetPurchasingAnalytics(ctx context.Context, or
outletName = &outlet.Name outletName = &outlet.Name
} }
} }
return r.getPurchaseOrderPurchasingAnalytics(ctx, organizationID, outletID, outletName, dateFrom, dateTo, groupBy)
}
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
summaryQuery := r.db.WithContext(ctx). summaryQuery := r.db.WithContext(ctx).
Table("inventory_movements im"). Table("purchase_orders po").
Select(` Select(`
COALESCE(SUM(im.total_cost), 0) as total_purchases, COALESCE(SUM(poi.amount), 0) as total_purchases,
COUNT(DISTINCT im.reference_id) as total_purchase_orders, COUNT(DISTINCT po.id) as total_purchase_orders,
COALESCE(SUM(im.quantity), 0) as total_quantity, COALESCE(SUM(poi.quantity), 0) as total_quantity,
CASE CASE
WHEN COUNT(DISTINCT im.reference_id) > 0 WHEN COUNT(DISTINCT po.id) > 0
THEN COALESCE(SUM(im.total_cost), 0) / COUNT(DISTINCT im.reference_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 im.item_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_orders po ON im.reference_id = po.id"). Joins("LEFT JOIN purchase_order_items poi ON poi.purchase_order_id = po.id").
Where("im.organization_id = ?", organizationID). Joins("LEFT JOIN ingredients i ON poi.ingredient_id = i.id").
Where("im.movement_type = ?", entities.InventoryMovementTypePurchase). Joins("LEFT JOIN units u ON poi.unit_id = u.id").
Where("im.item_type = ?", "INGREDIENT"). Where("po.organization_id = ?", organizationID).
Where("im.reference_type = ?", entities.InventoryMovementReferenceTypePurchaseOrder). Where("po.status != ?", "cancelled").
Where("im.created_at >= ? AND im.created_at <= ?", dateFrom, dateTo) Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo)
summaryQuery = r.applyPurchaseOrderItemOutletFilter(summaryQuery, outletID)
summaryQuery = r.resolveOutletID(summaryQuery, outletID, "im.outlet_id")
if err := summaryQuery.Scan(&summary).Error; err != nil { if err := summaryQuery.Scan(&summary).Error; err != nil {
return nil, err return nil, err
@ -175,36 +177,35 @@ func (r *AnalyticsRepositoryImpl) GetPurchasingAnalytics(ctx context.Context, or
var dateFormat string var dateFormat string
switch groupBy { switch groupBy {
case "hour": case "hour":
dateFormat = "DATE_TRUNC('hour', im.created_at)" dateFormat = "DATE_TRUNC('hour', po.created_at)"
case "week": case "week":
dateFormat = "DATE_TRUNC('week', im.created_at)" dateFormat = "DATE_TRUNC('week', po.transaction_date::timestamp)"
case "month": case "month":
dateFormat = "DATE_TRUNC('month', im.created_at)" dateFormat = "DATE_TRUNC('month', po.transaction_date::timestamp)"
default: default:
dateFormat = "DATE_TRUNC('day', im.created_at)" dateFormat = "DATE_TRUNC('day', po.transaction_date::timestamp)"
} }
var data []entities.PurchasingAnalyticsData var data []entities.PurchasingAnalyticsData
dataQuery := r.db.WithContext(ctx). dataQuery := r.db.WithContext(ctx).
Table("inventory_movements im"). Table("purchase_orders po").
Select(` Select(`
`+dateFormat+` as date, `+dateFormat+` as date,
COALESCE(SUM(im.total_cost), 0) as purchases, COALESCE(SUM(poi.amount), 0) as purchases,
COUNT(DISTINCT im.reference_id) as purchase_orders, COUNT(DISTINCT po.id) as purchase_orders,
COALESCE(SUM(im.quantity), 0) as quantity, COALESCE(SUM(poi.quantity), 0) as quantity,
COUNT(DISTINCT im.item_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_orders po ON im.reference_id = po.id"). Joins("LEFT JOIN purchase_order_items poi ON poi.purchase_order_id = po.id").
Where("im.organization_id = ?", organizationID). Joins("LEFT JOIN ingredients i ON poi.ingredient_id = i.id").
Where("im.movement_type = ?", entities.InventoryMovementTypePurchase). Joins("LEFT JOIN units u ON poi.unit_id = u.id").
Where("im.item_type = ?", "INGREDIENT"). Where("po.organization_id = ?", organizationID).
Where("im.reference_type = ?", entities.InventoryMovementReferenceTypePurchaseOrder). Where("po.status != ?", "cancelled").
Where("im.created_at >= ? AND im.created_at <= ?", 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)
dataQuery = r.resolveOutletID(dataQuery, outletID, "im.outlet_id")
if err := dataQuery.Scan(&data).Error; err != nil { if err := dataQuery.Scan(&data).Error; err != nil {
return nil, err return nil, err
@ -212,29 +213,28 @@ func (r *AnalyticsRepositoryImpl) GetPurchasingAnalytics(ctx context.Context, or
var ingredientData []entities.PurchasingIngredientData var ingredientData []entities.PurchasingIngredientData
ingredientQuery := r.db.WithContext(ctx). ingredientQuery := r.db.WithContext(ctx).
Table("inventory_movements im"). Table("purchase_order_items poi").
Select(` Select(`
i.id as ingredient_id, i.id as ingredient_id,
i.name as ingredient_name, i.name as ingredient_name,
COALESCE(SUM(im.quantity), 0) as quantity, COALESCE(SUM(poi.quantity), 0) as quantity,
COALESCE(SUM(im.total_cost), 0) as total_cost, COALESCE(SUM(poi.amount), 0) as total_cost,
CASE CASE
WHEN SUM(im.quantity) > 0 WHEN SUM(poi.quantity) > 0
THEN COALESCE(SUM(im.total_cost), 0) / SUM(im.quantity) THEN COALESCE(SUM(poi.amount), 0) / SUM(poi.quantity)
ELSE 0 ELSE 0
END as average_unit_cost, END as average_unit_cost,
COUNT(DISTINCT im.reference_id) as purchase_order_count COUNT(DISTINCT po.id) as purchase_order_count
`). `).
Joins("JOIN ingredients i ON im.item_id = i.id"). Joins("JOIN purchase_orders po ON poi.purchase_order_id = po.id").
Where("im.organization_id = ?", organizationID). Joins("JOIN ingredients i ON poi.ingredient_id = i.id").
Where("im.movement_type = ?", entities.InventoryMovementTypePurchase). Joins("LEFT JOIN units u ON poi.unit_id = u.id").
Where("im.item_type = ?", "INGREDIENT"). Where("po.organization_id = ?", organizationID).
Where("im.reference_type = ?", entities.InventoryMovementReferenceTypePurchaseOrder). Where("po.status != ?", "cancelled").
Where("im.created_at >= ? AND im.created_at <= ?", 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)
ingredientQuery = r.resolveOutletID(ingredientQuery, outletID, "im.outlet_id")
if err := ingredientQuery.Scan(&ingredientData).Error; err != nil { if err := ingredientQuery.Scan(&ingredientData).Error; err != nil {
return nil, err return nil, err
@ -242,26 +242,25 @@ func (r *AnalyticsRepositoryImpl) GetPurchasingAnalytics(ctx context.Context, or
var vendorData []entities.PurchasingVendorData var vendorData []entities.PurchasingVendorData
vendorQuery := r.db.WithContext(ctx). vendorQuery := r.db.WithContext(ctx).
Table("inventory_movements im"). Table("purchase_orders po").
Select(` Select(`
v.id as vendor_id, v.id as vendor_id,
v.name as vendor_name, v.name as vendor_name,
COALESCE(SUM(im.total_cost), 0) as total_cost, COALESCE(SUM(poi.amount), 0) as total_cost,
COUNT(DISTINCT im.reference_id) as purchase_order_count, COUNT(DISTINCT po.id) as purchase_order_count,
COUNT(DISTINCT im.item_id) as ingredient_count, COUNT(DISTINCT i.id) as ingredient_count,
COALESCE(SUM(im.quantity), 0) as quantity COALESCE(SUM(poi.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"). Joins("JOIN vendors v ON po.vendor_id = v.id").
Where("im.organization_id = ?", organizationID). Joins("LEFT JOIN purchase_order_items poi ON poi.purchase_order_id = po.id").
Where("im.movement_type = ?", entities.InventoryMovementTypePurchase). Joins("LEFT JOIN ingredients i ON poi.ingredient_id = i.id").
Where("im.item_type = ?", "INGREDIENT"). Joins("LEFT JOIN units u ON poi.unit_id = u.id").
Where("im.reference_type = ?", entities.InventoryMovementReferenceTypePurchaseOrder). Where("po.organization_id = ?", organizationID).
Where("im.created_at >= ? AND im.created_at <= ?", dateFrom, dateTo). Where("po.status != ?", "cancelled").
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)
vendorQuery = r.resolveOutletID(vendorQuery, outletID, "im.outlet_id")
if err := vendorQuery.Scan(&vendorData).Error; err != nil { if err := vendorQuery.Scan(&vendorData).Error; err != nil {
return nil, err return nil, err
@ -276,6 +275,13 @@ func (r *AnalyticsRepositoryImpl) GetPurchasingAnalytics(ctx context.Context, or
}, 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
@ -284,7 +290,6 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organ
Select(` Select(`
p.id as product_id, p.id as product_id,
p.name as product_name, p.name as product_name,
p.price as product_price,
c.id as category_id, c.id as category_id,
c.name as category_name, c.name as category_name,
c.order as category_order, c.order as category_order,
@ -343,7 +348,7 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organ
query = r.resolveOutletID(query, outletID, "o.outlet_id") query = r.resolveOutletID(query, outletID, "o.outlet_id")
err := query. err := query.
Group("p.id, p.name, p.price, p.cost, c.id, c.name, c.order, mahpp.hpp_per_unit"). Group("p.id, p.name, p.cost, c.id, c.name, c.order, mahpp.hpp_per_unit").
Order("revenue DESC"). Order("revenue DESC").
Limit(limit). Limit(limit).
Scan(&results).Error Scan(&results).Error
@ -638,7 +643,7 @@ func (r *AnalyticsRepositoryImpl) getExpenseByCategory(ctx context.Context, orga
query := r.db.WithContext(ctx). query := r.db.WithContext(ctx).
Table("expense_items ei"). Table("expense_items ei").
Select(`COALESCE(parent_coa.name, 'Lain-lain') as category_name, COALESCE(SUM(ei.amount), 0) as amount`). Select(`COALESCE(parent_coa.name, coa.name, 'Lain-lain') as category_name, COALESCE(SUM(ei.amount), 0) as amount`).
Joins("JOIN expenses e ON ei.expense_id = e.id"). Joins("JOIN expenses e ON ei.expense_id = e.id").
Joins("JOIN chart_of_accounts coa ON ei.chart_of_account_id = coa.id"). Joins("JOIN chart_of_accounts coa ON ei.chart_of_account_id = coa.id").
Joins("LEFT JOIN chart_of_accounts parent_coa ON coa.parent_id = parent_coa.id"). Joins("LEFT JOIN chart_of_accounts parent_coa ON coa.parent_id = parent_coa.id").
@ -651,8 +656,8 @@ func (r *AnalyticsRepositoryImpl) getExpenseByCategory(ctx context.Context, orga
} }
err := query. err := query.
Group("parent_coa.name"). Group("COALESCE(parent_coa.name, coa.name, 'Lain-lain')").
Order("parent_coa.name"). Order("COALESCE(parent_coa.name, coa.name, 'Lain-lain')").
Scan(&results).Error Scan(&results).Error
return results, err return results, err