Update Member

This commit is contained in:
aditya.siregar
2025-03-15 15:51:18 +08:00
parent 18003313dd
commit c41826bb1b
29 changed files with 1840 additions and 65 deletions
+120 -14
View File
@@ -15,6 +15,8 @@ type CustomerRepo interface {
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
FindSequence(ctx mycontext.Context, partnerID int64) (int64, error)
GetAllCustomers(ctx mycontext.Context, req entity.MemberSearch) (entity.MemberList, int, error)
}
type customerRepository struct {
@@ -105,24 +107,128 @@ func (r *customerRepository) AddPoints(ctx mycontext.Context, id int64, points i
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,
ID: customer.ID,
Name: customer.Name,
Email: customer.Email,
Phone: customer.Phone,
Points: customer.Points,
CreatedAt: customer.CreatedAt,
UpdatedAt: customer.UpdatedAt,
CustomerID: customer.CustomerID,
BirthDate: customer.BirthDate,
}
}
func (r *customerRepository) FindSequence(ctx mycontext.Context, partnerID int64) (int64, error) {
tx := r.db.Begin()
if tx.Error != nil {
return 0, errors.Wrap(tx.Error, "failed to begin transaction")
}
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
var sequence models.PartnerMemberSequence
result := tx.Where("partner_id = ?", partnerID).First(&sequence)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
now := time.Now()
newSequence := models.PartnerMemberSequence{
PartnerID: partnerID,
LastSequence: 1,
UpdatedAt: now,
}
if err := tx.Create(&newSequence).Error; err != nil {
tx.Rollback()
return 0, errors.Wrap(err, "failed to create new sequence")
}
if err := tx.Commit().Error; err != nil {
return 0, errors.Wrap(err, "failed to commit transaction")
}
return 1, nil
}
tx.Rollback()
return 0, errors.Wrap(result.Error, "failed to query sequence")
}
newSequenceValue := sequence.LastSequence + 1
updates := map[string]interface{}{
"last_sequence": newSequenceValue,
"updated_at": time.Now(),
}
if err := tx.Model(&sequence).Updates(updates).Error; err != nil {
tx.Rollback()
return 0, errors.Wrap(err, "failed to update sequence")
}
if err := tx.Commit().Error; err != nil {
return 0, errors.Wrap(err, "failed to commit transaction")
}
return newSequenceValue, nil
}
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,
ID: dbModel.ID,
Name: dbModel.Name,
Email: dbModel.Email,
Phone: dbModel.Phone,
Points: dbModel.Points,
CreatedAt: dbModel.CreatedAt,
UpdatedAt: dbModel.UpdatedAt,
CustomerID: dbModel.CustomerID,
BirthDate: dbModel.BirthDate,
}
}
func (r *customerRepository) GetAllCustomers(ctx mycontext.Context, req entity.MemberSearch) (entity.MemberList, int, error) {
if req.Limit <= 0 {
req.Limit = 10
}
if req.Offset < 0 {
req.Offset = 0
}
query := r.db.Model(&models.CustomerDB{})
if req.Search != "" {
searchTerm := "%" + req.Search + "%"
query = query.Where(
"name ILIKE ? OR email ILIKE ? OR phone ILIKE ?",
searchTerm, searchTerm, searchTerm,
)
}
var totalCount int64
if err := query.Count(&totalCount).Error; err != nil {
return nil, 0, errors.Wrap(err, "failed to count customers")
}
var customersDB []models.CustomerDB
result := query.
Order("created_at DESC").
Limit(req.Limit).
Offset(req.Offset).
Find(&customersDB)
if result.Error != nil {
return nil, 0, errors.Wrap(result.Error, "failed to retrieve customers")
}
customers := make(entity.MemberList, len(customersDB))
for i, customerDB := range customersDB {
customers[i] = r.toDomainCustomerModel(&customerDB)
}
return customers, int(totalCount), nil
}
+138
View File
@@ -0,0 +1,138 @@
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(&registrationDB).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(&registrationDB).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(&registrationDB)
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,
}
}
+20 -7
View File
@@ -5,15 +5,28 @@ import (
)
type CustomerDB struct {
ID int64 `gorm:"primaryKey;column:id"`
Name string `gorm:"column:name"`
Email string `gorm:"column:email"`
Phone string `gorm:"column:phone"`
Points int `gorm:"column:points"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
ID int64 `gorm:"primaryKey;column:id"`
Name string `gorm:"column:name"`
Email string `gorm:"column:email"`
Phone string `gorm:"column:phone"`
Points int `gorm:"column:points"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
CustomerID string `gorm:"column:customer_id"`
BirthDate time.Time `gorm:"column:birth_date"`
}
func (CustomerDB) TableName() string {
return "customers"
}
type PartnerMemberSequence struct {
ID int64 `gorm:"column:id;primary_key;auto_increment"`
PartnerID int64 `gorm:"column:partner_id;not null;index:idx_partner_month,unique"`
LastSequence int64 `gorm:"column:last_sequence;not null;default:0"`
UpdatedAt time.Time `gorm:"column:updated_at;not null"`
}
func (PartnerMemberSequence) TableName() string {
return "partner_member_sequences"
}
+25
View File
@@ -0,0 +1,25 @@
package models
import (
"time"
)
type MemberRegistrationDB struct {
ID string `gorm:"column:id;primary_key"`
Token string `gorm:"column:token;unique_index"`
Name string `gorm:"column:name"`
Email string `gorm:"column:email"`
Phone string `gorm:"column:phone"`
BirthDate time.Time `gorm:"column:birth_date"`
OTP string `gorm:"column:otp"`
Status string `gorm:"column:status"`
ExpiresAt time.Time `gorm:"column:expires_at"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
BranchID int64 `gorm:"column:branch_id"`
CashierID int64 `gorm:"column:cashier_id"`
}
func (MemberRegistrationDB) TableName() string {
return "member_registrations"
}
+10 -8
View File
@@ -52,10 +52,11 @@ type RepoManagerImpl struct {
PG PaymentGateway
LinkQu LinkQu
OrderRepo OrderRepository
CustomerRepo CustomerRepo
ProductRepo ProductRepository
TransactionRepo TransactionRepo
OrderRepo OrderRepository
CustomerRepo CustomerRepo
ProductRepo ProductRepository
TransactionRepo TransactionRepo
MemberRepository MemberRepository
}
func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
@@ -80,10 +81,11 @@ func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
PG: pg.NewPaymentGatewayRepo(&cfg.Midtrans, &cfg.LinkQu),
LinkQu: linkqu.NewLinkQuService(&cfg.LinkQu),
OrderRepo: NeworderRepository(db),
CustomerRepo: NewCustomerRepository(db),
ProductRepo: NewproductRepository(db),
TransactionRepo: NewTransactionRepository(db),
OrderRepo: NeworderRepository(db),
CustomerRepo: NewCustomerRepository(db),
ProductRepo: NewproductRepository(db),
TransactionRepo: NewTransactionRepository(db),
MemberRepository: NewMemberRepository(db),
}
}