ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / internal/modules/opportunities/service.go

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / internal/modules/opportunities/service.go
DateNot specified in source
RepositoryJanady13/missionmatch
Revision2178e7298d0e5d9af83afa12402fd587f0ba6ed8
Branchfeature/aioe-upgrade
Path or archive memberinternal/modules/opportunities/service.go
Original SHA-256d7b831758369ec3b956ce70da382b9ce70f976ab14abff184cbcd6ccf3b1ecb2
Git blob SHAa363800facf085acc95cc136505da92507da4f88
Reading-copy SHA-256d7b831758369ec3b956ce70da382b9ce70f976ab14abff184cbcd6ccf3b1ecb2

Original source ↗

Recovered source transcript

package opportunities import ( "context" "encoding/json" "errors" "strings" "time" "github.com/missionworkforce/missionmatch/internal/platform/database/dbgen" "github.com/missionworkforce/missionmatch/internal/platform/tenant" ) // ErrNoDatabase is returned when no pool is configured. var ErrNoDatabase = errors.New("opportunities: no database configured") const ( defaultLimit = 100 maxLimit = 500 ) // Service reads the cached SAM opportunities catalog. type Service struct{ db *tenant.DB } // NewService builds the service. db may be nil (then every call returns ErrNoDatabase -> 503). func NewService(db *tenant.DB) *Service { return &Service{db: db} } // Filters are the optional read-API filters. Empty slices / empty Q mean "no filter". type Filters struct { NAICS []string SetAsides []string States []string Departments []string SubAgencies []string Q string ActiveOnly bool Limit int } // List returns cached opportunities matching the filters. It reads the global catalog directly off // the pool (no tenant tx, sam_opportunities is public and outside RLS). func (s *Service) List(ctx context.Context, f Filters) ([]Opportunity, error) { if !s.db.Ready() { return nil, ErrNoDatabase } limit := f.Limit if limit <= 0 { limit = defaultLimit } if limit > maxLimit { limit = maxLimit } var q *string if v := strings.TrimSpace(f.Q); v != "" { q = &v } // The text-equality filters match upper(column); upper-case the params so the comparison is // case-insensitive [review COR-3]. NAICS is a numeric code, left as-is. pool, release, perr := s.acquirePool(ctx) if perr != nil { return nil, perr } defer release() rows, err := dbgen.New(pool).ListSamOpportunities(ctx, dbgen.ListSamOpportunitiesParams{ Naics: nilIfEmpty(f.NAICS), SetAsides: upperAll(nilIfEmpty(f.SetAsides)), States: upperAll(nilIfEmpty(f.States)), Departments: upperAll(nilIfEmpty(f.Departments)), SubAgencies: upperAll(nilIfEmpty(f.SubAgencies)), Q: q, ActiveOnly: f.ActiveOnly, Lim: int32(limit), }) if err != nil { return nil, err } out := make([]Opportunity, 0, len(rows)) for _, r := range rows { out = append(out, toView(r)) } return out, nil } // Get returns one cached opportunity by notice id. A missing row surfaces pgx.ErrNoRows for the // handler to map to 404. func (s *Service) Get(ctx context.Context, noticeID string) (Opportunity, error) { if !s.db.Ready() { return Opportunity{}, ErrNoDatabase } pool, release, perr := s.acquirePool(ctx) if perr != nil { return Opportunity{}, perr } defer release() r, err := dbgen.New(pool).GetSamOpportunity(ctx, noticeID) if err != nil { return Opportunity{}, err } return toView(r), nil } func toView(r dbgen.SamOpportunity) Opportunity { posted := "" if r.PostedDate.Valid { posted = r.PostedDate.Time.Format("2006-01-02") } deadline := "" if r.ResponseDeadline != nil { deadline = r.ResponseDeadline.Format(time.RFC3339) } return Opportunity{ NoticeID: r.NoticeID, Title: r.Title, SolicitationNumber: r.SolicitationNumber, Department: r.Department, SubAgency: r.SubAgency, FullAgencyPath: r.FullParentPath, NaicsCode: r.NaicsCode, PscCode: r.PscCode, SetAsideCode: r.SetAsideCode, SetAside: r.SetAside, Type: r.NoticeType, PostedDate: posted, ResponseDeadline: deadline, Active: r.Active, PlaceOfPerformance: Place{City: r.PopCity, State: r.PopState, Zip: r.PopZip}, UILink: r.UiLink, DescriptionURL: r.DescriptionUrl, ResourceLinks: jsonOrEmpty(r.ResourceLinks), PointOfContact: jsonOrEmpty(r.Poc), Source: r.Source, SyncedAt: r.SyncedAt.Format(time.RFC3339), } } func jsonOrEmpty(b []byte) json.RawMessage { if len(b) == 0 { return json.RawMessage("[]") } return json.RawMessage(b) } func nilIfEmpty(s []string) []string { if len(s) == 0 { return nil } return s } func upperAll(s []string) []string { if s == nil { return nil } out := make([]string, len(s)) for i, v := range s { out[i] = strings.ToUpper(v) } return out }

Search equations, builds, manuscript text, and recovered sources.