package customer import ( "enaklo-pos-be/internal/common/logger" "enaklo-pos-be/internal/common/mycontext" "enaklo-pos-be/internal/constants" "enaklo-pos-be/internal/entity" "github.com/pkg/errors" "go.uber.org/zap" "strings" ) type Repository interface { Create(ctx mycontext.Context, customer *entity.Customer) (*entity.Customer, error) FindByID(ctx mycontext.Context, id int64) (*entity.Customer, error) FindByPhone(ctx mycontext.Context, phone string) (*entity.Customer, error) FindByEmail(ctx mycontext.Context, email string) (*entity.Customer, error) AddPoints(ctx mycontext.Context, id int64, points int) error } type Service interface { ResolveCustomer(ctx mycontext.Context, req *entity.CustomerResolutionRequest) (int64, error) AddPoints(ctx mycontext.Context, customerID int64, points int) error GetCustomer(ctx mycontext.Context, id int64) (*entity.Customer, error) } type customerSvc struct { repo Repository } func New(repo Repository) Service { return &customerSvc{ repo: repo, } } func (s *customerSvc) ResolveCustomer(ctx mycontext.Context, req *entity.CustomerResolutionRequest) (int64, error) { if req.Email == "" && req.PhoneNumber == "" { return 0, nil } if req.ID != nil && *req.ID > 0 { customer, err := s.repo.FindByID(ctx, *req.ID) if err != nil { if !strings.Contains(err.Error(), "not found") { return 0, errors.Wrap(err, "failed to find customer by ID") } } else { return customer.ID, nil } } if req.PhoneNumber != "" { customer, err := s.repo.FindByPhone(ctx, req.PhoneNumber) if err != nil { if !strings.Contains(err.Error(), "not found") { return 0, errors.Wrap(err, "failed to find customer by phone") } } else { return customer.ID, nil } } if req.Email != "" { customer, err := s.repo.FindByEmail(ctx, req.Email) if err != nil { if !strings.Contains(err.Error(), "not found") { return 0, errors.Wrap(err, "failed to find customer by email") } } else { return customer.ID, nil } } if req.Name == "" { return 0, errors.New("customer name is required to create a new customer") } newCustomer := &entity.Customer{ Name: req.Name, Email: req.Email, Phone: req.PhoneNumber, Points: 0, CreatedAt: constants.TimeNow(), UpdatedAt: constants.TimeNow(), } customer, err := s.repo.Create(ctx, newCustomer) if err != nil { logger.ContextLogger(ctx).Error("failed to create customer", zap.Error(err)) return 0, errors.Wrap(err, "failed to create customer") } return customer.ID, nil } func (s *customerSvc) AddPoints(ctx mycontext.Context, customerID int64, points int) error { if points <= 0 { return nil } err := s.repo.AddPoints(ctx, customerID, points) if err != nil { return errors.Wrap(err, "failed to add points to customer") } return nil } func (s *customerSvc) GetCustomer(ctx mycontext.Context, id int64) (*entity.Customer, error) { customer, err := s.repo.FindByID(ctx, id) if err != nil { return nil, errors.Wrap(err, "failed to get customer") } return customer, nil }