user_asset_id, FILTER_VALIDATE_INT); if ($userAssetId === false || $userAssetId <= 0) { throw new \InvalidArgumentException(__('User asset not found')); } $scoreValue = filter_var($model->score_value, FILTER_VALIDATE_INT); if ($scoreValue === false || $scoreValue === 0) { throw new \InvalidArgumentException(__('Points adjustment must be a non-zero integer')); } $userAsset = MallUserAsset::where('id', $userAssetId)->lock(true)->find(); if (!$userAsset) { throw new \RuntimeException(__('User asset not found')); } $before = $userAsset->available_points; $after = $before + $scoreValue; if ($after < 0) { throw new \RuntimeException(__('Insufficient available points')); } $model->user_asset_id = $userAssetId; $model->score_value = $scoreValue; $model->before = $before; $model->after = $after; $model->memo = $scoreValue > 0 ? __('Administrator added %s points', [abs($scoreValue)]) : __('Administrator deducted %s points', [abs($scoreValue)]); $userAsset->available_points = $after; $userAsset->save(); } public static function onBeforeDelete(): bool { return false; } public function userAsset(): BelongsTo { return $this->belongsTo(MallUserAsset::class, 'user_asset_id'); } public function admin(): BelongsTo { return $this->belongsTo(Admin::class, 'admin_id'); } }