better end points and better tests

This commit is contained in:
samantha42
2026-03-21 15:47:40 +01:00
parent 3f203178b2
commit 3490dd13d4
10 changed files with 482 additions and 34 deletions

View File

@@ -0,0 +1,82 @@
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
}