From 4390d7e1a65421d06391307e225acb320945df12 Mon Sep 17 00:00:00 2001 From: Mazyar Date: Wed, 20 May 2026 16:03:30 +0330 Subject: [PATCH] tenders document filter --- internal/tender/form.go | 1 + internal/tender/handler.go | 3 +++ internal/tender/repository.go | 17 +++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/internal/tender/form.go b/internal/tender/form.go index 49765bb..4a2bfaa 100644 --- a/internal/tender/form.go +++ b/internal/tender/form.go @@ -61,6 +61,7 @@ type SearchForm struct { Languages []string `query:"languages" valid:"optional"` OnlyActiveDeadlines bool `query:"-" valid:"optional"` Language *string `query:"lang" valid:"optional"` + DocumentsScraped bool `query:"documents_scraped" valid:"optional"` } // SearchResponse represents the response for listing tenders diff --git a/internal/tender/handler.go b/internal/tender/handler.go index 353e6fd..81c643e 100644 --- a/internal/tender/handler.go +++ b/internal/tender/handler.go @@ -158,6 +158,7 @@ func (h *TenderHandler) Delete(c echo.Context) error { // @Param submission_date_to query number false "Submission deadline to (Unix timestamp, seconds)" // @Param languages query []string false "Filter by languages (comma-separated)" // @Param buyer_organization_id query string false "Filter by buyer organization ID" +// @Param documents_scraped query bool false "When true, only tenders with scraped documents" // @Param limit query int false "Number of items per page (default: 20, max: 100)" // @Param offset query int false "Number of items to skip (default: 0). Prefer cursor for deep pages." // @Param cursor query string false "Opaque cursor from previous page meta.next_cursor" @@ -228,6 +229,7 @@ func (h *TenderHandler) Search(c echo.Context) error { // @Param submission_date_to query number false "Submission deadline to (Unix seconds)" // @Param languages query []string false "Filter by languages (comma-separated)" // @Param buyer_organization_id query string false "Filter by buyer organization ID" +// @Param documents_scraped query bool false "When true, only tenders with scraped documents" // @Param limit query int false "Number of items per page (default: 20, max: 100)" // @Param offset query int false "Number of items to skip (default: 0). Prefer cursor for deep pages." // @Param cursor query string false "Opaque cursor from previous page meta.next_cursor" @@ -310,6 +312,7 @@ func (h *TenderHandler) GetPublicTenders(c echo.Context) error { // @Param submission_date_to query number false "Submission deadline to (Unix seconds)" // @Param languages query []string false "Filter by languages (comma-separated)" // @Param buyer_organization_id query string false "Filter by buyer organization ID" +// @Param documents_scraped query bool false "When true, only tenders with scraped documents" // @Param limit query int false "Number of items per page (default: 20, max: 100)" // @Param offset query int false "Number of items to skip (default: 0). Prefer cursor for deep pages." // @Param cursor query string false "Opaque cursor from previous page meta.next_cursor" diff --git a/internal/tender/repository.go b/internal/tender/repository.go index ed9561e..bb5f441 100644 --- a/internal/tender/repository.go +++ b/internal/tender/repository.go @@ -1058,5 +1058,22 @@ func (r *tenderRepository) buildSearchFilter(form *SearchForm) bson.M { filter["notice_language_code"] = bson.M{"$in": dedupeNonEmptyStrings(form.Languages)} } + if form.DocumentsScraped { + scrapedClause := bson.M{ + "$or": []bson.M{ + {"processing_metadata.documents_scraped": true}, + {"scraped_documents.0": bson.M{"$exists": true}}, + }, + } + if len(filter) == 0 { + return scrapedClause + } + if and, ok := filter["$and"].([]bson.M); ok { + filter["$and"] = append(and, scrapedClause) + } else { + filter["$and"] = []bson.M{filter, scrapedClause} + } + } + return filter }