fix: handle contact details on create
Separate nested contact details from the base payload, propagate sync failures to the API response, and add a regression test covering contact creation with details.
This commit is contained in:
parent
ee7b677ae4
commit
1c1808fdb9
@ -72,8 +72,17 @@ class ContactController extends BaseController {
|
|||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
|
if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
|
||||||
try {
|
try {
|
||||||
$id = $this->model->saveContact($input,true);
|
$result = $this->model->saveContact($input);
|
||||||
return $this->respondCreated([ 'status' => 'success', 'message' => 'data created successfully', 'data' => $id ], 201);
|
|
||||||
|
if (($result['status'] ?? 'error') !== 'success') {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'message' => $result['message'] ?? 'Failed to create contact',
|
||||||
|
'data' => []
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respondCreated([ 'status' => 'success', 'message' => 'data created successfully', 'data' => $result ], 201);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,6 +79,9 @@ class ContactModel extends BaseModel {
|
|||||||
$db->transStart();
|
$db->transStart();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
$details = $data['Details'] ?? [];
|
||||||
|
unset($data['Details']);
|
||||||
|
|
||||||
if (!empty($data['ContactID'])) {
|
if (!empty($data['ContactID'])) {
|
||||||
$contactId = $data['ContactID'];
|
$contactId = $data['ContactID'];
|
||||||
$this->update($contactId, $data);
|
$this->update($contactId, $data);
|
||||||
@ -90,9 +93,9 @@ class ContactModel extends BaseModel {
|
|||||||
throw new \RuntimeException('Failed to save contact');
|
throw new \RuntimeException('Failed to save contact');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($data['Details'])) {
|
if (!empty($details)) {
|
||||||
$modelDetail = new \App\Models\Contact\ContactDetailModel();
|
$modelDetail = new \App\Models\Contact\ContactDetailModel();
|
||||||
$result = $modelDetail->syncDetails($contactId, $data['Details']);
|
$result = $modelDetail->syncDetails($contactId, $details);
|
||||||
|
|
||||||
if ($result['status'] !== 'success') {
|
if ($result['status'] !== 'success') {
|
||||||
throw new \RuntimeException('SyncDetails failed: ' . $result['message']);
|
throw new \RuntimeException('SyncDetails failed: ' . $result['message']);
|
||||||
@ -104,6 +107,7 @@ class ContactModel extends BaseModel {
|
|||||||
return [
|
return [
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'ContactID' => $contactId,
|
'ContactID' => $contactId,
|
||||||
|
'DetailsCount' => count($details),
|
||||||
];
|
];
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$db->transRollback();
|
$db->transRollback();
|
||||||
|
|||||||
@ -111,6 +111,50 @@ class ContactControllerTest extends CIUnitTestCase
|
|||||||
$this->assertIsInt($data['data']['ContactID']);
|
$this->assertIsInt($data['data']['ContactID']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCreateContactWithDetails()
|
||||||
|
{
|
||||||
|
$contactData = [
|
||||||
|
'NameFirst' => 'TestContact' . time(),
|
||||||
|
'NameLast' => 'LastName',
|
||||||
|
'Initial' => 'TC',
|
||||||
|
'Details' => [
|
||||||
|
[
|
||||||
|
'SiteID' => '1',
|
||||||
|
'ContactCode' => 'CODE1',
|
||||||
|
'ContactEmail' => 'code1@example.com',
|
||||||
|
'OccupationID' => '1',
|
||||||
|
'JobTitle' => 'Doctor',
|
||||||
|
'Department' => 'General',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'SiteID' => '2',
|
||||||
|
'ContactCode' => 'CODE2',
|
||||||
|
'ContactEmail' => 'code2@example.com',
|
||||||
|
'OccupationID' => '2',
|
||||||
|
'JobTitle' => 'Specialist',
|
||||||
|
'Department' => 'Laboratory',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = $this->withHeaders(['Cookie' => 'token=' . $this->token])
|
||||||
|
->withBody(json_encode($contactData))
|
||||||
|
->call('post', 'api/contact');
|
||||||
|
|
||||||
|
$result->assertStatus(201);
|
||||||
|
$data = json_decode($result->getJSON(), true);
|
||||||
|
$contactId = $data['data']['ContactID'] ?? null;
|
||||||
|
|
||||||
|
$this->assertIsInt($contactId);
|
||||||
|
|
||||||
|
$show = $this->callProtected('get', 'api/contact/' . $contactId);
|
||||||
|
$show->assertStatus(200);
|
||||||
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
|
$this->assertCount(2, $showData['Details']);
|
||||||
|
$this->assertEqualsCanonicalizing(['1', '2'], array_column($showData['Details'], 'SiteID'));
|
||||||
|
}
|
||||||
|
|
||||||
public function testPartialUpdateContactWithSingleField()
|
public function testPartialUpdateContactWithSingleField()
|
||||||
{
|
{
|
||||||
$contactId = $this->createContact(['NameFirst' => 'Original']);
|
$contactId = $this->createContact(['NameFirst' => 'Original']);
|
||||||
@ -121,7 +165,7 @@ class ContactControllerTest extends CIUnitTestCase
|
|||||||
'NameFirst' => 'Patched'
|
'NameFirst' => 'Patched'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(200);
|
||||||
$response = json_decode($patch->getJSON(), true);
|
$response = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $response['status']);
|
$this->assertEquals('success', $response['status']);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user