seubert-claims/ondeck/scripts/backfill-ams-customer-number.ts
lorentz fad9e18662 feat(imageright): Task Audit feature for SHAPE clients
- Add TaskAudit/TaskAuditStatus Prisma models linked to Client/Task/User.
- Add ImageRightClient (auth, findFilesByFileNumber, findDocuments,
  getSortedFolders) per Vertafore REST v1 API.
- Add audit engine that resolves per-item target dates/windows from the
  SHAPE_IR_Filing_Audit_Spec.md checklist, navigates real ImageRight folder
  structure, and links results to existing Tasks where found.
- Add GET/POST /api/clients/[id]/task-audit (SHAPE/SHAPE2-gated) and a
  Document Audit tab in the client detail page.
- Add Client.amsCustomerNumber (AFW_Customer.CustNo) — ImageRight's
  FileNumberPart1 expects this AMS360 account number, not the amsCustomerId
  GUID. Backfilled via one-off /api/admin/backfill-ams-customer-number.
- Fix folder/document traversal against verified live ImageRight data:
  real folders are nested under a per-year "Policy Term" folder (not flat
  SUBMISSION/PRERENEWAL as in the source spec doc), and document listing
  requires POST /api/documents/find with {FileId, ParentId} — the
  previously assumed /api/containers/{id} endpoint 404s on real ids.
- Add jest coverage for client auth/find calls and folder/doc-type matching.

Known open items (need process-owner input, not resolved here):
- Real IR document types (Correspondences, Pre-Renewal Information, Loss
  Run) don't map 1:1 to the spec's generic labels (EMAIL, EXCEL DOC, PDF).
- Spec's second folder_path segment (e.g. PRERENEWAL) has no matching real
  subfolder for at least one tested client; currently ignored for folder
  navigation and only surfaced in the audit result label.
- Whether an audit item should be skipped when no open Task exists for it,
  rather than always running and reporting INCOMPLETE.
2026-07-08 10:39:12 +00:00

55 lines
1.6 KiB
TypeScript

/**
* One-off backfill for Client.amsCustomerNumber (AFW_Customer.CustNo).
*
* This field was added after clients were already synced, so existing rows
* have it null until their AFW record naturally changes and re-syncs. This
* script backfills it directly from AFW (read-only SELECT) without going
* through the full sync engine's change-detection gating.
*
* Needed for the Task Audit / ImageRight feature: ImageRight's
* FileNumberPart1 expects this short numeric customer number, not the
* amsCustomerId GUID.
*/
import 'dotenv/config'
import { fetchAfwCustomers } from '../src/lib/sync/afw-queries'
import { prisma } from '../src/lib/db'
async function main() {
console.log('Fetching customers from AFW...')
const afwCustomers = await fetchAfwCustomers()
console.log(`Fetched ${afwCustomers.length} AFW customers`)
let updated = 0
let skippedNoCustNo = 0
let skippedNoMatch = 0
for (const afwCustomer of afwCustomers) {
if (afwCustomer.CustNo === null || afwCustomer.CustNo === undefined) {
skippedNoCustNo++
continue
}
const result = await prisma.client.updateMany({
where: { amsCustomerId: afwCustomer.CustId },
data: { amsCustomerNumber: afwCustomer.CustNo },
})
if (result.count > 0) {
updated++
} else {
skippedNoMatch++
}
}
console.log(`\n✅ Backfill complete`)
console.log(` Updated: ${updated}`)
console.log(` Skipped (no CustNo in AFW): ${skippedNoCustNo}`)
console.log(` Skipped (no matching local client): ${skippedNoMatch}`)
}
main()
.catch((error) => {
console.error('Fatal error:', error)
process.exit(1)
})
.finally(() => process.exit(0))