find($this->tenantId); if (! $tenant instanceof Tenant) { throw new RuntimeException('Tenant not found.'); } $user = User::query()->find($this->userId); if (! $user instanceof User) { throw new RuntimeException('User not found.'); } $bulkRun = BulkOperationRun::query()->find($this->bulkRunId); if (! $bulkRun instanceof BulkOperationRun) { throw new RuntimeException('BulkOperationRun not found.'); } $run = InventorySyncRun::query()->find($this->inventorySyncRunId); if (! $run instanceof InventorySyncRun) { throw new RuntimeException('InventorySyncRun not found.'); } $bulkOperationService->start($bulkRun); $processedPolicyTypes = []; $run = $inventorySyncService->executePendingRun( $run, $tenant, function (string $policyType, bool $success, ?string $errorCode) use ($bulkOperationService, $bulkRun, &$processedPolicyTypes): void { $processedPolicyTypes[] = $policyType; if ($success) { $bulkOperationService->recordSuccess($bulkRun); return; } $bulkOperationService->recordFailure($bulkRun, $policyType, $errorCode ?? 'failed'); }, ); $policyTypes = is_array($bulkRun->item_ids ?? null) ? $bulkRun->item_ids : []; if ($policyTypes === []) { $policyTypes = is_array($run->selection_payload['policy_types'] ?? null) ? $run->selection_payload['policy_types'] : []; } if ($run->status === InventorySyncRun::STATUS_SUCCESS) { $bulkOperationService->complete($bulkRun); $auditLogger->log( tenant: $tenant, action: 'inventory.sync.completed', context: [ 'metadata' => [ 'inventory_sync_run_id' => $run->id, 'bulk_run_id' => $bulkRun->id, 'selection_hash' => $run->selection_hash, 'observed' => $run->items_observed_count, 'upserted' => $run->items_upserted_count, ], ], actorId: $user->id, actorEmail: $user->email, actorName: $user->name, resourceType: 'inventory_sync_run', resourceId: (string) $run->id, ); Notification::make() ->title('Inventory sync completed') ->body('Inventory sync finished successfully.') ->success() ->sendToDatabase($user) ->send(); return; } if ($run->status === InventorySyncRun::STATUS_PARTIAL) { $bulkOperationService->complete($bulkRun); $auditLogger->log( tenant: $tenant, action: 'inventory.sync.partial', context: [ 'metadata' => [ 'inventory_sync_run_id' => $run->id, 'bulk_run_id' => $bulkRun->id, 'selection_hash' => $run->selection_hash, 'observed' => $run->items_observed_count, 'upserted' => $run->items_upserted_count, 'errors' => $run->errors_count, ], ], actorId: $user->id, actorEmail: $user->email, actorName: $user->name, status: 'failure', resourceType: 'inventory_sync_run', resourceId: (string) $run->id, ); Notification::make() ->title('Inventory sync completed with errors') ->body('Inventory sync finished with some errors. Review the run details for error codes.') ->warning() ->sendToDatabase($user) ->send(); return; } if ($run->status === InventorySyncRun::STATUS_SKIPPED) { $reason = (string) (($run->error_codes ?? [])[0] ?? 'skipped'); foreach ($policyTypes as $policyType) { $bulkOperationService->recordSkippedWithReason($bulkRun, (string) $policyType, $reason); } $bulkOperationService->complete($bulkRun); $auditLogger->log( tenant: $tenant, action: 'inventory.sync.skipped', context: [ 'metadata' => [ 'inventory_sync_run_id' => $run->id, 'bulk_run_id' => $bulkRun->id, 'selection_hash' => $run->selection_hash, 'reason' => $reason, ], ], actorId: $user->id, actorEmail: $user->email, actorName: $user->name, resourceType: 'inventory_sync_run', resourceId: (string) $run->id, ); Notification::make() ->title('Inventory sync skipped') ->body('Inventory sync could not start due to locks or concurrency limits.') ->warning() ->sendToDatabase($user) ->send(); return; } $reason = (string) (($run->error_codes ?? [])[0] ?? 'failed'); $missingPolicyTypes = array_values(array_diff($policyTypes, array_unique($processedPolicyTypes))); foreach ($missingPolicyTypes as $policyType) { $bulkOperationService->recordFailure($bulkRun, (string) $policyType, $reason); } $bulkOperationService->complete($bulkRun); $auditLogger->log( tenant: $tenant, action: 'inventory.sync.failed', context: [ 'metadata' => [ 'inventory_sync_run_id' => $run->id, 'bulk_run_id' => $bulkRun->id, 'selection_hash' => $run->selection_hash, 'reason' => $reason, ], ], actorId: $user->id, actorEmail: $user->email, actorName: $user->name, status: 'failure', resourceType: 'inventory_sync_run', resourceId: (string) $run->id, ); Notification::make() ->title('Inventory sync failed') ->body('Inventory sync finished with errors.') ->danger() ->sendToDatabase($user) ->send(); } }