diff --git a/.gitignore b/.gitignore
index 8811b48..79e185e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ Homestead.json
/.idea
/_ide_helper.php
/storage/
+composer.phar
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 9e16811..92cdb5f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,8 @@
language: php
+services:
+ - mysql
+
php:
- 5.6
- 7.0
diff --git a/AutoStart.bat b/AutoStart.bat
new file mode 100644
index 0000000..833cfbd
--- /dev/null
+++ b/AutoStart.bat
@@ -0,0 +1,14 @@
+@echo off
+rem this is for windows users only
+rem change the drive path to what suits your server
+re
+
+
+cd C:\path to folder\
+
+start php artisan serve --host xx.xx.xx.xx --port 8000
+
+rem auto display of the web browser
+rem this will automatically open the application using your default set web browser
+
+start http://xx.xx.xx.xx:8000
diff --git a/app/Http/Controllers/APIController.php b/app/Http/Controllers/APIController.php
index 65acdb9..44c071b 100644
--- a/app/Http/Controllers/APIController.php
+++ b/app/Http/Controllers/APIController.php
@@ -155,6 +155,7 @@ public function getAllRemainingPrescriptions() {
}
$clinic = Clinic::getCurrentClinic();
+ // TODO Fix for large number of records
$prescriptions = Prescription::whereIn('patient_id', $clinic->patients()->lists('id'))
->where('issued', false)->orderBy('id')
->with('prescriptionDrugs.dosage', 'prescriptionDrugs.frequency', 'prescriptionPharmacyDrugs',
diff --git a/app/Http/Controllers/PatientController.php b/app/Http/Controllers/PatientController.php
index 6a48be1..844cd94 100644
--- a/app/Http/Controllers/PatientController.php
+++ b/app/Http/Controllers/PatientController.php
@@ -13,17 +13,97 @@
use Illuminate\Support\Facades\Validator;
class PatientController extends Controller {
+
/**
* Get the patients list
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getPatientList() {
$clinic = Clinic::getCurrentClinic();
- $patients = $clinic->patients;
- return view('patients.patients', ['patients' => $patients]);
+ return view('patients.patients', ['patients' => []]);
}
+ /**
+ * Get the patients list for data tables, server side processing
+ * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+ */
+ public function listPatients(Request $request)
+ {
+ $clinic = Clinic::getCurrentClinic();
+
+ $draw = $request->query('draw');
+ $start = $request->query('start');
+ $length = $request->query('length');
+ $search = $request->query('search');
+ $order = $request->query('order');
+ $query = $search['value'];
+ $orderByColIdx = $order[0]["column"];
+ $orderByDirection = $order[0]["dir"];
+
+ $orderByCol = 'first_name';
+ if ($orderByColIdx == 2) {
+ $orderByCol = 'phone';
+ } else if ($orderByColIdx == 3) {
+ $orderByCol = 'address';
+ } else if ($orderByColIdx == 4) {
+ $orderByCol = 'dob';
+ $orderByDirection = $orderByDirection == 'asc' ? 'desc' : 'asc';
+ }
+
+ Log::debug("Draw -> $draw, Start-> $start, Length-> $length, OrderByColumn-> $orderByColIdx, Query-> $query");
+
+ $totalRecords = $clinic->patients()->count();
+ $filteredRecords = $totalRecords;
+
+ $patients = $clinic->patients();
+
+ if (!empty($query)) {
+ $patients = $patients->where(DB::raw('concat(first_name, " ", last_name)'), 'like', "%$query%");
+ $filteredRecords = $patients->count();
+ }
+
+ $patients = $patients->orderBy($orderByCol, $orderByDirection)
+ ->skip($start)->take($length)->get();
+
+ $data = [];
+ foreach ($patients as $patient) {
+ $buttons = '';
+ if (\Gate::allows('delete', $patient)) {
+ $buttons = "
+ ";
+ }
+
+ $row = [
+ $patient->id,
+ $patient->first_name . ' ' . $patient->last_name,
+ $patient->phone,
+ $patient->address,
+ \Utils::getAge($patient->dob),
+ $buttons
+ ];
+
+ $data[] = $row;
+ }
+
+ $result = [
+ 'draw' => $draw,
+ 'recordsTotal' => $totalRecords,
+ 'recordsFiltered' => $filteredRecords,
+ 'data' => $data
+ ];
+
+ return response()->json($result);
+ }
+
/**
* Adds a patient to the system
*
diff --git a/app/Http/Controllers/UtilityController.php b/app/Http/Controllers/UtilityController.php
index 1ad03c7..837cc34 100644
--- a/app/Http/Controllers/UtilityController.php
+++ b/app/Http/Controllers/UtilityController.php
@@ -49,17 +49,24 @@ public function getDashboard() {
}
$clinic = Clinic::getCurrentClinic();
- $prescriptions = Prescription::whereIn('patient_id', $clinic->patients()->lists('id'));
+ $idList = $clinic->patients()->pluck('id')->toArray();
+
+ $prescriptions = collect();
+ $batch_size = 10000;
+ foreach (array_chunk($idList, $batch_size) as $idListBatch) {
+ $prescriptions = Prescription::whereIn('patient_id', $idListBatch)->get()->toBase()->merge($prescriptions);
+ }
$prescriptionCount = $prescriptions->where('issued', 1)->count();
$payments = Payment::whereIn('prescription_id',
- $prescriptions->where('issued', 1)->lists('id'))->sum('amount');
-
+ $prescriptions->where('issued', 1)->pluck('id'))->sum('amount');
$stats = $this->calcClinicStats($clinic);
return view('dashboard', [
- 'clinic' => $clinic, 'prescriptionCount' => $prescriptionCount,
- 'payments' => $payments, 'stats' => $stats
+ 'clinic' => $clinic,
+ 'prescriptionCount' => $prescriptionCount,
+ 'payments' => $payments,
+ 'stats' => $stats
]);
}
@@ -79,7 +86,8 @@ private function calcClinicStats($clinic) {
];
$date = date('Y-m-d H:i:s', strtotime("-6 months"));
- $patientIds = $clinic->patients()->lists('id')->toArray();
+// $patientIds = $clinic->patients()->lists('id')->toArray();
+ $patientIds = [];
if (count($patientIds) > 0) {
$patientIds = implode(",", $patientIds);
$query = "SELECT MONTH(created_at) AS m,COUNT(*) AS c FROM `prescriptions` WHERE `patient_id`
diff --git a/app/Http/routes.php b/app/Http/routes.php
index ed38c95..49e8b87 100644
--- a/app/Http/routes.php
+++ b/app/Http/routes.php
@@ -101,10 +101,10 @@
*/
Route::group(['prefix' => 'patients'], function () {
Route::get('/', ['as' => 'patients', 'uses' => 'PatientController@getPatientList']);
-
/*
* PATIENTS
*/
+ Route::get('/list', ['as' => 'listPatients', 'uses' => 'PatientController@listPatients']);
Route::post('addPatient', ['as' => 'addPatient', 'uses' => 'PatientController@addPatient']);
Route::get('patient/{id}', ['as' => 'patient', 'uses' => 'PatientController@getPatient']);
Route::any('deletePatient/{id}', ['as' => 'deletePatient', 'uses' => 'PatientController@deletePatient']);
diff --git a/database/seeds/PatientTableSeeder.php b/database/seeds/PatientTableSeeder.php
index 5ae40eb..b50d671 100644
--- a/database/seeds/PatientTableSeeder.php
+++ b/database/seeds/PatientTableSeeder.php
@@ -21,5 +21,17 @@ public function run()
});
}
}
+
+ // Uncomment for large number of patient records.
+// $clinic = \App\Clinic::find(1);
+//
+// foreach ($clinic->users as $user) {
+// //add patients to the clinic
+// factory(App\Patient::class, 100000)->make()->each(function (\App\Patient $patient) use ($clinic, $user) {
+// $patient->creator()->associate($user);
+// $patient->clinic()->associate($clinic);
+// $patient->save();
+// });
+// }
}
}
diff --git a/docs/chr247.postman_collection.json b/docs/chr247.postman_collection.json
new file mode 100644
index 0000000..3bce093
--- /dev/null
+++ b/docs/chr247.postman_collection.json
@@ -0,0 +1,177 @@
+{
+ "info": {
+ "_postman_id": "183abd2f-a810-4516-8714-9dc61610368e",
+ "name": "chr247",
+ "description": "chr247 APIs and pages",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "Login",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "7c782fb2-28cd-430d-85f6-080c38d79121",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ " pm.response.to.be.withBody;",
+ "});",
+ "",
+ "pm.test(\"Check cookies\", function() {",
+ " pm.expect(pm.cookies.has(\"XSRF-TOKEN\")).to.be.true;",
+ " pm.expect(pm.cookies.has(\"chr247_session\")).to.be.true;",
+ "});",
+ "",
+ "pm.environment.set(\"xsrf_token\", pm.cookies.get(\"XSRF-TOKEN\"));",
+ "pm.environment.set(\"session\", pm.cookies.get(\"chr247_session\"));",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{chr247_url}}/login",
+ "host": [
+ "{{chr247_url}}"
+ ],
+ "path": [
+ "login"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Login",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "fee7c243-2c36-4ea3-adba-b832fd446f70",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ " pm.response.to.be.withBody;",
+ "});",
+ "",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "formdata",
+ "formdata": [
+ {
+ "key": "password",
+ "value": "{{password}}",
+ "type": "text"
+ },
+ {
+ "key": "username",
+ "value": "{{username}}",
+ "type": "text"
+ }
+ ]
+ },
+ "url": {
+ "raw": "{{chr247_url}}/login",
+ "host": [
+ "{{chr247_url}}"
+ ],
+ "path": [
+ "login"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "List Patients",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{chr247_url}}/patients/list?order[0][column]=1&order[0][dir]=asc&start=0&length=10&search[value]=a&search[regex]=false&draw=1",
+ "host": [
+ "{{chr247_url}}"
+ ],
+ "path": [
+ "patients",
+ "list"
+ ],
+ "query": [
+ {
+ "key": "order[0][column]",
+ "value": "1"
+ },
+ {
+ "key": "order[0][dir]",
+ "value": "asc"
+ },
+ {
+ "key": "start",
+ "value": "0"
+ },
+ {
+ "key": "length",
+ "value": "10"
+ },
+ {
+ "key": "search[value]",
+ "value": "a"
+ },
+ {
+ "key": "search[regex]",
+ "value": "false"
+ },
+ {
+ "key": "draw",
+ "value": "1"
+ }
+ ]
+ },
+ "description": "API used by data tables to paginate and load patients"
+ },
+ "response": []
+ }
+ ],
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "id": "96ee9cc0-96a5-4fcd-b677-b47f58005cf0",
+ "type": "text/javascript",
+ "exec": [
+ "if(pm.environment.has(\"xsrf_token\")) {",
+ " pm.request.headers.add({",
+ " key: \"X-XSRF-TOKEN\",",
+ " value: \"{{xsrf_token}}\"",
+ " });",
+ "}"
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "id": "3a1eba76-6c9a-4497-8931-ab05d5115ff3",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ],
+ "protocolProfileBehavior": {}
+}
\ No newline at end of file
diff --git a/docs/chr247_jmeter_test.jmx b/docs/chr247_jmeter_test.jmx
new file mode 100644
index 0000000..d4e9471
--- /dev/null
+++ b/docs/chr247_jmeter_test.jmx
@@ -0,0 +1,415 @@
+
+
+
+
+ Load test to benchmard chr247 performance
+ false
+ true
+ false
+
+
+
+ protocol
+ http
+ =
+
+
+ host
+ imesha-playground.southeastasia.cloudapp.azure.com
+ =
+
+
+ port
+ 80
+ =
+
+
+ threads
+ 100
+ =
+
+
+ loops
+ 10
+ =
+
+
+ username
+ imesha
+ =
+
+
+ password
+ 1234
+ =
+
+
+
+
+
+
+
+ startnextloop
+
+ false
+ ${loops}
+
+ ${threads}
+ 30
+ false
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ ${host}
+ ${port}
+ ${protocol}
+
+ login
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+ false
+ ${username}
+ =
+ true
+ username
+
+
+ false
+ ${password}
+ =
+ true
+ password
+
+
+
+ ${host}
+ ${port}
+ ${protocol}
+
+ login
+ POST
+ false
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+ X-XSRF-TOKEN
+ ${__urldecode(${COOKIE_XSRF-TOKEN})}
+
+
+
+
+
+
+
+
+
+ false
+ 1
+ =
+ true
+ order[0][column]
+
+
+ false
+ asc
+ =
+ true
+ order[0][dir]
+
+
+ false
+ 0
+ =
+ true
+ start
+
+
+ false
+ 10
+ =
+ true
+ length
+
+
+ false
+ a
+ =
+ true
+ search[value]
+
+
+ false
+ false
+ =
+ true
+ search[regex]
+
+
+ false
+ 1
+ =
+ true
+ draw
+
+
+
+ ${host}
+ ${port}
+ ${protocol}
+
+ patients/list
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 200
+
+
+ Assertion.response_code
+ false
+ 8
+
+
+
+ $.recordsTotal
+
+ false
+ false
+ false
+ true
+
+
+
+
+
+
+
+ false
+ 1
+ =
+ true
+ order[0][column]
+
+
+ false
+ asc
+ =
+ true
+ order[0][dir]
+
+
+ false
+ 0
+ =
+ true
+ start
+
+
+ false
+ 10
+ =
+ true
+ length
+
+
+ false
+ a
+ =
+ true
+ search[value]
+
+
+ false
+ false
+ =
+ true
+ search[regex]
+
+
+ false
+ 1
+ =
+ true
+ draw
+
+
+
+ ${host}
+ ${port}
+ ${protocol}
+
+ drugs
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+ 200
+
+
+ Assertion.response_code
+ false
+ 8
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ false
+
+ saveConfig
+
+
+ true
+ true
+ true
+
+ true
+ true
+ true
+ true
+ false
+ true
+ true
+ false
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+
+
diff --git a/docs/chr247_local.postman_environment.json b/docs/chr247_local.postman_environment.json
new file mode 100644
index 0000000..135f384
--- /dev/null
+++ b/docs/chr247_local.postman_environment.json
@@ -0,0 +1,34 @@
+{
+ "id": "dbb2b788-d4f3-4ee7-bcee-53f43cdd5740",
+ "name": "chr247_local",
+ "values": [
+ {
+ "key": "session",
+ "value": "",
+ "enabled": true
+ },
+ {
+ "key": "chr247_url",
+ "value": "http://localhost:8000",
+ "enabled": true
+ },
+ {
+ "key": "xsrf_token",
+ "value": "",
+ "enabled": true
+ },
+ {
+ "key": "username",
+ "value": "imesha",
+ "enabled": true
+ },
+ {
+ "key": "password",
+ "value": "1234",
+ "enabled": true
+ }
+ ],
+ "_postman_variable_scope": "environment",
+ "_postman_exported_at": "2019-11-30T16:36:50.427Z",
+ "_postman_exported_using": "Postman/7.10.0"
+}
\ No newline at end of file
diff --git a/readme.md b/readme.md
index 8aad06c..4688075 100644
--- a/readme.md
+++ b/readme.md
@@ -72,22 +72,27 @@ manager used internally.
- Within the project root directory,
- Make sure the permissions for `storage` and `bootstrap/cache`
are set to `776` (i.e writable by the web server) - (Windows users make sure the current user has full permissions to read and write on the folders `storage` and `bootstrap/cache`)
- - Copy the `.env.example` file as `.env` (windows Users- do this using the command prompt). Its advisable to have a copy of this file before you do this.
- - Run `composer install` within the project root.
+ - Copy the `.env.example` file as `.env` (windows Users- do this using the command prompt **`copy .env.example .env`** ). Its advisable to have a copy of this file before you do this.
+ - Run `composer install` within the project root.`
- Run `php artisan key:generate` to generate application key.
- This command will set a newly generated application key to `.env` file.
- Set the database related information within `.env` file. If you are using a DB otherthan
MySQL, you may have to add `DB_CONNECTION=` to `.env` file as well.
- ```
- DB_HOST=
+ DB_HOST= or DB_HOST=: if using non default settings for mysql
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
```
- Run database migrations and seeds with `php artisan migrate:refresh --seed`
- - Run `php artisan serve`
-- Visit [http://localhost:8000] to view the webapp. You can use the login
+ - Run `php artisan serve` this will only provide the page for the development computer
+ - Visit [http://localhost:8000] to view the webapp.
+ or
+ - Run `php artisan serve --host xxx.xxx.xxx.xxx --port 8000` this will provide page for all computers on the same network
+ - Visit [http://xxx.xxx.xxx.xxx:8000] to view the webapp.
+
+You can use the login
- username: `imesha`, password: `1234` to login.
## Contributions
diff --git a/resources/views/patients/patients.blade.php b/resources/views/patients/patients.blade.php
index 12da2cd..603671b 100644
--- a/resources/views/patients/patients.blade.php
+++ b/resources/views/patients/patients.blade.php
@@ -42,6 +42,14 @@
@endif