# ASHT – move_aa_to_ym Development Requirements

## 1. Purpose & Scope
- Track the more complex migration path for ASHT from `aa` to `ym`, while aligning with the shared `move_aa_to_ym` module being built for all sites.
- Document dependencies, blockers, and per-environment actions so future contributors can extend this plan.

## 2. Shared Requirements (inherit from OARSI document)
The following items mirror the cross-site expectations:
1. Build/extend `modules/custom/move_aa_to_ym` with batch + Drush tooling.
2. Reuse `httpServices` and `memberServices` in `modules/custom/ams/ams.services.yml` for all external calls.
3. Introduce `field_aa_id` alongside existing `field_ams_id` on every entity synced to AMS data.
4. Use `PeopleProfileFindID` to locate `ym` IDs, write the old `aa` ID to the remote `ConstituentID`, and keep `field_ams_id` empty for skipped users.
5. Provide reporting + remediation flows (view of missing `field_ams_id`, delete/block with audit output).
6. Author environment-specific automation scripts that drive the module’s commands once validated in staging.

## 3. ASHT-Specific Considerations
- ASHT has additional integrations (custom member benefits, legacy dues rules, etc.); document each dependency and confirm they can read `field_aa_id` if needed.
- Identify extra entity bundles (custom content types, commerce orders, etc.) that store AMS IDs; ensure new fields and migrations cover them.
- Determine whether ASHT needs phased cutovers (e.g., cohort-by-cohort) and reflect that in batch/Drush options.
- Capture API credential differences if ASHT uses a separate YM client or environment.
- When backfilling `field_ams_id`, update the user entity alongside the `therapist_listing` node in `therapist_directory` so both reference the same YM profile; handle `clinic_listing` nodes separately because they map to distinct YM profiles.

## 3a. Bundles Currently Using AMS IDs (ASHT)
| Entity | Bundle / Type | Notes |
| --- | --- | --- |
| `user` | (core user) | Stores existing `field_ams_id`; will hold `field_aa_id` moving forward. |
| `node` | `therapist_listing` (`sites/asht/modules/therapist_directory`) | Shares YM profile with the related user; must be updated in tandem. |
| `node` | `clinic_listing` (`sites/asht/modules/clinic_directory`) | Has its own `field_ams_id`; no overlap with user profiles. |
- Use `/admin/config/ams/field-mapping` to validate these relationships or register new ones if other modules surface.

## 4. Data Handling Requirements
- Prefer exact matches on ImportID or ConstituentID when calling `PeopleProfileFindID` before falling back to email/username.
- For users staying on `aa`, set `field_aa_id`, leave `field_ams_id` empty, and flag them in the “not migrated” view for manual review.
- Ensure the legacy `aa` ID is written to the `ConstituentID` field on the `ym` profile record once created/matched.

## 5. Reporting & Cleanup
- View of empty `field_ams_id` must include filters for ASHT-specific metadata (roles, membership status) to guide the delete vs. block decision.
- Deletion/blocking flow should:
  - Offer dry-run mode showing which accounts would be affected.
  - Emit a timestamped CSV/log (UID, email, `field_aa_id`, action, operator).
  - Optionally just block the accounts, based on CLI flag or Drush option.

## 6. Automation & Deployment
- Draft script location: `sites/asht/scripts/move_aa_to_ym.sh` (exact path TBD).
- Script steps (high level): export creds, run Drush commands to backfill fields, produce non-migrated report, choose delete vs. block action, archive logs.
- Plan separate staging rehearsal before production run; document timing windows and rollback strategy.

## 7. API Reference Snapshot & Migration Flow Clarification

### API Endpoint
```
GET /Ams/{ClientID}/PeopleProfileFindID
Params: ImportID, ConstituentID, ProfileID, Username, Email, PageNumber, PageSize
Response includes ID arrays plus ResponseStatus; handle errors + pagination.
```

### How the Migration Works
**IMPORTANT**: Users have already been migrated from AA to YM in the external AMS system. This migration updates Drupal to reflect that external migration.

**Current State in Drupal**: 
- `field_ams_id` contains the old AA ID (e.g., "12345")

**Current State in YM**: 
- The user profile was migrated from AA to YM
- YM assigned a new ProfileID (e.g., "67890")
- YM stored the old AA ID in the `ConstituentID` field for reference

**Migration Process**:
1. Read the AA ID from Drupal's `field_ams_id` (e.g., "12345")
2. Call YM API: `PeopleProfileFindID` with parameter `ConstituentID=12345`
3. YM returns the new `ProfileID` from the `ProfileIDs` array (e.g., "67890")
4. Store the old AA ID → `field_aa_id` (for historical tracking)
5. Update `field_ams_id` with the new YM ProfileID (e.g., "67890")

**No data is written to YM** - we are only reading from YM to get the new ProfileID that corresponds to each old AA ID.

## 8. Progress Tracker
| Area | Task | Owner | Status | Notes |
| --- | --- | --- | --- | --- |
| Discovery | Inventory all ASHT bundles using AMS IDs |  | ☐ Not started | Bundles listed above; verify via `drush @asht sql:query "SELECT entity_type, bundle FROM field_config WHERE field_name = 'field_ams_id';"` if needed |
| Module | Extend shared batch + Drush commands for ASHT edge cases |  | ☐ Not started | Might require additional service plugins |
| Data | Add `field_aa_id` + update `field_ams_id` storage config |  | ☐ Not started | Ensure config sync captures changes |
| Data | Backfill IDs using YM API (phased by cohort) |  | ☐ Not started | Confirm throttling + pagination |
| Reporting | Build ASHT-specific “missing `field_ams_id`” view |  | ☐ Not started | Add membership filters |
| Cleanup | Implement delete/block workflow with reporting |  | ☐ Not started | Must support dry-run |
| Automation | Create ASHT deployment script + docs |  | ☐ Not started | Script may branch per cohort |
| Validation | Full staging rehearsal incl. scripts |  | ☐ Not started | Sign-off required before prod |

## 9. Component Migration Checklist
| Component | Path | Work Needed | Owner | Status | Notes |
| --- | --- | --- | --- | --- | --- |
| Shared batch/Drush tooling | `public_html/modules/custom/move_aa_to_ym` | Extend commands to support phased ASHT runs + reporting |  | ☐ Not started | Reuse foundation built for OARSI |
| AMS services reuse | `public_html/modules/custom/ams` | Confirm services expose YM endpoints + credentials for ASHT |  | ☐ Not started | Update configs if ASHT uses different ClientID |
| AMS iframe controllers | `public_html/modules/custom/ams/ams_iframes/src/Controller` | Swap legacy `aa` lookups for `ym` data, ensure iframe payloads use `field_ams_id` |  | ☐ Not started | Shared impact across sites |
| LMS integration | `public_html/modules/custom/lms` | Port service calls + ID storage to `ym`; confirm ASHT LMS enrollments read new fields |  | ☐ Not started | Needed before cutting off `aa` |
| ASHT LMS wrapper | `public_html/sites/asht/modules/asht_lms` | Verify custom hooks/jobs reference `field_aa_id` + `field_ams_id` correctly |  | ☐ Not started | Coordinates with global LMS module |
| Digital products | `public_html/sites/asht/modules/aa_digital_product` | Replace `aa` API usage in purchase flows with `ym`; update entity refs |  | ☐ Not started | Validate receipts + fulfillment |
| Clinic directory | `public_html/sites/asht/modules/clinic_directory` | Update profile/node sync to populate `field_aa_id`/`field_ams_id` + YM data pulls |  | ☐ Not started | Regression-test directory search |
| Therapist directory | `public_html/sites/asht/modules/therapist_directory` | Same as clinic directory; ensure YM IDs drive filters/results |  | ☐ Not started | High visibility feature |
| Online store | `public_html/sites/asht/modules/online_store` | Audit for AMS-driven pricing/access rules; migrate calls to `ym` or shared services |  | ☐ Not started | May already rely on `ams` module |
| Other site modules | `public_html/sites/asht/modules/*` | Comprehensive review to catch any remaining `aa` integrations (advocacy, vendor, etc.) |  | ☐ Not started | Document findings per module |
| Site automation script | `public_html/sites/asht/scripts/move_aa_to_ym.sh` (TBD) | Script orchestrated runs incl. module-specific steps + logging |  | ☐ Not started | Requires branching per cohort |

## 10. Implementation Roadmap (hand-off ready)
1. **Shared module prep**
   - Extend `move_aa_to_ym` to expose `drush move-aa-ym:backfill-asht` (filters: `--uid`, `--listing-id`, `--batch-size`, `--dry-run`, `--action=block|delete`).
   - Register any site-specific services/plugins under `sites/asht` if needed, but keep orchestration in the shared module.
   - Ensure `move_aa_to_ym` holds every reusable service/utility while allowing per-site handlers (via config or service tags) for bundle-specific behavior.
2. **YM lookup + pairing logic**
   - Use `memberServices` → `PeopleProfileFindID` to locate YM IDs.
   - Prioritize ImportID/ConstituentID, then Username/Email.
   - For each successful match, capture:
     - User entity `field_aa_id` (legacy AA) + `field_ams_id` (new YM).
     - Paired `therapist_listing` node (match via stored relationship) with identical IDs.
     - For `clinic_listing` nodes, run a separate pass; they never share YM profiles with users.
3. **Remote updates**
   - Push the AA ID into YM’s `ConstituentID` field post-match so remote data mirrors local history.
4. **Unmatched handling**
   - If no YM ID, set `field_aa_id`, leave `field_ams_id` empty, add entry to the “non-migrated” report.
   - Respect flags to `--block-only` vs. `--delete` when later cleanup runs occur.
5. **Logging and audit**
   - Produce CSV/log per batch (UID, listing node IDs, AA ID, YM ID, action).
   - Maintain a separate failure log capturing API errors, timeouts, or skipped records.
6. **Extensibility hooks**
   - Provide alter hooks or service tags so modules like `online_store` or `asht_lms` can react when IDs change.
7. **Testing/deployment notes**
   - Dry-run in staging: confirm user ↔ therapist listing pairs update together.
   - Manually verify clinic directory listing updates with unique YM IDs.
   - After code verification, turn the same command on in production via the future site script.

## 11. Field Mapping Follow-up
- Manual AMS field mappings reside in `public_html/modules/custom/ams/ams_field_mappings`.
- After YM IDs are populated, update/export the relevant site configs (e.g., `public_html/sites/asht/modules/clinic_directory/config/install/...` and `.../therapist_directory/...`) so the new `field_aa_id`/`field_ams_id` behavior propagates.
- The administrative interface `/admin/config/ams/field-mapping` (driven by `modules/custom/ams/ams_field_mappings/src/Form/amsFieldMappingForm.php`) can be used, or you can ship static configuration per site if that’s easier for deployment.

## 12. Operational Notes
- Configuration import/export relies on the Features module; run commands like `drush @asht features:export <feature_name>` after adjusting field mappings or views.
- Always execute Drush commands with the correct alias (`@asht`, `@oarsi`, etc.) so changes stay scoped to the intended site.
- When source configs are missing, use Drush SQL queries (e.g., `drush @asht sql:query "SHOW TABLES LIKE '%field_ams_id%';"`) to confirm every storage location for `field_ams_id` before writing migrations.

## 13. Open Questions
- Does ASHT require additional API scopes/keys for YM beyond the shared credentials?
- Are there ASHT-specific fields (e.g., certification IDs) that must migrate simultaneously?
- Should the delete/block decision be automatic based on membership status, or manual per run?
