---

description: "Task list for Inventory Sync Button (046)"

---

# Tasks: Inventory Sync Button (046)

**Input**: Design documents from `/specs/046-inventory-sync-button/`
**Prerequisites**: plan.md (required), spec.md (required), research.md, data-model.md, contracts/

**Tests**: REQUIRED (Pest) — this feature changes runtime behavior.

**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.

## Format: `- [ ] T### [P?] [Story] Description with file path`

- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
- Include exact file paths in descriptions

---

## Phase 1: Setup (Shared Infrastructure)

**Purpose**: Ensure feature docs and baseline scaffolding are in place.

- [ ] T001 Verify feature docs exist and are current in specs/046-inventory-sync-button/{spec.md,plan.md,research.md,data-model.md,quickstart.md,contracts/internal-actions.md}
- [X] T001 Verify feature docs exist and are current in specs/046-inventory-sync-button/{spec.md,plan.md,research.md,data-model.md,quickstart.md,contracts/internal-actions.md}
- [X] T002 [P] Locate existing Inventory landing UI and runs list pages in app/Filament/Pages/InventoryLanding.php and app/Filament/Resources/InventorySyncRunResource/**

---

## Phase 2: Foundational (Blocking Prerequisites)

**Purpose**: Core infrastructure that MUST be complete before ANY user story work can be finished end-to-end.

- [X] T003 Add nullable initiator FK to inventory sync runs in database/migrations/xxxx_xx_xx_xxxxxx_add_user_id_to_inventory_sync_runs_table.php
- [X] T004 [P] Add `user()` relationship + casts/guarding as needed in app/Models/InventorySyncRun.php
- [X] T005 [P] Add `use Illuminate\Database\Eloquent\Relations\BelongsTo;` + `user(): BelongsTo` in app/Models/InventorySyncRun.php
- [X] T006 Add queued job skeleton for inventory sync in app/Jobs/RunInventorySyncJob.php
- [X] T007 [P] Add default inventory selection builder (full inventory) and deterministic selection_hash helper as methods on app/Services/Inventory/InventorySyncService.php (no new factory/hasher classes)
- [X] T008 Add service entrypoint that attributes initiator on run record in app/Services/Inventory/InventorySyncService.php

**Checkpoint**: DB schema + job/service primitives exist.

---

## Phase 3: User Story 1 — Run Inventory Sync from UI (Priority: P1) 🎯 MVP

**Goal**: Provide a “Run Inventory Sync” action for the current tenant that dispatches work asynchronously and is observable.

**Independent Test**: Clicking the action creates a `BulkOperationRun` and an `InventorySyncRun`, then job completes and updates both + DB notifications.

### Tests for User Story 1 (REQUIRED)

- [X] T010 [P] [US1] Add feature test covering action dispatch + run creation AND cross-tenant rejection (403 + “Not allowed” + no run/job created) in tests/Feature/Inventory/InventorySyncButtonTest.php
- [X] T011 [P] [US1] Add feature test covering queued job success updates bulk run + inventory run in tests/Feature/Inventory/RunInventorySyncJobTest.php

### Implementation for User Story 1

- [X] T012 [US1] Add “Run Inventory Sync” header action to app/Filament/Pages/InventoryLanding.php
- [X] T013 [US1] If needed, surface the action in resources/views/filament/pages/inventory-landing.blade.php (only if header actions aren’t visible)
- [X] T014 [US1] On click, build default selection via app/Services/Inventory/InventorySyncService.php
- [X] T015 [US1] On click, create BulkOperationRun (resource `inventory`, action `sync`, total_items=1) via app/Services/BulkOperationService.php (inline from the action handler)
- [X] T016 [US1] On click, send “started” Filament DB notification in app/Filament/Pages/InventoryLanding.php
- [X] T017 [US1] On click, dispatch app/Jobs/RunInventorySyncJob.php with tenant_id, user_id, bulk_run_id, selection_payload
- [X] T018 [US1] Implement app/Jobs/RunInventorySyncJob.php to start bulk run + call InventorySyncService entrypoint
- [X] T019 [US1] In job, map InventorySyncRun terminal outcome → BulkOperationService counters/status in app/Jobs/RunInventorySyncJob.php
- [X] T020 [US1] In job, send completion/failure DB notification to the initiating user in app/Jobs/RunInventorySyncJob.php
- [X] T021 [US1] Emit audit events for dispatched + completed/failed/skipped using app/Services/Intune/AuditLogger.php from app/Jobs/RunInventorySyncJob.php

**Checkpoint**: US1 works end-to-end with queue worker running.

---

## Phase 4: User Story 2 — Safe feedback when sync cannot start (Priority: P2)

**Goal**: Prevent duplicate/overlapping runs and provide clear feedback when sync can’t start.

**Independent Test**: With a `running` InventorySyncRun for the same tenant+selection, the action does not dispatch a new job and shows an informational message.

### Tests for User Story 2 (REQUIRED)

- [X] T022 [P] [US2] Add feature test for “already running” preflight blocking in tests/Feature/Inventory/InventorySyncButtonTest.php
- [X] T023 [P] [US2] Add feature test for lock/concurrency skip outcome mapping in tests/Feature/Inventory/RunInventorySyncJobTest.php

### Implementation for User Story 2

- [X] T024 [US2] Add preflight check for existing running selection_hash in app/Filament/Pages/InventoryLanding.php
- [X] T025 [US2] Compute selection_hash using app/Services/Inventory/InventorySyncService.php (same logic used for run creation) and use it for the preflight check in app/Filament/Pages/InventoryLanding.php
- [X] T026 [US2] Add clear Filament notification message when blocked due to running/locks in app/Filament/Pages/InventoryLanding.php
- [X] T027 [US2] Ensure RunInventorySyncJob handles `skipped` InventorySyncRun (concurrency/lock) and marks BulkOperationRun as completed_with_errors or completed (skipped) with reason in app/Jobs/RunInventorySyncJob.php

**Checkpoint**: User gets clear feedback; duplicates are prevented.

---

## Phase 5: User Story 3 — Permissioned access (Priority: P3)

**Goal**: Only authorized users can start Inventory Sync.

**Independent Test**: Unauthorized users do not see the action (or cannot execute it) and no runs are created.

### Tests for User Story 3 (REQUIRED)

- [X] T028 [P] [US3] Add feature test that unauthorized user cannot see/execute the action in tests/Feature/Inventory/InventorySyncButtonTest.php

### Implementation for User Story 3

- [X] T029 [US3] Gate action visibility/authorization via User::canSyncTenant(Tenant::current()) in app/Filament/Pages/InventoryLanding.php
- [X] T030 [US3] Ensure server-side authorization check is enforced in action handler (not only visibility) in app/Filament/Pages/InventoryLanding.php

**Checkpoint**: Authorization is enforced and tested.

---

## Phase 6: Polish & Cross-Cutting Concerns

**Purpose**: Make delivery safe, consistent, and easy to validate.

- [X] T031 [P] Add/adjust translation-safe, consistent notification copy (start/complete/fail) in app/Filament/Pages/InventoryLanding.php and app/Jobs/RunInventorySyncJob.php
- [X] T032 Ensure `InventorySyncRunResource` shows initiator when present (user_id) in app/Filament/Resources/InventorySyncRunResource.php
- [X] T033 [P] Run formatter on changed files: `./vendor/bin/pint --dirty`
- [X] T034 Run targeted tests: `./vendor/bin/sail artisan test --filter=InventorySync` (or specific test files)
- [X] T035 Validate quickstart steps remain accurate in specs/046-inventory-sync-button/quickstart.md
- [X] T036 Make BulkOperation progress reflect selected policy types (total_items = #types; per-type success/failure) in app/Filament/Pages/InventoryLanding.php and app/Jobs/RunInventorySyncJob.php
- [X] T037 Add `include_dependencies` toggle to the “Run Inventory Sync” modal in app/Filament/Pages/InventoryLanding.php and cover via tests/Feature/Inventory/InventorySyncButtonTest.php

---

## Dependencies & Execution Order

### User Story dependency graph

- Setup → Foundational → US1 → (US2, US3) → Polish

Rationale:
- US1 establishes the action + job + progress/notifications baseline.
- US2 and US3 are incremental safety/guardrails on top of the same action.

### Parallel opportunities

- Phase 2: T004, T005, T007 can run in parallel (separate files).
- US1: T010 and T011 can be written in parallel.
- US2: T022 and T023 can be written in parallel.

---

## Parallel Example: User Story 1

Parallelizable work for US1 (after Phase 2 is complete):

```text
Run in parallel:
- T010 + T011 (tests)
- T012 + T018 (UI action + job implementation)

Then:
- T015–T017 (wire dispatch + notifications)
- T019–T021 (status mapping + DB notif + audit)
```

---

## Implementation Strategy

### MVP scope (recommended)

- Deliver US1 only (Phases 1–3) and validate via quickstart.
- Then add US2 and US3 as hardening increments.
