From 8f909618d88be64b5e887b50552b34ebfc7fc0dc Mon Sep 17 00:00:00 2001 From: "n.nakhostin" Date: Tue, 2 Sep 2025 11:31:59 +0330 Subject: [PATCH] Refactor Feedback Service to Include Tender Information in Responses - Updated the FeedbackService to include a new dependency on TenderService, allowing feedback responses to include associated tender details. - Modified the ListFeedback method to return a new FeedbackListWithTenderResponse type, which includes feedback along with tender information. - Enhanced the feedback entity and form structures to support the new response format, improving the API's capability to provide comprehensive feedback data. - Adjusted the main application initialization to reflect the changes in the feedback service dependencies. --- cmd/web/main.go | 2 +- internal/feedback/entity.go | 7 ----- internal/feedback/form.go | 61 ++++++++++++++++++++++++++++++++++++ internal/feedback/service.go | 49 +++++++++++++++++++++++------ internal/tender/handler.go | 10 +++--- 5 files changed, 106 insertions(+), 23 deletions(-) diff --git a/cmd/web/main.go b/cmd/web/main.go index d3493d7..fb498f3 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -127,7 +127,7 @@ func main() { companyService := company.NewCompanyService(companyRepository, logger) customerService := customer.NewCustomerService(customerRepository, logger, customerAuthService, companyService) tenderService := tender.NewTenderService(tenderRepository, companyService, logger) - feedbackService := feedback.NewFeedbackService(feedbackRepo, logger) + feedbackService := feedback.NewFeedbackService(feedbackRepo, tenderService, logger) tenderApprovalService := tender_approval.NewTenderApprovalService(tenderApprovalRepository, tenderService, logger) logger.Info("Services initialized successfully", map[string]interface{}{ "services": []string{"customer", "user", "company", "tender", "feedback", "tender_approval"}, diff --git a/internal/feedback/entity.go b/internal/feedback/entity.go index 3691b5f..57f1729 100644 --- a/internal/feedback/entity.go +++ b/internal/feedback/entity.go @@ -3,7 +3,6 @@ package feedback import ( "time" "tm/pkg/mongo" - "tm/pkg/response" ) // FeedbackType represents the type of feedback @@ -43,12 +42,6 @@ type FeedbackSearchCriteria struct { Offset int `json:"offset,omitempty"` } -// FeedbackListResponse represents a paginated list of feedback -type FeedbackListResponse struct { - Feedback []*FeedbackResponse `json:"feedback"` - Meta *response.Meta `json:"meta"` -} - // GetID returns the feedback ID func (f *Feedback) GetID() string { return f.ID.Hex() diff --git a/internal/feedback/form.go b/internal/feedback/form.go index 5393e95..16e61cb 100644 --- a/internal/feedback/form.go +++ b/internal/feedback/form.go @@ -2,6 +2,7 @@ package feedback import ( "time" + "tm/pkg/response" ) // ListFeedbackForm represents the form for listing feedback @@ -30,6 +31,53 @@ type FeedbackResponse struct { CompanyId *string `json:"company_id"` } +// FeedbackListResponse represents a paginated list of feedback +type FeedbackListResponse struct { + Feedback []*FeedbackResponse `json:"feedback"` + Meta *response.Meta `json:"meta"` +} + +// FeedbackListResponse represents a paginated list of feedback +type FeedbackListWithTenderResponse struct { + Feedback []*FeedbackWithTenderResponse `json:"feedback"` + Meta *response.Meta `json:"meta"` +} +type FeedbackWithTenderResponse struct { + ID string `json:"id"` + FeedbackType FeedbackType `json:"feedback_type"` + UpdatedAt int64 `json:"updated_at"` + CreatedAt int64 `json:"created_at"` + TenderID string `json:"tender_id"` + CustomerID *string `json:"customer_id"` + CompanyId *string `json:"company_id"` + Tender *tenderDetails `json:"tender"` +} + +// tenderDetails represents essential tender information for the response +type ( + tenderDetails struct { + ID string `json:"id"` + NoticePublicationID string `json:"notice_publication_id"` + PublicationDate int64 `json:"publication_date"` + Title string `json:"title"` + Description string `json:"description"` + ProcurementTypeCode string `json:"procurement_type_code"` + ProcedureCode string `json:"procedure_code"` + EstimatedValue float64 `json:"estimated_value"` + Currency string `json:"currency"` + Duration string `json:"duration"` + DurationUnit string `json:"duration_unit"` + TenderDeadline int64 `json:"tender_deadline"` + SubmissionDeadline int64 `json:"submission_deadline"` + CountryCode string `json:"country_code"` + BuyerOrganization *organizationResponse `json:"buyer_organization"` + Status string `json:"status"` + } + organizationResponse struct { + Name string `json:"name"` + } +) + // CompanyFeedbackStatsResponse represents the response for company feedback statistics type CompanyFeedbackStatsResponse struct { CompanyID string `json:"company_id"` @@ -68,3 +116,16 @@ func (f *Feedback) ToResponse() *FeedbackResponse { CreatedAt: f.CreatedAt, } } + +func (f *Feedback) ToResponseWithTender(tender *tenderDetails) *FeedbackWithTenderResponse { + return &FeedbackWithTenderResponse{ + ID: f.ID.Hex(), + FeedbackType: f.FeedbackType, + TenderID: f.TenderID, + CustomerID: f.CustomerID, + CompanyId: f.CompanyID, + UpdatedAt: f.UpdatedAt, + CreatedAt: f.CreatedAt, + Tender: tender, + } +} diff --git a/internal/feedback/service.go b/internal/feedback/service.go index 1987adf..10045f3 100644 --- a/internal/feedback/service.go +++ b/internal/feedback/service.go @@ -2,6 +2,7 @@ package feedback import ( "context" + "tm/internal/tender" "tm/pkg/logger" "tm/pkg/response" ) @@ -10,7 +11,7 @@ import ( type FeedbackService interface { ToggleFeedback(ctx context.Context, req ToggleFeedbackForm, customerID *string, companyID *string) (*FeedbackResponse, error) GetFeedback(ctx context.Context, id string) (*FeedbackResponse, error) - ListFeedback(ctx context.Context, criteria FeedbackSearchCriteria, limit, offset int) (*FeedbackListResponse, error) + ListFeedback(ctx context.Context, criteria FeedbackSearchCriteria, limit, offset int) (*FeedbackListWithTenderResponse, error) DeleteFeedback(ctx context.Context, id string) error GetFeedbackByTenderID(ctx context.Context, tenderID, companyID string) (*FeedbackResponse, error) CompanyFeedbackStats(ctx context.Context, companyID string) (*CompanyFeedbackStatsResponse, error) @@ -18,15 +19,17 @@ type FeedbackService interface { // feedbackService implements FeedbackService interface type feedbackService struct { - feedbackRepo Repository - logger logger.Logger + feedbackRepo Repository + tenderService tender.TenderService + logger logger.Logger } // NewFeedbackService creates a new feedback service -func NewFeedbackService(feedbackRepo Repository, logger logger.Logger) FeedbackService { +func NewFeedbackService(feedbackRepo Repository, tenderService tender.TenderService, logger logger.Logger) FeedbackService { return &feedbackService{ - feedbackRepo: feedbackRepo, - logger: logger, + feedbackRepo: feedbackRepo, + tenderService: tenderService, + logger: logger, } } @@ -108,7 +111,7 @@ func (s *feedbackService) GetFeedback(ctx context.Context, id string) (*Feedback return feedback.ToResponse(), nil } -func (s *feedbackService) ListFeedback(ctx context.Context, criteria FeedbackSearchCriteria, limit, offset int) (*FeedbackListResponse, error) { +func (s *feedbackService) ListFeedback(ctx context.Context, criteria FeedbackSearchCriteria, limit, offset int) (*FeedbackListWithTenderResponse, error) { feedbacks, total, err := s.feedbackRepo.List(ctx, criteria, limit, offset) if err != nil { s.logger.Error("Failed to list feedback", map[string]interface{}{ @@ -128,11 +131,37 @@ func (s *feedbackService) ListFeedback(ctx context.Context, criteria FeedbackSea Pages: int((total + int64(limit) - 1) / int64(limit)), } - result := make([]*FeedbackResponse, len(feedbacks)) + result := make([]*FeedbackWithTenderResponse, len(feedbacks)) for i, feedback := range feedbacks { - result[i] = feedback.ToResponse() + tender, err := s.tenderService.GetTenderByID(ctx, feedback.TenderID) + if err != nil { + s.logger.Error("Failed to get tender", map[string]interface{}{ + "tender_id": feedback.TenderID, + "error": err.Error(), + }) + return nil, err + } + resp := feedback.ToResponseWithTender(&tenderDetails{ + ID: tender.ID, + NoticePublicationID: tender.NoticePublicationID, + PublicationDate: tender.PublicationDate, + Title: tender.Title, + Description: tender.Description, + ProcurementTypeCode: tender.ProcurementTypeCode, + ProcedureCode: tender.ProcedureCode, + EstimatedValue: tender.EstimatedValue, + Currency: tender.Currency, + Duration: tender.Duration, + DurationUnit: tender.DurationUnit, + TenderDeadline: tender.TenderDeadline, + SubmissionDeadline: tender.SubmissionDeadline, + CountryCode: tender.CountryCode, + BuyerOrganization: &organizationResponse{Name: tender.BuyerOrganization.Name}, + Status: string(tender.Status), + }) + result[i] = resp } - return &FeedbackListResponse{ + return &FeedbackListWithTenderResponse{ Feedback: result, Meta: meta, }, nil diff --git a/internal/tender/handler.go b/internal/tender/handler.go index 678c55f..7f4454e 100644 --- a/internal/tender/handler.go +++ b/internal/tender/handler.go @@ -347,21 +347,21 @@ func (h *TenderHandler) RecommendTenders(c echo.Context) error { companyID = &customerCompanyID } - from := int64(0) + var from *int64 if fromParam := c.QueryParam("publication_from"); fromParam != "" { if parsed, err := strconv.ParseInt(fromParam, 10, 64); err == nil { - from = parsed + from = &parsed } } - to := int64(0) + var to *int64 if toParam := c.QueryParam("publication_to"); toParam != "" { if parsed, err := strconv.ParseInt(toParam, 10, 64); err == nil { - to = parsed + to = &parsed } } - result, err := h.service.RecommendTenders(c.Request().Context(), companyID, &from, &to, limit, offset) + result, err := h.service.RecommendTenders(c.Request().Context(), companyID, from, to, limit, offset) if err != nil { return response.InternalServerError(c, "Failed to retrieve tenders") }