Refactor TED Calendar and EForm Structure for Enhanced Functionality
- Updated the GetOJS function to accept a base URL parameter, improving flexibility in constructing the calendar URL. - Removed the deprecated eform.go file, streamlining the codebase by eliminating unused components. - Introduced new eform structures for BusinessRegistrationInformationNotice, ContractNotice, ContractAwardNotice, and PriorInformationNotice, enhancing the handling of TED XML data. - Implemented mapping functions to convert eform notices to the Tender entity, improving integration with the tender management system. - Added a service layer to encapsulate business logic related to eform processing, adhering to Clean Architecture principles.
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
package contract
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"time"
|
||||
"tm/internal/tender"
|
||||
"tm/ted/eform"
|
||||
)
|
||||
|
||||
// Notice represents the UBL ContractNotice structure used by TED
|
||||
type ContractNotice struct {
|
||||
XMLName xml.Name `xml:"ContractNotice"`
|
||||
UBLVersionID string `xml:"UBLVersionID"`
|
||||
CustomizationID string `xml:"CustomizationID"`
|
||||
ID string `xml:"ID"`
|
||||
ContractFolderID string `xml:"ContractFolderID"`
|
||||
IssueDate string `xml:"IssueDate"`
|
||||
IssueTime string `xml:"IssueTime"`
|
||||
VersionID string `xml:"VersionID"`
|
||||
RegulatoryDomain string `xml:"RegulatoryDomain"`
|
||||
NoticeTypeCode string `xml:"NoticeTypeCode"`
|
||||
NoticeLanguageCode string `xml:"NoticeLanguageCode"`
|
||||
UBLExtensions eform.UBLExtensions `xml:"UBLExtensions,omitempty"`
|
||||
ContractingParty eform.ContractingParty `xml:"ContractingParty"`
|
||||
TenderingTerms eform.TenderingTerms `xml:"TenderingTerms,omitempty"`
|
||||
TenderingProcess eform.TenderingProcess `xml:"TenderingProcess,omitempty"`
|
||||
ProcurementProject eform.ProcurementProject `xml:"ProcurementProject"`
|
||||
ProcurementProjectLot []eform.ProcurementProjectLot `xml:"ProcurementProjectLot,omitempty"`
|
||||
}
|
||||
|
||||
func (notice ContractNotice) MapToTender() *tender.Tender {
|
||||
now := time.Now().Unix()
|
||||
|
||||
t := &tender.Tender{
|
||||
ContractNoticeID: notice.ID,
|
||||
ContractFolderID: notice.ContractFolderID,
|
||||
NoticeTypeCode: notice.NoticeTypeCode,
|
||||
// NoticeSubTypeCode: notice.NoticeSubTypeCode,
|
||||
NoticeLanguageCode: notice.NoticeLanguageCode,
|
||||
// IssueDate: parseDateToUnixMilli(notice.IssueDate),
|
||||
// IssueTime: parseTimeToUnixMilli(notice.IssueTime),
|
||||
// GazetteID: notice.GetOJSID(),
|
||||
// Title: notice.GetProcurementTitle(),
|
||||
// Description: notice.GetProcurementDescription(),
|
||||
// ProcurementTypeCode: notice.GetContractNature(),
|
||||
// ProcedureCode: notice.GetProcedureCode(),
|
||||
// MainClassification: notice.GetMainClassification(),
|
||||
// PlaceOfPerformance: notice.GetPlaceOfPerformance(),
|
||||
// DocumentURI: notice.GetDocumentURI(),
|
||||
Status: tender.TenderStatusActive,
|
||||
Source: tender.TenderSourceTEDScraper,
|
||||
ProcessingMetadata: tender.ProcessingMetadata{
|
||||
ScrapedAt: now,
|
||||
ProcessedAt: now,
|
||||
ProcessingVersion: "1.0",
|
||||
},
|
||||
}
|
||||
|
||||
// Set publication information
|
||||
// if pubInfo := notice.GetPublicationInfo(); pubInfo != nil {
|
||||
// t.NoticePublicationID = pubInfo.NoticePublicationID
|
||||
// t.PublicationDate = s.parseDateToUnixMilli(pubInfo.PublicationDate)
|
||||
// t.TenderURL = s.generateTenderURL(pubInfo.NoticePublicationID)
|
||||
// }
|
||||
|
||||
// Set additional classifications
|
||||
// if notice.ProcurementProject != nil && notice.ProcurementProject.AdditionalCommodityClassification != nil {
|
||||
// for _, additionalClass := range notice.ProcurementProject.AdditionalCommodityClassification {
|
||||
// if additionalClass.ItemClassificationCode != "" {
|
||||
// t.AdditionalClassifications = append(t.AdditionalClassifications, additionalClass.ItemClassificationCode)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Set estimated value and currency
|
||||
// if amount, currency := notice.GetBudget(); amount != "" {
|
||||
// if value, err := strconv.ParseFloat(amount, 64); err == nil {
|
||||
// t.EstimatedValue = value
|
||||
// t.Currency = currency
|
||||
// }
|
||||
// }
|
||||
|
||||
// Set duration information
|
||||
// if duration, unit := notice.GetDuration(); duration != "" {
|
||||
// t.Duration = duration
|
||||
// t.DurationUnit = unit
|
||||
// }
|
||||
|
||||
// Set tender deadline
|
||||
// if deadline := notice.GetTenderDeadline(); deadline != "" {
|
||||
// t.TenderDeadline = parseDateToUnixMilli(deadline)
|
||||
|
||||
// if deadlineTime, err := parseDate(deadline); err == nil {
|
||||
// applicationDeadline := calculateApplicationDeadline(deadlineTime)
|
||||
// t.ApplicationDeadline = applicationDeadline.UnixMilli()
|
||||
// }
|
||||
// }
|
||||
|
||||
// if pubDate, err := parseDate(notice.GetPublicationDate()); err == nil {
|
||||
// submissionDeadline := calculateSubmissionDeadline(pubDate)
|
||||
// t.SubmissionDeadline = submissionDeadline.UnixMilli()
|
||||
// }
|
||||
|
||||
// Set SubmissionURL from TenderingTerms
|
||||
// if notice.ProcurementProjectLot != nil && notice.ProcurementProjectLot.TenderingTerms != nil {
|
||||
// if tenderingTerms := notice.ProcurementProjectLot.TenderingTerms; tenderingTerms.TenderRecipientParty != nil {
|
||||
// if endpointID := tenderingTerms.TenderRecipientParty.EndpointID; endpointID != "" {
|
||||
// if strings.HasPrefix(endpointID, "http") {
|
||||
// t.SubmissionURL = endpointID
|
||||
// } else {
|
||||
// t.SubmissionURL = "https://" + endpointID
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Set location information
|
||||
// if notice.ProcurementProject != nil && notice.ProcurementProject.RealizedLocation != nil {
|
||||
// if addr := notice.ProcurementProject.RealizedLocation.Address; addr != nil {
|
||||
// t.CityName = addr.CityName
|
||||
// t.PostalCode = addr.PostalZone
|
||||
// t.RegionCode = addr.CountrySubentityCode
|
||||
// if addr.Country != nil {
|
||||
// t.CountryCode = addr.Country.IdentificationCode
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Set buyer organization
|
||||
// buyerID := notice.GetBuyerID()
|
||||
// if buyerID != "" {
|
||||
// if buyerOrg := notice.GetOrganizationByID(buyerID); buyerOrg != nil {
|
||||
// t.BuyerOrganization = s.mapOrganization(buyerOrg, "buyer")
|
||||
// }
|
||||
// }
|
||||
|
||||
// Set review organization
|
||||
// reviewID := notice.GetReviewOrganizationID()
|
||||
// if reviewID != "" {
|
||||
// if reviewOrg := notice.GetOrganizationByID(reviewID); reviewOrg != nil {
|
||||
// t.ReviewOrganization = s.mapOrganization(reviewOrg, "review")
|
||||
// }
|
||||
// }
|
||||
|
||||
// Set all organizations
|
||||
// if orgs := notice.GetOrganizations(); orgs != nil {
|
||||
// for _, org := range orgs.Organization {
|
||||
// mappedOrg := s.mapOrganization(&org, "")
|
||||
// if mappedOrg != nil {
|
||||
// t.Organizations = append(t.Organizations, *mappedOrg)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Set selection criteria
|
||||
// if criteria := notice.GetSelectionCriteria(); criteria != nil {
|
||||
// for _, criterion := range criteria {
|
||||
// t.SelectionCriteria = append(t.SelectionCriteria, tender.SelectionCriterion{
|
||||
// TypeCode: criterion.CriterionTypeCode,
|
||||
// Description: criterion.Description,
|
||||
// LanguageID: criterion.LanguageID,
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// Set official languages
|
||||
// if languages := notice.GetOfficialLanguages(); languages != nil {
|
||||
// t.OfficialLanguages = languages
|
||||
// }
|
||||
|
||||
// Generate unique tender ID
|
||||
// t.TenderID = generateTenderID(t)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// GetID returns the contract notice ID
|
||||
func (cn ContractNotice) GetID() string {
|
||||
return cn.ID
|
||||
}
|
||||
|
||||
// Validate validates the parsed model
|
||||
func (cn ContractNotice) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMainBuyer returns the lead/main buyer organization
|
||||
func (n *ContractNotice) GetMainBuyer() *eform.Organization {
|
||||
if len(n.UBLExtensions.UBLExtension) > 0 {
|
||||
orgs := n.UBLExtensions.UBLExtension[0].ExtensionContent.EformsExtension.Organizations.Organization
|
||||
for i := range orgs {
|
||||
for _, role := range orgs[i].Roles {
|
||||
if role == eform.RoleBuyer || role == eform.RoleLeadBuyer {
|
||||
return &orgs[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOrganizationByID retrieves organization by ID
|
||||
func (n *ContractNotice) GetOrganizationByID(id string) *eform.Organization {
|
||||
if len(n.UBLExtensions.UBLExtension) > 0 {
|
||||
orgs := n.UBLExtensions.UBLExtension[0].ExtensionContent.EformsExtension.Organizations.Organization
|
||||
for i := range orgs {
|
||||
if orgs[i].ID == id {
|
||||
return &orgs[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user