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.
This commit is contained in:
n.nakhostin
2025-09-02 11:31:59 +03:30
parent c684a12155
commit 8f909618d8
5 changed files with 106 additions and 23 deletions
-7
View File
@@ -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()
+61
View File
@@ -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,
}
}
+39 -10
View File
@@ -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
+5 -5
View File
@@ -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")
}