Refactor TED Repository and Introduce TED Mapping Functionality

- Updated the tender repository to create a unique index on tender_id, enhancing database query performance.
- Introduced new TED mapping functions to convert parsed TED documents into tender entities, improving integration with the tender management system.
- Added error handling for contract notice processing in the TED scraper, ensuring robust logging and error management.
- Removed deprecated eform structures to streamline the codebase and focus on essential components.
This commit is contained in:
n.nakhostin
2025-10-04 12:34:37 +03:30
parent 366f7290a7
commit 0dd877a46d
32 changed files with 2386 additions and 1817 deletions
+19 -40
View File
@@ -6,31 +6,10 @@ import (
"strings"
"time"
"tm/internal/tender"
"tm/ted/eform/business_registration_information"
"tm/ted/eform/contract"
"tm/ted/eform/contract_award"
"tm/ted/eform/prior_information"
)
func EFormMapper(notice interface{}) *tender.Tender {
t := new(tender.Tender)
switch notice := notice.(type) {
case contract.ContractNotice:
return notice.MapToTender()
case contract_award.ContractAwardNotice:
return notice.MapToTender()
case prior_information.PriorInformationNotice:
return notice.MapToTender()
case business_registration_information.BusinessRegistrationInformationNotice:
return notice.MapToTender()
default:
return t
}
}
// parseDate parses various date formats used in TED XML
func parseDate(dateStr string) (time.Time, error) {
func ParseDate(dateStr string) (time.Time, error) {
if dateStr == "" {
return time.Time{}, fmt.Errorf("empty date string")
}
@@ -58,20 +37,20 @@ func parseDate(dateStr string) (time.Time, error) {
}
// parseDateToUnixMilli converts string date to Unix milliseconds (int64)
func parseDateToUnixMilli(dateStr string) int64 {
func ParseDateToUnix(dateStr string) int64 {
if dateStr == "" {
return 0
}
if parsedTime, err := parseDate(dateStr); err == nil {
return parsedTime.UnixMilli()
if parsedTime, err := ParseDate(dateStr); err == nil {
return parsedTime.Unix()
}
return 0
}
// parseTimeToUnixMilli converts string time to Unix milliseconds (int64)
func parseTimeToUnixMilli(timeStr string) int64 {
// parseTimeToUnix converts string time to Unix milliseconds (int64)
func ParseTimeToUnix(timeStr string) int64 {
if timeStr == "" {
return 0
}
@@ -83,23 +62,23 @@ func parseTimeToUnixMilli(timeStr string) int64 {
timeStr = fmt.Sprintf("%sT%s", today, timeStr)
}
if parsedTime, err := parseDate(timeStr); err == nil {
return parsedTime.UnixMilli()
if parsedTime, err := ParseDate(timeStr); err == nil {
return parsedTime.Unix()
}
return 0
}
// unixMilliToDateString converts Unix milliseconds to date string for TenderID generation
func unixMilliToDateString(unixMilli int64) string {
if unixMilli == 0 {
// unixToDateString converts Unix to date string for TenderID generation
func UnixToDateString(unix int64) string {
if unix == 0 {
return "00000000"
}
return time.UnixMilli(unixMilli).Format("20060102")
return time.Unix(unix, 0).Format("20060102")
}
func calculateSubmissionDeadline(publicationDate time.Time) time.Time {
func CalculateSubmissionDeadline(publicationDate time.Time) time.Time {
deadline := publicationDate
workingHoursAdded := 0
@@ -114,7 +93,7 @@ func calculateSubmissionDeadline(publicationDate time.Time) time.Time {
return deadline
}
func calculateApplicationDeadline(tenderDeadline time.Time) time.Time {
func CalculateApplicationDeadline(tenderDeadline time.Time) time.Time {
applicationDeadline := tenderDeadline
workingDaysSubtracted := 0
@@ -130,7 +109,7 @@ func calculateApplicationDeadline(tenderDeadline time.Time) time.Time {
}
// padOrTruncate pads a string with zeros or truncates it to the specified length
func padOrTruncate(str string, length int) string {
func PadOrTruncate(str string, length int) string {
// Remove any non-alphanumeric characters and convert to uppercase
clean := strings.ToUpper(strings.ReplaceAll(str, "-", ""))
clean = strings.ReplaceAll(clean, " ", "")
@@ -144,7 +123,7 @@ func padOrTruncate(str string, length int) string {
}
// generateTenderURL generates the TED tender URL from NoticePublicationID
func generateTenderURL(noticePublicationID string) string {
func GenerateTenderURL(noticePublicationID string) string {
if noticePublicationID == "" {
return ""
}
@@ -167,7 +146,7 @@ func generateTenderURL(noticePublicationID string) string {
// generateTenderID generates a unique tender ID using the format:
// {Source}{BUYER_CODE}{TED_CODE}{DATE}{LOCATION_CODE}
func generateTenderID(t *tender.Tender) string {
func GenerateTenderID(t *tender.Tender) string {
var parts []string
// Source (TED)
@@ -176,7 +155,7 @@ func generateTenderID(t *tender.Tender) string {
// TED code (Notice Publication ID, first 8 chars)
tedCode := "00000000"
if t.NoticePublicationID != "" {
tedCode = padOrTruncate(t.NoticePublicationID, 8)
tedCode = PadOrTruncate(t.NoticePublicationID, 8)
}
parts = append(parts, tedCode)
@@ -188,7 +167,7 @@ func generateTenderID(t *tender.Tender) string {
// parts = append(parts, buyerCode)
// Date (YYYYMMDD format from issue date)
parts = append(parts, padOrTruncate(unixMilliToDateString(t.IssueDate), 4))
parts = append(parts, PadOrTruncate(UnixToDateString(t.IssueDate), 4))
// Location code (country code + region code, padded to 6 chars)
locationCode := "EU"