From e9ed9c0dd129beb4d1b85bc2f607274f25016acd Mon Sep 17 00:00:00 2001 From: "aditya.siregar" Date: Tue, 30 Jul 2024 02:48:31 +0700 Subject: [PATCH] Add partners --- internal/entity/partner.go | 46 ++++++++++++++++------- internal/entity/user.go | 19 ++++++---- internal/handlers/http/partner/partner.go | 14 ++++--- internal/handlers/request/partner.go | 8 ++-- internal/handlers/response/partner.go | 16 +++++--- internal/repository/partners/partners.go | 45 ++++++++++++++++------ internal/repository/repository.go | 1 + internal/services/partner/partner.go | 6 +++ migrations/000004_partner-table.up.sql | 1 + 9 files changed, 109 insertions(+), 47 deletions(-) diff --git a/internal/entity/partner.go b/internal/entity/partner.go index d87cc4f..eb62fdf 100644 --- a/internal/entity/partner.go +++ b/internal/entity/partner.go @@ -33,6 +33,11 @@ type Partner struct { DeletedAt *time.Time `gorm:"column:deleted_at"` CreatedBy int64 `gorm:"type:int;column:created_by"` UpdatedBy int64 `gorm:"type:int;column:updated_by"` + AdminUserID int64 `gorm:"type:int;column:admin_user_id"` + Balance float64 `gorm:"-"` + AdminName string `json:"admin_name"` + AdminPhoneNumber string `json:"admin_phone_number"` + AdminEmail string `json:"admin_email"` } func (Partner) TableName() string { @@ -52,6 +57,14 @@ type PartnerDB struct { Partner } +type PartnerDBSearch struct { + Partner + WalletBalance float64 `gorm:"type:number;column:wallet_balance"` + AdminName string `gorm:"type:varchar;column:admin_name"` + AdminEmail string `gorm:"type:varchar;column:admin_email"` + AdminPhoneNumber string `gorm:"type:varchar;column:admin_phone_number"` +} + func (p *Partner) ToPartnerDB() *PartnerDB { return &PartnerDB{ Partner: *p, @@ -64,13 +77,17 @@ func (PartnerDB) TableName() string { func (e *PartnerDB) ToPartner() *Partner { return &Partner{ - ID: e.ID, - Name: e.Name, - Status: e.Status, - Address: e.Address, - CreatedAt: e.CreatedAt, - UpdatedAt: e.UpdatedAt, - CreatedBy: e.CreatedBy, + ID: e.ID, + Name: e.Name, + Status: e.Status, + Address: e.Address, + CreatedAt: e.CreatedAt, + UpdatedAt: e.UpdatedAt, + CreatedBy: e.CreatedBy, + Balance: e.Balance, + AdminEmail: e.AdminEmail, + AdminPhoneNumber: e.AdminPhoneNumber, + AdminName: e.AdminName, } } @@ -106,13 +123,14 @@ func (o *PartnerDB) SetDeleted(updatedBy int64) { func (c *CreatePartnerRequest) ToUserAdmin(partnerID int64) *User { return &User{ - Name: c.FullName, - Password: c.Password, - Email: c.Email, - NIK: c.NIK, - Status: "active", - RoleID: role.PartnerAdmin, - PartnerID: &partnerID, + Name: c.FullName, + Password: c.Password, + Email: c.Email, + NIK: c.NIK, + PhoneNumber: c.PhoneNumber, + Status: "active", + RoleID: role.PartnerAdmin, + PartnerID: &partnerID, } } diff --git a/internal/entity/user.go b/internal/entity/user.go index d9a8ad7..6bbb138 100644 --- a/internal/entity/user.go +++ b/internal/entity/user.go @@ -19,6 +19,7 @@ type User struct { CreatedAt time.Time UpdatedAt time.Time RoleID role.Role + PhoneNumber string RoleName string PartnerID *int64 SiteID *int64 @@ -66,14 +67,16 @@ func (u *User) ToUserDB(createdBy int64) (*UserDB, error) { } return &UserDB{ - Name: u.Name, - Email: u.Email, - Password: hashedPassword, - RoleID: int64(u.RoleID), - PartnerID: u.PartnerID, - Status: userstatus.Active, - CreatedBy: createdBy, - SiteID: u.SiteID, + Name: u.Name, + Email: u.Email, + Password: hashedPassword, + RoleID: int64(u.RoleID), + PartnerID: u.PartnerID, + Status: userstatus.Active, + CreatedBy: createdBy, + SiteID: u.SiteID, + PhoneNumber: u.PhoneNumber, + NIK: u.NIK, }, nil } diff --git a/internal/handlers/http/partner/partner.go b/internal/handlers/http/partner/partner.go index 97edde6..af1ab30 100644 --- a/internal/handlers/http/partner/partner.go +++ b/internal/handlers/http/partner/partner.go @@ -242,11 +242,15 @@ func (h *Handler) GetByID(c *gin.Context) { func (h *Handler) toPartnerResponse(resp *entity.Partner) response.Partner { return response.Partner{ - ID: &resp.ID, - Name: resp.Name, - Status: resp.Status, - CreatedAt: resp.CreatedAt.Format(time.RFC3339), - UpdatedAt: resp.CreatedAt.Format(time.RFC3339), + ID: &resp.ID, + Name: resp.Name, + Status: resp.Status, + CreatedAt: resp.CreatedAt.Format(time.RFC3339), + UpdatedAt: resp.CreatedAt.Format(time.RFC3339), + Balance: resp.Balance, + AdminName: resp.AdminName, + AdminPhoneNumber: resp.AdminPhoneNumber, + AdminEmail: resp.AdminEmail, } } diff --git a/internal/handlers/request/partner.go b/internal/handlers/request/partner.go index ca64b08..7c32215 100644 --- a/internal/handlers/request/partner.go +++ b/internal/handlers/request/partner.go @@ -21,9 +21,11 @@ func (p *PartnerParam) ToEntity() entity.PartnerSearch { } type Partner struct { - Name string `json:"name" validate:"required"` - Address string `json:"address" validate:"required"` - Status string `json:"status"` + Name string `json:"name"` + Address string `json:"address"` + Status string `json:"status"` + Email string `json:"email"` + PhoneNumber string `json:"phone_number"` } type CreatePartnerRequest struct { diff --git a/internal/handlers/response/partner.go b/internal/handlers/response/partner.go index a7105f2..592f244 100644 --- a/internal/handlers/response/partner.go +++ b/internal/handlers/response/partner.go @@ -1,12 +1,16 @@ package response type Partner struct { - ID *int64 `json:"id"` - Name string `json:"name"` - Status string `json:"status"` - Address string `json:"address,omitempty"` - CreatedAt string `json:"created_at,omitempty"` - UpdatedAt string `json:"updated_at,omitempty"` + ID *int64 `json:"id"` + Name string `json:"name"` + Status string `json:"status"` + Address string `json:"address,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + AdminName string `json:"admin_name"` + AdminPhoneNumber string `json:"admin_phone_number"` + AdminEmail string `json:"admin_email"` + Balance float64 `json:"balance"` } type PartnerList struct { diff --git a/internal/repository/partners/partners.go b/internal/repository/partners/partners.go index 8cdf4f2..998af49 100644 --- a/internal/repository/partners/partners.go +++ b/internal/repository/partners/partners.go @@ -45,6 +45,14 @@ func (b *PartnerRepository) Update(ctx context.Context, Partner *entity.PartnerD return Partner, nil } +func (b *PartnerRepository) UpdateWithTx(ctx context.Context, tx *gorm.DB, Partner *entity.PartnerDB) (*entity.PartnerDB, error) { + if err := tx.Save(Partner).Error; err != nil { + logger.ContextLogger(ctx).Error("error when update Partner", zap.Error(err)) + return nil, err + } + return Partner, nil +} + func (b *PartnerRepository) GetByID(ctx context.Context, id int64) (*entity.PartnerDB, error) { Partner := new(entity.PartnerDB) if err := b.db.First(Partner, id).Error; err != nil { @@ -55,18 +63,21 @@ func (b *PartnerRepository) GetByID(ctx context.Context, id int64) (*entity.Part } func (b *PartnerRepository) GetAll(ctx context.Context, req entity.PartnerSearch) (entity.PartnerList, int, error) { - var Partneres []*entity.PartnerDB + var partners []*entity.PartnerDBSearch var total int64 - query := b.db - query = query.Where("deleted_at is null") + query := b.db.Table("partners p"). + Select("p.*, w.balance as wallet_balance, u.name as admin_name, u.email as admin_email, u.phone_number as admin_phone_number"). + Joins("LEFT JOIN wallets w ON w.partner_id = p.id"). + Joins("LEFT JOIN users u ON p.admin_user_id = u.id"). + Where("p.deleted_at IS NULL") if req.Search != "" { - query = query.Where("name ILIKE ?", "%"+req.Search+"%") + query = query.Where("p.name ILIKE ?", "%"+req.Search+"%") } if req.Name != "" { - query = query.Where("name ILIKE ?", "%"+req.Name+"%") + query = query.Where("p.name ILIKE ?", "%"+req.Name+"%") } if req.Limit > 0 { @@ -77,19 +88,31 @@ func (b *PartnerRepository) GetAll(ctx context.Context, req entity.PartnerSearch query = query.Offset(req.Offset) } - if err := query.Find(&Partneres).Error; err != nil { - logger.ContextLogger(ctx).Error("error when get all Partneres", zap.Error(err)) + // Find partners with joined wallet balances + if err := query.Find(&partners).Error; err != nil { + logger.ContextLogger(ctx).Error("error when getting all partners", zap.Error(err)) return nil, 0, err } - if err := b.db.Model(&entity.PartnerDB{}).Where(query).Count(&total).Error; err != nil { - logger.ContextLogger(ctx).Error("error when count Partneres", zap.Error(err)) + // Counting total records + if err := b.db.Table("partners p"). + Joins("LEFT JOIN wallets w ON w.partner_id = p.id"). + Where("p.deleted_at IS NULL"). + Count(&total).Error; err != nil { + logger.ContextLogger(ctx).Error("error when counting partners", zap.Error(err)) return nil, 0, err } - return Partneres, int(total), nil + partnersSearchResult := entity.PartnerList{} + + for _, partner := range partners { + partner.Balance = partner.WalletBalance + partnersSearchResult = append(partnersSearchResult, &entity.PartnerDB{partner.Partner}) + } + + return partnersSearchResult, int(total), nil + } - func (b *PartnerRepository) Delete(ctx context.Context, id int64) error { Partner := new(entity.PartnerDB) Partner.ID = id diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 1e8c8a5..8682edb 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -148,6 +148,7 @@ type OSSRepository interface { type PartnerRepository interface { Create(ctx context.Context, branch *entity.PartnerDB) (*entity.PartnerDB, error) CreateWithTx(ctx context.Context, tx *gorm.DB, Partner *entity.PartnerDB) (*entity.PartnerDB, error) + UpdateWithTx(ctx context.Context, tx *gorm.DB, Partner *entity.PartnerDB) (*entity.PartnerDB, error) Update(ctx context.Context, branch *entity.PartnerDB) (*entity.PartnerDB, error) GetByID(ctx context.Context, id int64) (*entity.PartnerDB, error) GetAll(ctx context.Context, req entity.PartnerSearch) (entity.PartnerList, int, error) diff --git a/internal/services/partner/partner.go b/internal/services/partner/partner.go index 6cd984a..80cf2aa 100644 --- a/internal/services/partner/partner.go +++ b/internal/services/partner/partner.go @@ -61,6 +61,12 @@ func (s *PartnerService) Create(ctx mycontext.Context, partnerReq *entity.Create return nil, err } + partnerDB.AdminUserID = adminUser.ID + if partnerDB, err = s.repo.UpdateWithTx(ctx, tx, partnerDB); err != nil { + logger.ContextLogger(ctx).Error("error when creating partner", zap.Error(err)) + return nil, err + } + partnerWallet := partnerReq.ToWallet(partnerDB.ID) if partnerWallet, err = s.walletRepo.Create(ctx, tx, partnerWallet); err != nil { logger.ContextLogger(ctx).Error("error when creating wallet", zap.Error(err)) diff --git a/migrations/000004_partner-table.up.sql b/migrations/000004_partner-table.up.sql index 4637326..1d80c6b 100644 --- a/migrations/000004_partner-table.up.sql +++ b/migrations/000004_partner-table.up.sql @@ -12,5 +12,6 @@ CREATE TABLE partners updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_by INTEGER, updated_by INTEGER, + admin_user_id INTEGER, deleted_at TIMESTAMP ); \ No newline at end of file