- 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.
55 lines
1.6 KiB
TypeScript
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))
|