package matching import ( "context" "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/missionworkforce/missionmatch/internal/platform/database/dbgen" ) // SupportView is one candidate who can support a mission today, read from the persisted screenMATCH // qualification (the stored artifact), never a rescore. It carries the frozen total and band so the // number matches what screenMATCH and slateMATCH show for the same candidate. type SupportView struct { CandidateID string `json:"candidate_id"` FullName string `json:"full_name"` Total string `json:"total_score"` Band string `json:"band"` BandLabel string `json:"band_label"` Available bool `json:"available"` EvaluatedAt string `json:"evaluated_at"` } // WhoCanSupport returns the candidates with a persisted screenMATCH qualification for one requirement, // best first (the missionMATCH "who can support this mission today" rollup). It READS the stored // candidate_evaluations rows; it never rescores the pool, so the rollup agrees with the screen and the // slate to the cent. An empty result means no one has been screened against the requirement yet. func (s *Service) WhoCanSupport(ctx context.Context, requirementID uuid.UUID) ([]SupportView, error) { if s.db == nil { return nil, ErrNoDatabase } var out []SupportView err := s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { rows, e := dbgen.New(tx).ListEvaluationsForRequirement(ctx, requirementID) if e != nil { return e } out = make([]SupportView, len(rows)) for i, r := range rows { out[i] = SupportView{ CandidateID: r.CandidateID.String(), FullName: r.FullName, Total: r.TotalScore.StringFixed(2), Band: r.Band, BandLabel: bandLabel(r.Band), Available: r.Available, EvaluatedAt: r.EvaluatedAt.Format("2006-01-02"), } } return nil }) return out, err }