2fbf329182
continuous-integration/drone/push Build is passing
- Removed the resetting of `SubmissionMode` in the `Reject` method of the `TenderApproval` entity, ensuring that the submission mode is preserved upon rejection. - Updated the `GetCompanyTenderApprovalStats` method in the repository to count submissions by mode without filtering by status, enhancing the accuracy of statistics. - Adjusted the `ToggleTenderApproval` method in the service to set the `SubmissionMode` when rejecting a tender, ensuring consistent handling of submission modes across approval states. This update improves the clarity and functionality of tender approval processes, ensuring that submission modes are correctly managed during approval and rejection scenarios.
590 lines
19 KiB
Go
590 lines
19 KiB
Go
package tender_approval
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
"tm/pkg/logger"
|
|
"tm/pkg/mongo"
|
|
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
mongodriver "go.mongodb.org/mongo-driver/v2/mongo"
|
|
)
|
|
|
|
// Repository defines the interface for tender approval data operations
|
|
type Repository interface {
|
|
Create(ctx context.Context, tenderApproval *TenderApproval) error
|
|
GetByID(ctx context.Context, id string) (*TenderApproval, error)
|
|
GetByTenderAndCompany(ctx context.Context, tenderID, companyID string) (*TenderApproval, error)
|
|
GetByTenderID(ctx context.Context, tenderID string) ([]*TenderApproval, error)
|
|
GetByCompanyID(ctx context.Context, companyID string, submissionMode *SubmissionMode, status *ApprovalStatus, limit int, offset int, from *int64, to *int64) ([]*TenderApproval, int64, error)
|
|
GetByIDs(ctx context.Context, ids []string) ([]*TenderApproval, error)
|
|
Update(ctx context.Context, tenderApproval *TenderApproval) error
|
|
Delete(ctx context.Context, id string) error
|
|
List(ctx context.Context, limit, offset int) ([]*TenderApproval, error)
|
|
Search(ctx context.Context, tenderID *string, companyID *string, status []ApprovalStatus, submissionMode []SubmissionMode, createdAtFrom *int64, createdAtTo *int64, limit, offset int, sortBy, sortOrder string) ([]*TenderApproval, error)
|
|
Count(ctx context.Context) (int64, error)
|
|
CountByStatus(ctx context.Context, status ApprovalStatus) (int64, error)
|
|
CountBySubmissionMode(ctx context.Context, submissionMode SubmissionMode) (int64, error)
|
|
CountByTenderID(ctx context.Context, tenderID string) (int64, error)
|
|
CountByCompanyID(ctx context.Context, companyID string) (int64, error)
|
|
GetTenderApprovalStats(ctx context.Context) (*TenderApprovalStatsResponse, error)
|
|
GetCompanyTenderApprovalStats(ctx context.Context, companyID string) (*CompanyTenderApprovalStatsResponse, error)
|
|
SearchByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error)
|
|
ListRejectedTenderIDsByCompanyID(ctx context.Context, companyID string) ([]string, error)
|
|
}
|
|
|
|
// tenderApprovalRepository implements the Repository interface using the MongoDB ORM
|
|
type tenderApprovalRepository struct {
|
|
ormRepo mongo.Repository[TenderApproval]
|
|
logger logger.Logger
|
|
}
|
|
|
|
// NewTenderApprovalRepository creates a new tender approval repository
|
|
func NewRepository(mongoManager *mongo.ConnectionManager, logger logger.Logger) Repository {
|
|
// Create indexes using the ORM's index management
|
|
indexes := []mongo.Index{
|
|
*mongo.CreateUniqueIndex("tender_company_idx", bson.D{{Key: "tender_id", Value: 1}, {Key: "company_id", Value: 1}}),
|
|
*mongo.NewIndex("tender_id_idx", bson.D{{Key: "tender_id", Value: 1}}),
|
|
*mongo.NewIndex("company_id_idx", bson.D{{Key: "company_id", Value: 1}}),
|
|
*mongo.NewIndex("status_idx", bson.D{{Key: "status", Value: 1}}),
|
|
*mongo.NewIndex("submission_mode_idx", bson.D{{Key: "submission_mode", Value: 1}}),
|
|
*mongo.NewIndex("created_at_idx", bson.D{{Key: "created_at", Value: -1}}),
|
|
*mongo.NewIndex("updated_at_idx", bson.D{{Key: "updated_at", Value: -1}}),
|
|
}
|
|
|
|
// Create indexes
|
|
err := mongoManager.CreateIndexes("tender_approvals", indexes)
|
|
if err != nil {
|
|
logger.Warn("Failed to create tender approval indexes", map[string]interface{}{
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
// Create ORM repository
|
|
ormRepo := mongo.NewRepository[TenderApproval](mongoManager.GetCollection("tender_approvals"), logger)
|
|
|
|
return &tenderApprovalRepository{
|
|
ormRepo: ormRepo,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// Create creates a new tender approval
|
|
func (r *tenderApprovalRepository) Create(ctx context.Context, tenderApproval *TenderApproval) error {
|
|
// Set created/updated timestamps using Unix timestamps
|
|
now := time.Now().Unix()
|
|
tenderApproval.SetCreatedAt(now)
|
|
tenderApproval.SetUpdatedAt(now)
|
|
|
|
// Use ORM to create tender approval
|
|
err := r.ormRepo.Create(ctx, tenderApproval)
|
|
if err != nil {
|
|
r.logger.Error("Failed to create tender approval", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"tender_id": tenderApproval.TenderID,
|
|
"company_id": tenderApproval.CompanyID,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Tender approval created successfully", map[string]interface{}{
|
|
"tender_approval_id": tenderApproval.ID,
|
|
"tender_id": tenderApproval.TenderID,
|
|
"company_id": tenderApproval.CompanyID,
|
|
"status": tenderApproval.Status,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetByID retrieves a tender approval by ID
|
|
func (r *tenderApprovalRepository) GetByID(ctx context.Context, id string) (*TenderApproval, error) {
|
|
tenderApproval, err := r.ormRepo.FindByID(ctx, id)
|
|
if err != nil {
|
|
if errors.Is(err, mongo.ErrDocumentNotFound) {
|
|
return nil, ErrTenderApprovalNotFound
|
|
}
|
|
r.logger.Error("Failed to get tender approval by ID", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"tender_approval_id": id,
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
return tenderApproval, nil
|
|
}
|
|
|
|
// GetByTenderAndCompany retrieves a tender approval by tender ID and company ID
|
|
func (r *tenderApprovalRepository) GetByTenderAndCompany(ctx context.Context, tenderID, companyID string) (*TenderApproval, error) {
|
|
filter := bson.M{
|
|
"tender_id": tenderID,
|
|
"company_id": companyID,
|
|
}
|
|
|
|
tenderApproval, err := r.ormRepo.FindOne(ctx, filter)
|
|
if err != nil {
|
|
if errors.Is(err, mongo.ErrDocumentNotFound) {
|
|
return nil, ErrTenderApprovalNotFound
|
|
}
|
|
r.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
|
|
}
|
|
|
|
return tenderApproval, nil
|
|
}
|
|
|
|
// GetByTenderID retrieves all tender approvals for a specific tender
|
|
func (r *tenderApprovalRepository) GetByTenderID(ctx context.Context, tenderID string) ([]*TenderApproval, error) {
|
|
filter := bson.M{"tender_id": tenderID}
|
|
|
|
result, err := r.ormRepo.FindAll(ctx, filter, mongo.NewPaginationBuilder().SortDesc("created_at").Build())
|
|
if err != nil {
|
|
r.logger.Error("Failed to get tender approvals by tender ID", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"tender_id": tenderID,
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
// Convert []TenderApproval to []*TenderApproval
|
|
tenderApprovals := make([]*TenderApproval, len(result.Items))
|
|
for i := range result.Items {
|
|
tenderApprovals[i] = &result.Items[i]
|
|
}
|
|
|
|
return tenderApprovals, nil
|
|
}
|
|
|
|
// GetByCompanyID retrieves all tender approvals for a specific company with optional filters
|
|
func (r *tenderApprovalRepository) GetByCompanyID(ctx context.Context, companyID string, submissionMode *SubmissionMode, status *ApprovalStatus, limit int, offset int, from *int64, to *int64) ([]*TenderApproval, int64, error) {
|
|
filter := bson.M{"company_id": companyID}
|
|
|
|
pagination := mongo.Pagination{
|
|
Limit: limit,
|
|
Skip: offset,
|
|
SortField: "created_at",
|
|
SortOrder: -1,
|
|
}
|
|
|
|
// Add submission mode filter if provided
|
|
if submissionMode != nil {
|
|
filter["submission_mode"] = *submissionMode
|
|
}
|
|
|
|
// Add status filter if provided
|
|
if status != nil {
|
|
filter["status"] = *status
|
|
}
|
|
|
|
if from != nil {
|
|
filter["created_at"] = bson.M{"$gte": *from}
|
|
}
|
|
if to != nil {
|
|
filter["created_at"] = bson.M{"$lte": *to}
|
|
}
|
|
|
|
result, err := r.ormRepo.FindAll(ctx, filter, pagination)
|
|
if err != nil {
|
|
r.logger.Error("Failed to get tender approvals by company ID", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"company_id": companyID,
|
|
})
|
|
return nil, 0, err
|
|
}
|
|
|
|
// Convert []TenderApproval to []*TenderApproval
|
|
tenderApprovals := make([]*TenderApproval, len(result.Items))
|
|
for i := range result.Items {
|
|
tenderApprovals[i] = &result.Items[i]
|
|
}
|
|
|
|
return tenderApprovals, result.TotalCount, nil
|
|
}
|
|
|
|
// GetByIDs retrieves multiple tender approvals by their IDs
|
|
func (r *tenderApprovalRepository) GetByIDs(ctx context.Context, ids []string) ([]*TenderApproval, error) {
|
|
if len(ids) == 0 {
|
|
return []*TenderApproval{}, nil
|
|
}
|
|
|
|
// Convert string IDs to ObjectIDs for MongoDB query
|
|
objectIDs := make([]interface{}, len(ids))
|
|
for i, id := range ids {
|
|
objectID, err := bson.ObjectIDFromHex(id)
|
|
if err != nil {
|
|
r.logger.Warn("Invalid tender approval ID format", map[string]interface{}{
|
|
"id": id,
|
|
"error": err.Error(),
|
|
})
|
|
continue
|
|
}
|
|
objectIDs[i] = objectID
|
|
}
|
|
|
|
if len(objectIDs) == 0 {
|
|
return []*TenderApproval{}, nil
|
|
}
|
|
|
|
filter := bson.M{"_id": bson.M{"$in": objectIDs}}
|
|
result, err := r.ormRepo.FindAll(ctx, filter, mongo.NewPaginationBuilder().Limit(len(ids)).Build())
|
|
if err != nil {
|
|
r.logger.Error("Failed to get tender approvals by IDs", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"ids": ids,
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
// Convert []TenderApproval to []*TenderApproval
|
|
tenderApprovals := make([]*TenderApproval, len(result.Items))
|
|
for i := range result.Items {
|
|
tenderApprovals[i] = &result.Items[i]
|
|
}
|
|
|
|
r.logger.Info("Retrieved tender approvals by IDs", map[string]interface{}{
|
|
"requested_count": len(ids),
|
|
"found_count": len(tenderApprovals),
|
|
})
|
|
|
|
return tenderApprovals, nil
|
|
}
|
|
|
|
// Update updates a tender approval
|
|
func (r *tenderApprovalRepository) Update(ctx context.Context, tenderApproval *TenderApproval) error {
|
|
// Set updated timestamp using Unix timestamp
|
|
tenderApproval.SetUpdatedAt(time.Now().Unix())
|
|
|
|
// Use ORM to update tender approval
|
|
err := r.ormRepo.Update(ctx, tenderApproval)
|
|
if err != nil {
|
|
r.logger.Error("Failed to update tender approval", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"tender_approval_id": tenderApproval.ID,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Tender approval updated successfully", map[string]interface{}{
|
|
"tender_approval_id": tenderApproval.ID,
|
|
"tender_id": tenderApproval.TenderID,
|
|
"company_id": tenderApproval.CompanyID,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// Delete deletes a tender approval
|
|
func (r *tenderApprovalRepository) Delete(ctx context.Context, id string) error {
|
|
// Get tender approval first
|
|
tenderApproval, err := r.GetByID(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Delete from database
|
|
err = r.ormRepo.Delete(ctx, id)
|
|
if err != nil {
|
|
r.logger.Error("Failed to delete tender approval", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"tender_approval_id": id,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Tender approval deleted successfully", map[string]interface{}{
|
|
"tender_approval_id": id,
|
|
"tender_id": tenderApproval.TenderID,
|
|
"company_id": tenderApproval.CompanyID,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// List retrieves tender approvals with pagination
|
|
func (r *tenderApprovalRepository) List(ctx context.Context, limit, offset int) ([]*TenderApproval, error) {
|
|
// Build pagination
|
|
pagination := mongo.NewPaginationBuilder().
|
|
Limit(limit).
|
|
Skip(offset).
|
|
SortDesc("created_at").
|
|
Build()
|
|
|
|
// Use ORM to find tender approvals
|
|
result, err := r.ormRepo.FindAll(ctx, bson.M{}, pagination)
|
|
if err != nil {
|
|
r.logger.Error("Failed to list tender approvals", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"limit": limit,
|
|
"offset": offset,
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
// Convert []TenderApproval to []*TenderApproval
|
|
tenderApprovals := make([]*TenderApproval, len(result.Items))
|
|
for i := range result.Items {
|
|
tenderApprovals[i] = &result.Items[i]
|
|
}
|
|
|
|
return tenderApprovals, nil
|
|
}
|
|
|
|
// Search retrieves tender approvals with search and filters
|
|
func (r *tenderApprovalRepository) Search(ctx context.Context, tenderID *string, companyID *string, status []ApprovalStatus, submissionMode []SubmissionMode, createdAtFrom *int64, createdAtTo *int64, limit, offset int, sortBy, sortOrder string) ([]*TenderApproval, error) {
|
|
// Build filter
|
|
filter := bson.M{}
|
|
|
|
if tenderID != nil {
|
|
filter["tender_id"] = *tenderID
|
|
}
|
|
|
|
if companyID != nil {
|
|
filter["company_id"] = *companyID
|
|
}
|
|
|
|
if len(status) > 0 {
|
|
statusStrings := make([]string, len(status))
|
|
for i, s := range status {
|
|
statusStrings[i] = string(s)
|
|
}
|
|
filter["status"] = bson.M{"$in": statusStrings}
|
|
}
|
|
|
|
if len(submissionMode) > 0 {
|
|
modeStrings := make([]string, len(submissionMode))
|
|
for i, m := range submissionMode {
|
|
modeStrings[i] = string(m)
|
|
}
|
|
filter["submission_mode"] = bson.M{"$in": modeStrings}
|
|
}
|
|
|
|
// Date range filters
|
|
if createdAtFrom != nil || createdAtTo != nil {
|
|
dateFilter := bson.M{}
|
|
if createdAtFrom != nil {
|
|
dateFilter["$gte"] = *createdAtFrom
|
|
}
|
|
if createdAtTo != nil {
|
|
dateFilter["$lte"] = *createdAtTo
|
|
}
|
|
filter["created_at"] = dateFilter
|
|
}
|
|
|
|
// Build pagination
|
|
pagination := mongo.NewPaginationBuilder().
|
|
Limit(limit).
|
|
Skip(offset)
|
|
|
|
// Set sort
|
|
if sortBy != "" {
|
|
if sortOrder == "desc" {
|
|
pagination.SortDesc(sortBy)
|
|
} else {
|
|
pagination.SortAsc(sortBy)
|
|
}
|
|
} else {
|
|
pagination.SortDesc("created_at") // Default sort
|
|
}
|
|
|
|
// Use ORM to find tender approvals
|
|
result, err := r.ormRepo.FindAll(ctx, filter, pagination.Build())
|
|
if err != nil {
|
|
r.logger.Error("Failed to search tender approvals", map[string]interface{}{
|
|
"error": err.Error(),
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
// Convert []TenderApproval to []*TenderApproval
|
|
tenderApprovals := make([]*TenderApproval, len(result.Items))
|
|
for i := range result.Items {
|
|
tenderApprovals[i] = &result.Items[i]
|
|
}
|
|
|
|
return tenderApprovals, nil
|
|
}
|
|
|
|
// Count counts all tender approvals
|
|
func (r *tenderApprovalRepository) Count(ctx context.Context) (int64, error) {
|
|
count, err := r.ormRepo.Count(ctx, bson.M{})
|
|
if err != nil {
|
|
r.logger.Error("Failed to count tender approvals", map[string]interface{}{
|
|
"error": err.Error(),
|
|
})
|
|
return 0, err
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// CountByStatus counts tender approvals by status
|
|
func (r *tenderApprovalRepository) CountByStatus(ctx context.Context, status ApprovalStatus) (int64, error) {
|
|
filter := bson.M{"status": string(status)}
|
|
|
|
count, err := r.ormRepo.Count(ctx, filter)
|
|
if err != nil {
|
|
r.logger.Error("Failed to count tender approvals by status", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"status": status,
|
|
})
|
|
return 0, err
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// CountBySubmissionMode counts tender approvals by submission mode
|
|
func (r *tenderApprovalRepository) CountBySubmissionMode(ctx context.Context, submissionMode SubmissionMode) (int64, error) {
|
|
filter := bson.M{"submission_mode": string(submissionMode)}
|
|
|
|
count, err := r.ormRepo.Count(ctx, filter)
|
|
if err != nil {
|
|
r.logger.Error("Failed to count tender approvals by submission mode", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"submission_mode": submissionMode,
|
|
})
|
|
return 0, err
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// CountByTenderID counts tender approvals for a specific tender
|
|
func (r *tenderApprovalRepository) CountByTenderID(ctx context.Context, tenderID string) (int64, error) {
|
|
filter := bson.M{"tender_id": tenderID}
|
|
|
|
count, err := r.ormRepo.Count(ctx, filter)
|
|
if err != nil {
|
|
r.logger.Error("Failed to count tender approvals by tender ID", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"tender_id": tenderID,
|
|
})
|
|
return 0, err
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// CountByCompanyID counts tender approvals for a specific company
|
|
func (r *tenderApprovalRepository) CountByCompanyID(ctx context.Context, companyID string) (int64, error) {
|
|
filter := bson.M{"company_id": companyID}
|
|
|
|
count, err := r.ormRepo.Count(ctx, filter)
|
|
if err != nil {
|
|
r.logger.Error("Failed to count tender approvals by company ID", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"company_id": companyID,
|
|
})
|
|
return 0, err
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// GetTenderApprovalStats returns tender approval statistics
|
|
func (r *tenderApprovalRepository) GetTenderApprovalStats(ctx context.Context) (*TenderApprovalStatsResponse, error) {
|
|
// Get basic counts
|
|
totalApprovals, _ := r.Count(ctx)
|
|
submittedTenders, _ := r.CountByStatus(ctx, ApprovalStatusSubmitted)
|
|
rejectedTenders, _ := r.CountByStatus(ctx, ApprovalStatusRejected)
|
|
|
|
stats := &TenderApprovalStatsResponse{
|
|
TotalApprovals: totalApprovals,
|
|
SubmittedTenders: submittedTenders,
|
|
RejectedTenders: rejectedTenders,
|
|
LastUpdated: time.Now().Unix(),
|
|
}
|
|
|
|
return stats, nil
|
|
}
|
|
|
|
// GetCompanyTenderApprovalStats returns company-specific tender approval statistics
|
|
func (r *tenderApprovalRepository) GetCompanyTenderApprovalStats(ctx context.Context, companyID string) (*CompanyTenderApprovalStatsResponse, error) {
|
|
// Get company-specific counts
|
|
totalApprovals, _ := r.CountByCompanyID(ctx, companyID)
|
|
|
|
// Count by status for this company
|
|
submittedFilter := bson.M{"company_id": companyID, "status": string(ApprovalStatusSubmitted)}
|
|
submittedTenders, _ := r.ormRepo.Count(ctx, submittedFilter)
|
|
|
|
rejectedFilter := bson.M{"company_id": companyID, "status": string(ApprovalStatusRejected)}
|
|
rejectedTenders, _ := r.ormRepo.Count(ctx, rejectedFilter)
|
|
|
|
// Count by submission mode for this company (includes submitted and rejected decisions).
|
|
selfApplyFilter := bson.M{"company_id": companyID, "submission_mode": string(SubmissionModeSelfApply)}
|
|
selfApplyCount, _ := r.ormRepo.Count(ctx, selfApplyFilter)
|
|
|
|
partnershipFilter := bson.M{"company_id": companyID, "submission_mode": string(SubmissionModePartnership)}
|
|
partnershipCount, _ := r.ormRepo.Count(ctx, partnershipFilter)
|
|
|
|
stats := &CompanyTenderApprovalStatsResponse{
|
|
CompanyID: companyID,
|
|
TotalApprovals: totalApprovals,
|
|
SubmittedTenders: submittedTenders,
|
|
RejectedTenders: rejectedTenders,
|
|
SelfApplyCount: selfApplyCount,
|
|
PartnershipCount: partnershipCount,
|
|
LastUpdated: time.Now().Unix(),
|
|
}
|
|
|
|
return stats, nil
|
|
}
|
|
|
|
// ListRejectedTenderIDsByCompanyID returns distinct tender IDs rejected by a company.
|
|
func (r *tenderApprovalRepository) ListRejectedTenderIDsByCompanyID(ctx context.Context, companyID string) ([]string, error) {
|
|
pipeline := mongodriver.Pipeline{
|
|
{{Key: "$match", Value: bson.M{
|
|
"company_id": companyID,
|
|
"status": string(ApprovalStatusRejected),
|
|
}}},
|
|
{{Key: "$group", Value: bson.M{"_id": "$tender_id"}}},
|
|
}
|
|
|
|
results, err := r.ormRepo.Aggregate(ctx, pipeline)
|
|
if err != nil {
|
|
r.logger.Error("Failed to list rejected tender IDs by company", map[string]interface{}{
|
|
"company_id": companyID,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
return aggregateStringIDs(results), nil
|
|
}
|
|
|
|
// SearchByCriteria searches tender approvals using search criteria
|
|
func (r *tenderApprovalRepository) SearchByCriteria(ctx context.Context, criteria *TenderApprovalSearchCriteria) ([]*TenderApproval, error) {
|
|
// Convert criteria to search parameters
|
|
var status []ApprovalStatus
|
|
if criteria.Status != nil {
|
|
status = criteria.Status
|
|
}
|
|
|
|
var submissionMode []SubmissionMode
|
|
if criteria.SubmissionMode != nil {
|
|
submissionMode = criteria.SubmissionMode
|
|
}
|
|
|
|
// Use the search method
|
|
return r.Search(ctx, criteria.TenderID, criteria.CompanyID, status, submissionMode, criteria.CreatedAtFrom, criteria.CreatedAtTo, criteria.Limit, criteria.Offset, "created_at", "desc")
|
|
}
|
|
|
|
func aggregateStringIDs(results []bson.M) []string {
|
|
ids := make([]string, 0, len(results))
|
|
for _, result := range results {
|
|
switch id := result["_id"].(type) {
|
|
case string:
|
|
if strings.TrimSpace(id) != "" {
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
}
|
|
return ids
|
|
}
|