From 229908e492a3b1b6b58824b2fbcd87a9aa535919 Mon Sep 17 00:00:00 2001 From: R Date: Thu, 16 Mar 2023 14:27:53 +0700 Subject: [PATCH] [WIP] Encounter --- .../Http/Controllers/Api/ClaimController.php | 117 ++++++++++++++++++ Modules/Client/Routes/api.php | 5 + .../Client/Transformers/ClaimShowResource.php | 41 ++++++ .../Http/Controllers/Api/ClaimController.php | 3 +- .../Http/Controllers/Api/OptionController.php | 31 +++++ app/Models/ClaimDiagnosis.php | 9 ++ app/Models/Encounter.php | 31 +++++ app/Models/EncounterDiagnosis.php | 29 +++++ app/Models/EncounterParticipant.php | 27 ++++ app/Models/Practitioner.php | 8 +- ...3_03_15_155301_create_encounters_table.php | 43 +++++++ ...38_create_encounter_participants_table.php | 39 ++++++ ...62148_create_encounter_diagnoses_table.php | 41 ++++++ .../client-portal/src/pages/Claims/List.tsx | 14 +-- frontend/client-portal/src/routes/index.tsx | 5 + 15 files changed, 433 insertions(+), 10 deletions(-) create mode 100644 Modules/Client/Http/Controllers/Api/ClaimController.php create mode 100644 Modules/Client/Transformers/ClaimShowResource.php create mode 100644 app/Models/Encounter.php create mode 100644 app/Models/EncounterDiagnosis.php create mode 100644 app/Models/EncounterParticipant.php create mode 100644 database/migrations/2023_03_15_155301_create_encounters_table.php create mode 100644 database/migrations/2023_03_15_162138_create_encounter_participants_table.php create mode 100644 database/migrations/2023_03_15_162148_create_encounter_diagnoses_table.php diff --git a/Modules/Client/Http/Controllers/Api/ClaimController.php b/Modules/Client/Http/Controllers/Api/ClaimController.php new file mode 100644 index 00000000..0e30f332 --- /dev/null +++ b/Modules/Client/Http/Controllers/Api/ClaimController.php @@ -0,0 +1,117 @@ +when($request->search ?? null, function($query, $search) { + $query->where('code', 'LIKE', '%'.$search.'%'); + }) + ->with([ + 'member', + 'diagnoses' => function ($diagnosis) { + return $diagnosis->where('type', 'primary'); + }, + 'diagnoses.icd', + 'plan', + 'benefit', + 'claimRequest', + 'claimRequest.service' + ]) + ->paginate(10); + + return Helper::responseJson($claims); + } + + /** + * Show the form for creating a new resource. + * @return Renderable + */ + public function create() + { + return view('client::create'); + } + + /** + * Store a newly created resource in storage. + * @param Request $request + * @return Renderable + */ + public function store(Request $request) + { + // + } + + /** + * Show the specified resource. + * @param int $id + * @return Renderable + */ + public function show($id) + { + $claim = Claim::query() + ->with([ + 'member', + 'member.currentPlan', + 'member.currentPlan.benefits', + 'member.currentCorporate', + 'member.currentPolicy', + 'diagnosis', + 'diagnoses', + 'benefit', + 'files', + 'claimRequest', + 'claimRequest.files', + 'items', + 'items.claim_itemable' + ]) + ->findOrFail($id); + + return Helper::responseJson(ClaimShowResource::make($claim)); + } + + /** + * Show the form for editing the specified resource. + * @param int $id + * @return Renderable + */ + public function edit($id) + { + return view('client::edit'); + } + + /** + * Update the specified resource in storage. + * @param Request $request + * @param int $id + * @return Renderable + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * @param int $id + * @return Renderable + */ + public function destroy($id) + { + // + } +} diff --git a/Modules/Client/Routes/api.php b/Modules/Client/Routes/api.php index 9b77b4e6..49b3d864 100755 --- a/Modules/Client/Routes/api.php +++ b/Modules/Client/Routes/api.php @@ -6,6 +6,7 @@ use Modules\Client\Http\Controllers\Api\CorporateManageController; use Modules\Client\Http\Controllers\Api\CorporateMemberController; use Modules\Client\Http\Controllers\Api\CorporatePolicyController; use Modules\Client\Http\Controllers\Api\UserController; +use Modules\Client\Http\Controllers\Api\ClaimController; /* |-------------------------------------------------------------------------- @@ -34,6 +35,10 @@ Route::prefix('client')->group(function () { Route::get('policy', [CorporatePolicyController::class, 'index']); Route::get('division', [CorporateDivisionController::class, 'index']); Route::get('members', [CorporateMemberController::class, 'index']); + + Route::get('claims', [ClaimController::class, 'index']); }); + + Route::get('claims/{id}', [ClaimController::class, 'show']); }); }); diff --git a/Modules/Client/Transformers/ClaimShowResource.php b/Modules/Client/Transformers/ClaimShowResource.php new file mode 100644 index 00000000..04068898 --- /dev/null +++ b/Modules/Client/Transformers/ClaimShowResource.php @@ -0,0 +1,41 @@ +citems + ->filter(function ($item) { + return $item->claim_itemable_type == Benefit::class; + }) + ->map(function ($item) { + $itemData = $item->claim_itemable->toArray(); + $itemData['nominal_dicover'] = $item['nominal_dicover'] ?? 0; + $itemData['nominal_ditagihkan'] = $item['nominal_ditagihkan'] ?? 0; + $itemData['nominal_total'] = $item['nominal_total'] ?? 0; + + // For React Frotnend + $itemData['biaya_diajukan'] = $itemData['nominal_ditagihkan']; + $itemData['biaya_disetujui'] = $itemData['nominal_dicover']; + + return $itemData; + }); + + $data['primary_diagnosis'] = $this->diagnoses->filter(function($diagnosis){ return $diagnosis->type == 'primary';})->values(); + $data['secondary_diagnosis'] = $this->diagnoses->filter(function($diagnosis){ return $diagnosis->type == 'secondary';})->values(); + + return $data; + } +} diff --git a/Modules/Internal/Http/Controllers/Api/ClaimController.php b/Modules/Internal/Http/Controllers/Api/ClaimController.php index ed16ab02..065d576a 100644 --- a/Modules/Internal/Http/Controllers/Api/ClaimController.php +++ b/Modules/Internal/Http/Controllers/Api/ClaimController.php @@ -99,8 +99,9 @@ class ClaimController extends Controller 'member.currentPlan.benefits', 'member.currentCorporate', 'member.currentPolicy', - 'diagnosis', + // 'diagnosis', 'diagnoses', + 'diagnoses.icd', 'benefit', 'files', 'claimRequest', diff --git a/Modules/Internal/Http/Controllers/Api/OptionController.php b/Modules/Internal/Http/Controllers/Api/OptionController.php index 26040625..050c9867 100644 --- a/Modules/Internal/Http/Controllers/Api/OptionController.php +++ b/Modules/Internal/Http/Controllers/Api/OptionController.php @@ -3,6 +3,8 @@ namespace Modules\Internal\Http\Controllers\Api; use App\Models\Icd; +use App\Models\Organization; +use App\Models\Practitioner; use Illuminate\Contracts\Support\Renderable; use Illuminate\Http\Request; use Illuminate\Routing\Controller; @@ -30,6 +32,35 @@ class OptionController extends Controller return $icds; break; + case 'doctors': + $doctors = Practitioner::query() + ->whereHas('person', function ($person) use ($request) { + $person->where('name', 'LIKE', '%'.$request->search.'%'); + }) + ->limit('10') + ->get(); + + $doctors = $doctors->map(function($doctor) { + $doctorDetail = $doctor->person->toArray(); + unset($doctorDetail['id']); + + return array_merge([ + 'id' => $doctor->id, + 'code' => $doctor->code + ], $doctorDetail); + }); + + return $doctors; + break; + case 'healthcares': + $healthcares = Organization::query() + ->hospital() + ->where('name', 'LIKE', '%'.$request->search.'%') + ->limit('10') + ->get(); + + return $healthcares; + break; default: # code... diff --git a/app/Models/ClaimDiagnosis.php b/app/Models/ClaimDiagnosis.php index 0e5295e1..ef3788e9 100644 --- a/app/Models/ClaimDiagnosis.php +++ b/app/Models/ClaimDiagnosis.php @@ -19,6 +19,15 @@ class ClaimDiagnosis extends Model 'description', ]; + protected $hidden = [ + 'created_at', + 'updated_at', + 'deleted_at', + 'created_by', + 'updated_by', + 'deleted_by', + ]; + public function icd() { return $this->belongsTo(Icd::class, 'diagnosis_id', 'id'); diff --git a/app/Models/Encounter.php b/app/Models/Encounter.php new file mode 100644 index 00000000..7ece9052 --- /dev/null +++ b/app/Models/Encounter.php @@ -0,0 +1,31 @@ +hasMany(EncounterParticipant::class, 'encounter_id'); + } + + public function diagnoses() + { + return $this->hasMany(EncounterDiagnosis::class, 'encounter_id'); + } +} diff --git a/app/Models/EncounterDiagnosis.php b/app/Models/EncounterDiagnosis.php new file mode 100644 index 00000000..7b3fa650 --- /dev/null +++ b/app/Models/EncounterDiagnosis.php @@ -0,0 +1,29 @@ + 'Working', + 'final' => 'Final' + ]; + + public function encounter() + { + return $this->belongsTo(Encounter::class, 'encounter_id'); + } +} diff --git a/app/Models/EncounterParticipant.php b/app/Models/EncounterParticipant.php new file mode 100644 index 00000000..08a6a0fe --- /dev/null +++ b/app/Models/EncounterParticipant.php @@ -0,0 +1,27 @@ +belongsTo(Encounter::class, 'encounter_id'); + } + + public function participantable() + { + return $this->morphTo(); + } +} diff --git a/app/Models/Practitioner.php b/app/Models/Practitioner.php index 7720ff2f..43d0fac8 100755 --- a/app/Models/Practitioner.php +++ b/app/Models/Practitioner.php @@ -14,7 +14,8 @@ class Practitioner extends Model ]; public $appends = [ - 'meta' + 'meta', + 'code' ]; public function getMetaAttribute() @@ -27,6 +28,11 @@ class Practitioner extends Model return (object) $orgMeta; } + public function getCodeAttribute() + { + return 'DOC'.str_pad($this->id, 4, '0', STR_PAD_LEFT); + } + public function person() { return $this->belongsTo(Person::class, 'person_id'); diff --git a/database/migrations/2023_03_15_155301_create_encounters_table.php b/database/migrations/2023_03_15_155301_create_encounters_table.php new file mode 100644 index 00000000..d267ca63 --- /dev/null +++ b/database/migrations/2023_03_15_155301_create_encounters_table.php @@ -0,0 +1,43 @@ +id(); + $table->foreignId('part_of')->comment('encounter_id'); + $table->string('status'); + $table->string('class')->nullable(); + $table->string('type')->nullable(); + $table->foreignId('patient_id')->nullable(); + $table->dateTime('start')->nullable(); + $table->dateTime('end')->nullable(); + + $table->timestamps(); + $table->softDeletes(); + $table->unsignedBigInteger('created_by')->nullable()->index(); + $table->unsignedBigInteger('updated_by')->nullable()->index(); + $table->unsignedBigInteger('deleted_by')->nullable()->index(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('encounters'); + } +}; diff --git a/database/migrations/2023_03_15_162138_create_encounter_participants_table.php b/database/migrations/2023_03_15_162138_create_encounter_participants_table.php new file mode 100644 index 00000000..e55aa437 --- /dev/null +++ b/database/migrations/2023_03_15_162138_create_encounter_participants_table.php @@ -0,0 +1,39 @@ +id(); + $table->foreignId('encounter_id'); + $table->string('type'); + $table->nullableMorphs('participantable', 'participantable'); + + $table->timestamps(); + $table->softDeletes(); + $table->unsignedBigInteger('created_by')->nullable()->index(); + $table->unsignedBigInteger('updated_by')->nullable()->index(); + $table->unsignedBigInteger('deleted_by')->nullable()->index(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('encounter_participants'); + } +}; diff --git a/database/migrations/2023_03_15_162148_create_encounter_diagnoses_table.php b/database/migrations/2023_03_15_162148_create_encounter_diagnoses_table.php new file mode 100644 index 00000000..2f391331 --- /dev/null +++ b/database/migrations/2023_03_15_162148_create_encounter_diagnoses_table.php @@ -0,0 +1,41 @@ +id(); + $table->foreignId('encounter_id'); + $table->foreignId('diagnosis_id'); + $table->string('use')->nullable(); + $table->text('source')->nullable(); + $table->text('description')->nullable(); + + $table->timestamps(); + $table->softDeletes(); + $table->unsignedBigInteger('created_by')->nullable()->index(); + $table->unsignedBigInteger('updated_by')->nullable()->index(); + $table->unsignedBigInteger('deleted_by')->nullable()->index(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('encounter_diagnoses'); + } +}; diff --git a/frontend/client-portal/src/pages/Claims/List.tsx b/frontend/client-portal/src/pages/Claims/List.tsx index d575fcc3..0c362c1e 100755 --- a/frontend/client-portal/src/pages/Claims/List.tsx +++ b/frontend/client-portal/src/pages/Claims/List.tsx @@ -19,23 +19,21 @@ import { } from '@mui/material'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; -import AddIcon from '@mui/icons-material/Add'; -import UploadIcon from '@mui/icons-material/Upload'; -import CancelIcon from '@mui/icons-material/Cancel'; // hooks -import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; +import React, { ChangeEvent, useContext, useEffect, useRef, useState } from 'react'; import { Navigate, useNavigate, useSearchParams } from 'react-router-dom'; // components import axios from '../../utils/axios'; import { LaravelPaginatedData, LaravelPaginatedDataDefault } from '../../@types/paginated-data'; import DataTable from '../../components/LaravelTable'; import { fCurrency } from '../../utils/formatNumber'; -import EditRoundedIcon from '@mui/icons-material/EditRounded'; import { Chip } from '@mui/material'; import Iconify from '@/components/Iconify'; import { enqueueSnackbar } from 'notistack'; +import { UserCurrentCorporateContext } from '@/contexts/UserCurrentCorporate'; export default function List() { + const { corporateValue } = useContext(UserCurrentCorporateContext); const [searchParams, setSearchParams] = useSearchParams(); const [importResult, setImportResult] = useState(null); const navigate = useNavigate(); @@ -108,11 +106,11 @@ export default function List() { const loadDataTableData = async (appliedFilter: any | null = null) => { setDataTableLoading(true); const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); - const response = await axios.get('/claims', { params: filter }); - // console.log(response.data); + const response = await axios.get(corporateValue+'/claims', { params: filter }); + // console.log(response.data.data); setDataTableLoading(false); - setDataTableData(response.data); + setDataTableData(response.data.data); }; const applyFilter = async (searchFilter: { search: string }) => { diff --git a/frontend/client-portal/src/routes/index.tsx b/frontend/client-portal/src/routes/index.tsx index 704cdf95..3a29e017 100755 --- a/frontend/client-portal/src/routes/index.tsx +++ b/frontend/client-portal/src/routes/index.tsx @@ -122,6 +122,10 @@ export default function Router() { element: , index: true, }, + { + path: ':id', + element: , + }, ], }, { @@ -153,3 +157,4 @@ const AlarmCenterUserProfile = Loadable(lazy(() => import('../pages/AlarmCenter/ // Claim Report const ClaimReport = Loadable(lazy(() => import('../pages/ClaimReport/Index'))); const Claims = Loadable(lazy(() => import('../pages/Claims/Index'))); +const ClaimShow = Loadable(lazy(() => import('../pages/Claims/Show')));