Enhance Tender Approval Service with Tender Details Integration
- Updated the tender approval service to include methods for retrieving tender approvals with associated tender details, improving the response structure for API consumers. - Modified the tender approval handler to utilize the new service methods, ensuring that tender details are included in the responses for created, updated, and retrieved tender approvals. - Enhanced the API documentation to reflect the changes in response formats, including the new `TenderApprovalWithTenderResponse` structure. - Ensured adherence to Clean Architecture principles by maintaining a clear separation of concerns in the service and handler layers.
This commit is contained in:
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"tm/internal/tender"
|
||||
"tm/pkg/logger"
|
||||
)
|
||||
|
||||
@@ -13,15 +13,20 @@ type Service interface {
|
||||
// Core tender approval operations
|
||||
CreateTenderApproval(ctx context.Context, form *CreateTenderApprovalForm, companyID string) (*TenderApproval, error)
|
||||
GetTenderApprovalByID(ctx context.Context, id string) (*TenderApproval, error)
|
||||
GetTenderApprovalByIDWithTender(ctx context.Context, id string) (*TenderApprovalWithTenderResponse, error)
|
||||
GetTenderApprovalByTenderAndCompany(ctx context.Context, tenderID, companyID string) (*TenderApproval, error)
|
||||
GetTenderApprovalByTenderAndCompanyWithTender(ctx context.Context, tenderID, companyID string) (*TenderApprovalWithTenderResponse, error)
|
||||
GetTenderApprovalsByTenderID(ctx context.Context, tenderID string) ([]*TenderApproval, error)
|
||||
GetTenderApprovalsByCompanyID(ctx context.Context, companyID string, submissionMode *SubmissionMode, status *ApprovalStatus) ([]*TenderApproval, error)
|
||||
GetTenderApprovalsByCompanyIDWithTender(ctx context.Context, companyID string, submissionMode *SubmissionMode, status *ApprovalStatus) ([]*TenderApprovalWithTenderResponse, error)
|
||||
GetTenderApprovalsByIDs(ctx context.Context, ids []string) ([]*TenderApproval, error)
|
||||
UpdateTenderApproval(ctx context.Context, id string, form *UpdateTenderApprovalForm) (*TenderApproval, error)
|
||||
UpdateTenderApprovalWithTender(ctx context.Context, id string, form *UpdateTenderApprovalForm) (*TenderApprovalWithTenderResponse, error)
|
||||
DeleteTenderApproval(ctx context.Context, id string) error
|
||||
|
||||
// Tender approval listing and search
|
||||
ListTenderApprovals(ctx context.Context, form *ListTenderApprovalsForm) (*TenderApprovalListResponse, error)
|
||||
ListTenderApprovalsWithTender(ctx context.Context, form *ListTenderApprovalsForm) (*TenderApprovalListResponseWithTender, error)
|
||||
SearchTenderApprovals(ctx context.Context, form *TenderApprovalSearchForm) (*TenderApprovalListResponse, error)
|
||||
SearchTenderApprovalsByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error)
|
||||
|
||||
@@ -34,20 +39,24 @@ type Service interface {
|
||||
|
||||
// Search and filtering helpers
|
||||
GetTenderApprovalsByStatus(ctx context.Context, status ApprovalStatus, limit, offset int) ([]*TenderApproval, int64, error)
|
||||
GetTenderApprovalsByStatusWithTender(ctx context.Context, status ApprovalStatus, limit, offset int) ([]*TenderApprovalWithTenderResponse, int64, error)
|
||||
GetTenderApprovalsBySubmissionMode(ctx context.Context, submissionMode SubmissionMode, limit, offset int) ([]*TenderApproval, int64, error)
|
||||
GetTenderApprovalsBySubmissionModeWithTender(ctx context.Context, submissionMode SubmissionMode, limit, offset int) ([]*TenderApprovalWithTenderResponse, int64, error)
|
||||
}
|
||||
|
||||
// tenderApprovalService implements the Service interface
|
||||
type tenderApprovalService struct {
|
||||
repository Repository
|
||||
logger logger.Logger
|
||||
repository Repository
|
||||
tenderService tender.TenderService
|
||||
logger logger.Logger
|
||||
}
|
||||
|
||||
// NewTenderApprovalService creates a new tender approval service
|
||||
func NewTenderApprovalService(repository Repository, logger logger.Logger) Service {
|
||||
func NewTenderApprovalService(repository Repository, tenderService tender.TenderService, logger logger.Logger) Service {
|
||||
return &tenderApprovalService{
|
||||
repository: repository,
|
||||
logger: logger,
|
||||
repository: repository,
|
||||
tenderService: tenderService,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +118,55 @@ func (s *tenderApprovalService) GetTenderApprovalByID(ctx context.Context, id st
|
||||
return tenderApproval, nil
|
||||
}
|
||||
|
||||
// GetTenderApprovalByIDWithTender retrieves a tender approval by ID with tender details
|
||||
func (s *tenderApprovalService) GetTenderApprovalByIDWithTender(ctx context.Context, id string) (*TenderApprovalWithTenderResponse, error) {
|
||||
tenderApproval, err := s.repository.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get tender approval by ID", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"tender_approval_id": id,
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get tender details
|
||||
tenderResponse, err := s.tenderService.GetTenderByID(ctx, tenderApproval.TenderID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to get tender details", map[string]interface{}{
|
||||
"tender_id": tenderApproval.TenderID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
// Return approval without tender details rather than failing completely
|
||||
return tenderApproval.ToResponseWithTender(nil), nil
|
||||
}
|
||||
|
||||
// Convert tender response to tender details
|
||||
tenderDetails := &TenderDetails{
|
||||
ID: tenderResponse.ID,
|
||||
NoticePublicationID: tenderResponse.NoticePublicationID,
|
||||
PublicationDate: tenderResponse.PublicationDate,
|
||||
Title: tenderResponse.Title,
|
||||
Description: tenderResponse.Description,
|
||||
ProcurementTypeCode: tenderResponse.ProcurementTypeCode,
|
||||
ProcedureCode: tenderResponse.ProcedureCode,
|
||||
EstimatedValue: tenderResponse.EstimatedValue,
|
||||
Currency: tenderResponse.Currency,
|
||||
Duration: tenderResponse.Duration,
|
||||
DurationUnit: tenderResponse.DurationUnit,
|
||||
TenderDeadline: tenderResponse.TenderDeadline,
|
||||
SubmissionDeadline: tenderResponse.SubmissionDeadline,
|
||||
CountryCode: tenderResponse.CountryCode,
|
||||
BuyerOrganization: &OrganizationResponse{Name: tenderResponse.BuyerOrganization.Name},
|
||||
Status: string(tenderResponse.Status),
|
||||
}
|
||||
|
||||
s.logger.Info("Tender approval with tender details retrieved successfully", map[string]interface{}{
|
||||
"tender_approval_id": id,
|
||||
})
|
||||
|
||||
return tenderApproval.ToResponseWithTender(tenderDetails), nil
|
||||
}
|
||||
|
||||
// GetTenderApprovalByTenderAndCompany retrieves a tender approval by tender ID and company ID
|
||||
func (s *tenderApprovalService) GetTenderApprovalByTenderAndCompany(ctx context.Context, tenderID, companyID string) (*TenderApproval, error) {
|
||||
tenderApproval, err := s.repository.GetByTenderAndCompany(ctx, tenderID, companyID)
|
||||
@@ -130,6 +188,57 @@ func (s *tenderApprovalService) GetTenderApprovalByTenderAndCompany(ctx context.
|
||||
return tenderApproval, nil
|
||||
}
|
||||
|
||||
// GetTenderApprovalByTenderAndCompanyWithTender retrieves a tender approval by tender ID and company ID with tender details
|
||||
func (s *tenderApprovalService) GetTenderApprovalByTenderAndCompanyWithTender(ctx context.Context, tenderID, companyID string) (*TenderApprovalWithTenderResponse, error) {
|
||||
tenderApproval, err := s.repository.GetByTenderAndCompany(ctx, tenderID, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get tender approval by tender and company", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"tender_id": tenderID,
|
||||
"company_id": companyID,
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get tender details
|
||||
tenderResponse, err := s.tenderService.GetTenderByID(ctx, tenderApproval.TenderID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to get tender details", map[string]interface{}{
|
||||
"tender_id": tenderApproval.TenderID,
|
||||
})
|
||||
// Return approval without tender details rather than failing completely
|
||||
return tenderApproval.ToResponseWithTender(nil), nil
|
||||
}
|
||||
|
||||
// Convert tender response to tender details
|
||||
tenderDetails := &TenderDetails{
|
||||
ID: tenderResponse.ID,
|
||||
NoticePublicationID: tenderResponse.NoticePublicationID,
|
||||
PublicationDate: tenderResponse.PublicationDate,
|
||||
Title: tenderResponse.Title,
|
||||
Description: tenderResponse.Description,
|
||||
ProcurementTypeCode: tenderResponse.ProcurementTypeCode,
|
||||
ProcedureCode: tenderResponse.ProcedureCode,
|
||||
EstimatedValue: tenderResponse.EstimatedValue,
|
||||
Currency: tenderResponse.Currency,
|
||||
Duration: tenderResponse.Duration,
|
||||
DurationUnit: tenderResponse.DurationUnit,
|
||||
TenderDeadline: tenderResponse.TenderDeadline,
|
||||
SubmissionDeadline: tenderResponse.SubmissionDeadline,
|
||||
CountryCode: tenderResponse.CountryCode,
|
||||
BuyerOrganization: &OrganizationResponse{Name: tenderResponse.BuyerOrganization.Name},
|
||||
Status: string(tenderResponse.Status),
|
||||
}
|
||||
|
||||
s.logger.Info("Tender approval with tender details retrieved successfully", map[string]interface{}{
|
||||
"tender_approval_id": tenderApproval.ID,
|
||||
"tender_id": tenderApproval.TenderID,
|
||||
"company_id": tenderApproval.CompanyID,
|
||||
})
|
||||
|
||||
return tenderApproval.ToResponseWithTender(tenderDetails), nil
|
||||
}
|
||||
|
||||
// GetTenderApprovalsByTenderID retrieves all tender approvals for a specific tender
|
||||
func (s *tenderApprovalService) GetTenderApprovalsByTenderID(ctx context.Context, tenderID string) ([]*TenderApproval, error) {
|
||||
tenderApprovals, err := s.repository.GetByTenderID(ctx, tenderID)
|
||||
@@ -168,6 +277,57 @@ func (s *tenderApprovalService) GetTenderApprovalsByCompanyID(ctx context.Contex
|
||||
return tenderApprovals, nil
|
||||
}
|
||||
|
||||
// GetTenderApprovalsByCompanyIDWithTender retrieves all tender approvals for a specific company with tender details
|
||||
func (s *tenderApprovalService) GetTenderApprovalsByCompanyIDWithTender(ctx context.Context, companyID string, submissionMode *SubmissionMode, status *ApprovalStatus) ([]*TenderApprovalWithTenderResponse, error) {
|
||||
tenderApprovals, err := s.repository.GetByCompanyID(ctx, companyID, submissionMode, status)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get tender approvals by company ID", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"company_id": companyID,
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert to response with tender details
|
||||
var responses []*TenderApprovalWithTenderResponse
|
||||
for _, approval := range tenderApprovals {
|
||||
// Get tender details
|
||||
tenderResponse, err := s.tenderService.GetTenderByID(ctx, approval.TenderID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to get tender details", map[string]interface{}{
|
||||
"tender_id": approval.TenderID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
// Continue without tender details rather than failing completely
|
||||
responses = append(responses, approval.ToResponseWithTender(nil))
|
||||
continue
|
||||
}
|
||||
|
||||
// Convert tender response to tender details
|
||||
tenderDetails := &TenderDetails{
|
||||
ID: tenderResponse.ID,
|
||||
Title: tenderResponse.Title,
|
||||
Description: tenderResponse.Description,
|
||||
EstimatedValue: tenderResponse.EstimatedValue,
|
||||
Currency: tenderResponse.Currency,
|
||||
TenderDeadline: tenderResponse.TenderDeadline,
|
||||
SubmissionDeadline: tenderResponse.SubmissionDeadline,
|
||||
CountryCode: tenderResponse.CountryCode,
|
||||
BuyerOrganization: &OrganizationResponse{Name: tenderResponse.BuyerOrganization.Name},
|
||||
Status: string(tenderResponse.Status),
|
||||
}
|
||||
|
||||
responses = append(responses, approval.ToResponseWithTender(tenderDetails))
|
||||
}
|
||||
|
||||
s.logger.Info("Tender approvals with tender details retrieved successfully", map[string]interface{}{
|
||||
"company_id": companyID,
|
||||
"count": len(responses),
|
||||
})
|
||||
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
// GetTenderApprovalsByIDs retrieves multiple tender approvals by their IDs
|
||||
func (s *tenderApprovalService) GetTenderApprovalsByIDs(ctx context.Context, ids []string) ([]*TenderApproval, error) {
|
||||
if len(ids) == 0 {
|
||||
@@ -234,6 +394,80 @@ func (s *tenderApprovalService) UpdateTenderApproval(ctx context.Context, id str
|
||||
return tenderApproval, nil
|
||||
}
|
||||
|
||||
// UpdateTenderApprovalWithTender updates a tender approval and returns it with tender details
|
||||
func (s *tenderApprovalService) UpdateTenderApprovalWithTender(ctx context.Context, id string, form *UpdateTenderApprovalForm) (*TenderApprovalWithTenderResponse, error) {
|
||||
// Get existing tender approval
|
||||
tenderApproval, err := s.repository.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get tender approval for update", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"tender_approval_id": id,
|
||||
})
|
||||
return nil, errors.New("tender approval not found")
|
||||
}
|
||||
|
||||
// Update fields if provided
|
||||
if form.SubmissionMode != nil {
|
||||
tenderApproval.SubmissionMode = SubmissionMode(*form.SubmissionMode)
|
||||
}
|
||||
|
||||
if form.Status != nil {
|
||||
tenderApproval.Status = ApprovalStatus(*form.Status)
|
||||
}
|
||||
|
||||
// Set updated timestamp
|
||||
tenderApproval.UpdatedAt = time.Now().Unix()
|
||||
|
||||
// Update in database
|
||||
err = s.repository.Update(ctx, tenderApproval)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update tender approval", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"tender_approval_id": id,
|
||||
})
|
||||
return nil, errors.New("failed to update tender approval")
|
||||
}
|
||||
|
||||
// Get tender details
|
||||
tenderResponse, err := s.tenderService.GetTenderByID(ctx, tenderApproval.TenderID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to get tender details", map[string]interface{}{
|
||||
"tender_id": tenderApproval.TenderID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
// Return approval without tender details rather than failing completely
|
||||
return tenderApproval.ToResponseWithTender(nil), nil
|
||||
}
|
||||
|
||||
// Convert tender response to tender details
|
||||
tenderDetails := &TenderDetails{
|
||||
ID: tenderResponse.ID,
|
||||
NoticePublicationID: tenderResponse.NoticePublicationID,
|
||||
PublicationDate: tenderResponse.PublicationDate,
|
||||
Title: tenderResponse.Title,
|
||||
Description: tenderResponse.Description,
|
||||
ProcurementTypeCode: tenderResponse.ProcurementTypeCode,
|
||||
ProcedureCode: tenderResponse.ProcedureCode,
|
||||
EstimatedValue: tenderResponse.EstimatedValue,
|
||||
Currency: tenderResponse.Currency,
|
||||
Duration: tenderResponse.Duration,
|
||||
DurationUnit: tenderResponse.DurationUnit,
|
||||
TenderDeadline: tenderResponse.TenderDeadline,
|
||||
SubmissionDeadline: tenderResponse.SubmissionDeadline,
|
||||
CountryCode: tenderResponse.CountryCode,
|
||||
BuyerOrganization: &OrganizationResponse{Name: tenderResponse.BuyerOrganization.Name},
|
||||
Status: string(tenderResponse.Status),
|
||||
}
|
||||
|
||||
s.logger.Info("Tender approval updated successfully", map[string]interface{}{
|
||||
"tender_approval_id": tenderApproval.ID,
|
||||
"tender_id": tenderApproval.TenderID,
|
||||
"company_id": tenderApproval.CompanyID,
|
||||
})
|
||||
|
||||
return tenderApproval.ToResponseWithTender(tenderDetails), nil
|
||||
}
|
||||
|
||||
// DeleteTenderApproval deletes a tender approval
|
||||
func (s *tenderApprovalService) DeleteTenderApproval(ctx context.Context, id string) error {
|
||||
// Get tender approval to check if exists
|
||||
@@ -525,3 +759,213 @@ func (s *tenderApprovalService) GetTenderApprovalsBySubmissionMode(ctx context.C
|
||||
|
||||
return tenderApprovals, total, nil
|
||||
}
|
||||
|
||||
// GetTenderApprovalsByStatusWithTender retrieves tender approvals by status with tender details
|
||||
func (s *tenderApprovalService) GetTenderApprovalsByStatusWithTender(ctx context.Context, status ApprovalStatus, limit, offset int) ([]*TenderApprovalWithTenderResponse, int64, error) {
|
||||
tenderApprovals, total, err := s.GetTenderApprovalsByStatus(ctx, status, limit, offset)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Convert to response with tender details
|
||||
var responses []*TenderApprovalWithTenderResponse
|
||||
for _, approval := range tenderApprovals {
|
||||
// Get tender details
|
||||
tenderResponse, err := s.tenderService.GetTenderByID(ctx, approval.TenderID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to get tender details", map[string]interface{}{
|
||||
"tender_id": approval.TenderID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
// Continue without tender details rather than failing completely
|
||||
responses = append(responses, approval.ToResponseWithTender(nil))
|
||||
continue
|
||||
}
|
||||
|
||||
// Convert tender response to tender details
|
||||
tenderDetails := &TenderDetails{
|
||||
ID: tenderResponse.ID,
|
||||
NoticePublicationID: tenderResponse.NoticePublicationID,
|
||||
PublicationDate: tenderResponse.PublicationDate,
|
||||
Title: tenderResponse.Title,
|
||||
Description: tenderResponse.Description,
|
||||
ProcurementTypeCode: tenderResponse.ProcurementTypeCode,
|
||||
ProcedureCode: tenderResponse.ProcurementTypeCode,
|
||||
EstimatedValue: tenderResponse.EstimatedValue,
|
||||
Currency: tenderResponse.Currency,
|
||||
Duration: tenderResponse.Duration,
|
||||
DurationUnit: tenderResponse.DurationUnit,
|
||||
TenderDeadline: tenderResponse.TenderDeadline,
|
||||
SubmissionDeadline: tenderResponse.SubmissionDeadline,
|
||||
CountryCode: tenderResponse.CountryCode,
|
||||
BuyerOrganization: &OrganizationResponse{Name: tenderResponse.BuyerOrganization.Name},
|
||||
Status: string(tenderResponse.Status),
|
||||
}
|
||||
|
||||
responses = append(responses, approval.ToResponseWithTender(tenderDetails))
|
||||
}
|
||||
|
||||
return responses, total, nil
|
||||
}
|
||||
|
||||
// GetTenderApprovalsBySubmissionModeWithTender retrieves tender approvals by submission mode with tender details
|
||||
func (s *tenderApprovalService) GetTenderApprovalsBySubmissionModeWithTender(ctx context.Context, submissionMode SubmissionMode, limit, offset int) ([]*TenderApprovalWithTenderResponse, int64, error) {
|
||||
tenderApprovals, total, err := s.GetTenderApprovalsBySubmissionMode(ctx, submissionMode, limit, offset)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Convert to response with tender details
|
||||
var responses []*TenderApprovalWithTenderResponse
|
||||
for _, approval := range tenderApprovals {
|
||||
// Get tender details
|
||||
tenderResponse, err := s.tenderService.GetTenderByID(ctx, approval.TenderID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to get tender details", map[string]interface{}{
|
||||
"tender_id": approval.TenderID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
// Continue without tender details rather than failing completely
|
||||
responses = append(responses, approval.ToResponseWithTender(nil))
|
||||
continue
|
||||
}
|
||||
|
||||
// Convert tender response to tender details
|
||||
tenderDetails := &TenderDetails{
|
||||
ID: tenderResponse.ID,
|
||||
NoticePublicationID: tenderResponse.NoticePublicationID,
|
||||
PublicationDate: tenderResponse.PublicationDate,
|
||||
Title: tenderResponse.Title,
|
||||
Description: tenderResponse.Description,
|
||||
ProcurementTypeCode: tenderResponse.ProcurementTypeCode,
|
||||
ProcedureCode: tenderResponse.ProcedureCode,
|
||||
EstimatedValue: tenderResponse.EstimatedValue,
|
||||
Currency: tenderResponse.Currency,
|
||||
Duration: tenderResponse.Duration,
|
||||
DurationUnit: tenderResponse.DurationUnit,
|
||||
TenderDeadline: tenderResponse.TenderDeadline,
|
||||
SubmissionDeadline: tenderResponse.SubmissionDeadline,
|
||||
CountryCode: tenderResponse.CountryCode,
|
||||
BuyerOrganization: &OrganizationResponse{Name: tenderResponse.BuyerOrganization.Name},
|
||||
Status: string(tenderResponse.Status),
|
||||
}
|
||||
|
||||
responses = append(responses, approval.ToResponseWithTender(tenderDetails))
|
||||
}
|
||||
|
||||
return responses, total, nil
|
||||
}
|
||||
|
||||
// ListTenderApprovalsWithTender lists tender approvals with search and filters, including tender details
|
||||
func (s *tenderApprovalService) ListTenderApprovalsWithTender(ctx context.Context, form *ListTenderApprovalsForm) (*TenderApprovalListResponseWithTender, error) {
|
||||
// Set defaults
|
||||
limit := 20
|
||||
if form.Limit != nil {
|
||||
limit = *form.Limit
|
||||
}
|
||||
|
||||
offset := 0
|
||||
if form.Offset != nil {
|
||||
offset = *form.Offset
|
||||
}
|
||||
|
||||
sortBy := "created_at"
|
||||
if form.SortBy != nil {
|
||||
sortBy = *form.SortBy
|
||||
}
|
||||
|
||||
sortOrder := "desc"
|
||||
if form.SortOrder != nil {
|
||||
sortOrder = *form.SortOrder
|
||||
}
|
||||
|
||||
// Convert status strings to ApprovalStatus
|
||||
var status []ApprovalStatus
|
||||
if form.Status != nil {
|
||||
for _, s := range form.Status {
|
||||
status = append(status, ApprovalStatus(s))
|
||||
}
|
||||
}
|
||||
|
||||
// Convert submission mode strings to SubmissionMode
|
||||
var submissionMode []SubmissionMode
|
||||
if form.SubmissionMode != nil {
|
||||
for _, sm := range form.SubmissionMode {
|
||||
submissionMode = append(submissionMode, SubmissionMode(sm))
|
||||
}
|
||||
}
|
||||
|
||||
// Search tender approvals
|
||||
tenderApprovals, err := s.repository.Search(ctx, form.TenderID, form.CompanyID, status, submissionMode, form.CreatedAtFrom, form.CreatedAtTo, limit, offset, sortBy, sortOrder)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to search tender approvals", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, errors.New("failed to search tender approvals")
|
||||
}
|
||||
|
||||
// Get total count for pagination
|
||||
total, err := s.repository.Count(ctx)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to count tender approvals", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
})
|
||||
total = int64(len(tenderApprovals)) // Use actual count if total count fails
|
||||
}
|
||||
|
||||
// Convert to response with tender details
|
||||
var responses []*TenderApprovalWithTenderResponse
|
||||
for _, approval := range tenderApprovals {
|
||||
// Get tender details
|
||||
tenderResponse, err := s.tenderService.GetTenderByID(ctx, approval.TenderID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to get tender details", map[string]interface{}{
|
||||
"tender_id": approval.TenderID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
// Continue without tender details rather than failing completely
|
||||
responses = append(responses, approval.ToResponseWithTender(nil))
|
||||
continue
|
||||
}
|
||||
|
||||
// Convert tender response to tender details
|
||||
tenderDetails := &TenderDetails{
|
||||
ID: tenderResponse.ID,
|
||||
NoticePublicationID: tenderResponse.NoticePublicationID,
|
||||
PublicationDate: tenderResponse.PublicationDate,
|
||||
Title: tenderResponse.Title,
|
||||
Description: tenderResponse.Description,
|
||||
ProcurementTypeCode: tenderResponse.ProcurementTypeCode,
|
||||
ProcedureCode: tenderResponse.ProcedureCode,
|
||||
EstimatedValue: tenderResponse.EstimatedValue,
|
||||
Currency: tenderResponse.Currency,
|
||||
Duration: tenderResponse.Duration,
|
||||
DurationUnit: tenderResponse.DurationUnit,
|
||||
TenderDeadline: tenderResponse.TenderDeadline,
|
||||
SubmissionDeadline: tenderResponse.SubmissionDeadline,
|
||||
CountryCode: tenderResponse.CountryCode,
|
||||
BuyerOrganization: &OrganizationResponse{Name: tenderResponse.BuyerOrganization.Name},
|
||||
Status: string(tenderResponse.Status),
|
||||
}
|
||||
|
||||
responses = append(responses, approval.ToResponseWithTender(tenderDetails))
|
||||
}
|
||||
|
||||
// Calculate pagination metadata
|
||||
pages := int(total) / limit
|
||||
if int(total)%limit > 0 {
|
||||
pages++
|
||||
}
|
||||
page := (offset / limit) + 1
|
||||
|
||||
meta := &TenderApprovalListResponseWithTender{
|
||||
TenderApprovals: responses,
|
||||
Total: total,
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
Page: page,
|
||||
Pages: pages,
|
||||
}
|
||||
|
||||
return meta, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user