196 lines
5.8 KiB
Go
196 lines
5.8 KiB
Go
package processor
|
|
|
|
import (
|
|
"apskel-pos-be/internal/mappers"
|
|
"apskel-pos-be/internal/models"
|
|
"apskel-pos-be/internal/repository"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type CustomerProcessor struct {
|
|
customerRepo *repository.CustomerRepository
|
|
}
|
|
|
|
func NewCustomerProcessor(customerRepo *repository.CustomerRepository) *CustomerProcessor {
|
|
return &CustomerProcessor{
|
|
customerRepo: customerRepo,
|
|
}
|
|
}
|
|
|
|
// CreateCustomer creates a new customer
|
|
func (p *CustomerProcessor) CreateCustomer(ctx context.Context, req *models.CreateCustomerRequest, organizationID uuid.UUID) (*models.CustomerResponse, error) {
|
|
if req.Email != nil {
|
|
existingCustomer, err := p.customerRepo.GetByEmail(ctx, *req.Email, organizationID)
|
|
if err == nil && existingCustomer != nil {
|
|
return nil, errors.New("email already exists for this organization")
|
|
}
|
|
}
|
|
|
|
// Convert request to entity
|
|
customer := mappers.ToCustomerEntity(req, organizationID)
|
|
|
|
// Create customer
|
|
err := p.customerRepo.Create(ctx, customer)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create customer: %w", err)
|
|
}
|
|
|
|
return mappers.ToCustomerResponse(customer), nil
|
|
}
|
|
|
|
// GetCustomer retrieves a customer by ID
|
|
func (p *CustomerProcessor) GetCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*models.CustomerResponse, error) {
|
|
customer, err := p.customerRepo.GetByIDAndOrganization(ctx, customerID, organizationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("customer not found: %w", err)
|
|
}
|
|
|
|
return mappers.ToCustomerResponse(customer), nil
|
|
}
|
|
|
|
// ListCustomers retrieves customers with pagination and filtering
|
|
func (p *CustomerProcessor) ListCustomers(ctx context.Context, query *models.ListCustomersQuery, organizationID uuid.UUID) (*models.PaginatedResponse[models.CustomerResponse], error) {
|
|
// Set default values
|
|
if query.Page <= 0 {
|
|
query.Page = 1
|
|
}
|
|
if query.Limit <= 0 {
|
|
query.Limit = 10
|
|
}
|
|
if query.Limit > 100 {
|
|
query.Limit = 100
|
|
}
|
|
|
|
offset := (query.Page - 1) * query.Limit
|
|
|
|
// Get customers from repository
|
|
customers, total, err := p.customerRepo.List(
|
|
ctx,
|
|
organizationID,
|
|
offset,
|
|
query.Limit,
|
|
query.Search,
|
|
query.IsActive,
|
|
query.IsDefault,
|
|
query.SortBy,
|
|
query.SortOrder,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list customers: %w", err)
|
|
}
|
|
|
|
// Convert to responses
|
|
responses := mappers.ToCustomerResponses(customers)
|
|
|
|
// Calculate pagination info
|
|
totalPages := int((total + int64(query.Limit) - 1) / int64(query.Limit))
|
|
|
|
return &models.PaginatedResponse[models.CustomerResponse]{
|
|
Data: responses,
|
|
Pagination: models.Pagination{
|
|
Page: query.Page,
|
|
Limit: query.Limit,
|
|
Total: total,
|
|
TotalPages: totalPages,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
// UpdateCustomer updates an existing customer
|
|
func (p *CustomerProcessor) UpdateCustomer(ctx context.Context, customerID, organizationID uuid.UUID, req *models.UpdateCustomerRequest) (*models.CustomerResponse, error) {
|
|
// Get existing customer
|
|
customer, err := p.customerRepo.GetByIDAndOrganization(ctx, customerID, organizationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("customer not found: %w", err)
|
|
}
|
|
|
|
// Check if email is already taken by another customer within the organization
|
|
if req.Email != nil && *req.Email != *customer.Email {
|
|
existingCustomer, err := p.customerRepo.GetByEmail(ctx, *req.Email, organizationID)
|
|
if err == nil && existingCustomer != nil && existingCustomer.ID != customerID {
|
|
return nil, errors.New("email already exists for this organization")
|
|
}
|
|
}
|
|
|
|
// Update customer fields
|
|
mappers.UpdateCustomerEntity(customer, req)
|
|
|
|
// Save updated customer
|
|
err = p.customerRepo.Update(ctx, customer)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to update customer: %w", err)
|
|
}
|
|
|
|
return mappers.ToCustomerResponse(customer), nil
|
|
}
|
|
|
|
// DeleteCustomer deletes a customer
|
|
func (p *CustomerProcessor) DeleteCustomer(ctx context.Context, customerID, organizationID uuid.UUID) error {
|
|
// Get existing customer
|
|
customer, err := p.customerRepo.GetByIDAndOrganization(ctx, customerID, organizationID)
|
|
if err != nil {
|
|
return fmt.Errorf("customer not found: %w", err)
|
|
}
|
|
|
|
// Prevent deletion of default customer
|
|
if customer.IsDefault {
|
|
return errors.New("cannot delete default customer")
|
|
}
|
|
|
|
// Delete customer
|
|
err = p.customerRepo.Delete(ctx, customerID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete customer: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *CustomerProcessor) SetDefaultCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*models.CustomerResponse, error) {
|
|
_, err := p.customerRepo.GetByIDAndOrganization(ctx, customerID, organizationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("customer not found: %w", err)
|
|
}
|
|
|
|
// Set as default
|
|
err = p.customerRepo.SetAsDefault(ctx, customerID, organizationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to set default customer: %w", err)
|
|
}
|
|
|
|
// Get updated customer
|
|
updatedCustomer, err := p.customerRepo.GetByID(ctx, customerID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get updated customer: %w", err)
|
|
}
|
|
|
|
return mappers.ToCustomerResponse(updatedCustomer), nil
|
|
}
|
|
|
|
func (p *CustomerProcessor) GetDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*models.CustomerResponse, error) {
|
|
customer, err := p.customerRepo.GetDefaultCustomer(ctx, organizationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("default customer not found: %w", err)
|
|
}
|
|
|
|
return mappers.ToCustomerResponse(customer), nil
|
|
}
|
|
|
|
func (p *CustomerProcessor) EnsureDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*models.CustomerResponse, error) {
|
|
customer, err := p.customerRepo.GetDefaultCustomer(ctx, organizationID)
|
|
if err == nil {
|
|
return mappers.ToCustomerResponse(customer), nil
|
|
}
|
|
|
|
defaultCustomer, err := p.customerRepo.CreateDefaultCustomer(ctx, organizationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create default customer: %w", err)
|
|
}
|
|
|
|
return mappers.ToCustomerResponse(defaultCustomer), nil
|
|
}
|