Update Patient (Patcom & Unit Testing)

This commit is contained in:
mikael-zakaria 2025-10-19 22:36:31 +07:00
parent 6287785b73
commit 88f2633bb6
5 changed files with 351 additions and 148 deletions

View File

@ -62,10 +62,19 @@ class DummySeeder extends Seeder {
$this->db->table('patient')->insertBatch($data); $this->db->table('patient')->insertBatch($data);
$data = [ $data = [
[ 'InternalPID'=>1, 'IdentifierType'=>'KTP', 'Identifier'=>'9901', 'CreateDate'=> "$now" ], [ 'InternalPID'=>1, 'IdentifierType'=>'KTP', 'Identifier'=>'9901', 'CreateDate'=> "$now" ],
[ 'InternalPID'=>2, 'IdentifierType'=>'KTP', 'Identifier'=>'9902', 'CreateDate'=> "$now" ], // [ 'InternalPID'=>2, 'IdentifierType'=>'KTP', 'Identifier'=>'9902', 'CreateDate'=> "$now" ],
[ 'InternalPID'=>3, 'IdentifierType'=>'KTP', 'Identifier'=>'9903', 'CreateDate'=> "$now" ] [ 'InternalPID'=>3, 'IdentifierType'=>'KTP', 'Identifier'=>'9903', 'CreateDate'=> "$now" ]
]; ];
$this->db->table('patidt')->insertBatch($data); $this->db->table('patidt')->insertBatch($data);
$data = [
[ "InternalPID" => 1, "Address" => "/api/upload/assasasasd" . 1 . ".jpg", 'CreateDate'=> "$now" ],
[ "InternalPID" => 1, "Address" => "/api/upload/adsasasds" . 2 . ".jpg", 'CreateDate'=> "$now" ],
[ "InternalPID" => 1, "Address" => "/api/upload/sasaasadjs" . 6 . ".jpg", 'CreateDate'=> "$now" ],
[ "InternalPID" => 1, "Address" => "/api/upload/sdjasass" . 5 . ".jpg", 'CreateDate'=> "$now" ],
[ "InternalPID" => 1, "Address" => "/api/upload/sdasasjs" . 4 . ".jpg", 'CreateDate'=> "$now" ],
];
$this->db->table('patatt')->insertBatch($data);
// containerdef // containerdef
$data = [ $data = [

View File

@ -7,7 +7,7 @@ use App\Models\BaseUtcModel;
class PatComModel extends BaseModel { class PatComModel extends BaseModel {
protected $table = 'patcom'; protected $table = 'patcom';
protected $primaryKey = 'PatComID '; protected $primaryKey = 'PatComID ';
protected $allowedFields = ['InternalPID', 'Comment', 'CreateDate', 'DelDate']; protected $allowedFields = ['InternalPID', 'Comment', 'CreateDate', 'EndDate'];
protected $useTimestamps = true; protected $useTimestamps = true;
protected $createdField = 'CreateDate'; protected $createdField = 'CreateDate';
@ -26,14 +26,14 @@ class PatComModel extends BaseModel {
} }
public function updatePatCom(string $patcom, string $InternalPID) { public function updatePatCom(string $patcom, string $InternalPID) {
$exists = $this->where('InternalPID', $InternalPID)->first(); $exists = $this->withDeleted()->where('InternalPID', $InternalPID)->first();
if ($exists) { if ($exists) {
//Update //Update
$this->where('InternalPID', $InternalPID)->set('Comment', $patcom)->update(); $this->where('InternalPID', $InternalPID)->set(['EndDate' => null,'Comment' => $patcom])->update();
} else { } else {
//Insert //Insert
$this->insert(['InternalPID' => $InternalPID, 'Comment' => $patcom]); $this->insert(['InternalPID' => $InternalPID, 'Comment' => $patcom]);
} }
} }

View File

@ -11,14 +11,14 @@ class PatientCreateTest extends CIUnitTestCase
use FeatureTestTrait; use FeatureTestTrait;
protected $endpoint = 'api/patient'; protected $endpoint = 'api/patient';
// 400 - Passed // 400 - Passed
// Validation Gagal - Array Tidak Complete
public function testCreatePatientValidationFail() { public function testCreatePatientValidationFail() {
// Test dengan payload yg tidak lengkap // Test dengan payload yg tidak lengkap
// error 400 yg diharapkan // error 400 yg diharapkan
$payload = ['Name' => 'Ngawur']; $payload = ['Name' => 'Ngawur'];
$result = $this->withBodyFormat('json') $result = $this->withBodyFormat('json')->call('post', 'api/patient', $payload);
->call('post', 'api/patient', $payload);
$result->assertStatus(400); $result->assertStatus(400);
// Test dengan PatiD yg sudah ada // Test dengan PatiD yg sudah ada
@ -35,14 +35,13 @@ class PatientCreateTest extends CIUnitTestCase
"NameAlias"=> "Bud", "NameAlias"=> "Bud",
"Gender"=> "1", "Gender"=> "1",
]; ];
$result = $this->withBodyFormat('json') $result = $this->withBodyFormat('json')->call('post', 'api/patient', $payload);
->call('post', 'api/patient', $payload);
$result->assertStatus(400); $result->assertStatus(400);
} }
// 201 - Passed // 201 - Passed
// Test dengan user dummy // Test Sukses Dengan User Dummy
public function testCreatePatientSuccess() { public function testCreatePatientSuccess() {
$faker = Factory::create('id_ID'); $faker = Factory::create('id_ID');
@ -141,8 +140,8 @@ class PatientCreateTest extends CIUnitTestCase
"Custodian" => 1, "Custodian" => 1,
"PatIdt" => [ "PatIdt" => [
"IdentifierType" => "KTP", "IdentifierType" => "KTP",
// Identifier lebih dari 255 karakter - error validasi
"Identifier" => "numberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetween" "Identifier" => "numberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetweennumberBetween"
// "Identifier" => $faker->nik() ?? $faker->numerify('################')
], ],
"PatAtt" => [ "PatAtt" => [
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ] [ "Address" => "/api/upload/" . $faker->word . ".jpg" ]
@ -163,6 +162,60 @@ class PatientCreateTest extends CIUnitTestCase
$result->assertArrayHasKey("error", $data); $result->assertArrayHasKey("error", $data);
} }
public function testCreateWithoutAttachments() {
$faker = Factory::create('id_ID');
$payload = [
"PatientID" => "DUAU" . $faker->numberBetween(1, 1000).$faker->numberBetween(1, 1000),
"AlternatePID" => "DMAU" . $faker->numberBetween(5, 1000).$faker->numberBetween(1, 1000),
"Prefix" => $faker->title,
"NameFirst" => $faker->firstName,
"NameMiddle" => $faker->firstName,
"NameMaiden" => $faker->firstName,
"NameLast" => $faker->lastName,
"Suffix" => "S.Kom",
"NameAlias" => $faker->userName,
"Gender" => $faker->numberBetween(5, 6),
"PlaceOfBirth" => $faker->city,
"Birthdate" => $faker->date('Y-m-d'),
"ZIP" => $faker->postcode,
"Street_1" => $faker->streetAddress,
"Street_2" => "RT " . $faker->numberBetween(1, 10) . " RW " . $faker->numberBetween(1, 10),
"Street_3" => "Blok " . $faker->numberBetween(1, 20),
"City" => $faker->city,
"Province" => $faker->state,
"EmailAddress1" => "AiA" . $faker->numberBetween(1, 1110).$faker->numberBetween(1, 1110).'@gmail.com',
"EmailAddress2" => "BiA" . $faker->numberBetween(1, 1110).$faker->numberBetween(1, 1110).'@gmail.com',
"Phone" => $faker->phoneNumber,
"MobilePhone" => $faker->phoneNumber,
"Race" => (string) $faker->numberBetween(175, 205),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Religion" => (string) $faker->numberBetween(206, 212),
"Ethnic" => (string) $faker->numberBetween(213, 220),
"Citizenship" => "WNI",
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
"LinkTo" => (string) $faker->numberBetween(2, 3),
"Custodian" => 1,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => $faker->nik() ?? $faker->numerify('################')
],
"PatAtt" => [],
"PatCom" => $faker->sentence,
];
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
$result->assertStatus(201);
}
// 201 - Passed // 201 - Passed
// Test dengan user dummy dan harus berhasil - Attachment kosong // Test dengan user dummy dan harus berhasil - Attachment kosong
public function testCreateWithoutAttachments() { public function testCreateWithoutAttachments() {

View File

@ -11,16 +11,6 @@ class PatientShowTest extends CIUnitTestCase
protected $endpoint = 'api/patient'; protected $endpoint = 'api/patient';
// 200 ok not found - Passed
public function testShowNotFound() {
$result = $this->get($this->endpoint . '/90909090');
$result->assertStatus(200);
$result->assertJSONFragment([
'status' => 'success',
"message" => "data not found."
]);
}
// 200 ok found - Passed // 200 ok found - Passed
public function testShowSingleRow() { public function testShowSingleRow() {
// Pastikan DB test punya seed patient InternalPID=10 tanpa id/addr // Pastikan DB test punya seed patient InternalPID=10 tanpa id/addr
@ -33,5 +23,62 @@ class PatientShowTest extends CIUnitTestCase
$result->assertArrayHasKey('data', $data); $result->assertArrayHasKey('data', $data);
$result->assertIsArray($data['data']); $result->assertIsArray($data['data']);
} }
// 200 ok - Test validasi respons selalu sukses - Passed
public function testShowAlwaysReturnSuccessStatus() {
$result = $this->get($this->endpoint . '/99999');
$result->assertJSONFragment(['status' => 'success']);
}
} // 200 ok not found - Passed
public function testShowNotFound() {
$result = $this->get($this->endpoint . '/90909090');
$result->assertStatus(200);
$result->assertJSONFragment([
'status' => 'success',
"message" => "data not found."
]);
}
// 200 ok found - PatIdt null - Passed
public function testShowWithNullPatIdt() {
$result = $this->get($this->endpoint . '/2');
$data = $result->getJSON();
$data = json_decode($data, true);
$result->assertStatus(200);
$this->assertNull($data['data']['PatIdt']);
}
// 200 ok found - PatAtt null - Passed
public function testShowWithNullPatAtt() {
$result = $this->get($this->endpoint . '/2');
$data = $result->getJSON();
$data = json_decode($data, true);
$result->assertStatus(200);
$this->assertNull($data['data']['PatAtt']);
}
// 200 ok found - PatCom null - Passed
public function testShowWithNullPatCom() {
$result = $this->get($this->endpoint . '/2');
$data = $result->getJSON();
$data = json_decode($data, true);
$result->assertStatus(200);
$this->assertNull($data['data']['PatCom']);
}
// 200 ok found - PatAtt greater dan 1 - Passed
public function testShowWithMultipleAddresses() {
$result = $this->get($this->endpoint . '/1');
$data = $result->getJSON();
$data = json_decode($data, true);
$result->assertStatus(200);
$this->assertIsArray($data['data']['PatAtt']);
$this->assertGreaterThan(1, count($data['data']['PatAtt']));
}
}

View File

@ -10,149 +10,243 @@ class PatientUpdateTest extends CIUnitTestCase
{ {
use FeatureTestTrait; use FeatureTestTrait;
protected $endpoint = 'api/patient'; protected $endpoint = 'api/patient';
/**
* 400 - Validation Fail
* Coba update tanpa field wajib harus gagal validasi.
*/
public function testUpdatePatientValidationFail()
{
$payload = [ 'InternalPID' => null, 'NameFirst' => '' ]; // Tidak valid
$result = $this->withBodyFormat('json')->call('patch', $this->endpoint, $payload);
$result->assertStatus(400);
$json = $result->getJSON();
$data = json_decode($json, true);
$this->assertArrayHasKey('messages', $data);
}
/**
* 404 / 500 - Update Nonexistent Patient
* Coba update InternalPID yang tidak ada.
*/
public function testUpdateNonexistentPatientShouldFail()
{
$faker = Factory::create('id_ID');
$payload = [
'InternalPID' => 999999, // Asumsi tidak ada di DB
"PatientID" => "SMAJ1",
"EmailAddress1" => 'asaas7890@gmail.com',
'NameFirst' => $faker->firstName,
'NameLast' => $faker->lastName,
'Gender' => '1',
'Birthdate' => $faker->date('Y-m-d'),
'PatIdt' => [ 'IdentifierType' => 'KTP', 'Identifier' => $faker->nik() ],
'PatCom' => $faker->sentence,
'PatAtt' => [],
];
$result = $this->withBodyFormat('json')->call('patch', $this->endpoint, $payload);
$result->assertStatus(500); // karena di model akan trigger rollback dan failServerError
}
/**
* 201 - Update Success
* Pastikan bisa update data yang valid (gunakan dummy data dari database).
*/
public function testUpdatePatientSuccess() public function testUpdatePatientSuccess()
{ {
$faker = Factory::create('id_ID'); $faker = Factory::create('id_ID');
// NOTE: Sebaiknya ambil InternalPID yang sudah ada (mock atau dari DB fixture)
// Untuk contoh ini kita asumsikan ada ID 1
$payload = [ $payload = [
"InternalPID" => 1, 'InternalPID' => 1,
"PatientID" => "UPDT" . $faker->numberBetween(100, 999), "PatientID" => "SMAJ1",
"NameFirst" => $faker->firstName, 'NameFirst' => $faker->firstName,
"NameLast" => $faker->lastName, 'NameMiddle' => $faker->firstName,
"Gender" => (string) $faker->numberBetween(5, 6), 'NameLast' => $faker->lastName,
"Birthdate" => $faker->date('Y-m-d'), 'Gender' => '1',
"DeathDateTime" => null, 'Birthdate' => $faker->date('Y-m-d'),
"EmailAddress1" => "asasa@gmail.com", 'EmailAddress1' => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
"PlaceOfBirth" => $faker->city, 'PlaceOfBirth' => $faker->city,
"Race" => (string) $faker->numberBetween(175, 205), 'LinkTo' => null,
"Religion" => (string) $faker->numberBetween(206, 212), 'PatIdt' => [
"Country" => (string) $faker->numberBetween(221, 469), 'IdentifierType' => 'KTP',
"MaritalStatus" => (string) $faker->numberBetween(8, 15), 'Identifier' => $faker->nik(),
"Citizenship" => "WNI", ],
"LinkTo" => null, "DeathIndicator" => (string) $faker->numberBetween(16, 17),
"PatIdt" => [ 'PatCom' => 'Update be',
"IdentifierType" => "KTP", 'PatAtt' => [
"Identifier" => $faker->nik(), [ 'Address' => '/api/upload/' . $faker->word . '.jpg' ],
], ],
"PatCom" => $faker->sentence(5),
"PatAtt" => [
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ]
]
]; ];
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
$result = $this->withBodyFormat('json')->patch($this->endpoint, $payload); $result = $this->withBodyFormat('json')->call('patch', $this->endpoint, $payload);
$result->assertStatus(201); $result->assertStatus(201);
$json = $result->getJSON();
$data = json_decode($json, true);
$this->assertEquals('success', $data['status']);
} }
// /** /**
// * Test gagal karena InternalPID kosong (validasi) * 201 - Update dengan PatCom kosong
// */ */
public function testUpdatePatientValidationError() public function testUpdateWithoutPatCom()
{ {
$faker = Factory::create('id_ID'); $faker = Factory::create('id_ID');
$payload = [ $payload = [
"NameFirst" => $faker->firstName, 'InternalPID' => 1,
"Gender" => (string) $faker->numberBetween(5, 6), "PatientID" => "SMAJ1",
"Birthdate" => $faker->date('Y-m-d'), 'NameFirst' => $faker->firstName,
// Tidak kirim InternalPID 'NameMiddle' => $faker->firstName,
'NameLast' => $faker->lastName,
'Gender' => '1',
'Birthdate' => $faker->date('Y-m-d'),
'EmailAddress1' => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
'PlaceOfBirth' => $faker->city,
'LinkTo' => null,
'PatIdt' => [
'IdentifierType' => 'KTP',
'Identifier' => $faker->nik(),
],
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
'PatCom' => null,
'PatAtt' => [
[ 'Address' => '/api/upload/' . $faker->word . '.jpg' ],
],
]; ];
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
$result = $this->withBodyFormat('json')->patch($this->endpoint, $payload); $result = $this->withBodyFormat('json')->call('patch', $this->endpoint, $payload);
$result->assertStatus(201);
}
/**
* 201 - Update tanpa PatAtt
*/
public function testUpdateWithoutAttachments()
{
$faker = Factory::create('id_ID');
$payload = [
'InternalPID' => 1,
"PatientID" => "SMAJ1",
'NameFirst' => $faker->firstName,
'NameMiddle' => $faker->firstName,
'NameLast' => $faker->lastName,
'Gender' => '1',
'Birthdate' => $faker->date('Y-m-d'),
'EmailAddress1' => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
'PlaceOfBirth' => $faker->city,
'LinkTo' => null,
'PatIdt' => [
'IdentifierType' => 'KTP',
'Identifier' => $faker->nik(),
],
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
'PatCom' => null,
'PatAtt' => [],
];
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
$result = $this->withBodyFormat('json')->call('patch', $this->endpoint, $payload);
$result->assertStatus(201);
}
/**
* 201 - Update tanpa PatAtt
*/
public function testUpdateWithAttachments()
{
$faker = Factory::create('id_ID');
$payload = [
'InternalPID' => 1,
"PatientID" => "SMAJ1",
'NameFirst' => $faker->firstName,
'NameMiddle' => $faker->firstName,
'NameLast' => $faker->lastName,
'Gender' => '1',
'Birthdate' => $faker->date('Y-m-d'),
'EmailAddress1' => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
'PlaceOfBirth' => $faker->city,
'LinkTo' => null,
'PatIdt' => [
'IdentifierType' => 'KTP',
'Identifier' => $faker->nik(),
],
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
'PatCom' => null,
'PatAtt' => [
[ 'Address' => '/api/upload/' . $faker->word . '.jpg' ],
],
];
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
$result = $this->withBodyFormat('json')->call('patch', $this->endpoint, $payload);
$result->assertStatus(201);
}
// /**
// * 500 - Invalid PatIdt
// */
public function testUpdatePatIdtInvalid()
{
$faker = Factory::create('id_ID');
$payload = [
'InternalPID' => 1,
"PatientID" => "SMAJ1",
'NameFirst' => $faker->firstName,
'NameMiddle' => $faker->firstName,
'NameLast' => $faker->lastName,
'Gender' => '1',
'Birthdate' => $faker->date('Y-m-d'),
'EmailAddress1' => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
'PlaceOfBirth' => $faker->city,
'LinkTo' => null,
'PatIdt' => [
'IdentifierType' => [],
'Identifier' => $faker->nik(),
],
"DeathIndicator" => (string) $faker->numberBetween(16, 17),
'PatCom' => null,
'PatAtt' => [
[ 'Address' => '/api/upload/' . $faker->word . '.jpg' ],
],
];
if($payload['DeathIndicator'] == '16') {
$payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
} else {
$payload['DeathDateTime'] = null;
}
$result = $this->withBodyFormat('json')->call('patch', $this->endpoint, $payload);
$result->assertStatus(500);
$json = $result->getJSON(); $json = $result->getJSON();
$data = json_decode($json, true); $data = json_decode($json, true);
$result->assertStatus(400);
$this->assertArrayHasKey('error', $data); $this->assertArrayHasKey('error', $data);
} }
// /**
// * Test update dengan address baru & hapus address lama
// */
public function testUpdatePatientWithAddressChange()
{
$faker = Factory::create('id_ID');
$payload = [
"InternalPID" => 1,
"PatientID" => "UPDT" . $faker->numberBetween(100, 999),
"NameFirst" => $faker->firstName,
"NameLast" => $faker->lastName,
"Gender" => (string) $faker->numberBetween(5, 6),
"Birthdate" => $faker->date('Y-m-d'),
"DeathDateTime" => null,
"EmailAddress1" => "asasa@gmail.com",
"PlaceOfBirth" => $faker->city,
"Race" => (string) $faker->numberBetween(175, 205),
"Religion" => (string) $faker->numberBetween(206, 212),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Citizenship" => "WNI",
"LinkTo" => null,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => $faker->nik(),
],
"PatCom" => $faker->sentence(5),
"PatAtt" => [
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ],
[ "Address" => "/api/upload/" . $faker->word . ".jpg" ]
]
];
$result = $this->withBodyFormat('json')->patch($this->endpoint, $payload);
$result->assertStatus(201);
$json = $result->getJSON();
$data = json_decode($json, true);
$this->assertEquals('success', $data['status']);
}
// /**
// * Test update kosong → semua pattat address dihapus (soft delete)
// */
public function testUpdatePatientEmptyAddress()
{
$faker = Factory::create('id_ID');
$payload = [
"InternalPID" => 1,
"PatientID" => "UPDT" . $faker->numberBetween(100, 999),
"NameFirst" => $faker->firstName,
"NameLast" => $faker->lastName,
"Gender" => (string) $faker->numberBetween(5, 6),
"Birthdate" => $faker->date('Y-m-d'),
"DeathDateTime" => null,
"EmailAddress1" => "asasa@gmail.com",
"PlaceOfBirth" => $faker->city,
"Race" => (string) $faker->numberBetween(175, 205),
"Religion" => (string) $faker->numberBetween(206, 212),
"Country" => (string) $faker->numberBetween(221, 469),
"MaritalStatus" => (string) $faker->numberBetween(8, 15),
"Citizenship" => "WNI",
"LinkTo" => null,
"PatIdt" => [
"IdentifierType" => "KTP",
"Identifier" => $faker->nik(),
],
"PatCom" => $faker->sentence(5),
"PatAtt" => []
];
$result = $this->withBodyFormat('json')->patch($this->endpoint, $payload);
$json = $result->getJSON();
$data = json_decode($json, true);
$result->assertStatus(201);
$this->assertEquals('success', $data['status']);
}
} }