8f909618d8
- 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.
209 lines
6.4 KiB
Go
209 lines
6.4 KiB
Go
package feedback
|
|
|
|
import (
|
|
"context"
|
|
"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)
|
|
}
|
|
|
|
// feedbackService implements FeedbackService interface
|
|
type feedbackService struct {
|
|
feedbackRepo Repository
|
|
tenderService tender.TenderService
|
|
logger logger.Logger
|
|
}
|
|
|
|
// NewFeedbackService creates a new feedback service
|
|
func NewFeedbackService(feedbackRepo Repository, tenderService tender.TenderService, logger logger.Logger) FeedbackService {
|
|
return &feedbackService{
|
|
feedbackRepo: feedbackRepo,
|
|
tenderService: tenderService,
|
|
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)
|
|
|
|
if err != nil {
|
|
feedback := &Feedback{
|
|
TenderID: req.TenderID,
|
|
FeedbackType: req.FeedbackType,
|
|
CompanyID: companyID,
|
|
CustomerID: customerID,
|
|
}
|
|
|
|
err = s.feedbackRepo.Create(ctx, feedback)
|
|
if err != nil {
|
|
s.logger.Error("Failed to create new feedback", map[string]interface{}{
|
|
"tender_id": req.TenderID,
|
|
"company_id": *companyID,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
return feedback.ToResponse(), nil
|
|
}
|
|
|
|
if existing.FeedbackType == req.FeedbackType {
|
|
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,
|
|
"company_id": *companyID,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
if req.FeedbackType == FeedbackTypeLike {
|
|
existing.FeedbackType = "unlike"
|
|
} else {
|
|
existing.FeedbackType = "undislike"
|
|
}
|
|
|
|
return existing.ToResponse(), nil
|
|
}
|
|
|
|
if existing.FeedbackType == FeedbackTypeLike {
|
|
existing.FeedbackType = FeedbackTypeDislike
|
|
} else {
|
|
existing.FeedbackType = FeedbackTypeLike
|
|
}
|
|
|
|
err = s.feedbackRepo.Update(ctx, existing)
|
|
if err != nil {
|
|
s.logger.Error("Failed to update existing feedback", map[string]interface{}{
|
|
"feedback_id": existing.GetID(),
|
|
"tender_id": req.TenderID,
|
|
"company_id": *companyID,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
return existing.ToResponse(), nil
|
|
}
|
|
|
|
func (s *feedbackService) GetFeedback(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{}{
|
|
"id": id,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
return feedback.ToResponse(), 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)
|
|
if err != nil {
|
|
s.logger.Error("Failed to list feedback", map[string]interface{}{
|
|
"criteria": criteria,
|
|
"limit": limit,
|
|
"offset": offset,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
meta := &response.Meta{
|
|
Total: int(total),
|
|
Limit: limit,
|
|
Offset: offset,
|
|
Page: (offset / limit) + 1,
|
|
Pages: int((total + int64(limit) - 1) / int64(limit)),
|
|
}
|
|
|
|
result := make([]*FeedbackWithTenderResponse, len(feedbacks))
|
|
for i, feedback := range feedbacks {
|
|
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 &FeedbackListWithTenderResponse{
|
|
Feedback: result,
|
|
Meta: meta,
|
|
}, 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)
|
|
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
|
|
}
|
|
return feedback.ToResponse(), nil
|
|
}
|
|
|
|
func (s *feedbackService) CompanyFeedbackStats(ctx context.Context, companyID string) (*CompanyFeedbackStatsResponse, error) {
|
|
s.logger.Info("Getting company feedback statistics", map[string]interface{}{
|
|
"company_id": companyID,
|
|
})
|
|
|
|
stats, err := s.feedbackRepo.GetCompanyFeedbackStats(ctx, companyID)
|
|
if err != nil {
|
|
s.logger.Error("Failed to get company feedback statistics", map[string]interface{}{
|
|
"company_id": companyID,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
s.logger.Info("Company feedback statistics retrieved successfully", map[string]interface{}{
|
|
"company_id": companyID,
|
|
"total_feedback": stats.TotalFeedback,
|
|
"total_likes": stats.TotalLikes,
|
|
"total_dislikes": stats.TotalDislikes,
|
|
})
|
|
|
|
return stats, nil
|
|
}
|