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:
+1
-1
@@ -124,7 +124,7 @@ func main() {
|
|||||||
customerService := customer.NewCustomerService(customerRepository, logger, customerAuthService, companyService)
|
customerService := customer.NewCustomerService(customerRepository, logger, customerAuthService, companyService)
|
||||||
tenderService := tender.NewTenderService(tenderRepository, companyService, logger)
|
tenderService := tender.NewTenderService(tenderRepository, companyService, logger)
|
||||||
feedbackService := feedback.NewFeedbackService(feedbackRepo, logger)
|
feedbackService := feedback.NewFeedbackService(feedbackRepo, logger)
|
||||||
tenderApprovalService := tender_approval.NewTenderApprovalService(tenderApprovalRepository, logger)
|
tenderApprovalService := tender_approval.NewTenderApprovalService(tenderApprovalRepository, tenderService, logger)
|
||||||
logger.Info("Services initialized successfully", map[string]interface{}{
|
logger.Info("Services initialized successfully", map[string]interface{}{
|
||||||
"services": []string{"customer", "user", "company", "tender", "feedback", "tender_approval"},
|
"services": []string{"customer", "user", "company", "tender", "feedback", "tender_approval"},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -52,6 +52,42 @@ type TenderApprovalResponse struct {
|
|||||||
CreatedAt int64 `json:"created_at"`
|
CreatedAt int64 `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TenderApprovalWithTenderResponse represents the response data for tender approval with tender details
|
||||||
|
type TenderApprovalWithTenderResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
TenderID string `json:"tender_id"`
|
||||||
|
CompanyID string `json:"company_id"`
|
||||||
|
SubmissionMode string `json:"submission_mode"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
Tender *TenderDetails `json:"tender,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// TenderApprovalSearchCriteria represents search criteria for tender approvals
|
// TenderApprovalSearchCriteria represents search criteria for tender approvals
|
||||||
type TenderApprovalSearchCriteria struct {
|
type TenderApprovalSearchCriteria struct {
|
||||||
TenderID *string `json:"tender_id,omitempty"`
|
TenderID *string `json:"tender_id,omitempty"`
|
||||||
@@ -64,6 +100,16 @@ type TenderApprovalSearchCriteria struct {
|
|||||||
Offset int `json:"offset,omitempty"`
|
Offset int `json:"offset,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TenderApprovalListResponseWithTender represents a paginated list of tender approvals with tender details
|
||||||
|
type TenderApprovalListResponseWithTender struct {
|
||||||
|
TenderApprovals []*TenderApprovalWithTenderResponse `json:"tender_approvals"`
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
Limit int `json:"limit"`
|
||||||
|
Offset int `json:"offset"`
|
||||||
|
Page int `json:"page"`
|
||||||
|
Pages int `json:"pages"`
|
||||||
|
}
|
||||||
|
|
||||||
// TenderApprovalStatistics represents statistics for tender approvals
|
// TenderApprovalStatistics represents statistics for tender approvals
|
||||||
type TenderApprovalStatistics struct {
|
type TenderApprovalStatistics struct {
|
||||||
TotalApprovals int64 `json:"total_approvals"`
|
TotalApprovals int64 `json:"total_approvals"`
|
||||||
@@ -123,3 +169,16 @@ func (ta *TenderApproval) ToResponse() *TenderApprovalResponse {
|
|||||||
CreatedAt: ta.CreatedAt,
|
CreatedAt: ta.CreatedAt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToResponseWithTender converts TenderApproval to TenderApprovalWithTenderResponse
|
||||||
|
func (ta *TenderApproval) ToResponseWithTender(tenderDetails *TenderDetails) *TenderApprovalWithTenderResponse {
|
||||||
|
return &TenderApprovalWithTenderResponse{
|
||||||
|
ID: ta.ID.Hex(),
|
||||||
|
TenderID: ta.TenderID,
|
||||||
|
CompanyID: ta.CompanyID,
|
||||||
|
SubmissionMode: string(ta.SubmissionMode),
|
||||||
|
Status: string(ta.Status),
|
||||||
|
CreatedAt: ta.CreatedAt,
|
||||||
|
Tender: tenderDetails,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,7 +56,13 @@ func (h *Handler) CreateTenderApproval(c echo.Context) error {
|
|||||||
return response.InternalServerError(c, "Failed to create tender approval")
|
return response.InternalServerError(c, "Failed to create tender approval")
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.Created(c, tenderApproval.ToResponse(), "Tender approval created successfully")
|
// Get the created approval with tender details
|
||||||
|
tenderApprovalWithTender, err := h.service.GetTenderApprovalByIDWithTender(c.Request().Context(), tenderApproval.GetID())
|
||||||
|
if err != nil {
|
||||||
|
return response.InternalServerError(c, "Failed to get tender approval details")
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Created(c, tenderApprovalWithTender, "Tender approval created successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateTenderApproval updates a tender approval
|
// UpdateTenderApproval updates a tender approval
|
||||||
@@ -81,7 +87,7 @@ func (h *Handler) UpdateTenderApproval(c echo.Context) error {
|
|||||||
return response.ValidationError(c, "Invalid request data", err.Error())
|
return response.ValidationError(c, "Invalid request data", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
tenderApproval, err := h.service.UpdateTenderApproval(c.Request().Context(), id, form)
|
_, err = h.service.UpdateTenderApproval(c.Request().Context(), id, form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "tender approval not found" {
|
if err.Error() == "tender approval not found" {
|
||||||
return response.NotFound(c, "Tender approval not found")
|
return response.NotFound(c, "Tender approval not found")
|
||||||
@@ -89,7 +95,13 @@ func (h *Handler) UpdateTenderApproval(c echo.Context) error {
|
|||||||
return response.InternalServerError(c, "Failed to update tender approval")
|
return response.InternalServerError(c, "Failed to update tender approval")
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.Success(c, tenderApproval.ToResponse(), "Tender approval updated successfully")
|
// Get the updated approval with tender details
|
||||||
|
tenderApprovalWithTender, err := h.service.GetTenderApprovalByIDWithTender(c.Request().Context(), id)
|
||||||
|
if err != nil {
|
||||||
|
return response.InternalServerError(c, "Failed to get tender approval details")
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Success(c, tenderApprovalWithTender, "Tender approval updated successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTenderApproval retrieves a tender approval by ID
|
// GetTenderApproval retrieves a tender approval by ID
|
||||||
@@ -108,7 +120,8 @@ func (h *Handler) UpdateTenderApproval(c echo.Context) error {
|
|||||||
func (h *Handler) GetPublicTenderApproval(c echo.Context) error {
|
func (h *Handler) GetPublicTenderApproval(c echo.Context) error {
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
|
|
||||||
tenderApproval, err := h.service.GetTenderApprovalByID(c.Request().Context(), id)
|
// Get the approval with tender details
|
||||||
|
tenderApprovalWithTender, err := h.service.GetTenderApprovalByIDWithTender(c.Request().Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "tender approval not found" {
|
if err.Error() == "tender approval not found" {
|
||||||
return response.NotFound(c, "Tender approval not found")
|
return response.NotFound(c, "Tender approval not found")
|
||||||
@@ -116,7 +129,7 @@ func (h *Handler) GetPublicTenderApproval(c echo.Context) error {
|
|||||||
return response.InternalServerError(c, "Failed to get tender approval")
|
return response.InternalServerError(c, "Failed to get tender approval")
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.Success(c, tenderApproval.ToResponse(), "Tender approval retrieved successfully")
|
return response.Success(c, tenderApprovalWithTender, "Tender approval retrieved successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTenderApprovalByTenderAndCompany retrieves a tender approval by tender ID and company ID
|
// GetTenderApprovalByTenderAndCompany retrieves a tender approval by tender ID and company ID
|
||||||
@@ -144,7 +157,7 @@ func (h *Handler) GetTenderApprovalByTenderAndCompany(c echo.Context) error {
|
|||||||
return response.BadRequest(c, "Missing required parameters", "tender_id and company_id are required")
|
return response.BadRequest(c, "Missing required parameters", "tender_id and company_id are required")
|
||||||
}
|
}
|
||||||
|
|
||||||
tenderApproval, err := h.service.GetTenderApprovalByTenderAndCompany(c.Request().Context(), tenderID, companyID)
|
tenderApprovalWithTender, err := h.service.GetTenderApprovalByTenderAndCompanyWithTender(c.Request().Context(), tenderID, companyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "tender approval not found" {
|
if err.Error() == "tender approval not found" {
|
||||||
return response.NotFound(c, "Tender approval not found")
|
return response.NotFound(c, "Tender approval not found")
|
||||||
@@ -152,7 +165,7 @@ func (h *Handler) GetTenderApprovalByTenderAndCompany(c echo.Context) error {
|
|||||||
return response.InternalServerError(c, "Failed to get tender approval")
|
return response.InternalServerError(c, "Failed to get tender approval")
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.Success(c, tenderApproval.ToResponse(), "Tender approval retrieved successfully")
|
return response.Success(c, tenderApprovalWithTender, "Tender approval retrieved successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteTenderApproval deletes a tender approval
|
// DeleteTenderApproval deletes a tender approval
|
||||||
@@ -192,7 +205,7 @@ func (h *Handler) DeleteTenderApproval(c echo.Context) error {
|
|||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param submission_mode query string false "Filter by submission mode Enums(self-apply, partnership)"
|
// @Param submission_mode query string false "Filter by submission mode Enums(self-apply, partnership)"
|
||||||
// @Param status query string false "Filter by status Enums(approved, rejected)"
|
// @Param status query string false "Filter by status Enums(approved, rejected)"
|
||||||
// @Success 200 {object} response.APIResponse{data=[]TenderApprovalResponse} "Tender approvals retrieved successfully"
|
// @Success 200 {object} response.APIResponse{data=[]TenderApprovalWithTenderResponse} "Tender approvals retrieved successfully"
|
||||||
// @Failure 400 {object} response.APIResponse "Bad request - Invalid company ID"
|
// @Failure 400 {object} response.APIResponse "Bad request - Invalid company ID"
|
||||||
// @Failure 500 {object} response.APIResponse "Internal server error"
|
// @Failure 500 {object} response.APIResponse "Internal server error"
|
||||||
// @Security BearerAuth
|
// @Security BearerAuth
|
||||||
@@ -227,17 +240,12 @@ func (h *Handler) PublicGetTenderApprovals(c echo.Context) error {
|
|||||||
status = &statusVal
|
status = &statusVal
|
||||||
}
|
}
|
||||||
|
|
||||||
tenderApprovals, err := h.service.GetTenderApprovalsByCompanyID(c.Request().Context(), companyID, submissionMode, status)
|
tenderApprovalsWithTender, err := h.service.GetTenderApprovalsByCompanyIDWithTender(c.Request().Context(), companyID, submissionMode, status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.InternalServerError(c, "Failed to get tender approvals")
|
return response.InternalServerError(c, "Failed to get tender approvals")
|
||||||
}
|
}
|
||||||
|
|
||||||
var responses []*TenderApprovalResponse
|
return response.Success(c, tenderApprovalsWithTender, "Tender approvals retrieved successfully")
|
||||||
for _, approval := range tenderApprovals {
|
|
||||||
responses = append(responses, approval.ToResponse())
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.Success(c, responses, "Tender approvals retrieved successfully")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// **************** Admin Routes ****************
|
// **************** Admin Routes ****************
|
||||||
@@ -270,7 +278,7 @@ func (h *Handler) ListTenderApprovals(c echo.Context) error {
|
|||||||
return response.ValidationError(c, "Invalid request data", err.Error())
|
return response.ValidationError(c, "Invalid request data", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := h.service.ListTenderApprovals(c.Request().Context(), form)
|
result, err := h.service.ListTenderApprovalsWithTender(c.Request().Context(), form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.InternalServerError(c, "Failed to list tender approvals")
|
return response.InternalServerError(c, "Failed to list tender approvals")
|
||||||
}
|
}
|
||||||
@@ -334,23 +342,18 @@ func (h *Handler) GetTenderApprovalsByStatus(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tenderApprovals, total, err := h.service.GetTenderApprovalsByStatus(c.Request().Context(), status, limit, offset)
|
tenderApprovalsWithTender, total, err := h.service.GetTenderApprovalsByStatusWithTender(c.Request().Context(), status, limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.InternalServerError(c, "Failed to retrieve tender approvals by status")
|
return response.InternalServerError(c, "Failed to retrieve tender approvals by status")
|
||||||
}
|
}
|
||||||
|
|
||||||
var responses []*TenderApprovalResponse
|
|
||||||
for _, approval := range tenderApprovals {
|
|
||||||
responses = append(responses, approval.ToResponse())
|
|
||||||
}
|
|
||||||
|
|
||||||
meta := &response.Meta{
|
meta := &response.Meta{
|
||||||
Total: int(total),
|
Total: int(total),
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.SuccessWithMeta(c, responses, meta, "Tender approvals retrieved successfully")
|
return response.SuccessWithMeta(c, tenderApprovalsWithTender, meta, "Tender approvals retrieved successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTenderApprovalsBySubmissionMode retrieves tender approvals by submission mode
|
// GetTenderApprovalsBySubmissionMode retrieves tender approvals by submission mode
|
||||||
@@ -390,23 +393,18 @@ func (h *Handler) GetTenderApprovalsBySubmissionMode(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tenderApprovals, total, err := h.service.GetTenderApprovalsBySubmissionMode(c.Request().Context(), submissionMode, limit, offset)
|
tenderApprovalsWithTender, total, err := h.service.GetTenderApprovalsBySubmissionModeWithTender(c.Request().Context(), submissionMode, limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.InternalServerError(c, "Failed to retrieve tender approvals by submission mode")
|
return response.InternalServerError(c, "Failed to retrieve tender approvals by submission mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
var responses []*TenderApprovalResponse
|
|
||||||
for _, approval := range tenderApprovals {
|
|
||||||
responses = append(responses, approval.ToResponse())
|
|
||||||
}
|
|
||||||
|
|
||||||
meta := &response.Meta{
|
meta := &response.Meta{
|
||||||
Total: int(total),
|
Total: int(total),
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.SuccessWithMeta(c, responses, meta, "Tender approvals retrieved successfully")
|
return response.SuccessWithMeta(c, tenderApprovalsWithTender, meta, "Tender approvals retrieved successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTenderApproval retrieves a tender approval by ID
|
// GetTenderApproval retrieves a tender approval by ID
|
||||||
@@ -425,7 +423,8 @@ func (h *Handler) GetTenderApprovalsBySubmissionMode(c echo.Context) error {
|
|||||||
func (h *Handler) GetTenderApproval(c echo.Context) error {
|
func (h *Handler) GetTenderApproval(c echo.Context) error {
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
|
|
||||||
tenderApproval, err := h.service.GetTenderApprovalByID(c.Request().Context(), id)
|
// Get the approval with tender details
|
||||||
|
tenderApprovalWithTender, err := h.service.GetTenderApprovalByIDWithTender(c.Request().Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "tender approval not found" {
|
if err.Error() == "tender approval not found" {
|
||||||
return response.NotFound(c, "Tender approval not found")
|
return response.NotFound(c, "Tender approval not found")
|
||||||
@@ -433,5 +432,5 @@ func (h *Handler) GetTenderApproval(c echo.Context) error {
|
|||||||
return response.InternalServerError(c, "Failed to get tender approval")
|
return response.InternalServerError(c, "Failed to get tender approval")
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.Success(c, tenderApproval.ToResponse(), "Tender approval retrieved successfully")
|
return response.Success(c, tenderApprovalWithTender, "Tender approval retrieved successfully")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
"tm/internal/tender"
|
||||||
"tm/pkg/logger"
|
"tm/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,15 +13,20 @@ type Service interface {
|
|||||||
// Core tender approval operations
|
// Core tender approval operations
|
||||||
CreateTenderApproval(ctx context.Context, form *CreateTenderApprovalForm, companyID string) (*TenderApproval, error)
|
CreateTenderApproval(ctx context.Context, form *CreateTenderApprovalForm, companyID string) (*TenderApproval, error)
|
||||||
GetTenderApprovalByID(ctx context.Context, id 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)
|
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)
|
GetTenderApprovalsByTenderID(ctx context.Context, tenderID string) ([]*TenderApproval, error)
|
||||||
GetTenderApprovalsByCompanyID(ctx context.Context, companyID string, submissionMode *SubmissionMode, status *ApprovalStatus) ([]*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)
|
GetTenderApprovalsByIDs(ctx context.Context, ids []string) ([]*TenderApproval, error)
|
||||||
UpdateTenderApproval(ctx context.Context, id string, form *UpdateTenderApprovalForm) (*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
|
DeleteTenderApproval(ctx context.Context, id string) error
|
||||||
|
|
||||||
// Tender approval listing and search
|
// Tender approval listing and search
|
||||||
ListTenderApprovals(ctx context.Context, form *ListTenderApprovalsForm) (*TenderApprovalListResponse, error)
|
ListTenderApprovals(ctx context.Context, form *ListTenderApprovalsForm) (*TenderApprovalListResponse, error)
|
||||||
|
ListTenderApprovalsWithTender(ctx context.Context, form *ListTenderApprovalsForm) (*TenderApprovalListResponseWithTender, error)
|
||||||
SearchTenderApprovals(ctx context.Context, form *TenderApprovalSearchForm) (*TenderApprovalListResponse, error)
|
SearchTenderApprovals(ctx context.Context, form *TenderApprovalSearchForm) (*TenderApprovalListResponse, error)
|
||||||
SearchTenderApprovalsByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error)
|
SearchTenderApprovalsByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error)
|
||||||
|
|
||||||
@@ -34,20 +39,24 @@ type Service interface {
|
|||||||
|
|
||||||
// Search and filtering helpers
|
// Search and filtering helpers
|
||||||
GetTenderApprovalsByStatus(ctx context.Context, status ApprovalStatus, limit, offset int) ([]*TenderApproval, int64, error)
|
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)
|
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
|
// tenderApprovalService implements the Service interface
|
||||||
type tenderApprovalService struct {
|
type tenderApprovalService struct {
|
||||||
repository Repository
|
repository Repository
|
||||||
logger logger.Logger
|
tenderService tender.TenderService
|
||||||
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTenderApprovalService creates a new tender approval service
|
// 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{
|
return &tenderApprovalService{
|
||||||
repository: repository,
|
repository: repository,
|
||||||
logger: logger,
|
tenderService: tenderService,
|
||||||
|
logger: logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +118,55 @@ func (s *tenderApprovalService) GetTenderApprovalByID(ctx context.Context, id st
|
|||||||
return tenderApproval, nil
|
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
|
// GetTenderApprovalByTenderAndCompany retrieves a tender approval by tender ID and company ID
|
||||||
func (s *tenderApprovalService) GetTenderApprovalByTenderAndCompany(ctx context.Context, tenderID, companyID string) (*TenderApproval, error) {
|
func (s *tenderApprovalService) GetTenderApprovalByTenderAndCompany(ctx context.Context, tenderID, companyID string) (*TenderApproval, error) {
|
||||||
tenderApproval, err := s.repository.GetByTenderAndCompany(ctx, tenderID, companyID)
|
tenderApproval, err := s.repository.GetByTenderAndCompany(ctx, tenderID, companyID)
|
||||||
@@ -130,6 +188,57 @@ func (s *tenderApprovalService) GetTenderApprovalByTenderAndCompany(ctx context.
|
|||||||
return tenderApproval, nil
|
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
|
// GetTenderApprovalsByTenderID retrieves all tender approvals for a specific tender
|
||||||
func (s *tenderApprovalService) GetTenderApprovalsByTenderID(ctx context.Context, tenderID string) ([]*TenderApproval, error) {
|
func (s *tenderApprovalService) GetTenderApprovalsByTenderID(ctx context.Context, tenderID string) ([]*TenderApproval, error) {
|
||||||
tenderApprovals, err := s.repository.GetByTenderID(ctx, tenderID)
|
tenderApprovals, err := s.repository.GetByTenderID(ctx, tenderID)
|
||||||
@@ -168,6 +277,57 @@ func (s *tenderApprovalService) GetTenderApprovalsByCompanyID(ctx context.Contex
|
|||||||
return tenderApprovals, nil
|
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
|
// GetTenderApprovalsByIDs retrieves multiple tender approvals by their IDs
|
||||||
func (s *tenderApprovalService) GetTenderApprovalsByIDs(ctx context.Context, ids []string) ([]*TenderApproval, error) {
|
func (s *tenderApprovalService) GetTenderApprovalsByIDs(ctx context.Context, ids []string) ([]*TenderApproval, error) {
|
||||||
if len(ids) == 0 {
|
if len(ids) == 0 {
|
||||||
@@ -234,6 +394,80 @@ func (s *tenderApprovalService) UpdateTenderApproval(ctx context.Context, id str
|
|||||||
return tenderApproval, nil
|
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
|
// DeleteTenderApproval deletes a tender approval
|
||||||
func (s *tenderApprovalService) DeleteTenderApproval(ctx context.Context, id string) error {
|
func (s *tenderApprovalService) DeleteTenderApproval(ctx context.Context, id string) error {
|
||||||
// Get tender approval to check if exists
|
// Get tender approval to check if exists
|
||||||
@@ -525,3 +759,213 @@ func (s *tenderApprovalService) GetTenderApprovalsBySubmissionMode(ctx context.C
|
|||||||
|
|
||||||
return tenderApprovals, total, nil
|
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