added AI auto-generated keywords to customer profile
This commit is contained in:
@@ -21,6 +21,7 @@ type SearchForm struct {
|
||||
CountryCodes []string `query:"country_codes" valid:"optional"`
|
||||
RegionCodes []string `query:"region_codes" valid:"optional"`
|
||||
CompanyID *string `query:"company_id" valid:"optional"`
|
||||
CustomerID *string `query:"customer_id" valid:"optional"`
|
||||
Status []string `query:"status" valid:"optional"`
|
||||
Classifications []string `query:"classifications" valid:"optional"`
|
||||
MinEstimatedValue *float64 `query:"min_estimated_value" valid:"optional"`
|
||||
|
||||
@@ -216,13 +216,19 @@ func (h *TenderHandler) GetPublicTenders(c echo.Context) error {
|
||||
|
||||
form.Status = []string{string(TenderStatusActive)}
|
||||
|
||||
// Get company ID from customer context for automatic matching
|
||||
// Get company ID and customer ID from customer context for automatic matching
|
||||
var companyID *string
|
||||
if customerCompanyID, ok := c.Get("company_id").(string); ok {
|
||||
companyID = &customerCompanyID
|
||||
}
|
||||
form.CompanyID = companyID
|
||||
|
||||
var customerID *string
|
||||
if customerIDStr, ok := c.Get("customer_id").(string); ok {
|
||||
customerID = &customerIDStr
|
||||
}
|
||||
form.CustomerID = customerID
|
||||
|
||||
result, err := h.service.Search(c.Request().Context(), form, response.NewPagination(c))
|
||||
if err != nil {
|
||||
return response.InternalServerError(c, "Failed to retrieve tenders")
|
||||
@@ -277,9 +283,14 @@ func (h *TenderHandler) RecommendTenders(c echo.Context) error {
|
||||
if customerCompanyID, ok := c.Get("company_id").(string); ok {
|
||||
companyID = &customerCompanyID
|
||||
}
|
||||
|
||||
form.CompanyID = companyID
|
||||
|
||||
var customerID *string
|
||||
if customerIDStr, ok := c.Get("customer_id").(string); ok {
|
||||
customerID = &customerIDStr
|
||||
}
|
||||
form.CustomerID = customerID
|
||||
|
||||
result, err := h.service.Recommend(c.Request().Context(), form, response.NewPagination(c))
|
||||
if err != nil {
|
||||
return response.InternalServerError(c, "Failed to retrieve tenders")
|
||||
|
||||
+86
-24
@@ -3,8 +3,10 @@ package tender
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
"tm/internal/company"
|
||||
"tm/internal/customer"
|
||||
"tm/pkg/logger"
|
||||
"tm/pkg/response"
|
||||
)
|
||||
@@ -26,17 +28,19 @@ type Service interface {
|
||||
|
||||
// tenderService implements TenderService interface
|
||||
type tenderService struct {
|
||||
repository TenderRepository
|
||||
companyService company.Service
|
||||
logger logger.Logger
|
||||
repository TenderRepository
|
||||
companyService company.Service
|
||||
customerService customer.Service
|
||||
logger logger.Logger
|
||||
}
|
||||
|
||||
// NewService creates a new tender service
|
||||
func NewService(repository TenderRepository, companyService company.Service, logger logger.Logger) Service {
|
||||
func NewService(repository TenderRepository, companyService company.Service, customerService customer.Service, logger logger.Logger) Service {
|
||||
return &tenderService{
|
||||
repository: repository,
|
||||
companyService: companyService,
|
||||
logger: logger,
|
||||
repository: repository,
|
||||
companyService: companyService,
|
||||
customerService: customerService,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,8 +160,8 @@ func (s *tenderService) GetDocumentSummaries(ctx context.Context, id string) ([]
|
||||
}
|
||||
|
||||
s.logger.Info("Retrieved document summaries for tender", map[string]interface{}{
|
||||
"tender_id": id,
|
||||
"summaries_count": len(tender.DocumentSummaries),
|
||||
"tender_id": id,
|
||||
"summaries_count": len(tender.DocumentSummaries),
|
||||
})
|
||||
|
||||
return tender.DocumentSummaries, nil
|
||||
@@ -166,13 +170,41 @@ func (s *tenderService) GetDocumentSummaries(ctx context.Context, id string) ([]
|
||||
// ListTenders retrieves tenders with pagination and filtering
|
||||
func (s *tenderService) Search(ctx context.Context, form *SearchForm, pagination *response.Pagination) (*SearchResponse, error) {
|
||||
s.logger.Info("Listing tenders", map[string]interface{}{
|
||||
"limit": pagination.Limit,
|
||||
"offset": pagination.Offset,
|
||||
"company_id": form.CompanyID,
|
||||
"from": form.DeadlineFrom,
|
||||
"to": form.DeadlineTo,
|
||||
"limit": pagination.Limit,
|
||||
"offset": pagination.Offset,
|
||||
"company_id": form.CompanyID,
|
||||
"customer_id": form.CustomerID,
|
||||
"from": form.DeadlineFrom,
|
||||
"to": form.DeadlineTo,
|
||||
})
|
||||
|
||||
// If customer ID is provided, get customer keywords and add to search
|
||||
if form.CustomerID != nil && *form.CustomerID != "" {
|
||||
customerResp, err := s.customerService.GetByID(ctx, *form.CustomerID)
|
||||
if err == nil && customerResp != nil {
|
||||
// Only use keywords if status is ready
|
||||
if customerResp.KeywordsStatus == "ready" && len(customerResp.Keywords) > 0 {
|
||||
// Combine customer keywords with existing search query
|
||||
keywordsQuery := strings.Join(customerResp.Keywords, " ")
|
||||
if form.Search != nil && *form.Search != "" {
|
||||
combinedSearch := *form.Search + " " + keywordsQuery
|
||||
form.Search = &combinedSearch
|
||||
} else {
|
||||
form.Search = &keywordsQuery
|
||||
}
|
||||
s.logger.Info("Using customer keywords for search", map[string]interface{}{
|
||||
"customer_id": *form.CustomerID,
|
||||
"keywords": customerResp.Keywords,
|
||||
})
|
||||
} else {
|
||||
s.logger.Info("Customer keywords not ready, skipping keyword-based search", map[string]interface{}{
|
||||
"customer_id": *form.CustomerID,
|
||||
"keywords_status": customerResp.KeywordsStatus,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tenders, total, err := s.repository.Search(ctx, form, pagination)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to list tenders", map[string]interface{}{
|
||||
@@ -240,20 +272,50 @@ func (s *tenderService) Search(ctx context.Context, form *SearchForm, pagination
|
||||
// Recommend retrieves tenders with pagination and filtering
|
||||
func (s *tenderService) Recommend(ctx context.Context, form *SearchForm, pagination *response.Pagination) (*SearchResponse, error) {
|
||||
s.logger.Info("Recommend tenders", map[string]interface{}{
|
||||
"company_id": form.CompanyID,
|
||||
"company_id": form.CompanyID,
|
||||
"customer_id": form.CustomerID,
|
||||
})
|
||||
|
||||
company, err := s.companyService.GetByID(ctx, *form.CompanyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get company", map[string]interface{}{
|
||||
"company_id": form.CompanyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, fmt.Errorf("failed to get company: %w", err)
|
||||
form.Status = []string{string(TenderStatusActive)}
|
||||
|
||||
// Priority: Use customer keywords if available, otherwise use company CPV codes
|
||||
if form.CustomerID != nil && *form.CustomerID != "" {
|
||||
customerResp, err := s.customerService.GetByID(ctx, *form.CustomerID)
|
||||
if err == nil && customerResp != nil {
|
||||
// Only use keywords if status is ready
|
||||
if customerResp.KeywordsStatus == "ready" && len(customerResp.Keywords) > 0 {
|
||||
// Use customer keywords for recommendation
|
||||
keywordsQuery := strings.Join(customerResp.Keywords, " ")
|
||||
form.Search = &keywordsQuery
|
||||
s.logger.Info("Using customer keywords for recommendation", map[string]interface{}{
|
||||
"customer_id": *form.CustomerID,
|
||||
"keywords": customerResp.Keywords,
|
||||
})
|
||||
} else {
|
||||
s.logger.Info("Customer keywords not ready, falling back to company CPV codes", map[string]interface{}{
|
||||
"customer_id": *form.CustomerID,
|
||||
"keywords_status": customerResp.KeywordsStatus,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
form.Status = []string{string(TenderStatusActive)}
|
||||
form.Classifications = company.Tags.CPVCodes
|
||||
// Fallback to company CPV codes if no customer keywords
|
||||
if form.Search == nil || *form.Search == "" {
|
||||
if form.CompanyID != nil && *form.CompanyID != "" {
|
||||
company, err := s.companyService.GetByID(ctx, *form.CompanyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get company", map[string]interface{}{
|
||||
"company_id": form.CompanyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, fmt.Errorf("failed to get company: %w", err)
|
||||
}
|
||||
if company.Tags != nil && len(company.Tags.CPVCodes) > 0 {
|
||||
form.Classifications = company.Tags.CPVCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tenders, total, err := s.repository.Search(ctx, form, pagination)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user