Visit offboard removes members from the Visit wellness side after they are
deleted or exited in Nhance. A background job calls the Visit delete-policy
API; on HTTP 200 and a JSON body where message is
success, Nhance appends _DEL to
employee_polices.wellness_onboard for the affected rows.
app/Controllers/EmployeeController.php
(visitOffBoard(), updateVisitoffboardStatus()).
The insurer deletion flow importDeletionUpdateEndorsementID()
enqueues the job from
app/Controllers/EmpDataServiceController.php. The worker maps
the job name in app/Controllers/JobWorker.php.
After importDeletionUpdateEndorsementID() applies policy and
endorsement updates from the deletion Excel, when
$file['insurer_or_tpa'] == 'insurer', the controller enqueues
visitOffBoard alongside cash-deposit and BDS jobs. The payload
carries the list of employee_polices.id values processed in that
batch, the client policy number, and a fixed source string.
$r = Jobs::addJob(['job_name' => 'visitOffBoard', 'payload' => [
'memberIds' => $employee_policy_table_primaryKey ?? [],
'policyNumber' => $policy_name['policy_no'] ?? null,
'source' => 'NHANCE',
]]);
| Payload key | Meaning |
|---|---|
memberIds |
Array of employee_polices.id primary keys collected from the deletion Excel flow (emp_policy_primarykey per row). |
policyNumber |
Policy number from getPolicyNameUsingClientPolicyId() for the batch client policy. |
source |
Always NHANCE in the enqueue; visitOffBoard() also forces source to NHANCE before the HTTP call. |
'visitOffBoard' => [
'type' => 'CC',
'handler' => 'App\Controllers\EmployeeController',
],
The handler builds the Visit URL from environment configuration, appends the
path delete-policy-with-dependents, and POSTs JSON with
memberIds, policyNumber, and source.
Authorization uses a JWT prefix (this differs from the Visit
onboard upload path, which uses Basic auth in
sendFamiliesToWellnessApi()).
$apiUrl = env('WELLNESS_ONBOARD_ENDPOINT_URL') . 'delete-policy-with-dependents';
$apiToken = env('WELLNESS_ONBOARD_AUTHORIZATION');
$response = $client->request('POST', '', [
'headers' => [
'Authorization' => 'JWT ' . $apiToken,
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'memberIds' => $params['memberIds'] ?? [],
'policyNumber' => $params['policyNumber'] ?? '',
'source' => $params['source'] ?? '',
],
'http_errors' => false,
]);
| Outcome | Behavior |
|---|---|
HTTP status 200 |
Decodes JSON, calls updateVisitoffboardStatus() with memberIds and api_result, returns that array shape to the worker. |
| Other HTTP status | Logs failure; returns a structured error array; DB is not updated here. |
| Network or client exception | Logs exception; returns error array with error message. |
This method is only invoked from visitOffBoard() after a
200 response. It validates the payload, requires
$data['api_result']['message'] === 'success', then updates all
listed employee policy rows in one statement.
Empty or non-array input logs and returns false.
Missing api_result logs and returns false.
If message is not exactly success, logs and returns false (no DB update).
If the API returns missingMemberIds, it is logged but processing continues.
Runs whereIn('id', $memberIds) and sets wellness_onboard to CONCAT(wellness_onboard, '_DEL') so existing reference ids stay traceable.
$this->employeePolicyModel
->whereIn('id', $memberIds)
->set('wellness_onboard', "CONCAT(wellness_onboard, '_DEL')", false)
->update();
message === 'success'. A 200 with a failed business payload will
not append _DEL.
visitOffBoardCheck() is a thin admin helper that builds a hardcoded
sample $params array and prints visitOffBoard($params).
It is not part of the production deletion pipeline; use it only for targeted
debugging in non-production environments.
$routes->get('/visitOffBoardCheck', 'EmployeeController::visitOffBoardCheck');
ACL restricts this path to admin role in app/Config/Acl.php
(#^/visitOffBoardCheck#).
The job must supply memberIds, policyNumber, and source in the shape the delete endpoint expects.
WELLNESS_ONBOARD_ENDPOINT_URL must include the correct base (trailing slash behavior matters when concatenating delete-policy-with-dependents). WELLNESS_ONBOARD_AUTHORIZATION must be the token value expected after JWT .
updateVisitoffboardStatus() directly for partial failures
It trusts api_result['message']; wire new callers through visitOffBoard() or replicate its guards.
As with other jobs, the worker must be running; otherwise the offboard job stays queued after deletion processing.
| Pitfall | Why it happens |
|---|---|
wellness_onboard never gets _DEL |
HTTP not 200, or JSON message is not success, or memberIds empty / wrong type. |
| Visit receives wrong identifiers | memberIds must match what the delete API expects (same identifiers family as onboard where applicable). |
| Auth works for onboard but not offboard | Offboard uses JWT header construction; onboard upload uses Basic in a different helper. |
| Job never enqueues | The enqueue block runs only when insurer_or_tpa == 'insurer' on that deletion file path. |