package tender import ( "strings" "go.mongodb.org/mongo-driver/v2/bson" ) const aiProcedurePrefix = "PROC_" // FormatAIProcedureRef builds the AI service tender reference: // PROC_{contract_folder_id}/{notice_publication_id} func FormatAIProcedureRef(contractFolderID, noticePublicationID string) string { contractFolderID = strings.TrimSpace(contractFolderID) noticePublicationID = strings.TrimSpace(noticePublicationID) if contractFolderID == "" || noticePublicationID == "" { return "" } return aiProcedurePrefix + contractFolderID + "/" + noticePublicationID } // ProcedureReference identifies a tender using AI procedure coordinates. type ProcedureReference struct { Ref string ContractFolderID string NoticePublicationID string } // ParseAIProcedureRef parses PROC_{contract_folder_id}/{notice_publication_id}. func ParseAIProcedureRef(ref string) (contractFolderID, noticePublicationID string, ok bool) { ref = strings.TrimSpace(ref) if ref == "" { return "", "", false } withoutPrefix := ref if len(ref) >= len(aiProcedurePrefix) && strings.EqualFold(ref[:len(aiProcedurePrefix)], aiProcedurePrefix) { withoutPrefix = ref[len(aiProcedurePrefix):] } slash := strings.Index(withoutPrefix, "/") if slash <= 0 || slash >= len(withoutPrefix)-1 { return "", "", false } contractFolderID = strings.TrimSpace(withoutPrefix[:slash]) noticePublicationID = strings.TrimSpace(withoutPrefix[slash+1:]) if contractFolderID == "" || noticePublicationID == "" { return "", "", false } return contractFolderID, noticePublicationID, true } func tenderMatchesProcedureRef(t Tender, contractFolderID, noticePublicationID string) bool { if strings.TrimSpace(t.ContractFolderID) != strings.TrimSpace(contractFolderID) { return false } if t.NoticePublicationID == noticePublicationID { return true } for _, related := range t.RelatedNoticePublicationIDs { if related == noticePublicationID { return true } } return false } // IsMongoObjectIDRef reports whether ref is a 24-char hex MongoDB ObjectId. func IsMongoObjectIDRef(ref string) bool { ref = strings.TrimSpace(ref) if len(ref) != 24 { return false } _, err := bson.ObjectIDFromHex(ref) return err == nil }