Add GetScrapePortals endpoint and related service functionality
continuous-integration/drone/push Build is passing

- Introduced the GetScrapePortals method in the AI pipeline handler to list document scraping portals supported by the Opplens AI service.
- Updated the service layer to include GetScrapePortals, which retrieves the portals from the client and handles errors appropriately.
- Enhanced the routes to register the new endpoint for retrieving scrape portals.
- Added a new error type for invalid date ranges in the document scraper, improving validation and error handling.

This update expands the AI pipeline capabilities, allowing for better management of document scraping portals within the tender management system.
This commit is contained in:
Mazyar
2026-06-18 19:53:07 +03:30
parent 2f19ecae55
commit e5fa0dfe47
10 changed files with 192 additions and 53 deletions
+44 -17
View File
@@ -31,7 +31,7 @@ type TenderRepository interface {
GetTenderCountByClassification(ctx context.Context) (map[string]int64, error)
Search(ctx context.Context, form *SearchForm, pagination *response.Pagination) (*SearchPageResult, error)
GetExpiredTenders(ctx context.Context, beforeDate int64) ([]Tender, error)
GetPendingDocumentScrapeTenders(ctx context.Context, countryCodes []string, minDeadline int64, limit, skip int) ([]Tender, bool, error)
GetPendingDocumentScrapeTenders(ctx context.Context, filter PendingDocumentScrapeFilter) ([]Tender, bool, error)
GetUnSummarizedTenders(ctx context.Context, limit, skip int) ([]Tender, int64, error)
GetUnTranslatedTenders(ctx context.Context, language string, limit, skip int) ([]Tender, int64, error)
Update(ctx context.Context, tender *Tender) error
@@ -555,37 +555,64 @@ func (r *tenderRepository) GetExpiredTenders(ctx context.Context, beforeDate int
return result.Items, nil
}
// GetPendingDocumentScrapeTenders returns unscraped tenders for the given countries with an active deadline.
func (r *tenderRepository) GetPendingDocumentScrapeTenders(ctx context.Context, countryCodes []string, minDeadline int64, limit, skip int) ([]Tender, bool, error) {
if len(countryCodes) == 0 {
// PendingDocumentScrapeFilter defines query criteria for pending document scrape tenders.
type PendingDocumentScrapeFilter struct {
CountryCodes []string
MinDeadline *int64 // when set, tender_deadline must be greater than this value
CreatedAtFrom *int64
CreatedAtTo *int64
Limit int
Skip int
}
// GetPendingDocumentScrapeTenders returns unscraped tenders for the given countries.
// When MinDeadline is set, only tenders with tender_deadline greater than that value are returned.
func (r *tenderRepository) GetPendingDocumentScrapeTenders(ctx context.Context, filter PendingDocumentScrapeFilter) ([]Tender, bool, error) {
if len(filter.CountryCodes) == 0 {
return nil, false, nil
}
filter := bson.M{
"country_code": bson.M{"$in": countryCodes},
"tender_deadline": bson.M{
"$gt": minDeadline,
},
query := bson.M{
"country_code": bson.M{"$in": filter.CountryCodes},
"processing_metadata.documents_scraped": bson.M{"$ne": true},
}
if filter.MinDeadline != nil {
query["tender_deadline"] = bson.M{
"$gt": *filter.MinDeadline,
}
}
if filter.CreatedAtFrom != nil || filter.CreatedAtTo != nil {
createdFilter := bson.M{}
if filter.CreatedAtFrom != nil {
createdFilter["$gte"] = *filter.CreatedAtFrom
}
if filter.CreatedAtTo != nil {
createdFilter["$lte"] = *filter.CreatedAtTo
}
query["created_at"] = createdFilter
}
pagination := orm.Pagination{
Limit: limit,
Skip: skip,
Limit: filter.Limit,
Skip: filter.Skip,
SortField: "created_at",
SortOrder: 1,
SkipCount: true,
Projection: documentScraperListProjection(),
}
result, err := r.ormRepo.FindAll(ctx, filter, pagination)
result, err := r.ormRepo.FindAll(ctx, query, pagination)
if err != nil {
r.logger.Error("Failed to get pending document scrape tenders", map[string]interface{}{
"country_codes": countryCodes,
"min_deadline": minDeadline,
"limit": limit,
"skip": skip,
"error": err.Error(),
"country_codes": filter.CountryCodes,
"min_deadline": filter.MinDeadline,
"created_at_from": filter.CreatedAtFrom,
"created_at_to": filter.CreatedAtTo,
"limit": filter.Limit,
"skip": filter.Skip,
"error": err.Error(),
})
return nil, false, err
}