b28bc23975
- Updated the `markResolvedRecommendedTenderSeen` function to accept an additional `tenderRef` parameter, allowing for better tracking of tender references and preventing duplicates. - Refactored the `GetByProcedureReferences` method in the repository to combine indexed notice lookups with contract-folder candidates, ensuring older notice references resolve correctly after tender merges. - Introduced a new `findTendersByContractFolderIDs` method to streamline the retrieval of tenders by contract folder IDs, enhancing performance and maintainability. - Added unit tests for new functionality in `ai_reference_test.go` and `recommendation_filter_test.go`, ensuring robust validation of tender reference mapping and deduplication logic. This update significantly improves the handling of tender references and enhances the overall test coverage, ensuring more reliable and efficient processing of tender data.
95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
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
|
|
}
|