package repository import ( "enaklo-pos-be/internal/common/mycontext" "enaklo-pos-be/internal/entity" "enaklo-pos-be/internal/repository/models" "github.com/pkg/errors" "gorm.io/gorm" "time" ) type CustomerRepo 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 customerRepository struct { db *gorm.DB } func NewCustomerRepository(db *gorm.DB) *customerRepository { return &customerRepository{db: db} } func (r *customerRepository) Create(ctx mycontext.Context, customer *entity.Customer) (*entity.Customer, error) { customerDB := r.toCustomerDBModel(customer) if err := r.db.Create(&customerDB).Error; err != nil { return nil, errors.Wrap(err, "failed to insert customer") } customer.ID = customerDB.ID return customer, nil } func (r *customerRepository) FindByID(ctx mycontext.Context, id int64) (*entity.Customer, error) { var customerDB models.CustomerDB if err := r.db.First(&customerDB, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("customer not found") } return nil, errors.Wrap(err, "failed to find customer") } customer := r.toDomainCustomerModel(&customerDB) return customer, nil } func (r *customerRepository) FindByPhone(ctx mycontext.Context, phone string) (*entity.Customer, error) { var customerDB models.CustomerDB if err := r.db.Where("phone = ?", phone).First(&customerDB).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("customer not found") } return nil, errors.Wrap(err, "failed to find customer by phone") } customer := r.toDomainCustomerModel(&customerDB) return customer, nil } func (r *customerRepository) FindByEmail(ctx mycontext.Context, email string) (*entity.Customer, error) { var customerDB models.CustomerDB if err := r.db.Where("email = ?", email).First(&customerDB).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("customer not found") } return nil, errors.Wrap(err, "failed to find customer by email") } customer := r.toDomainCustomerModel(&customerDB) return customer, nil } func (r *customerRepository) AddPoints(ctx mycontext.Context, id int64, points int) error { now := time.Now() result := r.db.Model(&models.CustomerDB{}). Where("id = ?", id). Updates(map[string]interface{}{ "points": gorm.Expr("points + ?", points), "updated_at": now, }) if result.Error != nil { return errors.Wrap(result.Error, "failed to add points to customer") } if result.RowsAffected == 0 { return errors.New("customer not found") } return nil } func (r *customerRepository) toCustomerDBModel(customer *entity.Customer) models.CustomerDB { return models.CustomerDB{ ID: customer.ID, Name: customer.Name, Email: customer.Email, Phone: customer.Phone, Points: customer.Points, CreatedAt: customer.CreatedAt, UpdatedAt: customer.UpdatedAt, } } func (r *customerRepository) toDomainCustomerModel(dbModel *models.CustomerDB) *entity.Customer { return &entity.Customer{ ID: dbModel.ID, Name: dbModel.Name, Email: dbModel.Email, Phone: dbModel.Phone, Points: dbModel.Points, CreatedAt: dbModel.CreatedAt, UpdatedAt: dbModel.UpdatedAt, } }