feat: 实现账号与佣金管理模块
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 4m35s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 4m35s
新增功能: - 店铺佣金查询:店铺佣金统计、店铺佣金记录列表、店铺提现记录 - 佣金提现审批:提现申请列表、审批通过、审批拒绝 - 提现配置管理:配置列表、新增配置、获取当前生效配置 - 企业管理:企业列表、创建、更新、删除、获取详情 - 企业卡授权:授权列表、批量授权、批量取消授权、统计 - 客户账号管理:账号列表、创建、更新状态、重置密码 - 我的佣金:佣金统计、佣金记录、提现申请、提现记录 数据库变更: - 扩展 tb_commission_withdrawal_request 新增提现单号等字段 - 扩展 tb_account 新增 is_primary 字段 - 扩展 tb_commission_record 新增 shop_id、balance_after - 扩展 tb_commission_withdrawal_setting 新增每日提现次数限制 - 扩展 tb_iot_card、tb_device 新增 shop_id 冗余字段 - 新建 tb_enterprise_card_authorization 企业卡授权表 - 新建 tb_asset_allocation_record 资产分配记录表 - 数据迁移:owner_type 枚举值 agent 统一为 shop 测试: - 新增 7 个单元测试文件覆盖各服务 - 修复集成测试 Redis 依赖问题
This commit is contained in:
@@ -218,6 +218,30 @@ func (s *AccountStore) BulkUpdateStatus(ctx context.Context, ids []uint, status
|
||||
}).Error
|
||||
}
|
||||
|
||||
func (s *AccountStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.Account, error) {
|
||||
if len(ids) == 0 {
|
||||
return []*model.Account{}, nil
|
||||
}
|
||||
var accounts []*model.Account
|
||||
if err := s.db.WithContext(ctx).Where("id IN ?", ids).Find(&accounts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
func (s *AccountStore) GetPrimaryAccountsByShopIDs(ctx context.Context, shopIDs []uint) ([]*model.Account, error) {
|
||||
if len(shopIDs) == 0 {
|
||||
return []*model.Account{}, nil
|
||||
}
|
||||
var accounts []*model.Account
|
||||
if err := s.db.WithContext(ctx).
|
||||
Where("shop_id IN ? AND is_primary = ?", shopIDs, true).
|
||||
Find(&accounts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
// ListByShopID 按店铺ID分页查询账号列表
|
||||
func (s *AccountStore) ListByShopID(ctx context.Context, shopID uint, opts *store.QueryOptions, filters map[string]interface{}) ([]*model.Account, int64, error) {
|
||||
var accounts []*model.Account
|
||||
|
||||
88
internal/store/postgres/commission_record_store.go
Normal file
88
internal/store/postgres/commission_record_store.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CommissionRecordStore struct {
|
||||
db *gorm.DB
|
||||
redis *redis.Client
|
||||
}
|
||||
|
||||
func NewCommissionRecordStore(db *gorm.DB, redis *redis.Client) *CommissionRecordStore {
|
||||
return &CommissionRecordStore{
|
||||
db: db,
|
||||
redis: redis,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CommissionRecordStore) Create(ctx context.Context, record *model.CommissionRecord) error {
|
||||
return s.db.WithContext(ctx).Create(record).Error
|
||||
}
|
||||
|
||||
func (s *CommissionRecordStore) GetByID(ctx context.Context, id uint) (*model.CommissionRecord, error) {
|
||||
var record model.CommissionRecord
|
||||
if err := s.db.WithContext(ctx).First(&record, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &record, nil
|
||||
}
|
||||
|
||||
type CommissionRecordListFilters struct {
|
||||
ShopID uint
|
||||
CommissionType string
|
||||
ICCID string
|
||||
DeviceNo string
|
||||
OrderNo string
|
||||
Status *int
|
||||
}
|
||||
|
||||
func (s *CommissionRecordStore) ListByShopID(ctx context.Context, opts *store.QueryOptions, filters *CommissionRecordListFilters) ([]*model.CommissionRecord, int64, error) {
|
||||
var records []*model.CommissionRecord
|
||||
var total int64
|
||||
|
||||
query := s.db.WithContext(ctx).Model(&model.CommissionRecord{})
|
||||
|
||||
if filters != nil {
|
||||
if filters.ShopID > 0 {
|
||||
query = query.Where("shop_id = ?", filters.ShopID)
|
||||
}
|
||||
if filters.CommissionType != "" {
|
||||
query = query.Where("commission_type = ?", filters.CommissionType)
|
||||
}
|
||||
if filters.Status != nil {
|
||||
query = query.Where("status = ?", *filters.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if opts == nil {
|
||||
opts = &store.QueryOptions{
|
||||
Page: 1,
|
||||
PageSize: constants.DefaultPageSize,
|
||||
}
|
||||
}
|
||||
offset := (opts.Page - 1) * opts.PageSize
|
||||
query = query.Offset(offset).Limit(opts.PageSize)
|
||||
|
||||
if opts.OrderBy != "" {
|
||||
query = query.Order(opts.OrderBy)
|
||||
} else {
|
||||
query = query.Order("created_at DESC")
|
||||
}
|
||||
|
||||
if err := query.Find(&records).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return records, total, nil
|
||||
}
|
||||
193
internal/store/postgres/commission_withdrawal_request_store.go
Normal file
193
internal/store/postgres/commission_withdrawal_request_store.go
Normal file
@@ -0,0 +1,193 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CommissionWithdrawalRequestStore struct {
|
||||
db *gorm.DB
|
||||
redis *redis.Client
|
||||
}
|
||||
|
||||
func NewCommissionWithdrawalRequestStore(db *gorm.DB, redis *redis.Client) *CommissionWithdrawalRequestStore {
|
||||
return &CommissionWithdrawalRequestStore{
|
||||
db: db,
|
||||
redis: redis,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalRequestStore) Create(ctx context.Context, req *model.CommissionWithdrawalRequest) error {
|
||||
return s.db.WithContext(ctx).Create(req).Error
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalRequestStore) GetByID(ctx context.Context, id uint) (*model.CommissionWithdrawalRequest, error) {
|
||||
var req model.CommissionWithdrawalRequest
|
||||
if err := s.db.WithContext(ctx).First(&req, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalRequestStore) Update(ctx context.Context, req *model.CommissionWithdrawalRequest) error {
|
||||
return s.db.WithContext(ctx).Save(req).Error
|
||||
}
|
||||
|
||||
type WithdrawalRequestListFilters struct {
|
||||
ShopID uint
|
||||
WithdrawalNo string
|
||||
StartTime *time.Time
|
||||
EndTime *time.Time
|
||||
Status *int
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalRequestStore) ListByShopID(ctx context.Context, opts *store.QueryOptions, filters *WithdrawalRequestListFilters) ([]*model.CommissionWithdrawalRequest, int64, error) {
|
||||
var requests []*model.CommissionWithdrawalRequest
|
||||
var total int64
|
||||
|
||||
query := s.db.WithContext(ctx).Model(&model.CommissionWithdrawalRequest{})
|
||||
|
||||
if filters != nil {
|
||||
if filters.ShopID > 0 {
|
||||
query = query.Where("shop_id = ?", filters.ShopID)
|
||||
}
|
||||
if filters.WithdrawalNo != "" {
|
||||
query = query.Where("withdrawal_no = ?", filters.WithdrawalNo)
|
||||
}
|
||||
if filters.StartTime != nil {
|
||||
query = query.Where("created_at >= ?", filters.StartTime)
|
||||
}
|
||||
if filters.EndTime != nil {
|
||||
query = query.Where("created_at <= ?", filters.EndTime)
|
||||
}
|
||||
if filters.Status != nil {
|
||||
query = query.Where("status = ?", *filters.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if opts == nil {
|
||||
opts = &store.QueryOptions{
|
||||
Page: 1,
|
||||
PageSize: constants.DefaultPageSize,
|
||||
}
|
||||
}
|
||||
offset := (opts.Page - 1) * opts.PageSize
|
||||
query = query.Offset(offset).Limit(opts.PageSize)
|
||||
|
||||
if opts.OrderBy != "" {
|
||||
query = query.Order(opts.OrderBy)
|
||||
} else {
|
||||
query = query.Order("created_at DESC")
|
||||
}
|
||||
|
||||
if err := query.Find(&requests).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return requests, total, nil
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalRequestStore) SumAmountByShopIDAndStatus(ctx context.Context, shopID uint, status int) (int64, error) {
|
||||
var sum struct {
|
||||
Total int64
|
||||
}
|
||||
err := s.db.WithContext(ctx).
|
||||
Model(&model.CommissionWithdrawalRequest{}).
|
||||
Select("COALESCE(SUM(amount), 0) as total").
|
||||
Where("shop_id = ? AND status = ?", shopID, status).
|
||||
Scan(&sum).Error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return sum.Total, nil
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalRequestStore) SumAmountByShopIDsAndStatus(ctx context.Context, shopIDs []uint, status int) (map[uint]int64, error) {
|
||||
if len(shopIDs) == 0 {
|
||||
return make(map[uint]int64), nil
|
||||
}
|
||||
|
||||
type sumResult struct {
|
||||
ShopID uint
|
||||
Total int64
|
||||
}
|
||||
|
||||
var results []sumResult
|
||||
err := s.db.WithContext(ctx).
|
||||
Model(&model.CommissionWithdrawalRequest{}).
|
||||
Select("shop_id, COALESCE(SUM(amount), 0) as total").
|
||||
Where("shop_id IN ? AND status = ?", shopIDs, status).
|
||||
Group("shop_id").
|
||||
Scan(&results).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uint]int64)
|
||||
for _, r := range results {
|
||||
result[r.ShopID] = r.Total
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalRequestStore) List(ctx context.Context, opts *store.QueryOptions, filters *WithdrawalRequestListFilters) ([]*model.CommissionWithdrawalRequest, int64, error) {
|
||||
var requests []*model.CommissionWithdrawalRequest
|
||||
var total int64
|
||||
|
||||
query := s.db.WithContext(ctx).Model(&model.CommissionWithdrawalRequest{})
|
||||
|
||||
if filters != nil {
|
||||
if filters.WithdrawalNo != "" {
|
||||
query = query.Where("withdrawal_no = ?", filters.WithdrawalNo)
|
||||
}
|
||||
if filters.StartTime != nil {
|
||||
query = query.Where("created_at >= ?", filters.StartTime)
|
||||
}
|
||||
if filters.EndTime != nil {
|
||||
query = query.Where("created_at <= ?", filters.EndTime)
|
||||
}
|
||||
if filters.Status != nil {
|
||||
query = query.Where("status = ?", *filters.Status)
|
||||
}
|
||||
}
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if opts == nil {
|
||||
opts = &store.QueryOptions{
|
||||
Page: 1,
|
||||
PageSize: constants.DefaultPageSize,
|
||||
}
|
||||
}
|
||||
offset := (opts.Page - 1) * opts.PageSize
|
||||
query = query.Offset(offset).Limit(opts.PageSize)
|
||||
|
||||
if opts.OrderBy != "" {
|
||||
query = query.Order(opts.OrderBy)
|
||||
} else {
|
||||
query = query.Order("created_at DESC")
|
||||
}
|
||||
|
||||
if err := query.Find(&requests).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return requests, total, nil
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalRequestStore) UpdateStatusWithTx(ctx context.Context, tx *gorm.DB, id uint, updates map[string]interface{}) error {
|
||||
return tx.WithContext(ctx).Model(&model.CommissionWithdrawalRequest{}).Where("id = ? AND status = ?", id, constants.WithdrawalStatusPending).Updates(updates).Error
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CommissionWithdrawalSettingStore struct {
|
||||
db *gorm.DB
|
||||
redis *redis.Client
|
||||
}
|
||||
|
||||
func NewCommissionWithdrawalSettingStore(db *gorm.DB, redis *redis.Client) *CommissionWithdrawalSettingStore {
|
||||
return &CommissionWithdrawalSettingStore{
|
||||
db: db,
|
||||
redis: redis,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalSettingStore) Create(ctx context.Context, setting *model.CommissionWithdrawalSetting) error {
|
||||
return s.db.WithContext(ctx).Create(setting).Error
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalSettingStore) CreateWithTx(ctx context.Context, tx *gorm.DB, setting *model.CommissionWithdrawalSetting) error {
|
||||
return tx.WithContext(ctx).Create(setting).Error
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalSettingStore) GetByID(ctx context.Context, id uint) (*model.CommissionWithdrawalSetting, error) {
|
||||
var setting model.CommissionWithdrawalSetting
|
||||
if err := s.db.WithContext(ctx).First(&setting, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &setting, nil
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalSettingStore) GetCurrent(ctx context.Context) (*model.CommissionWithdrawalSetting, error) {
|
||||
var setting model.CommissionWithdrawalSetting
|
||||
if err := s.db.WithContext(ctx).Where("is_active = ?", true).First(&setting).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &setting, nil
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalSettingStore) List(ctx context.Context, opts *store.QueryOptions) ([]*model.CommissionWithdrawalSetting, int64, error) {
|
||||
var settings []*model.CommissionWithdrawalSetting
|
||||
var total int64
|
||||
|
||||
query := s.db.WithContext(ctx).Model(&model.CommissionWithdrawalSetting{})
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if opts == nil {
|
||||
opts = &store.QueryOptions{
|
||||
Page: 1,
|
||||
PageSize: constants.DefaultPageSize,
|
||||
}
|
||||
}
|
||||
offset := (opts.Page - 1) * opts.PageSize
|
||||
query = query.Offset(offset).Limit(opts.PageSize).Order("created_at DESC")
|
||||
|
||||
if err := query.Find(&settings).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return settings, total, nil
|
||||
}
|
||||
|
||||
func (s *CommissionWithdrawalSettingStore) DeactivateCurrentWithTx(ctx context.Context, tx *gorm.DB) error {
|
||||
return tx.WithContext(ctx).Model(&model.CommissionWithdrawalSetting{}).
|
||||
Where("is_active = ?", true).
|
||||
Update("is_active", false).Error
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type EnterpriseCardAuthorizationStore struct {
|
||||
db *gorm.DB
|
||||
redis *redis.Client
|
||||
}
|
||||
|
||||
func NewEnterpriseCardAuthorizationStore(db *gorm.DB, redis *redis.Client) *EnterpriseCardAuthorizationStore {
|
||||
return &EnterpriseCardAuthorizationStore{
|
||||
db: db,
|
||||
redis: redis,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) Create(ctx context.Context, auth *model.EnterpriseCardAuthorization) error {
|
||||
return s.db.WithContext(ctx).Create(auth).Error
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) BatchCreate(ctx context.Context, auths []*model.EnterpriseCardAuthorization) error {
|
||||
if len(auths) == 0 {
|
||||
return nil
|
||||
}
|
||||
return s.db.WithContext(ctx).CreateInBatches(auths, 100).Error
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) UpdateStatus(ctx context.Context, enterpriseID, cardID uint, status int) error {
|
||||
return s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND iot_card_id = ?", enterpriseID, cardID).
|
||||
Update("status", status).Error
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) BatchUpdateStatus(ctx context.Context, enterpriseID uint, cardIDs []uint, status int) error {
|
||||
if len(cardIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND iot_card_id IN ?", enterpriseID, cardIDs).
|
||||
Update("status", status).Error
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) GetByEnterpriseAndCard(ctx context.Context, enterpriseID, cardID uint) (*model.EnterpriseCardAuthorization, error) {
|
||||
var auth model.EnterpriseCardAuthorization
|
||||
err := s.db.WithContext(ctx).
|
||||
Where("enterprise_id = ? AND iot_card_id = ?", enterpriseID, cardID).
|
||||
First(&auth).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &auth, nil
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) ListByEnterprise(ctx context.Context, enterpriseID uint, status *int) ([]*model.EnterpriseCardAuthorization, error) {
|
||||
var auths []*model.EnterpriseCardAuthorization
|
||||
query := s.db.WithContext(ctx).Where("enterprise_id = ?", enterpriseID)
|
||||
if status != nil {
|
||||
query = query.Where("status = ?", *status)
|
||||
}
|
||||
if err := query.Find(&auths).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return auths, nil
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) ListCardIDsByEnterprise(ctx context.Context, enterpriseID uint) ([]uint, error) {
|
||||
var cardIDs []uint
|
||||
err := s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND status = 1", enterpriseID).
|
||||
Pluck("iot_card_id", &cardIDs).Error
|
||||
return cardIDs, err
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) GetActiveAuthsByCardIDs(ctx context.Context, enterpriseID uint, cardIDs []uint) (map[uint]bool, error) {
|
||||
if len(cardIDs) == 0 {
|
||||
return make(map[uint]bool), nil
|
||||
}
|
||||
var auths []model.EnterpriseCardAuthorization
|
||||
err := s.db.WithContext(ctx).
|
||||
Where("enterprise_id = ? AND iot_card_id IN ? AND status = 1", enterpriseID, cardIDs).
|
||||
Find(&auths).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make(map[uint]bool)
|
||||
for _, auth := range auths {
|
||||
result[auth.IotCardID] = true
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
108
internal/store/postgres/wallet_store.go
Normal file
108
internal/store/postgres/wallet_store.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type WalletStore struct {
|
||||
db *gorm.DB
|
||||
redis *redis.Client
|
||||
}
|
||||
|
||||
func NewWalletStore(db *gorm.DB, redis *redis.Client) *WalletStore {
|
||||
return &WalletStore{
|
||||
db: db,
|
||||
redis: redis,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *WalletStore) GetByResourceTypeAndID(ctx context.Context, resourceType string, resourceID uint, walletType string) (*model.Wallet, error) {
|
||||
var wallet model.Wallet
|
||||
err := s.db.WithContext(ctx).
|
||||
Where("resource_type = ? AND resource_id = ? AND wallet_type = ?", resourceType, resourceID, walletType).
|
||||
First(&wallet).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &wallet, nil
|
||||
}
|
||||
|
||||
func (s *WalletStore) GetShopCommissionWallet(ctx context.Context, shopID uint) (*model.Wallet, error) {
|
||||
return s.GetByResourceTypeAndID(ctx, "shop", shopID, "commission")
|
||||
}
|
||||
|
||||
type ShopCommissionSummary struct {
|
||||
ShopID uint
|
||||
Balance int64
|
||||
FrozenBalance int64
|
||||
}
|
||||
|
||||
func (s *WalletStore) GetShopCommissionSummaryBatch(ctx context.Context, shopIDs []uint) (map[uint]*ShopCommissionSummary, error) {
|
||||
if len(shopIDs) == 0 {
|
||||
return make(map[uint]*ShopCommissionSummary), nil
|
||||
}
|
||||
|
||||
var wallets []model.Wallet
|
||||
err := s.db.WithContext(ctx).
|
||||
Where("resource_type = ? AND resource_id IN ? AND wallet_type = ?", "shop", shopIDs, "commission").
|
||||
Find(&wallets).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uint]*ShopCommissionSummary)
|
||||
for _, w := range wallets {
|
||||
result[w.ResourceID] = &ShopCommissionSummary{
|
||||
ShopID: w.ResourceID,
|
||||
Balance: w.Balance,
|
||||
FrozenBalance: w.FrozenBalance,
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *WalletStore) GetByID(ctx context.Context, id uint) (*model.Wallet, error) {
|
||||
var wallet model.Wallet
|
||||
if err := s.db.WithContext(ctx).First(&wallet, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &wallet, nil
|
||||
}
|
||||
|
||||
func (s *WalletStore) DeductFrozenBalanceWithTx(ctx context.Context, tx *gorm.DB, walletID uint, amount int64) error {
|
||||
result := tx.WithContext(ctx).
|
||||
Model(&model.Wallet{}).
|
||||
Where("id = ? AND frozen_balance >= ?", walletID, amount).
|
||||
Updates(map[string]interface{}{
|
||||
"frozen_balance": gorm.Expr("frozen_balance - ?", amount),
|
||||
})
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *WalletStore) UnfreezeBalanceWithTx(ctx context.Context, tx *gorm.DB, walletID uint, amount int64) error {
|
||||
result := tx.WithContext(ctx).
|
||||
Model(&model.Wallet{}).
|
||||
Where("id = ? AND frozen_balance >= ?", walletID, amount).
|
||||
Updates(map[string]interface{}{
|
||||
"balance": gorm.Expr("balance + ?", amount),
|
||||
"frozen_balance": gorm.Expr("frozen_balance - ?", amount),
|
||||
})
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
37
internal/store/postgres/wallet_transaction_store.go
Normal file
37
internal/store/postgres/wallet_transaction_store.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type WalletTransactionStore struct {
|
||||
db *gorm.DB
|
||||
redis *redis.Client
|
||||
}
|
||||
|
||||
func NewWalletTransactionStore(db *gorm.DB, redis *redis.Client) *WalletTransactionStore {
|
||||
return &WalletTransactionStore{
|
||||
db: db,
|
||||
redis: redis,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *WalletTransactionStore) CreateWithTx(ctx context.Context, tx *gorm.DB, transaction *model.WalletTransaction) error {
|
||||
return tx.WithContext(ctx).Create(transaction).Error
|
||||
}
|
||||
|
||||
func (s *WalletTransactionStore) Create(ctx context.Context, transaction *model.WalletTransaction) error {
|
||||
return s.db.WithContext(ctx).Create(transaction).Error
|
||||
}
|
||||
|
||||
func (s *WalletTransactionStore) GetByID(ctx context.Context, id uint) (*model.WalletTransaction, error) {
|
||||
var tx model.WalletTransaction
|
||||
if err := s.db.WithContext(ctx).First(&tx, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tx, nil
|
||||
}
|
||||
Reference in New Issue
Block a user