Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/commandcenter/service.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | internal/modules/commandcenter/service.go |
| Original SHA-256 | fd24d283dcafa6857b4c53c7d4c509e6b422a55a6b72846ddce89a39b6540464 |
| Git blob SHA | dc791715c1d6a25ca073dcd3024e25cb342c73bf |
| Reading-copy SHA-256 | fd24d283dcafa6857b4c53c7d4c509e6b422a55a6b72846ddce89a39b6540464 |
Every recorded occurrence
These 2 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / internal/modules/commandcenter/service.go | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / internal/modules/commandcenter/service.go | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
Recovered source transcript
Download complete source text ↓353 lines · 13.1 KB
package commandcenter
import (
"context"
"errors"
"fmt"
"reflect"
"time"
"github.com/jackc/pgx/v5"
"github.com/shopspring/decimal"
"github.com/missionworkforce/missionmatch/internal/modules/matching/engine"
"github.com/missionworkforce/missionmatch/internal/platform/audit"
"github.com/missionworkforce/missionmatch/internal/platform/tenant"
)
// ErrNoDatabase is returned when no pool is configured.
var ErrNoDatabase = errors.New("commandcenter: no database configured")
// ErrForecastNotFound is returned when an adopt targets a record that does not exist, and
// ErrNotAForecast when it targets a record that is not a forecast (only forecasts are adoptable).
var (
ErrForecastNotFound = errors.New("commandcenter: forecast not found")
ErrNotAForecast = errors.New("commandcenter: record is not a forecast")
ErrBadRequest = errors.New("commandcenter: bad request")
)
var hundred = decimal.NewFromInt(100)
// WCC composite weights (DISTINCT from the engine's per-candidate weights). Sum == 1.00 (tested).
var weights = map[string]decimal.Decimal{
"clearance_coverage": decimal.RequireFromString("0.30"),
"skill_coverage": decimal.RequireFromString("0.25"),
"labor_category_coverage": decimal.RequireFromString("0.20"),
"proposal_readiness": decimal.RequireFromString("0.15"),
"availability_coverage": decimal.RequireFromString("0.10"),
}
var driverOrder = []struct{ key, label string }{
{"clearance_coverage", "Clearance Coverage"},
{"skill_coverage", "Skill Coverage"},
{"labor_category_coverage", "Labor Category Coverage"},
{"proposal_readiness", "Proposal Readiness"},
{"availability_coverage", "Availability Coverage"},
}
var levelLabels = map[string]string{
"unknown": "Unknown", "none": "None", "confidential": "Confidential",
"secret": "Secret", "top_secret": "Top Secret", "ts_sci": "TS/SCI",
}
// Service computes the Workforce Command Center view.
type Service struct {
db *tenant.DB
audit *audit.Writer // optional; used to record an adopt as requirement (a tenant record create)
clock func() time.Time
}
func NewService(db *tenant.DB) *Service { return &Service{db: db, clock: time.Now} }
// NewServiceWithAudit builds a Service that records the adopt as requirement action to the append only
// audit trail. The read only dashboard paths do not need the writer, so NewService stays valid.
func NewServiceWithAudit(db *tenant.DB, aud *audit.Writer) *Service {
return &Service{db: db, audit: aud, clock: time.Now}
}
func levelLabel(code string) string {
if l, ok := levelLabels[code]; ok {
return l
}
return code
}
func pct(num, den int64) decimal.Decimal {
if den <= 0 {
return decimal.Zero
}
return decimal.NewFromInt(num).Div(decimal.NewFromInt(den)).Mul(hundred).Round(2)
}
func driverState(p decimal.Decimal) string {
switch {
case p.GreaterThanOrEqual(engine.BandGreenMin):
return "ready"
case p.GreaterThanOrEqual(engine.BandYellowMin):
return "partial"
default:
return "gap"
}
}
func colorFor(p decimal.Decimal) string {
switch driverState(p) {
case "ready":
return "green"
case "partial":
return "yellow"
default:
return "red"
}
}
// CommandCenter computes the full dashboard for the caller's org as-of the given date.
func (s *Service) CommandCenter(ctx context.Context, asOf time.Time) (View, error) {
if s.db == nil {
return View{}, ErrNoDatabase
}
asOfStr := asOf.Format("2006-01-02")
v := View{AsOf: asOfStr, GeneratedAt: asOf.UTC().Format(time.RFC3339), Meta: Meta{Notes: []string{}}}
if org, ok := tenant.OrgFromContext(ctx); ok {
v.OrganizationID = org
}
var greenCoveredReqs, activeReqsForCards int64
err := s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error {
if err := buildTemps(ctx, tx, asOfStr); err != nil {
return err
}
// ---- opportunity metadata (RLS-scoped) ----
oppMeta := map[string]oppInfo{}
rows, err := tx.Query(ctx, `SELECT id::text, name, COALESCE(customer_agency,''), COALESCE(solicitation_number,''), COALESCE(to_char(due_date,'YYYY-MM-DD'),''), value, value_source FROM opportunities WHERE status='open'`)
if err != nil {
return fmt.Errorf("opp map: %w", err)
}
for rows.Next() {
var id, name, cust, sol, due, src string
var val *decimal.Decimal
if err := rows.Scan(&id, &name, &cust, &sol, &due, &val, &src); err != nil {
rows.Close()
return err
}
oppMeta[id] = oppInfo{name: name, customer: cust, solicitation: sol, dueDate: due, value: val, valueSource: src}
}
rows.Close()
if err := rows.Err(); err != nil {
return err
}
// ---- assignment-based panels (each available candidate consumed at most once) ----
assigned, qualified, reqs, _, err := fetchAssignment(ctx, tx)
if err != nil {
return err
}
opps, highRisk := opportunitiesFromAssignment(reqs, assigned, oppMeta)
v.ActiveOpportunities = opps
gaps, suggestReq, totalGaps := gapsFromAssignment(reqs, assigned, oppMeta)
v.StaffingGaps = gaps
v.LaborCategoryCoverage = lcatCoverageFromAssignment(reqs, assigned)
var proposalPct decimal.Decimal
v.ProposalReadiness, proposalPct = proposalFromAssignment(reqs, assigned, qualified, oppMeta)
// ---- drivers (clearance/skill/lcat coverage + availability via SQL; proposal from assignment) ----
drivers, availReqCov, err := s.drivers(ctx, tx)
if err != nil {
return err
}
drivers["proposal_readiness"] = proposalPct
var totalCleared, availableAll, availCleared int64
if err := tx.QueryRow(ctx,
`SELECT count(*) FILTER (WHERE effective AND lvl>=2), count(*) FILTER (WHERE available),
count(*) FILTER (WHERE available AND effective AND lvl>=2) FROM cc_cand`).
Scan(&totalCleared, &availableAll, &availCleared); err != nil {
return fmt.Errorf("banner cand: %w", err)
}
// Proposal-ready = green slate members on slates tied to an OPEN (or standalone) opportunity,
// excluding closed-opportunity slates [review EN-2].
var proposalReady, activeReqs int64
if err := tx.QueryRow(ctx,
`SELECT count(DISTINCT sm.candidate_id)
FROM slate_members sm
JOIN slates s ON s.id = sm.slate_id
JOIN requirements r ON r.id = s.requirement_id
LEFT JOIN opportunities o ON o.id = r.opportunity_id
WHERE sm.band='green' AND (o.id IS NULL OR o.status='open')`).Scan(&proposalReady); err != nil {
return fmt.Errorf("proposal ready: %w", err)
}
if err := tx.QueryRow(ctx, `SELECT count(*) FROM cc_active_req`).Scan(&activeReqs); err != nil {
return fmt.Errorf("active reqs: %w", err)
}
// ---- clearance intelligence ----
if v.ClearanceIntelligence, err = s.clearance(ctx, tx, asOfStr); err != nil {
return err
}
// ---- win impact ----
if v.WinImpact, err = s.winImpact(ctx, tx); err != nil {
return err
}
// ---- heat map ----
if v.HeatMap, err = s.heatMap(ctx, tx); err != nil {
return err
}
// ---- upcoming opportunities (forecasts; planning data, does NOT alter current readiness or RaR) ----
if v.UpcomingOpportunities, err = s.upcomingOpportunities(ctx, tx); err != nil {
return err
}
// ---- incumbent and award context (from the contract award feed) ----
if v.IncumbentLandscape, err = s.incumbentLandscape(ctx, tx); err != nil {
return err
}
// ---- action center badge counts ----
var openNoSlate, reqsUnscreened int64
if err := tx.QueryRow(ctx,
`SELECT count(*) FROM opportunities o WHERE o.status='open'
AND NOT EXISTS (SELECT 1 FROM slates s WHERE s.requirement_id IN (SELECT id FROM requirements r WHERE r.opportunity_id=o.id))`).
Scan(&openNoSlate); err != nil {
return fmt.Errorf("open no slate: %w", err)
}
if err := tx.QueryRow(ctx,
`SELECT count(*) FROM cc_active_req ar WHERE NOT EXISTS (SELECT 1 FROM slates s WHERE s.requirement_id=ar.id)`).
Scan(&reqsUnscreened); err != nil {
return fmt.Errorf("reqs unscreened: %w", err)
}
// ---- assemble mission readiness ----
score := decimal.Zero
drvViews := make([]Driver, 0, len(driverOrder))
for _, d := range driverOrder {
p := drivers[d.key]
score = score.Add(p.Mul(weights[d.key]))
drvViews = append(drvViews, Driver{
Key: d.key, Label: d.label, Pct: p.StringFixed(2), State: driverState(p),
Weight: weights[d.key].String(),
})
}
score = score.Round(2)
band, status := readinessBand(score, totalCleared == 0 && activeReqs == 0)
v.MissionReadiness = MissionReadiness{
Score: score.StringFixed(2), Band: band, Status: status, Drivers: drvViews,
AvailabilityReqCoverage: availReqCov.StringFixed(2), Flags: []string{},
}
v.Banner = Banner{
TotalClearedWorkforce: int(totalCleared), AvailableCandidates: int(availableAll),
ProposalReadyCandidates: int(proposalReady), ActiveRequirements: int(activeReqs),
StaffingGaps: int(totalGaps), HighRiskOpportunities: highRisk,
}
v.ActionCenter = buildActionCenter(suggestReq, opps, int(openNoSlate), int(reqsUnscreened))
v.Meta.Empty = totalCleared == 0 && activeReqs == 0 && availableAll == 0
// ---- executive cards: staffing confidence feed (stored proposal ready screens per active req) ----
if err := tx.QueryRow(ctx, `
SELECT count(DISTINCT ce.requirement_id) FROM candidate_evaluations ce
JOIN cc_active_req ar ON ar.id = ce.requirement_id
WHERE ce.band = 'green'`).Scan(&greenCoveredReqs); err != nil {
return fmt.Errorf("green covered reqs: %w", err)
}
activeReqsForCards = activeReqs
return nil
})
if err != nil {
return View{}, err
}
v.AIRecommendations = buildRecommendations(v)
v.ExecutiveCards = buildExecutiveCards(v, greenCoveredReqs, activeReqsForCards)
// Every list field is emitted as a LIST, never null.
//
// Go marshals a nil slice to JSON `null`, and none of these fields carry omitempty, so an organization
// with no opportunities produced {"active_opportunities": null}. The client maps straight over them,
// so `null.map` threw during render and took the whole page down: a brand new tenant, or any tenant on
// a quiet day, could not open the Command Center at all. Only two of the eight fields had been given
// this treatment, one at the call site above and one nowhere.
//
// Fixed at the source rather than with a `?? []` on each of the seven client dereferences, because the
// contract belongs to the API: a field typed as a list should always be a list, for every consumer,
// including ones written later that will not know to defend against it.
normalizeLists(&v)
return v, nil
}
// normalizeLists replaces every nil slice anywhere in the view with an empty one.
//
// It walks the struct by reflection rather than checking the eight top level fields by hand, because the
// hand written version was already wrong when it was written: the nulls are not only at the top level.
// meta.notes, mission_readiness.drivers and flags, clearance_intelligence.inventory_by_level, the four
// proposal_readiness lists, win_impact.top and action_center.launch are all nested a level or two down,
// and several of them are mapped over by the client exactly like the top level ones. Enumerating them by
// hand means the next nested list added anywhere in this tree is a blank screen waiting for the first
// tenant that has none of it.
//
// This runs once per Command Center request over a small fixed struct, so the reflection cost is
// irrelevant next to the queries that built it.
func normalizeLists(v *View) { normalizeValue(reflect.ValueOf(v).Elem()) }
// normalizeValue recurses through structs, slices, pointers and maps, setting any nil slice it finds to
// an empty slice of the same type.
func normalizeValue(rv reflect.Value) {
switch rv.Kind() {
case reflect.Struct:
for i := 0; i < rv.NumField(); i++ {
f := rv.Field(i)
if f.CanSet() {
normalizeValue(f)
}
}
case reflect.Slice:
if rv.IsNil() {
rv.Set(reflect.MakeSlice(rv.Type(), 0, 0))
return // an empty slice has no elements to recurse into
}
for i := 0; i < rv.Len(); i++ {
normalizeValue(rv.Index(i))
}
case reflect.Ptr:
// A nil pointer stays nil: it means "absent", which is a real and different answer from an empty
// list, and the client's optional field handling depends on the distinction.
if !rv.IsNil() {
normalizeValue(rv.Elem())
}
case reflect.Map:
// Map values are not addressable, so each is normalized on a copy and written back.
for _, k := range rv.MapKeys() {
ev := reflect.New(rv.Type().Elem()).Elem()
ev.Set(rv.MapIndex(k))
normalizeValue(ev)
rv.SetMapIndex(k, ev)
}
}
}
type oppInfo struct {
name string
customer string
solicitation string
dueDate string
value *decimal.Decimal
valueSource string // representative, operator, sam, usaspending (W2 Revenue at Risk provenance)
}
// isRealValueSource reports whether an opportunity value came from a cached federal source (SAM or
// USASpending). A representative or operator entered dollar is not a real federal figure, so it can
// never clear the representative label on Revenue at Risk.
func isRealValueSource(s string) bool { return s == "sam" || s == "usaspending" }
func readinessBand(score decimal.Decimal, empty bool) (band, status string) {
if empty {
return "red", "No Data"
}
switch {
case score.GreaterThanOrEqual(engine.BandGreenMin):
return "green", "Mission Ready"
case score.GreaterThanOrEqual(engine.BandYellowMin):
return "yellow", "Watch"
default:
return "red", "At Risk"
}
}