merge tenders which have the same procedure id - worker performance fix

This commit is contained in:
Mazyar
2026-05-11 15:10:01 +03:30
parent 8ba667e4f4
commit b4efb97f47
22 changed files with 661 additions and 2234 deletions
+1 -1
View File
@@ -403,7 +403,7 @@ func (h *Handler) GetProfile(c echo.Context) error {
// UpdateProfileKeywords updates customer profile keywords (Mobile)
// @Summary Update customer profile keywords
// @Description Update profile keywords manually and trigger asynchronous GLM enhancement based on customer company information (including country).
// @Description Update profile keywords manually; optional async keyword refresh is reserved for the AI service.
// @Tags Authorization
// @Accept json
// @Produce json
+20 -119
View File
@@ -11,7 +11,6 @@ import (
"time"
"tm/internal/company"
"tm/pkg/glm"
"tm/pkg/logger"
"tm/pkg/notification"
"tm/pkg/redis"
@@ -63,11 +62,10 @@ type customerService struct {
redisClient redis.Client
notification notification.SDK
validator ValidationService
glmSDK *glm.SDK
}
// New creates a new customer service
func NewService(repository Repository, logger logger.Logger, authService authorization.AuthorizationService, companyService company.Service, redisClient redis.Client, notificationSDK notification.SDK, validator ValidationService, glmSDK *glm.SDK) Service {
func NewService(repository Repository, logger logger.Logger, authService authorization.AuthorizationService, companyService company.Service, redisClient redis.Client, notificationSDK notification.SDK, validator ValidationService) Service {
return &customerService{
repository: repository,
logger: logger,
@@ -76,7 +74,6 @@ func NewService(repository Repository, logger logger.Logger, authService authori
redisClient: redisClient,
notification: notificationSDK,
validator: validator,
glmSDK: glmSDK,
}
}
@@ -134,7 +131,7 @@ func (s *customerService) Register(ctx context.Context, form *CreateCustomerForm
Phone: form.Phone,
}
// Generate keywords using GLM AI
// Keyword auto-generation is handled by the AI service when integrated; backend leaves keywords empty on register.
customer.KeywordsStatus = KeywordsStatusInProgress
keywords, err := s.generateKeywords(ctx, customer)
if err != nil {
@@ -1349,99 +1346,11 @@ func (s *customerService) AssignRole(ctx context.Context, customerID string, for
}, nil
}
// generateKeywords generates keywords for a customer using GLM AI based on their information
// generateKeywords is reserved for future integration with the AI service; the backend does not generate keywords.
func (s *customerService) generateKeywords(ctx context.Context, customer *Customer) ([]string, error) {
// If GLM SDK is not available, return empty keywords
if s.glmSDK == nil {
s.logger.Warn("GLM SDK not available, skipping keyword generation", map[string]interface{}{
"customer_id": customer.ID,
})
return []string{}, nil
}
// Build customer information string for AI
var customerInfo strings.Builder
if customer.FullName != nil {
customerInfo.WriteString(fmt.Sprintf("Name: %s\n", *customer.FullName))
}
customerInfo.WriteString(fmt.Sprintf("Type: %s\n", customer.Type))
customerInfo.WriteString(fmt.Sprintf("Role: %s\n", customer.Role))
if customer.Phone != nil {
customerInfo.WriteString(fmt.Sprintf("Phone: %s\n", *customer.Phone))
}
// Get company information if available
if len(customer.Companies) > 0 {
customerInfo.WriteString("Companies: ")
for i, companyID := range customer.Companies {
comp, err := s.companyService.GetByID(ctx, companyID)
if err == nil {
if i > 0 {
customerInfo.WriteString(", ")
}
customerInfo.WriteString(comp.Name)
if comp.Industry != "" {
customerInfo.WriteString(fmt.Sprintf(" (Industry: %s)", comp.Industry))
}
if comp.Address != nil && comp.Address.Country != "" {
customerInfo.WriteString(fmt.Sprintf(" (Country: %s)", comp.Address.Country))
}
if comp.Tags != nil && len(comp.Tags.Keywords) > 0 {
customerInfo.WriteString(fmt.Sprintf(" (Company Keywords: %s)", strings.Join(comp.Tags.Keywords, ", ")))
}
}
}
customerInfo.WriteString("\n")
}
systemPrompt := `You are a keyword extraction assistant for a tender management system.
Analyze the customer information and generate 5-10 relevant keywords that would help match them with appropriate tenders.
Keywords should be:
- Relevant to tender/procurement categories
- Based on customer type, role, and company information
- Professional and specific
- Suitable for matching with tender descriptions
Return ONLY a comma-separated list of keywords, no explanations or additional text.`
userMessage := fmt.Sprintf("Generate keywords for this customer:\n\n%s", customerInfo.String())
s.logger.Info("Generating keywords using GLM AI", map[string]interface{}{
"customer_id": customer.ID,
})
response, err := s.glmSDK.QuickChatWithSystem(ctx, systemPrompt, userMessage)
if err != nil {
s.logger.Error("Failed to generate keywords using GLM AI", map[string]interface{}{
"error": err.Error(),
"customer_id": customer.ID,
})
return []string{}, fmt.Errorf("failed to generate keywords: %w", err)
}
// Parse comma-separated keywords
keywordsStr := strings.TrimSpace(response)
if keywordsStr == "" {
return []string{}, nil
}
// Split by comma and clean up
keywordList := strings.Split(keywordsStr, ",")
keywords := make([]string, 0, len(keywordList))
for _, kw := range keywordList {
kw = strings.TrimSpace(kw)
if kw != "" {
keywords = append(keywords, kw)
}
}
s.logger.Info("Keywords generated successfully", map[string]interface{}{
"customer_id": customer.ID,
"keywords": keywords,
"count": len(keywords),
})
return keywords, nil
_ = ctx
_ = customer
return []string{}, nil
}
func (s *customerService) processKeywordsAsync(customerID string) {
@@ -1456,34 +1365,26 @@ func (s *customerService) processKeywordsAsync(customerID string) {
return
}
if s.glmSDK == nil {
s.logger.Info("GLM SDK not available, keeping manual keywords", map[string]interface{}{
keywords, err := s.generateKeywords(ctx, cust)
if err != nil {
s.logger.Warn("Failed to process keywords after manual update", map[string]interface{}{
"error": err.Error(),
"customer_id": customerID,
})
cust.KeywordsStatus = KeywordsStatusFailed
} else if len(keywords) > 0 {
cust.Keywords = keywords
cust.KeywordsStatus = KeywordsStatusReady
} else {
s.logger.Debug("No auto-generated keywords from backend, keeping existing keywords", map[string]interface{}{
"customer_id": customerID,
})
cust.KeywordsStatus = KeywordsStatusReady
} else {
keywords, err := s.generateKeywords(ctx, cust)
if err != nil {
s.logger.Warn("Failed to process keywords after manual update", map[string]interface{}{
"error": err.Error(),
"customer_id": customerID,
})
cust.KeywordsStatus = KeywordsStatusFailed
} else if len(keywords) > 0 {
cust.Keywords = keywords
cust.KeywordsStatus = KeywordsStatusReady
} else {
s.logger.Warn("GLM returned empty keywords, keeping manual keywords", map[string]interface{}{
"customer_id": customerID,
})
cust.KeywordsStatus = KeywordsStatusReady
}
}
err = s.repository.Update(ctx, cust)
if err != nil {
if updateErr := s.repository.Update(ctx, cust); updateErr != nil {
s.logger.Error("Failed to update customer keywords status", map[string]interface{}{
"error": err.Error(),
"error": updateErr.Error(),
"customer_id": customerID,
})
} else {