|
|
@@ -45,8 +45,10 @@ func (r *AnalyticsRepositoryImpl) GetPaymentMethodAnalytics(ctx context.Context,
|
|
|
|
Joins("JOIN payment_methods pm ON p.payment_method_id = pm.id").
|
|
|
|
Joins("JOIN payment_methods pm ON p.payment_method_id = pm.id").
|
|
|
|
Joins("JOIN orders o ON p.order_id = o.id").
|
|
|
|
Joins("JOIN orders o ON p.order_id = o.id").
|
|
|
|
Where("o.organization_id = ?", organizationID).
|
|
|
|
Where("o.organization_id = ?", organizationID).
|
|
|
|
|
|
|
|
Where("o.is_void = ?", false).
|
|
|
|
|
|
|
|
Where("o.is_refund = ?", false).
|
|
|
|
Where("p.status = ?", entities.PaymentTransactionStatusCompleted).
|
|
|
|
Where("p.status = ?", entities.PaymentTransactionStatusCompleted).
|
|
|
|
Where("p.created_at >= ? AND p.created_at <= ?", dateFrom, dateTo)
|
|
|
|
Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo)
|
|
|
|
|
|
|
|
|
|
|
|
if outletID != nil {
|
|
|
|
if outletID != nil {
|
|
|
|
query = query.Where("o.outlet_id = ?", *outletID)
|
|
|
|
query = query.Where("o.outlet_id = ?", *outletID)
|
|
|
@@ -81,7 +83,7 @@ func (r *AnalyticsRepositoryImpl) GetSalesAnalytics(ctx context.Context, organiz
|
|
|
|
`+dateFormat+` as date,
|
|
|
|
`+dateFormat+` as date,
|
|
|
|
COALESCE(SUM(o.total_amount), 0) as sales,
|
|
|
|
COALESCE(SUM(o.total_amount), 0) as sales,
|
|
|
|
COUNT(o.id) as orders,
|
|
|
|
COUNT(o.id) as orders,
|
|
|
|
COALESCE(SUM(oi.quantity), 0) as items,
|
|
|
|
COALESCE(SUM(CASE WHEN oi.status != 'cancelled' AND oi.is_fully_refunded = false THEN oi.quantity - COALESCE(oi.refund_quantity, 0) ELSE 0 END), 0) as items,
|
|
|
|
COALESCE(SUM(o.tax_amount), 0) as tax,
|
|
|
|
COALESCE(SUM(o.tax_amount), 0) as tax,
|
|
|
|
COALESCE(SUM(o.discount_amount), 0) as discount,
|
|
|
|
COALESCE(SUM(o.discount_amount), 0) as discount,
|
|
|
|
COALESCE(SUM(o.total_amount - o.tax_amount - o.discount_amount), 0) as net_sales
|
|
|
|
COALESCE(SUM(o.total_amount - o.tax_amount - o.discount_amount), 0) as net_sales
|
|
|
@@ -89,6 +91,8 @@ func (r *AnalyticsRepositoryImpl) GetSalesAnalytics(ctx context.Context, organiz
|
|
|
|
Joins("LEFT JOIN order_items oi ON o.id = oi.order_id").
|
|
|
|
Joins("LEFT JOIN order_items oi ON o.id = oi.order_id").
|
|
|
|
Where("o.organization_id = ?", organizationID).
|
|
|
|
Where("o.organization_id = ?", organizationID).
|
|
|
|
Where("o.is_void = ?", false).
|
|
|
|
Where("o.is_void = ?", false).
|
|
|
|
|
|
|
|
Where("o.is_refund = ?", false).
|
|
|
|
|
|
|
|
Where("o.payment_status = ?", entities.PaymentStatusCompleted).
|
|
|
|
Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo)
|
|
|
|
Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo)
|
|
|
|
|
|
|
|
|
|
|
|
if outletID != nil {
|
|
|
|
if outletID != nil {
|
|
|
@@ -113,10 +117,11 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organ
|
|
|
|
p.name as product_name,
|
|
|
|
p.name as product_name,
|
|
|
|
c.id as category_id,
|
|
|
|
c.id as category_id,
|
|
|
|
c.name as category_name,
|
|
|
|
c.name as category_name,
|
|
|
|
COALESCE(SUM(oi.quantity), 0) as quantity_sold,
|
|
|
|
COALESCE(SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.quantity - COALESCE(oi.refund_quantity, 0) ELSE 0 END), 0) as quantity_sold,
|
|
|
|
COALESCE(SUM(oi.total_price), 0) as revenue,
|
|
|
|
COALESCE(SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.total_price - COALESCE(oi.refund_amount, 0) ELSE 0 END), 0) as revenue,
|
|
|
|
CASE
|
|
|
|
CASE
|
|
|
|
WHEN SUM(oi.quantity) > 0 THEN COALESCE(SUM(oi.total_price), 0) / SUM(oi.quantity)
|
|
|
|
WHEN SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.quantity - COALESCE(oi.refund_quantity, 0) ELSE 0 END) > 0
|
|
|
|
|
|
|
|
THEN COALESCE(SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.total_price - COALESCE(oi.refund_amount, 0) ELSE 0 END), 0) / SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.quantity - COALESCE(oi.refund_quantity, 0) ELSE 0 END)
|
|
|
|
ELSE 0
|
|
|
|
ELSE 0
|
|
|
|
END as average_price,
|
|
|
|
END as average_price,
|
|
|
|
COUNT(DISTINCT oi.order_id) as order_count
|
|
|
|
COUNT(DISTINCT oi.order_id) as order_count
|
|
|
@@ -126,6 +131,9 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organ
|
|
|
|
Joins("JOIN orders o ON oi.order_id = o.id").
|
|
|
|
Joins("JOIN orders o ON oi.order_id = o.id").
|
|
|
|
Where("o.organization_id = ?", organizationID).
|
|
|
|
Where("o.organization_id = ?", organizationID).
|
|
|
|
Where("o.is_void = ?", false).
|
|
|
|
Where("o.is_void = ?", false).
|
|
|
|
|
|
|
|
Where("o.is_refund = ?", false).
|
|
|
|
|
|
|
|
Where("o.payment_status = ?", entities.PaymentStatusCompleted).
|
|
|
|
|
|
|
|
Where("oi.status != ?", entities.OrderItemStatusCancelled).
|
|
|
|
Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo)
|
|
|
|
Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo)
|
|
|
|
|
|
|
|
|
|
|
|
if outletID != nil {
|
|
|
|
if outletID != nil {
|
|
|
@@ -134,7 +142,7 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organ
|
|
|
|
|
|
|
|
|
|
|
|
err := query.
|
|
|
|
err := query.
|
|
|
|
Group("p.id, p.name, c.id, c.name").
|
|
|
|
Group("p.id, p.name, c.id, c.name").
|
|
|
|
Order("revenue DESC").
|
|
|
|
Order("c.name ASC, revenue DESC").
|
|
|
|
Limit(limit).
|
|
|
|
Limit(limit).
|
|
|
|
Scan(&results).Error
|
|
|
|
Scan(&results).Error
|
|
|
|
|
|
|
|
|
|
|
@@ -149,8 +157,8 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalyticsPerCategory(ctx context.Con
|
|
|
|
Select(`
|
|
|
|
Select(`
|
|
|
|
c.id as category_id,
|
|
|
|
c.id as category_id,
|
|
|
|
c.name as category_name,
|
|
|
|
c.name as category_name,
|
|
|
|
COALESCE(SUM(oi.total_price), 0) as total_revenue,
|
|
|
|
COALESCE(SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.total_price - COALESCE(oi.refund_amount, 0) ELSE 0 END), 0) as total_revenue,
|
|
|
|
COALESCE(SUM(oi.quantity), 0) as total_quantity,
|
|
|
|
COALESCE(SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.quantity - COALESCE(oi.refund_quantity, 0) ELSE 0 END), 0) as total_quantity,
|
|
|
|
COUNT(DISTINCT p.id) as product_count,
|
|
|
|
COUNT(DISTINCT p.id) as product_count,
|
|
|
|
COUNT(DISTINCT oi.order_id) as order_count
|
|
|
|
COUNT(DISTINCT oi.order_id) as order_count
|
|
|
|
`).
|
|
|
|
`).
|
|
|
@@ -159,6 +167,9 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalyticsPerCategory(ctx context.Con
|
|
|
|
Joins("JOIN orders o ON oi.order_id = o.id").
|
|
|
|
Joins("JOIN orders o ON oi.order_id = o.id").
|
|
|
|
Where("o.organization_id = ?", organizationID).
|
|
|
|
Where("o.organization_id = ?", organizationID).
|
|
|
|
Where("o.is_void = ?", false).
|
|
|
|
Where("o.is_void = ?", false).
|
|
|
|
|
|
|
|
Where("o.is_refund = ?", false).
|
|
|
|
|
|
|
|
Where("o.payment_status = ?", entities.PaymentStatusCompleted).
|
|
|
|
|
|
|
|
Where("oi.status != ?", entities.OrderItemStatusCancelled).
|
|
|
|
Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo)
|
|
|
|
Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo)
|
|
|
|
|
|
|
|
|
|
|
|
if outletID != nil {
|
|
|
|
if outletID != nil {
|
|
|
@@ -319,18 +330,18 @@ func (r *AnalyticsRepositoryImpl) GetProfitLossAnalytics(ctx context.Context, or
|
|
|
|
p.name as product_name,
|
|
|
|
p.name as product_name,
|
|
|
|
c.id as category_id,
|
|
|
|
c.id as category_id,
|
|
|
|
c.name as category_name,
|
|
|
|
c.name as category_name,
|
|
|
|
SUM(oi.quantity) as quantity_sold,
|
|
|
|
SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.quantity - COALESCE(oi.refund_quantity, 0) ELSE 0 END) as quantity_sold,
|
|
|
|
SUM(oi.total_price) as revenue,
|
|
|
|
SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.total_price - COALESCE(oi.refund_amount, 0) ELSE 0 END) as revenue,
|
|
|
|
SUM(oi.total_cost) as cost,
|
|
|
|
SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.total_cost * ((oi.quantity - COALESCE(oi.refund_quantity, 0))::float / NULLIF(oi.quantity, 0)) ELSE 0 END) as cost,
|
|
|
|
SUM(oi.total_price - oi.total_cost) as gross_profit,
|
|
|
|
SUM(CASE WHEN oi.is_fully_refunded = false THEN (oi.total_price - COALESCE(oi.refund_amount, 0)) - (oi.total_cost * ((oi.quantity - COALESCE(oi.refund_quantity, 0))::float / NULLIF(oi.quantity, 0))) ELSE 0 END) as gross_profit,
|
|
|
|
CASE
|
|
|
|
CASE
|
|
|
|
WHEN SUM(oi.total_price) > 0
|
|
|
|
WHEN SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.total_price - COALESCE(oi.refund_amount, 0) ELSE 0 END) > 0
|
|
|
|
THEN (SUM(oi.total_price - oi.total_cost) / SUM(oi.total_price)) * 100
|
|
|
|
THEN (SUM(CASE WHEN oi.is_fully_refunded = false THEN (oi.total_price - COALESCE(oi.refund_amount, 0)) - (oi.total_cost * ((oi.quantity - COALESCE(oi.refund_quantity, 0))::float / NULLIF(oi.quantity, 0))) ELSE 0 END) / SUM(CASE WHEN oi.is_fully_refunded = false THEN oi.total_price - COALESCE(oi.refund_amount, 0) ELSE 0 END)) * 100
|
|
|
|
ELSE 0
|
|
|
|
ELSE 0
|
|
|
|
END as gross_profit_margin,
|
|
|
|
END as gross_profit_margin,
|
|
|
|
AVG(oi.unit_price) as average_price,
|
|
|
|
AVG(CASE WHEN oi.is_fully_refunded = false THEN oi.unit_price ELSE NULL END) as average_price,
|
|
|
|
AVG(oi.unit_cost) as average_cost,
|
|
|
|
AVG(CASE WHEN oi.is_fully_refunded = false THEN oi.unit_cost ELSE NULL END) as average_cost,
|
|
|
|
AVG(oi.unit_price - oi.unit_cost) as profit_per_unit
|
|
|
|
AVG(CASE WHEN oi.is_fully_refunded = false THEN oi.unit_price - oi.unit_cost ELSE NULL END) as profit_per_unit
|
|
|
|
`).
|
|
|
|
`).
|
|
|
|
Joins("JOIN orders o ON oi.order_id = o.id").
|
|
|
|
Joins("JOIN orders o ON oi.order_id = o.id").
|
|
|
|
Joins("JOIN products p ON oi.product_id = p.id").
|
|
|
|
Joins("JOIN products p ON oi.product_id = p.id").
|
|
|
@@ -339,10 +350,11 @@ func (r *AnalyticsRepositoryImpl) GetProfitLossAnalytics(ctx context.Context, or
|
|
|
|
Where("o.status = ?", entities.OrderStatusCompleted).
|
|
|
|
Where("o.status = ?", entities.OrderStatusCompleted).
|
|
|
|
Where("o.payment_status = ?", entities.PaymentStatusCompleted).
|
|
|
|
Where("o.payment_status = ?", entities.PaymentStatusCompleted).
|
|
|
|
Where("o.is_void = false AND o.is_refund = false").
|
|
|
|
Where("o.is_void = false AND o.is_refund = false").
|
|
|
|
|
|
|
|
Where("oi.status != ?", entities.OrderItemStatusCancelled).
|
|
|
|
Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo).
|
|
|
|
Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo).
|
|
|
|
Group("p.id, p.name, c.id, c.name").
|
|
|
|
Group("p.id, p.name, c.id, c.name").
|
|
|
|
Order("gross_profit DESC").
|
|
|
|
Order("c.name ASC, gross_profit DESC").
|
|
|
|
Limit(20)
|
|
|
|
Limit(1000)
|
|
|
|
|
|
|
|
|
|
|
|
if outletID != nil {
|
|
|
|
if outletID != nil {
|
|
|
|
productQuery = productQuery.Where("o.outlet_id = ?", *outletID)
|
|
|
|
productQuery = productQuery.Where("o.outlet_id = ?", *outletID)
|
|
|
|