From 0f60176c35d2bcf499a9c525279d3882f3e2362a Mon Sep 17 00:00:00 2001 From: Tb Fajri Date: Thu, 21 Sep 2023 10:55:57 +0700 Subject: [PATCH] update master icd --- .../Controllers/Api/DiagnosisController.php | 50 ++- .../Api/DiagnosisTemplateController.php | 314 ++++++++++++++++++ Modules/Internal/Routes/api.php | 21 +- Modules/Internal/Services/IcdService.php | 36 +- app/Models/Icd.php | 3 +- app/Models/IcdTemplate.php | 32 ++ app/Providers/AppServiceProvider.php | 10 + .../2023_09_19_164907_create_icd_template.php | 34 ++ ...9_20_090317_add_active_to_icd_template.php | 32 ++ ...9_20_152738_add_icd_template_id_to_icd.php | 32 ++ frontend/dashboard/src/@types/corporates.ts | 7 + .../layouts/dashboard/navbar/NavConfig.tsx | 2 +- .../src/pages/Master/Diagnosis/History.tsx | 24 +- .../src/pages/Master/Diagnosis/Index.tsx | 8 +- .../src/pages/Master/Diagnosis/List.tsx | 67 +--- .../Master/Diagnosis/Master/CreateUpdate.tsx | 18 +- .../pages/Master/Diagnosis/Master/Form.tsx | 19 +- .../pages/Master/Diagnosis/Master/History.tsx | 218 ++++++++++++ .../pages/Master/Diagnosis/Master/Index.tsx | 8 +- .../pages/Master/Diagnosis/Master/List.tsx | 119 ++----- frontend/dashboard/src/routes/index.tsx | 21 +- public/files/CorporateMembershipList.xlsx | Bin 4647 -> 3293 bytes .../CorporatePlan&BenefitImportData.xlsx | Bin 3623 -> 6831 bytes public/files/Template - ICD.xlsx | Bin 9981 -> 9972 bytes public/files/TemplateICDList.xlsx | Bin 0 -> 3293 bytes 25 files changed, 827 insertions(+), 248 deletions(-) create mode 100644 Modules/Internal/Http/Controllers/Api/DiagnosisTemplateController.php create mode 100644 app/Models/IcdTemplate.php create mode 100644 database/migrations/2023_09_19_164907_create_icd_template.php create mode 100644 database/migrations/2023_09_20_090317_add_active_to_icd_template.php create mode 100644 database/migrations/2023_09_20_152738_add_icd_template_id_to_icd.php create mode 100644 frontend/dashboard/src/pages/Master/Diagnosis/Master/History.tsx create mode 100644 public/files/TemplateICDList.xlsx diff --git a/Modules/Internal/Http/Controllers/Api/DiagnosisController.php b/Modules/Internal/Http/Controllers/Api/DiagnosisController.php index bea90e0f..db329ea4 100644 --- a/Modules/Internal/Http/Controllers/Api/DiagnosisController.php +++ b/Modules/Internal/Http/Controllers/Api/DiagnosisController.php @@ -29,12 +29,12 @@ class DiagnosisController extends Controller * Display a listing of the resource. * @return Renderable */ - public function index(Request $request) + public function index(Request $request, $diagnosis_template_id) { $diagnosis = Icd::query() ->filter($request->toArray()) - // ->where('deleted_at', '=', NULL) + ->where('icd_template_id', '=', $diagnosis_template_id) ->orderBy('code', 'ASC') ->paginate(15); return $diagnosis; @@ -108,7 +108,7 @@ class DiagnosisController extends Controller })->limit(10)->get(); } - public function import(Request $request) + public function import(Request $request, $id) { $request->validate([ 'file' => 'required|file|mimes:xls,xlsx,csv,txt', @@ -143,14 +143,8 @@ class DiagnosisController extends Controller } else { // Next Row Should be Data $row_data = []; $row_map = [ - 0 => 'code', - 1 => 'parent_code', - 2 => 'reff_exc', - 3 => 'description_en', - 4 => 'description_id', - 5 => 'keywords', - 6 => 'version', - 7 => 'active', + 0 => 'ICD_Code', + 1 => 'Description', ]; foreach ($row->getCells() as $header_index => $cell) { @@ -166,21 +160,15 @@ class DiagnosisController extends Controller try { // Process the Row Data if ( - empty($row_data['code']) && - empty($row_data['parent_code']) && - empty($row_data['reff_exc']) && - empty($row_data['description_en']) && - empty($row_data['description_id']) && - empty($row_data['keywords']) && - empty($row_data['version']) && - empty($row_data['active']) + empty($row_data['ICD_Code']) && + empty($row_data['Description']) ) { continue; } // Save the Row $icdService = new IcdService(); - $icdService->handleIcdRow($row_data); + $icdService->handleIcdRow($row_data, $id); // Write Success Result to File $import->addArrayToRow(array_merge($row_data, [ @@ -242,15 +230,15 @@ class DiagnosisController extends Controller } } - public function generateIcdList(Request $request){ + public function generateIcdList(Request $request, $diagnosis_id){ // Mendapatkan data yang akan diekspor (misalnya, dari database) - $data = Icd::get()->toArray(); + $data = Icd::where('icd_template_id', $diagnosis_id)->get()->toArray(); // Membuat penulis entitas Spout $writer = WriterEntityFactory::createXLSXWriter(); // Membuka penulis untuk menulis ke file - $writer->openToFile(public_path('files/CorporateMembershipList.xlsx')); + $writer->openToFile(public_path('files/TemplateICDList.xlsx')); /** Create a style with the StyleBuilder */ $style = (new StyleBuilder()) ->setFontBold() @@ -266,14 +254,14 @@ class DiagnosisController extends Controller if (!empty($data)) { foreach ($data as $item) { $rowData = [ - $item['rev'], // Rev - $item['version'], // Version + // $item['rev'], // Rev + // $item['version'], // Version $item['code'], // Code - $item['parent_code'], // Parent Code + // $item['parent_code'], // Parent Code $item['name'], // Name - $item['description'], // Description - $item['active'] == 1 ? 'Active' : 'Inactive', // Status - $item['type'], // Type + // $item['description'], // Description + // $item['active'] == 1 ? 'Active' : 'Inactive', // Status + // $item['type'], // Type ]; $row = WriterEntityFactory::createRowFromArray($rowData); @@ -285,11 +273,11 @@ class DiagnosisController extends Controller $writer->close(); // Mengembalikan response untuk mengunduh file - $filePath = public_path('files/CorporateMembershipList.xlsx'); + $filePath = public_path('files/TemplateICDList.xlsx'); return Helper::responseJson([ 'file_name' => "Diagnosis ICD List " . date('Y-m-d h:i:s'), - "file_url" => url('files/CorporateMembershipList.xlsx') + "file_url" => url('files/TemplateICDList.xlsx') ]); } diff --git a/Modules/Internal/Http/Controllers/Api/DiagnosisTemplateController.php b/Modules/Internal/Http/Controllers/Api/DiagnosisTemplateController.php new file mode 100644 index 00000000..01bb72a9 --- /dev/null +++ b/Modules/Internal/Http/Controllers/Api/DiagnosisTemplateController.php @@ -0,0 +1,314 @@ +search){ + return IcdTemplate::when($request->search ?? null, function($icd, $search) { + $icd->where('name', 'LIKE', '%'.$search.'%') + ->orWhere('code', 'LIKE', '%'.$search.'%'); + })->paginate(15); + } else { + $diagnosisTemplate = IcdTemplate::query() + // ->filter($request->toArray()) + ->orderBy('code', 'ASC') + ->paginate(15); + return $diagnosisTemplate; + } + + } + + /** + * Show the form for creating a new resource. + * @return Renderable + */ + public function create() + { + return view('internal::create'); + } + + /** + * Store a newly created resource in storage. + * @param Request $request + * @return Renderable + */ + public function store(Request $request) + { + $request->validate([ + 'name' => 'required' + ]); + + $newDiagnosisTemplate = IcdTemplate::create($request->all()); + + return $newDiagnosisTemplate; + } + + /** + * Show the specified resource. + * @param int $id + * @return Renderable + */ + public function show($id) + { + return view('internal::show'); + } + + /** + * Show the form for editing the specified resource. + * @param int $id + * @return Renderable + */ + public function edit($id) + { + $IcdTemplate = IcdTemplate::findOrFail($id); + + return $IcdTemplate; + } + + /** + * Update the specified resource in storage. + * @param Request $request + * @param int $id + * @return Renderable + */ + public function update(Request $request, $id) + { + $IcdTemplate = IcdTemplate::findOrFail($id); + $request->validate([ + 'name' => 'required' + ]); + $IcdTemplate->fill([ + // 'code' => $request->code, + 'name' => $request->name, + 'description' => $request->description, + 'active' => $request->active, + ])->save(); + + return $IcdTemplate; + } + + /** + * Remove the specified resource from storage. + * @param int $id + * @return Renderable + */ + public function destroy($id) + { + // + } + + public function search(Request $request) + { + return IcdTemplate::when($request->search ?? null, function($icd, $search) { + $icd->where('name', 'LIKE', '%'.$search.'%') + ->orWhere('code', 'LIKE', '%'.$search.'%'); + })->limit(10)->get(); + } + + public function import(Request $request) + { + $request->validate([ + 'file' => 'required|file|mimes:xls,xlsx,csv,txt', + ]); + $file_name = now()->getPreciseTimestamp(3).'-'.$request->file('file')->getClientOriginalName(); + $file = $request->file('file')->storeAs('temp', $file_name); + + $import = new ImportService(); + $import->read(Storage::path('temp/'.$file_name)); + $import->write(Storage::disk('public')->path('temp/result-'.$file_name), 'xsls'); + + $imported_icd_data = 0; + $failed_icd_data = []; + foreach ($import->sheetsIterator() as $sheetIndex => $sheet) { + $doc_headers_indexes = []; + foreach ($sheet->getRowIterator() as $index => $row) { + if ($index == 1) { // First Row Must be Header + foreach ($row->getCells() as $index => $cell) { + $title = $cell->getValue(); + $title = preg_replace( "/\r|\n/", " ", $title ); + $title = preg_replace('/\xc2\xa0/', " ", $title ); + $title = rtrim($title); + $title = ltrim($title); + $doc_headers_indexes[$index] = $title; + } + + // Write Header to File + $result_headers = array_merge($doc_headers_indexes, ['Ingest Code', 'Ingest Note']); + $import->addArrayToRow($result_headers); + + // TODO Validate if First Row not Header + } else { // Next Row Should be Data + $row_data = []; + $row_map = [ + 0 => 'code', + 1 => 'parent_code', + 2 => 'reff_exc', + 3 => 'description_en', + 4 => 'description_id', + 5 => 'keywords', + 6 => 'version', + 7 => 'active', + ]; + + foreach ($row->getCells() as $header_index => $cell) { + if (isset($row_map[$header_index])) { + $value = $cell->getValue(); + $value = preg_replace( "/\r|\n/", " ", $value ); + $value = preg_replace('/\xc2\xa0/', " ", $value ); + $value = rtrim($value); + $value = ltrim($value); + $row_data[$row_map[$header_index]] = $cell->getValue(); + } + } + + try { // Process the Row Data + if ( + empty($row_data['code']) && + empty($row_data['parent_code']) && + empty($row_data['reff_exc']) && + empty($row_data['description_en']) && + empty($row_data['description_id']) && + empty($row_data['keywords']) && + empty($row_data['version']) && + empty($row_data['active']) + ) { + continue; + } + + // Save the Row + $icdService = new IcdService(); + $icdService->handleIcdRow($row_data); + + // Write Success Result to File + $import->addArrayToRow(array_merge($row_data, [ + 'Ingest Code' => 200, + 'Ingest Note' => 'Success', + ]), $sheet->getName()); + $imported_icd_data++; + + } catch (ImportRowException $e) { + // Write Data Validation Error to File + $import->addArrayToRow(array_merge($row_data, [ + 'Ingest Code' => $e->getCode(), + 'Ingest Note' => $e->getMessage(), + ]), $sheet->getName()); + $failed_icd_data[] = ['row_number' => $index, 'error' => $e->getMessage(), 'data' => $row_data]; + } catch (\Exception $e) { + throw new \Exception($e); + // Write Server Error to File + $import->addArrayToRow(array_merge($row_data, [ + 'Ingest Code' => 500, + 'Ingest Note' => env('APP_DEBUG') ? $e->getMessage() : 'Server Error', + ]), $sheet->getName()); + $failed_icd_data[] = ['row_number' => $index, 'error' => $e->getMessage(), 'data' => $row_data]; + } + } + } + + break; // Only Read First Row + } + $import->reader->close(); + Storage::delete('temp/'.$file_name); + $import->writer->close(); + + return [ + 'total_successed_row' => $imported_icd_data, + 'total_failed_row' => count($failed_icd_data), + 'failed_row' => $failed_icd_data, + 'result_file' => [ + 'url' => Storage::disk('public')->url('temp/result-'.$file_name), + 'name' => 'result-'.$file_name, + ] + ]; + } + + public function activation(Request $request, $id) + { + $request->validate([ + 'active' => 'required' + ]); + $Icd = IcdTemplate::findOrFail($id); + $Icd->active = $request->active == '1'; + + if ($Icd->save()) { + return response()->json([ + 'icd' => $Icd, + 'message' => 'Status Updated Successfully' + ]); + } + } + + public function generateIcdList(Request $request){ + // Mendapatkan data yang akan diekspor (misalnya, dari database) + $data = Icd::get()->toArray(); + + // Membuat penulis entitas Spout + $writer = WriterEntityFactory::createXLSXWriter(); + + // Membuka penulis untuk menulis ke file + $writer->openToFile(public_path('files/CorporateMembershipList.xlsx')); + /** Create a style with the StyleBuilder */ + $style = (new StyleBuilder()) + ->setFontBold() + ->build(); + + // Menulis header kolom + $headers_map_to_table_fields = $this->icdService->listing_doc_headers; + $headerRow = WriterEntityFactory::createRowFromArray($headers_map_to_table_fields, $style); + + $writer->addRow($headerRow); + + // Menulis data + if (!empty($data)) { + foreach ($data as $item) { + $rowData = [ + $item['rev'], // Rev + $item['version'], // Version + $item['code'], // Code + $item['parent_code'], // Parent Code + $item['name'], // Name + $item['description'], // Description + $item['active'] == 1 ? 'Active' : 'Inactive', // Status + $item['type'], // Type + ]; + + $row = WriterEntityFactory::createRowFromArray($rowData); + $writer->addRow($row); + } + } + + // Menutup penulis + $writer->close(); + + // Mengembalikan response untuk mengunduh file + $filePath = public_path('files/CorporateMembershipList.xlsx'); + + return Helper::responseJson([ + 'file_name' => "Diagnosis ICD List " . date('Y-m-d h:i:s'), + "file_url" => url('files/CorporateMembershipList.xlsx') + ]); + + } +} diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index 435e09ff..9315ddbc 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -15,6 +15,7 @@ use Modules\Internal\Http\Controllers\Api\CorporateMemberController; use Modules\Internal\Http\Controllers\Api\CorporatePlanController; use Modules\Internal\Http\Controllers\Api\CorporateServiceController; use Modules\Internal\Http\Controllers\Api\DiagnosisController; +use Modules\Internal\Http\Controllers\Api\DiagnosisTemplateController; use Modules\Internal\Http\Controllers\Api\DiagnosisExclusionController; use Modules\Internal\Http\Controllers\Api\DistrictController; use Modules\Internal\Http\Controllers\Api\DivisionController; @@ -127,12 +128,22 @@ Route::prefix('internal')->group(function () { // Audittrail Route::get('audittrail/{corporate_id}', [AuditTrailController::class, 'index']); + + Route::get('master/diagnosis-template', [DiagnosisTemplateController::class, 'index']); + Route::get('master/diagnosis-template/search', [DiagnosisTemplateController::class, 'search']); + Route::post('master/diagnosis-template/store', [DiagnosisTemplateController::class, 'store']); + Route::put('master/diagnosis-template/{id}/activation', [DiagnosisTemplateController::class, 'activation']); + Route::get('master/diagnosis-template/{id}/edit', [DiagnosisTemplateController::class, 'edit']); + Route::put('master/diagnosis-template/{id}/update', [DiagnosisTemplateController::class, 'update']); - Route::get('master/diagnosis', [DiagnosisController::class, 'index']); - Route::get('master/diagnosis/search', [DiagnosisController::class, 'search']); - Route::post('master/diagnosis/import', [DiagnosisController::class, 'import']); - Route::get('master/diagnosis/list', [DiagnosisController::class, 'generateIcdList']); - Route::put('master/diagnosis/{id}/activation', [DiagnosisController::class, 'activation']); + Route::get('master/diagnosis/{diagnosis_template_id}', [DiagnosisController::class, 'index']); + Route::get('master/diagnosis/{diagnosis_template_id}/search', [DiagnosisController::class, 'search']); + Route::post('master/diagnosis/{diagnosis_template_id}/import', [DiagnosisController::class, 'import']); + Route::get('master/diagnosis/{diagnosis_template_id}/list', [DiagnosisController::class, 'generateIcdList']); + Route::put('master/diagnosis/{diagnosis_template_id}/activation', [DiagnosisController::class, 'activation']); + + + Route::get('master/drugs', [DrugController::class, 'index']); Route::get('master/formulariums', [FormulariumController::class, 'index']); Route::post('master/formulariums', [FormulariumController::class, 'store']); diff --git a/Modules/Internal/Services/IcdService.php b/Modules/Internal/Services/IcdService.php index c3a22c20..ce668a4b 100644 --- a/Modules/Internal/Services/IcdService.php +++ b/Modules/Internal/Services/IcdService.php @@ -13,27 +13,25 @@ class IcdService { protected function validateDiagnosisExclusionRow($row) { - if (empty($row['code'])) { - throw new ImportRowException(__('code.REQUIRED'), 0, null, $row); - } - if (empty($row['description_en'])) { - throw new ImportRowException(__('name.REQUIRED'), 0, null, $row); + if (empty($row['ICD_Code'])) { + throw new ImportRowException(__('ICD_Code is REQUIRED'), 0, null, $row); } } - public function handleIcdRow($row) + public function handleIcdRow($row, $id) { try { $this->validateDiagnosisExclusionRow($row); $icd = Icd::updateOrCreate([ - 'code' => $row['code'] + 'code' => $row['ICD_Code'] ], [ - "code" => $row['code'], - "parent_code" => $row['parent_code'] ?? null, - "rev" => $row['reff_exc'], - "name" => $row['description_en'], - "version" => $row["version"] ?? null, - "active" => $row["active"] ?? 0 + "code" => $row['ICD_Code'], + "parent_code" => null, + "rev" => '', + "name" => $row['Description'] ?? null, + "version" => null, + "active" => 1, + "icd_template_id" => $id, ]); return true; @@ -43,13 +41,13 @@ class IcdService } public $listing_doc_headers = [ - "Rev", - "Version", + // "Rev", + // "Version", "Code", - "Parent Code", - "Name", + // "Parent Code", + // "Name", "Description", - "Status", - "Type" + // "Status", + // "Type" ]; } diff --git a/app/Models/Icd.php b/app/Models/Icd.php index 69497c4a..981c5a57 100644 --- a/app/Models/Icd.php +++ b/app/Models/Icd.php @@ -21,7 +21,8 @@ class Icd extends Model 'name', 'description', 'parent_code', - 'active' + 'active', + 'icd_template_id' ]; public $appends = [ diff --git a/app/Models/IcdTemplate.php b/app/Models/IcdTemplate.php new file mode 100644 index 00000000..e58c03dc --- /dev/null +++ b/app/Models/IcdTemplate.php @@ -0,0 +1,32 @@ +logAuditTrail($model, 'deleted'); }); + // ICD or exlusion + IcdTemplate::updated(function ($model) { + $this->logAuditTrail($model, 'updated'); + }); + + IcdTemplate::deleted(function ($model) { + $this->logAuditTrail($model, 'deleted'); + }); + } diff --git a/database/migrations/2023_09_19_164907_create_icd_template.php b/database/migrations/2023_09_19_164907_create_icd_template.php new file mode 100644 index 00000000..9174bc8d --- /dev/null +++ b/database/migrations/2023_09_19_164907_create_icd_template.php @@ -0,0 +1,34 @@ +id(); + $table->string('name'); + $table->string('code'); + $table->string('description'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('icd_template'); + } +}; diff --git a/database/migrations/2023_09_20_090317_add_active_to_icd_template.php b/database/migrations/2023_09_20_090317_add_active_to_icd_template.php new file mode 100644 index 00000000..977af55f --- /dev/null +++ b/database/migrations/2023_09_20_090317_add_active_to_icd_template.php @@ -0,0 +1,32 @@ +integer('active'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('icd_template', function (Blueprint $table) { + $table->dropColumn('active'); + }); + } +}; diff --git a/database/migrations/2023_09_20_152738_add_icd_template_id_to_icd.php b/database/migrations/2023_09_20_152738_add_icd_template_id_to_icd.php new file mode 100644 index 00000000..603b9104 --- /dev/null +++ b/database/migrations/2023_09_20_152738_add_icd_template_id_to_icd.php @@ -0,0 +1,32 @@ +integer('icd_template_id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('icd', function (Blueprint $table) { + $table->dropColumn('icd_template_id'); + }); + } +}; diff --git a/frontend/dashboard/src/@types/corporates.ts b/frontend/dashboard/src/@types/corporates.ts index 45ad95ca..5484f2ce 100644 --- a/frontend/dashboard/src/@types/corporates.ts +++ b/frontend/dashboard/src/@types/corporates.ts @@ -182,3 +182,10 @@ export type CorporateService = { status: string; configurations: any; } + +export type MasterExclusion = { + id?: string | number; + name?: string; + code: string; + description?: string; +} diff --git a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx index f99b2ef4..2629d771 100644 --- a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx +++ b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx @@ -54,7 +54,7 @@ const navConfig = [ // { title: 'Corporate Create', path: '/corporates/create' }, { title: 'Formularium', path: '/master/formularium' }, { title: 'Obat', path: '/master/drugs' }, - { title: 'Diagnosis Library (ICD-X)', path: '/master/diagnosis' }, + { title: 'Master ICD-10 Diagnosis', path: '/master/diagnosis-template' }, { title: 'Hospitals', path: '/hospitals' }, ], }, diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx index 1e6b7361..8b9d8bc1 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx @@ -157,7 +157,12 @@ export default function CustomizedAccordions() { key === 'created_by' || key === 'created_at' || key === 'updated_by' || - key === 'description' + key === 'description'|| + key === 'version'|| + key === 'rev'|| + key === 'active'|| + key === 'parent_code'|| + key === 'id' ) { return null; // Melewati iterasi saat key adalah 'deleted_by' } @@ -196,14 +201,15 @@ export default function CustomizedAccordions() { } const field = key.charAt(0).toUpperCase() + key.slice(1); - - return ( - - {`${field}`} - {`${value}`} - {renderedValue} - - ); + // if (value != renderedValue) { + return ( + + {`${field}`} + {`${value}`} + {renderedValue} + + ); + // } })} diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx index 7f4f7381..495f9880 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx @@ -21,11 +21,15 @@ export default function Divisions() { links={[ { name: 'Master', - href: '/master/diagnosis', + href: '/master/diagnosis-template', + }, + { + name: 'Diagnosis Template', + href: '/master/diagnosis-template', }, { name: 'Diagnosis', - href: '/master/diagnosis', + href: '/master/diagnosis-template', }, ]} /> diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx index 6719e31f..ee729f7f 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx @@ -20,7 +20,7 @@ import { enqueueSnackbar } from 'notistack'; export default function List() { const { themeStretch } = useSettings(); - const { corporate_id } = useParams(); + const { diagnosis_template_id } = useParams(); const [searchParams, setSearchParams] = useSearchParams(); const [importResult, setImportResult] = useState(null); @@ -76,7 +76,7 @@ export default function List() { } const handleICDList = async (appliedFilter = null) => { - axios.get('master/diagnosis/list').then((response) => { + axios.get('master/diagnosis/'+ diagnosis_template_id +'/list').then((response) => { const link = document.createElement('a'); link.href = response.data.data.file_url; link.setAttribute('download', response.data.data.file_name); @@ -108,7 +108,7 @@ export default function List() { if (importForm.current?.files.length) { const formData = new FormData(); formData.append("file", importForm.current?.files[0]) - axios.post(`master/diagnosis/import`, formData ) + axios.post(`master/diagnosis/` + diagnosis_template_id + `/import`, formData ) .then(response => { handleCancelImportButton(); loadDataTableData(); @@ -241,48 +241,8 @@ export default function List() { return ( *': { borderBottom: 'unset' } }}> - - setOpen(!open)} - > - {open ? : } - - - {row.type} {row.code} {row.name} - {row.version} - - - {/* */} - - {row.active == 1 && ( - - )} - {row.active != 1 && ( - - )} - {/* */} @@ -290,18 +250,6 @@ export default function List() { - {/* COLLAPSIBLE ROW */} - - - - - - Description : {row.description} - - - - - ); } @@ -329,8 +277,7 @@ 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('/master/diagnosis', { params: filter }); - console.log(response.data); + const response = await axios.get('/master/diagnosis/'+diagnosis_template_id, { params: filter }); setDataTableLoading(false); setDataTableData(response.data); @@ -365,12 +312,8 @@ export default function List() { - - Type Code - Name - Version - Status + Description Action diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx index 7e5d53b2..d84e7f80 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx @@ -32,7 +32,7 @@ export default function PlanCreate() { useEffect(() => { if (isEdit) { - axios.get('/corporates/'+corporate_id+'/divisions/'+id+'/edit') + axios.get('/master/diagnosis-template/'+id+'/edit') .then((res) => { setCurrentCorporatePlan(res.data); }) @@ -46,21 +46,17 @@ export default function PlanCreate() { return ( - + ({ name: currentCorporatePlan?.name || '', - code: currentCorporatePlan?.code || '', + description: currentCorporatePlan?.description || '', active: currentCorporatePlan?.active === 1 ? true : false, }), [currentCorporatePlan] @@ -64,12 +63,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop const onSubmit = async (data: any) => { if (!isEdit) { await axios - .post('/corporates/' + corporate_id + '/divisions', data) + .post('/master/diagnosis-template/store', data) .then((res) => { enqueueSnackbar('Division created successfully', { variant: 'success' }); }) .then((res) => { - navigate('/corporate/' + corporate_id + '/divisions', { replace: true }); + navigate('/master/diagnosis-template', { replace: true }); }) .catch(({ response }) => { if (response.status === 422) { @@ -84,12 +83,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop }); } else { await axios - .put('/corporates/' + corporate_id + '/divisions/' + currentCorporatePlan?.id , data) + .put('/master/diagnosis-template/' + currentCorporatePlan?.id + '/update', data) .then((res) => { enqueueSnackbar('Division updated successfully', { variant: 'success' }); }) .then((res) => { - navigate('/corporate/' + corporate_id + '/divisions/' , { replace: true }); + navigate('/master/diagnosis-template' , { replace: true }); }) .catch(({ response }) => { enqueueSnackbar('Update Failed : '+ response.data.message, { variant: 'error' }); @@ -106,9 +105,9 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop Division Detail - - + + { isEdit? 'Update' : 'Create' } @@ -117,12 +116,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop - + {/* - + */} ); diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/History.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/History.tsx new file mode 100644 index 00000000..c72d8f80 --- /dev/null +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/History.tsx @@ -0,0 +1,218 @@ +// @mui +import { + Box, + Button, + Card, + Collapse, + Container, + FormControl, + Grid, + IconButton, + InputLabel, + MenuItem, + OutlinedInput, + Paper, + Select, + SelectChangeEvent, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, + Typography, + Badge, + Stack, +} from '@mui/material'; +import * as React from 'react'; +import { useParams } from 'react-router-dom'; +import { styled } from '@mui/material/styles'; +import ArrowForwardIosSharpIcon from '@mui/icons-material/ArrowForwardIosSharp'; +import MuiAccordion, { AccordionProps } from '@mui/material/Accordion'; +import { useContext, useEffect, useState } from 'react'; +import MuiAccordionSummary, { + AccordionSummaryProps, +} from '@mui/material/AccordionSummary'; +import useSettings from '../../../../hooks/useSettings'; +import axios from '../../../../utils/axios'; +import { ConfiguredCorporateContext } from '@/contexts/ConfiguredCorporateContext'; +import MuiAccordionDetails from '@mui/material/AccordionDetails'; +import HeaderBreadcrumbs from '../../../../components/HeaderBreadcrumbs'; +import { Corporate } from '@/@types/corporates'; +import { fDate, fDateTime } from '@/utils/formatTime'; + +const Accordion = styled((props: AccordionProps) => ( + +))(({ theme }) => ({ + border: `1px solid ${theme.palette.divider}`, + '&:not(:last-child)': { + borderBottom: 0, + }, + '&:before': { + display: 'none', + }, +})); + +const AccordionSummary = styled((props: AccordionSummaryProps) => ( + } + {...props} + /> +))(({ theme }) => ({ + backgroundColor: + theme.palette.mode === 'dark' + ? 'rgba(255, 255, 255, .05)' + : 'rgba(0, 0, 0, .03)', + flexDirection: 'row-reverse', + '& .MuiAccordionSummary-expandIconWrapper.Mui-expanded': { + transform: 'rotate(90deg)', + }, + '& .MuiAccordionSummary-content': { + marginLeft: theme.spacing(1), + }, +})); + +const AccordionDetails = styled(MuiAccordionDetails)(({ theme }) => ({ + padding: theme.spacing(2), + borderTop: '1px solid rgba(0, 0, 0, .125)', +})); + +export default function CustomizedAccordions() { + const [expanded, setExpanded] = React.useState('panel1'); + + const handleChange = + (panel: string) => (event: React.SyntheticEvent, newExpanded: boolean) => { + setExpanded(newExpanded ? panel : false); + }; + const pageTitle = 'Diagnosis Template Audittrail'; + + const { themeStretch } = useSettings(); + + const { id } = useParams(); + + const [corporate, setCorporate] = useState(); + const [ currentCorporate, setCurrentCorporate ] = useState(); + + const configuredCorporateContext = useContext(ConfiguredCorporateContext); + + useEffect(() => { + setCorporate(configuredCorporateContext.currentCorporate); + const model = 'App\\Models\\IcdTemplate'; + const url = `/audittrail/${id}?model=${model}`; + axios.get(url) + .then((res) => { + setCurrentCorporate(res.data); + }) + .catch((error) => { + console.error('Terjadi kesalahan:', error); + }); + + }, [configuredCorporateContext]); + + return ( +
+ + {currentCorporate?.data.map((item, index) => ( + + + {`Data has ${item.action} by ${item.user_id} on ${fDateTime(item.updated_at)}`} + + + + + Field + Old Value + New Values + + + + {Object.entries(item.old_values).map(([key, value]) => { + let renderedValue; + if (key === 'deleted_by' || + key === 'deleted_at' || + key === 'created_by' || + key === 'created_at' || + key === 'updated_by' || + key === 'description' + ) { + return null; // Melewati iterasi saat key adalah 'deleted_by' + } + switch (key) { + case 'welcome_message': + renderedValue = item.new_values[key].replace(/<[^>]*>/g, ''); + value = value.replace(/<[^>]*>/g, ''); + break; + case 'help_text': + renderedValue = item.new_values[key].replace(/<[^>]*>/g, ''); + value = value.replace(/<[^>]*>/g, ''); + break; + case 'active': + renderedValue = item.new_values[key] == 1 ? 'Active' : 'Inactive'; + value = value == 1 ? 'Active' : 'Inactive'; + break; + case 'created_at': + renderedValue = fDateTime(item.new_values[key]); + value = fDateTime(value); + break; + case 'updated_at': + renderedValue = fDateTime(item.new_values[key]); + value = fDateTime(value); + break; + case 'updated_at': + renderedValue = fDateTime(item.new_values[key]); + value = fDateTime(value); + break; + case 'delete_at': + renderedValue = fDateTime(item.new_values[key]); + value = fDateTime(value); + break; + default: + renderedValue = item.new_values[key]; + break; + } + + const field = key.charAt(0).toUpperCase() + key.slice(1); + if (value == renderedValue) { + return null + } else { + return ( + + {`${field}`} + {`${value}`} + {renderedValue} + + ); + } + })} + + + + + ))} +
+ ); +} diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx index ab1cecb2..0afc6518 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx @@ -12,7 +12,7 @@ export default function Divisions() { const { corporate_id } = useParams(); - const pageTitle = 'Diagnosis'; + const pageTitle = 'Diagnosis Template'; return ( @@ -21,11 +21,11 @@ export default function Divisions() { links={[ { name: 'Master', - href: '/master/diagnosis', + href: '/master/diagnosis-template', }, { - name: 'Diagnosis', - href: '/master/diagnosis', + name: 'Diagnosis Template', + href: '/master/diagnosis-template', }, ]} /> diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx index b40379e1..67e30f2f 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx @@ -129,6 +129,7 @@ export default function List() { handleClose(); }) } + return ( @@ -144,9 +145,11 @@ export default function List() { aria-controls={createMenu ? 'basic-menu' : undefined} aria-haspopup="true" aria-expanded={createMenu ? 'true' : undefined} - onClick={handleClick} + > - Import + + Create + - Create Template - {handleGetTemplate('master-icd')}}>Download Template - Download ICD + + + )} - - {( currentImportFileName && - - - - - - - - )} - {( importResult && - - Last Import Result Report : {importResult.result_file?.name ?? "-"} - - )} ); } @@ -203,7 +184,7 @@ export default function List() { const handleActivate = (model: any, status: string) => { axios - .put(`/master/diagnosis/${row.id}/activation`, { + .put(`/master/diagnosis-template/${row.id}/activation`, { // service_code: service.service_code, active: status == 'active', }) @@ -231,65 +212,25 @@ export default function List() { return ( *': { borderBottom: 'unset' } }}> - - setOpen(!open)} - > - {open ? : } - - - {row.type} - {row.code} {row.name} - {row.version} - - - {/* */} - - {row.active == 1 && ( - - )} - {row.active != 1 && ( - - )} - - + {row.description ?? '-'} + {/* */} - + + + + + + + + - - - {/* COLLAPSIBLE ROW */} - - - - - - Description : {row.description} - - - + @@ -319,7 +260,7 @@ 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('/master/diagnosis', { params: filter }); + const response = await axios.get('/master/diagnosis-template', { params: filter }); console.log(response.data); setDataTableLoading(false); @@ -355,12 +296,8 @@ export default function List() {
- - Type - Code Name - Version - Status + Description Action @@ -368,7 +305,7 @@ export default function List() { ( - Loading + Loading ) : ( @@ -376,7 +313,7 @@ export default function List() { ( - No Data + No Data ) : ( diff --git a/frontend/dashboard/src/routes/index.tsx b/frontend/dashboard/src/routes/index.tsx index 29f81fe6..23725491 100644 --- a/frontend/dashboard/src/routes/index.tsx +++ b/frontend/dashboard/src/routes/index.tsx @@ -236,12 +236,25 @@ export default function Router() { path: 'master/hospitals/:id/edit', element: , }, + { + path: 'master/diagnosis-template/create', + element: , + }, { path: 'master/diagnosis-template', element: , }, { - path: 'master/diagnosis', + path: 'master/diagnosis-template/:id/diagnosis-template-history', + element: , + }, + { + path: 'master/diagnosis-template/:id/edit', + element: , + }, + + { + path: 'master/diagnosis/:diagnosis_template_id', element: , }, { @@ -423,8 +436,12 @@ const DiagnosisExclusions = Loadable( const CorporateFormularium = Loadable(lazy(() => import('../pages/Corporates/Formularium/Index'))); -const MasterDiagnosis = Loadable(lazy(() => import('../pages/Master/Diagnosis/Index'))); const MasterDiagnosisTemplate = Loadable(lazy(() => import('../pages/Master/Diagnosis/Master/Index'))); +const MasterDiagnosisTemplateCreate = Loadable(lazy(() => import('../pages/Master/Diagnosis/Master/CreateUpdate'))); +const MasterDiagnosisTemplateHistories = Loadable( + lazy(() => import('../pages/Master/Diagnosis/Master/History')) +); +const MasterDiagnosis = Loadable(lazy(() => import('../pages/Master/Diagnosis/Index'))); const MasterDiagnosisHistories = Loadable( lazy(() => import('../pages/Master/Diagnosis/History')) ); diff --git a/public/files/CorporateMembershipList.xlsx b/public/files/CorporateMembershipList.xlsx index 0b61774ef465de6a959cf55e2e5199e328ca790d..a3fd8fdcaf3c18c0f8fc683ff6dd6e3ba9cac21f 100644 GIT binary patch delta 1420 zcmZ3ka#xZ!z?+#xgn@~HgJDjn=|r_Ynhuy}z}c-sRnDQkqoexbVTz)9W6X=3X|N&_5|<`r7^X zJTKqUQ<5{8e#R&5-t0Y|Fa9l3u_}Jua?#SSoYO7l`ZB>?r$64_xTp5OiOOZtYQ4`a z<#rza{iw~#zTT_uh2?h+fi0&C-~avK(XqOE-Hh8a8?!AkdqdAOXInpFJ01DhY2qXm z?@85*W?a~@;MWqbr?RWgdj6JC7f>o*vtaGT*MV)x3l_X%o;$N;p0N*Clys)frr4>E zH~B0RJv2*G?()2uB2z^bJ(Lc_C$19By5+Rm>D22m#efTqmFL&$)gN@+Tr0yK5Zt_M z<6_PC)8CxiWO(+S8S7=XJySRGo+(K5`zWNf;>p@}Chc8zZ|?CdEPcE;kTKnJHt&H| zJEyc8-2Gn0UD2Fy(Yrh8k+<-%7N-A6O)Q%w-Nj{@`df1hl@GJoykOaJdy(#qwntsR zE}dhOX0x28_Dyo{a!tca|2yV7{$nNh}Y!k!^i$DKRn0J>(Idy*9A@PdFk*l+1~$}Rn)TiXnJgFV@GIoFgUEUgPF!nv=Cyx1G%{#|2B-^y8A=Qc6P z9$XYE`6MRzo@9mTT(-w7H!gHfSsEjr@qErQiRgXICv)C#K0Tb9u2Q_ug!fuc{U){o zulf_R(;h^el{wsOaA~uk@2Oemz5b@&3JfUb(e(&8_ejO>gT8jFb=Hom$0GAC^7U*9 ze`q-KWV5L8)$g@;(v_e8_WyAF^yk|aSt?gPgvbO)w)}fCd43V|8AsVF?!PbJP087G ze0f&ysVPe$UE~&-tQ2w*=dRklN738MqfcK&JnLn++E&s3rSo+r-_gH*AdaVg(U&Wg zl08rFU!8s*B?KpP@t@*GDrh!Kv#>DoGBVjS!^@t@5BcrDWsj186)#HJGdWX0PXQ!? zn!JI<5fm(GlxG1Zb~UheNkM6*F4oEaxMlbQyisjP1WL_hn_MTT1U3#FiNM_A#>BuN z2r~;vFKG;ApL{@2-VtPHre6r(a-iTdAQnJTw1k6!AtgUKpeVnfSU<6#08}KR+c--= iTD6jsfg!#qHK$l#4@3rdv$BEA;RHf^pv@gzARYj(QCAuO delta 2777 zcmZ9Oc{CJUAIFD5V;ETmlO@?Fgn4FYqMBrBvr}V*;!&pp5U{oZr#?~nT#Jy4_qvAzK0g93N~AV6QD zLIot82e_w{M4k=uo?=HvC&Yqz002QC0003101*K?q|nF!Z<2OIV8BgV3;)-;!u88o z*f_Q*J{=(^tq)qPykI!kcaHw%qfS5#YI~hBS!FTg-f%YR&KS$9XVg(MRQ%*we~r3P zC`_4dbg9-82(yjzXYpqqMh-ft z3wuQ^=w*s-#q-VbFQ4|~q-2|N%~3f5NWYBQegw1spv9A59#KbKvuOXI;v=1a{E2;x zXS@Y(Zglr+EMzIrzyo23JU-bnQ|;*4^ZKr8x4o_psl*od-fetyz^#`HyLnWP56|6C zNsxq*9ZVkGU)U)=cs%dvbkASz`pglB@up7$6z^mk)h!UjRm8Kh+u+U}gcBn|+dCC_ zxzyS(@4?gyoW#jP=(P{|mp8i$NB=A!hq&{n=58>6ygKInbjOJY$GK&>{a%{44ChIW z=nu#A`tJ-4#)+GrR?ze8S z5(W8qWd5gpSYuG{dZqvXkfsFyzyOp$AsKQZ&6zZehQ^I=VDW?Z8J~gJ@fYWufbnP^ z^JgfFaeFO~z_g_-bMdbO<>m&Xor^|)te77JO;IwuVhqlJrSrzZ1)~(xdbH{TLY)}` zO7m)|_^r?(hjKHEn)rzL9+0}@d2QK!uVnMeVqZjb3?efH58uWgn$Ago24Bfs(kG9< z@k)x+Y&)lMa>yqjNrG@cFQp)+o~2c8ck8qB0^VKyv9i>b2nz`rV)~x8 ztJI=yX0Mc_e)2QYKakpmN_}hk;u*OXpF^lQiuo9;8WHwZG2&3t?B;C*RG5bdS19bNV9md`s@{DW_HgelCvwVNu5CER)y4}!4oB&Rh z(if5RAP-cWbPI#Gc^(Po1PU-E*yfXKzL|MU%OYas(Jv0|RX0oTf$?xabfjoNsnqeZ@KXbA3(zyMJ;>_SZJGHeVd=R&CQvg?w*{-%@H zg1z#je~kD}q=@F!nk(bJV~&;?Eu8_yz-*d@P>MP#Mx=Z7UCIBz*gPi}WI2p=yP7ix zBWi9S#BX7j$vkVdWrGW34?QCVpDByJd5N~Kk=135@Owe#UDr>t`DIk7Br Tllnx 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 delta 2252 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 r42ER-jYx;tGm(geEX_2nd2}KYVTtZWN5)d$I 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 literal 0 HcmV?d00001