From fb5a65103a7741d56f7193d7b2f28722b7d718d2 Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Mon, 13 Oct 2025 11:08:26 +0700 Subject: [PATCH] utc helper --- app/Controllers/Patient.php | 21 ++++---- .../2025-09-09-155526_Pat_Visit.php | 12 ++--- app/Helpers/utc_helper.php | 52 +++++++++++++++++++ app/Models/ContactDetailModel.php | 9 ++++ app/Models/ContactModel.php | 11 +++- app/Models/PatVisitModel.php | 11 +++- app/Models/PatientModel.php | 13 +++-- 7 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 app/Helpers/utc_helper.php diff --git a/app/Controllers/Patient.php b/app/Controllers/Patient.php index cbcbcb3..0b20c4b 100644 --- a/app/Controllers/Patient.php +++ b/app/Controllers/Patient.php @@ -9,14 +9,13 @@ class Patient extends Controller { use ResponseTrait; protected $db; - protected $modelPatient; - protected $rulesPatient; - protected $rulesPatIdt; + protected $model; + protected $rules; public function __construct() { $this->db = \Config\Database::connect(); - $this->modelPatient = new PatientModel(); - $this->rulesPatient = [ + $this->model = new PatientModel(); + $this->rules = [ 'PatientID' => 'required|max_length[50]', 'AlternatePID' => 'permit_empty|max_length[50]', 'NameFirst' => 'required|min_length[1]|max_length[255]', @@ -34,7 +33,7 @@ class Patient extends Controller { ]; try { - $rows = $this->modelPatient->getPatients($filters); + $rows = $this->model->getPatients($filters); return $this->respond([ 'status' => 'success', 'message'=> "data fetched successfully", 'data' => $rows ], 200); } catch (\Exception $e) { return $this->failServerError('Exception : '.$e->getMessage()); @@ -43,7 +42,7 @@ class Patient extends Controller { public function show($InternalPID = null) { try { - $rows = $this->modelPatient->getPatient($InternalPID); + $rows = $this->model->getPatient($InternalPID); if (empty($rows)) { return $this->respond([ 'status' => 'success', 'message' => "data not found." ], 200); } return $this->respond([ 'status' => 'success', 'message' => "data fetched successfully", 'data' => $rows ], 200); } catch (\Exception $e) { @@ -53,9 +52,9 @@ class Patient extends Controller { public function create() { $input = $this->request->getJSON(true); - if (!$this->validateData($input, $this->rulesPatient)) { return $this->validationError('patient', $this->validator->getErrors()); } + if (!$this->validateData($input, $this->rules)) { return $this->validationError('patient', $this->validator->getErrors()); } try { - $InternalPID = $this->modelPatient->createPatient($input); + $InternalPID = $this->model->createPatient($input); return $this->respondCreated([ 'status' => 'success', 'message' => "data $InternalPID created successfully" ]); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); @@ -72,9 +71,9 @@ class Patient extends Controller { public function update() { $input = $this->request->getJSON(true); - if (!$this->validateData($input, $this->rulesPatient)) { return $this->validationError('patient', $this->validator->getErrors()); } + if (!$this->validateData($input, $this->rules)) { return $this->validationError('patient', $this->validator->getErrors()); } try { - $InternalPID = $this->modelPatient->updatePatient($input); + $InternalPID = $this->model->updatePatient($input); return $this->respondCreated([ 'status' => 'success', 'message' => "data $InternalPID update successfully" ]); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); diff --git a/app/Database/Migrations/2025-09-09-155526_Pat_Visit.php b/app/Database/Migrations/2025-09-09-155526_Pat_Visit.php index 9602818..167d550 100644 --- a/app/Database/Migrations/2025-09-09-155526_Pat_Visit.php +++ b/app/Database/Migrations/2025-09-09-155526_Pat_Visit.php @@ -8,15 +8,15 @@ class CreatePVTables extends Migration { public function up() { // patvisit $this->forge->addField([ - 'SiteID' => ['type' => 'INT', 'constraint' => 11, 'null' => true], + 'SiteID' => ['type' => 'INT', 'constraint' => 11, 'null' => true], 'InternalPVID'=> ['type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true], - 'PVID' => ['type' => 'VARCHAR', 'constraint' => 20, 'null' => true], + 'PVID' => ['type' => 'VARCHAR', 'constraint' => 20, 'null' => true], 'InternalPID' => ['type' => 'INT', 'constraint' => 11, 'null' => true], - 'EpisodeID' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true], - 'CreateDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP', - 'EndDate' => ['type' => 'DATETIME', 'null' => true], + 'EpisodeID' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true], + 'CreateDate' => ['type' => 'DATETIME', 'null' => true], + 'EndDate' => ['type' => 'DATETIME', 'null' => true], 'ArchivedDate'=> ['type' => 'DATETIME', 'null' => true], - 'DelDate' => ['type' => 'DATETIME', 'null' => true], + 'DelDate' => ['type' => 'DATETIME', 'null' => true], ]); $this->forge->addKey('InternalPVID', true); diff --git a/app/Helpers/utc_helper.php b/app/Helpers/utc_helper.php new file mode 100644 index 0000000..a05c64e --- /dev/null +++ b/app/Helpers/utc_helper.php @@ -0,0 +1,52 @@ + $value) { + if (is_array($value)) { + $data[$key] = convert_array_to_utc($value); + } elseif (is_string($value) && is_datetime_string($value)) { + try { + $data[$key] = Time::parse($value)->setTimezone('UTC')->toDateTimeString(); + } catch (\Exception $e) { + // skip if not valid + } + } + } + return $data; + } +} + +if (!function_exists('is_datetime_string')) { + function is_datetime_string(string $value): bool { + return preg_match( + '/^\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}:\d{2}(?:[\+\-]\d{2}:?\d{2}|Z)?)?$/', + $value + ) === 1; + } +} + +if (!function_exists('convert_array_to_utc_iso')) { + function convert_array_to_utc_iso($data) { + if (is_array($data)) { + foreach ($data as $key => $value) { + if (is_array($value)) { + $data[$key] = convert_array_to_utc_iso($value); + } elseif (is_string($value) && is_datetime_string($value)) { + try { + $data[$key] = Time::parse($value, 'UTC')->toISOString(); + } catch (\Exception $e) { + // skip + } + } + } + } elseif (is_object($data)) { + foreach ($data as $key => $value) { + $data->$key = convert_array_to_utc_iso($value); + } + } + return $data; + } +} diff --git a/app/Models/ContactDetailModel.php b/app/Models/ContactDetailModel.php index e5e2488..3f6aeb8 100644 --- a/app/Models/ContactDetailModel.php +++ b/app/Models/ContactDetailModel.php @@ -8,6 +8,15 @@ class ContactDetailModel extends Model { protected $table = 'contactdetail'; protected $primaryKey = 'ContactDetID'; protected $allowedFields = ['ContactID', 'SiteID', 'ContactCode', 'ContactEmail', 'OccupationID', 'JobTitle', 'Department', 'ContactStartDate', 'ContactEndDate']; + + protected $useTimestamps = true; + protected $createdField = 'ContactStartDate'; + + protected $beforeInsert = ['normalizeDatesToUTC']; + protected $beforeUpdate = ['normalizeDatesToUTC']; + protected $afterFind = ['convertDatesToUTCISO']; + protected $afterInsert = ['convertDatesToUTCISO']; + protected $afterUpdate = ['convertDatesToUTCISO']; public function syncDetails(int $ContactID, array $contactDetails) { try { diff --git a/app/Models/ContactModel.php b/app/Models/ContactModel.php index e8740d3..06a65d9 100644 --- a/app/Models/ContactModel.php +++ b/app/Models/ContactModel.php @@ -7,7 +7,16 @@ use CodeIgniter\Model; class ContactModel extends Model { protected $table = 'contact'; protected $primaryKey = 'ContactID'; - protected $allowedFields = ['NameFirst', 'NameLast', 'Title', 'Initial', 'Birthdate', 'EmailAddress1', 'EmailAddress2', 'Phone', 'MobilePhone1', 'MobilePhone2', 'Specialty', 'SubSpecialty']; + protected $allowedFields = ['NameFirst', 'NameLast', 'Title', 'Initial', 'Birthdate', 'EmailAddress1', 'EmailAddress2', 'Phone', 'MobilePhone1', 'MobilePhone2', 'Specialty', 'SubSpecialty', 'CreateDate', 'EndDate']; + + protected $useTimestamps = true; + protected $createdField = 'CreateDate'; + + protected $beforeInsert = ['normalizeDatesToUTC']; + protected $beforeUpdate = ['normalizeDatesToUTC']; + protected $afterFind = ['convertDatesToUTCISO']; + protected $afterInsert = ['convertDatesToUTCISO']; + protected $afterUpdate = ['convertDatesToUTCISO']; public function getContactsWithDetail() { $rows = $this->select("contact.ContactID, cd.SiteID, cd.ContactCode, NameFirst, NameLast, Specialty") diff --git a/app/Models/PatVisitModel.php b/app/Models/PatVisitModel.php index 51d41bb..befa875 100644 --- a/app/Models/PatVisitModel.php +++ b/app/Models/PatVisitModel.php @@ -8,9 +8,18 @@ use App\Models\CounterModel; class PatVisitModel extends Model { protected $table = 'patvisit'; protected $primaryKey = 'InternalPVID'; - protected $allowedFields = ['PVID', 'InternalPID', 'EpisodeID', 'EndDate']; + protected $allowedFields = ['PVID', 'InternalPID', 'EpisodeID', 'CreateDate', 'EndDate']; protected $db; protected $visnum_prefix; + + protected $useTimestamps = true; + protected $createdField = 'CreateDate'; + + protected $beforeInsert = ['normalizeDatesToUTC']; + protected $beforeUpdate = ['normalizeDatesToUTC']; + protected $afterFind = ['convertDatesToUTCISO']; + protected $afterInsert = ['convertDatesToUTCISO']; + protected $afterUpdate = ['convertDatesToUTCISO']; public function __construct() { $this->db = \Config\Database::connect(); diff --git a/app/Models/PatientModel.php b/app/Models/PatientModel.php index f68b793..4b70c56 100644 --- a/app/Models/PatientModel.php +++ b/app/Models/PatientModel.php @@ -10,10 +10,15 @@ class PatientModel extends Model { protected $primaryKey = 'InternalPID'; protected $allowedFields = ['PatientID', 'AlternatePID', 'Prefix', 'NameFirst', 'NameMiddle', 'NameMaiden', 'NameLast', 'Suffix', 'NameAlias', 'Gender', 'Birthdate', 'PlaceOfBirth', 'Street_1', 'Street_2', 'Street_3', 'City', 'Province', 'ZIP', 'EmailAddress1', 'EmailAddress2', 'Phone', 'MobilePhone', 'Custodian', 'AccountNumber', 'Country', 'Race', 'MaritalStatus', 'Religion', 'Ethnic', 'Citizenship', - 'DeathIndicator', 'DeathDateTime', 'LinkTo' ]; - protected $useTimestamps = true; // Enable automatic timestamps - protected $createdField = 'CreateDate'; // Specify the 'created_at' field name - protected $dateFormat = 'datetime'; + 'DeathIndicator', 'DeathDateTime', 'LinkTo', 'CreateDate', 'DelDate' ]; + protected $useTimestamps = true; + protected $createdField = 'CreateDate'; + + protected $beforeInsert = ['normalizeDatesToUTC']; + protected $beforeUpdate = ['normalizeDatesToUTC']; + protected $afterFind = ['convertDatesToUTCISO']; + protected $afterInsert = ['convertDatesToUTCISO']; + protected $afterUpdate = ['convertDatesToUTCISO']; public function getPatients($filters = []) { $qname = "LOWER(CONCAT_WS(' ', IFNULL(Prefix,''), IFNULL(NameFirst,''), IFNULL(NameMiddle,''), IFNULL(NameLast,''), IFNULL(NameMaiden,''), IFNULL(Suffix,'')))";