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

supplier_key, person_id, first_name, last_name, ssn, optional test, test_timeout

Allowed sources

INTERNAL only

Input validator

yes (name + SSN)

Output

{correlation_id}

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

  1. Reload the row and build the search payload from background_person_search.xml (first_name, last_name, ssn).

  2. POST {THOMSON_REUTERS_API_URL}/v3/person/searchResults; read GroupCount from ns*:PersonResults (0 or missing → ResultNotFound) and Uri (missing → MalformedResponse), then GET the search result.

  3. Resolve the person:

    • One group — take ResultGroup.GroupId from ns*:PersonResultsPageV3.

    • Several groups — iterate ResultGroup and pick the record whose FirstName, LastName (case-insensitive) and SSN all equal the task input; no match → ResultNotFound. A missing node anywhere in that scan → MalformedResponse.

  4. POST /v2/personReport/reportResults with background_person_report.xml for that GroupId, then poll the returned Uri until the report’s Status.StatusCode is no longer 204 (Retry(total=20) on the worker, 10 s apart).

  5. 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

ERROR

SectionStatus is Error, ERROR or INCOMPLETE.

PASS

SectionStatus == COMPLETE and SectionRecordCount == 0 — except CorporateSection, which passes with SectionRecordCount ⇐ 1 (owning one company is normal).

FAIL

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.

  • ERROR is normalised to FAIL for 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

VERIFIED_ACCESS_AND_ADVANCE

Neither tier contains ERROR, FAIL or PENDING.

VERIFIED_ACCESS

Only the access tier is clean.

NOT_VERIFIED

The access tier contains ERROR, FAIL or PENDING.

(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: ProcessFinishedEvent with DetailType = DOWNLOAD_PERSONAL_BACKGROUND_REPORT.

  • Implements purge().

Overridable fields

PUT /tasks/{correlation_id}/final_statuses accepts the keys access and advance, each a map of the seven section names to PASS, FAIL, ERROR or PENDING.

Source files

  • task/thomson_reuters/request_personal_background_report/

  • task/thomson_reuters/handle_personal_background_report_response/

  • components/thomson_reuters/request_template/background_person_search.xml, background_person_report.xml

  • Tests: development/unit_tests/task_/thomson_reuters/**