Compare commits
36 Commits
feature/ge
...
feature/cl
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ee9293daf | |||
| 89cd2a9d37 | |||
| ce0fde18dc | |||
| acf9fa348e | |||
| 74dd65efde | |||
| edc5ba9822 | |||
| 8902718523 | |||
| 1c4f03ea83 | |||
| 627904abba | |||
| bd3f53b596 | |||
| 69919878fa | |||
| f3bdf12bc4 | |||
| eb1211cde7 | |||
|
|
b8ed27f2ff | ||
| 74cfcfa16b | |||
| 9f95e89a9a | |||
| e51068b0a6 | |||
| 5cd23ff343 | |||
| 615330bb46 | |||
| be43f8a4a4 | |||
| dba421ad0b | |||
| c3a78f8a40 | |||
| 6c6a7c3919 | |||
| 5c71b556a0 | |||
| 63c53d18d1 | |||
| a5db01bd25 | |||
| 5d4033a9ca | |||
| 27523b8cce | |||
| f6117743ad | |||
| 8c97df9fc4 | |||
| 4f2bb19d8a | |||
| 13764a3766 | |||
| ed273fdafa | |||
| d706bf0623 | |||
| 13542cd3c0 | |||
|
|
a7e688a52c |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -12,3 +12,6 @@ npm-debug.log
|
|||||||
yarn-error.log
|
yarn-error.log
|
||||||
/.idea
|
/.idea
|
||||||
/.vscode
|
/.vscode
|
||||||
|
|
||||||
|
/public/dashboard
|
||||||
|
/public/dashboard-staging
|
||||||
|
|||||||
0
Modules/HospitalPortal/Config/.gitkeep
Normal file
0
Modules/HospitalPortal/Config/.gitkeep
Normal file
5
Modules/HospitalPortal/Config/config.php
Normal file
5
Modules/HospitalPortal/Config/config.php
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'name' => 'HospitalPortal'
|
||||||
|
];
|
||||||
0
Modules/HospitalPortal/Console/.gitkeep
Normal file
0
Modules/HospitalPortal/Console/.gitkeep
Normal file
0
Modules/HospitalPortal/Database/Migrations/.gitkeep
Normal file
0
Modules/HospitalPortal/Database/Migrations/.gitkeep
Normal file
0
Modules/HospitalPortal/Database/Seeders/.gitkeep
Normal file
0
Modules/HospitalPortal/Database/Seeders/.gitkeep
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class HospitalPortalDatabaseSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
Model::unguard();
|
||||||
|
|
||||||
|
// $this->call("OthersTableSeeder");
|
||||||
|
}
|
||||||
|
}
|
||||||
0
Modules/HospitalPortal/Database/factories/.gitkeep
Normal file
0
Modules/HospitalPortal/Database/factories/.gitkeep
Normal file
0
Modules/HospitalPortal/Entities/.gitkeep
Normal file
0
Modules/HospitalPortal/Entities/.gitkeep
Normal file
0
Modules/HospitalPortal/Http/Controllers/.gitkeep
Normal file
0
Modules/HospitalPortal/Http/Controllers/.gitkeep
Normal file
128
Modules/HospitalPortal/Http/Controllers/Api/AuthController.php
Executable file
128
Modules/HospitalPortal/Http/Controllers/Api/AuthController.php
Executable file
@@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\User;
|
||||||
|
use Crypt;
|
||||||
|
use Error;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Modules\Internal\Emails\SendVerifyEmail;
|
||||||
|
use Modules\Internal\Events\ForgetPassword;
|
||||||
|
|
||||||
|
class AuthController extends Controller
|
||||||
|
{
|
||||||
|
public function login(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'email' => 'required|email',
|
||||||
|
'password' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = User::query()
|
||||||
|
->where('email', $request->email)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return response(['message' => 'User Tidak Ditemukan'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hash::check($request->password, $user->password)) {
|
||||||
|
return response(['message' => 'Password Salah'], 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response([
|
||||||
|
'message' => 'Selamat Datang',
|
||||||
|
'user' => $user,
|
||||||
|
'token' => $user->createToken('app')->plainTextToken
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout(Request $request)
|
||||||
|
{
|
||||||
|
$token = $request->bearerToken();
|
||||||
|
Auth::user()->tokens()->where('id', $token)->delete();
|
||||||
|
|
||||||
|
return response(['message' => 'Berhasil Logout.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resetPassword(Request $request)
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'old_password' => 'required',
|
||||||
|
'new_password' => 'required',
|
||||||
|
'confirm_new_password' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!Hash::check($request['old_password'], $user->password)) {
|
||||||
|
return response(['message' => 'Password Salah'], 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request["new_password"] != $request["confirm_new_password"]) {
|
||||||
|
return response([
|
||||||
|
'message' => "Password Tidak Sama"
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->update([
|
||||||
|
'password' => Hash::make($request->confirm_new_password),
|
||||||
|
]);
|
||||||
|
return response()->json($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function verifyEmail(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'email' => 'required|email',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = User::query()
|
||||||
|
->where('email', $request->email)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return response(['message' => 'User Tidak Ditemukan'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
Event(new ForgetPassword($user));
|
||||||
|
|
||||||
|
// Mail::to($user->email)->send(new SendVerifyEmail($user));
|
||||||
|
|
||||||
|
return response()->json($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forgetPassword(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'new_password' => 'required',
|
||||||
|
'confirm_new_password' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$token = Crypt::decryptString($request->token);
|
||||||
|
$email = explode('|', $token)[0];
|
||||||
|
|
||||||
|
$user = User::query()
|
||||||
|
->where('email', $email)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return response(['message' => 'User Tidak Ditemukan'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request["new_password"] != $request["confirm_new_password"]) {
|
||||||
|
return response([
|
||||||
|
'message' => "Password Tidak Sama"
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->update([
|
||||||
|
'password' => Hash::make($request->confirm_new_password),
|
||||||
|
]);
|
||||||
|
return response()->json($user);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Events\ClaimRequested;
|
||||||
|
use App\Helpers\Helper;
|
||||||
|
use App\Models\ClaimRequest;
|
||||||
|
use App\Models\File;
|
||||||
|
use App\Models\Member;
|
||||||
|
use App\Services\ClaimRequestService;
|
||||||
|
use App\Services\ClaimService;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Contracts\Support\Renderable;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Routing\Controller;
|
||||||
|
use Modules\HospitalPortal\Transformers\ClaimRequestResource;
|
||||||
|
use Modules\HospitalPortal\Transformers\ClaimRequestShowResource;
|
||||||
|
use PDF;
|
||||||
|
|
||||||
|
class ClaimRequestController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function index(request $request)
|
||||||
|
{
|
||||||
|
$claimRequests = ClaimRequest::query()
|
||||||
|
->when($request->search, function ($q, $search) {
|
||||||
|
$q->where('code', 'LIKE', "%".$search."%");
|
||||||
|
})
|
||||||
|
->when($request->orderBy, function ($q, $orderBy) use ($request) {
|
||||||
|
if (in_array($orderBy, ['submission_date', 'code'])) {
|
||||||
|
$q->orderBy($orderBy, $request->order);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->when($request->status, function($q, $status) {
|
||||||
|
$q->where('status', $status);
|
||||||
|
})
|
||||||
|
->with(['member'])
|
||||||
|
->orderBy('created_at', 'DESC')
|
||||||
|
->paginate();
|
||||||
|
|
||||||
|
return Helper::responseJson($claimRequests);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('hospitalportal::create');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
* @param Request $request
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'member_id' => 'required',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$member = Member::find($request->member_id);
|
||||||
|
$newClaimRequest = ClaimRequestService::storeClaimRequest(member: $member);
|
||||||
|
|
||||||
|
ClaimRequested::dispatch($newClaimRequest);
|
||||||
|
|
||||||
|
// Log History
|
||||||
|
$newClaimRequest->histories()->create([
|
||||||
|
'title' => 'New Claim Requested',
|
||||||
|
'description' => "Claim Requested for Member : {$member->member_id} - ({$member->full_name})",
|
||||||
|
'type' => 'info',
|
||||||
|
'system_origin' => 'hospital-portal'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($request->hasFile('result_files')) {
|
||||||
|
foreach ($request->result_files as $file) {
|
||||||
|
$pathFile = File::storeFile('claim-result', $newClaimRequest->id, $file);
|
||||||
|
$newClaimRequest->files()->updateOrCreate([
|
||||||
|
'type' => 'claim-result',
|
||||||
|
'name' => File::getFileName('claim-result', $newClaimRequest->id, $file),
|
||||||
|
'original_name' => $file->getClientOriginalName(),
|
||||||
|
'extension' => $file->getClientOriginalExtension(),
|
||||||
|
'path' => $pathFile,
|
||||||
|
'created_by' => auth()->user()->id,
|
||||||
|
'updated_by' => auth()->user()->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->hasFile('diagnosa_files')) {
|
||||||
|
foreach ($request->diagnosa_files as $file) {
|
||||||
|
$pathFile = File::storeFile('claim-diagnosis', $newClaimRequest->id, $file);
|
||||||
|
$newClaimRequest->files()->updateOrCreate([
|
||||||
|
'type' => 'claim-diagnosis',
|
||||||
|
'name' => File::getFileName('claim-diagnosis', $newClaimRequest->id, $file),
|
||||||
|
'original_name' => $file->getClientOriginalName(),
|
||||||
|
'extension' => $file->getClientOriginalExtension(),
|
||||||
|
'path' => $pathFile,
|
||||||
|
'created_by' => auth()->user()->id,
|
||||||
|
'updated_by' => auth()->user()->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->hasFile('result_files')) {
|
||||||
|
foreach ($request->result_files as $file) {
|
||||||
|
$pathFile = File::storeFile('claim-kondisi', $newClaimRequest->id, $file);
|
||||||
|
$newClaimRequest->files()->updateOrCreate([
|
||||||
|
'type' => 'claim-kondisi',
|
||||||
|
'name' => File::getFileName('claim-kondisi', $newClaimRequest->id, $file),
|
||||||
|
'original_name' => $file->getClientOriginalName(),
|
||||||
|
'extension' => $file->getClientOriginalExtension(),
|
||||||
|
'path' => $pathFile,
|
||||||
|
'created_by' => auth()->user()->id,
|
||||||
|
'updated_by' => auth()->user()->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Helper::responseJson(data: $request->toArray(), message: 'Claim Request berhasil ajukan!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the specified resource.
|
||||||
|
* @param int $id
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
$claimRequest = ClaimRequest::findOrFail($id);
|
||||||
|
$claimRequest->load([
|
||||||
|
'histories' => function ($history) {
|
||||||
|
$history->latest();
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
return Helper::responseJson(data: ClaimRequestShowResource::make($claimRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
* @param int $id
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
return view('hospitalportal::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)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateLog($claim_request_id)
|
||||||
|
{
|
||||||
|
$claimRequest = ClaimRequest::findOrFail($claim_request_id);
|
||||||
|
|
||||||
|
if ($claimRequest->status != 'approved') {
|
||||||
|
throw new Exception("Belum Teverifikasi", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$member = Member::findOrFail($claimRequest->member_id)
|
||||||
|
->load(['currentPlan', 'currentPolicy', 'currentPlan.corporateBenefits', 'currentPlan.corporateBenefits.benefit']);
|
||||||
|
|
||||||
|
$pdf = PDF::loadView('pdf.guaranted_leter', compact('member', 'claimRequest'));
|
||||||
|
return $pdf->download('Guaranted Letter - '.$member->full_name.'.pdf');
|
||||||
|
|
||||||
|
return $claimRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\Helper;
|
||||||
|
use App\Models\Member;
|
||||||
|
use Illuminate\Contracts\Support\Renderable;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Routing\Controller;
|
||||||
|
|
||||||
|
class MemberController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function search(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'no_polis' => 'required',
|
||||||
|
'birth_date' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$member = Member::query()
|
||||||
|
->where('member_id', $request->no_polis)
|
||||||
|
->where('birth_date', $request->birth_date)
|
||||||
|
->with(['person', 'currentCorporate',
|
||||||
|
// 'currentCorporate.corporateServices' => function ($corporateService) {
|
||||||
|
// $corporateService->where('status', 'active');
|
||||||
|
// },
|
||||||
|
// 'currentCorporate.corporateServices.service'
|
||||||
|
// 'currentPlan.benefits',
|
||||||
|
// 'currentPlan.corporateBenefit.plan',
|
||||||
|
'currentPlan.corporateBenefits.benefit'
|
||||||
|
])
|
||||||
|
->firstOrFail();
|
||||||
|
|
||||||
|
|
||||||
|
return Helper::responseJson($member);
|
||||||
|
}
|
||||||
|
}
|
||||||
83
Modules/HospitalPortal/Http/Controllers/ClaimController.php
Normal file
83
Modules/HospitalPortal/Http/Controllers/ClaimController.php
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Helpers\Helper;
|
||||||
|
use App\Models\Claim;
|
||||||
|
use Illuminate\Contracts\Support\Renderable;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Routing\Controller;
|
||||||
|
|
||||||
|
class ClaimController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$claims = Claim::where('deleted_at', 'ASD')->paginate(5);
|
||||||
|
|
||||||
|
return Helper::responseJson($claims);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('hospitalportal::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)
|
||||||
|
{
|
||||||
|
return view('hospitalportal::show');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
* @param int $id
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
return view('hospitalportal::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)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Support\Renderable;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Routing\Controller;
|
||||||
|
|
||||||
|
class HospitalPortalController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('hospitalportal::index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('hospitalportal::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)
|
||||||
|
{
|
||||||
|
return view('hospitalportal::show');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
* @param int $id
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
return view('hospitalportal::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)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
0
Modules/HospitalPortal/Http/Middleware/.gitkeep
Normal file
0
Modules/HospitalPortal/Http/Middleware/.gitkeep
Normal file
0
Modules/HospitalPortal/Http/Requests/.gitkeep
Normal file
0
Modules/HospitalPortal/Http/Requests/.gitkeep
Normal file
0
Modules/HospitalPortal/Providers/.gitkeep
Normal file
0
Modules/HospitalPortal/Providers/.gitkeep
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Database\Eloquent\Factory;
|
||||||
|
|
||||||
|
class HospitalPortalServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string $moduleName
|
||||||
|
*/
|
||||||
|
protected $moduleName = 'HospitalPortal';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $moduleNameLower
|
||||||
|
*/
|
||||||
|
protected $moduleNameLower = 'hospitalportal';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boot the application events.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
$this->registerTranslations();
|
||||||
|
$this->registerConfig();
|
||||||
|
$this->registerViews();
|
||||||
|
$this->loadMigrationsFrom(module_path($this->moduleName, 'Database/Migrations'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the service provider.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app->register(RouteServiceProvider::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register config.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function registerConfig()
|
||||||
|
{
|
||||||
|
$this->publishes([
|
||||||
|
module_path($this->moduleName, 'Config/config.php') => config_path($this->moduleNameLower . '.php'),
|
||||||
|
], 'config');
|
||||||
|
$this->mergeConfigFrom(
|
||||||
|
module_path($this->moduleName, 'Config/config.php'), $this->moduleNameLower
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register views.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function registerViews()
|
||||||
|
{
|
||||||
|
$viewPath = resource_path('views/modules/' . $this->moduleNameLower);
|
||||||
|
|
||||||
|
$sourcePath = module_path($this->moduleName, 'Resources/views');
|
||||||
|
|
||||||
|
$this->publishes([
|
||||||
|
$sourcePath => $viewPath
|
||||||
|
], ['views', $this->moduleNameLower . '-module-views']);
|
||||||
|
|
||||||
|
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register translations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function registerTranslations()
|
||||||
|
{
|
||||||
|
$langPath = resource_path('lang/modules/' . $this->moduleNameLower);
|
||||||
|
|
||||||
|
if (is_dir($langPath)) {
|
||||||
|
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
|
||||||
|
} else {
|
||||||
|
$this->loadTranslationsFrom(module_path($this->moduleName, 'Resources/lang'), $this->moduleNameLower);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the services provided by the provider.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function provides()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPublishableViewPaths(): array
|
||||||
|
{
|
||||||
|
$paths = [];
|
||||||
|
foreach (\Config::get('view.paths') as $path) {
|
||||||
|
if (is_dir($path . '/modules/' . $this->moduleNameLower)) {
|
||||||
|
$paths[] = $path . '/modules/' . $this->moduleNameLower;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
69
Modules/HospitalPortal/Providers/RouteServiceProvider.php
Normal file
69
Modules/HospitalPortal/Providers/RouteServiceProvider.php
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
|
class RouteServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The module namespace to assume when generating URLs to actions.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $moduleNamespace = 'Modules\HospitalPortal\Http\Controllers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before routes are registered.
|
||||||
|
*
|
||||||
|
* Register any model bindings or pattern based filters.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the routes for the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function map()
|
||||||
|
{
|
||||||
|
$this->mapApiRoutes();
|
||||||
|
|
||||||
|
$this->mapWebRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the "web" routes for the application.
|
||||||
|
*
|
||||||
|
* These routes all receive session state, CSRF protection, etc.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function mapWebRoutes()
|
||||||
|
{
|
||||||
|
Route::middleware('web')
|
||||||
|
->namespace($this->moduleNamespace)
|
||||||
|
->group(module_path('HospitalPortal', '/Routes/web.php'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the "api" routes for the application.
|
||||||
|
*
|
||||||
|
* These routes are typically stateless.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function mapApiRoutes()
|
||||||
|
{
|
||||||
|
Route::prefix('api')
|
||||||
|
->middleware('api')
|
||||||
|
->namespace($this->moduleNamespace)
|
||||||
|
->group(module_path('HospitalPortal', '/Routes/api.php'));
|
||||||
|
}
|
||||||
|
}
|
||||||
0
Modules/HospitalPortal/Resources/assets/.gitkeep
Normal file
0
Modules/HospitalPortal/Resources/assets/.gitkeep
Normal file
0
Modules/HospitalPortal/Resources/assets/js/app.js
Normal file
0
Modules/HospitalPortal/Resources/assets/js/app.js
Normal file
0
Modules/HospitalPortal/Resources/lang/.gitkeep
Normal file
0
Modules/HospitalPortal/Resources/lang/.gitkeep
Normal file
0
Modules/HospitalPortal/Resources/views/.gitkeep
Normal file
0
Modules/HospitalPortal/Resources/views/.gitkeep
Normal file
9
Modules/HospitalPortal/Resources/views/index.blade.php
Normal file
9
Modules/HospitalPortal/Resources/views/index.blade.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
@extends('hospitalportal::layouts.master')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<h1>Hello World</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This view is loaded from module: {!! config('hospitalportal.name') !!}
|
||||||
|
</p>
|
||||||
|
@endsection
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Module HospitalPortal</title>
|
||||||
|
|
||||||
|
{{-- Laravel Mix - CSS File --}}
|
||||||
|
{{-- <link rel="stylesheet" href="{{ mix('css/hospitalportal.css') }}"> --}}
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
@yield('content')
|
||||||
|
|
||||||
|
{{-- Laravel Mix - JS File --}}
|
||||||
|
{{-- <script src="{{ mix('js/hospitalportal.js') }}"></script> --}}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
0
Modules/HospitalPortal/Routes/.gitkeep
Normal file
0
Modules/HospitalPortal/Routes/.gitkeep
Normal file
44
Modules/HospitalPortal/Routes/api.php
Normal file
44
Modules/HospitalPortal/Routes/api.php
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Modules\HospitalPortal\Http\Controllers\Api\AuthController;
|
||||||
|
use Modules\HospitalPortal\Http\Controllers\Api\ClaimRequestController;
|
||||||
|
use Modules\HospitalPortal\Http\Controllers\Api\MemberController;
|
||||||
|
use Modules\HospitalPortal\Http\Controllers\ClaimController;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| API Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here is where you can register API routes for your application. These
|
||||||
|
| routes are loaded by the RouteServiceProvider within a group which
|
||||||
|
| is assigned the "api" middleware group. Enjoy building your API!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Route::prefix('hospitalportal')->group(function () {
|
||||||
|
|
||||||
|
Route::post('login', [AuthController::class, 'login'])->name('login');
|
||||||
|
Route::post('forget-password', [AuthController::class, 'forgetPassword'])->name('forget-password');
|
||||||
|
Route::post('verify-email', [AuthController::class, 'verifyEmail'])->name('verify-email');
|
||||||
|
|
||||||
|
|
||||||
|
Route::middleware('auth:sanctum')->group(function () {
|
||||||
|
|
||||||
|
Route::post('logout', [AuthController::class, 'logout'])->name('logout');
|
||||||
|
Route::get('/user', function (Request $request) {
|
||||||
|
return $request->user();
|
||||||
|
});
|
||||||
|
Route::put('reset-password', [AuthController::class, 'resetPassword'])->name('resetPassword');
|
||||||
|
|
||||||
|
Route::get('claims', [ClaimController::class, 'index']);
|
||||||
|
|
||||||
|
Route::post('search-member', [MemberController::class, 'search']);
|
||||||
|
|
||||||
|
Route::get('claim-requests', [ClaimRequestController::class, 'index'])->name('claim-requests.index');
|
||||||
|
Route::post('claim-requests', [ClaimRequestController::class, 'store'])->name('claim-requests.store');
|
||||||
|
Route::get('claim-requests/{claim_request_id}/log', [ClaimRequestController::class, 'generateLog'])->name('claim-requests.generate-log');
|
||||||
|
Route::get('claim-requests/{id}', [ClaimRequestController::class, 'show'])->name('claim-requests.show');
|
||||||
|
});
|
||||||
|
});
|
||||||
16
Modules/HospitalPortal/Routes/web.php
Normal file
16
Modules/HospitalPortal/Routes/web.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Web Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here is where you can register web routes for your application. These
|
||||||
|
| routes are loaded by the RouteServiceProvider within a group which
|
||||||
|
| contains the "web" middleware group. Now create something great!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Route::prefix('hospitalportal')->group(function() {
|
||||||
|
Route::get('/', 'HospitalPortalController@index');
|
||||||
|
});
|
||||||
0
Modules/HospitalPortal/Tests/Feature/.gitkeep
Normal file
0
Modules/HospitalPortal/Tests/Feature/.gitkeep
Normal file
0
Modules/HospitalPortal/Tests/Unit/.gitkeep
Normal file
0
Modules/HospitalPortal/Tests/Unit/.gitkeep
Normal file
31
Modules/HospitalPortal/Transformers/ClaimRequestResource.php
Normal file
31
Modules/HospitalPortal/Transformers/ClaimRequestResource.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Transformers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ClaimRequestResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
$data = parent::toArray($request);
|
||||||
|
$historiesGroupByDate = $this->histories->mapToGroups(function($history) {
|
||||||
|
return [$history->created_at->format('Y-m-d') => $history];
|
||||||
|
});
|
||||||
|
$data['histories_by_date'] = [];
|
||||||
|
foreach ($historiesGroupByDate as $date => $histories) {
|
||||||
|
$data['histories_by_date'][] = [
|
||||||
|
'date' => $date,
|
||||||
|
'histories' => $histories
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data; //parent::toArray($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\HospitalPortal\Transformers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ClaimRequestShowResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
$data = parent::toArray($request);
|
||||||
|
$historiesGroupByDate = $this->histories->mapToGroups(function($history) {
|
||||||
|
return [$history->created_at->format('Y-m-d') => $history];
|
||||||
|
});
|
||||||
|
$data['histories_by_date'] = [];
|
||||||
|
foreach ($historiesGroupByDate as $date => $histories) {
|
||||||
|
$data['histories_by_date'][] = [
|
||||||
|
'date' => $date,
|
||||||
|
'histories' => $histories
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
Modules/HospitalPortal/composer.json
Normal file
23
Modules/HospitalPortal/composer.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "nwidart/hospitalportal",
|
||||||
|
"description": "",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Widart",
|
||||||
|
"email": "n.widart@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [],
|
||||||
|
"aliases": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Modules\\HospitalPortal\\": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Modules/HospitalPortal/module.json
Normal file
13
Modules/HospitalPortal/module.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "HospitalPortal",
|
||||||
|
"alias": "hospitalportal",
|
||||||
|
"description": "",
|
||||||
|
"keywords": [],
|
||||||
|
"priority": 0,
|
||||||
|
"providers": [
|
||||||
|
"Modules\\HospitalPortal\\Providers\\HospitalPortalServiceProvider"
|
||||||
|
],
|
||||||
|
"aliases": {},
|
||||||
|
"files": [],
|
||||||
|
"requires": []
|
||||||
|
}
|
||||||
21
Modules/HospitalPortal/package.json
Normal file
21
Modules/HospitalPortal/package.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "npm run development",
|
||||||
|
"development": "mix",
|
||||||
|
"watch": "mix watch",
|
||||||
|
"watch-poll": "mix watch -- --watch-options-poll=1000",
|
||||||
|
"hot": "mix watch --hot",
|
||||||
|
"prod": "npm run production",
|
||||||
|
"production": "mix --production"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"axios": "^0.21.4",
|
||||||
|
"dotenv": "^10.0.0",
|
||||||
|
"dotenv-expand": "^5.1.0",
|
||||||
|
"laravel-mix": "^6.0.31",
|
||||||
|
"laravel-mix-merge-manifest": "^2.0.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"postcss": "^8.3.7"
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Modules/HospitalPortal/webpack.mix.js
Normal file
14
Modules/HospitalPortal/webpack.mix.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const dotenvExpand = require('dotenv-expand');
|
||||||
|
dotenvExpand(require('dotenv').config({ path: '../../.env'/*, debug: true*/}));
|
||||||
|
|
||||||
|
const mix = require('laravel-mix');
|
||||||
|
require('laravel-mix-merge-manifest');
|
||||||
|
|
||||||
|
mix.setPublicPath('../../public').mergeManifest();
|
||||||
|
|
||||||
|
mix.js(__dirname + '/Resources/assets/js/app.js', 'js/hospitalportal.js')
|
||||||
|
.sass( __dirname + '/Resources/assets/sass/app.scss', 'css/hospitalportal.css');
|
||||||
|
|
||||||
|
if (mix.inProduction()) {
|
||||||
|
mix.version();
|
||||||
|
}
|
||||||
133
Modules/Internal/Http/Controllers/Api/ClaimRequestController.php
Normal file
133
Modules/Internal/Http/Controllers/Api/ClaimRequestController.php
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Internal\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\Helper;
|
||||||
|
use App\Models\ClaimRequest;
|
||||||
|
use App\Models\Member;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Contracts\Support\Renderable;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Routing\Controller;
|
||||||
|
use Knp\Snappy\Pdf;
|
||||||
|
use Modules\Internal\Transformers\ClaimRequestResource;
|
||||||
|
use Modules\Internal\Transformers\ClaimRequestShowResource;
|
||||||
|
|
||||||
|
class ClaimRequestController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$claimRequests = ClaimRequest::query()
|
||||||
|
->when($request->search, function ($q, $search) {
|
||||||
|
$q->where('code', 'LIKE', "%".$search."%");
|
||||||
|
})
|
||||||
|
->when($request->orderBy, function ($q, $orderBy) use ($request) {
|
||||||
|
if (in_array($orderBy, ['submission_date', 'code'])) {
|
||||||
|
$q->orderBy($orderBy, $request->order);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->when(empty($request->orderBy), function ($q) {
|
||||||
|
$q->orderBy('created_at', 'desc');
|
||||||
|
})
|
||||||
|
->when($request->status, function($q, $status) {
|
||||||
|
$q->where('status', $status);
|
||||||
|
})
|
||||||
|
->with(['member', 'files'])
|
||||||
|
->paginate();
|
||||||
|
|
||||||
|
return Helper::paginateResources(ClaimRequestResource::collection($claimRequests));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the specified resource.
|
||||||
|
* @param int $id
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
$claimRequest = ClaimRequest::findOrFail($id);
|
||||||
|
$claimRequest->load([
|
||||||
|
'histories' => function ($history) {
|
||||||
|
$history->latest();
|
||||||
|
},
|
||||||
|
'files'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return Helper::responseJson(data: ClaimRequestShowResource::make($claimRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
* @param int $id
|
||||||
|
* @return Renderable
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
return view('internal::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)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approve($id)
|
||||||
|
{
|
||||||
|
$claimRequest = ClaimRequest::findOrFail($id);
|
||||||
|
$member = $claimRequest->member;
|
||||||
|
|
||||||
|
$claimRequest->status = 'approved';
|
||||||
|
$claimRequest->save();
|
||||||
|
|
||||||
|
// Store Generated Documents
|
||||||
|
$logContent = view('pdf.guaranted_leter', compact('member', 'claimRequest'));
|
||||||
|
$claimRequest->generatedDocuments()->create([
|
||||||
|
'type' => 'guarantee_letter',
|
||||||
|
'title' => 'Guarantee Letter for '. $member->full_name,
|
||||||
|
'document_type' => 'type',
|
||||||
|
'html_content' => $logContent,
|
||||||
|
'system_origin' => 'primecenter'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $claimRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -240,7 +240,7 @@ class CorporateMemberController extends Controller
|
|||||||
'currentPolicy',
|
'currentPolicy',
|
||||||
'currentPlan.corporateBenefits' => function ($benefit) use ($request) {
|
'currentPlan.corporateBenefits' => function ($benefit) use ($request) {
|
||||||
return $benefit->when($request->benefit_ids, function ($q, $ids) {
|
return $benefit->when($request->benefit_ids, function ($q, $ids) {
|
||||||
return $q->whereIn('id', $ids);
|
return $q->whereIn('benefit_id', $ids);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
'currentPlan.corporateBenefits.benefit']);
|
'currentPlan.corporateBenefits.benefit']);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use Modules\Internal\Http\Controllers\Api\AppointmentController;
|
|||||||
use Modules\Internal\Http\Controllers\Api\BenefitController;
|
use Modules\Internal\Http\Controllers\Api\BenefitController;
|
||||||
use Modules\Internal\Http\Controllers\Api\CityController;
|
use Modules\Internal\Http\Controllers\Api\CityController;
|
||||||
use Modules\Internal\Http\Controllers\Api\ClaimController;
|
use Modules\Internal\Http\Controllers\Api\ClaimController;
|
||||||
|
use Modules\Internal\Http\Controllers\Api\ClaimRequestController;
|
||||||
use Modules\Internal\Http\Controllers\Api\CorporateBenefitController;
|
use Modules\Internal\Http\Controllers\Api\CorporateBenefitController;
|
||||||
use Modules\Internal\Http\Controllers\Api\CorporateController;
|
use Modules\Internal\Http\Controllers\Api\CorporateController;
|
||||||
use Modules\Internal\Http\Controllers\Api\CorporateFormulariumController;
|
use Modules\Internal\Http\Controllers\Api\CorporateFormulariumController;
|
||||||
@@ -134,6 +135,7 @@ Route::prefix('internal')->group(function () {
|
|||||||
|
|
||||||
Route::get('claim-requests', [ClaimRequestController::class, 'index'])->name('claim-requests.index');
|
Route::get('claim-requests', [ClaimRequestController::class, 'index'])->name('claim-requests.index');
|
||||||
Route::post('claim-requests/{id}/approve', [ClaimRequestController::class, 'approve'])->name('claim-requests.approve');
|
Route::post('claim-requests/{id}/approve', [ClaimRequestController::class, 'approve'])->name('claim-requests.approve');
|
||||||
|
Route::get('claim-requests/{id}', [ClaimRequestController::class, 'show'])->name('claim-requests.show');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('province', [ProvinceController::class, 'index']);
|
Route::get('province', [ProvinceController::class, 'index']);
|
||||||
|
|||||||
33
Modules/Internal/Transformers/ClaimRequestResource.php
Normal file
33
Modules/Internal/Transformers/ClaimRequestResource.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Internal\Transformers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ClaimRequestResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
$filesGroupByType = $this->files->mapToGroups(function($file) {
|
||||||
|
return [$file->type => $file];
|
||||||
|
});
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'id' => $this->id,
|
||||||
|
'code' => $this->code,
|
||||||
|
'submission_date' => $this->submission_date,
|
||||||
|
'member' => $this->member,
|
||||||
|
'status' => $this->status ?? 'unknown',
|
||||||
|
'service_type' => $this->service_type,
|
||||||
|
'files_by_type' => $filesGroupByType
|
||||||
|
];
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Modules/Internal/Transformers/ClaimRequestShowResource.php
Normal file
40
Modules/Internal/Transformers/ClaimRequestShowResource.php
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Internal\Transformers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class ClaimRequestShowResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
$data = parent::toArray($request);
|
||||||
|
|
||||||
|
// Map Histories to Group by Dates
|
||||||
|
$historiesGroupByDate = $this->histories->mapToGroups(function($history) {
|
||||||
|
return [$history->created_at->format('Y-m-d') => $history];
|
||||||
|
});
|
||||||
|
$data['histories_by_date'] = [];
|
||||||
|
foreach ($historiesGroupByDate as $date => $histories) {
|
||||||
|
$data['histories_by_date'][] = [
|
||||||
|
'date' => $date,
|
||||||
|
'histories' => $histories
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map Files by type
|
||||||
|
$filesGroupByType = $this->files->mapToGroups(function($file) {
|
||||||
|
return [Str::slug($file->type, '_') => $file];
|
||||||
|
});
|
||||||
|
$data['files_by_type'] = $filesGroupByType;
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Events;
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\ClaimRequest;
|
||||||
use Illuminate\Broadcasting\Channel;
|
use Illuminate\Broadcasting\Channel;
|
||||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
use Illuminate\Broadcasting\PresenceChannel;
|
use Illuminate\Broadcasting\PresenceChannel;
|
||||||
@@ -14,14 +15,16 @@ class ClaimRequested
|
|||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
public $claim_request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new event instance.
|
* Create a new event instance.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(ClaimRequest $claimRequest)
|
||||||
{
|
{
|
||||||
//
|
$this->claim_request = $claimRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ namespace App\Http\Controllers\Api\OLDLMS;
|
|||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Resources\OLDLMS\MemberResource;
|
||||||
|
use App\Models\Corporate;
|
||||||
use App\Models\Member;
|
use App\Models\Member;
|
||||||
|
use App\Rules\NikRule;
|
||||||
use App\Services\ClaimService;
|
use App\Services\ClaimService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
@@ -169,4 +172,92 @@ class MembershipController extends Controller
|
|||||||
|
|
||||||
return Helper::responseJson(data: $limits);
|
return Helper::responseJson(data: $limits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function linkingRules(Request $request)
|
||||||
|
{
|
||||||
|
$corporates = Corporate::query()
|
||||||
|
->when($request->search, function ($q, $search) {
|
||||||
|
$q->where('name', 'LIKE', '%'.$search.'%');
|
||||||
|
})
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return Helper::responseJson(data: $corporates);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function linkingValidate(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'corporate_id' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$corporate = Corporate::findOrFail($request->corporate_id);
|
||||||
|
|
||||||
|
// Make Validation from Linking Rules
|
||||||
|
$linkingRulesArr = $corporate->linking_rules->toArray();
|
||||||
|
$validationRules = [];
|
||||||
|
foreach ($linkingRulesArr as $field) {
|
||||||
|
$rules = ['required']; // Default is required if in the linking_rules
|
||||||
|
if ($field == 'email') {
|
||||||
|
$rules[] = 'email';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($field == 'nric') {
|
||||||
|
$rules[] = new NikRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
$validationRules[$field] = $rules;
|
||||||
|
}
|
||||||
|
$request->validate($validationRules);
|
||||||
|
|
||||||
|
$member = Member::query()
|
||||||
|
->when(in_array('nric', $linkingRulesArr), function($q) use ($request) {
|
||||||
|
$q->where('nric', $request->nric);
|
||||||
|
})
|
||||||
|
->when(in_array('member_id', $linkingRulesArr), function($q) use ($request) {
|
||||||
|
$q->where('member_id', $request->member_id);
|
||||||
|
})
|
||||||
|
->when(in_array('name', $linkingRulesArr), function($q) use ($request) {
|
||||||
|
$q->where('name', $request->name);
|
||||||
|
})
|
||||||
|
->when(in_array('dob', $linkingRulesArr), function($q) use ($request) {
|
||||||
|
$q->where('birth_date', $request->dob);
|
||||||
|
})
|
||||||
|
->when(in_array('phone', $linkingRulesArr), function($q) use ($request) {
|
||||||
|
$q->whereHas('person', function ($person) use ($request) {
|
||||||
|
$person->where('phone', $request->phone);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
->when(in_array('email', $linkingRulesArr), function($q) use ($request) {
|
||||||
|
$q->where('email', $request->email);
|
||||||
|
})
|
||||||
|
->when(in_array('nik', $linkingRulesArr), function($q) use ($request) {
|
||||||
|
$q->whereHas('employeds', function ($employed) use ($request) {
|
||||||
|
$employed->where('corporate_id', $request->corporate_id)
|
||||||
|
->where('nik', $request->nik);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
->with([
|
||||||
|
'memberPlans' => function ($memberPlan) {
|
||||||
|
$memberPlan->latest();
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($member) {
|
||||||
|
return Helper::responseJson(data: MemberResource::make($member), message: 'Data Member ditemukan!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Helper::responseJson(data: [], message: 'Member Tidak ditemukan', statusCode: 404, status: 'error');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show($member_id)
|
||||||
|
{
|
||||||
|
$member = Member::where('member_id', $member_id)->firstOrFail();
|
||||||
|
$member->load(['currentPlan', 'memberPlans']);
|
||||||
|
$member->totalUsage = ClaimService::getMemberTotalUsage($member);
|
||||||
|
|
||||||
|
return Helper::responseJson(data: MemberResource::make($member));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
92
app/Http/Controllers/GeneratedDocumentController.php
Normal file
92
app/Http/Controllers/GeneratedDocumentController.php
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use App\Models\GeneratedDocument;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use PDF;
|
||||||
|
use Response;
|
||||||
|
|
||||||
|
class GeneratedDocumentController extends Controller
|
||||||
|
{
|
||||||
|
// Display Content from generated_documents to used by pdf generator (wkhtmltopdf)
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
$document = GeneratedDocument::findOrFail($id);
|
||||||
|
|
||||||
|
return $document->html_content.$document->html_content.$document->html_content.$document->html_content.$document->html_content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function header(Request $request)
|
||||||
|
{
|
||||||
|
return '<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre>'.json_encode($request->toArray()).'
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="width: 200px; background-color: #00be67;"> asdkjasnd </td>
|
||||||
|
<td style="width: 500px; background-color: #0a94e3;" align="center"> asjdkadsn </td>
|
||||||
|
<td style="width: 200px; background-color: #7b3f25" align="right"> qkjwenkqwjenkqwjen </td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function footer()
|
||||||
|
{
|
||||||
|
return "<h2>Footer Fatherfucker</h2>";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pdf($id)
|
||||||
|
{
|
||||||
|
// return 'fuck';
|
||||||
|
// $document = GeneratedDocument::findOrFail($id);
|
||||||
|
|
||||||
|
// $pdf = PDF::loadFile('http://localhost:8000/');
|
||||||
|
// $pdf = PDF::loadFile('http://aso-linksehat.local/');
|
||||||
|
// return $pdf->inline();
|
||||||
|
// dd(route('generated-document.show', $id));
|
||||||
|
// $pdf = PDF::loadFile(route('generated-document.show', $id));
|
||||||
|
// return $pdf->inline();
|
||||||
|
|
||||||
|
// $snappy = App::make('snappy.pdf');
|
||||||
|
// $html = '<h1>Bill</h1><p>You owe me money, dude.</p>';
|
||||||
|
// // $snappy->generateFromHtml($html, '/tmp/bill-123.pdf');
|
||||||
|
// // $snappy->generate('http://www.github.com', '/tmp/github.pdf');
|
||||||
|
// //Or output:
|
||||||
|
// return new Response(
|
||||||
|
// $snappy->getOutputFromHtml($html),
|
||||||
|
// 200,
|
||||||
|
// array(
|
||||||
|
// 'Content-Type' => 'application/pdf',
|
||||||
|
// 'Content-Disposition' => 'attachment; filename="file.pdf"'
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
|
||||||
|
$pdf = PDF::loadFile(route('generated-document.show', $id));
|
||||||
|
|
||||||
|
// $pdf->loadFile(route('generated-document.show', $id));
|
||||||
|
// $pdf->loadFile(route('generated-document.show', $id));
|
||||||
|
// $pdf->loadFile(route('generated-document.show', $id));
|
||||||
|
// $pdf->loadFile(route('generated-document.show', $id));
|
||||||
|
|
||||||
|
// $pdf->setPaper('a4')->setOrientation('landscape')->setOption('margin-bottom', 0);
|
||||||
|
|
||||||
|
// $pdf->setOption('header-html', route('pdf.header'));
|
||||||
|
// $pdf->setOption('footer-html', route('pdf.header'));
|
||||||
|
// $pdf->setOption('footer-center', 'asdasdasd');
|
||||||
|
|
||||||
|
// $pdf->setOption('footer-html', route('pdf.footer'));
|
||||||
|
// $pdf->loadHtml('asdasdasd');
|
||||||
|
|
||||||
|
return $pdf->inline();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Resources\OLDLMS;
|
namespace App\Http\Resources\OLDLMS;
|
||||||
|
|
||||||
|
use App\Services\ClaimService;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
class MemberResource extends JsonResource
|
class MemberResource extends JsonResource
|
||||||
@@ -14,6 +15,32 @@ class MemberResource extends JsonResource
|
|||||||
*/
|
*/
|
||||||
public function toArray($request)
|
public function toArray($request)
|
||||||
{
|
{
|
||||||
return parent::toArray($request);
|
// $data = parent::toArray($request);
|
||||||
|
$currentMemberPlan = $this->memberPlans?->first();
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'member_id' => $this->member_id,
|
||||||
|
'birth_date' => $this->birth_date,
|
||||||
|
'email' => $this->email,
|
||||||
|
'phone' => $this->person->phone ?? null,
|
||||||
|
'full_name' => $this->full_name,
|
||||||
|
'nric' => $this->nric,
|
||||||
|
'plan' => $currentMemberPlan ? [
|
||||||
|
'code' => $currentMemberPlan->plan->code ?? null,
|
||||||
|
'start' => $currentMemberPlan->start,
|
||||||
|
'end' => $currentMemberPlan->end,
|
||||||
|
'limit' => $this->currentPlan->limit_rules
|
||||||
|
] : null,
|
||||||
|
'policy_code' => $this->currentPolicy?->code ?? null,
|
||||||
|
'corporate' => [
|
||||||
|
'code' => $this->currentPolicy?->corporate->code ?? null,
|
||||||
|
'name' => $this->currentPolicy?->corporate->name,
|
||||||
|
'welcome_message' => $this->currentPolicy?->corporate?->welcome_message,
|
||||||
|
'help_text' => $this->currentPolicy?->corporate?->help_text,
|
||||||
|
'avatar_url' => $this->currentpolicy?->corporate?->avatar_url
|
||||||
|
],
|
||||||
|
'limit_usage' => $this->totalUsage ?? null
|
||||||
|
];
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
app/Listeners/NotifyClaimRequested.php
Normal file
35
app/Listeners/NotifyClaimRequested.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Events\ClaimRequested;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Notifications\ClaimRequestedNotification;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
|
||||||
|
class NotifyClaimRequested
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param \App\Events\ClaimRequested $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(ClaimRequested $event)
|
||||||
|
{
|
||||||
|
// TODO List Of User that should be notified about Claim that Requested
|
||||||
|
$user = User::first();
|
||||||
|
$user->notify(new ClaimRequestedNotification());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,15 @@ class Benefit extends Model
|
|||||||
'active'
|
'active'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $hidden = [
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
"deleted_at",
|
||||||
|
"created_by",
|
||||||
|
"updated_by",
|
||||||
|
"deleted_by",
|
||||||
|
];
|
||||||
|
|
||||||
public function scopeFilter($query, array $filters)
|
public function scopeFilter($query, array $filters)
|
||||||
{
|
{
|
||||||
$query->when($filters['search'] ?? false, function ($query, $search) {
|
$query->when($filters['search'] ?? false, function ($query, $search) {
|
||||||
|
|||||||
@@ -18,8 +18,11 @@ use Illuminate\Support\Str;
|
|||||||
class Claim extends Model
|
class Claim extends Model
|
||||||
{
|
{
|
||||||
use HasFactory, Blameable, SoftDeletes;
|
use HasFactory, Blameable, SoftDeletes;
|
||||||
|
|
||||||
|
protected static $code_prefix = 'CLM';
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
'claim_request_id',
|
||||||
'code',
|
'code',
|
||||||
'member_id',
|
'member_id',
|
||||||
'total_claim',
|
'total_claim',
|
||||||
@@ -54,7 +57,8 @@ class Claim extends Model
|
|||||||
|
|
||||||
static::creating(function ($model) {
|
static::creating(function ($model) {
|
||||||
try {
|
try {
|
||||||
$model->code = (string) Str::orderedUuid(); // generate uuid
|
$model->uuid = (string) Str::orderedUuid(); // generate uuid
|
||||||
|
$model->code = self::getNextCode();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
abort(500, $e->getMessage());
|
abort(500, $e->getMessage());
|
||||||
}
|
}
|
||||||
@@ -78,9 +82,9 @@ class Claim extends Model
|
|||||||
'status' => $model->status
|
'status' => $model->status
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($model->status == 'requested') {
|
// if ($model->status == 'requested') {
|
||||||
ClaimRequested::dispatch($model);
|
// ClaimRequested::dispatch($model);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if ($model->status == 'received') {
|
if ($model->status == 'received') {
|
||||||
ClaimReceived::dispatch($model);
|
ClaimReceived::dispatch($model);
|
||||||
@@ -104,6 +108,20 @@ class Claim extends Model
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getNextCode()
|
||||||
|
{
|
||||||
|
$last_number = self::withTrashed()->max('code');
|
||||||
|
$next_number = empty($last_number) ? 1 : ((int) explode('-', $last_number)[1] + 1);
|
||||||
|
|
||||||
|
return self::makeCode($next_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function makeCode($next_number)
|
||||||
|
{
|
||||||
|
return (string) self::$code_prefix .'-'. str_pad($next_number, 5, 0, STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function files()
|
public function files()
|
||||||
{
|
{
|
||||||
|
|||||||
48
app/Models/ClaimHistory.php
Normal file
48
app/Models/ClaimHistory.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\Blameable;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class ClaimHistory extends Model
|
||||||
|
{
|
||||||
|
use HasFactory, Blameable;
|
||||||
|
|
||||||
|
public $fillable = [
|
||||||
|
'claim_id',
|
||||||
|
'title',
|
||||||
|
'description',
|
||||||
|
'type',
|
||||||
|
'parent_id',
|
||||||
|
'data',
|
||||||
|
'system_origin'
|
||||||
|
];
|
||||||
|
|
||||||
|
public static $types = [
|
||||||
|
'info',
|
||||||
|
'document-request',
|
||||||
|
'document-submit'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function parent()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ClaimHistory::class, 'parent_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function childs()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Claimhistory::class, 'parent_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function claim()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Claim::class, 'claim_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function historiable()
|
||||||
|
{
|
||||||
|
return $this->morphTo();
|
||||||
|
}
|
||||||
|
}
|
||||||
143
app/Models/ClaimRequest.php
Normal file
143
app/Models/ClaimRequest.php
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Events\ClaimReceived;
|
||||||
|
use App\Events\ClaimRequested;
|
||||||
|
use App\Traits\Blameable;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Str;
|
||||||
|
|
||||||
|
class ClaimRequest extends Model
|
||||||
|
{
|
||||||
|
use HasFactory, SoftDeletes, Blameable;
|
||||||
|
|
||||||
|
protected static $code_prefix = 'CRQ';
|
||||||
|
|
||||||
|
public $fillable = [
|
||||||
|
'submission_date',
|
||||||
|
'member_id',
|
||||||
|
'status',
|
||||||
|
'claim_id'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $hidden = [
|
||||||
|
// 'created_at',
|
||||||
|
'updated_at',
|
||||||
|
'deleted_at',
|
||||||
|
'created_by',
|
||||||
|
'updated_by',
|
||||||
|
'deleted_by',
|
||||||
|
];
|
||||||
|
|
||||||
|
public static $status = [
|
||||||
|
'draft' => 'Draft',
|
||||||
|
'requested' => 'Requested',
|
||||||
|
'received' => 'Received',
|
||||||
|
'approved' => 'Approved',
|
||||||
|
'postpone' => 'Postpone',
|
||||||
|
'paid' => 'Paid',
|
||||||
|
'declined' => 'Declined'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected static function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
|
||||||
|
static::creating(function ($model) {
|
||||||
|
try {
|
||||||
|
$model->uuid = (string) Str::orderedUuid(); // generate uuid
|
||||||
|
$model->code = self::getNextCode();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
abort(500, $e->getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static::created(function ($model) {
|
||||||
|
// try {
|
||||||
|
// if (!empty($model->status) && $model->status == 'requested') {
|
||||||
|
// $model->histories()->create([
|
||||||
|
// 'title' => 'New Claim Requested',
|
||||||
|
// 'description' => "Claim Requested for Member : {$model->member->member_id} - ({$model->member->full_name})",
|
||||||
|
// 'type' => 'info'
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
// } catch (\Exception $e) {
|
||||||
|
// abort(500, $e->getMessage());
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
|
||||||
|
static::updated(function ($model) {
|
||||||
|
if ($model->hasChanges(['status'])) {
|
||||||
|
|
||||||
|
// if ($model->status == 'requested') {
|
||||||
|
// $model->histories()->create([
|
||||||
|
// 'title' => 'New Claim Requested',
|
||||||
|
// 'description' => "Claim Requested for Member : {$model->member->member_id} - ({$model->member->full_name})",
|
||||||
|
// 'type' => 'info'
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ($model->status == 'received') {
|
||||||
|
// ClaimReceived::dispatch($model);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ($model->status == 'approved') {
|
||||||
|
// ClaimApproved::dispatch($model);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ($model->status == 'postpone') {
|
||||||
|
// ClaimPostpone::dispatch($model);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ($model->status == 'paid') {
|
||||||
|
// ClaimPaid::dispatch($model);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ($model->status == 'declined') {
|
||||||
|
// ClaimDeclined::dispatch($model);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getNextCode()
|
||||||
|
{
|
||||||
|
$last_number = self::withTrashed()->max('code');
|
||||||
|
$next_number = empty($last_number) ? 1 : ((int) explode('-', $last_number)[1] + 1);
|
||||||
|
|
||||||
|
return self::makeCode($next_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function makeCode($next_number)
|
||||||
|
{
|
||||||
|
return (string) self::$code_prefix .'-'. str_pad($next_number, 5, 0, STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function claims()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Claim::class, 'claim_request_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function files()
|
||||||
|
{
|
||||||
|
return $this->morphMany(File::class, 'fileable');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generatedDocuments()
|
||||||
|
{
|
||||||
|
return $this->morphMany(GeneratedDocument::class, 'generated_documentable');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function histories()
|
||||||
|
{
|
||||||
|
return $this->morphMany(ClaimHistory::class, 'historiable');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function member()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Member::class, 'member_id', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Traits\Blameable;
|
use App\Traits\Blameable;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
@@ -23,7 +24,7 @@ class Corporate extends Model
|
|||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'linking_rules' => 'array',
|
'linking_rules' => AsArrayObject::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $appends = [
|
protected $appends = [
|
||||||
|
|||||||
@@ -16,10 +16,20 @@ class File extends Model
|
|||||||
'fileable_id',
|
'fileable_id',
|
||||||
'type',
|
'type',
|
||||||
'name',
|
'name',
|
||||||
|
'original_name',
|
||||||
'extension',
|
'extension',
|
||||||
'path',
|
'path',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $hidden = [
|
||||||
|
'created_at',
|
||||||
|
'updated_at',
|
||||||
|
'deleted_at',
|
||||||
|
'created_by',
|
||||||
|
'updated_by',
|
||||||
|
'deleted_by',
|
||||||
|
];
|
||||||
|
|
||||||
public $appends = [
|
public $appends = [
|
||||||
'url'
|
'url'
|
||||||
];
|
];
|
||||||
@@ -27,7 +37,10 @@ class File extends Model
|
|||||||
public static $file_directories = [
|
public static $file_directories = [
|
||||||
'import-temp' => 'import-temp/',
|
'import-temp' => 'import-temp/',
|
||||||
'avatar' => 'user-avatar/',
|
'avatar' => 'user-avatar/',
|
||||||
'dataDiri' => 'data-diri/'
|
'dataDiri' => 'data-diri/',
|
||||||
|
'claim-result' => 'claim/',
|
||||||
|
'claim-diagnosis' => 'claim/',
|
||||||
|
'claim-kondisi' => 'claim/',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function fileable()
|
public function fileable()
|
||||||
@@ -45,6 +58,11 @@ class File extends Model
|
|||||||
return $type . '-' . $id . '-' . Str::random(10);
|
return $type . '-' . $id . '-' . Str::random(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getNameAttribute($value)
|
||||||
|
{
|
||||||
|
return !empty($this->original_name) ? $this->original_name : ($value . '.' . $this->extension);
|
||||||
|
}
|
||||||
|
|
||||||
public function getUrlAttribute()
|
public function getUrlAttribute()
|
||||||
{
|
{
|
||||||
return url(Storage::url($this->path));
|
return url(Storage::url($this->path));
|
||||||
|
|||||||
41
app/Models/GeneratedDocument.php
Normal file
41
app/Models/GeneratedDocument.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use PDF;
|
||||||
|
|
||||||
|
class GeneratedDocument extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
public $fillable = [
|
||||||
|
'type',
|
||||||
|
'title',
|
||||||
|
'document_type',
|
||||||
|
'html_content',
|
||||||
|
'system_origin',
|
||||||
|
'parent_id'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function parent()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(GeneratedDocument::class, 'parent_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function childs()
|
||||||
|
{
|
||||||
|
return $this->hasMany(GeneratedDocument::class, 'parent_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generated_documentable()
|
||||||
|
{
|
||||||
|
return $this->morphTo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function makePdf()
|
||||||
|
{
|
||||||
|
return PDF::loadFile(route('generated-document.show', $this->id));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -141,7 +141,8 @@ class Member extends Model
|
|||||||
|
|
||||||
public function currentPlan()
|
public function currentPlan()
|
||||||
{
|
{
|
||||||
return $this->hasOneThrough(Plan::class, MemberPlan::class, 'member_id', 'id', 'id', 'plan_id')->latest();
|
return $this->hasOneThrough(Plan::class, MemberPlan::class, 'member_id', 'id', 'id', 'plan_id')
|
||||||
|
->latest(); // TODO Fix This
|
||||||
}
|
}
|
||||||
|
|
||||||
public function policies()
|
public function policies()
|
||||||
@@ -192,12 +193,13 @@ class Member extends Model
|
|||||||
|
|
||||||
public function getNameAttribute()
|
public function getNameAttribute()
|
||||||
{
|
{
|
||||||
return $this->person->name ?? null;
|
return $this->person->name ?? ($this->name ?? null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBirthDateAttribute()
|
public function getBirthDateAttribute()
|
||||||
{
|
{
|
||||||
return Carbon::parse($this->person->birth_date ?? null)->format('Y-m-d') ?? null;
|
$date = $this->person->birth_date ?? ($this->birth_date ?? null);
|
||||||
|
return !empty($date) ? Carbon::parse($date)->format('Y-m-d') : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getGenderAttribute()
|
public function getGenderAttribute()
|
||||||
|
|||||||
@@ -31,4 +31,17 @@ class MemberPlan extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(CorporatePlan::class, 'plan_id', 'code');
|
return $this->belongsTo(CorporatePlan::class, 'plan_id', 'code');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function plan()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Plan::class, 'plan_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeActive($q)
|
||||||
|
{
|
||||||
|
return $q
|
||||||
|
->where('start', '<', now())
|
||||||
|
->where('end', '>', now())
|
||||||
|
->latest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
app/Models/OLDLMS/Kota.php
Normal file
27
app/Models/OLDLMS/Kota.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models\OLDLMS;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
class Kota extends Model
|
||||||
|
{
|
||||||
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
|
const CREATED_AT = 'dCreateOn';
|
||||||
|
const UPDATED_AT = 'dUpdateOn';
|
||||||
|
const DELETED_AT = 'dDeleteOn';
|
||||||
|
|
||||||
|
protected $connection = 'oldlms';
|
||||||
|
|
||||||
|
protected $table = 'tm_kota';
|
||||||
|
|
||||||
|
protected $primaryKey = 'nID';
|
||||||
|
|
||||||
|
public function provinsi()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Provinsi::class, 'nIDProvinsi', 'nID');
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Models/OLDLMS/Provinsi.php
Normal file
22
app/Models/OLDLMS/Provinsi.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models\OLDLMS;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
class Provinsi extends Model
|
||||||
|
{
|
||||||
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
|
const CREATED_AT = 'dCreateOn';
|
||||||
|
const UPDATED_AT = 'dUpdateOn';
|
||||||
|
const DELETED_AT = 'dDeleteOn';
|
||||||
|
|
||||||
|
protected $connection = 'oldlms';
|
||||||
|
|
||||||
|
protected $table = 'tm_provinsi';
|
||||||
|
|
||||||
|
protected $primaryKey = 'nID';
|
||||||
|
}
|
||||||
@@ -182,7 +182,63 @@ class Plan extends Model
|
|||||||
return $this->belongsToMany(Benefit::class, 'corporate_benefits', 'plan_id', 'benefit_id')
|
return $this->belongsToMany(Benefit::class, 'corporate_benefits', 'plan_id', 'benefit_id')
|
||||||
->withTimestamps()
|
->withTimestamps()
|
||||||
->withPivot([
|
->withPivot([
|
||||||
// TODO corporate_benefits pivot
|
'corporate_id',
|
||||||
|
'plan_id',
|
||||||
|
'benefit_id',
|
||||||
|
'corporate_benefit_code',
|
||||||
|
'budget',
|
||||||
|
'budget_conditions',
|
||||||
|
'budget_code',
|
||||||
|
'primary_benefit_code',
|
||||||
|
'benefit_mode',
|
||||||
|
'room_class_coverage',
|
||||||
|
'max_bed_coverage',
|
||||||
|
'tolerance_parameter',
|
||||||
|
'max_room_class',
|
||||||
|
'limit_amount',
|
||||||
|
'area_limit',
|
||||||
|
'shared_benefit',
|
||||||
|
'shared_benefit_type',
|
||||||
|
'msc',
|
||||||
|
'genders',
|
||||||
|
'min_age',
|
||||||
|
'max_age',
|
||||||
|
'max_frequency_period',
|
||||||
|
'daily_frequency',
|
||||||
|
'weekly_frequency',
|
||||||
|
'monthly_frequency',
|
||||||
|
'yearly_frequency',
|
||||||
|
'custom_frequency_days',
|
||||||
|
'custom_duration_value',
|
||||||
|
'allowed_transaction_types',
|
||||||
|
'high_plan_factor',
|
||||||
|
'pre_post_treatment',
|
||||||
|
'pre_treatment_days',
|
||||||
|
'post_treatment_days',
|
||||||
|
'layer_type_1',
|
||||||
|
'layer_value_1',
|
||||||
|
'layer_type_2',
|
||||||
|
'layer_value_2',
|
||||||
|
'cashless_percentage',
|
||||||
|
'reimbursement_percentage',
|
||||||
|
'digital_percentage',
|
||||||
|
'co_share_m_percentage',
|
||||||
|
'co_share_s_percentage',
|
||||||
|
'co_share_c_percentage',
|
||||||
|
'cashless_deductible',
|
||||||
|
'reimbursement_deductible',
|
||||||
|
'digital_deductible',
|
||||||
|
'co_share_m_deductible',
|
||||||
|
'co_share_s_deductible',
|
||||||
|
'co_share_c_deductible',
|
||||||
|
'prorate_type',
|
||||||
|
'prorate_lookup',
|
||||||
|
'max_days_for_disability',
|
||||||
|
'max_period_for_disability',
|
||||||
|
'currency',
|
||||||
|
'show_benefit_item',
|
||||||
|
'show_benefit_value',
|
||||||
|
'active'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,4 +246,9 @@ class Plan extends Model
|
|||||||
{
|
{
|
||||||
return $this->hasMany(CorporateBenefit::class, 'plan_id', 'id');
|
return $this->hasMany(CorporateBenefit::class, 'plan_id', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function service()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Service::class, 'service_code', 'code');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,9 @@ class Service extends Model
|
|||||||
'name',
|
'name',
|
||||||
'description',
|
'description',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function corporateService()
|
||||||
|
{
|
||||||
|
return $this->hasMany(CorporateService::class, 'service_code', 'code');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
use Laravel\Sanctum\HasApiTokens;
|
use Laravel\Sanctum\HasApiTokens;
|
||||||
|
use Spatie\Permission\Traits\HasRoles;
|
||||||
|
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
{
|
{
|
||||||
use HasApiTokens, HasFactory, Notifiable;
|
use HasApiTokens, HasFactory, Notifiable, HasRoles;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
|
|||||||
61
app/Notifications/ClaimRequestedNotification.php
Normal file
61
app/Notifications/ClaimRequestedNotification.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
|
class ClaimRequestedNotification extends Notification implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new notification instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification's delivery channels.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function via($notifiable)
|
||||||
|
{
|
||||||
|
return ['database'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mail representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||||
|
*/
|
||||||
|
public function toMail($notifiable)
|
||||||
|
{
|
||||||
|
return (new MailMessage)
|
||||||
|
->line('The introduction to the notification.')
|
||||||
|
->action('Notification Action', url('/'))
|
||||||
|
->line('Thank you for using our application!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($notifiable)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'asdasd' => 'asdasdsd'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Rules\NikRule;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Str;
|
use Str;
|
||||||
|
|
||||||
|
|||||||
36
app/Providers/ClaimRequested.php
Normal file
36
app/Providers/ClaimRequested.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Broadcasting\Channel;
|
||||||
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
|
use Illuminate\Broadcasting\PresenceChannel;
|
||||||
|
use Illuminate\Broadcasting\PrivateChannel;
|
||||||
|
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ClaimRequested
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channels the event should broadcast on.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Broadcasting\Channel|array
|
||||||
|
*/
|
||||||
|
public function broadcastOn()
|
||||||
|
{
|
||||||
|
return new PrivateChannel('channel-name');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ namespace App\Providers;
|
|||||||
|
|
||||||
use App\Events\ClaimApproved;
|
use App\Events\ClaimApproved;
|
||||||
use App\Listeners\LogClaimJournal;
|
use App\Listeners\LogClaimJournal;
|
||||||
|
use App\Listeners\NotifyClaimRequested;
|
||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
@@ -21,9 +22,14 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
SendEmailVerificationNotification::class,
|
SendEmailVerificationNotification::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
ClaimRequested::class => [
|
||||||
|
NotifyClaimRequested::class,
|
||||||
|
],
|
||||||
|
|
||||||
ClaimApproved::class => [
|
ClaimApproved::class => [
|
||||||
LogClaimJournal::class,
|
LogClaimJournal::class,
|
||||||
]
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,6 +49,6 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function shouldDiscoverEvents()
|
public function shouldDiscoverEvents()
|
||||||
{
|
{
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
66
app/Rules/NikRule.php
Normal file
66
app/Rules/NikRule.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Rules;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Validation\Rule;
|
||||||
|
|
||||||
|
class NikRule implements Rule
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new rule instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the validation rule passes.
|
||||||
|
*
|
||||||
|
* @param string $attribute
|
||||||
|
* @param mixed $value
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function passes($attribute, $value)
|
||||||
|
{
|
||||||
|
// The NIK is a 16-digit number
|
||||||
|
if (!preg_match('/^[0-9]{16}$/', $value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // The first 6 digits represent the person's birth date in the format of YYMMDD
|
||||||
|
// $year = substr($value, 6, 2);
|
||||||
|
// $month = substr($value, 8, 2);
|
||||||
|
// $day = substr($value, 10, 2);
|
||||||
|
|
||||||
|
// // dd($year, $month, $day);
|
||||||
|
// // dd(checkdate($month, $day, "19{$year}"));
|
||||||
|
|
||||||
|
// if (!checkdate($month, $day, "19{$year}")) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // The next 2 digits represent the place of birth (province/city code)
|
||||||
|
// $provinceCode = substr($value, 6, 2);
|
||||||
|
|
||||||
|
// // The next 2 digits represent the person's gender (odd for male, even for female)
|
||||||
|
// $genderCode = substr($value, 14, 1);
|
||||||
|
|
||||||
|
// // The last 4 digits represent the sequence number of the person's birth in that day
|
||||||
|
// $sequenceNumber = substr($value, 12, 4);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation error message.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function message()
|
||||||
|
{
|
||||||
|
return ':attribute bukan valid NIK Indonesia.';
|
||||||
|
}
|
||||||
|
}
|
||||||
39
app/Services/ClaimRequestService.php
Normal file
39
app/Services/ClaimRequestService.php
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Events\ClaimApproved;
|
||||||
|
use App\Events\ClaimRequested;
|
||||||
|
use App\Models\Claim;
|
||||||
|
use App\Models\ClaimRequest;
|
||||||
|
use App\Models\Icd;
|
||||||
|
use App\Models\Member;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use DB;
|
||||||
|
use Str;
|
||||||
|
|
||||||
|
class ClaimRequestService{
|
||||||
|
|
||||||
|
public static function storeClaimRequest($member, $submissionDate = null, $status = 'requested')
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
$claimRequestData = [
|
||||||
|
'member_id' => $member->id,
|
||||||
|
'submission_date' => $submissionDate ?? now(),
|
||||||
|
'status' => $status
|
||||||
|
];
|
||||||
|
|
||||||
|
$claimRequest = ClaimRequest::create($claimRequestData);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
return $claimRequest;
|
||||||
|
} catch (\Exception $error) {
|
||||||
|
DB::rollBack();
|
||||||
|
|
||||||
|
throw new \Exception($error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -119,8 +119,6 @@ class ClaimService{
|
|||||||
->active()
|
->active()
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
// dd($benefit->toArray());
|
|
||||||
// dd(compact(['plan', 'policy', 'corporate', 'benefit']));
|
|
||||||
$limits = [
|
$limits = [
|
||||||
'total_limit' => $corporateBenefit ? $corporateBenefit->limit_amount : 0,
|
'total_limit' => $corporateBenefit ? $corporateBenefit->limit_amount : 0,
|
||||||
'frequency_limit_name' => $corporateBenefit ? $corporateBenefit->max_frequency_period_name : null,
|
'frequency_limit_name' => $corporateBenefit ? $corporateBenefit->max_frequency_period_name : null,
|
||||||
@@ -163,22 +161,21 @@ class ClaimService{
|
|||||||
return $limits;
|
return $limits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function storeClaim($member, $diagnosis, $totalClaim, $benefit, $status)
|
public static function storeClaim($member, $diagnosis = null, $totalClaim = null, $benefit = null, $status = 'requested', $claimRequest = null)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
|
||||||
$claimData = [
|
$claimData = [
|
||||||
'member_id' => $member->id,
|
'member_id' => $member->id,
|
||||||
|
'claim_request_id' => $claimRequest->id ?? null,
|
||||||
'diagnosis_id' => $diagnosis->id ?? null,
|
'diagnosis_id' => $diagnosis->id ?? null,
|
||||||
'total_claim' => $totalClaim,
|
'total_claim' => $totalClaim ?? null,
|
||||||
'currency' => 'IDR',
|
'currency' => 'IDR',
|
||||||
'plan_id' => $member->currentPlan->id,
|
'plan_id' => $member->currentPlan->id ?? null,
|
||||||
'benefit_id' => $benefit->id,
|
'benefit_id' => $benefit->id ?? null,
|
||||||
'status' => $status
|
'status' => $status
|
||||||
];
|
];
|
||||||
// $claimData[$status.'_at'] = now();
|
|
||||||
// $claimData[$status.'_by'] = auth()->user()->id ?? null;
|
|
||||||
|
|
||||||
$claim = Claim::create($claimData);
|
$claim = Claim::create($claimData);
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
"maatwebsite/excel": "^3.1",
|
"maatwebsite/excel": "^3.1",
|
||||||
"nwidart/laravel-modules": "^9.0",
|
"nwidart/laravel-modules": "^9.0",
|
||||||
"psr/simple-cache": "^1.0",
|
"psr/simple-cache": "^1.0",
|
||||||
"pusher/pusher-php-server": "^7.2"
|
"pusher/pusher-php-server": "^7.2",
|
||||||
|
"spatie/laravel-permission": "^5.9"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"barryvdh/laravel-debugbar": "^3.7",
|
"barryvdh/laravel-debugbar": "^3.7",
|
||||||
|
|||||||
1092
composer.lock
generated
Executable file → Normal file
1092
composer.lock
generated
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -188,6 +188,7 @@ return [
|
|||||||
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
|
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
|
||||||
Maatwebsite\Excel\ExcelServiceProvider::class,
|
Maatwebsite\Excel\ExcelServiceProvider::class,
|
||||||
Barryvdh\Snappy\ServiceProvider::class,
|
Barryvdh\Snappy\ServiceProvider::class,
|
||||||
|
Spatie\Permission\PermissionServiceProvider::class,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Application Service Providers...
|
* Application Service Providers...
|
||||||
|
|||||||
161
config/permission.php
Normal file
161
config/permission.php
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
'models' => [
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When using the "HasPermissions" trait from this package, we need to know which
|
||||||
|
* Eloquent model should be used to retrieve your permissions. Of course, it
|
||||||
|
* is often just the "Permission" model but you may use whatever you like.
|
||||||
|
*
|
||||||
|
* The model you want to use as a Permission model needs to implement the
|
||||||
|
* `Spatie\Permission\Contracts\Permission` contract.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'permission' => Spatie\Permission\Models\Permission::class,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When using the "HasRoles" trait from this package, we need to know which
|
||||||
|
* Eloquent model should be used to retrieve your roles. Of course, it
|
||||||
|
* is often just the "Role" model but you may use whatever you like.
|
||||||
|
*
|
||||||
|
* The model you want to use as a Role model needs to implement the
|
||||||
|
* `Spatie\Permission\Contracts\Role` contract.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'role' => Spatie\Permission\Models\Role::class,
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
'table_names' => [
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When using the "HasRoles" trait from this package, we need to know which
|
||||||
|
* table should be used to retrieve your roles. We have chosen a basic
|
||||||
|
* default value but you may easily change it to any table you like.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'roles' => 'roles',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When using the "HasPermissions" trait from this package, we need to know which
|
||||||
|
* table should be used to retrieve your permissions. We have chosen a basic
|
||||||
|
* default value but you may easily change it to any table you like.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'permissions' => 'permissions',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When using the "HasPermissions" trait from this package, we need to know which
|
||||||
|
* table should be used to retrieve your models permissions. We have chosen a
|
||||||
|
* basic default value but you may easily change it to any table you like.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'model_has_permissions' => 'model_has_permissions',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When using the "HasRoles" trait from this package, we need to know which
|
||||||
|
* table should be used to retrieve your models roles. We have chosen a
|
||||||
|
* basic default value but you may easily change it to any table you like.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'model_has_roles' => 'model_has_roles',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When using the "HasRoles" trait from this package, we need to know which
|
||||||
|
* table should be used to retrieve your roles permissions. We have chosen a
|
||||||
|
* basic default value but you may easily change it to any table you like.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'role_has_permissions' => 'role_has_permissions',
|
||||||
|
],
|
||||||
|
|
||||||
|
'column_names' => [
|
||||||
|
/*
|
||||||
|
* Change this if you want to name the related pivots other than defaults
|
||||||
|
*/
|
||||||
|
'role_pivot_key' => null, //default 'role_id',
|
||||||
|
'permission_pivot_key' => null, //default 'permission_id',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change this if you want to name the related model primary key other than
|
||||||
|
* `model_id`.
|
||||||
|
*
|
||||||
|
* For example, this would be nice if your primary keys are all UUIDs. In
|
||||||
|
* that case, name this `model_uuid`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'model_morph_key' => 'model_id',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change this if you want to use the teams feature and your related model's
|
||||||
|
* foreign key is other than `team_id`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'team_foreign_key' => 'team_id',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When set to true, the method for checking permissions will be registered on the gate.
|
||||||
|
* Set this to false, if you want to implement custom logic for checking permissions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'register_permission_check_method' => true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When set to true the package implements teams using the 'team_foreign_key'. If you want
|
||||||
|
* the migrations to register the 'team_foreign_key', you must set this to true
|
||||||
|
* before doing the migration. If you already did the migration then you must make a new
|
||||||
|
* migration to also add 'team_foreign_key' to 'roles', 'model_has_roles', and
|
||||||
|
* 'model_has_permissions'(view the latest version of package's migration file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
'teams' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When set to true, the required permission names are added to the exception
|
||||||
|
* message. This could be considered an information leak in some contexts, so
|
||||||
|
* the default setting is false here for optimum safety.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'display_permission_in_exception' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When set to true, the required role names are added to the exception
|
||||||
|
* message. This could be considered an information leak in some contexts, so
|
||||||
|
* the default setting is false here for optimum safety.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'display_role_in_exception' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default wildcard permission lookups are disabled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'enable_wildcard_permission' => false,
|
||||||
|
|
||||||
|
'cache' => [
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default all permissions are cached for 24 hours to speed up performance.
|
||||||
|
* When permissions or roles are updated the cache is flushed automatically.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'expiration_time' => \DateInterval::createFromDateString('24 hours'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The cache key used to store all permissions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'key' => 'spatie.permission.cache',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You may optionally indicate a specific cache driver to use for permission and
|
||||||
|
* role caching using any of the `store` drivers listed in the cache.php config
|
||||||
|
* file. Using 'default' here means to use the `default` set in cache.php.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'store' => 'default',
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -15,7 +15,9 @@ return new class extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('claims', function (Blueprint $table) {
|
Schema::create('claims', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
|
$table->uuid('uuid');
|
||||||
$table->string('code')->index();
|
$table->string('code')->index();
|
||||||
|
$table->foreignId('claim_request_id')->nullable()->index();
|
||||||
$table->foreignId('member_id')->index();
|
$table->foreignId('member_id')->index();
|
||||||
// $table->foreignId('diagnosis_id')->index()->nullable();
|
// $table->foreignId('diagnosis_id')->index()->nullable();
|
||||||
$table->string('currency');
|
$table->string('currency');
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('claim_requests', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->uuid('uuid');
|
||||||
|
$table->string('code')->index();
|
||||||
|
$table->dateTime('submission_date')->nullable();
|
||||||
|
$table->foreignId('member_id');
|
||||||
|
$table->string('status')->nullable();
|
||||||
|
$table->foreignId('claim_id')->nullable()->comment('After Claim is Created');
|
||||||
|
|
||||||
|
$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('claim_requests');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Spatie\Permission\PermissionRegistrar;
|
||||||
|
|
||||||
|
class CreatePermissionTables extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$tableNames = config('permission.table_names');
|
||||||
|
$columnNames = config('permission.column_names');
|
||||||
|
$teams = config('permission.teams');
|
||||||
|
|
||||||
|
if (empty($tableNames)) {
|
||||||
|
throw new \Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.');
|
||||||
|
}
|
||||||
|
if ($teams && empty($columnNames['team_foreign_key'] ?? null)) {
|
||||||
|
throw new \Exception('Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.');
|
||||||
|
}
|
||||||
|
|
||||||
|
Schema::create($tableNames['permissions'], function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id'); // permission id
|
||||||
|
$table->string('name'); // For MySQL 8.0 use string('name', 125);
|
||||||
|
$table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique(['name', 'guard_name']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create($tableNames['roles'], function (Blueprint $table) use ($teams, $columnNames) {
|
||||||
|
$table->bigIncrements('id'); // role id
|
||||||
|
if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
|
||||||
|
$table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
|
||||||
|
$table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
|
||||||
|
}
|
||||||
|
$table->string('name'); // For MySQL 8.0 use string('name', 125);
|
||||||
|
$table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);
|
||||||
|
$table->timestamps();
|
||||||
|
if ($teams || config('permission.testing')) {
|
||||||
|
$table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
|
||||||
|
} else {
|
||||||
|
$table->unique(['name', 'guard_name']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames, $teams) {
|
||||||
|
$table->unsignedBigInteger(PermissionRegistrar::$pivotPermission);
|
||||||
|
|
||||||
|
$table->string('model_type');
|
||||||
|
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||||
|
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
|
||||||
|
|
||||||
|
$table->foreign(PermissionRegistrar::$pivotPermission)
|
||||||
|
->references('id') // permission id
|
||||||
|
->on($tableNames['permissions'])
|
||||||
|
->onDelete('cascade');
|
||||||
|
if ($teams) {
|
||||||
|
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||||
|
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
|
||||||
|
|
||||||
|
$table->primary([$columnNames['team_foreign_key'], PermissionRegistrar::$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||||
|
'model_has_permissions_permission_model_type_primary');
|
||||||
|
} else {
|
||||||
|
$table->primary([PermissionRegistrar::$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||||
|
'model_has_permissions_permission_model_type_primary');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames, $teams) {
|
||||||
|
$table->unsignedBigInteger(PermissionRegistrar::$pivotRole);
|
||||||
|
|
||||||
|
$table->string('model_type');
|
||||||
|
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||||
|
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
|
||||||
|
|
||||||
|
$table->foreign(PermissionRegistrar::$pivotRole)
|
||||||
|
->references('id') // role id
|
||||||
|
->on($tableNames['roles'])
|
||||||
|
->onDelete('cascade');
|
||||||
|
if ($teams) {
|
||||||
|
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||||
|
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
|
||||||
|
|
||||||
|
$table->primary([$columnNames['team_foreign_key'], PermissionRegistrar::$pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||||
|
'model_has_roles_role_model_type_primary');
|
||||||
|
} else {
|
||||||
|
$table->primary([PermissionRegistrar::$pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||||
|
'model_has_roles_role_model_type_primary');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames) {
|
||||||
|
$table->unsignedBigInteger(PermissionRegistrar::$pivotPermission);
|
||||||
|
$table->unsignedBigInteger(PermissionRegistrar::$pivotRole);
|
||||||
|
|
||||||
|
$table->foreign(PermissionRegistrar::$pivotPermission)
|
||||||
|
->references('id') // permission id
|
||||||
|
->on($tableNames['permissions'])
|
||||||
|
->onDelete('cascade');
|
||||||
|
|
||||||
|
$table->foreign(PermissionRegistrar::$pivotRole)
|
||||||
|
->references('id') // role id
|
||||||
|
->on($tableNames['roles'])
|
||||||
|
->onDelete('cascade');
|
||||||
|
|
||||||
|
$table->primary([PermissionRegistrar::$pivotPermission, PermissionRegistrar::$pivotRole], 'role_has_permissions_permission_id_role_id_primary');
|
||||||
|
});
|
||||||
|
|
||||||
|
app('cache')
|
||||||
|
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
|
||||||
|
->forget(config('permission.cache.key'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
$tableNames = config('permission.table_names');
|
||||||
|
|
||||||
|
if (empty($tableNames)) {
|
||||||
|
throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
|
||||||
|
}
|
||||||
|
|
||||||
|
Schema::drop($tableNames['role_has_permissions']);
|
||||||
|
Schema::drop($tableNames['model_has_roles']);
|
||||||
|
Schema::drop($tableNames['model_has_permissions']);
|
||||||
|
Schema::drop($tableNames['roles']);
|
||||||
|
Schema::drop($tableNames['permissions']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('files', function (Blueprint $table) {
|
||||||
|
$table->string('original_name')->nullable()->after('name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('files', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('original_name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('claim_histories', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->morphs('historiable');
|
||||||
|
$table->string('title')->nullable();
|
||||||
|
$table->string('description')->nullable();
|
||||||
|
$table->string('type');
|
||||||
|
$table->foreignId('parent_id')->nullable();
|
||||||
|
$table->text('data')->nullable();
|
||||||
|
$table->string('system_origin')->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('claim_histories');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('generated_documents', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->morphs('generated_documentable', 'generated_document_index');
|
||||||
|
$table->string('type');
|
||||||
|
$table->string('title');
|
||||||
|
$table->string('document_type')->nullable();
|
||||||
|
$table->string('system_origin');
|
||||||
|
$table->text('html_content')->nullable();
|
||||||
|
$table->text('data')->nullable();
|
||||||
|
$table->foreignId('parent_id')->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('generated_documents');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('notifications', function (Blueprint $table) {
|
||||||
|
$table->uuid('id')->primary();
|
||||||
|
$table->string('type');
|
||||||
|
$table->morphs('notifiable');
|
||||||
|
$table->text('data');
|
||||||
|
$table->timestamp('read_at')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('notifications');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -17,18 +17,23 @@ class DummyMemberSeeder extends Seeder
|
|||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$userEmails = [
|
$userEmails = [
|
||||||
'admin@linksehat.dev',
|
'admin@linksehat.dev' => ['administrator'],
|
||||||
'manager+one@gmail.com',
|
'manager+one@gmail.com' => ['corporate-manager'],
|
||||||
'manager+two@gmail.com'
|
'manager+two@gmail.com' => ['corporate-manager'],
|
||||||
|
'hospitaladmin@gmail.com' => ['hospital-admin']
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($userEmails as $email) {
|
foreach ($userEmails as $email => $roles) {
|
||||||
User::updateOrCreate([
|
$user = User::updateOrCreate([
|
||||||
'email' => $email
|
'email' => $email
|
||||||
], [
|
], [
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'password' => Hash::make('password')
|
'password' => Hash::make('password')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (isset($roles) && count($roles)) {
|
||||||
|
$user->syncRoles($roles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
85
database/seeders/IngestProviderSeeder.php
Normal file
85
database/seeders/IngestProviderSeeder.php
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\OLDLMS\Healthcare;
|
||||||
|
use App\Models\OLDLMS\Kota;
|
||||||
|
use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Str;
|
||||||
|
|
||||||
|
class IngestProviderSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$file_path = resource_path('files/providers.csv');
|
||||||
|
$reader = ReaderEntityFactory::createReaderFromFile($file_path);
|
||||||
|
$reader->open($file_path);
|
||||||
|
|
||||||
|
$chunks = [];
|
||||||
|
$time = now();
|
||||||
|
foreach ($reader->getSheetIterator() as $sheet) {
|
||||||
|
foreach ($sheet->getRowIterator() as $index => $row) {
|
||||||
|
if ($index != 1) {
|
||||||
|
$row_data = [
|
||||||
|
'timezone' => 'Asia/Jakarta',
|
||||||
|
'nIDType' => 2,
|
||||||
|
'nIDCountry' => 1,
|
||||||
|
'sMoto' => 'Memberikan Kesehatan Pelayanan Terbaik',
|
||||||
|
'sStatus' => 1,
|
||||||
|
'sCreateBy' => 9999999,
|
||||||
|
];
|
||||||
|
|
||||||
|
$row_data['nIDHealthCareCategory'] = 1; // RS
|
||||||
|
|
||||||
|
foreach ($row->getCells() as $cell_index => $cell) {
|
||||||
|
if ($cell_index == 2) {
|
||||||
|
$namaKota = $cell->getValue();
|
||||||
|
$kota = Kota::where('sKota', 'LIKE', '%'.$namaKota.'%')->first();
|
||||||
|
if ($kota) {
|
||||||
|
$row_data['nIDKota'] = $kota->nID;
|
||||||
|
$row_data['nIDProvinsi'] = $kota->nIDProvinsi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($cell_index == 3) {
|
||||||
|
$row_data['sHealthCare'] = $cell->getValue();
|
||||||
|
$row_data['sSlug'] = Str::slug($row_data['sHealthCare']);
|
||||||
|
}
|
||||||
|
else if ($cell_index == 4) {
|
||||||
|
$row_data['sAlamat'] = $cell->getValue();
|
||||||
|
}
|
||||||
|
else if ($cell_index == 5) {
|
||||||
|
$row_data['sTelp'] = $cell->getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// $chunks[] = $row_data;
|
||||||
|
try {
|
||||||
|
// Transaction
|
||||||
|
Healthcare::create($row_data);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(\Exception $e) {
|
||||||
|
dd($row_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($chunks && count($chunks) == 100) {
|
||||||
|
Healthcare::insert($chunks);
|
||||||
|
$chunks = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($chunks && count($chunks) > 0) {
|
||||||
|
Healthcare::insert($chunks);
|
||||||
|
$chunks = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
database/seeders/RoleSeeder.php
Normal file
30
database/seeders/RoleSeeder.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Spatie\Permission\Models\Role;
|
||||||
|
|
||||||
|
class RoleSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$roles = [
|
||||||
|
'administrator',
|
||||||
|
'corporate-manager',
|
||||||
|
'hospital-admin'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($roles as $name) {
|
||||||
|
Role::create([
|
||||||
|
'name' => $name
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,10 +16,7 @@ import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate
|
|||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
const itemList = [
|
const itemList = [
|
||||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '08:00 WIB' },
|
{ info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
|
||||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '09:00 WIB' },
|
|
||||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '10:00 WIB' },
|
|
||||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '11:00 WIB' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|||||||
@@ -24,10 +24,7 @@ const ItemStyle = styled(Card)(({ theme }) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const itemList = [
|
const itemList = [
|
||||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '08:00 WIB' },
|
{ info: 'Mohon lengkapi dokumen Alison Born', date: 'Selasa, 13 Februari 23', time: '09:43 WIB' },
|
||||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '09:00 WIB' },
|
|
||||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '10:00 WIB' },
|
|
||||||
{ info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '11:00 WIB' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|||||||
296
frontend/dashboard/src/components/dialogs/DialogDetailClaim.tsx
Normal file
296
frontend/dashboard/src/components/dialogs/DialogDetailClaim.tsx
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
// @mui
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Box,
|
||||||
|
Stepper,
|
||||||
|
Step,
|
||||||
|
StepLabel,
|
||||||
|
Card,
|
||||||
|
Typography,
|
||||||
|
Divider,
|
||||||
|
Stack,
|
||||||
|
CircularProgress,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { Add } from '@mui/icons-material';
|
||||||
|
// components
|
||||||
|
import MuiDialog from '@/components/MuiDialog';
|
||||||
|
// theme
|
||||||
|
import palette from '@/theme/palette';
|
||||||
|
// React
|
||||||
|
import { ReactElement, useEffect, useState } from 'react';
|
||||||
|
import { fDate } from '@/utils/formatTime';
|
||||||
|
import { addMinutes, format } from 'date-fns';
|
||||||
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
import { enqueueSnackbar } from 'notistack';
|
||||||
|
import Iconify from '../Iconify';
|
||||||
|
|
||||||
|
type DataContent = {
|
||||||
|
claim: object;
|
||||||
|
isLoading: boolean;
|
||||||
|
handleDownloadLog: void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MuiDialogProps = {
|
||||||
|
title?: {
|
||||||
|
name?: string;
|
||||||
|
icon?: string;
|
||||||
|
};
|
||||||
|
openDialog: boolean;
|
||||||
|
setOpenDialog: Function;
|
||||||
|
content?: ReactElement;
|
||||||
|
data?: DataContent[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const steps = ['Review', 'Approval', 'Disbursement'];
|
||||||
|
|
||||||
|
const DialogDetailClaim = ({ title, openDialog, setOpenDialog, data }: MuiDialogProps) => {
|
||||||
|
const claim = data.claim ?? null;
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// Step
|
||||||
|
const [currentStep, setCurrentStep] = useState(0);
|
||||||
|
useEffect(
|
||||||
|
function () {
|
||||||
|
if (claim?.status == 'requested') {
|
||||||
|
setCurrentStep(0);
|
||||||
|
}
|
||||||
|
if (claim?.status == 'approved') {
|
||||||
|
setCurrentStep(1);
|
||||||
|
}
|
||||||
|
if (claim?.status == 'closed') {
|
||||||
|
setCurrentStep(2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[data]
|
||||||
|
);
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// Date Stamp
|
||||||
|
let currentDate = null;
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// Download LOG
|
||||||
|
const [loadingDownloadLog, setLoadingDownloadLog] = useState(false);
|
||||||
|
const handleDownloadLog = async (claimRequest) => {
|
||||||
|
setLoadingDownloadLog(true);
|
||||||
|
await data.handleDownloadLog(claimRequest).then(() => {
|
||||||
|
setLoadingDownloadLog(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
// Handle Upload Invoice
|
||||||
|
const handleUploadInvoice = () => {
|
||||||
|
enqueueSnackbar('Something went wrong, please contact Link Medis Sehat', { variant: 'error' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const getContent = () => (
|
||||||
|
<>
|
||||||
|
{data.isLoading && (
|
||||||
|
<Stack alignItems="center" justifyContent="space-between" sx={{ p: 4 }}>
|
||||||
|
<CircularProgress />
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!data.isLoading && (
|
||||||
|
<>
|
||||||
|
<Stack
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="space-between"
|
||||||
|
direction="row"
|
||||||
|
sx={{ marginTop: 1 }}
|
||||||
|
>
|
||||||
|
<Typography variant="subtitle1" sx={{ height: 'max-content' }}>
|
||||||
|
Claim Request
|
||||||
|
</Typography>
|
||||||
|
<Stack>
|
||||||
|
<Typography variant="caption">Submission date</Typography>
|
||||||
|
{/* {JSON.stringify(data)} */}
|
||||||
|
<Typography variant="caption">
|
||||||
|
{claim.created_at && fDate(claim.created_at)}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
<Box sx={{ width: '100%', marginTop: 2 }}>
|
||||||
|
<Stepper alternativeLabel activeStep={currentStep ?? 0}>
|
||||||
|
{steps.map((label) => (
|
||||||
|
<Step key={label}>
|
||||||
|
<StepLabel>{label}</StepLabel>
|
||||||
|
</Step>
|
||||||
|
))}
|
||||||
|
</Stepper>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* { claim.status == 'approved' && (
|
||||||
|
<Stack sx={{ marginTop: 4}}>
|
||||||
|
<LoadingButton loading={false}
|
||||||
|
variant="contained"
|
||||||
|
startIcon={<Add />}
|
||||||
|
fullWidth
|
||||||
|
// sx={{ typography: 'subtitle2', borderColor: '#F5F5F5' }}
|
||||||
|
onClick={() => {handleUploadInvoice()}}
|
||||||
|
>
|
||||||
|
Upload Invoice
|
||||||
|
</LoadingButton>
|
||||||
|
</Stack>
|
||||||
|
)} */}
|
||||||
|
|
||||||
|
{claim.histories_by_date &&
|
||||||
|
claim.histories_by_date.map((historiesByDate) => (
|
||||||
|
<Stack key={historiesByDate.date}>
|
||||||
|
<Stack marginTop={2}>
|
||||||
|
<Typography variant="subtitle1" paddingY={2}>
|
||||||
|
{fDate(historiesByDate.date)}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Stack direction="row" spacing={2}>
|
||||||
|
<Divider orientation="vertical" flexItem sx={{ borderStyle: 'dashed' }} />
|
||||||
|
<Stack spacing={2} sx={{ flex: 1, maxWidth: '100%' }}>
|
||||||
|
{historiesByDate.histories &&
|
||||||
|
historiesByDate.histories.map((history) => (
|
||||||
|
<Stack key={history.id}>
|
||||||
|
{/* ---------------------------------TYPE INFO------------------------------------ */}
|
||||||
|
<Card sx={{ paddingY: 2, paddingX: 3 }}>
|
||||||
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography variant="body1">
|
||||||
|
{fDate(history.created_at, 'HH:mm')} WIB
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
backgroundColor: palette.light.warning.lighter,
|
||||||
|
color: palette.light.warning.dark,
|
||||||
|
borderColor: palette.light.warning.dark,
|
||||||
|
border: '1px solid',
|
||||||
|
borderRadius: '6px',
|
||||||
|
padding: 1,
|
||||||
|
}}
|
||||||
|
variant="caption"
|
||||||
|
>
|
||||||
|
Request
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
<Divider sx={{ marginY: 2 }} />
|
||||||
|
<Stack>
|
||||||
|
<Typography variant="subtitle2" color="#404040">
|
||||||
|
{history.title}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="caption"
|
||||||
|
color="#757575"
|
||||||
|
sx={{ marginTop: 2, marginBottom: 1 }}
|
||||||
|
>
|
||||||
|
{history.description}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<Stack direction="row" spacing={2} sx={{ marginTop: 2 }}>
|
||||||
|
<Divider orientation="vertical" flexItem sx={{ borderStyle: 'dashed' }} />
|
||||||
|
<Stack spacing={2} sx={{ flex: 1, maxWidth: '100%' }}>
|
||||||
|
{/* ---------------------------------TYPE INFO------------------------------------ */}
|
||||||
|
<Card sx={{ paddingY: 2, paddingX: 3 }}>
|
||||||
|
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||||
|
<Typography variant="body1" fontWeight={600}>
|
||||||
|
<Iconify icon="eva:file-text-fill"></Iconify> Dokumen Kelengkapan
|
||||||
|
</Typography>
|
||||||
|
{/* <Typography
|
||||||
|
sx={{
|
||||||
|
backgroundColor: palette.light.warning.lighter,
|
||||||
|
color: palette.light.warning.dark,
|
||||||
|
borderColor: palette.light.warning.dark,
|
||||||
|
border: '1px solid',
|
||||||
|
borderRadius: '6px',
|
||||||
|
padding: 1,
|
||||||
|
}}
|
||||||
|
variant="caption"
|
||||||
|
>
|
||||||
|
Dokumen
|
||||||
|
</Typography> */}
|
||||||
|
</Stack>
|
||||||
|
<Divider sx={{ marginY: 2 }} />
|
||||||
|
|
||||||
|
<Typography fontWeight="600">Kondisi</Typography>
|
||||||
|
<Stack>
|
||||||
|
<Stack
|
||||||
|
// divider={<Divider orientation="horizontal" flexItem />}
|
||||||
|
spacing={1}
|
||||||
|
sx={{ marginY: 2 }}
|
||||||
|
>
|
||||||
|
{claim.files_by_type?.claim_kondisi &&
|
||||||
|
claim.files_by_type.claim_kondisi.map((file, index) => (
|
||||||
|
<Stack direction="row" justifyContent={'space-between'} key={index}>
|
||||||
|
<a href={file.url} target="_blank" style={{ textDecoration: 'none' }}>
|
||||||
|
<Typography sx={{ color: 'text.secondary' }} variant="subtitle2">
|
||||||
|
- {file.name}
|
||||||
|
</Typography>
|
||||||
|
</a>
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Typography fontWeight="600">Diagnosa</Typography>
|
||||||
|
<Stack
|
||||||
|
// divider={<Divider orientation="horizontal" flexItem />}
|
||||||
|
spacing={1}
|
||||||
|
sx={{ marginY: 2 }}
|
||||||
|
>
|
||||||
|
{claim.files_by_type?.claim_diagnosis &&
|
||||||
|
claim.files_by_type.claim_diagnosis.map((file, index) => (
|
||||||
|
<Stack direction="row" justifyContent={'space-between'} key={index}>
|
||||||
|
<a href={file.url} target="_blank" style={{ textDecoration: 'none' }}>
|
||||||
|
<Typography sx={{ color: 'text.secondary' }} variant="subtitle2">
|
||||||
|
- {file.name}
|
||||||
|
</Typography>
|
||||||
|
</a>
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Typography fontWeight="600">Hasil</Typography>
|
||||||
|
<Stack
|
||||||
|
divider={<Divider orientation="horizontal" flexItem />}
|
||||||
|
spacing={1}
|
||||||
|
sx={{ marginY: 2 }}
|
||||||
|
>
|
||||||
|
{claim.files_by_type?.result &&
|
||||||
|
claim.files_by_type.result.map((file, index) => (
|
||||||
|
<Stack direction="row" justifyContent={'space-between'} key={index}>
|
||||||
|
<a href={file.url} target="_blank" style={{ textDecoration: 'none' }}>
|
||||||
|
<Typography sx={{ color: 'text.secondary' }} variant="subtitle2">
|
||||||
|
- {file.name}
|
||||||
|
</Typography>
|
||||||
|
</a>
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MuiDialog
|
||||||
|
title={title}
|
||||||
|
openDialog={openDialog}
|
||||||
|
setOpenDialog={setOpenDialog}
|
||||||
|
content={getContent()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DialogDetailClaim;
|
||||||
@@ -58,6 +58,13 @@ const navConfig = [
|
|||||||
{ title: 'Hospitals', path: '/hospitals' },
|
{ title: 'Hospitals', path: '/hospitals' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'LOG REQUEST',
|
||||||
|
path: '/claim-requests',
|
||||||
|
// children: [
|
||||||
|
// { title: 'Request', path: '/case-request' },
|
||||||
|
// ],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'CASE MANAGEMENT',
|
title: 'CASE MANAGEMENT',
|
||||||
path: '/claims',
|
path: '/claims',
|
||||||
|
|||||||
64
frontend/dashboard/src/pages/ClaimRequests/CreateUpdate.tsx
Executable file
64
frontend/dashboard/src/pages/ClaimRequests/CreateUpdate.tsx
Executable file
@@ -0,0 +1,64 @@
|
|||||||
|
import * as Yup from 'yup';
|
||||||
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
|
import { Autocomplete, Button, Card, Collapse, Container, Divider, Grid, Stack, Table, TableBody, TableCell, TableRow, TextField, Typography } from '@mui/material';
|
||||||
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
|
import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
|
||||||
|
import { FormProvider, RHFCheckbox, RHFSelect, RHFTextField } from '../../components/hook-form';
|
||||||
|
import Page from '../../components/Page';
|
||||||
|
import useSettings from '../../hooks/useSettings';
|
||||||
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
import MemberSelectDialog from '../../components/dialogs/MemberSelectDialog';
|
||||||
|
import { styled } from '@mui/system';
|
||||||
|
import axios from '../../utils/axios';
|
||||||
|
import { enqueueSnackbar } from 'notistack';
|
||||||
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
import { fCurrency } from '../../utils/formatNumber';
|
||||||
|
import Iconify from '../../components/Iconify';
|
||||||
|
import Form from './Form';
|
||||||
|
|
||||||
|
export default function ClaimsCreateUpdate() {
|
||||||
|
|
||||||
|
const { themeStretch } = useSettings();
|
||||||
|
const { id } = useParams();
|
||||||
|
|
||||||
|
const isEdit = id ? true : false;
|
||||||
|
|
||||||
|
const [currentClaim, setCurrentClaim] = useState();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isEdit) {
|
||||||
|
axios.get('/claims/' + id).then((res) => {
|
||||||
|
// console.log('Yeet', res.data);
|
||||||
|
setCurrentClaim(res.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page title={isEdit ? `Edit Claim : ${currentClaim?.id}` : "Create New Claim"}>
|
||||||
|
<Container maxWidth={themeStretch ? false : 'xl'}>
|
||||||
|
<Stack direction="row" alignItems="center">
|
||||||
|
<HeaderBreadcrumbs
|
||||||
|
heading={
|
||||||
|
!isEdit
|
||||||
|
? 'Create New Claim'
|
||||||
|
: `Edit Claim : ${currentClaim?.code}`
|
||||||
|
}
|
||||||
|
links={[
|
||||||
|
{ name: 'Dashboard', href: '/dashboard' },
|
||||||
|
{
|
||||||
|
name: 'Claim',
|
||||||
|
href: '/claims',
|
||||||
|
},
|
||||||
|
{ name: !isEdit ? 'Create' : currentClaim?.id ?? '' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Form isEdit={isEdit} currentClaim={currentClaim} />
|
||||||
|
</Container>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
||||||
596
frontend/dashboard/src/pages/ClaimRequests/Form.tsx
Normal file
596
frontend/dashboard/src/pages/ClaimRequests/Form.tsx
Normal file
@@ -0,0 +1,596 @@
|
|||||||
|
import * as Yup from 'yup';
|
||||||
|
import { useSnackbar } from 'notistack';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
import axios from '../../utils/axios';
|
||||||
|
import { FormProvider, RHFTextField } from '../../components/hook-form';
|
||||||
|
import {
|
||||||
|
Autocomplete,
|
||||||
|
Button,
|
||||||
|
Grid,
|
||||||
|
Stack,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableRow,
|
||||||
|
TextField,
|
||||||
|
Typography,
|
||||||
|
useTheme,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
IconButton,
|
||||||
|
ListItemAvatar,
|
||||||
|
Avatar,
|
||||||
|
ListItemText,
|
||||||
|
} from '@mui/material';
|
||||||
|
import Iconify from '../../components/Iconify';
|
||||||
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
import { fCurrency } from '../../utils/formatNumber';
|
||||||
|
import MemberSelectDialog from '../../components/dialogs/MemberSelectDialog';
|
||||||
|
import { Add, DeleteOutline } from '@mui/icons-material';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isEdit: boolean;
|
||||||
|
currentClaim?: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ClaimForm({ isEdit, currentClaim }: Props) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
|
const NewCorporateSchema = Yup.object().shape({
|
||||||
|
name: Yup.string().required('Name is required'),
|
||||||
|
code: Yup.string().required('Corporate Code is required'),
|
||||||
|
active: Yup.boolean().required('Corporate Status is required'),
|
||||||
|
// file: Yup.boolean().required('Corporate Status is required'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultValues = useMemo(
|
||||||
|
() => ({
|
||||||
|
member: currentClaim?.member || {},
|
||||||
|
member_id: currentClaim?.member_id || null,
|
||||||
|
diagnosis_id: currentClaim?.diagnosis_id || null,
|
||||||
|
total_claim: currentClaim?.total_claim || 0,
|
||||||
|
}),
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
[currentClaim]
|
||||||
|
);
|
||||||
|
|
||||||
|
const methods = useForm<any>({
|
||||||
|
resolver: yupResolver(NewCorporateSchema),
|
||||||
|
defaultValues,
|
||||||
|
});
|
||||||
|
const {
|
||||||
|
reset,
|
||||||
|
watch,
|
||||||
|
control,
|
||||||
|
setValue,
|
||||||
|
getValues,
|
||||||
|
setError,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { isSubmitting },
|
||||||
|
} = methods;
|
||||||
|
|
||||||
|
const values = watch();
|
||||||
|
|
||||||
|
const [isCheckingLimit, setIsCheckingLimit] = useState(false);
|
||||||
|
const [isEligible, setIsEligible] = useState(false);
|
||||||
|
const [memberBenefits, setMemberBenefits] = useState([]);
|
||||||
|
const [diagnosisOption, setDiagnosisOption] = useState([]);
|
||||||
|
const [isMemberDialogOpen, setIsMemberDialogOpen] = useState(false);
|
||||||
|
const [member, setMember] = useState({})
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('defaultValues', defaultValues);
|
||||||
|
if (isEdit && currentClaim) {
|
||||||
|
reset(defaultValues);
|
||||||
|
setMember(defaultValues.member)
|
||||||
|
}
|
||||||
|
if (!isEdit) {
|
||||||
|
reset(defaultValues);
|
||||||
|
setMember(defaultValues.member)
|
||||||
|
}
|
||||||
|
}, [isEdit, currentClaim]);
|
||||||
|
|
||||||
|
const fileSelected = (event, type) => {
|
||||||
|
const files = event.target.files;
|
||||||
|
const currentFiles = getValues(`uploaded_files.${type}`) ?? [];
|
||||||
|
|
||||||
|
setValue(`uploaded_files.${type}`, [...currentFiles, ...files]);
|
||||||
|
|
||||||
|
console.log('currentFiles', getValues('uploaded_files'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const memberSelected = (member) => {
|
||||||
|
setMember(member)
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkLimit = async () => {
|
||||||
|
console.log('CHECKING LIMIT');
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async (data: any) => {
|
||||||
|
try {
|
||||||
|
if (!isEdit) {
|
||||||
|
const response = await axios.post('/claims', data);
|
||||||
|
} else {
|
||||||
|
const response = await axios.put('/claims/' + currentClaim?.id ?? '', data);
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
enqueueSnackbar(
|
||||||
|
!isEdit ? 'Organizations Created Successfully!' : 'Organizations Udpated Successfully!',
|
||||||
|
{ variant: 'success' }
|
||||||
|
);
|
||||||
|
navigate('/claims');
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error && error.response.status === 422) {
|
||||||
|
for (const [key, value] of Object.entries(error.response.data.errors)) {
|
||||||
|
setError(key, { message: value[0] });
|
||||||
|
enqueueSnackbar(value[0] ?? 'Failed Processing Request', { variant: 'error' });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
enqueueSnackbar(error.message ?? 'Failed Processing Request', { variant: 'error' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ascent = document?.querySelector('ascent');
|
||||||
|
if (ascent != null) {
|
||||||
|
ascent.innerHTML = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function generate(files, element: React.ReactElement) {
|
||||||
|
return files.map((value) =>
|
||||||
|
React.cloneElement(element, {
|
||||||
|
key: value,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const headStyle = {};
|
||||||
|
return (
|
||||||
|
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<Stack spacing={3}>
|
||||||
|
<Typography variant="h6">Member</Typography>
|
||||||
|
|
||||||
|
<Stack spacing={2} direction="row">
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<RHFTextField
|
||||||
|
name="member_id"
|
||||||
|
label="Member"
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
value={member?.name || ''}
|
||||||
|
InputProps={{
|
||||||
|
readOnly: true,
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
if (!isEdit) setIsMemberDialogOpen(true);
|
||||||
|
if (isEdit) enqueueSnackbar('Cannot Change Member', { variant: 'error' });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
{/* <Grid item xs={2}>
|
||||||
|
<Button variant="outlined" fullWidth sx={{ p: 1.8 }} onClick={() => {
|
||||||
|
setIsMemberDialogOpen(true)
|
||||||
|
}}>
|
||||||
|
{member ? 'Change' : 'Search'}
|
||||||
|
</Button>
|
||||||
|
</Grid> */}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{member?.id && (
|
||||||
|
<Stack>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<Table border="light-700">
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Name
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">{member?.full_name}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
DOB
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">
|
||||||
|
{member?.birth_date} ({member?.age + ' years'})
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Marital Status
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">{member?.marital_status}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Record Type
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">{member?.record_type}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Principal ID
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">
|
||||||
|
{member?.principal_id} (
|
||||||
|
{member?.relation_with_principal})
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<Table border="light-700">
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Plan
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">{member?.current_plan?.code}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Active
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">
|
||||||
|
{member?.current_plan?.start} -{' '}
|
||||||
|
{member?.current_plan?.end} (Active)
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Corporate Limit
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">
|
||||||
|
{fCurrency(0)} / {fCurrency(member?.current_plan?.limit_rules)}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Plan Usage
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">
|
||||||
|
{fCurrency(0)} / {fCurrency(member?.current_plan?.limit_rules)}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
name="benefit"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<Autocomplete
|
||||||
|
options={memberBenefits}
|
||||||
|
getOptionLabel={(option) =>
|
||||||
|
option ? `#${option.id} (${option.code}) ${option.description}` : ''
|
||||||
|
}
|
||||||
|
value={value || ''}
|
||||||
|
onChange={(event: any, newValue: any) => {
|
||||||
|
setValue('benefit_id', newValue?.id);
|
||||||
|
onChange(newValue);
|
||||||
|
}}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField
|
||||||
|
name="benefit"
|
||||||
|
{...params}
|
||||||
|
label="Benefit"
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
// onKeyPress={(event) => {
|
||||||
|
// if (event.key === 'Enter')
|
||||||
|
// searchDiagnosis(event.target.value)
|
||||||
|
// }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
name="diagnosis"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<Autocomplete
|
||||||
|
options={diagnosisOption}
|
||||||
|
getOptionLabel={(option) => (option ? `(${option.code}) ${option.name}` : '')}
|
||||||
|
value={value || ''}
|
||||||
|
onChange={(event: any, newValue: any) => {
|
||||||
|
setValue('diagnosis_id', newValue?.id);
|
||||||
|
// setValue('diagnosis', newValue)
|
||||||
|
onChange(newValue);
|
||||||
|
}}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField
|
||||||
|
name="diagnosis"
|
||||||
|
{...params}
|
||||||
|
label="Diagnosis"
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
onKeyPress={(event) => {
|
||||||
|
if (event.key === 'Enter') searchDiagnosis(event.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isCheckingLimit && (
|
||||||
|
<Stack
|
||||||
|
sx={{
|
||||||
|
backgroundColor: 'gray',
|
||||||
|
paddingY: 1,
|
||||||
|
paddingX: 1.5,
|
||||||
|
mb: 2,
|
||||||
|
borderRadius: '3-xl',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Checking */}
|
||||||
|
<Typography sx={{ typography: 'caption', display: 'flex', alignItems: 'center' }}>
|
||||||
|
<Iconify
|
||||||
|
icon="bxs:info-circle"
|
||||||
|
width={12}
|
||||||
|
height={13}
|
||||||
|
sx={{ color: '#424242', marginRight: '6px' }}
|
||||||
|
/>
|
||||||
|
<Typography variant="caption" component="span">
|
||||||
|
Please Wait, Checking Eligibilty
|
||||||
|
</Typography>
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
{false && isCheckingLimit == false && isEligible == null && (
|
||||||
|
<Stack
|
||||||
|
sx={{
|
||||||
|
backgroundColor: 'gray',
|
||||||
|
paddingY: 1,
|
||||||
|
paddingX: 1.5,
|
||||||
|
mb: 2,
|
||||||
|
borderRadius: '3-xl',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* No Data Selected */}
|
||||||
|
<Typography sx={{ typography: 'caption', display: 'flex', alignItems: 'center' }}>
|
||||||
|
<Iconify
|
||||||
|
icon="bxs:info-circle"
|
||||||
|
width={12}
|
||||||
|
height={13}
|
||||||
|
sx={{ color: '#424242', marginRight: '6px' }}
|
||||||
|
/>
|
||||||
|
<Typography variant="caption" component="span">
|
||||||
|
Please Select Diagnosis !
|
||||||
|
</Typography>
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
{!isCheckingLimit && isEligible !== null && isEligible && (
|
||||||
|
<Stack
|
||||||
|
sx={{
|
||||||
|
backgroundColor: '#B2E8E8',
|
||||||
|
paddingY: 1,
|
||||||
|
paddingX: 1.5,
|
||||||
|
mb: 2,
|
||||||
|
borderRadius: '3-xl',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Eligible */}
|
||||||
|
<Typography sx={{ typography: 'caption', display: 'flex', alignItems: 'center' }}>
|
||||||
|
<Iconify
|
||||||
|
icon="bxs:lock-alt"
|
||||||
|
width={12}
|
||||||
|
height={13}
|
||||||
|
sx={{ color: '#424242', marginRight: '6px' }}
|
||||||
|
/>
|
||||||
|
<Typography variant="caption" component="span">
|
||||||
|
Diagnosis is Eligible
|
||||||
|
</Typography>
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ typography: 'caption', color: '#637381' }}>
|
||||||
|
125.000.000 / 125.000.000
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
{!isCheckingLimit && isEligible !== null && !isEligible && (
|
||||||
|
<Stack
|
||||||
|
sx={{
|
||||||
|
backgroundColor: '#B2E8E8',
|
||||||
|
paddingY: 1,
|
||||||
|
paddingX: 1.5,
|
||||||
|
mb: 2,
|
||||||
|
borderRadius: '3-xl',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Not Eligible */}
|
||||||
|
{/* <Typography sx={{ typography: 'caption', display: 'flex', alignItems: 'center' }}>
|
||||||
|
<Iconify
|
||||||
|
icon="bxs:lock-alt"
|
||||||
|
width={12}
|
||||||
|
height={13}
|
||||||
|
sx={{ color: '#424242', marginRight: '6px' }}
|
||||||
|
/>
|
||||||
|
<Typography variant="caption" component="span">
|
||||||
|
Not Eligible
|
||||||
|
</Typography>
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ typography: 'caption', color: '#637381' }}>
|
||||||
|
125.000.000 / 125.000.000
|
||||||
|
</Typography> */}
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<RHFTextField type="number" name="total_claim" label="Total Claim" />
|
||||||
|
|
||||||
|
{isEdit && (
|
||||||
|
<React.Fragment>
|
||||||
|
<Typography variant="h6">Documents</Typography>
|
||||||
|
|
||||||
|
<List>
|
||||||
|
{(getValues('uploaded_files.invoice') && getValues('uploaded_files.invoice').length
|
||||||
|
? getValues('uploaded_files.invoice')
|
||||||
|
: []
|
||||||
|
).map((file, index) => (
|
||||||
|
<ListItem
|
||||||
|
secondaryAction={
|
||||||
|
<IconButton edge="end" aria-label="delete">
|
||||||
|
<DeleteOutline />
|
||||||
|
</IconButton>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
{/* <FileIcon /> */}
|
||||||
|
I
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary={file.name} secondary={file.type} />
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
startIcon={<Add />}
|
||||||
|
component="label"
|
||||||
|
sx={{ paddingY: 2, width: '100%', ':hover': { border: 'none' } }}
|
||||||
|
>
|
||||||
|
Invoice
|
||||||
|
<input
|
||||||
|
name="invoice"
|
||||||
|
hidden
|
||||||
|
accept="image/*,application/pdf"
|
||||||
|
multiple
|
||||||
|
type="file"
|
||||||
|
onChange={(event) => {
|
||||||
|
fileSelected(event, 'invoice');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
<List>
|
||||||
|
{(getValues('uploaded_files.prescription') && getValues('uploaded_files.prescription').length
|
||||||
|
? getValues('uploaded_files.prescription')
|
||||||
|
: []
|
||||||
|
).map((file, index) => (
|
||||||
|
<ListItem
|
||||||
|
secondaryAction={
|
||||||
|
<IconButton edge="end" aria-label="delete">
|
||||||
|
<DeleteOutline />
|
||||||
|
</IconButton>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
{/* <FileIcon /> */}
|
||||||
|
P
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary={file.name} secondary={file.type} />
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
startIcon={<Add />}
|
||||||
|
component="label"
|
||||||
|
sx={{ paddingY: 2, width: '100%', ':hover': { border: 'none' } }}
|
||||||
|
>
|
||||||
|
Prescription
|
||||||
|
<input
|
||||||
|
name="prescription"
|
||||||
|
hidden
|
||||||
|
accept="image/*,application/pdf"
|
||||||
|
multiple
|
||||||
|
type="file"
|
||||||
|
onChange={(event) => {
|
||||||
|
fileSelected(event, 'prescription');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<List>
|
||||||
|
{(getValues('uploaded_files.diagnosis') && getValues('uploaded_files.diagnosis').length
|
||||||
|
? getValues('uploaded_files.diagnosis')
|
||||||
|
: []
|
||||||
|
).map((file, index) => (
|
||||||
|
<ListItem
|
||||||
|
secondaryAction={
|
||||||
|
<IconButton edge="end" aria-label="delete">
|
||||||
|
<DeleteOutline />
|
||||||
|
</IconButton>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
{/* <FileIcon /> */}
|
||||||
|
DR
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary={file.name} secondary={file.type} />
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
startIcon={<Add />}
|
||||||
|
component="label"
|
||||||
|
sx={{ paddingY: 2, width: '100%', ':hover': { border: 'none' } }}
|
||||||
|
>
|
||||||
|
Doctor Result
|
||||||
|
<input
|
||||||
|
name="invoice"
|
||||||
|
hidden
|
||||||
|
accept="image/*,application/pdf"
|
||||||
|
multiple
|
||||||
|
type="file"
|
||||||
|
onChange={(event) => {
|
||||||
|
fileSelected(event, 'diagnosis');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isEligible === true ? (
|
||||||
|
<LoadingButton
|
||||||
|
onClick={handleSubmit(onSubmit)}
|
||||||
|
variant="contained"
|
||||||
|
color="success"
|
||||||
|
style={{ color: '#ffffff' }}
|
||||||
|
size="large"
|
||||||
|
fullWidth={true}
|
||||||
|
loading={isCheckingLimit}
|
||||||
|
>
|
||||||
|
Create Claim
|
||||||
|
</LoadingButton>
|
||||||
|
) : (
|
||||||
|
<LoadingButton
|
||||||
|
onClick={checkLimit}
|
||||||
|
variant="outlined"
|
||||||
|
size="large"
|
||||||
|
fullWidth={true}
|
||||||
|
loading={isCheckingLimit}
|
||||||
|
>
|
||||||
|
Check Limit
|
||||||
|
</LoadingButton>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<MemberSelectDialog
|
||||||
|
openDialog={isMemberDialogOpen}
|
||||||
|
setOpenDialog={setIsMemberDialogOpen}
|
||||||
|
onSelect={memberSelected}
|
||||||
|
></MemberSelectDialog>
|
||||||
|
</FormProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
frontend/dashboard/src/pages/ClaimRequests/Index.tsx
Executable file
30
frontend/dashboard/src/pages/ClaimRequests/Index.tsx
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
import { Card, Stack } from "@mui/material";
|
||||||
|
import HeaderBreadcrumbs from "../../components/HeaderBreadcrumbs";
|
||||||
|
import Page from "../../components/Page";
|
||||||
|
import List from "./List";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default function Claims() {
|
||||||
|
|
||||||
|
const pageTitle = 'Claim Request';
|
||||||
|
return (
|
||||||
|
<Page title={ pageTitle } sx={{ mx: 2}}>
|
||||||
|
|
||||||
|
<HeaderBreadcrumbs
|
||||||
|
heading={ pageTitle }
|
||||||
|
links={[
|
||||||
|
{ name: 'Dashboard', href: '/dashboard' },
|
||||||
|
{
|
||||||
|
name: 'Claim Request',
|
||||||
|
href: '/claim-requests',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* <Stack> */}
|
||||||
|
<List />
|
||||||
|
{/* </Stack> */}
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
||||||
339
frontend/dashboard/src/pages/ClaimRequests/List.tsx
Executable file
339
frontend/dashboard/src/pages/ClaimRequests/List.tsx
Executable file
@@ -0,0 +1,339 @@
|
|||||||
|
// @mui
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Collapse,
|
||||||
|
IconButton,
|
||||||
|
MenuItem,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableRow,
|
||||||
|
TextField,
|
||||||
|
Typography,
|
||||||
|
Stack,
|
||||||
|
Menu,
|
||||||
|
ButtonGroup,
|
||||||
|
Link,
|
||||||
|
Chip,
|
||||||
|
} 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 { 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 { LoadingButton } from '@mui/lab';
|
||||||
|
import { enqueueSnackbar } from 'notistack';
|
||||||
|
import { Divider } from '@mui/material';
|
||||||
|
import Iconify from '@/components/Iconify';
|
||||||
|
import DialogDetailClaim from '@/components/dialogs/DialogDetailClaim';
|
||||||
|
// import LoadingButton from '@/theme/overrides/LoadingButton';
|
||||||
|
|
||||||
|
export default function List() {
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
const [importResult, setImportResult] = useState(null);
|
||||||
|
|
||||||
|
function SearchInput(props: any) {
|
||||||
|
// SEARCH
|
||||||
|
const searchInput = useRef<HTMLInputElement>(null);
|
||||||
|
const [searchText, setSearchText] = useState('');
|
||||||
|
|
||||||
|
const handleSearchChange = (event: any) => {
|
||||||
|
const newSearchText = event.target.value ?? '';
|
||||||
|
setSearchText(newSearchText);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearchSubmit = (event: any) => {
|
||||||
|
event.preventDefault();
|
||||||
|
props.onSearch({ search: searchText }); // Trigger to Parent
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Trigger First Search
|
||||||
|
setSearchText(searchParams.get('search') ?? '');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSearchSubmit} style={{ width: '100%' }}>
|
||||||
|
<TextField
|
||||||
|
id="search-input"
|
||||||
|
ref={searchInput}
|
||||||
|
label="Search"
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
onChange={handleSearchChange}
|
||||||
|
value={searchText}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ImportForm(props: any) {
|
||||||
|
// IMPORT
|
||||||
|
// Create Button Menu
|
||||||
|
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||||
|
const createMenu = Boolean(anchorEl);
|
||||||
|
const importForm = useRef<HTMLInputElement>(null);
|
||||||
|
const [currentImportFileName, setCurrentImportFileName] = useState(null);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Stack direction={'row'} spacing={2} sx={{ p: 2 }}>
|
||||||
|
<SearchInput onSearch={applyFilter} />
|
||||||
|
{/* <Button
|
||||||
|
variant="outlined"
|
||||||
|
startIcon={<AddIcon />}
|
||||||
|
sx={{ p: 1.8 }}
|
||||||
|
onClick={() => {
|
||||||
|
navigate('/claims/create');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Create
|
||||||
|
</Button> */}
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dummy Default Data
|
||||||
|
const [dataTableIsLoading, setDataTableLoading] = useState(true);
|
||||||
|
const [dataTableData, setDataTableData] = useState<LaravelPaginatedData>(
|
||||||
|
LaravelPaginatedDataDefault
|
||||||
|
);
|
||||||
|
|
||||||
|
const loadDataTableData = async (appliedFilter: any | null = null) => {
|
||||||
|
setDataTableLoading(true);
|
||||||
|
const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]);
|
||||||
|
const response = await axios.get('/claim-requests', { params: filter });
|
||||||
|
// console.log(response.data);
|
||||||
|
setDataTableLoading(false);
|
||||||
|
|
||||||
|
setDataTableData(response.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyFilter = async (searchFilter: { search: string }) => {
|
||||||
|
await loadDataTableData(searchFilter);
|
||||||
|
setSearchParams(searchFilter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePageChange = (event: ChangeEvent, value: number): void => {
|
||||||
|
const filter = Object.fromEntries([...searchParams.entries(), ['page', value]]);
|
||||||
|
loadDataTableData(filter);
|
||||||
|
setSearchParams(filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleApprove = (claimRequest) => {
|
||||||
|
axios.post(`claim-requests/${claimRequest.id}/approve`)
|
||||||
|
.then((response) => {
|
||||||
|
enqueueSnackbar('Success Approve', {variant: 'success'})
|
||||||
|
loadDataTableData()
|
||||||
|
})
|
||||||
|
.catch(({response}) => {
|
||||||
|
enqueueSnackbar(response.data.message ?? 'Something went wrong!', {variant : "error"})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadDataTableData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const headStyle = {
|
||||||
|
fontWeight: 'bold',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Called on every row to map the data to the columns
|
||||||
|
function createData(data: any): any {
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* ------------------ TABLE ROW ------------------ */
|
||||||
|
}
|
||||||
|
function Row(props: { row: ReturnType<typeof createData> }) {
|
||||||
|
const { row } = props;
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const [loadingApprove, setLoadingApprove] = React.useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }}>
|
||||||
|
<TableCell>
|
||||||
|
<IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
|
||||||
|
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
|
||||||
|
</IconButton>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left">{row.code}</TableCell>
|
||||||
|
<TableCell align="left">{row.member?.full_name}</TableCell>
|
||||||
|
<TableCell align="left">{row.submission_date}</TableCell>
|
||||||
|
<TableCell align="left">{row.service_type}</TableCell>
|
||||||
|
<TableCell align="right"><Chip label={row.status}/></TableCell>
|
||||||
|
<TableCell align="right">{ row.status == 'requested' && (<LoadingButton loading={loadingApprove} variant="outlined" onClick={() => {handleApprove(row)}}>Approve</LoadingButton> )}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
handleShowClaim(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Iconify icon="eva:eye-fill" />
|
||||||
|
</IconButton>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
{/* COLLAPSIBLE ROW */}
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={99}>
|
||||||
|
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||||
|
<Box sx={{ borderBottom: 1 }}>
|
||||||
|
<Stack
|
||||||
|
divider={<Divider orientation="horizontal" flexItem />}
|
||||||
|
spacing={1}
|
||||||
|
sx={{ marginY: 2 }}
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
<Typography fontWeight={600}>Berkas Hasil Penunjang</Typography>
|
||||||
|
{row.files_by_type?.result &&
|
||||||
|
row.files_by_type?.result.map((file, index) => (
|
||||||
|
<Stack direction="row" key={index}>
|
||||||
|
<Typography sx={{marginRight: 2}}>-</Typography> <a href={file.url} target="_blank">{file.name}</a>
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{ !row.files_by_type?.result && (
|
||||||
|
<Typography>Tidak ada berkas</Typography>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</Collapse>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* ------------------ END TABLE ROW ------------------ */
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableContent() {
|
||||||
|
return (
|
||||||
|
<Table aria-label="collapsible table">
|
||||||
|
{/* ------------------ TABLE HEADER ------------------ */}
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell style={headStyle} align="left" />
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Code
|
||||||
|
</TableCell>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Member Name
|
||||||
|
</TableCell>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Submission Date
|
||||||
|
</TableCell>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Jenis Layanan
|
||||||
|
</TableCell>
|
||||||
|
<TableCell style={headStyle} align="left">
|
||||||
|
Status
|
||||||
|
</TableCell>
|
||||||
|
<TableCell style={headStyle} align="right">
|
||||||
|
Action
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
{/* ------------------ END TABLE HEADER ------------------ */}
|
||||||
|
|
||||||
|
{/* ------------------ TABLE ROW ------------------ */}
|
||||||
|
{dataTableIsLoading ? (
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={8} align="center">
|
||||||
|
Loading
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
) : dataTableData.data.length === 0 ? (
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={8} align="center">
|
||||||
|
No Data
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
) : (
|
||||||
|
<TableBody>
|
||||||
|
{dataTableData.data.map((row) => (
|
||||||
|
<Row key={row.id} row={row} />
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
)}
|
||||||
|
{/* ------------------ END TABLE ROW ------------------ */}
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// Dialog Detail Claim Request
|
||||||
|
const [openDialogDetailClaim, setOpenDialogDetailClaim] = useState(false);
|
||||||
|
const [loadingClaimDetail, setLoadingClaimDetail] = useState(true);
|
||||||
|
const [currentClaim, setCurrentClaim] = useState(null);
|
||||||
|
|
||||||
|
function handleShowClaim(claimRequest) {
|
||||||
|
setLoadingClaimDetail(true);
|
||||||
|
setOpenDialogDetailClaim(true);
|
||||||
|
|
||||||
|
axios.get(`/claim-requests/${claimRequest.id}`)
|
||||||
|
.then(({data}) => {
|
||||||
|
setCurrentClaim(data.data);
|
||||||
|
setLoadingClaimDetail(false);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
enqueueSnackbar(err.message, {variant: 'error'})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDownloadLog() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<ImportForm />
|
||||||
|
|
||||||
|
<DataTable
|
||||||
|
isLoading={dataTableIsLoading}
|
||||||
|
lastRequest={0}
|
||||||
|
data={dataTableData}
|
||||||
|
handlePageChange={handlePageChange}
|
||||||
|
TableContent={<TableContent />}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<DialogDetailClaim
|
||||||
|
openDialog={openDialogDetailClaim}
|
||||||
|
setOpenDialog={setOpenDialogDetailClaim}
|
||||||
|
title={{ name: 'Claim Request Detail' }}
|
||||||
|
data={{ claim: currentClaim, isLoading: loadingClaimDetail, handleDownloadLog }}
|
||||||
|
></DialogDetailClaim>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -100,7 +100,7 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
|
|||||||
policy_stop_service_net: currentCorporate?.current_policy?.minimal_stop_service_net || 0,
|
policy_stop_service_net: currentCorporate?.current_policy?.minimal_stop_service_net || 0,
|
||||||
policy_start: currentCorporate?.current_policy?.start || '',
|
policy_start: currentCorporate?.current_policy?.start || '',
|
||||||
policy_end: currentCorporate?.current_policy?.end || '',
|
policy_end: currentCorporate?.current_policy?.end || '',
|
||||||
linking_rules: currentCorporate?.linking_rules || ['nrik', 'nik', 'member_id'],
|
linking_rules: currentCorporate?.linking_rules || ['nric', 'nik', 'member_id'],
|
||||||
type: currentCorporate?.type || 'corporate',
|
type: currentCorporate?.type || 'corporate',
|
||||||
logo: currentCorporate?.logo || '',
|
logo: currentCorporate?.logo || '',
|
||||||
}),
|
}),
|
||||||
@@ -174,6 +174,8 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
|
|||||||
formData.append('policy_end', data.policy_end);
|
formData.append('policy_end', data.policy_end);
|
||||||
formData.append('linking_rules', data.linking_rules);
|
formData.append('linking_rules', data.linking_rules);
|
||||||
|
|
||||||
|
console.log('MOTHERFUCKER', data.linking_rules)
|
||||||
|
|
||||||
if (!isEdit) {
|
if (!isEdit) {
|
||||||
const response = await axios.post('/corporates', formData);
|
const response = await axios.post('/corporates', formData);
|
||||||
} else {
|
} else {
|
||||||
@@ -269,7 +271,7 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
|
|||||||
const linking_rules_checkbox_name = 'linking_rules';
|
const linking_rules_checkbox_name = 'linking_rules';
|
||||||
const linking_tools = [
|
const linking_tools = [
|
||||||
{
|
{
|
||||||
value: 'nrik',
|
value: 'nric',
|
||||||
label: 'No. KTP',
|
label: 'No. KTP',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -425,6 +427,7 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
|
|||||||
Linking Rules
|
Linking Rules
|
||||||
</Typography>
|
</Typography>
|
||||||
<Stack>
|
<Stack>
|
||||||
|
{JSON.stringify(getValues('linking_rules'))}
|
||||||
<RHFCustomMultiCheckbox name="linking_rules" options={linking_tools} />
|
<RHFCustomMultiCheckbox name="linking_rules" options={linking_tools} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ export default function FormulariumForm({ isEdit, currentFormularium }: Props) {
|
|||||||
const linking_rules_checkbox_name = "linking_rules"
|
const linking_rules_checkbox_name = "linking_rules"
|
||||||
const linking_tools = [
|
const linking_tools = [
|
||||||
{
|
{
|
||||||
"value" : "nrik",
|
"value" : "nric",
|
||||||
"label" : "No. KTP"
|
"label" : "No. KTP"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -212,10 +212,10 @@ export default function List() {
|
|||||||
<Grid item xs={2}>Metode Pembayaran</Grid><Grid item xs="10">: {row.payment_method}</Grid>
|
<Grid item xs={2}>Metode Pembayaran</Grid><Grid item xs="10">: {row.payment_method}</Grid>
|
||||||
<Grid item xs={2}>HIS RegID</Grid><Grid item xs="10">: {row.his_detail?.sRegID}</Grid>
|
<Grid item xs={2}>HIS RegID</Grid><Grid item xs="10">: {row.his_detail?.sRegID}</Grid>
|
||||||
<Grid item xs={2}>HIS Medrec</Grid><Grid item xs="10">: {row.his_detail?.Medrec}</Grid>
|
<Grid item xs={2}>HIS Medrec</Grid><Grid item xs="10">: {row.his_detail?.Medrec}</Grid>
|
||||||
<Grid item xs={2}>No HP</Grid><Grid item xs="10">: {row.patient.sPhone ?? ''}</Grid>
|
<Grid item xs={2}>No HP</Grid><Grid item xs="10">: {row.patient?.sPhone ?? ''}</Grid>
|
||||||
<Grid item xs={2}>E-mail</Grid><Grid item xs="10">: {row.patient.sEmail ?? ''}</Grid>
|
<Grid item xs={2}>E-mail</Grid><Grid item xs="10">: {row.patient?.sEmail ?? ''}</Grid>
|
||||||
<Grid item xs={2}>Alamat</Grid><Grid item xs="10">: {row.patient.detail.sAlamat ?? ''}</Grid>
|
<Grid item xs={2}>Alamat</Grid><Grid item xs="10">: {row.patient?.detail?.sAlamat ?? ''}</Grid>
|
||||||
<Grid item xs={2}>KTP</Grid><Grid item xs="10">: {row.patient.detail.sKTP ?? ''}</Grid>
|
<Grid item xs={2}>KTP</Grid><Grid item xs="10">: {row.patient?.detail?.sKTP ?? ''}</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
|||||||
@@ -270,6 +270,10 @@ export default function Router() {
|
|||||||
path: 'claims',
|
path: 'claims',
|
||||||
element: <Claims />,
|
element: <Claims />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'claim-requests',
|
||||||
|
element: <ClaimRequests />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'claims/create',
|
path: 'claims/create',
|
||||||
element: <ClaimsCreate />,
|
element: <ClaimsCreate />,
|
||||||
@@ -398,3 +402,5 @@ const Profile = Loadable(lazy(() => import('../pages/Profile/Index')));
|
|||||||
|
|
||||||
const Claims = Loadable(lazy(() => import('../pages/Claims/Index')));
|
const Claims = Loadable(lazy(() => import('../pages/Claims/Index')));
|
||||||
const ClaimsCreate = Loadable(lazy(() => import('../pages/Claims/CreateUpdate')));
|
const ClaimsCreate = Loadable(lazy(() => import('../pages/Claims/CreateUpdate')));
|
||||||
|
|
||||||
|
const ClaimRequests = Loadable(lazy(() => import('../pages/ClaimRequests/Index')));
|
||||||
4
frontend/hospital-portal/.env.development
Normal file
4
frontend/hospital-portal/.env.development
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
REACT_APP_HOST_API_URL="http://localhost:8000"
|
||||||
|
|
||||||
|
VITE_API_URL="http://localhost:8000/api/hospitalportal"
|
||||||
1
frontend/hospital-portal/.env.staging
Normal file
1
frontend/hospital-portal/.env.staging
Normal file
@@ -0,0 +1 @@
|
|||||||
|
VITE_API_URL="https://aso-api.linksehat.dev/api/hospitalportal"
|
||||||
8
frontend/hospital-portal/.eslintignore
Executable file
8
frontend/hospital-portal/.eslintignore
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
// .eslintignore
|
||||||
|
build/*
|
||||||
|
public/*
|
||||||
|
src/react-app-env.d.ts
|
||||||
|
src/reportWebVitals.ts
|
||||||
|
src/service-worker.ts
|
||||||
|
src/serviceWorkerRegistration.ts
|
||||||
|
src/setupTests.ts
|
||||||
54
frontend/hospital-portal/.eslintrc
Executable file
54
frontend/hospital-portal/.eslintrc
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"prettier",
|
||||||
|
"@typescript-eslint"
|
||||||
|
],
|
||||||
|
"extends": [
|
||||||
|
"airbnb-typescript",
|
||||||
|
"react-app",
|
||||||
|
"prettier"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"project": [
|
||||||
|
"**/tsconfig.json"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"import/resolver": {
|
||||||
|
"typescript": {
|
||||||
|
"alwaysTryTypes": true,
|
||||||
|
"exceptAfterSingleLine": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"react/jsx-key": 2,
|
||||||
|
"arrow-body-style": 1,
|
||||||
|
"import/no-duplicates": 1,
|
||||||
|
"react/self-closing-comp": 1,
|
||||||
|
"@typescript-eslint/no-shadow": 0,
|
||||||
|
"import/no-useless-path-segments": 1,
|
||||||
|
"import/no-extraneous-dependencies": 0,
|
||||||
|
"@typescript-eslint/naming-convention": 0,
|
||||||
|
"import/extensions": "never",
|
||||||
|
"object-curly-spacing": [
|
||||||
|
1,
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
1,
|
||||||
|
{
|
||||||
|
"vars": "all",
|
||||||
|
"args": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prefer-destructuring": [
|
||||||
|
1,
|
||||||
|
{
|
||||||
|
"object": true,
|
||||||
|
"array": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
26
frontend/hospital-portal/.gitignore
vendored
Executable file
26
frontend/hospital-portal/.gitignore
vendored
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
/.env
|
||||||
|
/.env.local
|
||||||
|
/.env.development.local
|
||||||
|
/.env.test.local
|
||||||
|
/.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user