Find a Tender API client updates
- Convert OCDS releases to types.Opportunity (internal/types); FetchOnce and FetchAll now return opportunities, built from each ocid's latest release - Include each item's main classification as well as its additional ones - Return ErrUnexpectedStatus for non-200 responses and ErrRateLimitExceeded for a repeated 429; close discarded bodies - Stop fetchAll on a repeated next link and close each page's body once read rather than deferring in the loop - Default a zero Since to 24 hours ago - Merge date repair and releaseIDs into api.go - Filter --planning/--opportunities/--awards on each procedure's current stage, using OCDS release tags; --opportunities previously matched a nonexistent "opportunity" tag and returned nothing - Reject conflicting filters before fetching (cobra flag group)
This commit is contained in:
1 parent
69620e5f7d
commit
399eccf2de
8 files changed
+567
-86
No files matched your search
+31
-14
@@ -9,17 +9,41 @@ import (
|
||||
|
||||
"git.avsdev.uk/Go/job-search/internal/cli"
|
||||
"git.avsdev.uk/Go/job-search/internal/findATender"
|
||||
"git.avsdev.uk/Go/job-search/internal/findATender/ocds"
|
||||
"git.avsdev.uk/Go/job-search/internal/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func filter(reqs []ocds.Release, tag string) []ocds.Release {
|
||||
var resp []ocds.Release
|
||||
for _, req := range reqs {
|
||||
if slices.Contains(req.Tag, tag) {
|
||||
resp = append(resp, req)
|
||||
// Release tags for each stage of a procedure, from the OCDS releaseTag
|
||||
// codelist. Cancellations are left out, as a cancelled procedure is no longer
|
||||
// at any stage.
|
||||
var stageTags = map[string][]string{
|
||||
"planning": {"planning", "planningUpdate"},
|
||||
"opportunity": {"tender", "tenderAmendment", "tenderUpdate"},
|
||||
"award": {
|
||||
"award", "awardUpdate",
|
||||
"contract", "contractUpdate", "contractAmendment",
|
||||
"implementation", "implementationUpdate", "contractTermination",
|
||||
},
|
||||
}
|
||||
|
||||
// filter keeps the opportunities whose latest release is at stage. Releases
|
||||
// are oldest first, so the last one is the procedure's current stage.
|
||||
func filter(opps []*types.Opportunity, stage string) []*types.Opportunity {
|
||||
var resp []*types.Opportunity
|
||||
|
||||
for _, opp := range opps {
|
||||
if len(opp.Releases) == 0 {
|
||||
continue
|
||||
}
|
||||
latest := opp.Releases[len(opp.Releases)-1]
|
||||
for _, tag := range latest.Tags {
|
||||
if slices.Contains(stageTags[stage], tag.Tag) {
|
||||
resp = append(resp, opp)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
@@ -60,14 +84,6 @@ func commandOnce(opts *cli.Options) *cobra.Command {
|
||||
opportunities, _ := cmd.Flags().GetBool("opportunities")
|
||||
awards, _ := cmd.Flags().GetBool("awards")
|
||||
|
||||
if (planning && (opportunities || awards)) ||
|
||||
(opportunities && (planning || awards)) ||
|
||||
(awards && (planning || opportunities)) {
|
||||
return fmt.Errorf(
|
||||
"--planning, --opportunities and --awards are exclusive, only one can be provided",
|
||||
)
|
||||
}
|
||||
|
||||
filterTag := ""
|
||||
if planning {
|
||||
filterTag = "planning"
|
||||
@@ -112,5 +128,6 @@ func commandOnce(opts *cli.Options) *cobra.Command {
|
||||
cmd.Flags().Bool(
|
||||
"ignore-rate-limit", false, "ignore the rate limit and fail if exceeded",
|
||||
)
|
||||
cmd.MarkFlagsMutuallyExclusive("planning", "opportunities", "awards")
|
||||
return cmd
|
||||
}
|
||||
Reference in new issue
Block a user