package service import ( "context" "fmt" "Engine/internal/database" "Engine/internal/model" ) type ReportService struct { repo *database.ReportRepo } func NewReportService(repo *database.ReportRepo) *ReportService { return &ReportService{repo: repo} } type PnLFilter struct { FiscalYear int FiscalPeriod int DeptCode string Version model.BudgetVersion } func (s *ReportService) CreatePnL(ctx context.Context, f PnLFilter) (*model.PnLReport, error) { // fetch all five GL type buckets in parallel would be nicer, but keeping // it simple and sequential matches the rest of your codebase style. revenue, err := s.repo.GetGLRevenueActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode) if err != nil { return nil, fmt.Errorf("CreatePnL: revenue actuals: %w", err) } cogs, err := s.repo.GetGLCOGSActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode) if err != nil { return nil, fmt.Errorf("CreatePnL: cogs actuals: %w", err) } opex, err := s.repo.GetGLOpexActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode) if err != nil { return nil, fmt.Errorf("CreatePnL: opex actuals: %w", err) } headcount, err := s.repo.GetGLHeadcountActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode) if err != nil { return nil, fmt.Errorf("CreatePnL: headcount actuals: %w", err) } capex, err := s.repo.GetGLCapexActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode) if err != nil { return nil, fmt.Errorf("CreatePnL: capex actuals: %w", err) } report := &model.PnLReport{ Department: f.DeptCode, FiscalYear: f.FiscalYear, FiscalPeriod: f.FiscalPeriod, Version: f.Version, Currency: "DKK", Revenue: toSection(revenue), COGS: toSection(cogs), Opex: toSection(opex), Headcount: toSection(headcount), Capex: toSection(capex), } report.GrossProfit = report.Revenue.Total - report.COGS.Total report.EBIT = report.GrossProfit - report.Opex.Total - report.Headcount.Total report.NetIncome = report.EBIT - report.Capex.Total return report, nil } // toSection sums the rows and packages them into a PnLSection. func toSection(rows []model.GLAmountRow) model.PnLSection { s := model.PnLSection{Lines: rows} for _, r := range rows { s.Total += r.Amount } return s }