Refactor Worker Initialization to Integrate GLM SDK

- Updated the worker initialization process to include the new GLM SDK, enhancing the worker's capabilities for translation tasks.
- Modified the InitWorker function and NewNoticeWorker constructor to accept the GLM service, ensuring a cohesive integration.
- Implemented the GLM service initialization and logging for successful setup, improving maintainability and usability.
- Updated the NoticeWorker to utilize the GLM SDK for translating notice titles and descriptions, enhancing functionality and user experience.
This commit is contained in:
n.nakhostin
2025-11-04 16:51:45 +03:30
parent a5d3a94c97
commit fafccd0d74
10 changed files with 379 additions and 134 deletions
+115 -14
View File
@@ -2,30 +2,33 @@ package workers
import (
"context"
"strings"
"time"
"tm/internal/notice"
"tm/internal/tender"
"tm/pkg/glm"
"tm/pkg/logger"
"tm/pkg/mongo"
"tm/pkg/notification"
"tm/pkg/ollama"
)
type NoticeWorker struct {
Mongo *mongo.ConnectionManager
Logger logger.Logger
Notify notification.SDK
Ollama *ollama.SDK
Notify *notification.SDK
NoticeRepo notice.Repository
TenderRepo tender.TenderRepository
GLM *glm.SDK
}
func NewNoticeWorker(mongo *mongo.ConnectionManager, logger logger.Logger, notify notification.SDK, noticeRepo notice.Repository, tenderRepo tender.TenderRepository) *NoticeWorker {
func NewNoticeWorker(mongo *mongo.ConnectionManager, logger logger.Logger, notify *notification.SDK, noticeRepo notice.Repository, tenderRepo tender.TenderRepository, glmService *glm.SDK) *NoticeWorker {
return &NoticeWorker{
Mongo: mongo,
Logger: logger,
Notify: notify,
NoticeRepo: noticeRepo,
TenderRepo: tenderRepo,
GLM: glmService,
}
}
@@ -52,12 +55,7 @@ func (w *NoticeWorker) Run() {
"notice": n.ID.Hex(),
})
t, err := w.TenderRepo.GetByNoticePublicationID(context.Background(), n.NoticePublicationID)
if err == nil {
continue
}
err = w.ToTender(&n, t)
t, err := w.ToTender(&n)
if err != nil {
w.Logger.Error("Failed to create tender", map[string]interface{}{
"error": err.Error(),
@@ -80,13 +78,33 @@ func (w *NoticeWorker) Run() {
})
}
}
n.ProcessingMetadata.Processed = true
n.ProcessingMetadata.ProcessedAt = time.Now().Unix()
err = w.NoticeRepo.Update(context.Background(), &n)
if err != nil {
w.Logger.Error("Failed to update notice", map[string]interface{}{
"error": err.Error(),
})
}
w.Logger.Info("Notice processed", map[string]interface{}{
"notice": n.ID.Hex(),
})
}
skip += limit
}
}
func (w *NoticeWorker) ToTender(n *notice.Notice, t *tender.Tender) error {
func (w *NoticeWorker) ToTender(n *notice.Notice) (*tender.Tender, error) {
t, err := w.TenderRepo.GetByNoticePublicationID(context.Background(), n.NoticePublicationID)
if err != nil {
w.Logger.Info("New tender raised", map[string]interface{}{
"notice_publication_id": n.NoticePublicationID,
"country_code": n.CountryCode,
})
t = new(tender.Tender)
}
// Buyer Organization
buyerOrg := &tender.Organization{}
if n.BuyerOrganization != nil {
@@ -223,9 +241,32 @@ func (w *NoticeWorker) ToTender(n *notice.Notice, t *tender.Tender) error {
}
}
title, err := w.GLM.Translate(context.Background(), n.Title, n.NoticeLanguageCode, "en")
if err != nil {
w.Logger.Error("Failed to translate title", map[string]interface{}{
"notice_publication_id": n.NoticePublicationID,
"country_code": n.CountryCode,
"content": n.Title,
"error": err.Error(),
})
title = n.Title
// return err
}
description, err := w.GLM.Translate(context.Background(), n.Description, n.NoticeLanguageCode, "en")
if err != nil {
w.Logger.Error("Failed to translate description", map[string]interface{}{
"notice_publication_id": n.NoticePublicationID,
"country_code": n.CountryCode,
"content": n.Description,
"error": err.Error(),
})
description = n.Description
// return err
}
t.Title = title
t.Description = description
t.NoticePublicationID = n.NoticePublicationID
t.Title = n.Title
t.Description = n.Description
t.ProcurementTypeCode = n.ProcurementTypeCode
t.ProcedureCode = n.ProcedureCode
t.EstimatedValue = n.EstimatedValue
@@ -268,5 +309,65 @@ func (w *NoticeWorker) ToTender(n *notice.Notice, t *tender.Tender) error {
t.WinningTenderer = winningTenderer
t.Modifications = modifications
t.AwardedEntities = awardedEntities
return nil
t.TenderID = GenerateTenderID(n)
return t, nil
}
// generateTenderID generates a unique tender ID using the format:
// {Source}{BUYER_CODE}{TED_CODE}{DATE}{LOCATION_CODE}
func GenerateTenderID(t *notice.Notice) string {
var parts []string
// Source (TED)
parts = append(parts, "1")
// TED code (Notice Publication ID, first 8 chars)
tedCode := "00000000"
if t.NoticePublicationID != "" {
tedCode = PadOrTruncate(t.NoticePublicationID, 8)
}
parts = append(parts, tedCode)
// Buyer code (first 8 chars of buyer organization ID, or 8 zeros if not available)
// buyerCode := "00000000"
// if t.BuyerOrganization != nil && t.BuyerOrganization.ID != "" {
// buyerCode = padOrTruncate(t.BuyerOrganization.ID, 8)
// }
// parts = append(parts, buyerCode)
// Date (YYYYMMDD format from issue date)
parts = append(parts, PadOrTruncate(UnixToDateString(t.IssueDate), 4))
// Location code (country code + region code, padded to 6 chars)
locationCode := "EU"
if t.CountryCode != "" {
locationCode = t.CountryCode
}
parts = append(parts, locationCode)
return strings.Join(parts, "")
}
// padOrTruncate pads a string with zeros or truncates it to the specified length
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, " ", "")
if len(clean) >= length {
return clean[:length]
}
// Pad with zeros
return clean + strings.Repeat("0", length-len(clean))
}
// unixToDateString converts Unix to date string for TenderID generation
func UnixToDateString(unix int64) string {
if unix == 0 {
return "00000000"
}
return time.Unix(unix, 0).Format("20060102")
}