Add unit test for mapping procedure references to tenders
continuous-integration/drone/push Build is passing

- Introduced a new test function `TestMapProcedureReferencesToTenders` to validate the mapping of procedure references to corresponding tenders.
- Enhanced the `GetByProcedureReferences` method in the tender repository to utilize a more efficient filtering mechanism based on unique contract folder IDs.
- Updated pagination logic to dynamically adjust limits based on the number of unique folders and references, ensuring optimal data retrieval.

This update improves the testing coverage for tender mapping functionality and optimizes the repository's data fetching strategy, enhancing overall performance and reliability.
This commit is contained in:
Mazyar
2026-07-04 13:39:14 +03:30
parent 467090e5d2
commit 4c48e0bb3b
3 changed files with 109 additions and 42 deletions
+29 -22
View File
@@ -65,11 +65,11 @@ func tenderSearchListProjection() bson.M {
"source_file_url": 0,
"source_file_name": 0,
// Not used by list response mapping; can be large per tender.
"translations": 0,
"organizations": 0,
"review_organization": 0,
"processing_metadata.translated_data": 0,
"processing_metadata.parsing_errors": 0,
"translations": 0,
"organizations": 0,
"review_organization": 0,
"processing_metadata.translated_data": 0,
"processing_metadata.parsing_errors": 0,
"processing_metadata.validation_errors": 0,
}
}
@@ -350,28 +350,31 @@ func (r *tenderRepository) GetByProcedureReferences(ctx context.Context, refs []
return out, nil
}
orClauses := make([]bson.M, 0, len(refs))
contractFolderIDs := make([]string, 0, len(refs))
for _, ref := range refs {
folder := strings.TrimSpace(ref.ContractFolderID)
notice := strings.TrimSpace(ref.NoticePublicationID)
if folder == "" || notice == "" {
continue
}
orClauses = append(orClauses, bson.M{
"contract_folder_id": folder,
"$or": []bson.M{
{"notice_publication_id": notice},
{"related_notice_publication_ids": notice},
},
})
contractFolderIDs = append(contractFolderIDs, folder)
}
if len(orClauses) == 0 {
uniqueFolders := uniqueNonEmptyTrimmedStrings(contractFolderIDs)
if len(uniqueFolders) == 0 {
return out, nil
}
filter := bson.M{"$or": orClauses}
findLimit := len(uniqueFolders) * 5
if minLimit := len(refs) + len(uniqueFolders); findLimit < minLimit {
findLimit = minLimit
}
if findLimit > 100000 {
findLimit = 100000
}
filter := bson.M{"contract_folder_id": bson.M{"$in": uniqueFolders}}
pagination := orm.Pagination{
Limit: len(orClauses) * 2,
Limit: findLimit,
SortField: "updated_at",
SortOrder: -1,
}
@@ -379,22 +382,26 @@ func (r *tenderRepository) GetByProcedureReferences(ctx context.Context, refs []
result, err := r.ormRepo.FindAll(ctx, filter, pagination)
if err != nil {
r.logger.Error("Failed to get tenders by procedure references", map[string]interface{}{
"count": len(orClauses),
"count": len(uniqueFolders),
"error": err.Error(),
})
return nil, err
}
return mapProcedureReferencesToTenders(result.Items, refs), nil
}
func mapProcedureReferencesToTenders(candidates []Tender, refs []ProcedureReference) map[string]Tender {
out := make(map[string]Tender)
for _, ref := range refs {
for i := range result.Items {
if tenderMatchesProcedureRef(result.Items[i], ref.ContractFolderID, ref.NoticePublicationID) {
out[ref.Ref] = result.Items[i]
for i := range candidates {
if tenderMatchesProcedureRef(candidates[i], ref.ContractFolderID, ref.NoticePublicationID) {
out[ref.Ref] = candidates[i]
break
}
}
}
return out, nil
return out
}
// GetByContractFolderID retrieves a tender by its procedure-level identifier (ContractFolderID).