feat: updat analytic profit loss add purchasing
This commit is contained in:
parent
793919cf10
commit
9b0fc9a63b
@ -272,10 +272,28 @@ type ProfitLossAnalyticsResponse struct {
|
|||||||
Data []ProfitLossData `json:"data"`
|
Data []ProfitLossData `json:"data"`
|
||||||
ProductData []ProductProfitData `json:"product_data"`
|
ProductData []ProductProfitData `json:"product_data"`
|
||||||
MainSummary []ProfitLossSummaryRow `json:"main_summary"`
|
MainSummary []ProfitLossSummaryRow `json:"main_summary"`
|
||||||
|
Purchasing ProfitLossPurchasing `json:"purchasing"`
|
||||||
OperationalExpenses []OperationalExpenseItem `json:"operational_expenses"`
|
OperationalExpenses []OperationalExpenseItem `json:"operational_expenses"`
|
||||||
OperationalExpensesTotal float64 `json:"operational_expenses_total"`
|
OperationalExpensesTotal float64 `json:"operational_expenses_total"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProfitLossPurchasing struct {
|
||||||
|
TodayTotal float64 `json:"today_total"`
|
||||||
|
MtdTotal float64 `json:"mtd_total"`
|
||||||
|
TodayRawMaterial float64 `json:"today_raw_material"`
|
||||||
|
MtdRawMaterial float64 `json:"mtd_raw_material"`
|
||||||
|
TodayExpense float64 `json:"today_expense"`
|
||||||
|
MtdExpense float64 `json:"mtd_expense"`
|
||||||
|
Items []ProfitLossPurchasingItem `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProfitLossPurchasingItem struct {
|
||||||
|
Date time.Time `json:"date"`
|
||||||
|
Item string `json:"item"`
|
||||||
|
Quantity float64 `json:"quantity"`
|
||||||
|
Nominal float64 `json:"nominal"`
|
||||||
|
}
|
||||||
|
|
||||||
type ProfitLossSummary struct {
|
type ProfitLossSummary struct {
|
||||||
TotalRevenue float64 `json:"total_revenue"`
|
TotalRevenue float64 `json:"total_revenue"`
|
||||||
TotalCost float64 `json:"total_cost"`
|
TotalCost float64 `json:"total_cost"`
|
||||||
|
|||||||
@ -133,11 +133,25 @@ type ProfitLossAnalytics struct {
|
|||||||
TodayCost float64
|
TodayCost float64
|
||||||
MtdRevenue float64
|
MtdRevenue float64
|
||||||
MtdCost float64
|
MtdCost float64
|
||||||
|
TodayPurchasing float64
|
||||||
|
MtdPurchasing float64
|
||||||
|
TodayPurchasingRawMaterial float64
|
||||||
|
MtdPurchasingRawMaterial float64
|
||||||
|
TodayPurchasingExpense float64
|
||||||
|
MtdPurchasingExpense float64
|
||||||
|
PurchasingItems []PurchasingItemDetail
|
||||||
TodayExpenseByCategory []ExpenseCategoryTotal
|
TodayExpenseByCategory []ExpenseCategoryTotal
|
||||||
MtdExpenseByCategory []ExpenseCategoryTotal
|
MtdExpenseByCategory []ExpenseCategoryTotal
|
||||||
OperationalExpenseItems []OperationalExpenseItem
|
OperationalExpenseItems []OperationalExpenseItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PurchasingItemDetail struct {
|
||||||
|
Date time.Time
|
||||||
|
Item string
|
||||||
|
Quantity float64
|
||||||
|
Amount float64
|
||||||
|
}
|
||||||
|
|
||||||
type ProfitLossSummary struct {
|
type ProfitLossSummary struct {
|
||||||
TotalRevenue float64
|
TotalRevenue float64
|
||||||
TotalCost float64
|
TotalCost float64
|
||||||
|
|||||||
@ -282,10 +282,28 @@ type ProfitLossAnalyticsResponse struct {
|
|||||||
Data []ProfitLossData `json:"data"`
|
Data []ProfitLossData `json:"data"`
|
||||||
ProductData []ProductProfitData `json:"product_data"`
|
ProductData []ProductProfitData `json:"product_data"`
|
||||||
MainSummary []ProfitLossSummaryRow `json:"main_summary"`
|
MainSummary []ProfitLossSummaryRow `json:"main_summary"`
|
||||||
|
Purchasing ProfitLossPurchasing `json:"purchasing"`
|
||||||
OperationalExpenses []OperationalExpenseItem `json:"operational_expenses"`
|
OperationalExpenses []OperationalExpenseItem `json:"operational_expenses"`
|
||||||
OperationalExpensesTotal float64 `json:"operational_expenses_total"`
|
OperationalExpensesTotal float64 `json:"operational_expenses_total"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProfitLossPurchasing struct {
|
||||||
|
TodayTotal float64 `json:"today_total"`
|
||||||
|
MtdTotal float64 `json:"mtd_total"`
|
||||||
|
TodayRawMaterial float64 `json:"today_raw_material"`
|
||||||
|
MtdRawMaterial float64 `json:"mtd_raw_material"`
|
||||||
|
TodayExpense float64 `json:"today_expense"`
|
||||||
|
MtdExpense float64 `json:"mtd_expense"`
|
||||||
|
Items []ProfitLossPurchasingItem `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProfitLossPurchasingItem struct {
|
||||||
|
Date time.Time `json:"date"`
|
||||||
|
Item string `json:"item"`
|
||||||
|
Quantity float64 `json:"quantity"`
|
||||||
|
Nominal float64 `json:"nominal"`
|
||||||
|
}
|
||||||
|
|
||||||
type ProfitLossSummary struct {
|
type ProfitLossSummary struct {
|
||||||
TotalRevenue float64 `json:"total_revenue"`
|
TotalRevenue float64 `json:"total_revenue"`
|
||||||
TotalCost float64 `json:"total_cost"`
|
TotalCost float64 `json:"total_cost"`
|
||||||
|
|||||||
@ -626,6 +626,16 @@ func (p *AnalyticsProcessorImpl) GetProfitLossAnalytics(ctx context.Context, req
|
|||||||
opsTotal += item.Amount
|
opsTotal += item.Amount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
purchasingItems := make([]models.ProfitLossPurchasingItem, len(result.PurchasingItems))
|
||||||
|
for i, item := range result.PurchasingItems {
|
||||||
|
purchasingItems[i] = models.ProfitLossPurchasingItem{
|
||||||
|
Date: item.Date,
|
||||||
|
Item: item.Item,
|
||||||
|
Quantity: item.Quantity,
|
||||||
|
Nominal: item.Amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &models.ProfitLossAnalyticsResponse{
|
return &models.ProfitLossAnalyticsResponse{
|
||||||
OrganizationID: req.OrganizationID,
|
OrganizationID: req.OrganizationID,
|
||||||
OutletID: req.OutletID,
|
OutletID: req.OutletID,
|
||||||
@ -649,6 +659,15 @@ func (p *AnalyticsProcessorImpl) GetProfitLossAnalytics(ctx context.Context, req
|
|||||||
Data: data,
|
Data: data,
|
||||||
ProductData: productData,
|
ProductData: productData,
|
||||||
MainSummary: mainSummary,
|
MainSummary: mainSummary,
|
||||||
|
Purchasing: models.ProfitLossPurchasing{
|
||||||
|
TodayTotal: result.TodayPurchasing,
|
||||||
|
MtdTotal: result.MtdPurchasing,
|
||||||
|
TodayRawMaterial: result.TodayPurchasingRawMaterial,
|
||||||
|
MtdRawMaterial: result.MtdPurchasingRawMaterial,
|
||||||
|
TodayExpense: result.TodayPurchasingExpense,
|
||||||
|
MtdExpense: result.MtdPurchasingExpense,
|
||||||
|
Items: purchasingItems,
|
||||||
|
},
|
||||||
OperationalExpenses: opsItems,
|
OperationalExpenses: opsItems,
|
||||||
OperationalExpensesTotal: opsTotal,
|
OperationalExpensesTotal: opsTotal,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@ -68,6 +68,10 @@ func (s *analyticsRepositoryStub) GetExclusiveSummaryBankBalances(context.Contex
|
|||||||
return s.bankBalances, nil
|
return s.bankBalances, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (analyticsRepositoryStub) GetOutletName(context.Context, uuid.UUID, uuid.UUID) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
type expenseRepositoryStub struct{}
|
type expenseRepositoryStub struct{}
|
||||||
|
|
||||||
func (expenseRepositoryStub) Create(context.Context, *entities.Expense) error { return nil }
|
func (expenseRepositoryStub) Create(context.Context, *entities.Expense) error { return nil }
|
||||||
|
|||||||
@ -747,6 +747,20 @@ func (r *AnalyticsRepositoryImpl) GetProfitLossAnalytics(ctx context.Context, or
|
|||||||
}
|
}
|
||||||
opsItems = mergeOperationalExpenseItems(opsItems, poOpsItems)
|
opsItems = mergeOperationalExpenseItems(opsItems, poOpsItems)
|
||||||
|
|
||||||
|
todayPurchasing, err := r.getPurchaseOrderTotals(ctx, organizationID, todayStart, todayEnd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mtdPurchasing, err := r.getPurchaseOrderTotals(ctx, organizationID, mtdStart, todayEnd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
purchasingItems, err := r.getPurchasingItemDetails(ctx, organizationID, dateFrom, dateTo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &entities.ProfitLossAnalytics{
|
return &entities.ProfitLossAnalytics{
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
Data: data,
|
Data: data,
|
||||||
@ -755,6 +769,13 @@ func (r *AnalyticsRepositoryImpl) GetProfitLossAnalytics(ctx context.Context, or
|
|||||||
TodayCost: todayRC.Cost,
|
TodayCost: todayRC.Cost,
|
||||||
MtdRevenue: mtdRC.Revenue,
|
MtdRevenue: mtdRC.Revenue,
|
||||||
MtdCost: mtdRC.Cost,
|
MtdCost: mtdRC.Cost,
|
||||||
|
TodayPurchasing: todayPurchasing.Total,
|
||||||
|
MtdPurchasing: mtdPurchasing.Total,
|
||||||
|
TodayPurchasingRawMaterial: todayPurchasing.RawMaterial,
|
||||||
|
MtdPurchasingRawMaterial: mtdPurchasing.RawMaterial,
|
||||||
|
TodayPurchasingExpense: todayPurchasing.Expense,
|
||||||
|
MtdPurchasingExpense: mtdPurchasing.Expense,
|
||||||
|
PurchasingItems: purchasingItems,
|
||||||
TodayExpenseByCategory: todayExpenseByCategory,
|
TodayExpenseByCategory: todayExpenseByCategory,
|
||||||
MtdExpenseByCategory: mtdExpenseByCategory,
|
MtdExpenseByCategory: mtdExpenseByCategory,
|
||||||
OperationalExpenseItems: opsItems,
|
OperationalExpenseItems: opsItems,
|
||||||
@ -784,6 +805,68 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderRawMaterialTotal(ctx context.C
|
|||||||
return result.Total, nil
|
return result.Total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type purchasingTotals struct {
|
||||||
|
Total float64
|
||||||
|
RawMaterial float64
|
||||||
|
Expense float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *AnalyticsRepositoryImpl) getPurchaseOrderTotals(ctx context.Context, organizationID uuid.UUID, dateFrom, dateTo time.Time) (purchasingTotals, error) {
|
||||||
|
type result struct {
|
||||||
|
Total float64
|
||||||
|
RawMaterial float64
|
||||||
|
Expense float64
|
||||||
|
}
|
||||||
|
var res result
|
||||||
|
|
||||||
|
query := r.db.WithContext(ctx).
|
||||||
|
Table("purchase_order_items poi").
|
||||||
|
Select(`
|
||||||
|
COALESCE(SUM(`+purchaseOrderItemTotalAmountSQL()+`), 0) as total,
|
||||||
|
COALESCE(SUM(`+purchaseOrderRawMaterialAmountSQL()+`), 0) as raw_material,
|
||||||
|
COALESCE(SUM(`+purchaseOrderExpenseAmountSQL()+`), 0) as expense
|
||||||
|
`).
|
||||||
|
Joins("JOIN purchase_orders po ON poi.purchase_order_id = po.id").
|
||||||
|
Joins("JOIN purchase_categories pc ON poi.purchase_category_id = pc.id").
|
||||||
|
Where("po.organization_id = ?", organizationID).
|
||||||
|
Where("po.status = ?", "received").
|
||||||
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo)
|
||||||
|
|
||||||
|
if err := query.Scan(&res).Error; err != nil {
|
||||||
|
return purchasingTotals{}, err
|
||||||
|
}
|
||||||
|
return purchasingTotals{
|
||||||
|
Total: res.Total,
|
||||||
|
RawMaterial: res.RawMaterial,
|
||||||
|
Expense: res.Expense,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *AnalyticsRepositoryImpl) getPurchasingItemDetails(ctx context.Context, organizationID uuid.UUID, dateFrom, dateTo time.Time) ([]entities.PurchasingItemDetail, error) {
|
||||||
|
var results []entities.PurchasingItemDetail
|
||||||
|
|
||||||
|
query := r.db.WithContext(ctx).
|
||||||
|
Table("purchase_order_items poi").
|
||||||
|
Select(`
|
||||||
|
po.transaction_date as date,
|
||||||
|
COALESCE(NULLIF(poi.description, ''), i.name, pc.name) as item,
|
||||||
|
COALESCE(poi.quantity, 0) as quantity,
|
||||||
|
CASE WHEN pc.type = '`+string(entities.PurchaseCategoryTypeRawMaterial)+`' THEN COALESCE(poi.quantity, 0) * poi.amount ELSE poi.amount END as amount
|
||||||
|
`).
|
||||||
|
Joins("JOIN purchase_orders po ON poi.purchase_order_id = po.id").
|
||||||
|
Joins("LEFT JOIN purchase_categories pc ON poi.purchase_category_id = pc.id").
|
||||||
|
Joins("LEFT JOIN ingredients i ON poi.ingredient_id = i.id").
|
||||||
|
Where("po.organization_id = ?", organizationID).
|
||||||
|
Where("po.status = ?", "received").
|
||||||
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
||||||
|
Order("po.transaction_date DESC, poi.created_at DESC")
|
||||||
|
|
||||||
|
if err := query.Scan(&results).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *AnalyticsRepositoryImpl) getPurchaseOrderRawMaterialCostByPeriod(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, groupBy string) ([]entities.ProfitLossData, error) {
|
func (r *AnalyticsRepositoryImpl) getPurchaseOrderRawMaterialCostByPeriod(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, groupBy string) ([]entities.ProfitLossData, error) {
|
||||||
var dateFormat string
|
var dateFormat string
|
||||||
switch groupBy {
|
switch groupBy {
|
||||||
|
|||||||
@ -524,6 +524,16 @@ func ProfitLossAnalyticsModelToContract(resp *models.ProfitLossAnalyticsResponse
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
purchasingItems := make([]contract.ProfitLossPurchasingItem, len(resp.Purchasing.Items))
|
||||||
|
for i, item := range resp.Purchasing.Items {
|
||||||
|
purchasingItems[i] = contract.ProfitLossPurchasingItem{
|
||||||
|
Date: item.Date,
|
||||||
|
Item: item.Item,
|
||||||
|
Quantity: item.Quantity,
|
||||||
|
Nominal: item.Nominal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &contract.ProfitLossAnalyticsResponse{
|
return &contract.ProfitLossAnalyticsResponse{
|
||||||
OrganizationID: resp.OrganizationID,
|
OrganizationID: resp.OrganizationID,
|
||||||
OutletID: resp.OutletID,
|
OutletID: resp.OutletID,
|
||||||
@ -547,6 +557,15 @@ func ProfitLossAnalyticsModelToContract(resp *models.ProfitLossAnalyticsResponse
|
|||||||
Data: data,
|
Data: data,
|
||||||
ProductData: productData,
|
ProductData: productData,
|
||||||
MainSummary: mainSummary,
|
MainSummary: mainSummary,
|
||||||
|
Purchasing: contract.ProfitLossPurchasing{
|
||||||
|
TodayTotal: resp.Purchasing.TodayTotal,
|
||||||
|
MtdTotal: resp.Purchasing.MtdTotal,
|
||||||
|
TodayRawMaterial: resp.Purchasing.TodayRawMaterial,
|
||||||
|
MtdRawMaterial: resp.Purchasing.MtdRawMaterial,
|
||||||
|
TodayExpense: resp.Purchasing.TodayExpense,
|
||||||
|
MtdExpense: resp.Purchasing.MtdExpense,
|
||||||
|
Items: purchasingItems,
|
||||||
|
},
|
||||||
OperationalExpenses: opsItems,
|
OperationalExpenses: opsItems,
|
||||||
OperationalExpensesTotal: resp.OperationalExpensesTotal,
|
OperationalExpensesTotal: resp.OperationalExpensesTotal,
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user