package repository import ( "enaklo-pos-be/internal/common/logger" "enaklo-pos-be/internal/common/mycontext" "enaklo-pos-be/internal/constants" "enaklo-pos-be/internal/entity" "enaklo-pos-be/internal/repository/models" "errors" "time" "go.uber.org/zap" "gorm.io/gorm" ) type MemberRepository interface { CreateRegistration(ctx mycontext.Context, registration *entity.MemberRegistration) (*entity.MemberRegistration, error) GetRegistrationByToken(ctx mycontext.Context, token string) (*entity.MemberRegistration, error) UpdateRegistrationStatus(ctx mycontext.Context, token string, status constants.RegistrationStatus) error UpdateRegistrationOTP(ctx mycontext.Context, token string, otp string, expiresAt time.Time) error } type memberRepository struct { db *gorm.DB } func NewMemberRepository(db *gorm.DB) MemberRepository { return &memberRepository{ db: db, } } func (r *memberRepository) CreateRegistration(ctx mycontext.Context, registration *entity.MemberRegistration) (*entity.MemberRegistration, error) { registrationDB := r.toRegistrationDBModel(registration) if err := r.db.Create(®istrationDB).Error; err != nil { logger.ContextLogger(ctx).Error("failed to create member registration", zap.Error(err)) return nil, errors.New("failed to insert member registration") } return registration, nil } func (r *memberRepository) GetRegistrationByToken(ctx mycontext.Context, token string) (*entity.MemberRegistration, error) { var registrationDB models.MemberRegistrationDB if err := r.db.Where("token = ?", token).First(®istrationDB).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("registration not found") } logger.ContextLogger(ctx).Error("failed to get registration by token", zap.Error(err)) return nil, errors.New("failed to get registration by token") } registration := r.toDomainRegistrationModel(®istrationDB) return registration, nil } func (r *memberRepository) UpdateRegistrationStatus(ctx mycontext.Context, token string, status constants.RegistrationStatus) error { now := time.Now() result := r.db.Model(&models.MemberRegistrationDB{}). Where("token = ?", token). Updates(map[string]interface{}{ "status": status, "updated_at": now, }) if result.Error != nil { logger.ContextLogger(ctx).Error("failed to update registration status", zap.Error(result.Error)) return errors.New("failed to update registration status") } if result.RowsAffected == 0 { return errors.New("registration not found") } return nil } func (r *memberRepository) UpdateRegistrationOTP(ctx mycontext.Context, token string, otp string, expiresAt time.Time) error { now := time.Now() result := r.db.Model(&models.MemberRegistrationDB{}). Where("token = ?", token). Updates(map[string]interface{}{ "otp": otp, "expires_at": expiresAt, "updated_at": now, }) if result.Error != nil { logger.ContextLogger(ctx).Error("failed to update registration OTP", zap.Error(result.Error)) return errors.New("failed to update registration OTP") } if result.RowsAffected == 0 { return errors.New("registration not found") } return nil } func (r *memberRepository) toRegistrationDBModel(registration *entity.MemberRegistration) models.MemberRegistrationDB { return models.MemberRegistrationDB{ ID: registration.ID, Token: registration.Token, Name: registration.Name, Email: registration.Email, Phone: registration.Phone, BirthDate: registration.BirthDate, OTP: registration.OTP, Status: registration.Status.String(), ExpiresAt: registration.ExpiresAt, CreatedAt: registration.CreatedAt, UpdatedAt: registration.UpdatedAt, BranchID: registration.BranchID, CashierID: registration.CashierID, } } func (r *memberRepository) toDomainRegistrationModel(dbModel *models.MemberRegistrationDB) *entity.MemberRegistration { return &entity.MemberRegistration{ ID: dbModel.ID, Token: dbModel.Token, Name: dbModel.Name, Email: dbModel.Email, Phone: dbModel.Phone, BirthDate: dbModel.BirthDate, OTP: dbModel.OTP, Status: constants.RegistrationStatus(dbModel.Status), ExpiresAt: dbModel.ExpiresAt, CreatedAt: dbModel.CreatedAt, UpdatedAt: dbModel.UpdatedAt, BranchID: dbModel.BranchID, CashierID: dbModel.CashierID, } }