Refactor Feedback Module for Consistency and Clarity
- Updated feedback repository and service methods to use a consistent naming convention, changing `NewTenderRepository` and similar methods to `NewRepository`. - Refactored feedback handler methods to improve clarity by renaming methods such as `ListFeedback` to `Search` and `GetFeedback` to `Get`. - Enhanced feedback response structures to include detailed company and tender information, improving the clarity of feedback data returned to API consumers. - Updated Swagger documentation to reflect changes in feedback response structures and endpoint paths, ensuring accurate representation of the API for consumers.
This commit is contained in:
+163
-67
@@ -2,44 +2,48 @@ package feedback
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tm/internal/company"
|
||||
"tm/internal/tender"
|
||||
"tm/pkg/logger"
|
||||
"tm/pkg/response"
|
||||
)
|
||||
|
||||
// FeedbackService interface defines feedback business logic methods
|
||||
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) (*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)
|
||||
type Service interface {
|
||||
Toggle(ctx context.Context, req ToggleFeedbackForm, customerID *string, companyID *string) (*FeedbackResponse, error)
|
||||
Search(ctx context.Context, criteria SearchForm, pagination *response.Pagination) (*FeedbackListResponse, error)
|
||||
Get(ctx context.Context, id string) (*FeedbackResponse, error)
|
||||
GetByTenderID(ctx context.Context, tenderID, companyID string) (*FeedbackResponse, error)
|
||||
Delete(ctx context.Context, id string) error
|
||||
CompanyStats(ctx context.Context, companyID string) (*StatsResponse, error)
|
||||
getDetails(ctx context.Context, tenderID, companyID string) (*tenderResponse, *companyResponse, error)
|
||||
}
|
||||
|
||||
// feedbackService implements FeedbackService interface
|
||||
type feedbackService struct {
|
||||
feedbackRepo Repository
|
||||
tenderService tender.Service
|
||||
logger logger.Logger
|
||||
feedbackRepo Repository
|
||||
tenderService tender.Service
|
||||
companyService company.Service
|
||||
logger logger.Logger
|
||||
}
|
||||
|
||||
// NewFeedbackService creates a new feedback service
|
||||
func NewFeedbackService(feedbackRepo Repository, tenderService tender.Service, logger logger.Logger) FeedbackService {
|
||||
// NewService creates a new feedback service
|
||||
func NewService(feedbackRepo Repository, tenderService tender.Service, companyService company.Service, logger logger.Logger) Service {
|
||||
return &feedbackService{
|
||||
feedbackRepo: feedbackRepo,
|
||||
tenderService: tenderService,
|
||||
logger: logger,
|
||||
feedbackRepo: feedbackRepo,
|
||||
tenderService: tenderService,
|
||||
companyService: companyService,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *feedbackService) ToggleFeedback(ctx context.Context, req ToggleFeedbackForm, customerID *string, companyID *string) (*FeedbackResponse, error) {
|
||||
existing, err := s.feedbackRepo.GetByCompanyID(ctx, *companyID, req.TenderID)
|
||||
func (s *feedbackService) Toggle(ctx context.Context, req ToggleFeedbackForm, customerID *string, companyID *string) (*FeedbackResponse, error) {
|
||||
existing, err := s.feedbackRepo.GetByCompanyID(ctx, *companyID, req.Tender)
|
||||
|
||||
if err != nil {
|
||||
feedback := &Feedback{
|
||||
TenderID: req.TenderID,
|
||||
FeedbackType: req.FeedbackType,
|
||||
TenderID: req.Tender,
|
||||
FeedbackType: req.Type,
|
||||
CompanyID: companyID,
|
||||
CustomerID: customerID,
|
||||
}
|
||||
@@ -47,35 +51,53 @@ func (s *feedbackService) ToggleFeedback(ctx context.Context, req ToggleFeedback
|
||||
err = s.feedbackRepo.Create(ctx, feedback)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to create new feedback", map[string]interface{}{
|
||||
"tender_id": req.TenderID,
|
||||
"tender_id": req.Tender,
|
||||
"company_id": *companyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return feedback.ToResponse(), nil
|
||||
tender, company, err := s.getDetails(ctx, req.Tender, *companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get details", map[string]interface{}{
|
||||
"tender_id": req.Tender,
|
||||
"company_id": *companyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return feedback.ToResponse(tender, company), nil
|
||||
}
|
||||
|
||||
if existing.FeedbackType == req.FeedbackType {
|
||||
if existing.FeedbackType == req.Type {
|
||||
err = s.feedbackRepo.Delete(ctx, existing.GetID())
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update existing feedback", map[string]interface{}{
|
||||
"feedback_id": existing.GetID(),
|
||||
"tender_id": req.TenderID,
|
||||
"tender_id": req.Tender,
|
||||
"company_id": *companyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.FeedbackType == FeedbackTypeLike {
|
||||
if req.Type == FeedbackTypeLike {
|
||||
existing.FeedbackType = "unlike"
|
||||
} else {
|
||||
existing.FeedbackType = "undislike"
|
||||
}
|
||||
|
||||
return existing.ToResponse(), nil
|
||||
tender, company, err := s.getDetails(ctx, req.Tender, *companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get details", map[string]interface{}{
|
||||
"tender_id": req.Tender,
|
||||
"company_id": *companyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return existing.ToResponse(tender, company), nil
|
||||
}
|
||||
|
||||
if existing.FeedbackType == FeedbackTypeLike {
|
||||
@@ -88,17 +110,26 @@ func (s *feedbackService) ToggleFeedback(ctx context.Context, req ToggleFeedback
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update existing feedback", map[string]interface{}{
|
||||
"feedback_id": existing.GetID(),
|
||||
"tender_id": req.TenderID,
|
||||
"tender_id": req.Tender,
|
||||
"company_id": *companyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return existing.ToResponse(), nil
|
||||
tender, company, err := s.getDetails(ctx, req.Tender, *companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get details", map[string]interface{}{
|
||||
"tender_id": req.Tender,
|
||||
"company_id": *companyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return existing.ToResponse(tender, company), nil
|
||||
}
|
||||
|
||||
func (s *feedbackService) GetFeedback(ctx context.Context, id string) (*FeedbackResponse, error) {
|
||||
func (s *feedbackService) Get(ctx context.Context, id string) (*FeedbackResponse, error) {
|
||||
feedback, err := s.feedbackRepo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get feedback", map[string]interface{}{
|
||||
@@ -108,16 +139,25 @@ func (s *feedbackService) GetFeedback(ctx context.Context, id string) (*Feedback
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return feedback.ToResponse(), nil
|
||||
tender, company, err := s.getDetails(ctx, feedback.TenderID, *feedback.CompanyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get details", map[string]interface{}{
|
||||
"tender_id": feedback.TenderID,
|
||||
"company_id": *feedback.CompanyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return feedback.ToResponse(tender, company), nil
|
||||
}
|
||||
|
||||
func (s *feedbackService) ListFeedback(ctx context.Context, criteria FeedbackSearchCriteria, limit, offset int) (*FeedbackListWithTenderResponse, error) {
|
||||
feedbacks, total, err := s.feedbackRepo.List(ctx, criteria, limit, offset)
|
||||
func (s *feedbackService) Search(ctx context.Context, criteria SearchForm, pagination *response.Pagination) (*FeedbackListResponse, error) {
|
||||
feedbacks, total, err := s.feedbackRepo.Search(ctx, criteria, pagination)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to list feedback", map[string]interface{}{
|
||||
"criteria": criteria,
|
||||
"limit": limit,
|
||||
"offset": offset,
|
||||
"limit": pagination.Limit,
|
||||
"offset": pagination.Offset,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, err
|
||||
@@ -125,23 +165,56 @@ func (s *feedbackService) ListFeedback(ctx context.Context, criteria FeedbackSea
|
||||
|
||||
meta := &response.Meta{
|
||||
Total: int(total),
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
Page: (offset / limit) + 1,
|
||||
Pages: int((total + int64(limit) - 1) / int64(limit)),
|
||||
Limit: pagination.Limit,
|
||||
Offset: pagination.Offset,
|
||||
Page: (pagination.Offset / pagination.Limit) + 1,
|
||||
Pages: int((total + int64(pagination.Limit) - 1) / int64(pagination.Limit)),
|
||||
}
|
||||
|
||||
result := make([]*FeedbackWithTenderResponse, len(feedbacks))
|
||||
result := make([]*FeedbackResponse, len(feedbacks))
|
||||
for i, feedback := range feedbacks {
|
||||
tender, err := s.tenderService.GetByID(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{
|
||||
tender, company, _ := s.getDetails(ctx, feedback.TenderID, *feedback.CompanyID)
|
||||
result[i] = feedback.ToResponse(tender, company)
|
||||
}
|
||||
|
||||
return &FeedbackListResponse{
|
||||
Feedback: result,
|
||||
Meta: meta,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *feedbackService) Delete(ctx context.Context, id string) error {
|
||||
return s.feedbackRepo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (s *feedbackService) GetByTenderID(ctx context.Context, tenderID, companyID string) (*FeedbackResponse, error) {
|
||||
feedback, err := s.feedbackRepo.GetByTenderID(ctx, tenderID, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get feedback by tender ID", map[string]interface{}{
|
||||
"tender_id": tenderID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tender, err := s.tenderService.GetByID(ctx, feedback.TenderID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get tender", map[string]interface{}{
|
||||
"tender_id": feedback.TenderID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
company, err := s.companyService.GetByID(ctx, *feedback.CompanyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get company", map[string]interface{}{
|
||||
"company_id": feedback.CompanyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return feedback.ToResponse(
|
||||
&tenderResponse{
|
||||
ID: tender.ID,
|
||||
NoticePublicationID: tender.NoticePublicationID,
|
||||
PublicationDate: tender.PublicationDate,
|
||||
@@ -158,46 +231,69 @@ func (s *feedbackService) ListFeedback(ctx context.Context, criteria FeedbackSea
|
||||
CountryCode: tender.CountryCode,
|
||||
BuyerOrganization: &organizationResponse{Name: tender.BuyerOrganization.Name},
|
||||
Status: string(tender.Status),
|
||||
})
|
||||
result[i] = resp
|
||||
}
|
||||
return &FeedbackListWithTenderResponse{
|
||||
Feedback: result,
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
&companyResponse{
|
||||
ID: company.ID,
|
||||
Name: company.Name,
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (s *feedbackService) DeleteFeedback(ctx context.Context, id string) error {
|
||||
return s.feedbackRepo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (s *feedbackService) GetFeedbackByTenderID(ctx context.Context, tenderID, companyID string) (*FeedbackResponse, error) {
|
||||
feedback, err := s.feedbackRepo.GetByTenderID(ctx, tenderID, companyID)
|
||||
func (s *feedbackService) getDetails(ctx context.Context, tenderID, companyID string) (*tenderResponse, *companyResponse, error) {
|
||||
tender, err := s.tenderService.GetByID(ctx, tenderID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get feedback by tender ID", map[string]interface{}{
|
||||
s.logger.Error("Failed to get tender", map[string]interface{}{
|
||||
"tender_id": tenderID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
return feedback.ToResponse(), nil
|
||||
|
||||
company, err := s.companyService.GetByID(ctx, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get company", map[string]interface{}{
|
||||
"company_id": companyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return &tenderResponse{
|
||||
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),
|
||||
}, &companyResponse{
|
||||
ID: company.ID,
|
||||
Name: company.Name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *feedbackService) CompanyFeedbackStats(ctx context.Context, companyID string) (*CompanyFeedbackStatsResponse, error) {
|
||||
func (s *feedbackService) CompanyStats(ctx context.Context, companyID string) (*StatsResponse, error) {
|
||||
s.logger.Info("Getting company feedback statistics", map[string]interface{}{
|
||||
"company_id": companyID,
|
||||
})
|
||||
|
||||
stats, err := s.feedbackRepo.GetCompanyFeedbackStats(ctx, companyID)
|
||||
stats, err := s.feedbackRepo.CompanyStats(ctx, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get company feedback statistics", map[string]interface{}{
|
||||
s.logger.Error("Failed to get company stats", map[string]interface{}{
|
||||
"company_id": companyID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.logger.Info("Company feedback statistics retrieved successfully", map[string]interface{}{
|
||||
s.logger.Info("Company stats retrieved successfully", map[string]interface{}{
|
||||
"company_id": companyID,
|
||||
"total_feedback": stats.TotalFeedback,
|
||||
"total_likes": stats.TotalLikes,
|
||||
|
||||
Reference in New Issue
Block a user