download_personal_background_report
Business purpose: pull a full personal background report for a supplier owner and derive an underwriting verdict split into two tiers — access (can they use the platform) and advance (can they receive advances).
Step 1 — thomson_reuters/request_personal_background_report
InitialTask, runs in the Web API.
Input |
|
Allowed sources |
|
Input validator |
yes (name + SSN) |
Output |
|
Side effects: save the row (pending), set THOMSON_REUTERS_PERSONAL_BACKGROUND_REPORT →
PENDING, validate, start SWF with task_input = {correlation_id}. Workflow id:
Automatic UW Tool - {supplier_key} - Download personal background report.
Step 2 — thomson_reuters/handle_personal_background_report_response
GenericTask + PurgableS3ObjectProducer. Input: {correlation_id}.
Flow
-
Reload the row and build the search payload from
background_person_search.xml(first_name,last_name,ssn). -
POST {THOMSON_REUTERS_API_URL}/v3/person/searchResults; readGroupCountfromns*:PersonResults(0or missing →ResultNotFound) andUri(missing →MalformedResponse), thenGETthe search result. -
Resolve the person:
-
One group — take
ResultGroup.GroupIdfromns*:PersonResultsPageV3. -
Several groups — iterate
ResultGroupand pick the record whoseFirstName,LastName(case-insensitive) andSSNall equal the task input; no match →ResultNotFound. A missing node anywhere in that scan →MalformedResponse.
-
-
POST /v2/personReport/reportResultswithbackground_person_report.xmlfor thatGroupId, then poll the returnedUriuntil the report’sStatus.StatusCodeis no longer204(Retry(total=20)on the worker, 10 s apart). -
Archive the report to S3 and score it.
Section scoring
Seven sections must be present, otherwise MissingResponseSection is raised:
ArrestSection, BankruptcySection, CorporateSection, LawsuitSection,
LienJudgmentSection, UCCSection, CriminalSection.
Each section is scored from SectionStatus and SectionRecordCount:
| Result | Condition |
|---|---|
|
|
|
|
|
anything else, including a missing key. |
The same per-section result is written to both the access and the advance tier initially.
Carrying forward manual overrides
__prepare_final_status_data returns two structures: the default statuses computed from this
run, and the effective statuses saved as the final status.
If a previous processed execution exists for the same supplier + person, its archived report
is re-scored and compared section by section with this run:
-
If this run’s default result differs from the previous run’s default → use the new default (the underlying data changed).
-
If they are identical → keep the previous run’s final status, preserving any manual underwriter override.
-
ERRORis normalised toFAILfor the purposes of that comparison. -
No previous task, no archived report, or no stored final status → defaults are used for both.
The computed defaults are also persisted on additional_data.default_result_statuses and
surfaced by the detailed GET /tasks/result as default_result_status, so an admin UI can show
"vendor says X, we decided Y".
Tool status tiers
ToolStatus |
When |
|---|---|
|
Neither tier contains |
|
Only the |
|
The |
(VERIFIED_ADVANCE exists in the enum but the "advance clean, access dirty" combination
resolves to NOT_VERIFIED.) The same calculation is reused by
PUT /tasks/{correlation_id}/final_statuses.
Test mode
test=true in the request input makes the handle step skip Thomson Reuters entirely and score
./examples/thomson_reuters_personal_background_check_response.json. Adding
test_timeout=true sleeps 360 s first, to exercise SWF activity timeouts. Both are intended for
non-production environments.
Side effects
-
S3:
thomson_reuters/background_reports/supplier_key=<sk>/person_id=<pid>/person/<timestamp>.json. -
TaskExecutionTable→processed,output = {raw_result_s3_path},additional_data = {full_result_s3_path, default_result_statuses}. -
FinalStatusTable.save—{access: {…}, advance: {…}}. -
ToolTable.update— tiered status as above. -
EventBridge:
ProcessFinishedEventwithDetailType = DOWNLOAD_PERSONAL_BACKGROUND_REPORT. -
Implements
purge().