package asset import ( "context" stderrors "errors" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/store/postgres" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "gorm.io/gorm" ) var deactivatableAssetStatuses = []int{constants.AssetStatusInStock, constants.AssetStatusSold} // LifecycleService 资产生命周期服务 type LifecycleService struct { db *gorm.DB iotCardStore *postgres.IotCardStore deviceStore *postgres.DeviceStore } // NewLifecycleService 创建资产生命周期服务 func NewLifecycleService(db *gorm.DB, iotCardStore *postgres.IotCardStore, deviceStore *postgres.DeviceStore) *LifecycleService { return &LifecycleService{ db: db, iotCardStore: iotCardStore, deviceStore: deviceStore, } } // DeactivateIotCard 手动停用 IoT 卡 func (s *LifecycleService) DeactivateIotCard(ctx context.Context, id uint) error { card, err := s.iotCardStore.GetByID(ctx, id) if err != nil { if stderrors.Is(err, gorm.ErrRecordNotFound) { return errors.New(errors.CodeIotCardNotFound) } return errors.Wrap(errors.CodeDatabaseError, err, "查询IoT卡失败") } if !canDeactivateAsset(card.AssetStatus) { return errors.New(errors.CodeForbidden, "当前状态不允许停用") } result := s.db.WithContext(ctx).Model(&model.IotCard{}). Where("id = ? AND asset_status IN ?", id, deactivatableAssetStatuses). Update("asset_status", constants.AssetStatusDeactivated) if result.Error != nil { return errors.Wrap(errors.CodeDatabaseError, result.Error, "停用IoT卡失败") } if result.RowsAffected == 0 { return errors.New(errors.CodeConflict, "状态已变更,请刷新后重试") } return nil } // DeactivateDevice 手动停用设备 func (s *LifecycleService) DeactivateDevice(ctx context.Context, id uint) error { device, err := s.deviceStore.GetByID(ctx, id) if err != nil { if stderrors.Is(err, gorm.ErrRecordNotFound) { return errors.New(errors.CodeNotFound, "设备不存在") } return errors.Wrap(errors.CodeDatabaseError, err, "查询设备失败") } if !canDeactivateAsset(device.AssetStatus) { return errors.New(errors.CodeForbidden, "当前状态不允许停用") } result := s.db.WithContext(ctx).Model(&model.Device{}). Where("id = ? AND asset_status IN ?", id, deactivatableAssetStatuses). Update("asset_status", constants.AssetStatusDeactivated) if result.Error != nil { return errors.Wrap(errors.CodeDatabaseError, result.Error, "停用设备失败") } if result.RowsAffected == 0 { return errors.New(errors.CodeConflict, "状态已变更,请刷新后重试") } return nil } func canDeactivateAsset(assetStatus int) bool { return assetStatus == constants.AssetStatusInStock || assetStatus == constants.AssetStatusSold }