Document scraper integration field fix

This commit is contained in:
m.nazemi
2026-05-02 17:44:56 +03:30
parent 81191656df
commit 0bd5e41b70
4 changed files with 11 additions and 66 deletions
+1 -1
View File
@@ -259,7 +259,7 @@ func main() {
tedConfig := buildTEDConfig(&conf.TED) tedConfig := buildTEDConfig(&conf.TED)
scraperService := scraper.NewServiceWithTED(conf.Scraper.BaseURL, conf.Scraper.Timeout, logger, mongoManager, noticeRepository, notificationSDK, tedConfig) scraperService := scraper.NewServiceWithTED(conf.Scraper.BaseURL, conf.Scraper.Timeout, logger, mongoManager, noticeRepository, notificationSDK, tedConfig)
kanbanService := kanban.NewService(boardRepository, columnRepository, cardRepository, logger) kanbanService := kanban.NewService(boardRepository, columnRepository, cardRepository, logger)
documentScraperService := document_scraper.NewService(tenderRepository, noticeRepository, logger) documentScraperService := document_scraper.NewService(tenderRepository, logger)
logger.Info("Services initialized successfully", map[string]interface{}{ logger.Info("Services initialized successfully", map[string]interface{}{
"services": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag", "notification", "contact", "cms", "scraper", "kanban", "document_scraper"}, "services": []string{"customer", "user", "company", "category", "tender", "feedback", "tender_approval", "inquiry", "flag", "notification", "contact", "cms", "scraper", "kanban", "document_scraper"},
}) })
-1
View File
@@ -18,7 +18,6 @@ type DocumentScraperTenderResponse struct {
DocumentURL string `json:"document_url"` DocumentURL string `json:"document_url"`
Title string `json:"title"` Title string `json:"title"`
Description string `json:"description"` Description string `json:"description"`
ParsedXML interface{} `json:"parsed_xml"`
} }
// DocumentScraperListResponse represents the paginated list response // DocumentScraperListResponse represents the paginated list response
+2 -2
View File
@@ -24,7 +24,7 @@ func NewHandler(service Service, logger logger.Logger) *Handler {
// ListPendingTenders retrieves tenders that need document scraping // ListPendingTenders retrieves tenders that need document scraping
// @Summary List pending tenders for document scraping // @Summary List pending tenders for document scraping
// @Description Retrieve tenders that have not yet been scraped for documents, including notice ID, title, description, and parsed XML // @Description Retrieve tenders that have not yet been scraped for documents, including notice ID, title, description
// @Tags Document-Scraper // @Tags Document-Scraper
// @Produce json // @Produce json
// @Param limit query int false "Number of items per page (default: 20, max: 100)" // @Param limit query int false "Number of items per page (default: 20, max: 100)"
@@ -62,7 +62,7 @@ func (h *Handler) ListPendingTenders(c echo.Context) error {
// GetTenderByNoticeID retrieves a specific tender by its notice publication ID // GetTenderByNoticeID retrieves a specific tender by its notice publication ID
// @Summary Get tender by notice ID for document scraping // @Summary Get tender by notice ID for document scraping
// @Description Retrieve a specific tender by its notice publication ID, including notice ID, title, description, and parsed XML // @Description Retrieve a specific tender by its notice publication ID, including notice ID, title, description
// @Tags Document-Scraper // @Tags Document-Scraper
// @Produce json // @Produce json
// @Param notice_id path string true "Notice Publication ID" // @Param notice_id path string true "Notice Publication ID"
+3 -57
View File
@@ -2,9 +2,7 @@ package document_scraper
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"tm/internal/notice"
"tm/internal/tender" "tm/internal/tender"
"tm/pkg/logger" "tm/pkg/logger"
"tm/pkg/response" "tm/pkg/response"
@@ -21,84 +19,32 @@ type Service interface {
type service struct { type service struct {
tenderRepo tender.TenderRepository tenderRepo tender.TenderRepository
noticeRepo notice.Repository
tedParser *ted.TEDParser tedParser *ted.TEDParser
logger logger.Logger logger logger.Logger
} }
// NewService creates a new document scraper service // NewService creates a new document scraper service
func NewService(tenderRepo tender.TenderRepository, noticeRepo notice.Repository, logger logger.Logger) Service { func NewService(tenderRepo tender.TenderRepository, logger logger.Logger) Service {
return &service{ return &service{
tenderRepo: tenderRepo, tenderRepo: tenderRepo,
noticeRepo: noticeRepo,
tedParser: ted.NewTEDParser(), tedParser: ted.NewTEDParser(),
logger: logger, logger: logger,
} }
} }
// parseXMLToJSON converts raw XML content into a structured JSON object // buildTenderResponse creates a DocumentScraperTenderResponse from a tender
func (s *service) parseXMLToJSON(xmlContent string) interface{} { func (s *service) buildTenderResponse(_ context.Context, t *tender.Tender) *DocumentScraperTenderResponse {
if xmlContent == "" {
return nil
}
parsedDoc, _, _, err := s.tedParser.ParseXML([]byte(xmlContent))
if err != nil {
s.logger.Warn("Failed to parse XML to JSON, returning raw XML string", map[string]interface{}{
"error": err.Error(),
})
return xmlContent
}
// Convert to a generic map to clean up the JSON output
jsonBytes, err := json.Marshal(parsedDoc)
if err != nil {
s.logger.Warn("Failed to marshal parsed XML to JSON, returning raw XML string", map[string]interface{}{
"error": err.Error(),
})
return xmlContent
}
var result interface{}
if err := json.Unmarshal(jsonBytes, &result); err != nil {
s.logger.Warn("Failed to unmarshal parsed XML, returning raw XML string", map[string]interface{}{
"error": err.Error(),
})
return xmlContent
}
return result
}
// buildTenderResponse creates a DocumentScraperTenderResponse from a tender and its notice
func (s *service) buildTenderResponse(ctx context.Context, t *tender.Tender) *DocumentScraperTenderResponse {
parsedXML := interface{}(nil)
documentURL := t.DocumentURI documentURL := t.DocumentURI
if documentURL == "" { if documentURL == "" {
documentURL = t.TenderURL documentURL = t.TenderURL
} }
// Try to get the parsed XML from the corresponding notice
n, err := s.noticeRepo.GetByContractNoticeID(ctx, t.ContractNoticeID)
if err != nil {
s.logger.Warn("Failed to get notice for parsed XML", map[string]interface{}{
"contract_notice_id": t.ContractNoticeID,
"error": err.Error(),
})
} else if n != nil {
parsedXML = s.parseXMLToJSON(n.ContentXML)
if documentURL == "" {
documentURL = n.DocumentURI
}
}
return &DocumentScraperTenderResponse{ return &DocumentScraperTenderResponse{
ID: t.ID.Hex(), ID: t.ID.Hex(),
NoticePublicationID: t.NoticePublicationID, NoticePublicationID: t.NoticePublicationID,
DocumentURL: documentURL, DocumentURL: documentURL,
Title: t.Title, Title: t.Title,
Description: t.Description, Description: t.Description,
ParsedXML: parsedXML,
} }
} }