Refactor Tender Approval Management and Update API Documentation

- Replaced the existing tender approval update and delete endpoints with a new toggle functionality, allowing for more streamlined management of tender approvals.
- Introduced the `ToggleTenderApproval` method in the service layer to handle both approval and rejection actions based on the current state of the tender approval.
- Updated the API documentation to reflect the new endpoint structure and response formats, including the `TenderApprovalWithTenderResponse`.
- Enhanced Swagger documentation to ensure accurate representation of the updated tender approval operations.
- Removed obsolete methods and routes to maintain a clean and efficient codebase, adhering to Clean Architecture principles.
This commit is contained in:
n.nakhostin
2025-08-19 11:01:49 +03:30
parent dd2573a308
commit 392b31626d
10 changed files with 298 additions and 532 deletions
+66 -63
View File
@@ -31,8 +31,7 @@ type Service interface {
SearchTenderApprovalsByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error)
// Business operations
ApproveTender(ctx context.Context, id string, form *ApproveTenderForm) (*TenderApproval, error)
RejectTender(ctx context.Context, id string, form *RejectTenderForm) (*TenderApproval, error)
ToggleTenderApproval(ctx context.Context, req *ToggleTenderApprovalForm, companyID string) (*TenderApprovalWithTenderResponse, error)
// Statistics and analytics
GetTenderApprovalStats(ctx context.Context) (*TenderApprovalStatsResponse, error)
@@ -636,67 +635,6 @@ func (s *tenderApprovalService) SearchTenderApprovalsByCriteria(ctx context.Cont
return tenderApprovals, nil
}
// ApproveTender approves a tender
func (s *tenderApprovalService) ApproveTender(ctx context.Context, id string, form *ApproveTenderForm) (*TenderApproval, error) {
// Get tender approval to check if exists
tenderApproval, err := s.repository.GetByID(ctx, id)
if err != nil {
return nil, errors.New("tender approval not found")
}
// Approve the tender
tenderApproval.Approve(form.Notes)
// Update in database
err = s.repository.Update(ctx, tenderApproval)
if err != nil {
s.logger.Error("Failed to approve tender", map[string]interface{}{
"error": err.Error(),
"tender_approval_id": id,
})
return nil, errors.New("failed to approve tender")
}
s.logger.Info("Tender approved successfully", map[string]interface{}{
"tender_approval_id": tenderApproval.ID,
"tender_id": tenderApproval.TenderID,
"company_id": tenderApproval.CompanyID,
})
return tenderApproval, nil
}
// RejectTender rejects a tender
func (s *tenderApprovalService) RejectTender(ctx context.Context, id string, form *RejectTenderForm) (*TenderApproval, error) {
// Get tender approval to check if exists
tenderApproval, err := s.repository.GetByID(ctx, id)
if err != nil {
return nil, errors.New("tender approval not found")
}
// Reject the tender
tenderApproval.Reject(form.Reason)
// Update in database
err = s.repository.Update(ctx, tenderApproval)
if err != nil {
s.logger.Error("Failed to reject tender", map[string]interface{}{
"error": err.Error(),
"tender_approval_id": id,
})
return nil, errors.New("failed to reject tender")
}
s.logger.Info("Tender rejected successfully", map[string]interface{}{
"tender_approval_id": tenderApproval.ID,
"tender_id": tenderApproval.TenderID,
"company_id": tenderApproval.CompanyID,
"reason": form.Reason,
})
return tenderApproval, nil
}
// GetTenderApprovalStats returns tender approval statistics
func (s *tenderApprovalService) GetTenderApprovalStats(ctx context.Context) (*TenderApprovalStatsResponse, error) {
stats, err := s.repository.GetTenderApprovalStats(ctx)
@@ -969,3 +907,68 @@ func (s *tenderApprovalService) ListTenderApprovalsWithTender(ctx context.Contex
return meta, nil
}
func (s *tenderApprovalService) ToggleTenderApproval(ctx context.Context, req *ToggleTenderApprovalForm, companyID string) (*TenderApprovalWithTenderResponse, error) {
existing, err := s.repository.GetByTenderAndCompany(ctx, req.TenderID, companyID)
if err != nil {
approval := &TenderApproval{
TenderID: req.TenderID,
CompanyID: companyID,
SubmissionMode: req.SubmissionMode,
Status: req.Status,
}
err = s.repository.Create(ctx, approval)
if err != nil {
s.logger.Error("Failed to create new tender approval", map[string]interface{}{
"tender_id": req.TenderID,
"company_id": companyID,
"status": req.Status,
"submission_mode": req.SubmissionMode,
"error": err.Error(),
})
return nil, err
}
return approval.ToResponseWithTender(nil), nil
}
if existing.Status == req.Status && existing.SubmissionMode == req.SubmissionMode {
err = s.repository.Delete(ctx, existing.GetID())
if err != nil {
s.logger.Error("Failed to update tender approval", map[string]interface{}{
"error": err.Error(),
})
return nil, err
}
return existing.ToResponseWithTender(nil), nil
} else if existing.Status == req.Status && existing.SubmissionMode != req.SubmissionMode {
existing.SubmissionMode = req.SubmissionMode
err = s.repository.Update(ctx, existing)
if err != nil {
s.logger.Error("Failed to update tender approval", map[string]interface{}{
"error": err.Error(),
})
return nil, err
}
return existing.ToResponseWithTender(nil), nil
}
if existing.Status == ApprovalStatusApproved {
existing.Reject()
} else {
existing.Approve()
}
err = s.repository.Update(ctx, existing)
if err != nil {
s.logger.Error("Failed to update tender approval", map[string]interface{}{
"error": err.Error(),
})
return nil, err
}
return existing.ToResponseWithTender(nil), nil
}