a342da193e
- Updated feedback repository and service methods to use a consistent naming convention, changing `NewTenderRepository` and similar methods to `NewRepository`. - Refactored feedback handler methods to improve clarity by renaming methods such as `ListFeedback` to `Search` and `GetFeedback` to `Get`. - Enhanced feedback response structures to include detailed company and tender information, improving the clarity of feedback data returned to API consumers. - Updated Swagger documentation to reflect changes in feedback response structures and endpoint paths, ensuring accurate representation of the API for consumers.
377 lines
9.7 KiB
Go
377 lines
9.7 KiB
Go
package company
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
"tm/pkg/logger"
|
|
orm "tm/pkg/mongo"
|
|
"tm/pkg/response"
|
|
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
)
|
|
|
|
// Repository defines the interface for company data operations
|
|
type Repository interface {
|
|
Create(ctx context.Context, company *Company) error
|
|
Update(ctx context.Context, company *Company) error
|
|
GetByID(ctx context.Context, id string) (*Company, error)
|
|
GetByIDs(ctx context.Context, ids []string) ([]Company, error)
|
|
GetByName(ctx context.Context, name string) (*Company, error)
|
|
GetByRegistrationNumber(ctx context.Context, registrationNumber string) (*Company, error)
|
|
GetByTaxID(ctx context.Context, taxID string) (*Company, error)
|
|
Search(ctx context.Context, form *SearchForm, pagination *response.Pagination) ([]Company, int64, error)
|
|
Delete(ctx context.Context, id string) error
|
|
UpdateStatus(ctx context.Context, id string, status CompanyStatus) error
|
|
UpdateVerification(ctx context.Context, id string, isVerified, isCompliant bool, complianceNotes *string) error
|
|
}
|
|
|
|
// companyRepository implements the Repository interface using the MongoDB ORM
|
|
type companyRepository struct {
|
|
ormRepo orm.Repository[Company]
|
|
logger logger.Logger
|
|
}
|
|
|
|
// NewCompanyRepository creates a new company repository
|
|
func NewRepository(mongoManager *orm.ConnectionManager, logger logger.Logger) Repository {
|
|
// Create indexes using the ORM's index management
|
|
indexes := []orm.Index{
|
|
*orm.NewIndex("registration_number_idx", bson.D{{Key: "registration_number", Value: 1}}),
|
|
}
|
|
|
|
// Create indexes
|
|
err := mongoManager.CreateIndexes("companies", indexes)
|
|
if err != nil {
|
|
logger.Warn("Failed to create company indexes", map[string]interface{}{
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
// Create ORM repository
|
|
ormRepo := orm.NewRepository[Company](mongoManager.GetCollection("companies"), logger)
|
|
|
|
return &companyRepository{
|
|
ormRepo: ormRepo,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// Create creates a new company
|
|
func (r *companyRepository) Create(ctx context.Context, company *Company) error {
|
|
// Set created/updated timestamps using Unix timestamps
|
|
now := time.Now().Unix()
|
|
company.SetCreatedAt(now)
|
|
|
|
// Use ORM to create company
|
|
err := r.ormRepo.Create(ctx, company)
|
|
if err != nil {
|
|
r.logger.Error("Failed to create company", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"name": company.Name,
|
|
"registration_number": company.RegistrationNumber,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Company created successfully", map[string]interface{}{
|
|
"company_id": company.ID,
|
|
"name": company.Name,
|
|
"type": company.Type,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetByID retrieves a company by ID
|
|
func (r *companyRepository) GetByID(ctx context.Context, id string) (*Company, error) {
|
|
company, err := r.ormRepo.FindByID(ctx, id)
|
|
if err != nil {
|
|
if errors.Is(err, orm.ErrDocumentNotFound) {
|
|
return nil, errors.New("company not found")
|
|
}
|
|
r.logger.Error("Failed to get company by ID", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"company_id": id,
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
return company, nil
|
|
}
|
|
|
|
// GetByIDs retrieves companies by IDs
|
|
func (r *companyRepository) GetByIDs(ctx context.Context, ids []string) ([]Company, error) {
|
|
objectIDs := make([]bson.ObjectID, len(ids))
|
|
for i, id := range ids {
|
|
objectID, err := bson.ObjectIDFromHex(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
objectIDs[i] = objectID
|
|
}
|
|
|
|
companies, err := r.ormRepo.FindAll(ctx, bson.M{"_id": bson.M{"$in": objectIDs}}, orm.NewPaginationBuilder().Build())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return companies.Items, nil
|
|
}
|
|
|
|
// GetByName retrieves a company by name
|
|
func (r *companyRepository) GetByName(ctx context.Context, name string) (*Company, error) {
|
|
company, err := r.ormRepo.FindOne(ctx, bson.M{"name": name})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return company, nil
|
|
}
|
|
|
|
// GetByRegistrationNumber retrieves a company by registration number
|
|
func (r *companyRepository) GetByRegistrationNumber(ctx context.Context, registrationNumber string) (*Company, error) {
|
|
company, err := r.ormRepo.FindOne(ctx, bson.M{"registration_number": registrationNumber})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return company, nil
|
|
}
|
|
|
|
// GetByTaxID retrieves a company by tax ID
|
|
func (r *companyRepository) GetByTaxID(ctx context.Context, taxID string) (*Company, error) {
|
|
company, err := r.ormRepo.FindOne(ctx, bson.M{"tax_id": taxID})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return company, nil
|
|
}
|
|
|
|
// Update updates a company
|
|
func (r *companyRepository) Update(ctx context.Context, company *Company) error {
|
|
// Set updated timestamp using Unix timestamp
|
|
company.SetUpdatedAt(time.Now().Unix())
|
|
|
|
// Use ORM to update company
|
|
err := r.ormRepo.Update(ctx, company)
|
|
if err != nil {
|
|
r.logger.Error("Failed to update company", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"company_id": company.ID,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Company updated successfully", map[string]interface{}{
|
|
"company_id": company.ID,
|
|
"name": company.Name,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// Delete deletes a company
|
|
func (r *companyRepository) Delete(ctx context.Context, id string) error {
|
|
// Get company first
|
|
_, err := r.GetByID(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Update in database
|
|
err = r.ormRepo.Delete(ctx, id)
|
|
if err != nil {
|
|
r.logger.Error("Failed to delete company", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"company_id": id,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Company deleted successfully", map[string]interface{}{
|
|
"company_id": id,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// Search retrieves companies with search and filters
|
|
func (r *companyRepository) Search(ctx context.Context, form *SearchForm, pagination *response.Pagination) ([]Company, int64, error) {
|
|
// Build filter
|
|
filter := bson.M{}
|
|
|
|
if form.Search != nil {
|
|
filter["$text"] = bson.M{"$search": *form.Search}
|
|
}
|
|
|
|
if form.Type != nil {
|
|
filter["type"] = *form.Type
|
|
}
|
|
|
|
if form.Status != nil {
|
|
filter["status"] = *form.Status
|
|
}
|
|
|
|
if form.Industry != nil {
|
|
filter["industry"] = *form.Industry
|
|
}
|
|
|
|
if form.IsVerified != nil {
|
|
filter["is_verified"] = *form.IsVerified
|
|
}
|
|
|
|
if form.IsCompliant != nil {
|
|
filter["is_compliant"] = *form.IsCompliant
|
|
}
|
|
|
|
if form.Language != nil {
|
|
filter["language"] = *form.Language
|
|
}
|
|
|
|
if form.Currency != nil {
|
|
filter["currency"] = *form.Currency
|
|
}
|
|
|
|
// Tag filters
|
|
if len(form.CPVCodes) > 0 {
|
|
filter["tags.cpv_codes"] = bson.M{"$in": form.CPVCodes}
|
|
}
|
|
|
|
if len(form.Categories) > 0 {
|
|
filter["tags.categories"] = bson.M{"$in": form.Categories}
|
|
}
|
|
|
|
if len(form.Keywords) > 0 {
|
|
filter["tags.keywords"] = bson.M{"$in": form.Keywords}
|
|
}
|
|
|
|
if len(form.Specializations) > 0 {
|
|
filter["tags.specializations"] = bson.M{"$in": form.Specializations}
|
|
}
|
|
|
|
// Range filters
|
|
if form.EmployeeCountMin != nil || form.EmployeeCountMax != nil {
|
|
rangeFilter := bson.M{}
|
|
if form.EmployeeCountMin != nil {
|
|
rangeFilter["$gte"] = *form.EmployeeCountMin
|
|
}
|
|
if form.EmployeeCountMax != nil {
|
|
rangeFilter["$lte"] = *form.EmployeeCountMax
|
|
}
|
|
filter["employee_count"] = rangeFilter
|
|
}
|
|
|
|
if form.AnnualRevenueMin != nil || form.AnnualRevenueMax != nil {
|
|
rangeFilter := bson.M{}
|
|
if form.AnnualRevenueMin != nil {
|
|
rangeFilter["$gte"] = *form.AnnualRevenueMin
|
|
}
|
|
if form.AnnualRevenueMax != nil {
|
|
rangeFilter["$lte"] = *form.AnnualRevenueMax
|
|
}
|
|
filter["annual_revenue"] = rangeFilter
|
|
}
|
|
|
|
if form.FoundedYearMin != nil || form.FoundedYearMax != nil {
|
|
rangeFilter := bson.M{}
|
|
if form.FoundedYearMin != nil {
|
|
rangeFilter["$gte"] = *form.FoundedYearMin
|
|
}
|
|
if form.FoundedYearMax != nil {
|
|
rangeFilter["$lte"] = *form.FoundedYearMax
|
|
}
|
|
filter["founded_year"] = rangeFilter
|
|
}
|
|
|
|
// Build sort
|
|
sort := "created_at"
|
|
if pagination.SortBy != "" {
|
|
sort = pagination.SortBy
|
|
}
|
|
|
|
sortOrder := "desc"
|
|
if pagination.SortOrder != "" {
|
|
sortOrder = pagination.SortOrder
|
|
}
|
|
|
|
// Build pagination
|
|
paginationBuilder := orm.NewPaginationBuilder().
|
|
Limit(pagination.Limit).
|
|
Skip(pagination.Offset).
|
|
SortBy(sort, sortOrder).
|
|
Build()
|
|
|
|
// Use ORM to find users
|
|
result, err := r.ormRepo.FindAll(ctx, filter, paginationBuilder)
|
|
if err != nil {
|
|
r.logger.Error("Failed to list users", map[string]interface{}{
|
|
"error": err.Error(),
|
|
})
|
|
return nil, 0, err
|
|
}
|
|
|
|
return result.Items, result.TotalCount, nil
|
|
}
|
|
|
|
// UpdateStatus updates company status
|
|
func (r *companyRepository) UpdateStatus(ctx context.Context, id string, status CompanyStatus) error {
|
|
// Get company first
|
|
company, err := r.GetByID(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Update status
|
|
company.Status = status
|
|
company.SetUpdatedAt(time.Now().Unix())
|
|
|
|
// Update in database
|
|
err = r.ormRepo.Update(ctx, company)
|
|
if err != nil {
|
|
r.logger.Error("Failed to update company status", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"company_id": id,
|
|
"status": status,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Company status updated successfully", map[string]interface{}{
|
|
"company_id": id,
|
|
"status": status,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdateVerification updates company verification status
|
|
func (r *companyRepository) UpdateVerification(ctx context.Context, id string, isVerified, isCompliant bool, complianceNotes *string) error {
|
|
// Get company first
|
|
company, err := r.GetByID(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Update verification fields
|
|
company.IsVerified = isVerified
|
|
company.IsCompliant = isCompliant
|
|
company.ComplianceNotes = complianceNotes
|
|
company.SetUpdatedAt(time.Now().Unix())
|
|
|
|
// Update in database
|
|
err = r.ormRepo.Update(ctx, company)
|
|
if err != nil {
|
|
r.logger.Error("Failed to update company verification", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"company_id": id,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Company verification updated successfully", map[string]interface{}{
|
|
"company_id": id,
|
|
"is_verified": isVerified,
|
|
"is_compliant": isCompliant,
|
|
})
|
|
|
|
return nil
|
|
}
|