Files
junhong_cmp_fiber/internal/bootstrap/services.go
huang 7e489a19fb fix: 角色删除前校验分配情况,禁止删除使用中的角色
角色被删除后,其关联的账号-角色记录未清理,导致 CountByAccountID
统计到孤儿记录,使被分配该角色的账号无法重新分配新角色。

修复方案:删除角色前检查 tb_account_role 和 tb_shop_role,
若仍有账号或店铺持有该角色则返回 1028 错误,强制管理员显式
解除所有分配后再删除,保证数据一致性与审计完整性。
2026-04-07 17:23:49 +08:00

242 lines
15 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package bootstrap
import (
"github.com/break/junhong_cmp_fiber/internal/polling"
accountSvc "github.com/break/junhong_cmp_fiber/internal/service/account"
accountAuditSvc "github.com/break/junhong_cmp_fiber/internal/service/account_audit"
assetAllocationRecordSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_allocation_record"
authSvc "github.com/break/junhong_cmp_fiber/internal/service/auth"
carrierSvc "github.com/break/junhong_cmp_fiber/internal/service/carrier"
clientAuthSvc "github.com/break/junhong_cmp_fiber/internal/service/client_auth"
commissionCalculationSvc "github.com/break/junhong_cmp_fiber/internal/service/commission_calculation"
commissionStatsSvc "github.com/break/junhong_cmp_fiber/internal/service/commission_stats"
commissionWithdrawalSvc "github.com/break/junhong_cmp_fiber/internal/service/commission_withdrawal"
commissionWithdrawalSettingSvc "github.com/break/junhong_cmp_fiber/internal/service/commission_withdrawal_setting"
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
"github.com/break/junhong_cmp_fiber/pkg/constants"
assetSvc "github.com/break/junhong_cmp_fiber/internal/service/asset"
assetWalletSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_wallet"
deviceSvc "github.com/break/junhong_cmp_fiber/internal/service/device"
deviceImportSvc "github.com/break/junhong_cmp_fiber/internal/service/device_import"
enterpriseSvc "github.com/break/junhong_cmp_fiber/internal/service/enterprise"
enterpriseCardSvc "github.com/break/junhong_cmp_fiber/internal/service/enterprise_card"
enterpriseDeviceSvc "github.com/break/junhong_cmp_fiber/internal/service/enterprise_device"
exchangeSvc "github.com/break/junhong_cmp_fiber/internal/service/exchange"
iotCardSvc "github.com/break/junhong_cmp_fiber/internal/service/iot_card"
iotCardImportSvc "github.com/break/junhong_cmp_fiber/internal/service/iot_card_import"
myCommissionSvc "github.com/break/junhong_cmp_fiber/internal/service/my_commission"
orderSvc "github.com/break/junhong_cmp_fiber/internal/service/order"
packageSvc "github.com/break/junhong_cmp_fiber/internal/service/package"
packageSeriesSvc "github.com/break/junhong_cmp_fiber/internal/service/package_series"
permissionSvc "github.com/break/junhong_cmp_fiber/internal/service/permission"
personalCustomerSvc "github.com/break/junhong_cmp_fiber/internal/service/personal_customer"
purchaseValidationSvc "github.com/break/junhong_cmp_fiber/internal/service/purchase_validation"
rechargeSvc "github.com/break/junhong_cmp_fiber/internal/service/recharge"
roleSvc "github.com/break/junhong_cmp_fiber/internal/service/role"
shopSvc "github.com/break/junhong_cmp_fiber/internal/service/shop"
agentRechargeSvc "github.com/break/junhong_cmp_fiber/internal/service/agent_recharge"
pollingSvc "github.com/break/junhong_cmp_fiber/internal/service/polling"
refundSvc "github.com/break/junhong_cmp_fiber/internal/service/refund"
shopCommissionSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_commission"
shopPackageBatchAllocationSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_package_batch_allocation"
shopPackageBatchPricingSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_package_batch_pricing"
shopSeriesGrantSvc "github.com/break/junhong_cmp_fiber/internal/service/shop_series_grant"
trafficSvc "github.com/break/junhong_cmp_fiber/internal/service/traffic"
wechatConfigSvc "github.com/break/junhong_cmp_fiber/internal/service/wechat_config"
)
type services struct {
Account *accountSvc.Service
AccountAudit *accountAuditSvc.Service
Role *roleSvc.Service
Permission *permissionSvc.Service
PersonalCustomer *personalCustomerSvc.Service
ClientAuth *clientAuthSvc.Service
Shop *shopSvc.Service
Auth *authSvc.Service
ShopCommission *shopCommissionSvc.Service
CommissionWithdrawal *commissionWithdrawalSvc.Service
CommissionWithdrawalSetting *commissionWithdrawalSettingSvc.Service
CommissionCalculation *commissionCalculationSvc.Service
Enterprise *enterpriseSvc.Service
EnterpriseCard *enterpriseCardSvc.Service
EnterpriseDevice *enterpriseDeviceSvc.Service
Authorization *enterpriseCardSvc.AuthorizationService
MyCommission *myCommissionSvc.Service
IotCard *iotCardSvc.Service
IotCardImport *iotCardImportSvc.Service
Device *deviceSvc.Service
DeviceImport *deviceImportSvc.Service
AssetAllocationRecord *assetAllocationRecordSvc.Service
Carrier *carrierSvc.Service
PackageSeries *packageSeriesSvc.Service
Package *packageSvc.Service
PackageDailyRecord *packageSvc.DailyRecordService
PackageCustomerView *packageSvc.CustomerViewService
ShopPackageBatchAllocation *shopPackageBatchAllocationSvc.Service
ShopPackageBatchPricing *shopPackageBatchPricingSvc.Service
ShopSeriesGrant *shopSeriesGrantSvc.Service
CommissionStats *commissionStatsSvc.Service
PurchaseValidation *purchaseValidationSvc.Service
Order *orderSvc.Service
Exchange *exchangeSvc.Service
Recharge *rechargeSvc.Service
PollingConfig *pollingSvc.ConfigService
PollingConcurrency *pollingSvc.ConcurrencyService
PollingMonitoring *pollingSvc.MonitoringService
PollingAlert *pollingSvc.AlertService
PollingCleanup *pollingSvc.CleanupService
PollingManualTrigger *pollingSvc.ManualTriggerService
Asset *assetSvc.Service
AssetLifecycle *assetSvc.LifecycleService
AssetWallet *assetWalletSvc.Service
StopResumeService *iotCardSvc.StopResumeService
WechatConfig *wechatConfigSvc.Service
AgentRecharge *agentRechargeSvc.Service
PackageActivation *packageSvc.ActivationService
Refund *refundSvc.Service
TrafficQuery *trafficSvc.QueryService
}
func initServices(s *stores, deps *Dependencies) *services {
purchaseValidation := purchaseValidationSvc.New(deps.DB, s.IotCard, s.Device, s.Package, s.ShopPackageAllocation)
accountAudit := accountAuditSvc.NewService(s.AccountOperationLog)
account := accountSvc.New(s.Account, s.Role, s.AccountRole, s.ShopRole, s.Shop, s.Enterprise, accountAudit)
// 创建 IotCard service 并设置回调
iotCard := iotCardSvc.New(deps.DB, s.IotCard, s.Shop, s.AssetAllocationRecord, s.ShopPackageAllocation, s.ShopSeriesAllocation, s.PackageSeries, deps.GatewayClient, deps.Logger)
// 使用 PollingLifecycleService 替代 APICallback通过分片队列准确操作修复 api_callback.go 遗漏 protect 队列的 Bug3
pollingConfigStore := postgres.NewPollingConfigStore(deps.DB)
pollingConfigMgr := polling.NewPollingConfigManager(pollingConfigStore, deps.Redis, deps.Logger)
pollingQueueMgr := polling.NewPollingQueueManager(deps.Redis, constants.PollingShardCount, deps.Logger)
iotCard.SetPollingCallback(polling.NewPollingLifecycleService(pollingQueueMgr, pollingConfigMgr, s.IotCard, s.DeviceSimBinding, s.Device, deps.Logger))
// 注入流量扣减回调,使手动刷新资产时能触发套餐流量扣减
usageService := packageSvc.NewUsageService(deps.DB, deps.Redis, s.PackageUsage, s.PackageUsageDailyRecord, s.DeviceSimBinding, deps.Logger)
iotCard.SetDataDeductor(usageService)
// 创建支付配置服务Order 和 Recharge 依赖)
wechatConfig := wechatConfigSvc.New(s.WechatConfig, s.Order, s.AssetRecharge, s.AgentRecharge, accountAudit, deps.Redis, deps.Logger)
packageActivation := packageSvc.NewActivationService(
deps.DB,
deps.Redis,
s.PackageUsage,
s.Package,
s.PackageUsageDailyRecord,
deps.Logger,
)
stopResumeService := iotCardSvc.NewStopResumeService(deps.Redis, s.IotCard, s.PackageUsage, s.DeviceSimBinding, deps.GatewayClient, deps.Logger)
device := deviceSvc.New(deps.DB, deps.Redis, s.Device, s.DeviceSimBinding, s.IotCard, s.Shop, s.AssetAllocationRecord, s.ShopPackageAllocation, s.ShopSeriesAllocation, s.PackageSeries, deps.GatewayClient, s.AssetIdentifier)
return &services{
Account: account,
AccountAudit: accountAudit,
Role: roleSvc.New(s.Role, s.Permission, s.RolePermission, s.AccountRole, s.ShopRole),
Permission: permissionSvc.New(s.Permission, s.AccountRole, s.RolePermission, account, deps.Redis),
PersonalCustomer: personalCustomerSvc.NewService(s.PersonalCustomer, s.PersonalCustomerPhone, deps.Logger),
ClientAuth: clientAuthSvc.New(
deps.DB,
s.PersonalCustomerOpenID,
s.PersonalCustomer,
s.PersonalCustomerDevice,
s.PersonalCustomerPhone,
s.IotCard,
s.Device,
wechatConfig,
deps.VerificationService,
deps.JWTManager,
deps.Redis,
deps.Logger,
),
Shop: shopSvc.New(s.Shop, s.Account, s.ShopRole, s.Role, s.AccountRole, s.AgentWallet),
Auth: authSvc.New(s.Account, s.AccountRole, s.RolePermission, s.Permission, s.Shop, deps.TokenManager, deps.Logger),
ShopCommission: shopCommissionSvc.New(s.Shop, s.Account, s.AgentWallet, s.CommissionWithdrawalRequest, s.CommissionRecord, deps.DB, deps.Logger),
CommissionWithdrawal: commissionWithdrawalSvc.New(deps.DB, s.Shop, s.Account, s.AgentWallet, s.AgentWalletTransaction, s.CommissionWithdrawalRequest),
CommissionWithdrawalSetting: commissionWithdrawalSettingSvc.New(deps.DB, s.Account, s.CommissionWithdrawalSetting),
CommissionCalculation: commissionCalculationSvc.New(
deps.DB,
s.CommissionRecord,
s.Shop,
s.ShopPackageAllocation,
s.ShopSeriesAllocation,
s.PackageSeries,
s.IotCard,
s.Device,
s.AgentWallet,
s.AgentWalletTransaction,
s.Order,
s.OrderItem,
s.Package,
s.ShopSeriesCommissionStats,
commissionStatsSvc.New(s.ShopSeriesCommissionStats),
deps.Logger,
),
Enterprise: enterpriseSvc.New(deps.DB, s.Enterprise, s.Shop, s.Account),
EnterpriseCard: enterpriseCardSvc.New(deps.DB, s.Enterprise, s.EnterpriseCardAuthorization),
EnterpriseDevice: enterpriseDeviceSvc.New(deps.DB, s.Enterprise, s.Device, s.DeviceSimBinding, s.EnterpriseDeviceAuthorization, s.EnterpriseCardAuthorization, deps.Logger),
Authorization: enterpriseCardSvc.NewAuthorizationService(s.Enterprise, s.IotCard, s.EnterpriseCardAuthorization, deps.Logger),
MyCommission: myCommissionSvc.New(deps.DB, s.Shop, s.AgentWallet, s.CommissionWithdrawalRequest, s.CommissionWithdrawalSetting, s.CommissionRecord, s.AgentWalletTransaction),
IotCard: iotCard,
IotCardImport: iotCardImportSvc.New(deps.DB, s.IotCardImportTask, deps.QueueClient),
Device: device,
DeviceImport: deviceImportSvc.New(deps.DB, s.DeviceImportTask, deps.QueueClient),
AssetAllocationRecord: assetAllocationRecordSvc.New(deps.DB, s.AssetAllocationRecord, s.Shop, s.Account),
Carrier: carrierSvc.New(s.Carrier),
PackageSeries: packageSeriesSvc.New(s.PackageSeries, s.ShopSeriesAllocation, s.Package),
Package: packageSvc.New(s.Package, s.PackageSeries, s.ShopPackageAllocation, s.ShopSeriesAllocation),
PackageDailyRecord: packageSvc.NewDailyRecordService(deps.DB, deps.Redis, s.PackageUsageDailyRecord, deps.Logger),
PackageCustomerView: packageSvc.NewCustomerViewService(deps.DB, deps.Redis, s.PackageUsage, deps.Logger),
ShopPackageBatchAllocation: shopPackageBatchAllocationSvc.New(deps.DB, s.Package, s.ShopPackageAllocation, s.ShopSeriesAllocation, s.Shop),
ShopPackageBatchPricing: shopPackageBatchPricingSvc.New(deps.DB, s.ShopPackageAllocation, s.ShopPackageAllocationPriceHistory, s.Shop),
ShopSeriesGrant: shopSeriesGrantSvc.New(deps.DB, s.ShopSeriesAllocation, s.ShopPackageAllocation, s.ShopPackageAllocationPriceHistory, s.Shop, s.Package, s.PackageSeries, deps.Logger),
CommissionStats: commissionStatsSvc.New(s.ShopSeriesCommissionStats),
PurchaseValidation: purchaseValidation,
Order: orderSvc.New(deps.DB, deps.Redis, s.Order, s.OrderItem, s.AgentWallet, s.AssetWallet, purchaseValidation, s.ShopPackageAllocation, s.ShopSeriesAllocation, s.IotCard, s.Device, s.PackageSeries, s.PackageUsage, s.Package, wechatConfig, deps.WechatPayment, deps.QueueClient, deps.Logger, s.AssetIdentifier),
Exchange: exchangeSvc.New(deps.DB, s.ExchangeOrder, s.IotCard, s.Device, s.AssetWallet, s.AssetWalletTransaction, s.PackageUsage, s.PackageUsageDailyRecord, s.ResourceTag, s.PersonalCustomerDevice, deps.Logger),
Recharge: rechargeSvc.New(deps.DB, s.AssetRecharge, s.AssetWallet, s.AssetWalletTransaction, s.IotCard, s.Device, s.ShopSeriesAllocation, s.PackageSeries, s.CommissionRecord, wechatConfig, deps.Logger, deps.QueueClient),
PollingConfig: pollingSvc.NewConfigService(s.PollingConfig),
PollingConcurrency: pollingSvc.NewConcurrencyService(s.PollingConcurrencyConfig, deps.Redis),
PollingMonitoring: pollingSvc.NewMonitoringService(deps.Redis),
PollingAlert: pollingSvc.NewAlertService(s.PollingAlertRule, s.PollingAlertHistory, deps.Redis, deps.Logger),
PollingCleanup: pollingSvc.NewCleanupService(s.DataCleanupConfig, s.DataCleanupLog, deps.Logger),
PollingManualTrigger: pollingSvc.NewManualTriggerService(s.PollingManualTriggerLog, s.IotCard, deps.Redis, deps.Logger),
Asset: assetSvc.New(deps.DB, s.Device, s.IotCard, s.PackageUsage, s.Package, s.PackageSeries, s.DeviceSimBinding, s.Shop, deps.Redis, iotCard, deps.GatewayClient, s.AssetIdentifier, s.Order, s.OrderItem, s.ExchangeOrder),
AssetLifecycle: assetSvc.NewLifecycleService(deps.DB, s.IotCard, s.Device),
AssetWallet: assetWalletSvc.New(s.AssetWallet, s.AssetWalletTransaction),
StopResumeService: stopResumeService,
WechatConfig: wechatConfig,
AgentRecharge: agentRechargeSvc.New(
deps.DB,
s.AgentRecharge,
s.AgentWallet,
s.AgentWalletTransaction,
s.Shop,
s.Account,
wechatConfig,
accountAudit,
deps.Redis,
deps.Logger,
),
PackageActivation: packageActivation,
TrafficQuery: trafficSvc.NewQueryService(deps.Redis, s.CardDailyUsage),
Refund: refundSvc.New(
deps.DB,
s.RefundRequest,
s.Order,
s.CommissionRecord,
s.AgentWallet,
s.AgentWalletTransaction,
stopResumeService,
device,
packageActivation,
s.IotCard,
s.Device,
s.AssetWallet,
deps.Logger,
),
}
}