From 3e0d75a4d03a8e11d1e6d94b43f8254cab894db3 Mon Sep 17 00:00:00 2001 From: efrilm Date: Thu, 9 Oct 2025 20:03:20 +0700 Subject: [PATCH] update products --- internal/contract/analytics_contract.go | 1 + internal/entities/analytics.go | 1 + internal/models/analytics.go | 1 + internal/processor/analytics_processor.go | 1 + internal/repository/analytics_repository.go | 36 +++++++++++++------ internal/transformer/analytics_transformer.go | 1 + 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/internal/contract/analytics_contract.go b/internal/contract/analytics_contract.go index 81d2e9e..c97edd4 100644 --- a/internal/contract/analytics_contract.go +++ b/internal/contract/analytics_contract.go @@ -105,6 +105,7 @@ type ProductAnalyticsResponse struct { type ProductAnalyticsData struct { ProductID uuid.UUID `json:"product_id"` ProductName string `json:"product_name"` + ProductSku string `json:"product_sku"` CategoryID uuid.UUID `json:"category_id"` CategoryName string `json:"category_name"` CategoryOrder int `json:"category_order"` diff --git a/internal/entities/analytics.go b/internal/entities/analytics.go index 0ba9882..10ae208 100644 --- a/internal/entities/analytics.go +++ b/internal/entities/analytics.go @@ -31,6 +31,7 @@ type SalesAnalytics struct { type ProductAnalytics struct { ProductID uuid.UUID `json:"product_id"` ProductName string `json:"product_name"` + ProductSku string `json:"product_sku"` CategoryID uuid.UUID `json:"category_id"` CategoryName string `json:"category_name"` CategoryOrder int `json:"category_order"` diff --git a/internal/models/analytics.go b/internal/models/analytics.go index e20b4df..1e41e4e 100644 --- a/internal/models/analytics.go +++ b/internal/models/analytics.go @@ -109,6 +109,7 @@ type ProductAnalyticsResponse struct { type ProductAnalyticsData struct { ProductID uuid.UUID `json:"product_id"` ProductName string `json:"product_name"` + ProductSku string `json:"product_sku"` CategoryID uuid.UUID `json:"category_id"` CategoryName string `json:"category_name"` CategoryOrder int `json:"category_order"` diff --git a/internal/processor/analytics_processor.go b/internal/processor/analytics_processor.go index d922a38..d35ac8d 100644 --- a/internal/processor/analytics_processor.go +++ b/internal/processor/analytics_processor.go @@ -187,6 +187,7 @@ func (p *AnalyticsProcessorImpl) GetProductAnalytics(ctx context.Context, req *m resultData = append(resultData, models.ProductAnalyticsData{ ProductID: data.ProductID, ProductName: data.ProductName, + ProductSku: data.ProductSku, CategoryID: data.CategoryID, CategoryName: data.CategoryName, CategoryOrder: data.CategoryOrder, diff --git a/internal/repository/analytics_repository.go b/internal/repository/analytics_repository.go index e2f85a1..031f055 100644 --- a/internal/repository/analytics_repository.go +++ b/internal/repository/analytics_repository.go @@ -110,14 +110,10 @@ func (r *AnalyticsRepositoryImpl) GetSalesAnalytics(ctx context.Context, organiz 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 - query := r.db.WithContext(ctx). - Table("order_items oi"). + // Subquery untuk menghitung analytics dari orders + salesSubquery := r.db.Table("order_items oi"). Select(` p.id as product_id, - p.name as product_name, - c.id as category_id, - c.name as category_name, - c.order as category_order, 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(CASE WHEN oi.is_fully_refunded = false THEN oi.total_price - COALESCE(oi.refund_amount, 0) ELSE 0 END), 0) as revenue, CASE @@ -128,7 +124,6 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organ COUNT(DISTINCT oi.order_id) as order_count `). Joins("JOIN products p ON oi.product_id = p.id"). - Joins("JOIN categories c ON p.category_id = c.id"). Joins("JOIN orders o ON oi.order_id = o.id"). Where("o.organization_id = ?", organizationID). Where("o.is_void = ?", false). @@ -138,12 +133,33 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organ Where("o.created_at >= ? AND o.created_at <= ?", dateFrom, dateTo) if outletID != nil { - query = query.Where("o.outlet_id = ?", *outletID) + salesSubquery = salesSubquery.Where("o.outlet_id = ?", *outletID) } + salesSubquery = salesSubquery.Group("p.id") + + // Main query: ambil semua products dan LEFT JOIN dengan sales subquery + query := r.db.WithContext(ctx). + Table("products p"). + Select(` + p.id as product_id, + p.name as product_name, + p.sku as product_sku, + c.id as category_id, + c.name as category_name, + c.order as category_order, + COALESCE(sales.quantity_sold, 0) as quantity_sold, + COALESCE(sales.revenue, 0) as revenue, + COALESCE(sales.average_price, 0) as average_price, + COALESCE(sales.order_count, 0) as order_count + `). + Joins("JOIN categories c ON p.category_id = c.id"). + Joins("LEFT JOIN (?) as sales ON sales.product_id = p.id", salesSubquery). + Where("p.organization_id = ?", organizationID) + err := query. - Group("p.id, p.name, c.id, c.name"). - Order("revenue DESC"). + Group("p.id, p.name, p.sku, c.id, c.name, c.order, sales.quantity_sold, sales.revenue, sales.average_price, sales.order_count"). + Order("COALESCE(sales.revenue, 0) DESC, p.name ASC"). Limit(limit). Scan(&results).Error diff --git a/internal/transformer/analytics_transformer.go b/internal/transformer/analytics_transformer.go index 3592893..934da2a 100644 --- a/internal/transformer/analytics_transformer.go +++ b/internal/transformer/analytics_transformer.go @@ -157,6 +157,7 @@ func ProductAnalyticsModelToContract(resp *models.ProductAnalyticsResponse) *con data = append(data, contract.ProductAnalyticsData{ ProductID: item.ProductID, ProductName: item.ProductName, + ProductSku: item.ProductSku, CategoryID: item.CategoryID, CategoryName: item.CategoryName, CategoryOrder: item.CategoryOrder,