chore(repo): normalize EOL and harden contact patch flow
- handle contact PATCH failures by checking model save result and returning HTTP 400 with the model error message - update ContactDetailModel nested updates to enforce active-detail checks and use model update() with explicit failure propagation - extend contact patch assertions and align test-create variants expectations to status=success for POST responses - refresh composer lock metadata/dependency constraints and include generated docs/data/test files updated during normalization - impact: API contract unchanged except clearer 400 error responses on invalid contact detail updates
This commit is contained in:
parent
7fd3dfddd8
commit
30c4e47304
@ -115,9 +115,17 @@ class ContactController extends BaseController {
|
|||||||
|
|
||||||
$input['ContactID'] = $id;
|
$input['ContactID'] = $id;
|
||||||
try {
|
try {
|
||||||
$this->model->saveContact($input);
|
$result = $this->model->saveContact($input);
|
||||||
$id = $input['ContactID'];
|
|
||||||
return $this->respond([ 'status' => 'success', 'message' => 'data updated successfully', 'data' => $id ], 200);
|
if (($result['status'] ?? 'error') !== 'success') {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'message' => $result['message'] ?? 'Failed to update contact',
|
||||||
|
'data' => []
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respond([ 'status' => 'success', 'message' => 'data updated successfully', 'data' => $result ], 200);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -113,6 +113,7 @@ class ContactDetailModel extends BaseModel {
|
|||||||
|
|
||||||
$existing = $this->where('ContactDetID', (int) $detailID)
|
$existing = $this->where('ContactDetID', (int) $detailID)
|
||||||
->where('ContactID', $contactID)
|
->where('ContactID', $contactID)
|
||||||
|
->where('ContactEndDate', null)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (empty($existing)) {
|
if (empty($existing)) {
|
||||||
@ -122,13 +123,8 @@ class ContactDetailModel extends BaseModel {
|
|||||||
$updateData = array_intersect_key($detail, array_flip($this->allowedFields));
|
$updateData = array_intersect_key($detail, array_flip($this->allowedFields));
|
||||||
unset($updateData['ContactID']);
|
unset($updateData['ContactID']);
|
||||||
|
|
||||||
if ($updateData !== []) {
|
if ($updateData !== [] && !$this->update((int) $detailID, $updateData)) {
|
||||||
$db = \Config\Database::connect();
|
return false;
|
||||||
$db->table($this->table)
|
|
||||||
->where('ContactDetID', (int) $detailID)
|
|
||||||
->where('ContactID', $contactID)
|
|
||||||
->where('ContactEndDate', null)
|
|
||||||
->update($updateData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
69
composer.lock
generated
69
composer.lock
generated
@ -88,12 +88,12 @@
|
|||||||
"version": "v7.0.5",
|
"version": "v7.0.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/firebase/php-jwt.git",
|
"url": "https://github.com/googleapis/php-jwt.git",
|
||||||
"reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380"
|
"reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380",
|
"url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380",
|
||||||
"reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380",
|
"reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
@ -142,8 +142,8 @@
|
|||||||
"php"
|
"php"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/firebase/php-jwt/issues",
|
"issues": "https://github.com/googleapis/php-jwt/issues",
|
||||||
"source": "https://github.com/firebase/php-jwt/tree/v7.0.5"
|
"source": "https://github.com/googleapis/php-jwt/tree/v7.0.5"
|
||||||
},
|
},
|
||||||
"time": "2026-04-01T20:38:03+00:00"
|
"time": "2026-04-01T20:38:03+00:00"
|
||||||
},
|
},
|
||||||
@ -362,30 +362,34 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache",
|
"name": "symfony/cache",
|
||||||
"version": "v8.0.8",
|
"version": "v7.4.8",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/cache.git",
|
"url": "https://github.com/symfony/cache.git",
|
||||||
"reference": "8abf3ccbeae9d3071b81a3ae7ee11b209f9e1e78"
|
"reference": "467464da294734b0fb17e853e5712abc8470f819"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/cache/zipball/8abf3ccbeae9d3071b81a3ae7ee11b209f9e1e78",
|
"url": "https://api.github.com/repos/symfony/cache/zipball/467464da294734b0fb17e853e5712abc8470f819",
|
||||||
"reference": "8abf3ccbeae9d3071b81a3ae7ee11b209f9e1e78",
|
"reference": "467464da294734b0fb17e853e5712abc8470f819",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.4",
|
"php": ">=8.2",
|
||||||
"psr/cache": "^2.0|^3.0",
|
"psr/cache": "^2.0|^3.0",
|
||||||
"psr/log": "^1.1|^2|^3",
|
"psr/log": "^1.1|^2|^3",
|
||||||
"symfony/cache-contracts": "^3.6",
|
"symfony/cache-contracts": "^3.6",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3",
|
||||||
"symfony/service-contracts": "^2.5|^3",
|
"symfony/service-contracts": "^2.5|^3",
|
||||||
"symfony/var-exporter": "^7.4|^8.0"
|
"symfony/var-exporter": "^6.4|^7.0|^8.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"doctrine/dbal": "<4.3",
|
"doctrine/dbal": "<3.6",
|
||||||
"ext-redis": "<6.1",
|
"ext-redis": "<6.1",
|
||||||
"ext-relay": "<0.12.1"
|
"ext-relay": "<0.12.1",
|
||||||
|
"symfony/dependency-injection": "<6.4",
|
||||||
|
"symfony/http-kernel": "<6.4",
|
||||||
|
"symfony/var-dumper": "<6.4"
|
||||||
},
|
},
|
||||||
"provide": {
|
"provide": {
|
||||||
"psr/cache-implementation": "2.0|3.0",
|
"psr/cache-implementation": "2.0|3.0",
|
||||||
@ -394,16 +398,16 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"cache/integration-tests": "dev-master",
|
"cache/integration-tests": "dev-master",
|
||||||
"doctrine/dbal": "^4.3",
|
"doctrine/dbal": "^3.6|^4",
|
||||||
"predis/predis": "^1.1|^2.0",
|
"predis/predis": "^1.1|^2.0",
|
||||||
"psr/simple-cache": "^1.0|^2.0|^3.0",
|
"psr/simple-cache": "^1.0|^2.0|^3.0",
|
||||||
"symfony/clock": "^7.4|^8.0",
|
"symfony/clock": "^6.4|^7.0|^8.0",
|
||||||
"symfony/config": "^7.4|^8.0",
|
"symfony/config": "^6.4|^7.0|^8.0",
|
||||||
"symfony/dependency-injection": "^7.4|^8.0",
|
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
|
||||||
"symfony/filesystem": "^7.4|^8.0",
|
"symfony/filesystem": "^6.4|^7.0|^8.0",
|
||||||
"symfony/http-kernel": "^7.4|^8.0",
|
"symfony/http-kernel": "^6.4|^7.0|^8.0",
|
||||||
"symfony/messenger": "^7.4|^8.0",
|
"symfony/messenger": "^6.4|^7.0|^8.0",
|
||||||
"symfony/var-dumper": "^7.4|^8.0"
|
"symfony/var-dumper": "^6.4|^7.0|^8.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -438,7 +442,7 @@
|
|||||||
"psr6"
|
"psr6"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/cache/tree/v8.0.8"
|
"source": "https://github.com/symfony/cache/tree/v7.4.8"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -458,7 +462,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-03-30T15:18:51+00:00"
|
"time": "2026-03-30T15:15:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache-contracts",
|
"name": "symfony/cache-contracts",
|
||||||
@ -760,25 +764,26 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-exporter",
|
"name": "symfony/var-exporter",
|
||||||
"version": "v8.0.8",
|
"version": "v7.4.8",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/var-exporter.git",
|
"url": "https://github.com/symfony/var-exporter.git",
|
||||||
"reference": "15776bb07a91b089037da89f8832fa41d5fa6ec6"
|
"reference": "398907e89a2a56fe426f7955c6fa943ec0c77225"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/15776bb07a91b089037da89f8832fa41d5fa6ec6",
|
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/398907e89a2a56fe426f7955c6fa943ec0c77225",
|
||||||
"reference": "15776bb07a91b089037da89f8832fa41d5fa6ec6",
|
"reference": "398907e89a2a56fe426f7955c6fa943ec0c77225",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.4"
|
"php": ">=8.2",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/property-access": "^7.4|^8.0",
|
"symfony/property-access": "^6.4|^7.0|^8.0",
|
||||||
"symfony/serializer": "^7.4|^8.0",
|
"symfony/serializer": "^6.4|^7.0|^8.0",
|
||||||
"symfony/var-dumper": "^7.4|^8.0"
|
"symfony/var-dumper": "^6.4|^7.0|^8.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -816,7 +821,7 @@
|
|||||||
"serialize"
|
"serialize"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/var-exporter/tree/v8.0.8"
|
"source": "https://github.com/symfony/var-exporter/tree/v7.4.8"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -836,7 +841,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-03-30T15:14:47+00:00"
|
"time": "2026-03-24T13:12:05+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
|||||||
@ -156,6 +156,7 @@ class ContactPatchTest extends CIUnitTestCase
|
|||||||
[
|
[
|
||||||
'ContactDetID' => $keepDetail['ContactDetID'],
|
'ContactDetID' => $keepDetail['ContactDetID'],
|
||||||
'JobTitle' => 'Senior Doctor',
|
'JobTitle' => 'Senior Doctor',
|
||||||
|
'ContactStartDate' => '2026-04-16T07:22:44.000Z',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'created' => [
|
'created' => [
|
||||||
@ -182,8 +183,19 @@ class ContactPatchTest extends CIUnitTestCase
|
|||||||
$this->assertCount(2, $afterData['Details']);
|
$this->assertCount(2, $afterData['Details']);
|
||||||
$detailIds = array_column($afterData['Details'], 'ContactDetID');
|
$detailIds = array_column($afterData['Details'], 'ContactDetID');
|
||||||
$this->assertContains($keepDetail['ContactDetID'], $detailIds);
|
$this->assertContains($keepDetail['ContactDetID'], $detailIds);
|
||||||
|
$this->assertNotContains($deleteDetail['ContactDetID'], $detailIds);
|
||||||
|
|
||||||
$updatedDetails = array_values(array_filter($afterData['Details'], static fn ($row) => $row['ContactDetID'] === $keepDetail['ContactDetID']));
|
$updatedDetails = array_values(array_filter(
|
||||||
|
$afterData['Details'],
|
||||||
|
static fn ($row) => $row['ContactDetID'] === $keepDetail['ContactDetID']
|
||||||
|
));
|
||||||
$this->assertNotEmpty($updatedDetails);
|
$this->assertNotEmpty($updatedDetails);
|
||||||
|
$this->assertSame('Senior Doctor', $updatedDetails[0]['JobTitle']);
|
||||||
|
|
||||||
|
$createdDetails = array_values(array_filter(
|
||||||
|
$afterData['Details'],
|
||||||
|
static fn ($row) => (string) $row['SiteID'] === '3'
|
||||||
|
));
|
||||||
|
$this->assertNotEmpty($createdDetails);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -347,7 +347,7 @@ class TestCreateVariantsTest extends CIUnitTestCase
|
|||||||
$response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload);
|
$response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload);
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$response->assertJSONFragment([
|
$response->assertJSONFragment([
|
||||||
'status' => 'created',
|
'status' => 'success',
|
||||||
'message' => 'Test created successfully',
|
'message' => 'Test created successfully',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -390,7 +390,7 @@ class TestCreateVariantsTest extends CIUnitTestCase
|
|||||||
$response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload);
|
$response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload);
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$response->assertJSONFragment([
|
$response->assertJSONFragment([
|
||||||
'status' => 'created',
|
'status' => 'success',
|
||||||
'message' => 'Test created successfully',
|
'message' => 'Test created successfully',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -419,7 +419,7 @@ class TestCreateVariantsTest extends CIUnitTestCase
|
|||||||
$response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload);
|
$response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload);
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$response->assertJSONFragment([
|
$response->assertJSONFragment([
|
||||||
'status' => 'created',
|
'status' => 'success',
|
||||||
'message' => 'Test created successfully',
|
'message' => 'Test created successfully',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user