f57e53bd9b
- Added new fields to the Tender entity for handling cancellation, award, and suspension details, improving the entity's capability to manage tender statuses. - Implemented a DetectNoticeStatus method in the TEDParser to identify the status of TED notices from XML data, enhancing the parser's functionality. - Updated the ParseXML method to include notice status detection, ensuring accurate status representation in parsed documents. - Introduced upsert logic in the TED scraper to handle tender records more effectively, allowing for updates or creation based on existing ContractIDs. - Enhanced logging and error handling throughout the scraping process to improve traceability and robustness. - Added a comprehensive usage example document to illustrate the new features and usage patterns for the TED XML parser and scraper.
2242 lines
96 KiB
Go
2242 lines
96 KiB
Go
package ted
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// DocumentType represents the type of TED document
|
|
type DocumentType string
|
|
|
|
// Document type constants for all supported TED XML notice types
|
|
const (
|
|
DocumentTypeContractNotice DocumentType = "ContractNotice"
|
|
DocumentTypeContractAwardNotice DocumentType = "ContractAwardNotice"
|
|
DocumentTypePriorInformationNotice DocumentType = "PriorInformationNotice"
|
|
DocumentTypeDesignContest DocumentType = "DesignContest"
|
|
DocumentTypeCorrigendum DocumentType = "Corrigendum"
|
|
DocumentTypeModificationNotice DocumentType = "ModificationNotice"
|
|
DocumentTypeConcessionNotice DocumentType = "ConcessionNotice"
|
|
DocumentTypeQualificationSystemNotice DocumentType = "QualificationSystemNotice"
|
|
DocumentTypePlanningNotice DocumentType = "PlanningNotice"
|
|
DocumentTypeCompetitionNotice DocumentType = "CompetitionNotice"
|
|
DocumentTypeResultNotice DocumentType = "ResultNotice"
|
|
DocumentTypeChangeNotice DocumentType = "ChangeNotice"
|
|
DocumentTypeVoluntaryExAnte DocumentType = "VoluntaryExAnte"
|
|
DocumentTypeSubcontractNotice DocumentType = "SubcontractNotice"
|
|
)
|
|
|
|
// NoticeStatus represents the status of a TED notice
|
|
type NoticeStatus string
|
|
|
|
// Notice status constants for all possible TED notice statuses
|
|
const (
|
|
NoticeStatusDraft NoticeStatus = "Draft"
|
|
NoticeStatusPublished NoticeStatus = "Published"
|
|
NoticeStatusCancelled NoticeStatus = "Cancelled"
|
|
NoticeStatusAwarded NoticeStatus = "Awarded"
|
|
NoticeStatusClosed NoticeStatus = "Closed"
|
|
NoticeStatusModified NoticeStatus = "Modified"
|
|
NoticeStatusSuspended NoticeStatus = "Suspended"
|
|
)
|
|
|
|
// ParsedDocument wraps any TED document with type information
|
|
type ParsedDocument struct {
|
|
Type DocumentType `json:"type"`
|
|
Status NoticeStatus `json:"status"`
|
|
ContractNotice *ContractNotice `json:"contract_notice,omitempty"`
|
|
ContractAwardNotice *ContractAwardNotice `json:"contract_award_notice,omitempty"`
|
|
PriorInformationNotice *PriorInformationNotice `json:"prior_information_notice,omitempty"`
|
|
DesignContest *DesignContest `json:"design_contest,omitempty"`
|
|
QualificationSystemNotice *QualificationSystemNotice `json:"qualification_system_notice,omitempty"`
|
|
ConcessionNotice *ConcessionNotice `json:"concession_notice,omitempty"`
|
|
PlanningNotice *PlanningNotice `json:"planning_notice,omitempty"`
|
|
CompetitionNotice *CompetitionNotice `json:"competition_notice,omitempty"`
|
|
ResultNotice *ResultNotice `json:"result_notice,omitempty"`
|
|
ChangeNotice *ChangeNotice `json:"change_notice,omitempty"`
|
|
SubcontractNotice *SubcontractNotice `json:"subcontract_notice,omitempty"`
|
|
}
|
|
|
|
// GetDocument returns the underlying document interface
|
|
func (pd *ParsedDocument) GetDocument() TEDDocument {
|
|
switch pd.Type {
|
|
case DocumentTypeContractNotice:
|
|
return pd.ContractNotice
|
|
case DocumentTypeContractAwardNotice:
|
|
return pd.ContractAwardNotice
|
|
case DocumentTypePriorInformationNotice:
|
|
return pd.PriorInformationNotice
|
|
case DocumentTypeDesignContest:
|
|
return pd.DesignContest
|
|
case DocumentTypeQualificationSystemNotice:
|
|
return pd.QualificationSystemNotice
|
|
case DocumentTypeConcessionNotice:
|
|
return pd.ConcessionNotice
|
|
case DocumentTypePlanningNotice:
|
|
return pd.PlanningNotice
|
|
case DocumentTypeCompetitionNotice:
|
|
return pd.CompetitionNotice
|
|
case DocumentTypeResultNotice:
|
|
return pd.ResultNotice
|
|
case DocumentTypeChangeNotice:
|
|
return pd.ChangeNotice
|
|
case DocumentTypeSubcontractNotice:
|
|
return pd.SubcontractNotice
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// TEDDocument represents the common interface for all TED document types
|
|
type TEDDocument interface {
|
|
GetID() string
|
|
GetNoticeType() string
|
|
GetLanguage() string
|
|
GetNoticeStatus() NoticeStatus
|
|
Validate() error
|
|
}
|
|
|
|
// PriorInformationNotice represents a prior information notice
|
|
type PriorInformationNotice struct {
|
|
XMLName xml.Name `xml:"PriorInformationNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
ProcurementProjectLot []ProcurementProjectLot `xml:"ProcurementProjectLot,omitempty"`
|
|
AdditionalDocumentReference []AdditionalDocumentReference `xml:"AdditionalDocumentReference,omitempty"`
|
|
}
|
|
|
|
// Interface methods for PriorInformationNotice
|
|
func (pin PriorInformationNotice) GetID() string {
|
|
return pin.ID
|
|
}
|
|
|
|
func (pin PriorInformationNotice) GetNoticeType() string {
|
|
return pin.NoticeTypeCode
|
|
}
|
|
|
|
func (pin PriorInformationNotice) GetLanguage() string {
|
|
return pin.NoticeLanguageCode
|
|
}
|
|
|
|
func (pin PriorInformationNotice) GetNoticeStatus() NoticeStatus {
|
|
// Prior information notices are typically published
|
|
return NoticeStatusPublished
|
|
}
|
|
|
|
func (pin PriorInformationNotice) Validate() error {
|
|
if pin.ID == "" {
|
|
return fmt.Errorf("prior information notice ID is required")
|
|
}
|
|
if pin.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DesignContest represents a design contest notice
|
|
type DesignContest struct {
|
|
XMLName xml.Name `xml:"DesignContest"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
ContestDesignJury *ContestDesignJury `xml:"ContestDesignJury,omitempty"`
|
|
ContestDesignReward []ContestDesignReward `xml:"ContestDesignReward,omitempty"`
|
|
}
|
|
|
|
// Interface methods for DesignContest
|
|
func (dc DesignContest) GetID() string { return dc.ID }
|
|
func (dc DesignContest) GetNoticeType() string { return dc.NoticeTypeCode }
|
|
func (dc DesignContest) GetLanguage() string { return dc.NoticeLanguageCode }
|
|
func (dc DesignContest) GetNoticeStatus() NoticeStatus { return NoticeStatusPublished }
|
|
func (dc DesignContest) Validate() error {
|
|
if dc.ID == "" {
|
|
return fmt.Errorf("design contest ID is required")
|
|
}
|
|
if dc.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// QualificationSystemNotice represents a qualification system notice
|
|
type QualificationSystemNotice struct {
|
|
XMLName xml.Name `xml:"QualificationSystemNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
QualificationApplication []QualificationApplication `xml:"QualificationApplication,omitempty"`
|
|
}
|
|
|
|
// Interface methods for QualificationSystemNotice
|
|
func (qsn QualificationSystemNotice) GetID() string { return qsn.ID }
|
|
func (qsn QualificationSystemNotice) GetNoticeType() string { return qsn.NoticeTypeCode }
|
|
func (qsn QualificationSystemNotice) GetLanguage() string { return qsn.NoticeLanguageCode }
|
|
func (qsn QualificationSystemNotice) GetNoticeStatus() NoticeStatus { return NoticeStatusPublished }
|
|
func (qsn QualificationSystemNotice) Validate() error {
|
|
if qsn.ID == "" {
|
|
return fmt.Errorf("qualification system notice ID is required")
|
|
}
|
|
if qsn.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ConcessionNotice represents a concession notice
|
|
type ConcessionNotice struct {
|
|
XMLName xml.Name `xml:"ConcessionNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
ProcurementProjectLot []ProcurementProjectLot `xml:"ProcurementProjectLot,omitempty"`
|
|
ConcessionRevenue *ConcessionRevenue `xml:"ConcessionRevenue,omitempty"`
|
|
ConcessionTerm *ConcessionTerm `xml:"ConcessionTerm,omitempty"`
|
|
}
|
|
|
|
// Interface methods for ConcessionNotice
|
|
func (cn ConcessionNotice) GetID() string { return cn.ID }
|
|
func (cn ConcessionNotice) GetNoticeType() string { return cn.NoticeTypeCode }
|
|
func (cn ConcessionNotice) GetLanguage() string { return cn.NoticeLanguageCode }
|
|
func (cn ConcessionNotice) GetNoticeStatus() NoticeStatus { return NoticeStatusPublished }
|
|
func (cn ConcessionNotice) Validate() error {
|
|
if cn.ID == "" {
|
|
return fmt.Errorf("concession notice ID is required")
|
|
}
|
|
if cn.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PlanningNotice represents a planning notice
|
|
type PlanningNotice struct {
|
|
XMLName xml.Name `xml:"PlanningNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
ProcurementProjectLot []ProcurementProjectLot `xml:"ProcurementProjectLot,omitempty"`
|
|
BudgetAccountLine []BudgetAccountLine `xml:"BudgetAccountLine,omitempty"`
|
|
PlannedPeriod *PlannedPeriod `xml:"PlannedPeriod,omitempty"`
|
|
}
|
|
|
|
// Interface methods for PlanningNotice
|
|
func (pn PlanningNotice) GetID() string { return pn.ID }
|
|
func (pn PlanningNotice) GetNoticeType() string { return pn.NoticeTypeCode }
|
|
func (pn PlanningNotice) GetLanguage() string { return pn.NoticeLanguageCode }
|
|
func (pn PlanningNotice) GetNoticeStatus() NoticeStatus { return NoticeStatusPublished }
|
|
func (pn PlanningNotice) Validate() error {
|
|
if pn.ID == "" {
|
|
return fmt.Errorf("planning notice ID is required")
|
|
}
|
|
if pn.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CompetitionNotice represents a competition notice
|
|
type CompetitionNotice struct {
|
|
XMLName xml.Name `xml:"CompetitionNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
ProcurementProjectLot []ProcurementProjectLot `xml:"ProcurementProjectLot,omitempty"`
|
|
}
|
|
|
|
// Interface methods for CompetitionNotice
|
|
func (cn CompetitionNotice) GetID() string { return cn.ID }
|
|
func (cn CompetitionNotice) GetNoticeType() string { return cn.NoticeTypeCode }
|
|
func (cn CompetitionNotice) GetLanguage() string { return cn.NoticeLanguageCode }
|
|
func (cn CompetitionNotice) GetNoticeStatus() NoticeStatus { return NoticeStatusPublished }
|
|
func (cn CompetitionNotice) Validate() error {
|
|
if cn.ID == "" {
|
|
return fmt.Errorf("competition notice ID is required")
|
|
}
|
|
if cn.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ResultNotice represents a result notice (eForms specific)
|
|
type ResultNotice struct {
|
|
XMLName xml.Name `xml:"ResultNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
ProcurementProjectLot []ProcurementProjectLot `xml:"ProcurementProjectLot,omitempty"`
|
|
TenderResult []TenderResult `xml:"TenderResult,omitempty"`
|
|
SettledContract []SettledContract `xml:"SettledContract,omitempty"`
|
|
}
|
|
|
|
// Interface methods for ResultNotice
|
|
func (rn ResultNotice) GetID() string { return rn.ID }
|
|
func (rn ResultNotice) GetNoticeType() string { return rn.NoticeTypeCode }
|
|
func (rn ResultNotice) GetLanguage() string { return rn.NoticeLanguageCode }
|
|
func (rn ResultNotice) GetNoticeStatus() NoticeStatus { return NoticeStatusAwarded }
|
|
func (rn ResultNotice) Validate() error {
|
|
if rn.ID == "" {
|
|
return fmt.Errorf("result notice ID is required")
|
|
}
|
|
if rn.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ChangeNotice represents a change notice (eForms specific)
|
|
type ChangeNotice struct {
|
|
XMLName xml.Name `xml:"ChangeNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
ProcurementProjectLot []ProcurementProjectLot `xml:"ProcurementProjectLot,omitempty"`
|
|
NoticeVersionIdentifier string `xml:"NoticeVersionIdentifier,omitempty"`
|
|
ChangeReason []ChangeReason `xml:"ChangeReason,omitempty"`
|
|
}
|
|
|
|
// Interface methods for ChangeNotice
|
|
func (cn ChangeNotice) GetID() string { return cn.ID }
|
|
func (cn ChangeNotice) GetNoticeType() string { return cn.NoticeTypeCode }
|
|
func (cn ChangeNotice) GetLanguage() string { return cn.NoticeLanguageCode }
|
|
func (cn ChangeNotice) GetNoticeStatus() NoticeStatus { return NoticeStatusModified }
|
|
func (cn ChangeNotice) Validate() error {
|
|
if cn.ID == "" {
|
|
return fmt.Errorf("change notice ID is required")
|
|
}
|
|
if cn.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SubcontractNotice represents a subcontract notice
|
|
type SubcontractNotice struct {
|
|
XMLName xml.Name `xml:"SubcontractNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
SubcontractCall []SubcontractCall `xml:"SubcontractCall,omitempty"`
|
|
ParentContract *ParentContract `xml:"ParentContract,omitempty"`
|
|
}
|
|
|
|
// Interface methods for SubcontractNotice
|
|
func (sn SubcontractNotice) GetID() string { return sn.ID }
|
|
func (sn SubcontractNotice) GetNoticeType() string { return sn.NoticeTypeCode }
|
|
func (sn SubcontractNotice) GetLanguage() string { return sn.NoticeLanguageCode }
|
|
func (sn SubcontractNotice) GetNoticeStatus() NoticeStatus { return NoticeStatusPublished }
|
|
func (sn SubcontractNotice) Validate() error {
|
|
if sn.ID == "" {
|
|
return fmt.Errorf("subcontract notice ID is required")
|
|
}
|
|
if sn.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Additional structures for new notice types
|
|
|
|
// ContestDesignJury contains design contest jury information
|
|
type ContestDesignJury struct {
|
|
XMLName xml.Name `xml:"ContestDesignJury"`
|
|
JuryDecisionDate string `xml:"JuryDecisionDate,omitempty"`
|
|
JuryDecision string `xml:"JuryDecision,omitempty"`
|
|
JuryMember []JuryMember `xml:"JuryMember,omitempty"`
|
|
JudgingCriteria *JudgingCriteria `xml:"JudgingCriteria,omitempty"`
|
|
}
|
|
|
|
// ContestDesignReward contains design contest reward information
|
|
type ContestDesignReward struct {
|
|
XMLName xml.Name `xml:"ContestDesignReward"`
|
|
RewardCode string `xml:"RewardCode,omitempty"`
|
|
Benefit *Benefit `xml:"Benefit,omitempty"`
|
|
}
|
|
|
|
// JuryMember contains jury member information
|
|
type JuryMember struct {
|
|
XMLName xml.Name `xml:"JuryMember"`
|
|
Party *Party `xml:"Party,omitempty"`
|
|
}
|
|
|
|
// JudgingCriteria contains judging criteria information
|
|
type JudgingCriteria struct {
|
|
XMLName xml.Name `xml:"JudgingCriteria"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// Benefit contains benefit information
|
|
type Benefit struct {
|
|
XMLName xml.Name `xml:"Benefit"`
|
|
BenefitValue CurrencyText `xml:"BenefitValue,omitempty"`
|
|
}
|
|
|
|
// QualificationApplication contains qualification application information
|
|
type QualificationApplication struct {
|
|
XMLName xml.Name `xml:"QualificationApplication"`
|
|
QualificationTypeCode string `xml:"QualificationTypeCode,omitempty"`
|
|
ApplicationPeriod *ApplicationPeriod `xml:"ApplicationPeriod,omitempty"`
|
|
TendererQualificationRequest *TendererQualificationRequest `xml:"TendererQualificationRequest,omitempty"`
|
|
}
|
|
|
|
// ApplicationPeriod contains application period information
|
|
type ApplicationPeriod struct {
|
|
XMLName xml.Name `xml:"ApplicationPeriod"`
|
|
StartDate string `xml:"StartDate,omitempty"`
|
|
EndDate string `xml:"EndDate,omitempty"`
|
|
StartTime string `xml:"StartTime,omitempty"`
|
|
EndTime string `xml:"EndTime,omitempty"`
|
|
}
|
|
|
|
// ConcessionRevenue contains concession revenue information
|
|
type ConcessionRevenue struct {
|
|
XMLName xml.Name `xml:"ConcessionRevenue"`
|
|
RevenueType string `xml:"RevenueType,omitempty"`
|
|
RevenueAmount CurrencyText `xml:"RevenueAmount,omitempty"`
|
|
}
|
|
|
|
// ConcessionTerm contains concession term information
|
|
type ConcessionTerm struct {
|
|
XMLName xml.Name `xml:"ConcessionTerm"`
|
|
ConcessionValue CurrencyText `xml:"ConcessionValue,omitempty"`
|
|
Duration *DurationMeasure `xml:"DurationMeasure,omitempty"`
|
|
}
|
|
|
|
// BudgetAccountLine contains budget account line information
|
|
type BudgetAccountLine struct {
|
|
XMLName xml.Name `xml:"BudgetAccountLine"`
|
|
ID string `xml:"ID,omitempty"`
|
|
BudgetYear string `xml:"BudgetYear,omitempty"`
|
|
TotalAmount CurrencyText `xml:"TotalAmount,omitempty"`
|
|
BudgetAccount *BudgetAccount `xml:"BudgetAccount,omitempty"`
|
|
}
|
|
|
|
// BudgetAccount contains budget account information
|
|
type BudgetAccount struct {
|
|
XMLName xml.Name `xml:"BudgetAccount"`
|
|
BudgetCode string `xml:"BudgetCode,omitempty"`
|
|
RequiredClassificationScheme *RequiredClassificationScheme `xml:"RequiredClassificationScheme,omitempty"`
|
|
}
|
|
|
|
// RequiredClassificationScheme contains classification scheme information
|
|
type RequiredClassificationScheme struct {
|
|
XMLName xml.Name `xml:"RequiredClassificationScheme"`
|
|
ItemClassificationCode string `xml:"ItemClassificationCode,omitempty"`
|
|
}
|
|
|
|
// SubcontractCall contains subcontract call information
|
|
type SubcontractCall struct {
|
|
XMLName xml.Name `xml:"SubcontractCall"`
|
|
SubcontractingTypeCode string `xml:"SubcontractingTypeCode,omitempty"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
}
|
|
|
|
// ParentContract contains parent contract information
|
|
type ParentContract struct {
|
|
XMLName xml.Name `xml:"ParentContract"`
|
|
ContractReference *ContractReference `xml:"ContractReference,omitempty"`
|
|
FrameworkAgreement *FrameworkAgreement `xml:"FrameworkAgreement,omitempty"`
|
|
}
|
|
|
|
// FrameworkAgreement contains framework agreement information
|
|
type FrameworkAgreement struct {
|
|
XMLName xml.Name `xml:"FrameworkAgreement"`
|
|
EstimatedMaximumValue CurrencyText `xml:"EstimatedMaximumValue,omitempty"`
|
|
MaximumParticipants string `xml:"MaximumParticipants,omitempty"`
|
|
Duration *DurationMeasure `xml:"DurationMeasure,omitempty"`
|
|
SubsequentProcedureIndicator string `xml:"SubsequentProcedureIndicator,omitempty"`
|
|
}
|
|
|
|
// AdditionalDocumentReference contains additional document reference information
|
|
type AdditionalDocumentReference struct {
|
|
XMLName xml.Name `xml:"AdditionalDocumentReference"`
|
|
ID string `xml:"ID,omitempty"`
|
|
DocumentType string `xml:"DocumentType,omitempty"`
|
|
DocumentDescription string `xml:"DocumentDescription,omitempty"`
|
|
LanguageID string `xml:"LanguageID,omitempty"`
|
|
Attachment *Attachment `xml:"Attachment,omitempty"`
|
|
ValidityPeriod *ValidityPeriod `xml:"ValidityPeriod,omitempty"`
|
|
UBLExtensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
}
|
|
|
|
// ValidityPeriod contains validity period information
|
|
type ValidityPeriod struct {
|
|
XMLName xml.Name `xml:"ValidityPeriod"`
|
|
StartDate string `xml:"StartDate,omitempty"`
|
|
EndDate string `xml:"EndDate,omitempty"`
|
|
StartTime string `xml:"StartTime,omitempty"`
|
|
EndTime string `xml:"EndTime,omitempty"`
|
|
}
|
|
|
|
// EnhancedTenderResult structure with more comprehensive information
|
|
type EnhancedTenderResult struct {
|
|
XMLName xml.Name `xml:"TenderResult"`
|
|
AwardDate string `xml:"AwardDate"`
|
|
AwardTime string `xml:"AwardTime,omitempty"`
|
|
ReceivedTenderQuantity string `xml:"ReceivedTenderQuantity,omitempty"`
|
|
LowerTenderAmount CurrencyText `xml:"LowerTenderAmount,omitempty"`
|
|
HigherTenderAmount CurrencyText `xml:"HigherTenderAmount,omitempty"`
|
|
AwardedTenderedProject *AwardedTenderedProject `xml:"AwardedTenderedProject,omitempty"`
|
|
ContractAwardNotice *ContractAwardNotice `xml:"ContractAwardNotice,omitempty"`
|
|
SubcontractingTerm []SubcontractingTerm `xml:"SubcontractingTerm,omitempty"`
|
|
WinningTenderLot []WinningTenderLot `xml:"WinningTenderLot,omitempty"`
|
|
ReceivedSubmissionsStatistics []ReceivedSubmissionsStatistics `xml:"ReceivedSubmissionsStatistics,omitempty"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
}
|
|
|
|
// AwardedTenderedProject contains awarded tendered project information
|
|
type AwardedTenderedProject struct {
|
|
XMLName xml.Name `xml:"AwardedTenderedProject"`
|
|
ProcurementTypeCode string `xml:"ProcurementTypeCode,omitempty"`
|
|
TotalAmount CurrencyText `xml:"TotalAmount,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
LegalMonetaryTotal *LegalMonetaryTotal `xml:"LegalMonetaryTotal,omitempty"`
|
|
TenderLot []TenderLot `xml:"TenderLot,omitempty"`
|
|
}
|
|
|
|
// WinningTenderLot contains winning tender lot information
|
|
type WinningTenderLot struct {
|
|
XMLName xml.Name `xml:"WinningTenderLot"`
|
|
TenderLot *TenderLot `xml:"TenderLot,omitempty"`
|
|
WinningTender []WinningTender `xml:"WinningTender,omitempty"`
|
|
}
|
|
|
|
// WinningTender contains winning tender information
|
|
type WinningTender struct {
|
|
XMLName xml.Name `xml:"WinningTender"`
|
|
ID string `xml:"ID"`
|
|
TenderVariantIndicator string `xml:"TenderVariantIndicator,omitempty"`
|
|
LegalMonetaryTotal *LegalMonetaryTotal `xml:"LegalMonetaryTotal,omitempty"`
|
|
TenderingParty *TenderingParty `xml:"TenderingParty,omitempty"`
|
|
SubcontractingTerm []SubcontractingTerm `xml:"SubcontractingTerm,omitempty"`
|
|
}
|
|
|
|
// Enhanced SubcontractingTerm structure
|
|
type SubcontractingTerm struct {
|
|
XMLName xml.Name `xml:"SubcontractingTerm"`
|
|
TermCode string `xml:"TermCode"`
|
|
Amount CurrencyText `xml:"Amount,omitempty"`
|
|
Rate string `xml:"Rate,omitempty"`
|
|
Description string `xml:"Description,omitempty"`
|
|
UnknownPriceIndicator string `xml:"UnknownPriceIndicator,omitempty"`
|
|
SubcontractingDescription string `xml:"SubcontractingDescription,omitempty"`
|
|
}
|
|
|
|
// NoticeStatusInformation contains status-specific fields
|
|
type NoticeStatusInformation struct {
|
|
Status NoticeStatus `xml:"NoticeStatus,omitempty"`
|
|
StatusCode string `xml:"StatusCode,omitempty"`
|
|
CancellationReason *CancellationReason `xml:"CancellationReason,omitempty"`
|
|
AwardInformation *AwardInformation `xml:"AwardInformation,omitempty"`
|
|
Modifications []NoticeModification `xml:"Modifications>Modification,omitempty"`
|
|
SuspensionReason *SuspensionReason `xml:"SuspensionReason,omitempty"`
|
|
}
|
|
|
|
// CancellationReason contains cancellation information
|
|
type CancellationReason struct {
|
|
XMLName xml.Name `xml:"CancellationReason"`
|
|
ReasonCode string `xml:"ReasonCode"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// AwardInformation contains award-specific information
|
|
type AwardInformation struct {
|
|
XMLName xml.Name `xml:"AwardInformation"`
|
|
AwardDate string `xml:"AwardDate"`
|
|
AwardedValue CurrencyText `xml:"AwardedValue,omitempty"`
|
|
WinningTenderer *WinningTenderer `xml:"WinningTenderer,omitempty"`
|
|
ContractNumber string `xml:"ContractNumber,omitempty"`
|
|
}
|
|
|
|
// WinningTenderer contains information about the winning tenderer
|
|
type WinningTenderer struct {
|
|
XMLName xml.Name `xml:"WinningTenderer"`
|
|
NaturalPersonIndicator string `xml:"NaturalPersonIndicator,omitempty"`
|
|
Company *Company `xml:"Company,omitempty"`
|
|
}
|
|
|
|
// NoticeModification contains modification information
|
|
type NoticeModification struct {
|
|
XMLName xml.Name `xml:"Modification"`
|
|
ModificationDate string `xml:"ModificationDate"`
|
|
ModificationReason string `xml:"ModificationReason"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// SuspensionReason contains suspension information
|
|
type SuspensionReason struct {
|
|
XMLName xml.Name `xml:"SuspensionReason"`
|
|
ReasonCode string `xml:"ReasonCode"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// ContractNotice represents the main TED XML contract notice structure
|
|
type ContractNotice struct {
|
|
XMLName xml.Name `xml:"ContractNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
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"`
|
|
StatusInformation *NoticeStatusInformation `xml:"StatusInformation,omitempty"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
ProcurementProjectLot *ProcurementProjectLot `xml:"ProcurementProjectLot,omitempty"`
|
|
}
|
|
|
|
// ContractAwardNotice represents the main TED XML contract award notice structure
|
|
type ContractAwardNotice struct {
|
|
XMLName xml.Name `xml:"ContractAwardNotice"`
|
|
Xmlns string `xml:"xmlns,attr,omitempty"`
|
|
XmlnsCac string `xml:"xmlns:cac,attr,omitempty"`
|
|
XmlnsCbc string `xml:"xmlns:cbc,attr,omitempty"`
|
|
XmlnsEfac string `xml:"xmlns:efac,attr,omitempty"`
|
|
XmlnsEfbc string `xml:"xmlns:efbc,attr,omitempty"`
|
|
XmlnsEfext string `xml:"xmlns:efext,attr,omitempty"`
|
|
XmlnsExt string `xml:"xmlns:ext,attr,omitempty"`
|
|
Extensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
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"`
|
|
StatusInformation *NoticeStatusInformation `xml:"StatusInformation,omitempty"`
|
|
ContractingParty *ContractingParty `xml:"ContractingParty,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
ProcurementProjectLot []ProcurementProjectLot `xml:"ProcurementProjectLot,omitempty"`
|
|
TenderResult *TenderResult `xml:"TenderResult,omitempty"`
|
|
}
|
|
|
|
// NoticeResult contains notice result information from extensions
|
|
type NoticeResult struct {
|
|
XMLName xml.Name `xml:"NoticeResult"`
|
|
TotalAmount *CurrencyText `xml:"TotalAmount,omitempty"`
|
|
LotResult []LotResult `xml:"LotResult,omitempty"`
|
|
LotTender []LotTender `xml:"LotTender,omitempty"`
|
|
SettledContract []SettledContract `xml:"SettledContract,omitempty"`
|
|
TenderingParty []TenderingParty `xml:"TenderingParty,omitempty"`
|
|
}
|
|
|
|
// LotResult contains lot result information
|
|
type LotResult struct {
|
|
XMLName xml.Name `xml:"LotResult"`
|
|
ID string `xml:"ID"`
|
|
TenderResultCode string `xml:"TenderResultCode"`
|
|
LotTender []LotTender `xml:"LotTender,omitempty"`
|
|
ReceivedSubmissionsStatistics []ReceivedSubmissionsStatistics `xml:"ReceivedSubmissionsStatistics,omitempty"`
|
|
SettledContract []SettledContract `xml:"SettledContract,omitempty"`
|
|
TenderLot *TenderLot `xml:"TenderLot,omitempty"`
|
|
}
|
|
|
|
// LotTender contains lot tender information
|
|
type LotTender struct {
|
|
XMLName xml.Name `xml:"LotTender"`
|
|
ID string `xml:"ID"`
|
|
RankCode string `xml:"RankCode,omitempty"`
|
|
TenderRankedIndicator string `xml:"TenderRankedIndicator,omitempty"`
|
|
TenderVariantIndicator string `xml:"TenderVariantIndicator,omitempty"`
|
|
LegalMonetaryTotal *LegalMonetaryTotal `xml:"LegalMonetaryTotal,omitempty"`
|
|
SubcontractingTerm *SubcontractingTerm `xml:"SubcontractingTerm,omitempty"`
|
|
TenderingParty *TenderingParty `xml:"TenderingParty,omitempty"`
|
|
TenderLot *TenderLot `xml:"TenderLot,omitempty"`
|
|
TenderReference *TenderReference `xml:"TenderReference,omitempty"`
|
|
}
|
|
|
|
// LegalMonetaryTotal contains monetary total information
|
|
type LegalMonetaryTotal struct {
|
|
XMLName xml.Name `xml:"LegalMonetaryTotal"`
|
|
PayableAmount CurrencyText `xml:"PayableAmount"`
|
|
}
|
|
|
|
// TenderingParty contains tendering party information
|
|
type TenderingParty struct {
|
|
XMLName xml.Name `xml:"TenderingParty"`
|
|
ID string `xml:"ID"`
|
|
Tenderer []Tenderer `xml:"Tenderer,omitempty"`
|
|
}
|
|
|
|
// Tenderer contains tenderer information
|
|
type Tenderer struct {
|
|
XMLName xml.Name `xml:"Tenderer"`
|
|
ID string `xml:"ID"`
|
|
}
|
|
|
|
// TenderLot contains tender lot information
|
|
type TenderLot struct {
|
|
XMLName xml.Name `xml:"TenderLot"`
|
|
ID string `xml:"ID"`
|
|
}
|
|
|
|
// TenderReference contains tender reference information
|
|
type TenderReference struct {
|
|
XMLName xml.Name `xml:"TenderReference"`
|
|
ID string `xml:"ID"`
|
|
}
|
|
|
|
// ReceivedSubmissionsStatistics contains received submissions statistics
|
|
type ReceivedSubmissionsStatistics struct {
|
|
XMLName xml.Name `xml:"ReceivedSubmissionsStatistics"`
|
|
StatisticsCode string `xml:"StatisticsCode"`
|
|
StatisticsNumeric string `xml:"StatisticsNumeric"`
|
|
}
|
|
|
|
// SettledContract contains settled contract information
|
|
type SettledContract struct {
|
|
XMLName xml.Name `xml:"SettledContract"`
|
|
ID string `xml:"ID"`
|
|
IssueDate string `xml:"IssueDate,omitempty"`
|
|
AwardDate string `xml:"AwardDate,omitempty"`
|
|
Title string `xml:"Title,omitempty"`
|
|
ContractFrameworkIndicator string `xml:"ContractFrameworkIndicator,omitempty"`
|
|
SignatoryParty *SignatoryParty `xml:"SignatoryParty,omitempty"`
|
|
ContractReference *ContractReference `xml:"ContractReference,omitempty"`
|
|
LotTender *LotTender `xml:"LotTender,omitempty"`
|
|
NoticeDocumentReference *NoticeDocumentReference `xml:"NoticeDocumentReference,omitempty"`
|
|
}
|
|
|
|
// SignatoryParty contains signatory party information
|
|
type SignatoryParty struct {
|
|
XMLName xml.Name `xml:"SignatoryParty"`
|
|
PartyIdentification *PartyIdentification `xml:"PartyIdentification,omitempty"`
|
|
}
|
|
|
|
// ContractReference contains contract reference information
|
|
type ContractReference struct {
|
|
XMLName xml.Name `xml:"ContractReference"`
|
|
ID string `xml:"ID"`
|
|
}
|
|
|
|
// TenderResult contains tender result information
|
|
type TenderResult struct {
|
|
XMLName xml.Name `xml:"TenderResult"`
|
|
AwardDate string `xml:"AwardDate"`
|
|
}
|
|
|
|
// NoticeDocumentReference contains notice document reference information
|
|
type NoticeDocumentReference struct {
|
|
XMLName xml.Name `xml:"NoticeDocumentReference"`
|
|
ID string `xml:"ID"`
|
|
}
|
|
|
|
// PresentationPeriod contains presentation period information
|
|
type PresentationPeriod struct {
|
|
XMLName xml.Name `xml:"PresentationPeriod"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// AppealInformationParty contains appeal information party
|
|
type AppealInformationParty struct {
|
|
XMLName xml.Name `xml:"AppealInformationParty"`
|
|
PartyIdentification *PartyIdentification `xml:"PartyIdentification,omitempty"`
|
|
}
|
|
|
|
// MediationParty contains mediation party information
|
|
type MediationParty struct {
|
|
XMLName xml.Name `xml:"MediationParty"`
|
|
PartyIdentification *PartyIdentification `xml:"PartyIdentification,omitempty"`
|
|
}
|
|
|
|
// UBLExtensions contains eForms extensions
|
|
type UBLExtensions struct {
|
|
XMLName xml.Name `xml:"UBLExtensions"`
|
|
UBLExtension *UBLExtension `xml:"UBLExtension,omitempty"`
|
|
}
|
|
|
|
// UBLExtension contains extension content
|
|
type UBLExtension struct {
|
|
XMLName xml.Name `xml:"UBLExtension"`
|
|
ExtensionContent *ExtensionContent `xml:"ExtensionContent,omitempty"`
|
|
}
|
|
|
|
// ExtensionContent contains eForms extension data
|
|
type ExtensionContent struct {
|
|
XMLName xml.Name `xml:"ExtensionContent"`
|
|
EformsExtension *EformsExtension `xml:"EformsExtension,omitempty"`
|
|
}
|
|
|
|
// EformsExtension contains eForms specific data
|
|
type EformsExtension struct {
|
|
XMLName xml.Name `xml:"EformsExtension"`
|
|
NoticeResult *NoticeResult `xml:"NoticeResult,omitempty"`
|
|
NoticeSubType *NoticeSubType `xml:"NoticeSubType,omitempty"`
|
|
Organizations *Organizations `xml:"Organizations,omitempty"`
|
|
Publication *Publication `xml:"Publication,omitempty"`
|
|
Changes *Changes `xml:"Changes,omitempty"`
|
|
SelectionCriteria []SelectionCriteria `xml:"SelectionCriteria,omitempty"`
|
|
OfficialLanguages *OfficialLanguages `xml:"OfficialLanguages,omitempty"`
|
|
AwardCriterionParameter *AwardCriterionParameter `xml:"AwardCriterionParameter,omitempty"`
|
|
AccessToolName string `xml:"AccessToolName,omitempty"`
|
|
}
|
|
|
|
// NoticeSubType contains notice subtype information
|
|
type NoticeSubType struct {
|
|
XMLName xml.Name `xml:"NoticeSubType"`
|
|
SubTypeCode string `xml:"SubTypeCode"`
|
|
}
|
|
|
|
// SelectionCriteria contains tenderer requirement information
|
|
type SelectionCriteria struct {
|
|
XMLName xml.Name `xml:"SelectionCriteria"`
|
|
CriterionTypeCode string `xml:"CriterionTypeCode"`
|
|
TendererRequirementTypeCode string `xml:"TendererRequirementTypeCode"`
|
|
Name string `xml:"Name,omitempty"`
|
|
Description string `xml:"Description,omitempty"`
|
|
CalculationExpressionCode string `xml:"CalculationExpressionCode,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// OfficialLanguages contains official language information
|
|
type OfficialLanguages struct {
|
|
XMLName xml.Name `xml:"OfficialLanguages"`
|
|
Language []Language `xml:"Language"`
|
|
}
|
|
|
|
// Language represents a language entry
|
|
type Language struct {
|
|
XMLName xml.Name `xml:"Language"`
|
|
ID string `xml:"ID"`
|
|
}
|
|
|
|
// Organizations contains organization information
|
|
type Organizations struct {
|
|
XMLName xml.Name `xml:"Organizations"`
|
|
Organization []Organization `xml:"Organization"`
|
|
}
|
|
|
|
// Organization represents an organization entity
|
|
type Organization struct {
|
|
XMLName xml.Name `xml:"Organization"`
|
|
NaturalPersonIndicator string `xml:"NaturalPersonIndicator,omitempty"`
|
|
Company *Company `xml:"Company,omitempty"`
|
|
}
|
|
|
|
// Company represents company informationf
|
|
type Company struct {
|
|
XMLName xml.Name `xml:"Company"`
|
|
WebsiteURI string `xml:"WebsiteURI,omitempty"`
|
|
PartyIdentification *PartyIdentification `xml:"PartyIdentification,omitempty"`
|
|
PartyName *PartyName `xml:"PartyName,omitempty"`
|
|
PostalAddress *PostalAddress `xml:"PostalAddress,omitempty"`
|
|
PartyLegalEntity *PartyLegalEntity `xml:"PartyLegalEntity,omitempty"`
|
|
Contact *Contact `xml:"Contact,omitempty"`
|
|
}
|
|
|
|
// PartyIdentification contains party ID information
|
|
type PartyIdentification struct {
|
|
XMLName xml.Name `xml:"PartyIdentification"`
|
|
ID string `xml:"ID"`
|
|
}
|
|
|
|
// PartyName contains party name
|
|
type PartyName struct {
|
|
XMLName xml.Name `xml:"PartyName"`
|
|
Name string `xml:"Name"`
|
|
}
|
|
|
|
// PostalAddress contains address information
|
|
type PostalAddress struct {
|
|
XMLName xml.Name `xml:"PostalAddress"`
|
|
StreetName string `xml:"StreetName,omitempty"`
|
|
CityName string `xml:"CityName,omitempty"`
|
|
PostalZone string `xml:"PostalZone,omitempty"`
|
|
CountrySubentityCode string `xml:"CountrySubentityCode,omitempty"`
|
|
Department string `xml:"Department,omitempty"`
|
|
Country *Country `xml:"Country,omitempty"`
|
|
}
|
|
|
|
// Country contains country information
|
|
type Country struct {
|
|
XMLName xml.Name `xml:"Country"`
|
|
IdentificationCode string `xml:"IdentificationCode"`
|
|
}
|
|
|
|
// PartyLegalEntity contains legal entity information
|
|
type PartyLegalEntity struct {
|
|
XMLName xml.Name `xml:"PartyLegalEntity"`
|
|
CompanyID string `xml:"CompanyID"`
|
|
}
|
|
|
|
// Contact contains contact information
|
|
type Contact struct {
|
|
XMLName xml.Name `xml:"Contact"`
|
|
Name string `xml:"Name,omitempty"`
|
|
Telephone string `xml:"Telephone,omitempty"`
|
|
Telefax string `xml:"Telefax,omitempty"`
|
|
ElectronicMail string `xml:"ElectronicMail,omitempty"`
|
|
}
|
|
|
|
// Publication contains publication information
|
|
type Publication struct {
|
|
XMLName xml.Name `xml:"Publication"`
|
|
NoticePublicationID string `xml:"NoticePublicationID"`
|
|
GazetteID string `xml:"GazetteID"`
|
|
PublicationDate string `xml:"PublicationDate"`
|
|
}
|
|
|
|
// Changes contains notice change information
|
|
type Changes struct {
|
|
XMLName xml.Name `xml:"Changes"`
|
|
ChangedNoticeIdentifier string `xml:"ChangedNoticeIdentifier"`
|
|
ChangeReason *ChangeReason `xml:"ChangeReason,omitempty"`
|
|
}
|
|
|
|
// ChangeReason contains change reason information
|
|
type ChangeReason struct {
|
|
XMLName xml.Name `xml:"ChangeReason"`
|
|
ReasonCode string `xml:"ReasonCode"`
|
|
}
|
|
|
|
// ContractingParty contains contracting party information
|
|
type ContractingParty struct {
|
|
XMLName xml.Name `xml:"ContractingParty"`
|
|
BuyerProfileURI string `xml:"BuyerProfileURI,omitempty"`
|
|
ContractingPartyType *ContractingPartyType `xml:"ContractingPartyType,omitempty"`
|
|
ContractingActivity *ContractingActivity `xml:"ContractingActivity,omitempty"`
|
|
Party *Party `xml:"Party,omitempty"`
|
|
}
|
|
|
|
// ContractingPartyType contains party type information
|
|
type ContractingPartyType struct {
|
|
XMLName xml.Name `xml:"ContractingPartyType"`
|
|
PartyTypeCode string `xml:"PartyTypeCode"`
|
|
}
|
|
|
|
// ContractingActivity contains contracting activity information
|
|
type ContractingActivity struct {
|
|
XMLName xml.Name `xml:"ContractingActivity"`
|
|
ActivityTypeCode string `xml:"ActivityTypeCode"`
|
|
}
|
|
|
|
// Party contains party information
|
|
type Party struct {
|
|
XMLName xml.Name `xml:"Party"`
|
|
PartyIdentification *PartyIdentification `xml:"PartyIdentification,omitempty"`
|
|
ServiceProviderParty *ServiceProviderParty `xml:"ServiceProviderParty,omitempty"`
|
|
}
|
|
|
|
// ServiceProviderParty contains service provider information
|
|
type ServiceProviderParty struct {
|
|
XMLName xml.Name `xml:"ServiceProviderParty"`
|
|
ServiceTypeCode string `xml:"ServiceTypeCode,omitempty"`
|
|
Party *Party `xml:"Party,omitempty"`
|
|
}
|
|
|
|
// TenderingTerms contains tendering terms
|
|
type TenderingTerms struct {
|
|
XMLName xml.Name `xml:"TenderingTerms"`
|
|
VariantConstraintCode string `xml:"VariantConstraintCode,omitempty"`
|
|
FundingProgramCode string `xml:"FundingProgramCode,omitempty"`
|
|
RecurringProcurementIndicator string `xml:"RecurringProcurementIndicator,omitempty"`
|
|
MultipleTendersCode string `xml:"MultipleTendersCode,omitempty"`
|
|
TendererQualificationRequest []TendererQualificationRequest `xml:"TendererQualificationRequest,omitempty"`
|
|
AppealTerms *AppealTerms `xml:"AppealTerms,omitempty"`
|
|
CallForTendersDocumentReference []CallForTendersDocumentReference `xml:"CallForTendersDocumentReference,omitempty"`
|
|
RequiredFinancialGuarantee *RequiredFinancialGuarantee `xml:"RequiredFinancialGuarantee,omitempty"`
|
|
PaymentTerms *PaymentTerms `xml:"PaymentTerms,omitempty"`
|
|
AwardingTerms *AwardingTerms `xml:"AwardingTerms,omitempty"`
|
|
AdditionalInformationParty *AdditionalInformationParty `xml:"AdditionalInformationParty,omitempty"`
|
|
TenderRecipientParty *TenderRecipientParty `xml:"TenderRecipientParty,omitempty"`
|
|
TenderValidityPeriod *TenderValidityPeriod `xml:"TenderValidityPeriod,omitempty"`
|
|
Language *Language `xml:"Language,omitempty"`
|
|
PostAwardProcess *PostAwardProcess `xml:"PostAwardProcess,omitempty"`
|
|
ContractExecutionRequirement []ContractExecutionRequirement `xml:"ContractExecutionRequirement,omitempty"`
|
|
UBLExtensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
}
|
|
|
|
// RequiredFinancialGuarantee contains financial guarantee information
|
|
type RequiredFinancialGuarantee struct {
|
|
XMLName xml.Name `xml:"RequiredFinancialGuarantee"`
|
|
GuaranteeTypeCode string `xml:"GuaranteeTypeCode,omitempty"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// PaymentTerms contains payment terms information
|
|
type PaymentTerms struct {
|
|
XMLName xml.Name `xml:"PaymentTerms"`
|
|
Note string `xml:"Note,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// AwardingTerms contains awarding terms information
|
|
type AwardingTerms struct {
|
|
XMLName xml.Name `xml:"AwardingTerms"`
|
|
AwardingCriterion []AwardingCriterion `xml:"AwardingCriterion,omitempty"`
|
|
}
|
|
|
|
// AwardingCriterion contains awarding criteria information
|
|
type AwardingCriterion struct {
|
|
XMLName xml.Name `xml:"AwardingCriterion"`
|
|
SubordinateAwardingCriterion []SubordinateAwardingCriterion `xml:"SubordinateAwardingCriterion,omitempty"`
|
|
}
|
|
|
|
// SubordinateAwardingCriterion contains subordinate awarding criteria
|
|
type SubordinateAwardingCriterion struct {
|
|
XMLName xml.Name `xml:"SubordinateAwardingCriterion"`
|
|
AwardingCriterionTypeCode string `xml:"AwardingCriterionTypeCode,omitempty"`
|
|
Name string `xml:"Name,omitempty"`
|
|
Description string `xml:"Description,omitempty"`
|
|
UBLExtensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
}
|
|
|
|
// AwardCriterionParameter contains award criterion parameter information
|
|
type AwardCriterionParameter struct {
|
|
XMLName xml.Name `xml:"AwardCriterionParameter"`
|
|
ParameterCode string `xml:"ParameterCode,omitempty"`
|
|
ParameterNumeric string `xml:"ParameterNumeric,omitempty"`
|
|
}
|
|
|
|
// AdditionalInformationParty contains additional information party
|
|
type AdditionalInformationParty struct {
|
|
XMLName xml.Name `xml:"AdditionalInformationParty"`
|
|
PartyIdentification *PartyIdentification `xml:"PartyIdentification,omitempty"`
|
|
}
|
|
|
|
// TenderRecipientParty contains tender recipient party information
|
|
type TenderRecipientParty struct {
|
|
XMLName xml.Name `xml:"TenderRecipientParty"`
|
|
EndpointID string `xml:"EndpointID,omitempty"`
|
|
}
|
|
|
|
// TenderValidityPeriod contains tender validity period
|
|
type TenderValidityPeriod struct {
|
|
XMLName xml.Name `xml:"TenderValidityPeriod"`
|
|
DurationMeasure *DurationMeasure `xml:"DurationMeasure,omitempty"`
|
|
}
|
|
|
|
// PostAwardProcess contains post award process information
|
|
type PostAwardProcess struct {
|
|
XMLName xml.Name `xml:"PostAwardProcess"`
|
|
ElectronicCatalogueUsageIndicator string `xml:"ElectronicCatalogueUsageIndicator,omitempty"`
|
|
ElectronicOrderUsageIndicator string `xml:"ElectronicOrderUsageIndicator,omitempty"`
|
|
ElectronicPaymentUsageIndicator string `xml:"ElectronicPaymentUsageIndicator,omitempty"`
|
|
}
|
|
|
|
// ContractExecutionRequirement contains contract execution requirements
|
|
type ContractExecutionRequirement struct {
|
|
XMLName xml.Name `xml:"ContractExecutionRequirement"`
|
|
ExecutionRequirementCode string `xml:"ExecutionRequirementCode,omitempty"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// AppealTerms contains appeal terms information
|
|
type AppealTerms struct {
|
|
XMLName xml.Name `xml:"AppealTerms"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
PresentationPeriod *PresentationPeriod `xml:"PresentationPeriod,omitempty"`
|
|
AppealInformationParty *AppealInformationParty `xml:"AppealInformationParty,omitempty"`
|
|
AppealReceiverParty *AppealReceiverParty `xml:"AppealReceiverParty,omitempty"`
|
|
MediationParty *MediationParty `xml:"MediationParty,omitempty"`
|
|
}
|
|
|
|
// AppealReceiverParty contains appeal receiver party information
|
|
type AppealReceiverParty struct {
|
|
XMLName xml.Name `xml:"AppealReceiverParty"`
|
|
PartyIdentification *PartyIdentification `xml:"PartyIdentification,omitempty"`
|
|
}
|
|
|
|
// CallForTendersDocumentReference contains document reference information
|
|
type CallForTendersDocumentReference struct {
|
|
XMLName xml.Name `xml:"CallForTendersDocumentReference"`
|
|
ID string `xml:"ID,omitempty"`
|
|
DocumentType string `xml:"DocumentType,omitempty"`
|
|
LanguageID string `xml:"LanguageID,omitempty"`
|
|
DocumentStatusCode string `xml:"DocumentStatusCode,omitempty"`
|
|
Attachment *Attachment `xml:"Attachment,omitempty"`
|
|
UBLExtensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
}
|
|
|
|
// Attachment contains attachment information
|
|
type Attachment struct {
|
|
XMLName xml.Name `xml:"Attachment"`
|
|
ExternalReference *ExternalReference `xml:"ExternalReference,omitempty"`
|
|
}
|
|
|
|
// ExternalReference contains external reference information
|
|
type ExternalReference struct {
|
|
XMLName xml.Name `xml:"ExternalReference"`
|
|
URI string `xml:"URI"`
|
|
DocumentHash string `xml:"DocumentHash,omitempty"`
|
|
FileName string `xml:"FileName,omitempty"`
|
|
}
|
|
|
|
// TendererQualificationRequest contains qualification request information
|
|
type TendererQualificationRequest struct {
|
|
XMLName xml.Name `xml:"TendererQualificationRequest"`
|
|
CompanyLegalFormCode string `xml:"CompanyLegalFormCode,omitempty"`
|
|
SpecificTendererRequirement []SpecificTendererRequirement `xml:"SpecificTendererRequirement,omitempty"`
|
|
}
|
|
|
|
// SpecificTendererRequirement contains specific requirement information
|
|
type SpecificTendererRequirement struct {
|
|
XMLName xml.Name `xml:"SpecificTendererRequirement"`
|
|
TendererRequirementTypeCode string `xml:"TendererRequirementTypeCode"`
|
|
Description string `xml:"Description,omitempty"`
|
|
}
|
|
|
|
// TenderingProcess contains tendering process information
|
|
type TenderingProcess struct {
|
|
XMLName xml.Name `xml:"TenderingProcess"`
|
|
Description string `xml:"Description,omitempty"`
|
|
ProcedureCode string `xml:"ProcedureCode"`
|
|
SubmissionMethodCode string `xml:"SubmissionMethodCode,omitempty"`
|
|
GovernmentAgreementConstraintIndicator string `xml:"GovernmentAgreementConstraintIndicator,omitempty"`
|
|
ProcessJustification *ProcessJustification `xml:"ProcessJustification,omitempty"`
|
|
TenderSubmissionDeadlinePeriod *TenderSubmissionDeadlinePeriod `xml:"TenderSubmissionDeadlinePeriod,omitempty"`
|
|
OpenTenderEvent *OpenTenderEvent `xml:"OpenTenderEvent,omitempty"`
|
|
AuctionTerms *AuctionTerms `xml:"AuctionTerms,omitempty"`
|
|
ContractingSystem []ContractingSystem `xml:"ContractingSystem,omitempty"`
|
|
NoticeDocumentReference []NoticeDocumentReference `xml:"NoticeDocumentReference,omitempty"`
|
|
UBLExtensions *UBLExtensions `xml:"UBLExtensions,omitempty"`
|
|
}
|
|
|
|
// TenderSubmissionDeadlinePeriod contains tender submission deadline information
|
|
type TenderSubmissionDeadlinePeriod struct {
|
|
XMLName xml.Name `xml:"TenderSubmissionDeadlinePeriod"`
|
|
EndDate string `xml:"EndDate"`
|
|
EndTime string `xml:"EndTime,omitempty"`
|
|
}
|
|
|
|
// OpenTenderEvent contains open tender event information
|
|
type OpenTenderEvent struct {
|
|
XMLName xml.Name `xml:"OpenTenderEvent"`
|
|
OccurrenceDate string `xml:"OccurrenceDate,omitempty"`
|
|
OccurrenceTime string `xml:"OccurrenceTime,omitempty"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
OccurenceLocation *OccurenceLocation `xml:"OccurenceLocation,omitempty"`
|
|
}
|
|
|
|
// OccurenceLocation contains occurrence location information
|
|
type OccurenceLocation struct {
|
|
XMLName xml.Name `xml:"OccurenceLocation"`
|
|
Description string `xml:"Description,omitempty"`
|
|
LanguageID string `xml:"languageID,attr,omitempty"`
|
|
}
|
|
|
|
// AuctionTerms contains auction terms information
|
|
type AuctionTerms struct {
|
|
XMLName xml.Name `xml:"AuctionTerms"`
|
|
AuctionConstraintIndicator string `xml:"AuctionConstraintIndicator,omitempty"`
|
|
}
|
|
|
|
// ContractingSystem contains contracting system information
|
|
type ContractingSystem struct {
|
|
XMLName xml.Name `xml:"ContractingSystem"`
|
|
ContractingSystemTypeCode string `xml:"ContractingSystemTypeCode,omitempty"`
|
|
}
|
|
|
|
// ProcurementProject contains procurement project information
|
|
type ProcurementProject struct {
|
|
XMLName xml.Name `xml:"ProcurementProject"`
|
|
ID string `xml:"ID"`
|
|
Name string `xml:"Name"`
|
|
Description string `xml:"Description"`
|
|
ProcurementTypeCode string `xml:"ProcurementTypeCode"`
|
|
SMESuitableIndicator string `xml:"SMESuitableIndicator,omitempty"`
|
|
Note string `xml:"Note,omitempty"`
|
|
|
|
RequestedTenderTotal *RequestedTenderTotal `xml:"RequestedTenderTotal,omitempty"`
|
|
MainCommodityClassification *MainCommodityClassification `xml:"MainCommodityClassification,omitempty"`
|
|
AdditionalCommodityClassification []AdditionalCommodityClassification `xml:"AdditionalCommodityClassification,omitempty"`
|
|
ProcurementAdditionalType *ProcurementAdditionalType `xml:"ProcurementAdditionalType,omitempty"`
|
|
RealizedLocation *RealizedLocation `xml:"RealizedLocation,omitempty"`
|
|
PlannedPeriod *PlannedPeriod `xml:"PlannedPeriod,omitempty"`
|
|
ContractExtension *ContractExtension `xml:"ContractExtension,omitempty"`
|
|
}
|
|
|
|
// ProcurementAdditionalType contains additional procurement type information
|
|
type ProcurementAdditionalType struct {
|
|
XMLName xml.Name `xml:"ProcurementAdditionalType"`
|
|
ProcurementTypeCode string `xml:"ProcurementTypeCode,omitempty"`
|
|
}
|
|
|
|
// ContractExtension contains contract extension information
|
|
type ContractExtension struct {
|
|
XMLName xml.Name `xml:"ContractExtension"`
|
|
MaximumNumberNumeric string `xml:"MaximumNumberNumeric,omitempty"`
|
|
}
|
|
|
|
// ProcessJustification contains process justification
|
|
type ProcessJustification struct {
|
|
XMLName xml.Name `xml:"ProcessJustification"`
|
|
ProcessReasonCode string `xml:"ProcessReasonCode"`
|
|
}
|
|
|
|
// RequestedTenderTotal contains tender total information
|
|
type RequestedTenderTotal struct {
|
|
XMLName xml.Name `xml:"RequestedTenderTotal"`
|
|
EstimatedOverallContractAmount CurrencyText `xml:"EstimatedOverallContractAmount"`
|
|
}
|
|
|
|
// CurrencyText represents text with currency attribute
|
|
type CurrencyText struct {
|
|
CurrencyID string `xml:"currencyID,attr,omitempty"`
|
|
Text string `xml:",chardata"`
|
|
}
|
|
|
|
// MainCommodityClassification contains main commodity classification
|
|
type MainCommodityClassification struct {
|
|
XMLName xml.Name `xml:"MainCommodityClassification"`
|
|
ItemClassificationCode string `xml:"ItemClassificationCode"`
|
|
}
|
|
|
|
// AdditionalCommodityClassification contains additional commodity classification
|
|
type AdditionalCommodityClassification struct {
|
|
XMLName xml.Name `xml:"AdditionalCommodityClassification"`
|
|
ItemClassificationCode string `xml:"ItemClassificationCode"`
|
|
}
|
|
|
|
// RealizedLocation contains location information
|
|
type RealizedLocation struct {
|
|
XMLName xml.Name `xml:"RealizedLocation"`
|
|
Description string `xml:"Description,omitempty"`
|
|
Address *Address `xml:"Address,omitempty"`
|
|
}
|
|
|
|
// Address contains address information (different from PostalAddress)
|
|
type Address struct {
|
|
XMLName xml.Name `xml:"Address"`
|
|
StreetName string `xml:"StreetName,omitempty"`
|
|
AdditionalStreetName string `xml:"AdditionalStreetName,omitempty"`
|
|
CityName string `xml:"CityName,omitempty"`
|
|
PostalZone string `xml:"PostalZone,omitempty"`
|
|
CountrySubentityCode string `xml:"CountrySubentityCode,omitempty"`
|
|
Region string `xml:"Region,omitempty"`
|
|
Country *Country `xml:"Country,omitempty"`
|
|
}
|
|
|
|
// PlannedPeriod contains planned period information
|
|
type PlannedPeriod struct {
|
|
XMLName xml.Name `xml:"PlannedPeriod"`
|
|
StartDate string `xml:"StartDate,omitempty"`
|
|
EndDate string `xml:"EndDate,omitempty"`
|
|
DurationMeasure *DurationMeasure `xml:"DurationMeasure,omitempty"`
|
|
}
|
|
|
|
// DurationMeasure contains duration with unit information
|
|
type DurationMeasure struct {
|
|
XMLName xml.Name `xml:"DurationMeasure"`
|
|
UnitCode string `xml:"unitCode,attr,omitempty"`
|
|
Text string `xml:",chardata"`
|
|
}
|
|
|
|
// ProcurementProjectLot contains lot information
|
|
type ProcurementProjectLot struct {
|
|
XMLName xml.Name `xml:"ProcurementProjectLot"`
|
|
ID string `xml:"ID"`
|
|
TenderingTerms *TenderingTerms `xml:"TenderingTerms,omitempty"`
|
|
TenderingProcess *TenderingProcess `xml:"TenderingProcess,omitempty"`
|
|
ProcurementProject *ProcurementProject `xml:"ProcurementProject,omitempty"`
|
|
}
|
|
|
|
// Validate validates the ContractNotice structure
|
|
func (cn ContractNotice) Validate() error {
|
|
if cn.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
|
|
// Validate date format - TED XML uses ISO 8601 format with timezone
|
|
validFormats := []string{
|
|
"2006-01-02+07:00",
|
|
"2006-01-02-07:00",
|
|
"2006-01-02T15:04:05+07:00",
|
|
"2006-01-02T15:04:05-07:00",
|
|
"2006-01-02T15:04:05Z",
|
|
"2006-01-02Z",
|
|
"2006-01-02",
|
|
time.RFC3339,
|
|
time.RFC3339Nano,
|
|
}
|
|
|
|
var validDate bool
|
|
for _, format := range validFormats {
|
|
if _, err := time.Parse(format, cn.IssueDate); err == nil {
|
|
validDate = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !validDate {
|
|
return fmt.Errorf("invalid issue date format: %s (expected ISO 8601 format)", cn.IssueDate)
|
|
}
|
|
|
|
// Validate language code if provided (should be 3-letter ISO code)
|
|
if cn.NoticeLanguageCode != "" && len(cn.NoticeLanguageCode) != 3 {
|
|
return fmt.Errorf("invalid notice language code: %s (expected 3-letter ISO code)", cn.NoticeLanguageCode)
|
|
}
|
|
|
|
// Validate tender submission deadline format if present
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.TenderingProcess != nil &&
|
|
cn.ProcurementProjectLot.TenderingProcess.TenderSubmissionDeadlinePeriod != nil {
|
|
|
|
deadline := cn.ProcurementProjectLot.TenderingProcess.TenderSubmissionDeadlinePeriod.EndDate
|
|
if deadline != "" {
|
|
var validDeadline bool
|
|
for _, format := range validFormats {
|
|
if _, err := time.Parse(format, deadline); err == nil {
|
|
validDeadline = true
|
|
break
|
|
}
|
|
}
|
|
if !validDeadline {
|
|
return fmt.Errorf("invalid tender submission deadline format: %s (expected ISO 8601 format)", deadline)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Validate currency code if provided in budget
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject.RequestedTenderTotal != nil {
|
|
|
|
currency := cn.ProcurementProjectLot.ProcurementProject.RequestedTenderTotal.EstimatedOverallContractAmount.CurrencyID
|
|
if currency != "" && len(currency) != 3 {
|
|
return fmt.Errorf("invalid currency code: %s (expected 3-letter ISO code)", currency)
|
|
}
|
|
}
|
|
|
|
// Validate duration unit code if provided
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject.PlannedPeriod != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject.PlannedPeriod.DurationMeasure != nil {
|
|
|
|
unitCode := cn.ProcurementProjectLot.ProcurementProject.PlannedPeriod.DurationMeasure.UnitCode
|
|
if unitCode != "" {
|
|
validUnits := map[string]bool{
|
|
"MONTH": true,
|
|
"DAY": true,
|
|
"WEEK": true,
|
|
"YEAR": true,
|
|
}
|
|
if !validUnits[unitCode] {
|
|
return fmt.Errorf("invalid duration unit code: %s (expected MONTH, DAY, WEEK, or YEAR)", unitCode)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetID returns the contract notice ID
|
|
func (cn ContractNotice) GetID() string {
|
|
return cn.ID
|
|
}
|
|
|
|
// GetNoticeType returns the notice type
|
|
func (cn ContractNotice) GetNoticeType() string {
|
|
return cn.NoticeTypeCode
|
|
}
|
|
|
|
// GetLanguage returns the notice language
|
|
func (cn ContractNotice) GetLanguage() string {
|
|
return cn.NoticeLanguageCode
|
|
}
|
|
|
|
// GetNoticeStatus returns the notice status
|
|
func (cn ContractNotice) GetNoticeStatus() NoticeStatus {
|
|
if cn.StatusInformation != nil {
|
|
if cn.StatusInformation.Status != "" {
|
|
return cn.StatusInformation.Status
|
|
}
|
|
// Check for specific status indicators
|
|
if cn.StatusInformation.CancellationReason != nil {
|
|
return NoticeStatusCancelled
|
|
}
|
|
if cn.StatusInformation.AwardInformation != nil {
|
|
return NoticeStatusAwarded
|
|
}
|
|
if cn.StatusInformation.SuspensionReason != nil {
|
|
return NoticeStatusSuspended
|
|
}
|
|
if len(cn.StatusInformation.Modifications) > 0 {
|
|
return NoticeStatusModified
|
|
}
|
|
}
|
|
// Default to Published if no status information is available
|
|
return NoticeStatusPublished
|
|
}
|
|
|
|
// GetCancellationReason returns the cancellation reason if notice is cancelled
|
|
func (cn ContractNotice) GetCancellationReason() *CancellationReason {
|
|
if cn.StatusInformation != nil {
|
|
return cn.StatusInformation.CancellationReason
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetAwardInformation returns the award information if notice is awarded
|
|
func (cn ContractNotice) GetAwardInformation() *AwardInformation {
|
|
if cn.StatusInformation != nil {
|
|
return cn.StatusInformation.AwardInformation
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetModifications returns the list of modifications if notice is modified
|
|
func (cn ContractNotice) GetModifications() []NoticeModification {
|
|
if cn.StatusInformation != nil {
|
|
return cn.StatusInformation.Modifications
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetSuspensionReason returns the suspension reason if notice is suspended
|
|
func (cn ContractNotice) GetSuspensionReason() *SuspensionReason {
|
|
if cn.StatusInformation != nil {
|
|
return cn.StatusInformation.SuspensionReason
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetPublicationInfo returns publication information if available
|
|
func (cn ContractNotice) GetPublicationInfo() *Publication {
|
|
if cn.Extensions != nil &&
|
|
cn.Extensions.UBLExtension != nil &&
|
|
cn.Extensions.UBLExtension.ExtensionContent != nil &&
|
|
cn.Extensions.UBLExtension.ExtensionContent.EformsExtension != nil {
|
|
return cn.Extensions.UBLExtension.ExtensionContent.EformsExtension.Publication
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetOrganizations returns organizations from extensions
|
|
func (cn ContractNotice) GetOrganizations() *Organizations {
|
|
if cn.Extensions != nil &&
|
|
cn.Extensions.UBLExtension != nil &&
|
|
cn.Extensions.UBLExtension.ExtensionContent != nil &&
|
|
cn.Extensions.UBLExtension.ExtensionContent.EformsExtension != nil {
|
|
return cn.Extensions.UBLExtension.ExtensionContent.EformsExtension.Organizations
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetNoticeSubType returns the notice subtype code from extensions
|
|
func (cn ContractNotice) GetNoticeSubType() string {
|
|
if cn.Extensions != nil &&
|
|
cn.Extensions.UBLExtension != nil &&
|
|
cn.Extensions.UBLExtension.ExtensionContent != nil &&
|
|
cn.Extensions.UBLExtension.ExtensionContent.EformsExtension != nil &&
|
|
cn.Extensions.UBLExtension.ExtensionContent.EformsExtension.NoticeSubType != nil {
|
|
return cn.Extensions.UBLExtension.ExtensionContent.EformsExtension.NoticeSubType.SubTypeCode
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetNoticePublicationID returns the notice publication ID from extensions
|
|
func (cn ContractNotice) GetNoticePublicationID() string {
|
|
pub := cn.GetPublicationInfo()
|
|
if pub != nil {
|
|
return pub.NoticePublicationID
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetOJSID returns the OJS gazette ID from extensions
|
|
func (cn ContractNotice) GetOJSID() string {
|
|
pub := cn.GetPublicationInfo()
|
|
if pub != nil {
|
|
return pub.GazetteID
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetPublicationDate returns the publication date from extensions
|
|
func (cn ContractNotice) GetPublicationDate() string {
|
|
pub := cn.GetPublicationInfo()
|
|
if pub != nil {
|
|
return pub.PublicationDate
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetOrganizationByID returns an organization by its ID
|
|
func (cn ContractNotice) GetOrganizationByID(orgID string) *Organization {
|
|
orgs := cn.GetOrganizations()
|
|
if orgs == nil {
|
|
return nil
|
|
}
|
|
|
|
for _, org := range orgs.Organization {
|
|
if org.Company != nil &&
|
|
org.Company.PartyIdentification != nil &&
|
|
org.Company.PartyIdentification.ID == orgID {
|
|
return &org
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetBuyerID returns the buyer organization ID from contracting party
|
|
func (cn ContractNotice) GetBuyerID() string {
|
|
if cn.ContractingParty != nil &&
|
|
cn.ContractingParty.Party != nil &&
|
|
cn.ContractingParty.Party.PartyIdentification != nil {
|
|
return cn.ContractingParty.Party.PartyIdentification.ID
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetReviewOrganizationID returns the review organization ID from appeal terms
|
|
func (cn ContractNotice) GetReviewOrganizationID() string {
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms.AppealTerms != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms.AppealTerms.AppealReceiverParty != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms.AppealTerms.AppealReceiverParty.PartyIdentification != nil {
|
|
return cn.ProcurementProjectLot.TenderingTerms.AppealTerms.AppealReceiverParty.PartyIdentification.ID
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetProcedureCode returns the type of procedure
|
|
func (cn ContractNotice) GetProcedureCode() string {
|
|
if cn.TenderingProcess != nil {
|
|
return cn.TenderingProcess.ProcedureCode
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetProcurementTitle returns the procurement project title
|
|
func (cn ContractNotice) GetProcurementTitle() string {
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject != nil {
|
|
return cn.ProcurementProjectLot.ProcurementProject.Name
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetProcurementDescription returns the procurement project description
|
|
func (cn ContractNotice) GetProcurementDescription() string {
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject != nil {
|
|
return cn.ProcurementProjectLot.ProcurementProject.Description
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetContractNature returns the main nature of the contract
|
|
func (cn ContractNotice) GetContractNature() string {
|
|
if cn.ProcurementProject != nil {
|
|
return cn.ProcurementProject.ProcurementTypeCode
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetMainClassification returns the main CPV classification code
|
|
func (cn ContractNotice) GetMainClassification() string {
|
|
if cn.ProcurementProject != nil &&
|
|
cn.ProcurementProject.MainCommodityClassification != nil {
|
|
return cn.ProcurementProject.MainCommodityClassification.ItemClassificationCode
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetPlaceOfPerformance returns the place of performance
|
|
func (cn ContractNotice) GetPlaceOfPerformance() string {
|
|
if cn.ProcurementProject != nil &&
|
|
cn.ProcurementProject.RealizedLocation != nil &&
|
|
cn.ProcurementProject.RealizedLocation.Address != nil {
|
|
return cn.ProcurementProject.RealizedLocation.Address.Region
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetLotID returns the procurement lot ID
|
|
func (cn ContractNotice) GetLotID() string {
|
|
if cn.ProcurementProjectLot != nil {
|
|
return cn.ProcurementProjectLot.ID
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetSelectionCriteria returns selection criteria from extensions
|
|
func (cn ContractNotice) GetSelectionCriteria() []SelectionCriteria {
|
|
if cn.Extensions != nil &&
|
|
cn.Extensions.UBLExtension != nil &&
|
|
cn.Extensions.UBLExtension.ExtensionContent != nil &&
|
|
cn.Extensions.UBLExtension.ExtensionContent.EformsExtension != nil {
|
|
return cn.Extensions.UBLExtension.ExtensionContent.EformsExtension.SelectionCriteria
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetOfficialLanguages returns official languages from tender terms extensions
|
|
func (cn ContractNotice) GetOfficialLanguages() []string {
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms != nil &&
|
|
len(cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference) > 0 &&
|
|
cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].UBLExtensions != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].UBLExtensions.UBLExtension != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].UBLExtensions.UBLExtension.ExtensionContent != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].UBLExtensions.UBLExtension.ExtensionContent.EformsExtension != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].UBLExtensions.UBLExtension.ExtensionContent.EformsExtension.OfficialLanguages != nil {
|
|
|
|
languages := make([]string, len(cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].UBLExtensions.UBLExtension.ExtensionContent.EformsExtension.OfficialLanguages.Language))
|
|
for i, lang := range cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].UBLExtensions.UBLExtension.ExtensionContent.EformsExtension.OfficialLanguages.Language {
|
|
languages[i] = lang.ID
|
|
}
|
|
return languages
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetDocumentURI returns the document URI from call for tenders document reference
|
|
func (cn ContractNotice) GetDocumentURI() string {
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms != nil &&
|
|
len(cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference) > 0 &&
|
|
cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].Attachment != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].Attachment.ExternalReference != nil {
|
|
return cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference[0].Attachment.ExternalReference.URI
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetAllDocumentURIs returns all document URIs from call for tenders document references
|
|
func (cn ContractNotice) GetAllDocumentURIs() []string {
|
|
var uris []string
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.TenderingTerms != nil {
|
|
|
|
for _, docRef := range cn.ProcurementProjectLot.TenderingTerms.CallForTendersDocumentReference {
|
|
if docRef.Attachment != nil &&
|
|
docRef.Attachment.ExternalReference != nil &&
|
|
docRef.Attachment.ExternalReference.URI != "" {
|
|
uris = append(uris, docRef.Attachment.ExternalReference.URI)
|
|
}
|
|
}
|
|
}
|
|
return uris
|
|
}
|
|
|
|
// GetTenderDeadline returns the tender submission deadline
|
|
func (cn ContractNotice) GetTenderDeadline() string {
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.TenderingProcess != nil &&
|
|
cn.ProcurementProjectLot.TenderingProcess.TenderSubmissionDeadlinePeriod != nil {
|
|
return cn.ProcurementProjectLot.TenderingProcess.TenderSubmissionDeadlinePeriod.EndDate
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetBudget returns the estimated contract amount and currency
|
|
func (cn ContractNotice) GetBudget() (amount string, currency string) {
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject.RequestedTenderTotal != nil {
|
|
|
|
contractAmount := cn.ProcurementProjectLot.ProcurementProject.RequestedTenderTotal.EstimatedOverallContractAmount
|
|
return contractAmount.Text, contractAmount.CurrencyID
|
|
}
|
|
return "", ""
|
|
}
|
|
|
|
// GetDuration returns the contract duration and unit
|
|
func (cn ContractNotice) GetDuration() (duration string, unit string) {
|
|
if cn.ProcurementProjectLot != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject.PlannedPeriod != nil &&
|
|
cn.ProcurementProjectLot.ProcurementProject.PlannedPeriod.DurationMeasure != nil {
|
|
|
|
durationMeasure := cn.ProcurementProjectLot.ProcurementProject.PlannedPeriod.DurationMeasure
|
|
return durationMeasure.Text, durationMeasure.UnitCode
|
|
}
|
|
return "", ""
|
|
}
|
|
|
|
// ==================== ContractAwardNotice Methods ====================
|
|
|
|
// Validate validates the ContractAwardNotice structure
|
|
func (can ContractAwardNotice) Validate() error {
|
|
if can.ID == "" {
|
|
return fmt.Errorf("contract award notice ID is required")
|
|
}
|
|
|
|
if can.ContractFolderID == "" {
|
|
return fmt.Errorf("contract folder ID is required")
|
|
}
|
|
|
|
if can.IssueDate == "" {
|
|
return fmt.Errorf("issue date is required")
|
|
}
|
|
|
|
// Validate date format - TED XML uses ISO 8601 format with timezone
|
|
validFormats := []string{
|
|
"2006-01-02+07:00",
|
|
"2006-01-02-07:00",
|
|
"2006-01-02T15:04:05+07:00",
|
|
"2006-01-02T15:04:05-07:00",
|
|
"2006-01-02T15:04:05Z",
|
|
"2006-01-02Z",
|
|
"2006-01-02",
|
|
time.RFC3339,
|
|
time.RFC3339Nano,
|
|
}
|
|
|
|
var validDate bool
|
|
for _, format := range validFormats {
|
|
if _, err := time.Parse(format, can.IssueDate); err == nil {
|
|
validDate = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !validDate {
|
|
return fmt.Errorf("invalid issue date format: %s (expected ISO 8601 format)", can.IssueDate)
|
|
}
|
|
|
|
// Validate language code if provided (should be 3-letter ISO code)
|
|
if can.NoticeLanguageCode != "" && len(can.NoticeLanguageCode) != 3 {
|
|
return fmt.Errorf("invalid notice language code: %s (expected 3-letter ISO code)", can.NoticeLanguageCode)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetID returns the contract award notice ID
|
|
func (can ContractAwardNotice) GetID() string {
|
|
return can.ID
|
|
}
|
|
|
|
// GetNoticeType returns the notice type
|
|
func (can ContractAwardNotice) GetNoticeType() string {
|
|
return can.NoticeTypeCode
|
|
}
|
|
|
|
// GetLanguage returns the notice language
|
|
func (can ContractAwardNotice) GetLanguage() string {
|
|
return can.NoticeLanguageCode
|
|
}
|
|
|
|
// GetNoticeStatus returns the notice status
|
|
func (can ContractAwardNotice) GetNoticeStatus() NoticeStatus {
|
|
if can.StatusInformation != nil && can.StatusInformation.Status != "" {
|
|
return can.StatusInformation.Status
|
|
}
|
|
// Award notices are typically awarded status
|
|
return NoticeStatusAwarded
|
|
}
|
|
|
|
// GetCancellationReason returns the cancellation reason if notice is cancelled
|
|
func (can ContractAwardNotice) GetCancellationReason() *CancellationReason {
|
|
if can.StatusInformation != nil {
|
|
return can.StatusInformation.CancellationReason
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetAwardInformation returns the award information if notice is awarded
|
|
func (can ContractAwardNotice) GetAwardInformation() *AwardInformation {
|
|
if can.StatusInformation != nil {
|
|
return can.StatusInformation.AwardInformation
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetModifications returns the list of modifications if notice is modified
|
|
func (can ContractAwardNotice) GetModifications() []NoticeModification {
|
|
if can.StatusInformation != nil {
|
|
return can.StatusInformation.Modifications
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetSuspensionReason returns the suspension reason if notice is suspended
|
|
func (can ContractAwardNotice) GetSuspensionReason() *SuspensionReason {
|
|
if can.StatusInformation != nil {
|
|
return can.StatusInformation.SuspensionReason
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetPublicationInfo returns publication information if available
|
|
func (can ContractAwardNotice) GetPublicationInfo() *Publication {
|
|
if can.Extensions != nil &&
|
|
can.Extensions.UBLExtension != nil &&
|
|
can.Extensions.UBLExtension.ExtensionContent != nil &&
|
|
can.Extensions.UBLExtension.ExtensionContent.EformsExtension != nil {
|
|
return can.Extensions.UBLExtension.ExtensionContent.EformsExtension.Publication
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetOrganizations returns organizations from extensions
|
|
func (can ContractAwardNotice) GetOrganizations() *Organizations {
|
|
if can.Extensions != nil &&
|
|
can.Extensions.UBLExtension != nil &&
|
|
can.Extensions.UBLExtension.ExtensionContent != nil &&
|
|
can.Extensions.UBLExtension.ExtensionContent.EformsExtension != nil {
|
|
return can.Extensions.UBLExtension.ExtensionContent.EformsExtension.Organizations
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetNoticeResult returns notice result from extensions
|
|
func (can ContractAwardNotice) GetNoticeResult() *NoticeResult {
|
|
if can.Extensions != nil &&
|
|
can.Extensions.UBLExtension != nil &&
|
|
can.Extensions.UBLExtension.ExtensionContent != nil &&
|
|
can.Extensions.UBLExtension.ExtensionContent.EformsExtension != nil {
|
|
return can.Extensions.UBLExtension.ExtensionContent.EformsExtension.NoticeResult
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetNoticeSubType returns the notice subtype code from extensions
|
|
func (can ContractAwardNotice) GetNoticeSubType() string {
|
|
if can.Extensions != nil &&
|
|
can.Extensions.UBLExtension != nil &&
|
|
can.Extensions.UBLExtension.ExtensionContent != nil &&
|
|
can.Extensions.UBLExtension.ExtensionContent.EformsExtension != nil &&
|
|
can.Extensions.UBLExtension.ExtensionContent.EformsExtension.NoticeSubType != nil {
|
|
return can.Extensions.UBLExtension.ExtensionContent.EformsExtension.NoticeSubType.SubTypeCode
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetNoticePublicationID returns the notice publication ID from extensions
|
|
func (can ContractAwardNotice) GetNoticePublicationID() string {
|
|
pub := can.GetPublicationInfo()
|
|
if pub != nil {
|
|
return pub.NoticePublicationID
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetOJSID returns the OJS gazette ID from extensions
|
|
func (can ContractAwardNotice) GetOJSID() string {
|
|
pub := can.GetPublicationInfo()
|
|
if pub != nil {
|
|
return pub.GazetteID
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetPublicationDate returns the publication date from extensions
|
|
func (can ContractAwardNotice) GetPublicationDate() string {
|
|
pub := can.GetPublicationInfo()
|
|
if pub != nil {
|
|
return pub.PublicationDate
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetBuyerID returns the buyer organization ID from contracting party
|
|
func (can ContractAwardNotice) GetBuyerID() string {
|
|
if can.ContractingParty != nil &&
|
|
can.ContractingParty.Party != nil &&
|
|
can.ContractingParty.Party.PartyIdentification != nil {
|
|
return can.ContractingParty.Party.PartyIdentification.ID
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetProcedureCode returns the type of procedure
|
|
func (can ContractAwardNotice) GetProcedureCode() string {
|
|
if can.TenderingProcess != nil {
|
|
return can.TenderingProcess.ProcedureCode
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetProcurementTitle returns the procurement project title
|
|
func (can ContractAwardNotice) GetProcurementTitle() string {
|
|
if can.ProcurementProject != nil {
|
|
return can.ProcurementProject.Name
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetProcurementDescription returns the procurement project description
|
|
func (can ContractAwardNotice) GetProcurementDescription() string {
|
|
if can.ProcurementProject != nil {
|
|
return can.ProcurementProject.Description
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetContractNature returns the main nature of the contract
|
|
func (can ContractAwardNotice) GetContractNature() string {
|
|
if can.ProcurementProject != nil {
|
|
return can.ProcurementProject.ProcurementTypeCode
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetMainClassification returns the main CPV classification code
|
|
func (can ContractAwardNotice) GetMainClassification() string {
|
|
if can.ProcurementProject != nil &&
|
|
can.ProcurementProject.MainCommodityClassification != nil {
|
|
return can.ProcurementProject.MainCommodityClassification.ItemClassificationCode
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetTotalAwardValue returns the total award amount and currency
|
|
func (can ContractAwardNotice) GetTotalAwardValue() (amount string, currency string) {
|
|
noticeResult := can.GetNoticeResult()
|
|
if noticeResult != nil && noticeResult.TotalAmount != nil {
|
|
return noticeResult.TotalAmount.Text, noticeResult.TotalAmount.CurrencyID
|
|
}
|
|
return "", ""
|
|
}
|
|
|
|
// GetAwardDate returns the tender award date
|
|
func (can ContractAwardNotice) GetAwardDate() string {
|
|
if can.TenderResult != nil {
|
|
return can.TenderResult.AwardDate
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetOrganizationByID returns an organization by its ID
|
|
func (can ContractAwardNotice) GetOrganizationByID(orgID string) *Organization {
|
|
orgs := can.GetOrganizations()
|
|
if orgs == nil {
|
|
return nil
|
|
}
|
|
|
|
for _, org := range orgs.Organization {
|
|
if org.Company != nil &&
|
|
org.Company.PartyIdentification != nil &&
|
|
org.Company.PartyIdentification.ID == orgID {
|
|
return &org
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetAwardedContractors returns detailed information about awarded contractors
|
|
func (can ContractAwardNotice) GetAwardedContractors() []AwardedContractorInfo {
|
|
var contractors []AwardedContractorInfo
|
|
|
|
noticeResult := can.GetNoticeResult()
|
|
if noticeResult == nil {
|
|
return contractors
|
|
}
|
|
|
|
// Create a map of tender ID to tender info for quick lookup
|
|
tenderMap := make(map[string]*LotTender)
|
|
for _, lotTender := range noticeResult.LotTender {
|
|
tenderMap[lotTender.ID] = &lotTender
|
|
}
|
|
|
|
// Create a map of tendering party ID to organization ID
|
|
partyToOrgMap := make(map[string]string)
|
|
for _, tenderingParty := range noticeResult.TenderingParty {
|
|
for _, tenderer := range tenderingParty.Tenderer {
|
|
partyToOrgMap[tenderingParty.ID] = tenderer.ID
|
|
}
|
|
}
|
|
|
|
// Process settled contracts to extract award information
|
|
for _, contract := range noticeResult.SettledContract {
|
|
if contract.LotTender != nil {
|
|
// Get tender information
|
|
tender := tenderMap[contract.LotTender.ID]
|
|
if tender == nil {
|
|
continue
|
|
}
|
|
|
|
// Get organization information
|
|
var org *Organization
|
|
if tender.TenderingParty != nil {
|
|
orgID := partyToOrgMap[tender.TenderingParty.ID]
|
|
if orgID != "" {
|
|
org = can.GetOrganizationByID(orgID)
|
|
}
|
|
}
|
|
|
|
// Create awarded contractor info
|
|
contractor := AwardedContractorInfo{
|
|
ContractID: contract.ID,
|
|
TenderID: contract.LotTender.ID,
|
|
AwardDate: contract.AwardDate,
|
|
IssueDate: contract.IssueDate,
|
|
}
|
|
|
|
// Set contract reference if available
|
|
if contract.ContractReference != nil {
|
|
contractor.ContractReference = contract.ContractReference.ID
|
|
}
|
|
|
|
// Set amount and currency from tender
|
|
if tender.LegalMonetaryTotal != nil {
|
|
contractor.Amount = tender.LegalMonetaryTotal.PayableAmount.Text
|
|
contractor.Currency = tender.LegalMonetaryTotal.PayableAmount.CurrencyID
|
|
}
|
|
|
|
// Set organization information
|
|
if org != nil && org.Company != nil {
|
|
if org.Company.PartyName != nil {
|
|
contractor.Name = org.Company.PartyName.Name
|
|
}
|
|
if org.Company.PartyLegalEntity != nil {
|
|
contractor.CompanyID = org.Company.PartyLegalEntity.CompanyID
|
|
}
|
|
if org.Company.PartyIdentification != nil {
|
|
contractor.OrganizationID = org.Company.PartyIdentification.ID
|
|
}
|
|
|
|
// Set address information
|
|
if org.Company.PostalAddress != nil {
|
|
addressParts := []string{}
|
|
if org.Company.PostalAddress.StreetName != "" {
|
|
addressParts = append(addressParts, org.Company.PostalAddress.StreetName)
|
|
}
|
|
if org.Company.PostalAddress.CityName != "" {
|
|
addressParts = append(addressParts, org.Company.PostalAddress.CityName)
|
|
}
|
|
if org.Company.PostalAddress.PostalZone != "" {
|
|
addressParts = append(addressParts, org.Company.PostalAddress.PostalZone)
|
|
}
|
|
contractor.Address = strings.Join(addressParts, ", ")
|
|
|
|
if org.Company.PostalAddress.Country != nil {
|
|
contractor.Country = org.Company.PostalAddress.Country.IdentificationCode
|
|
}
|
|
}
|
|
|
|
// Set contact information
|
|
if org.Company.Contact != nil {
|
|
contractor.ContactName = org.Company.Contact.Name
|
|
contractor.ContactEmail = org.Company.Contact.ElectronicMail
|
|
contractor.ContactPhone = org.Company.Contact.Telephone
|
|
}
|
|
}
|
|
|
|
// Set lot information
|
|
if tender.TenderLot != nil {
|
|
contractor.LotID = tender.TenderLot.ID
|
|
}
|
|
|
|
contractors = append(contractors, contractor)
|
|
}
|
|
}
|
|
|
|
return contractors
|
|
}
|
|
|
|
// AwardedContractorInfo contains detailed information about an awarded contractor
|
|
type AwardedContractorInfo struct {
|
|
ContractID string `json:"contract_id"`
|
|
TenderID string `json:"tender_id"`
|
|
LotID string `json:"lot_id,omitempty"`
|
|
Name string `json:"name"`
|
|
CompanyID string `json:"company_id,omitempty"`
|
|
OrganizationID string `json:"organization_id,omitempty"`
|
|
Address string `json:"address,omitempty"`
|
|
Country string `json:"country,omitempty"`
|
|
Amount string `json:"amount"`
|
|
Currency string `json:"currency,omitempty"`
|
|
AwardDate string `json:"award_date,omitempty"`
|
|
IssueDate string `json:"issue_date,omitempty"`
|
|
ContractReference string `json:"contract_reference,omitempty"`
|
|
ContactName string `json:"contact_name,omitempty"`
|
|
ContactEmail string `json:"contact_email,omitempty"`
|
|
ContactPhone string `json:"contact_phone,omitempty"`
|
|
}
|