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.
This commit is contained in:
parent
835267c333
commit
fad9e18662
14 changed files with 1369 additions and 1 deletions
55
ondeck/scripts/backfill-ams-customer-number.ts
Normal file
55
ondeck/scripts/backfill-ams-customer-number.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* 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))
|
||||
Loading…
Add table
Add a link
Reference in a new issue