package tender import ( "context" "strings" "tm/internal/company" ) const recommendationResolveBatchSize = 100 type recommendationPageResult struct { items []rankedRecommendedTender total int64 } func (s *tenderService) buildRecommendationPage( ctx context.Context, recommendations []company.RecommendedTenderResponse, form *SearchForm, companyIDs []string, excluded map[string]struct{}, excludedByCompany map[string]map[string]struct{}, now int64, offset int, limit int, ) (recommendationPageResult, error) { seenTenderIDs := make(map[string]struct{}, len(recommendations)) pageStart := offset pageEnd := offset + limit if pageStart < 0 { pageStart = 0 } if pageEnd < pageStart { pageEnd = pageStart } result := recommendationPageResult{ items: make([]rankedRecommendedTender, 0, limit), } for start := 0; start < len(recommendations); start += recommendationResolveBatchSize { end := start + recommendationResolveBatchSize if end > len(recommendations) { end = len(recommendations) } tenderByRef, err := s.resolveRecommendedTenders(ctx, recommendations[start:end]) if err != nil { return recommendationPageResult{}, err } for _, rec := range recommendations[start:end] { tenderRef := strings.TrimSpace(rec.TenderID) tender, ok := tenderByRef[tenderRef] if !ok { continue } if len(companyIDs) > 0 { if isRecommendedTenderExcludedForAllCompanies(tender, tenderRef, excludedByCompany, companyIDs) { continue } } else if isRecommendedTenderExcluded(tender, tenderRef, excluded) { continue } if form.OnlyActiveDeadlines && !tender.IsRecommendable(now) { continue } if len(form.Status) > 0 && !statusAllowed(tender.Status, form.Status) { continue } if markResolvedRecommendedTenderSeen(seenTenderIDs, tender, tenderRef) { continue } result.total++ if int(result.total) <= pageStart || len(result.items) >= limit { continue } if int(result.total) > pageEnd { continue } result.items = append(result.items, rankedRecommendedTender{ tender: tender, rank: rec.Rank, analysis: rec.Analysis, tenderRef: tenderRef, }) } } return result, nil }