apskel-pos-backend/internal/transformer/analytics_transformer.go

378 lines
11 KiB
Go
Raw Normal View History

2025-07-18 20:10:29 +07:00
package transformer
import (
"apskel-pos-be/internal/contract"
"apskel-pos-be/internal/models"
"fmt"
"time"
)
const ddmmyyyy = "02-01-2006"
// PaymentMethodAnalyticsContractToModel converts contract request to model
func PaymentMethodAnalyticsContractToModel(req *contract.PaymentMethodAnalyticsRequest) *models.PaymentMethodAnalyticsRequest {
var dateFrom, dateTo time.Time
if req.DateFrom != "" {
df, err := time.Parse(ddmmyyyy, req.DateFrom)
if err == nil {
dateFrom = df
}
}
if req.DateTo != "" {
dt, err := time.Parse(ddmmyyyy, req.DateTo)
if err == nil {
dateTo = dt
}
}
if req.DateFrom == req.DateTo {
dateTo.AddDate(0, 0, 1)
}
return &models.PaymentMethodAnalyticsRequest{
OrganizationID: req.OrganizationID,
OutletID: req.OutletID,
DateFrom: dateFrom,
DateTo: dateTo,
GroupBy: req.GroupBy,
}
}
// PaymentMethodAnalyticsModelToContract converts model response to contract
func PaymentMethodAnalyticsModelToContract(resp *models.PaymentMethodAnalyticsResponse) *contract.PaymentMethodAnalyticsResponse {
if resp == nil {
return nil
}
var data []contract.PaymentMethodAnalyticsData
for _, item := range resp.Data {
data = append(data, contract.PaymentMethodAnalyticsData{
PaymentMethodID: item.PaymentMethodID,
PaymentMethodName: item.PaymentMethodName,
PaymentMethodType: item.PaymentMethodType,
TotalAmount: item.TotalAmount,
OrderCount: item.OrderCount,
PaymentCount: item.PaymentCount,
Percentage: item.Percentage,
})
}
return &contract.PaymentMethodAnalyticsResponse{
OrganizationID: resp.OrganizationID,
OutletID: resp.OutletID,
DateFrom: resp.DateFrom,
DateTo: resp.DateTo,
GroupBy: resp.GroupBy,
Summary: contract.PaymentMethodSummary{
TotalAmount: resp.Summary.TotalAmount,
TotalOrders: resp.Summary.TotalOrders,
TotalPayments: resp.Summary.TotalPayments,
AverageOrderValue: resp.Summary.AverageOrderValue,
},
Data: data,
}
}
func SalesAnalyticsContractToModel(req *contract.SalesAnalyticsRequest) *models.SalesAnalyticsRequest {
var dateFrom, dateTo time.Time
if req.DateFrom != "" {
df, err := time.Parse(ddmmyyyy, req.DateFrom)
if err == nil {
dateFrom = df
}
}
if req.DateTo != "" {
dt, err := time.Parse(ddmmyyyy, req.DateTo)
if err == nil {
dateTo = dt
}
}
if req.DateFrom == req.DateTo {
dateTo.AddDate(0, 0, 1)
}
return &models.SalesAnalyticsRequest{
OrganizationID: req.OrganizationID,
OutletID: req.OutletID,
DateFrom: dateFrom,
DateTo: dateTo,
GroupBy: req.GroupBy,
}
}
// SalesAnalyticsModelToContract converts model response to contract
func SalesAnalyticsModelToContract(resp *models.SalesAnalyticsResponse) *contract.SalesAnalyticsResponse {
if resp == nil {
return nil
}
var data []contract.SalesAnalyticsData
for _, item := range resp.Data {
data = append(data, contract.SalesAnalyticsData{
Date: item.Date,
Sales: item.Sales,
Orders: item.Orders,
Items: item.Items,
Tax: item.Tax,
Discount: item.Discount,
NetSales: item.NetSales,
})
}
return &contract.SalesAnalyticsResponse{
OrganizationID: resp.OrganizationID,
OutletID: resp.OutletID,
DateFrom: resp.DateFrom,
DateTo: resp.DateTo,
GroupBy: resp.GroupBy,
Summary: contract.SalesSummary{
TotalSales: resp.Summary.TotalSales,
TotalOrders: resp.Summary.TotalOrders,
TotalItems: resp.Summary.TotalItems,
AverageOrderValue: resp.Summary.AverageOrderValue,
TotalTax: resp.Summary.TotalTax,
TotalDiscount: resp.Summary.TotalDiscount,
NetSales: resp.Summary.NetSales,
},
Data: data,
}
}
// ProductAnalyticsContractToModel converts contract request to model
func ProductAnalyticsContractToModel(req *contract.ProductAnalyticsRequest) *models.ProductAnalyticsRequest {
var dateFrom, dateTo time.Time
if req.DateFrom != "" {
df, err := time.Parse(ddmmyyyy, req.DateFrom)
if err == nil {
dateFrom = df
}
}
if req.DateTo != "" {
dt, err := time.Parse(ddmmyyyy, req.DateTo)
if err == nil {
dateTo = dt
}
}
if req.DateFrom == req.DateTo {
dateTo.AddDate(0, 0, 1)
}
return &models.ProductAnalyticsRequest{
OrganizationID: req.OrganizationID,
OutletID: req.OutletID,
DateFrom: dateFrom,
DateTo: dateTo,
Limit: req.Limit,
}
}
// ProductAnalyticsModelToContract converts model response to contract
func ProductAnalyticsModelToContract(resp *models.ProductAnalyticsResponse) *contract.ProductAnalyticsResponse {
if resp == nil {
return nil
}
var data []contract.ProductAnalyticsData
for _, item := range resp.Data {
data = append(data, contract.ProductAnalyticsData{
ProductID: item.ProductID,
ProductName: item.ProductName,
CategoryID: item.CategoryID,
CategoryName: item.CategoryName,
QuantitySold: item.QuantitySold,
Revenue: item.Revenue,
AveragePrice: item.AveragePrice,
OrderCount: item.OrderCount,
})
}
return &contract.ProductAnalyticsResponse{
OrganizationID: resp.OrganizationID,
OutletID: resp.OutletID,
DateFrom: resp.DateFrom,
DateTo: resp.DateTo,
Data: data,
}
}
// DashboardAnalyticsContractToModel converts contract request to model
func DashboardAnalyticsContractToModel(req *contract.DashboardAnalyticsRequest) *models.DashboardAnalyticsRequest {
var dateFrom, dateTo time.Time
if req.DateFrom != "" {
df, err := time.Parse(ddmmyyyy, req.DateFrom)
if err == nil {
dateFrom = df
}
}
if req.DateTo != "" {
dt, err := time.Parse(ddmmyyyy, req.DateTo)
if err == nil {
dateTo = dt
}
}
return &models.DashboardAnalyticsRequest{
OrganizationID: req.OrganizationID,
OutletID: req.OutletID,
DateFrom: dateFrom,
DateTo: dateTo,
}
}
// DashboardAnalyticsModelToContract converts model response to contract
func DashboardAnalyticsModelToContract(resp *models.DashboardAnalyticsResponse) *contract.DashboardAnalyticsResponse {
if resp == nil {
return nil
}
var topProducts []contract.ProductAnalyticsData
for _, item := range resp.TopProducts {
topProducts = append(topProducts, contract.ProductAnalyticsData{
ProductID: item.ProductID,
ProductName: item.ProductName,
CategoryID: item.CategoryID,
CategoryName: item.CategoryName,
QuantitySold: item.QuantitySold,
Revenue: item.Revenue,
AveragePrice: item.AveragePrice,
OrderCount: item.OrderCount,
})
}
var paymentMethods []contract.PaymentMethodAnalyticsData
for _, item := range resp.PaymentMethods {
paymentMethods = append(paymentMethods, contract.PaymentMethodAnalyticsData{
PaymentMethodID: item.PaymentMethodID,
PaymentMethodName: item.PaymentMethodName,
PaymentMethodType: item.PaymentMethodType,
TotalAmount: item.TotalAmount,
OrderCount: item.OrderCount,
PaymentCount: item.PaymentCount,
Percentage: item.Percentage,
})
}
var recentSales []contract.SalesAnalyticsData
for _, item := range resp.RecentSales {
recentSales = append(recentSales, contract.SalesAnalyticsData{
Date: item.Date,
Sales: item.Sales,
Orders: item.Orders,
Items: item.Items,
Tax: item.Tax,
Discount: item.Discount,
NetSales: item.NetSales,
})
}
return &contract.DashboardAnalyticsResponse{
OrganizationID: resp.OrganizationID,
OutletID: resp.OutletID,
DateFrom: resp.DateFrom,
DateTo: resp.DateTo,
Overview: contract.DashboardOverview{
TotalSales: resp.Overview.TotalSales,
TotalOrders: resp.Overview.TotalOrders,
AverageOrderValue: resp.Overview.AverageOrderValue,
TotalCustomers: resp.Overview.TotalCustomers,
VoidedOrders: resp.Overview.VoidedOrders,
RefundedOrders: resp.Overview.RefundedOrders,
},
TopProducts: topProducts,
PaymentMethods: paymentMethods,
RecentSales: recentSales,
}
}
// ProfitLossAnalyticsContractToModel transforms contract request to model
func ProfitLossAnalyticsContractToModel(req *contract.ProfitLossAnalyticsRequest) (*models.ProfitLossAnalyticsRequest, error) {
if req == nil {
return nil, fmt.Errorf("request cannot be nil")
}
dateFrom, err := time.Parse("02-01-2006", req.DateFrom)
if err != nil {
return nil, fmt.Errorf("invalid date_from format: %w", err)
}
dateTo, err := time.Parse("02-01-2006", req.DateTo)
if err != nil {
return nil, fmt.Errorf("invalid date_to format: %w", err)
}
return &models.ProfitLossAnalyticsRequest{
OrganizationID: req.OrganizationID,
OutletID: req.OutletID,
DateFrom: dateFrom,
DateTo: dateTo,
GroupBy: req.GroupBy,
}, nil
}
// ProfitLossAnalyticsModelToContract transforms model response to contract
func ProfitLossAnalyticsModelToContract(resp *models.ProfitLossAnalyticsResponse) *contract.ProfitLossAnalyticsResponse {
if resp == nil {
return nil
}
// Transform profit/loss data
data := make([]contract.ProfitLossData, len(resp.Data))
for i, item := range resp.Data {
data[i] = contract.ProfitLossData{
Date: item.Date,
Revenue: item.Revenue,
Cost: item.Cost,
GrossProfit: item.GrossProfit,
GrossProfitMargin: item.GrossProfitMargin,
Tax: item.Tax,
Discount: item.Discount,
NetProfit: item.NetProfit,
NetProfitMargin: item.NetProfitMargin,
Orders: item.Orders,
}
}
// Transform product profit data
productData := make([]contract.ProductProfitData, len(resp.ProductData))
for i, item := range resp.ProductData {
productData[i] = contract.ProductProfitData{
ProductID: item.ProductID,
ProductName: item.ProductName,
CategoryID: item.CategoryID,
CategoryName: item.CategoryName,
QuantitySold: item.QuantitySold,
Revenue: item.Revenue,
Cost: item.Cost,
GrossProfit: item.GrossProfit,
GrossProfitMargin: item.GrossProfitMargin,
AveragePrice: item.AveragePrice,
AverageCost: item.AverageCost,
ProfitPerUnit: item.ProfitPerUnit,
}
}
return &contract.ProfitLossAnalyticsResponse{
OrganizationID: resp.OrganizationID,
OutletID: resp.OutletID,
DateFrom: resp.DateFrom,
DateTo: resp.DateTo,
GroupBy: resp.GroupBy,
Summary: contract.ProfitLossSummary{
TotalRevenue: resp.Summary.TotalRevenue,
TotalCost: resp.Summary.TotalCost,
GrossProfit: resp.Summary.GrossProfit,
GrossProfitMargin: resp.Summary.GrossProfitMargin,
TotalTax: resp.Summary.TotalTax,
TotalDiscount: resp.Summary.TotalDiscount,
NetProfit: resp.Summary.NetProfit,
NetProfitMargin: resp.Summary.NetProfitMargin,
TotalOrders: resp.Summary.TotalOrders,
AverageProfit: resp.Summary.AverageProfit,
ProfitabilityRatio: resp.Summary.ProfitabilityRatio,
},
Data: data,
ProductData: productData,
}
}