60 Commits

Author SHA1 Message Date
R
a5db01bd25 Fix Download LOG 2023-02-15 12:50:46 +07:00
R
5d4033a9ca Display Uploaded Files 2023-02-15 12:30:35 +07:00
R
27523b8cce [WIP] Fix Upload Document from Hospital Portal 2023-02-15 08:00:14 +07:00
R
f6117743ad Fix Filter 2023-02-14 16:32:38 +07:00
R
8c97df9fc4 Remove Dummy Notifications 2023-02-14 15:31:57 +07:00
R
4f2bb19d8a [Build] Dashboard & Hospital Portal 2023-02-14 13:48:59 +07:00
R
13764a3766 [Build] Staging - Hospital Portal 2023-02-14 13:31:49 +07:00
R
ed273fdafa Merge branch 'feature/hospital-portal' 2023-02-14 13:09:14 +07:00
R
d706bf0623 [WIP] Add Approve Button 2023-02-14 13:07:17 +07:00
R
13542cd3c0 [WIP] Add Claim Request 2023-02-14 12:39:51 +07:00
R
6491f4d3e3 Add corporate Manager soft delete 2023-02-04 08:48:52 +07:00
R
5028b2d82b Fix Division by Zero 2023-02-04 08:46:44 +07:00
R
5d56434aa2 [Build] Client Portal 2023-02-04 08:38:46 +07:00
R
8e05280b7d Fix Name & User Avatar 2023-02-04 08:36:59 +07:00
R
e3de0a3c04 Hide Burger 2023-02-04 08:14:51 +07:00
R
c3a425c93d Fix Error on opening Add Claim Modal 2023-02-04 08:12:53 +07:00
R
431070efc3 Fix OTP Client Portal to 4444 2023-02-04 08:05:03 +07:00
R
e8c3decf85 Change Title 2023-02-01 20:27:53 +07:00
R
99c488baf3 Update Guaranted Letter 2023-02-01 20:21:03 +07:00
R
0b50e4c980 Update Guaranted Letter Styling 2023-02-01 20:17:32 +07:00
R
ba310a21c1 [Build] Both 2023-02-01 19:39:33 +07:00
R
5a0136acf8 Fix Download Blob Pdf 2023-02-01 19:35:30 +07:00
R
75c9781a22 [Build] Staging 2023-02-01 19:20:09 +07:00
R
2a1f0c854a [Build] Production 2023-02-01 19:16:50 +07:00
R
f0c787fede Add Download LOG 2023-02-01 19:15:31 +07:00
pajri
a7e688a52c hospital portal 2023-02-01 16:22:03 +07:00
R
8d5f4bb0bd Fix Import Benefit selecting wrong plan from another corporate 2023-02-01 01:37:53 +07:00
R
248047006e [Build] Staging 2023-02-01 01:16:44 +07:00
R
2c535b4021 [Build] Production 2023-02-01 00:56:17 +07:00
R
59dd63a78f Add name,dob linking tools 2023-02-01 00:51:14 +07:00
R
21282be7b3 Merge remote-tracking branch 'origin/feature/prices' 2023-02-01 00:42:44 +07:00
pajri
8cbfb1929b update csv 2023-02-01 11:52:19 +07:00
R
b8152e6b3f Fix Date Time Write 2023-01-30 12:40:04 +07:00
R
cfbe108629 Remove error sting 2023-01-30 12:20:14 +07:00
R
a8821dfb3c Fix Seeder 2023-01-30 12:08:49 +07:00
pajri
1ce2655b65 update schedule dokter 2023-01-28 09:44:14 +07:00
pajri
335e24b17c add biaya admin 2023-01-27 13:26:42 +07:00
pajri
4776eb5b0a seeder prices jadwal dokter 2023-01-27 09:52:31 +07:00
R
17daf20167 Add MCU 2023-01-26 14:51:32 +07:00
R
18ace75fc7 Add OLDLMS .env.example 2023-01-26 07:35:08 +07:00
R
ad743de98d Fix Bug Member Import 2023-01-19 15:09:32 +07:00
R
96a40842bd [Build] Import Loading Button 2023-01-19 14:43:16 +07:00
R
137fd07a28 Add Loading Button when Import 2023-01-19 14:41:56 +07:00
R
21dc0b1fc1 [Build] Frontend Dashboard 2023-01-19 10:15:55 +07:00
R
f56361de62 [Build] Frontend Dashboard 2023-01-19 10:15:00 +07:00
R
85f319878a Fix Regex Kode Corporate 2023-01-19 10:09:53 +07:00
R
23436164c2 Fix Corporate Create & Update Validation remove allow spaces 2023-01-17 12:40:15 +07:00
R
b19e0876e5 Change Specialities Button 2023-01-15 12:19:31 +07:00
R
704c5ecc44 [Bug Fix] Update Validation : Is there laravel validation update ? 2023-01-15 12:07:44 +07:00
R
9087580138 Add File Import Example Download 2023-01-15 11:28:07 +07:00
R
7ff199a3c1 [Fix] Member Benefit Specific 2023-01-13 14:48:15 +07:00
R
08a2502fb1 Enable Claim Softdeletes 2023-01-13 12:19:00 +07:00
R
65c9153fee [Build] Frontend 2023-01-13 12:14:00 +07:00
R
775f471a07 [WIP] Update Postponed 2023-01-13 12:08:57 +07:00
R
f09eaef5ad [Fix] Display Claim Postponed 2023-01-13 11:50:31 +07:00
R
e116fb814a [WIP] Fix Medicine 2023-01-13 08:19:43 +07:00
R
2f10f913c0 [WIP] Change Check Coverage Appointment 2023-01-13 00:43:58 +07:00
R
3a2dd84500 Fix Breadcrumbs Links 2023-01-12 15:10:59 +07:00
R
7d1872ef1e [Build] Update 2023-01-11 14:49:16 +07:00
R
552a2367f5 [WIP] Cashless 2023-01-11 14:29:02 +07:00
759 changed files with 58777 additions and 4302 deletions

View File

@@ -15,6 +15,13 @@ DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
OLDLMS_DB_CONNECTION=mysql
OLDLMS_DB_HOST=127.0.0.1
OLDLMS_DB_PORT=3306
OLDLMS_DB_DATABASE=linksehat
OLDLMS_DB_USERNAME=mysql
OLDLMS_DB_PASSWORD=password
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local

View File

@@ -35,13 +35,13 @@ class AuthController extends Controller
if (filter_var($request->phoneOrEmail, FILTER_VALIDATE_EMAIL)) {
User::query()->find($user->id)->update([
'email' => $request->phoneOrEmail,
'otp' => rand(1000, 9999),
'otp' => 4444, //rand(1000, 9999),
'otp_created_at' => now()
]);
} else {
User::query()->find($user->id)->update([
'phone' => $request->phoneOrEmail,
'otp' => rand(1000, 9999),
'otp' => 4444,//rand(1000, 9999),
'otp_created_at' => now()
]);
}

View File

@@ -26,7 +26,7 @@ class DashboardResources extends JsonResource
'myLimit' => [
'balance' => $myLimitBalance,
'total' => $myLimitTotal,
'percentage' => ($myLimitBalance / $myLimitTotal) * 100,
'percentage' => $myLimitTotal ? (($myLimitBalance / $myLimitTotal) * 100) : 0,
],
'lockLimit' => [
'balance' => $lockBalance,

View File

View File

@@ -0,0 +1,5 @@
<?php
return [
'name' => 'HospitalPortal'
];

View File

View 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");
}
}

View File

View 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);
}
}

View File

@@ -0,0 +1,145 @@
<?php
namespace Modules\HospitalPortal\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Models\ClaimRequest;
use App\Models\File;
use App\Models\Member;
use Exception;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
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'])
->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([
// 'submission_date' => 'required',
'member_id' => 'required',
// 'files' => ''
]);
$newClaimRequest = ClaimRequest::create([
'member_id' => $request->member_id,
'submission_date' => now(),
'status' => 'requested'
]);
if ($request->hasFile('result_files')) {
foreach ($request->result_files as $file) {
$pathFile = File::storeFile('claim', $newClaimRequest->id, $file);
$newClaimRequest->files()->updateOrCreate([
'type' => 'result',
'name' => File::getFileName('claim', $newClaimRequest->id, $file),
'original_name' => $file->getClientOriginalName(),
'extension' => $file->getClientOriginalExtension(),
'path' => $pathFile,
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id,
]);
}
}
return ($request->result_files[0]->getClientOriginalName());
return Helper::responseJson(data: $request->toArray(), message: 'Claim Request berhasil ajukan!');
}
/**
* 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)
{
//
}
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;
}
}

View File

@@ -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);
}
}

View 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)
{
//
}
}

View File

@@ -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)
{
//
}
}

View 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;
}
}

View 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'));
}
}

View 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

View File

@@ -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>

View File

View File

@@ -0,0 +1,43 @@
<?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');
});
});

View 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');
});

View 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\\": ""
}
}
}

View File

@@ -0,0 +1,13 @@
{
"name": "HospitalPortal",
"alias": "hospitalportal",
"description": "",
"keywords": [],
"priority": 0,
"providers": [
"Modules\\HospitalPortal\\Providers\\HospitalPortalServiceProvider"
],
"aliases": {},
"files": [],
"requires": []
}

View 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"
}
}

View 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();
}

View File

@@ -0,0 +1,113 @@
<?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;
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)
{
return view('internal::show');
}
/**
* 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);
$claimRequest->status = 'approved';
$claimRequest->save();
return $claimRequest;
}
}

View File

@@ -3,6 +3,7 @@
namespace Modules\Internal\Http\Controllers\Api;
use App\Exceptions\ImportRowException;
use App\Helpers\Helper;
use App\Imports\PlansImport;
use App\Models\Benefit;
use App\Models\Claim;
@@ -19,7 +20,8 @@ use Illuminate\Routing\Controller;
use Maatwebsite\Excel\Facades\Excel;
use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
use App\Models\File;
use Illuminate\Support\Facades\File as FacadesFile;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Modules\Internal\Services\CorporateService;
@@ -76,7 +78,7 @@ class CorporateController extends Controller
public function store(Request $request)
{
$request->validate([
'code' => 'required',
'code' => 'required|regex:/^[a-zA-Z0-9]+$/',
'name' => 'required',
// 'logo' => 'required',
'policy_code' => 'required_with:policy_id',
@@ -144,6 +146,12 @@ class CorporateController extends Controller
'code' => 'OPT',
'description' => 'Optical',
],
[
'id' => 6,
'name' => 'Medical Check Up',
'code' => 'MCU',
'description' => 'Medical Check Up',
],
];
foreach ($services as $service) {
@@ -293,7 +301,7 @@ class CorporateController extends Controller
public function update(Request $request, $id)
{
$request->validate([
'code' => 'required',
'code' => 'required|regex:/^[a-zA-Z0-9]+$/',
'name' => 'required',
'policy_code' => 'required_with:policy_id',
'policy_total_premi' => 'required_with:policy_code',
@@ -486,4 +494,31 @@ class CorporateController extends Controller
]
];
}
public function importDocumentExample($document_type)
{
switch ($document_type) {
case 'plan-benefit':
return Helper::responseJson([
'file_name' => "Corporate Plan & Benefit Import.xlsx",
"file_url" => url('files/Corporate Plan & Benefit Import.xlsx')
]);
break;
case 'member':
return Helper::responseJson([
'file_name' => "Corporate Membership Import.xlsx",
"file_url" => url('files/Corporate Membership Import.xlsx')
]);
break;
case 'diagnosis-exclusion':
return Helper::responseJson([
'file_name' => "Corporate Exclusion Import.xlsx",
"file_url" => url('files/Corporate Exclusion Import.xlsx')
]);
break;
default:
return Helper::responseJson([], 'error', 404);
break;
}
}
}

View File

@@ -15,6 +15,7 @@ use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Storage;
use Modules\Internal\Services\MemberEnrollmentService;
use PDF;
class CorporateMemberController extends Controller
{
@@ -192,9 +193,12 @@ class CorporateMemberController extends Controller
'ingestion_code' => $e->getCode(),
'ingestion_status' => $e->getMessage(),
]);
$singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRowWithResultFormat($new_member_data));
$writer->addRow($singleRow);
$failed_member_data[] = ['row_number' => $index, 'error' => $e->getMessage()];
// try {
$singleRow = WriterEntityFactory::createRow($this->memberEnrollmentService->makeResultRowWithResultFormat($new_member_data));
$writer->addRow($singleRow);
// } catch (\Exception $e) {
$failed_member_data[] = ['row_number' => $index, 'error' => $e->getMessage(), 'data' => $new_member_data];
// }
} catch (\Exception $e) {
// Write Server Error to File
$new_member_data = array_merge($new_member_data, [
@@ -225,4 +229,17 @@ class CorporateMemberController extends Controller
]
];
}
public function generateLog($member_id)
{
$member = Member::findOrFail($member_id)
->load(['currentPlan', 'currentPolicy', 'currentPlan.corporateBenefits', 'currentPlan.corporateBenefits.benefit']);
// dd($member->currentPlan->corporateBenefits->toArray());
// return view('pdf.guaranted_leter', compact('member'));
$pdf = PDF::loadView('pdf.guaranted_leter', compact('member'));
return $pdf->download('Guaranted Letter - '.$member->full_name.'.pdf');
}
}

View File

@@ -5,6 +5,7 @@ use Modules\Internal\Http\Controllers\Api\AuthController;
use Illuminate\Http\Request;
use Modules\Internal\Http\Controllers\Api\BenefitController;
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\CorporateController;
use Modules\Internal\Http\Controllers\Api\CorporateFormulariumController;
@@ -51,6 +52,7 @@ Route::prefix('internal')->group(function () {
Route::resource('corporates', CorporateController::class);
Route::get('corporates/import-document-example/{document_type}', [CorporateController::class, 'importDocumentExample']);
Route::put('corporates/{corporate_id}/activation', [CorporateController::class, 'activation']);
Route::post('corporates/{corporate_id}/import-plan-benefit', [CorporateController::class, 'importPlanBenefit']);
@@ -119,6 +121,11 @@ Route::prefix('internal')->group(function () {
Route::get('search-specialities', [SpecialityController::class, 'searchSpeciality']);
Route::resource('organizations', OrganizationController::class);
Route::resource('doctors', DoctorController::class);
Route::get('generate-log/{member_id}', [CorporateMemberController::class, 'generateLog']);
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::resource('organizations', OrganizationController::class);

View File

@@ -11,6 +11,8 @@
|
*/
use Modules\Internal\Http\Controllers\Api\CorporateMemberController;
Route::prefix('internal')->group(function() {
Route::get('/', 'InternalController@index');
});
});

View File

@@ -42,10 +42,8 @@ class CorporateService
$this->validatePlanRow($plan_data);
$plan = Plan::updateOrCreate([
$plan = $corporate->plans()->updateOrCreate([
'service_code' => $plan_data['service_code'],
'corporate_id' => $corporate->id,
'code' => $plan_data['code'],
], $plan_data);
return $plan;
@@ -91,7 +89,9 @@ class CorporateService
$this->validateBenefitRow($benefit_data);
$plan = Plan::where('corporate_plan_id', $benefit_data['plan_code'])->first();
$plan = $corporate->plans()
->where('corporate_plan_id', $benefit_data['plan_code'])
->first();
// $corporate->plans->where('corporate_plan_id', $benefit_data['plan_code'])->first();
$benefit_data['plan_code'] = $plan->id;

View File

@@ -15,6 +15,7 @@ use App\Models\Plan;
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Box\Spout\Common\Entity\Row;
use Carbon\Carbon;
use DateTime;
use DB;
class MemberEnrollmentService
@@ -45,6 +46,7 @@ class MemberEnrollmentService
"The Right Classes Room of BPJS Participants" => "bpjs_class",
"Name of Faskes" => "faskes_name",
"Rule_BPJSK ('Y' or 'N')" => "bpjsk",
"Rule BPJSK" => "bpjsk",
"Agent Code / intermediary code" => "agent_code",
"Member Name" => "name",
"Address1" => "address1",
@@ -123,7 +125,7 @@ class MemberEnrollmentService
"faskes_fkrtl" => "Faskes FKRTL (Next Level Provider) or Individual group preferred provider",
"bpjs_class" => "The Right Classes Room of BPJS Participants",
"faskes_name" => "Name of Faskes",
"bpjsk" => "Rule_BPJSK ('Y' or 'N')",
"bpjsk" => "Rule BPJSK",
"agent_code" => "Agent Code / intermediary code",
"name" => "Member Name",
"address1" => "Address1",
@@ -195,8 +197,8 @@ class MemberEnrollmentService
"Faskes FKRTL (Next Level Provider) or Individual group preferred provider",
"The Right Classes Room of BPJS Participants",
"Name of Faskes",
"Rule_BPJSK ('Y' or 'N')",
"Agent Code / intermediary code",
"Rule BPJSK",
"Internal Use",
"Member Name",
"Address1",
"Address 1",
@@ -247,6 +249,10 @@ class MemberEnrollmentService
$this->member = $member;
}
public function dateParser($date_from_row) {
return is_string($date_from_row) ? Carbon::parse(strtotime($date_from_row)) : Carbon::parse($date_from_row);
}
protected function validateRow($row)
{
if (empty($row['record_type'])) {
@@ -360,7 +366,7 @@ class MemberEnrollmentService
"member_id" => $row['member_id'] ?? null,
"payor_id" => $row['payor_id'] ?? null,
"nik" => $row['nik'] ?? null,
"birth_date" => Carbon::parse(strtotime($row['date_of_birth'])),
"birth_date" => $this->dateParser($row['date_of_birth']),
"gender" => Helper::genderNormalization($row['sex']),
// "language" => $row['language'] ?? null,
// "race" => $row['race'] ?? null,
@@ -415,7 +421,7 @@ class MemberEnrollmentService
],
[
'name' => $row['name'] ?? null,
'birth_date' => Carbon::parse(strtotime($row['date_of_birth'])),
'birth_date' => $this->dateParser($row['date_of_birth']),
'gender' => Helper::genderPerson($row['sex']),
'language' => $row['language'] ?? null,
'race' => $row['race'] ?? null,
@@ -462,7 +468,7 @@ class MemberEnrollmentService
$person = Person::create([
'name' => $row['name'],
'birth_date' => Carbon::parse(strtotime($row['date_of_birth'])),
'birth_date' => $this->dateParser($row['date_of_birth']),
'gender' => Helper::genderPerson($row['sex']),
'language' => $row['language'] ?? null,
'race' => $row['race'] ?? null,
@@ -474,8 +480,8 @@ class MemberEnrollmentService
$memberPolicy->fill([
'member_id' => $member->member_id,
'policy_id' => $row['policy_number'],
'start' => Carbon::parse(strtotime($row['member_effective_date'])),
'end' => Carbon::parse(strtotime($row['member_expiry_date'])),
'start' => $this->dateParser($row['member_effective_date']),
'end' => $this->dateParser($row['member_expiry_date']),
'status' => 'active'
]);
$memberPolicy->save();
@@ -505,8 +511,8 @@ class MemberEnrollmentService
$member->memberPlans()->create([
'plan_id' => $plan->id,
'status' => 'active',
'start' => Carbon::parse(strtotime($row['member_effective_date'])),
'end' => Carbon::parse(strtotime($row['member_expiry_date'])),
'start' => $this->dateParser($row['member_effective_date']),
'end' => $this->dateParser($row['member_expiry_date']),
]);
}
DB::commit();
@@ -620,13 +626,13 @@ class MemberEnrollmentService
}
if (Carbon::parse(strtotime($row['member_effective_date'])) > Carbon::parse(strtotime($row['member_expiry_date']))) {
if ($this->dateParser($row['member_effective_date']) > $this->dateParser($row['member_expiry_date'])) {
throw new ImportRowException(__('enrollment.MEMBER_EXPIRY_DATE_INVALID'), 0, null, $row);
}
if (
Carbon::parse($memberPolicy->end) > Carbon::parse(strtotime($row['member_expiry_date']))
|| $memberPolicy->end > Carbon::parse(strtotime($row['member_expiry_date']))
Carbon::parse($memberPolicy->end) > $this->dateParser($row['member_expiry_date'])
|| $memberPolicy->end > $this->dateParser($row['member_expiry_date'])
) {
throw new ImportRowException(__('enrollment.MEMBER_RENEWAL_STILL_ACTIVE'), 0, null, $row);
}
@@ -663,13 +669,13 @@ class MemberEnrollmentService
]), 0, null, $row);
}
if (Carbon::parse(strtotime($row['member_effective_date'])) > Carbon::parse(strtotime($row['member_expiry_date']))) {
if ($this->dateParser($row['member_effective_date']) > $this->dateParser($row['member_expiry_date'])) {
throw new ImportRowException(__('enrollment.MEMBER_EXPIRY_DATE_INVALID'), 0, null, $row);
}
if (
Carbon::parse($memberPolicy->end) > Carbon::parse(strtotime($row['member_expiry_date']))
|| $memberPolicy->end > Carbon::parse(strtotime($row['member_expiry_date']))
Carbon::parse($memberPolicy->end) > $this->dateParser($row['member_expiry_date'])
|| $memberPolicy->end > $this->dateParser($row['member_expiry_date'])
) {
throw new ImportRowException(__('enrollment.MEMBER_RENEWAL_STILL_ACTIVE'), 0, null, $row);
}
@@ -850,11 +856,11 @@ class MemberEnrollmentService
]), 0, null, $row);
}
if (Carbon::parse(strtotime($row['member_effective_date'])) < now() || Carbon::parse(strtotime($row['member_expiry_date'])) < now()) {
if ($this->dateParser($row['member_effective_date']) < now() || $this->dateParser($row['member_expiry_date']) < now()) {
throw new ImportRowException(__('enrollment.MEMBER_EXPIRY_MUST_BE_AFTER_TODAY'), 0, null, $row);
}
if (Carbon::parse(strtotime($row['member_effective_date'])) > Carbon::parse(strtotime($row['member_expiry_date']))) {
if ($this->dateParser($row['member_effective_date']) > $this->dateParser($row['member_expiry_date'])) {
throw new ImportRowException(__('enrollment.MEMBER_EXPIRY_DATE_INVALID'), 0, null, $row);
}
@@ -889,8 +895,8 @@ class MemberEnrollmentService
$newMemberPolicy->fill([
'member_id' => $row['member_id'],
'policy_id' => $row['policy_number'],
'start' => Carbon::parse(strtotime($row['member_effective_date'])),
'end' => Carbon::parse(strtotime($row['member_expiry_date'])),
'start' => $this->dateParser($row['member_effective_date']),
'end' => $this->dateParser($row['member_expiry_date']),
'status' => 'active'
]);
$newMemberPolicy->save();
@@ -931,7 +937,7 @@ class MemberEnrollmentService
throw new ImportRowException(__('enrollment.MEMBER_EXPIRY_DATE_NO_CHANGE'), 0, null, $row);
}
if (Carbon::parse(strtotime($row['member_effective_date'])) > Carbon::parse(strtotime($row['member_expiry_date']))) {
if ($this->dateParser($row['member_effective_date']) > $this->dateParser($row['member_expiry_date'])) {
throw new ImportRowException(__('enrollment.MEMBER_EXPIRY_DATE_INVALID'), 0, null, $row);
}
@@ -1016,7 +1022,15 @@ class MemberEnrollmentService
$cells = [];
foreach ($this->result_doc_headers as $header) {
$value = $row_data[$this->doc_headers_to_field_map[$header]] ?? null;
$cells[] = WriterEntityFactory::createCell($value);
if (is_string($value)) {
$cells[] = WriterEntityFactory::createCell($value);
}
else if ($value instanceof DateTime) {
$cells[] = WriterEntityFactory::createCell(Carbon::parse($value)->format('Ymd'));
}
else {
$cells[] = WriterEntityFactory::createCell(null);
}
}
return $cells;

View 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;
}
}

View File

@@ -20,8 +20,8 @@ class CorporateServiceConfigResource extends JsonResource
'corporate_id' => $this->corporate_id,
'service_code' => $this->service_code,
'status' => $this->status,
'name' => $this->service->name,
'description' => $this->service->description,
'name' => $this->service->name ?? '-',
'description' => $this->service->description ?? '-',
'configurations' => $this->configs->pluck('value', 'name'),
'selected_specialities' => $this->corporateServiceSpecialities->where('active', true)->pluck('speciality.name', 'speciality_id'),
'exclusions' => $this->corporateServiceSpecialities->map(function ($speciality) {

View File

@@ -6,8 +6,11 @@ use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\Icd;
use App\Models\Member;
use App\Models\Claim;
use App\Models\Speciality;
use App\Services\ClaimService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class ClaimController extends Controller
{
@@ -16,19 +19,23 @@ class ClaimController extends Controller
$request->validate([
'member_id' => 'required',
'user_id' => 'required',
'type' => 'required|in:consultation-gp,consultation-specialist,medicine',
'type' => 'required|in:consultation,teleconsultation,medicine',
// 'speciality_code' => 'required',
'total_claim' => 'required',
'detail' => 'required',
]);
$currentSpeciality = Speciality::where('code', $request->speciality_code)->first();
if ($request->type == 'consultation-gp') {
$benefitCode = 'OPCONS1';
}
if ($request->type == 'consultation-specialist') {
$benefitCode = 'OPCONS2';
}
$gpSpecialityName = config('aso.general_practitioner_speciality_name', 'Umum');
$isGp = $gpSpecialityName == ($currentSpeciality ? $currentSpeciality->name : false);
if ($request->type == 'medicine') {
$benefitCode = 'OPMEDI1';
} else if ($isGp) {
$benefitCode = 'OPCONS1';
} else {
$benefitCode = 'OPCONS2';
}
$member = Member::query()
@@ -38,12 +45,44 @@ class ClaimController extends Controller
])
->firstOrFail();
$benefit = $member->currentPlan->benefits()->where('code', $benefitCode)->first();
// $diagnosis = Icd::first();
$claim = ClaimService::storeClaim($member, null, $request->total_claim, $benefit, 'requested');
$claim->status = 'approved';
$claim->save();
return Helper::responseJson($claim);
}
public function updateClaimDiagnosis(Request $request)
{
$request->validate([
'claim_code' => 'required',
'icd_codes' => 'required'
]);
$claim = Claim::where('code', $request->claim_code)->firstOrFail();
try {
DB::beginTransaction();
$claim->fill(['status' => 'postpone'])->update();
$icds = Icd::whereIn('code', $request['icd_codes'])->get();
$icds = $icds->map(function($icd) use ($claim) {
return [
'claim_id' => $claim->id,
'type' => 'primary',
'diagnosis_id' => $icd->id,
'note' => 'HIS Summary',
'description'=> ''
];
})->toArray();
return $claim->diagnoses()->insert($icds);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
return Helper::responseJson($e, 500);
};
}
}

View File

@@ -11,7 +11,7 @@ use Illuminate\Http\Request;
class MembershipController extends Controller
{
//
public function check(Request $request)
public function check(Request $request)
{
$request->validate([
'member_id' => 'required',
@@ -25,7 +25,7 @@ class MembershipController extends Controller
}
if (!$member->active) {
return Helper::responseJson(statusCode: 406, message: 'The Member '.$request->member_id.' is Inactive.', status: 'error');
return Helper::responseJson(statusCode: 406, message: 'The Member ' . $request->member_id . ' is Inactive.', status: 'error');
}
return Helper::responseJson(data: $member, message: 'Member Found');
@@ -35,67 +35,31 @@ class MembershipController extends Controller
{
$request->validate([
'member_id' => 'required',
'type' => 'required|in:consultation-gp,consultation-specialist,medicine',
'type' => 'required|in:consultation,teleconsultation,medicine',
// 'speciality_code' => 'sometimes'
]);
if ($request->type == 'consultation-gp') {
$benefitCode = 'OPCONS1';
}
if ($request->type == 'consultation-specialist') {
$benefitCode = 'OPCONS2';
}
if ($request->type == 'medicine') {
$benefitCode = 'OPMEDI1';
}
$member = Member::query()
->where('member_id', $request->member_id)
->with(['currentCorporate', 'currentPolicy', 'currentPlan', 'postponedClaims'])
->first();
$member = Member::where('member_id', $request->member_id)->with(['currentCorporate', 'currentPolicy', 'currentPlan', 'postponedClaims'])->first();
$limits = ClaimService::showMemberBenefitLimit($member, $benefitCode);
$limits['postponed_claims'] = $member->postponedClaims;
$limits['postponed_claims_payment_url'] = "http://google.com";
$limits['postponed_claims_unpaid_total'] = $member->postponedClaims->sum('total_claim');
$corporateService = $member->currentCorporate->corporateServices()
->active()
->where('service_code', 'OP')
->with([
'configs',
'specialities' => function ($speciality) use ($request) {
$speciality->where('code', $request->speciality_code ?? null)
->wherePivot('active', 1);
}
])
->first();
if ($request->has('speciality_code') && !empty($request->speciality_code)) {
$corporateService = $member->currentCorporate
->corporateServices()
->active()
->where('service_code', 'OP')
->with([
'specialities' => function ($speciality) use ($request) {
$speciality->where('code', $request->speciality_code)
->wherePivot('active', 1);
}])
->first();
// $rules = $corporateServiceConfigs->
// dd($corporateServiceConfigs->toArray());
if (empty($corporateService)) {
$limit['coverage'] = [
'benefit' => false,
'admin_fee' => false,
'delivery_fee' => false
];
$currentSpeciality = $corporateService->specialities->first();
return Helper::responseJson(data: $limits);
}
if (empty($corporateService->specialities)) {
$limit['coverage'] = [
'benefit' => false,
'admin_fee' => false,
'delivery_fee' => false
];
return Helper::responseJson(data: $limits);
}
$currentSpeciality = $corporateService->specialities->first();
// Load the Relation Data after speciality check is supported
if ($currentSpeciality) {
$corporateService->load([
'configs',
// 'configs.exclusions.rules',
'corporateServiceSpecialities' => function ($corporateServiceSpeciality) use ($currentSpeciality) {
$corporateServiceSpeciality->where('speciality_id', $currentSpeciality->id);
},
@@ -104,114 +68,103 @@ class MembershipController extends Controller
},
'corporateServiceSpecialities.exclusions.rules'
]);
}
$configs = $corporateService->configs->mapWithKeys(function ($config) {
return [$config->name => $config];
});
$corporateServiceSpeciality = $corporateService->corporateServiceSpecialities->first() ?? null;
$serviceSpeciality = $corporateService->corporateServiceSpecialities->first() ?? null;
$serviceSpecialityRules = $serviceSpeciality->exclusions->first()->rules ?? collect([]);
$serviceSpecialityRules = $serviceSpecialityRules->mapWithKeys(function ($rule) {
return [$rule->name => $rule];
});
$serviceSpecialityRules = $corporateServiceSpeciality->exclusions->first()->rules ?? collect([]);
$serviceSpecialityRules = $serviceSpecialityRules->mapWithKeys(function ($rule) {
return [$rule->name => $rule];
});
$gpSpecialityName = config('aso.general_practitioner_speciality_name', 'Umum');
// dd($serviceSpecialityRules->toArray());
$configs = $corporateService->configs->mapWithKeys(function ($config) {
return [$config->name => $config];
});
$coverage = [
'benefit' => false,
'admin_fee' => false,
'delivery_fee' => false
];
$gpSpecialityName = config('aso.general_practitioner_speciality_name', 'Umum');
$isGp = $gpSpecialityName == ($currentSpeciality ? $currentSpeciality->name : false);
// dd($configs->toArray());
// dd($gpSpecialityName, $currentSpeciality->name);
if ($gpSpecialityName == $currentSpeciality->name) {
// To General Practitioner
if (($configs['gp_internal_doctor_online']['value'] ?? 1) == 1) {
$coverage['benefit'] = true;
}
if (($configs['general_practitioner_fee']['value'] ?? 1) == 1) {
$coverage['admin_fee'] = true;
}
if ($serviceSpeciality->active == 1) {
$coverage['benefit'] = true;
}
} else {
// To Specialist
if (($configs['sp_internal_doctor_online']['value'] ?? 1) == 1) {
$coverage['benefit'] = true;
}
// dd($configs['specialist_practitioner_fee']['value'], $configs['specialist_practitioner_fee']['value'] ?? 1, ($configs['specialist_practitioner_fee']['value'] ?? 1) == 1);
if (($configs['specialist_practitioner_fee']['value'] ?? 1) == 1) {
$coverage['admin_fee'] = true;
}
if ($serviceSpeciality->active == 1) {
$coverage['benefit'] = true;
}
}
// TODO THIS EXCLUSION IS USED AS INCLUSION NOW, MUST BE CHANGE TO USED AS EXCLUSION AND MAYBE MOVE THE TABLE
$excluded = [];
foreach ($serviceSpecialityRules as $ruleName => $rule) {
if ($ruleName == 'msc') {
$values = explode(',', $rule->values);
if (!in_array(strtolower($member->marital_status), $values)) {
$excluded[] = $rule;
}
}
if ($ruleName == 'gender') {
$values = explode(',', $rule->values);
if (!in_array(strtolower($member->gender), $values)) {
$excluded[] = $rule;
}
}
if ($ruleName == 'min_age') {
if (!empty($rule->values) && $member->age < $rule->values) {
$excluded[] = $rule;
}
}
if ($ruleName == 'max_age') {
if (!empty($rule->values) && $member->age > $rule->values) {
$excluded[] = $rule;
}
}
if ($ruleName == 'plan') {
$values = explode(',', $rule->values);
if (!in_array($member->currentPlan->code, $values)) {
$excluded[] = $rule;
}
}
}
if ( count($excluded) ) {
$coverage['benefit'] = false;
$coverage['benefit_exclusion'] = $excluded;
} else {
$coverage['benefit'] = true;
}
$limits['coverage'] = $coverage;
if ($request->type == 'medicine') {
$benefitCode = 'OPMEDI1';
} else if ($isGp) {
$benefitCode = 'OPCONS1';
} else {
$benefitCode = 'OPCONS2';
}
$limits['coverage'] = [
'benefit' => true,
'admin_fee' => true,
'delivery_fee' => true
];
$limits = ClaimService::showMemberBenefitLimit($member, $benefitCode);
$limits['postponed_claims'] = $member->postponedClaims;
$limits['postponed_claims_payment_url'] = route('postpone-pay', $member->member_id);
$limits['postponed_claims_unpaid_total'] = $member->postponedClaims->sum('total_claim');
$coverage['medicine_benefit'] = false;
if ($benefitCode = 'OPMEDI1') {
$medicineBenefit = $member->currentPlan->benefits()->where('code', $benefitCode)->wherePivot('active', 1)->first();
$coverage['medicine_benefit'] = !empty($medicineBenefit);
}
$coverage['medicine_delivery_fee'] = (($configs['delivery_fee']['value'] ?? 1) == 1);
if ($currentSpeciality) {
$xCoverage['sp_consultation_benefit'] = (($configs['sp_internal_doctor_offline']['value'] ?? 1) == 1);
$xCoverage['sp_teleconsultation_benefit'] = (($configs['sp_internal_doctor_online']['value'] ?? 1) == 1);
$xCoverage['gp_consultation_benefit'] = (($configs['gp_internal_doctor_offline']['value'] ?? 1) == 1);
$xCoverage['gp_teleconsultation_benefit'] = (($configs['gp_internal_doctor_online']['value'] ?? 1) == 1);
$coverage['consultation_benefit'] = ($isGp)
? $xCoverage['gp_consultation_benefit']
: $xCoverage['sp_consultation_benefit'];
$coverage['teleconsultation_benefit'] = ($isGp)
? $xCoverage['gp_teleconsultation_benefit']
: $xCoverage['sp_teleconsultation_benefit'];
$xCoverage['sp_admin_fee'] = (($configs['specialist_practitioner_fee']['value'] ?? 1) == 1);
$xCoverage['gp_admin_fee'] = (($configs['general_practitioner_fee']['value'] ?? 1) == 1);
$coverage['admin_fee'] = ($isGp)
? $xCoverage['gp_admin_fee']
: $xCoverage['sp_admin_fee'];
} else {
// Not Supported
$coverage['consultation_benefit'] = false;
$coverage['teleconsultation_benefit'] = false;
$coverage['admin_fee'] = false;
}
$limits['coverage'] = $coverage;
// TODO THIS EXCLUSION IS USED AS INCLUSION NOW, MUST BE CHANGE TO USED AS EXCLUSION AND MAYBE MOVE THE TABLE
$excluded = [];
foreach ($serviceSpecialityRules as $ruleName => $rule) {
if ($ruleName == 'msc') {
$values = explode(',', $rule->values);
if (!in_array(strtolower($member->marital_status), $values)) {
$excluded[] = $rule;
}
}
if ($ruleName == 'gender') {
$values = explode(',', $rule->values);
if (!in_array(strtolower($member->gender), $values)) {
$excluded[] = $rule;
}
}
if ($ruleName == 'min_age') {
if (!empty($rule->values) && $member->age < $rule->values) {
$excluded[] = $rule;
}
}
if ($ruleName == 'max_age') {
if (!empty($rule->values) && $member->age > $rule->values) {
$excluded[] = $rule;
}
}
if ($ruleName == 'plan') {
$values = explode(',', $rule->values);
if (!in_array($member->currentPlan->code, $values)) {
$excluded[] = $rule;
}
}
}
return Helper::responseJson(data: $limits);

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Http\Controllers\Api\OLDLMS;
use App\Http\Controllers\Controller;
use App\Models\Member;
use App\Services\Duitku;
use Illuminate\Http\Request;
use Str;
class PaymentController extends Controller
{
public function postponePay($memberId)
{
$member = Member::where('member_id', $memberId)->with('postponedClaims')->firstOrFail();
$totalBill = $member->postponedClaims->sum('total_claim');
$config_duitku = [
'merchant_code' => env('DUITKU_MERCHANT_CODE'),
'merchant_key' => env('DUITKU_MERCHANT_KEY'),
];
$paymentService = new Duitku($config_duitku);
$invoice = (object) [
'invoice_number' => 'INV'.Str::random(5, 5),
];
$user = (object) [
'email' => $member->email,
'phone' => $member->phone,
'name' => $member->name,
'last_name' => $member->last_name ?? '',
'address' => collect([
'line' => 'Alamat',
'city' => (object) [
'name' => 'Tangerang Selatan'
]
]),
'postal_code' => '124123',
];
$paymentCreate = (object) [
'transaction_id' => Str::random(10, 10)
];
$paymentMethod = (object) [
'code' => 'BC',
'timeout' => 60
];
$paymentService->applyInvoice($user, $invoice, $paymentCreate, $totalBill, $paymentMethod);
$duitkuPayment = $paymentService->createPayment();
return redirect($duitkuPayment->paymentUrl);
}
}

View File

@@ -18,6 +18,15 @@ class Benefit extends Model
'active'
];
protected $hidden = [
"created_at",
"updated_at",
"deleted_at",
"created_by",
"updated_by",
"deleted_by",
];
public function scopeFilter($query, array $filters)
{
$query->when($filters['search'] ?? false, function ($query, $search) {

View File

@@ -11,12 +11,13 @@ 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 Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
class Claim extends Model
{
use HasFactory, Blameable;
use HasFactory, Blameable, SoftDeletes;
protected $fillable = [
'code',

View File

@@ -0,0 +1,57 @@
<?php
namespace App\Models;
use App\Traits\Blameable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class ClaimRequest extends Model
{
use HasFactory, SoftDeletes, Blameable;
protected static $code_prefix = 'CRQ';
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
try {
$model->code = self::getNextCode();
} catch (\Exception $e) {
abort(500, $e->getMessage());
}
});
}
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 $fillable = [
'submission_date',
'member_id',
'status'
];
public function files()
{
return $this->morphMany(File::class, 'fileable');
}
public function member()
{
return $this->belongsTo(Member::class, 'member_id', 'id');
}
}

View File

@@ -215,6 +215,11 @@ class CorporateBenefit extends Model
return $this->belongsTo(Plan::class);
}
public function scopeActive($query)
{
$query->where('active', 1);
}
public function scopeFilter($query, array $filters)
{
$query->when($filters['search'] ?? false, function ($query, $search) {

View File

@@ -4,10 +4,11 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class CorporateManager extends Model
{
use HasFactory;
use HasFactory, SoftDeletes;
protected $table = 'corporate_manager';
}

View File

@@ -16,10 +16,20 @@ class File extends Model
'fileable_id',
'type',
'name',
'original_name',
'extension',
'path',
];
protected $hidden = [
'created_at',
'updated_at',
'deleted_at',
'created_by',
'updated_by',
'deleted_by',
];
public $appends = [
'url'
];
@@ -27,7 +37,8 @@ class File extends Model
public static $file_directories = [
'import-temp' => 'import-temp/',
'avatar' => 'user-avatar/',
'dataDiri' => 'data-diri/'
'dataDiri' => 'data-diri/',
'claim' => 'claim/'
];
public function fileable()
@@ -45,6 +56,11 @@ class File extends Model
return $type . '-' . $id . '-' . Str::random(10);
}
public function getNameAttribute($value)
{
return !empty($this->original_name) ? $this->original_name : ($value . '.' . $this->extension);
}
public function getUrlAttribute()
{
return url(Storage::url($this->path));

View File

@@ -192,12 +192,13 @@ class Member extends Model
public function getNameAttribute()
{
return $this->person->name ?? null;
return $this->person->name ?? ($this->name ?? null);
}
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()

View 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 Dokter extends Model
{
use HasFactory, SoftDeletes;
const CREATED_AT = 'dCreateOn';
const UPDATED_AT = 'dUpdateOn';
const DELETED_AT = 'dDeleteOn';
protected $connection = 'oldlms';
protected $table = 'tm_dokter';
protected $primaryKey = 'nID';
public function jadwalDokter()
{
return $this->hasMany(JadwalDokter::class, 'nIDDokter', 'nID');
}
}

View File

@@ -4,8 +4,24 @@ namespace App\Models\OLDLMS;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Healthcare extends Model
{
use HasFactory;
use HasFactory, SoftDeletes;
const CREATED_AT = 'dCreateOn';
const UPDATED_AT = 'dUpdateOn';
const DELETED_AT = 'dDeleteOn';
protected $connection = 'oldlms';
protected $table = 'tm_healthcare';
protected $primaryKey = 'nID';
public function jadwalDokter()
{
return $this->hasMany(JadwalDokter::class, 'nIDHealthCare', 'nID');
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Models\OLDLMS;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class JadwalDokter extends Model
{
use HasFactory, SoftDeletes;
const CREATED_AT = 'dCreateOn';
const UPDATED_AT = 'dUpdateOn';
const DELETED_AT = 'dDeleteOn';
protected $connection = 'oldlms';
protected $table = 'tx_jadwal_dokter';
protected $primaryKey = 'nID';
public function jadwalDokterDay()
{
return $this->hasMany(JadwalDokterDay::class, 'nIDJadwalDokter', 'nID');
}
public function healthcare()
{
return $this->belongsTo(Healthcare::class, 'nIDHealthCare', 'nID');
}
}

View 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 JadwalDokterDay extends Model
{
use HasFactory, SoftDeletes;
const CREATED_AT = 'dCreateOn';
const UPDATED_AT = 'dUpdateOn';
const DELETED_AT = 'dDeleteOn';
protected $connection = 'oldlms';
protected $table = 'tx_jadwal_dokter_detail';
protected $primaryKey = 'nID';
}

View File

@@ -179,10 +179,66 @@ class Plan extends Model
public function benefits()
{
return $this->belongsToMany(Benefit::class, 'corporate_benefits', 'plan_id', 'id')
return $this->belongsToMany(Benefit::class, 'corporate_benefits', 'plan_id', 'benefit_id')
->withTimestamps()
->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');
}
public function service()
{
return $this->belongsTo(Service::class, 'service_code', 'code');
}
}

View File

@@ -14,4 +14,9 @@ class Service extends Model
'name',
'description',
];
public function corporateService()
{
return $this->hasMany(CorporateService::class, 'service_code', 'code');
}
}

View File

@@ -7,10 +7,11 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
use HasApiTokens, HasFactory, Notifiable, HasRoles;
/**
* The attributes that are mass assignable.
@@ -48,13 +49,26 @@ class User extends Authenticatable
];
public $with = [
'metas'
'metas',
'person'
];
public $appends = [
'meta'
'meta',
'avatar_url',
'full_name'
];
public function getAvatarUrlAttribute()
{
return asset('images/specialities/anak.png');
}
public function getFullNameAttribute()
{
return $this->person?->full_name;
}
public function getMetaAttribute()
{
$orgMeta = [];

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class DuitkuServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
require_once app_path() . '/Services/Duitku.php';
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
}

View File

@@ -112,7 +112,12 @@ class ClaimService{
// $policy = $member->currentPolicy;
// $corporate = $member->currentCorporate;
$benefit = $member->currentPlan->benefits()->where('code', $benefit_code)->first();
$corporateBenefit = $member->currentPlan->corporateBenefits()->where('benefit_id', $benefit->id)->first();
$corporateBenefit = $member->currentPlan
->corporateBenefits()
->where('benefit_id', $benefit->id ?? null)
->where('plan_id', $member->currentPlan->id)
->active()
->first();
// dd($benefit->toArray());
// dd(compact(['plan', 'policy', 'corporate', 'benefit']));
@@ -128,7 +133,7 @@ class ClaimService{
'usage_yearly' => null
];
switch ($corporateBenefit->max_frequency_period) {
switch ($corporateBenefit->max_frequency_period ?? 0) {
case(0) :
$limits['usage_yearly'] = $member->claims()->used(Carbon::now()->firstOfYear(), now())->count();
$limits['total_claim'] = $member->claims()->used(Carbon::now()->firstOfYear(), now())->sum('total_claim');
@@ -153,7 +158,7 @@ class ClaimService{
// return null;
break;
}
$limits['remaining_limit'] = $corporateBenefit->limit_amount - $limits['total_claim'];
$limits['remaining_limit'] = ($corporateBenefit->limit_amount ?? 0) - $limits['total_claim'];
return $limits;
}

228
app/Services/Duitku.php Normal file
View File

@@ -0,0 +1,228 @@
<?php
namespace App\Services;
// use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Duitku\Config;
use Exception;
class Duitku
{
public function __construct($config_duitku)
{
$merchantKey = $config_duitku['merchant_key'];
$merchantCode = $config_duitku['merchant_code'];
$this->duitkuConfig = new Config($merchantKey, $merchantCode);
$this->duitkuConfig->setSandboxMode(env('DUITKU_SANDBOX', true));
// $duitkuConfig = new \Duitku\Config("3b4264fb0118bab008448a67e83f6cbe", "DS12798");
// // false for production mode
// // true for sandbox mode
// $duitkuConfig->setSandboxMode(true);
}
public function applyInvoice($patient, $invoices, $paymentCreate, $total_price, $paymentMethods)
{
$paymentMethod = $paymentMethods->code;
$paymentAmount = $total_price; // Amount
$email = $patient->email ?? ''; //"customer@gmail.com"; // your customer email
$phoneNumber = $patient->phone ?? ''; //"081234567890"; // your customer phone number (optional)
$productDetails = $invoices->invoice_number;
$merchantOrderId = $paymentCreate->transaction_id; // from merchant, unique
// dd($merchantOrderId);
$additionalParam = ''; // optional
$merchantUserInfo = ''; // optional
$customerVaName = $patient->name ?? ''; // display name on bank confirmation display
$callbackUrl = env('DUITKU_PAYMENT_CALLBACK_URL'); // url for callback
$returnUrl = 'https://dev-superapp.primaya.id';
$expiryPeriod = $paymentMethods->timeout; // set the expired time in minutes
// Customer Detail
$firstName = $patient->name ?? '';
// dd($firstName);
$lastName = $patient->last_name ?? '';
// Address
$alamat = $patient->address->first()->line ?? '';
// dd($alamat);
$city = $patient->address->first()->city->name ?? '';
// dd($city);
$postalCode = $patient->postal_code ?? '';
$countryCode = "ID";
$address = array(
'firstName' => $firstName,
'lastName' => $lastName,
'address' => $alamat,
'city' => $city,
'postalCode' => $postalCode,
'phone' => $phoneNumber,
'countryCode' => $countryCode
);
$customerDetail = array(
'firstName' => $firstName,
'lastName' => $lastName,
'email' => $email,
'phoneNumber' => $phoneNumber,
'billingAddress' => $address,
// 'shippingAddress' => $address
);
// $itemDetails = [];
// foreach ($invoices->items as $item) {
// $itemDetails[] = [
// 'name' => $invoices->invoice_number,
// 'price' => (int) $item->price_net,
// 'quantity' => 1,
// ];
// }
$itemDetails = array(
array(
'name' => $invoices->invoice_number,
'price' => (int) $total_price,
'quantity' => 1,
)
);
$params = array(
'paymentMethod' => $paymentMethod,
'paymentAmount' => (int) $paymentAmount,
'merchantOrderId' => $merchantOrderId,
'productDetails' => $productDetails,
'additionalParam' => $additionalParam,
'merchantUserInfo' => $merchantUserInfo,
'customerVaName' => $customerVaName,
'email' => $email,
'phoneNumber' => $phoneNumber,
'itemDetails' => $itemDetails,
'customerDetail' => $customerDetail,
'callbackUrl' => $callbackUrl,
'returnUrl' => $returnUrl,
'expiryPeriod' => $expiryPeriod
);
$this->transaction_details = $params;
return $this;
}
public function createPayment()
{
try {
// createInvoice Request
$responseDuitku = \Duitku\Api::createInvoice($this->transaction_details, $this->duitkuConfig);
return json_decode($responseDuitku);
} catch (\Exception $e) {
throw $e;
}
}
public function checkTransaction($paymentCreate)
{
try {
// $merchantOrderId = "96ce0853-35e2-4809-97bf-47463d236773";
$merchantOrderId = $paymentCreate->first()->transaction_id;
// dd($merchantOrderId);
$transactionList = \Duitku\Api::transactionStatus($merchantOrderId, $this->duitkuConfig);
header('Content-Type: application/json');
$transaction = json_decode($transactionList);
// var_dump($transactionList);
if ($transaction->statusCode == "00") {
return response()->json([
'data' => $transaction
]);
} else if ($transaction->statusCode == "01") {
return response()->json([
'data' => $transaction
]);
} else {
return response()->json([
'data' => $transaction
]);
// Action Failed Or Expired
}
} catch (Exception $e) {
echo $e->getMessage();
}
}
public static function getSignature($merchantCode, $amount, $merchantOrderId, $apiKey)
{
$params = $merchantCode . $amount . $merchantOrderId . $apiKey;
// DS12798
// 110.000,00
// 96ce58d2-0aec-4a1a-b0b1-c96c0e2ff2d8
// 3b4264fb0118bab008448a67e83f6cbe
return md5($params);
}
public function validateCallback($config_duitku, $merchantCode, $amount, $merchantOrderId, $signature)
{
$apiKey = $config_duitku['merchant_key'];
if (!empty($merchantCode) && !empty($amount) && !empty($merchantOrderId) && !empty($signature)) {
$this->params = $merchantCode . $amount . $merchantOrderId . $apiKey;
$calcSignature = $this->getSignature($merchantCode, $amount, $merchantOrderId, $apiKey);
if ($signature == $calcSignature) {
return true;
} else {
throw new \Exception('Bad Signature');
}
} else {
throw new \Exception('Bad Parameter');
}
}
public function translatePaymentStatus($paymentStatusCode)
{
switch ($paymentStatusCode) {
case '00':
$status = 'success';
break;
default:
$status = 'failed';
break;
}
return $status;
}
public function paymentMethod()
{
try {
$paymentAmount = "10000"; //"YOUR_AMOUNT";
$paymentMethodList = \Duitku\Api::getPaymentMethod($paymentAmount, $this->duitkuConfig);
header('Content-Type: application/json');
// return
$paymentMethod = json_decode($paymentMethodList);
return response()->json($paymentMethod->paymentFee);
// echo $paymentMethodList->paymentFee;
} catch (Exception $e) {
echo $e->getMessage();
}
}
}

View File

@@ -39,19 +39,36 @@ class LmsApi
$data['channel'] = 'Website';
}
$res = self::http()->post( self::baseUrl() . '/jadwaldokter', $data)->json();
$res = self::http()->post(self::baseUrl() . '/jadwaldokter', $data)->json();
// Reformat Jam Data
$res['data'] = collect($res['data'])->map(function($day) {
$res['data'] = collect($res['data'])->map(function ($day) {
$day['Jam'] = !empty($day['Jam']) ? explode(', ', $day['Jam']) : null;
return $day;
})->toArray();
return $res;
}
/**
* dokter
*
*
*/
public static function dokter($kodeRs, $channel = 'hospitaloka', $timeout = 30)
{
$data = [
'rs' => $kodeRs,
'channel' => $channel,
];
$res = self::http()->timeout($timeout)->post('http://lmsapi.primaya.id/dokter', $data)->json();
return $res;
}
/**
* jadwalDokterTersedia
*
@@ -72,21 +89,20 @@ class LmsApi
$data['channel'] = 'Website';
}
$res = self::http()->post( self::baseUrl() . '/jadwaldoktertersedia', $data)->json();
$res = self::http()->post(self::baseUrl() . '/jadwaldoktertersedia', $data)->json();
// Reformat Jam Data
$res['data'] = collect($res['data'])->map(function($day) {
$res['data'] = collect($res['data'])->map(function ($day) {
// Change jam to Jam to Standarize
$day['Jam'] = !empty($day['jam']) ? explode(', ', $day['jam']) : null;
unset($day['jam']);
return $day;
})->toArray();
return $res;
}
/**
* checkMedrec
*
@@ -113,11 +129,11 @@ class LmsApi
throw new Exception('name, birth_date, nik, phone are required in $patientData');
}
$res = self::http()->post( self::baseUrl() . '/medrec_nama', $data)->json();
$res = self::http()->post(self::baseUrl() . '/medrec_nama', $data)->json();
return $res;
}
/**
* checkGantung
*
@@ -126,7 +142,7 @@ class LmsApi
* @return void
*/
public static function checkGantung($HISKodeRS, $HISMedrec, $patientData)
{
{
$data = [
'rs' => $HISKodeRS,
'rm' => $HISMedrec,
@@ -141,11 +157,11 @@ class LmsApi
throw new Exception('name, birth_date are required in $patientData');
}
$res = self::http()->post( self::baseUrl() . '/cek_gantung', $data)->json();
$res = self::http()->post(self::baseUrl() . '/cek_gantung', $data)->json();
return $res;
}
/**
* checkSlot
*
@@ -156,9 +172,9 @@ class LmsApi
* @param string $type HIS Slot Type walkin, teleconsultation
* @return void
*/
public static function checkSlot( $HISKodeRS, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $type )
public static function checkSlot($HISKodeRS, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $type)
{
$data = [
'rs' => $HISKodeRS,
'dr' => $HISKodeDokter,
@@ -169,11 +185,11 @@ class LmsApi
$data['channel'] = 'Website';
}
$res = self::http()->post( self::baseUrl() . '/cek_slot', $data)->json();
$res = self::http()->post(self::baseUrl() . '/cek_slot', $data)->json();
return $res;
}
/**
* appointmentBaru
*
@@ -189,7 +205,8 @@ class LmsApi
* @param mixed $userId
* @return void
*/
public static function appointmentBaru( $HISKodeRS, $HISKodeDep, $HISKodeDokter, $jenisTC, $tanggalAppointment, $jamAppointment, $jumlahBayar, $kodePembayaran, $patientData, $userId ) {
public static function appointmentBaru($HISKodeRS, $HISKodeDep, $HISKodeDokter, $jenisTC, $tanggalAppointment, $jamAppointment, $jumlahBayar, $kodePembayaran, $patientData, $userId)
{
$data = [
'rs' => $HISKodeRS,
'dep' => $HISKodeDep,
@@ -220,11 +237,11 @@ class LmsApi
'jam' => $jamAppointment,
];
$res = self::http()->post( self::baseUrl() . '/appointment_baru', $data)->json();
$res = self::http()->post(self::baseUrl() . '/appointment_baru', $data)->json();
return $res;
}
/**
* appointment
*
@@ -241,7 +258,8 @@ class LmsApi
* @param mixed $userId
* @return void
*/
public static function appointment( $HISKodeRS, $HISKodeDep, $HISKodeDokter, $jenisTC, $tanggalAppointment, $jamAppointment, $jumlahBayar, $kodePembayaran, $HISMedrec, $patientData, $userId ) {
public static function appointment($HISKodeRS, $HISKodeDep, $HISKodeDokter, $jenisTC, $tanggalAppointment, $jamAppointment, $jumlahBayar, $kodePembayaran, $HISMedrec, $patientData, $userId)
{
$data = [
'rs' => $HISKodeRS,
'dep' => $HISKodeDep,
@@ -259,11 +277,11 @@ class LmsApi
'jam' => $jamAppointment,
];
$res = self::http()->post( self::baseUrl() . '/appointment', $data)->json();
$res = self::http()->post(self::baseUrl() . '/appointment', $data)->json();
return $res;
}
/**
* appointmentEdit
*
@@ -277,7 +295,7 @@ class LmsApi
* @param mixed $patientData
* @return void
*/
public static function appointmentEdit( $HISRegid, $HISKodeRS, $HISKodeDep, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $HISMedrec, $patientData )
public static function appointmentEdit($HISRegid, $HISKodeRS, $HISKodeDep, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $HISMedrec, $patientData)
{
$data = [
'regid' => $HISRegid,
@@ -293,11 +311,11 @@ class LmsApi
'jam' => $jamAppointment,
];
$res = self::http()->post( self::baseUrl() . '/appointment_edit', $data)->json();
$res = self::http()->post(self::baseUrl() . '/appointment_edit', $data)->json();
return $res;
}
/**
* booking
*
@@ -314,7 +332,8 @@ class LmsApi
* @param mixed $nomorRujukanBPJS
* @return void
*/
public static function booking( $HISKodeRS, $HISKodeDep, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $HISMedrec, $patientData, $jenisPenjamin = 0, $namaPenjamin = '', $nomorKartuBPJS = null, $nomorRujukanBPJS = null ) {
public static function booking($HISKodeRS, $HISKodeDep, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $HISMedrec, $patientData, $jenisPenjamin = 0, $namaPenjamin = '', $nomorKartuBPJS = null, $nomorRujukanBPJS = null)
{
$data = [
'rs' => $HISKodeRS,
'dep' => $HISKodeDep,
@@ -334,11 +353,11 @@ class LmsApi
'norujukan' => $nomorRujukanBPJS
];
$res = self::http()->post( self::baseUrl() . '/booking', $data)->json();
$res = self::http()->post(self::baseUrl() . '/booking', $data)->json();
return $res;
}
/**
* bookingBaru
*
@@ -354,7 +373,8 @@ class LmsApi
* @param mixed $nomorRujukanBPJS
* @return void
*/
public static function bookingBaru( $HISKodeRS, $HISKodeDep, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $patientData, $jenisPenjamin = 0, $namaPenjamin = '', $nomorKartuBPJS = null, $nomorRujukanBPJS = null) {
public static function bookingBaru($HISKodeRS, $HISKodeDep, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $patientData, $jenisPenjamin = 0, $namaPenjamin = '', $nomorKartuBPJS = null, $nomorRujukanBPJS = null)
{
$data = [
'rs' => $HISKodeRS,
'dep' => $HISKodeDep,
@@ -385,12 +405,12 @@ class LmsApi
'nokartu' => $nomorKartuBPJS,
'norujukan' => $nomorRujukanBPJS
];
$res = self::http()->post( self::baseUrl() . '/booking_baru', $data)->json();
$res = self::http()->post(self::baseUrl() . '/booking_baru', $data)->json();
return $res;
}
/**
* bookingEdit
* Used for Rescheduling appointment
@@ -409,7 +429,8 @@ class LmsApi
* @param mixed $nomorRujukanBPJS
* @return void
*/
public static function bookingEdit( $kodeBooking, $HISKodeRS, $HISKodeDep, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $tanggalAppointmentBaru, $jamAppointmentBaru, $jenisPenjamin = 0, $namaPenjamin = '', $nomorKartuBPJS = null, $nomorRujukanBPJS = null ) {
public static function bookingEdit($kodeBooking, $HISKodeRS, $HISKodeDep, $HISKodeDokter, $tanggalAppointment, $jamAppointment, $tanggalAppointmentBaru, $jamAppointmentBaru, $jenisPenjamin = 0, $namaPenjamin = '', $nomorKartuBPJS = null, $nomorRujukanBPJS = null)
{
$data = [
'kodebooking' => $kodeBooking,
'rs' => $HISKodeRS,
@@ -424,16 +445,16 @@ class LmsApi
'tglbaru' => $tanggalAppointmentBaru,
'jambaru' => $jamAppointmentBaru,
];
$res = self::http()->post( self::baseUrl() . '/booking_edit', $data)->json();
$res = self::http()->post(self::baseUrl() . '/booking_edit', $data)->json();
return $res;
}
public static function bookingPaket($kodeRs, $kodeDep, $rm, $ktp, $nama_pasien, $tgl_lahir, $email, $telp, $tgl, $jam, $jenis_penjamin, $penjamin, $paket, $jenis_paket)
{
throw new Exception("Not Implemented", 1);
$url = Http::withHeaders([
'id' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjE3NWZiNDI0LTA4MzMtNGZiMS1iOWNhLWQwMzQ5Nzc'
])->post('http://lmsapidev.primaya.id/booking_paket', [
@@ -485,7 +506,7 @@ class LmsApi
$jenis_paket
) {
throw new Exception("Not Implemented", 1);
$url = Http::withHeaders([
'id' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjE3NWZiNDI0LTA4MzMtNGZiMS1iOWNhLWQwMzQ5Nzc'
])->post('http://lmsapidev.primaya.id/booking_baru_paket', [
@@ -537,7 +558,7 @@ class LmsApi
$jenis_paket
) {
throw new Exception("Not Implemented", 1);
$url = Http::withHeaders([
'id' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjE3NWZiNDI0LTA4MzMtNGZiMS1iOWNhLWQwMzQ5Nzc'
])->post('http://lmsapidev.primaya.id/booking_edit_paket', [
@@ -558,7 +579,7 @@ class LmsApi
return $url;
}
public static function bookingBayar( $kodeBooking, $HISKodeRS, $tanggalBooking, $jumlahBayar, $merchantCode, $merchantOrderId, $reference)
public static function bookingBayar($kodeBooking, $HISKodeRS, $tanggalBooking, $jumlahBayar, $merchantCode, $merchantOrderId, $reference)
{
$data = [
"rs" => $HISKodeRS,
@@ -570,9 +591,9 @@ class LmsApi
'merchantorderid' => $merchantOrderId,
'reference' => $reference,
];
$res = self::http()->post( self::baseUrl() . '/booking_bayar', $data)->json();
$res = self::http()->post(self::baseUrl() . '/booking_bayar', $data)->json();
return $res;
}
@@ -603,4 +624,4 @@ class LmsApi
return $url;
}
}
}

View File

@@ -6,15 +6,20 @@
"license": "MIT",
"require": {
"php": "^8.0.2",
"barryvdh/laravel-snappy": "^1.0",
"box/spout": "^3.3",
"duitkupg/duitku-php": "dev-master",
"guzzlehttp/guzzle": "^7.2",
"h4cc/wkhtmltopdf-amd64": "0.12.x",
"laravel/framework": "^9.11",
"laravel/sanctum": "^2.15",
"laravel/socialite": "^5.5",
"laravel/tinker": "^2.7",
"maatwebsite/excel": "^3.1",
"nwidart/laravel-modules": "^9.0",
"psr/simple-cache": "^1.0"
"psr/simple-cache": "^1.0",
"pusher/pusher-php-server": "^7.2",
"spatie/laravel-permission": "^5.9"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.7",

2970
composer.lock generated Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -187,13 +187,18 @@ return [
*/
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
Maatwebsite\Excel\ExcelServiceProvider::class,
Barryvdh\Snappy\ServiceProvider::class,
Spatie\Permission\PermissionServiceProvider::class,
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\DuitkuServiceProvider::class,
App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
@@ -212,8 +217,11 @@ return [
'aliases' => Facade::defaultAliases()->merge([
// 'ExampleClass' => App\Example\ExampleClass::class,
'Duitku' => App\Services\Duitku::class,
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
'LmsApi' => App\Services\LmsApi::class,
'PDF' => Barryvdh\Snappy\Facades\SnappyPdf::class,
'SnappyImage' => Barryvdh\Snappy\Facades\SnappyImage::class,
])->toArray(),
];

View File

@@ -36,8 +36,11 @@ return [
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com',
'port' => env('PUSHER_PORT', 443),
'scheme' => env('PUSHER_SCHEME', 'https'),
'encrypted' => true,
'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
],
'client_options' => [
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html

161
config/permission.php Normal file
View 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',
],
];

52
config/snappy.php Normal file
View File

@@ -0,0 +1,52 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Snappy PDF / Image Configuration
|--------------------------------------------------------------------------
|
| This option contains settings for PDF generation.
|
| Enabled:
|
| Whether to load PDF / Image generation.
|
| Binary:
|
| The file path of the wkhtmltopdf / wkhtmltoimage executable.
|
| Timout:
|
| The amount of time to wait (in seconds) before PDF / Image generation is stopped.
| Setting this to false disables the timeout (unlimited processing time).
|
| Options:
|
| The wkhtmltopdf command options. These are passed directly to wkhtmltopdf.
| See https://wkhtmltopdf.org/usage/wkhtmltopdf.txt for all options.
|
| Env:
|
| The environment variables to set while running the wkhtmltopdf process.
|
*/
'pdf' => [
'enabled' => true,
'binary' => env('WKHTML_PDF_BINARY', '/usr/local/bin/wkhtmltopdf'),
'timeout' => false,
'options' => [],
'env' => [],
],
'image' => [
'enabled' => true,
'binary' => env('WKHTML_IMG_BINARY', '/usr/local/bin/wkhtmltoimage'),
'timeout' => false,
'options' => [],
'env' => [],
],
];

View File

@@ -0,0 +1,41 @@
<?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->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');
}
};

View File

@@ -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']);
}
}

View File

@@ -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');
});
}
};

View File

@@ -17,18 +17,23 @@ class DummyMemberSeeder extends Seeder
public function run()
{
$userEmails = [
'admin@linksehat.dev',
'manager+one@gmail.com',
'manager+two@gmail.com'
'admin@linksehat.dev' => ['administrator'],
'manager+one@gmail.com' => ['corporate-manager'],
'manager+two@gmail.com' => ['corporate-manager'],
'hospitaladmin@gmail.com' => ['hospital-admin']
];
foreach ($userEmails as $email) {
User::updateOrCreate([
foreach ($userEmails as $email => $roles) {
$user = User::updateOrCreate([
'email' => $email
], [
'email' => $email,
'password' => Hash::make('password')
]);
if (isset($roles) && count($roles)) {
$user->syncRoles($roles);
}
}
}
}

View File

@@ -0,0 +1,143 @@
<?php
namespace Database\Seeders;
use App\Models\OLDLMS\Healthcare;
use App\Models\OLDLMS\JadwalDokter;
use App\Models\OLDLMS\JadwalDokterDay;
use App\Services\LmsApi;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class JadwalDokterSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$mapHealthcare = [
'Q',
'C',
'D',
'E',
'F',
'M',
'O',
'P',
'Q',
'N',
'SG',
'BW',
'SK',
'PK',
'CK',
'DE'
];
$healthcares = Healthcare::whereIn('sKodeRS', $mapHealthcare)->get();
foreach ($healthcares as $healthcare) {
$jadwalDokterDay = LmsApi::dokter($healthcare->sKodeRS, 'hospitaloka', 300);
if (empty($jadwalDokterDay['data'])) {
continue;
}
$listDokter = $jadwalDokterDay['data'];
foreach ($listDokter as $dokter) {
$jadwalDokter = JadwalDokter::where('sIDDokter', $dokter['id'])->where('sDepartmenID', $dokter['DepartemenID'])->first() ?? null;
if ($jadwalDokter == null) {
continue;
}
// if ($jadwalDokter->nID != 1901) {
// continue;
// }
$jadwalDokterDay = $jadwalDokter->jadwalDokterDay()->get() ?? null;
// JadwalDokterDay::where('nIDJadwalDokter', $jadwalDokter->nID)->get() ?? null;
if ($jadwalDokterDay == null) {
continue;
}
// dd($dokter);
$listShcedule = $dokter['JadwalDokter'];
foreach ($jadwalDokterDay as $day) {
$NewJam = "";
foreach ($listShcedule as $key => $schedule) {
$jam = $schedule['Jam'];
$cek = $schedule['Jam'];
//jika jam memiliki hurug A-Z
if (preg_match('/[A-Z]/', $jam)) {
$jam = $jam;
} else {
//jika terdapat titik
if (strpos($jam, ".") !== false) {
//ganti titik dengan : dan tambahkan 00
$jam = str_replace(".", ":", $jam);
//jika jam nya terdapat strip
if (strpos($jam, "-") !== false) {
//jika didepan strip dan belakang strip ada spasi
if (strpos($jam, " ") !== false) {
//hapus spasi
$jam = str_replace(" ", "", $jam);
}
// try{
$jam = explode("-", $jam);
$jam = $jam[0] . " - " . $jam[1];
// } catch (\Exception $e) {
// $this->command->error($cek . "Id dokter : " . $jadwalDokter->nID);
// }
} else {
$jam = $jam;
}
} else {
//jika terdapat strip
if (strpos($jam, "-") !== false) {
//jika hanya ada strip tidak ada yang lain
if (strlen($jam) > 1) {
//jika sudah ada : maka diabaikan
if (strpos($jam, ":") !== false) {
$jam = explode("-", $jam);
$jam = $jam[0] . " - " . $jam[1];
} else {
//jika didepan strip ada spasi
if (strpos($jam, " ") !== false) {
//hapus spasi
$jam = str_replace(" ", "", $jam);
}
$jam = explode("-", $jam);
$jam = $jam[0] . ":00 - " . $jam[1] . ":00";
}
}
} else if (strpos($jam, ":") !== false) {
$jam = $jam;
} else {
$jam = $jam . ":00";
}
}
}
if ($day->sHari == $schedule['Hari']) {
if ($schedule['Jam'] == null) {
$NewJam = "";
} else {
$NewJam = $jam;
}
} else {
continue;
}
}
$day->sJam = $NewJam;
$day->save();
}
}
}
}
}

View File

@@ -0,0 +1,110 @@
<?php
namespace Database\Seeders;
use App\Models\OLDLMS\Healthcare;
use App\Models\OLDLMS\JadwalDokter;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class PricesJadwalDokter extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// $healthcare_primaya = Healthcare::where('nIDHealthCareGroup', 1)->get();
// PHSM = semarang
// PHBU = Bekasi Utara
// PHMA = makasar
// PHPK = pasar kemis
// PHPC = cikini
// PHBW = Bakti wara
// PEVH = evasari
// PHTA = tangerang
// PHSB = sukabumi
// PHKA = karawang
// PHBB = bekasi barat
// PHBT = bekasi timur
$mapHealthcare = [
'SG' => 'PHSM',
'P' => 'PHBU',
'F' => 'PHMA',
'PK' => 'PHPK',
'CK' => 'PHPC',
'BW' => 'PHBW',
'E' => 'PEVH',
'C' => 'PHTA',
'SK' => 'PHSB',
'Q' => 'PHKA',
'D' => 'PHBB',
'M' => 'PHBT',
];
$file = fopen(public_path("files/Tarif Konsultasi Primaya 2023.csv"), "r");
$data = [];
while ($row = fgetcsv($file)) {
for ($i = 0; $i < count($row); $i++) {
$data[$i][] = $row[$i];
}
}
fclose($file);
// foreach ($healthcare_primaya as $healthcare) {
$jadwalDokter = JadwalDokter::get();
foreach ($jadwalDokter as $jadwal) {
$id_healthcare_jadwal = $jadwal->nIDHealthCare;
$healthcare = Healthcare::where('nID', $id_healthcare_jadwal)->first() ?? null;
if ($healthcare == null) {
continue;
}
$mapValue = $mapHealthcare[$healthcare->sKodeRS] ?? null;
if ($mapValue == null) {
continue;
}
foreach ($data as $value) {
if ($value[0] == "") {
continue;
}
$codeValue = $value[0];
$codeValue = substr($codeValue, 1, 4);
if ($codeValue == $mapValue) {
if ($jadwal->nIDSpesialis == 1) {
//umum
$jadwal->nBiaya = (int)str_replace(",", "", $value[2]) + (int)str_replace(",", "", $value[1]);
$jadwal->nBiayaTC = (int)str_replace(",", "", $value[5]);
$jadwal->nBiayaATC = (int)str_replace(",", "", $value[5]);
$jadwal->save();
} else if ($jadwal->nIDSpesialis !== 1 && $jadwal->sIsSubSpesialis == 1) {
//sub spesialis
$jadwal->nBiaya = (int)str_replace(",", "", $value[4]) + (int)str_replace(",", "", $value[1]);
$jadwal->nBiayaTC = (int)str_replace(",", "", $value[7]);
$jadwal->nBiayaATC = (int)str_replace(",", "", $value[7]);
$jadwal->save();
} else if ($jadwal->nIDSpesialis !== 1) {
//spesialis
$jadwal->nBiaya = (int)str_replace(",", "", $value[3]) + (int)str_replace(",", "", $value[1]);
$jadwal->nBiayaTC = (int)str_replace(",", "", $value[6]);
$jadwal->nBiayaATC = (int)str_replace(",", "", $value[6]);
$jadwal->save();
}
} else {
continue;
}
}
}
// }
}
}

View 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
]);
}
}
}

View File

@@ -47,6 +47,12 @@ class ServiceSeeder extends Seeder
'code' => 'OPT',
'description' => 'Optical',
],
[
'id' => 6,
'name' => 'Medical Check Up',
'code' => 'MCU',
'description' => 'Medical Check Up',
],
];
@@ -56,12 +62,14 @@ class ServiceSeeder extends Seeder
$service = Service::updateOrCreate(['id' => $service['id']], $service);
foreach ($corporates as $corporate) {
$corporateService = $corporate->corporateServices()->create([
$corporateService = $corporate->corporateServices()->firstOrCreate([
'service_code' => $service->code
],[
'service_code' => $service->code,
'status' => 'active'
'status' => 'inactive'
]);
$corporateService->configs()->insert([
$corporate_service_configs_data = [
[
'corporate_service_id' => $corporateService->id,
'name' => 'gp_external_doctor_online',
@@ -122,7 +130,14 @@ class ServiceSeeder extends Seeder
'name' => 'specialist_practitioner_fee',
'value' => false,
],
]);
];
foreach ($corporate_service_configs_data as $config) {
$corporateService->configs()->firstOrCreate([
'corporate_service_id' => $config['corporate_service_id'],
'name' => $config['name']
], $config);
}
}
}
}

View File

@@ -1,4 +1,12 @@
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.html [QSA,L]
</IfModule>
<IfModule pagespeed_module>
ModPagespeed off
</IfModule>

View File

@@ -32,7 +32,7 @@ const MENU_OPTIONS = [
export default function AccountPopover() {
const [open, setOpen] = useState<HTMLElement | null>(null);
const navigate = useNavigate();
const { logout } = useAuth();
const { logout, user } = useAuth();
const handleOpen = (event: React.MouseEvent<HTMLElement>) => {
setOpen(event.currentTarget);
@@ -67,10 +67,10 @@ export default function AccountPopover() {
}),
}}
>
<Avatar
src="https://minimal-assets-api.vercel.app/assets/images/avatars/avatar_5.jpg"
alt="Rayan Moran"
/>
{user && user.user.avatar_url && (<Avatar
src={user ? user.user.avatar_url : ''}
alt={user ? user.user.full_name : ''}
/>)}
</IconButtonAnimate>
<MenuPopover
@@ -89,16 +89,16 @@ export default function AccountPopover() {
>
<Box sx={{ my: 1.5, px: 2.5 }}>
<Typography variant="subtitle2" noWrap>
Rayan Moran
{ user ? user.user.full_name ?? 'Hi, ' : 'Hi, '}
</Typography>
<Typography variant="body2" sx={{ color: 'text.secondary' }} noWrap>
rayan.moran@gmail.com
{ user ? user.user.email : 'Please Wait'}
</Typography>
</Box>
<Divider sx={{ borderStyle: 'dashed' }} />
<Stack sx={{ p: 1 }}>
{/* <Stack sx={{ p: 1 }}>
{MENU_OPTIONS.map((option) => (
<MenuItem key={option.label} onClick={handleClose}>
{option.label}
@@ -106,7 +106,7 @@ export default function AccountPopover() {
))}
</Stack>
<Divider sx={{ borderStyle: 'dashed' }} />
<Divider sx={{ borderStyle: 'dashed' }} /> */}
<MenuItem sx={{ m: 1 }} onClick={handleLogout}>
Logout

View File

@@ -1,6 +1,7 @@
// @mui
import { styled } from '@mui/material/styles';
import { Box, Link, Typography, Avatar } from '@mui/material';
import useAuth from '../../../hooks/useAuth';
// ----------------------------------------------------------------------
@@ -22,6 +23,10 @@ type Props = {
};
export default function NavbarAccount({ isCollapse }: Props) {
const { user } = useAuth();
console.log('current user is ', user)
return (
<Link underline="none" color="inherit">
<RootStyle
@@ -31,10 +36,10 @@ export default function NavbarAccount({ isCollapse }: Props) {
}),
}}
>
<Avatar
src="https://minimal-assets-api.vercel.app/assets/images/avatars/avatar_5.jpg"
alt="Rayan Moran"
/>
{user && user.user.avatar_url && (<Avatar
src={user ? user.user.avatar_url : ''}
alt={user ? user.user.full_name : ''}
/>)}
<Box
sx={{
@@ -50,10 +55,10 @@ export default function NavbarAccount({ isCollapse }: Props) {
}}
>
<Typography variant="subtitle2" noWrap>
Rayan Moran
{ user ? user.user.full_name ?? 'Hi, ' : 'Hi, '}
</Typography>
<Typography variant="body2" noWrap sx={{ color: 'text.secondary' }}>
user
<Typography variant="body2" noWrap sx={{ color: 'text.secondary', fontSize: '11px' }}>
{ user ? user.user.email : 'Please Wait'}
</Typography>
</Box>
</RootStyle>

View File

@@ -134,7 +134,7 @@ export default function DialogClaimSubmitMember({
params: { ...appliedParams, claimMember: true },
});
setData(response.data);
setData(response.data.data);
}
})();
}, [corporateValue, openDialog, appliedParams]);

View File

@@ -409,11 +409,11 @@ export default function TableList(props: any) {
</Button>
)}
</TableCell>
<TableCell align="right">
{/* <TableCell align="right">
<IconButton>
<Iconify icon="ic:baseline-more-vert" />
</IconButton>
</TableCell>
</TableCell> */}
</TableRow>
))
) : (

View File

@@ -1,7 +0,0 @@
GENERATE_SOURCEMAP=false
PORT=8083
REACT_APP_HOST_API_URL="http://localhost:8000"
VITE_API_URL="http://localhost:8000/api/internal"

View File

@@ -1,3 +1,3 @@
GENERATE_SOURCEMAP=false
VITE_API_URL="https://aso-api.linksehat.dev/api/internal"
VITE_API_URL="https://primecenter-api.linksehat.com/api/internal"

View File

@@ -0,0 +1 @@
VITE_API_URL="https://aso-api.linksehat.dev/api/internal"

View File

@@ -1,5 +1,4 @@
<IfModule mod_rewrite.c>
Modpagespeed Off
RewriteEngine On
RewriteBase /
@@ -7,3 +6,7 @@
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.html [QSA,L]
</IfModule>
<IfModule pagespeed_module>
ModPagespeed off
</IfModule>

View File

@@ -9,7 +9,7 @@
"lint:fix": "eslint --fix --ext .ts,.tsx ./src",
"start": "vite --port=3000",
"build": "vite build --mode production && cp .htaccess build/.htaccess && rm -f -r ../../public/dashboard && cp -r build ../../public/dashboard",
"build-two": "vite build --mode production",
"build-staging": "vite build --mode staging && cp .htaccess build/.htaccess && rm -f -r ../../public/dashboard-staging && cp -r build ../../public/dashboard-staging",
"serve": "vite preview",
"clear-all": "rm -rf build node_modules",
"re-start": "rm -rf build node_modules && yarn install && yarn start",
@@ -38,78 +38,78 @@
]
},
"dependencies": {
"@date-io/date-fns": "^2.14.0",
"@emotion/cache": "^11.9.3",
"@emotion/react": "^11.9.3",
"@emotion/styled": "^11.9.3",
"@hookform/resolvers": "^2.9.6",
"@date-io/date-fns": "^2.16.0",
"@emotion/cache": "^11.10.5",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@hookform/resolvers": "^2.9.10",
"@iconify/react": "^3.2.2",
"@mui/icons-material": "^5.8.4",
"@mui/icons-material": "^5.11.0",
"@mui/lab": "5.0.0-alpha.80",
"@mui/material": "^5.9.1",
"@mui/system": "^5.9.1",
"@mui/x-data-grid": "^5.14.0",
"@mui/material": "^5.11.5",
"@mui/system": "^5.11.5",
"@mui/x-data-grid": "^5.17.19",
"@mui/x-date-pickers": "5.0.0-beta.2",
"@vitejs/plugin-react": "^1.3.2",
"apexcharts": "^3.35.5",
"apexcharts": "^3.36.3",
"axios": "^0.27.2",
"change-case": "^4.1.2",
"csstype": "^3.1.0",
"date-fns": "^2.29.1",
"csstype": "^3.1.1",
"date-fns": "^2.29.3",
"framer-motion": "^6.5.1",
"highlight.js": "^11.6.0",
"highlight.js": "^11.7.0",
"history": "^5.3.0",
"jsx-runtime": "^1.2.0",
"lodash": "^4.17.21",
"notistack": "^3.0.0-alpha.7",
"notistack": "3.0.0-alpha.11",
"nprogress": "^0.2.0",
"numeral": "^2.0.6",
"react": "^17.0.2",
"react-apexcharts": "^1.4.0",
"react-dom": "^17.0.2",
"react-dropzone": "^14.2.2",
"react-dropzone": "^14.2.3",
"react-helmet-async": "^1.3.0",
"react-hook-form": "^7.33.1",
"react-hook-form": "^7.42.1",
"react-intersection-observer": "^8.34.0",
"react-lazy-load-image-component": "^1.5.5",
"react-lazy-load-image-component": "^1.5.6",
"react-quill": "2.0.0-beta.4",
"react-router": "^6.3.0",
"react-router-dom": "^6.3.0",
"simplebar": "^5.3.8",
"simplebar-react": "^2.4.1",
"stylis": "^4.1.1",
"react-router": "^6.7.0",
"react-router-dom": "^6.7.0",
"simplebar": "^5.3.9",
"simplebar-react": "^2.4.3",
"stylis": "^4.1.3",
"stylis-plugin-rtl": "^2.1.1",
"vite": "^3.0.4",
"vite-plugin-svgr": "^2.2.1",
"vite": "^3.2.5",
"vite-plugin-svgr": "^2.4.0",
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/core": "^7.18.9",
"@babel/eslint-parser": "^7.18.9",
"@babel/core": "^7.20.12",
"@babel/eslint-parser": "^7.19.1",
"@babel/plugin-syntax-flow": "^7.18.6",
"@babel/plugin-transform-react-jsx": "^7.18.6",
"@types/lodash": "^4.14.182",
"@babel/plugin-transform-react-jsx": "^7.20.7",
"@types/lodash": "^4.14.191",
"@types/nprogress": "^0.2.0",
"@types/react": "^17.0.47",
"@types/react-dom": "^17.0.17",
"@types/react": "^17.0.53",
"@types/react-dom": "^17.0.18",
"@types/react-lazy-load-image-component": "^1.5.2",
"@types/stylis": "^4.0.2",
"@typescript-eslint/eslint-plugin": "^5.30.7",
"@typescript-eslint/parser": "^5.30.7",
"eslint": "^8.20.0",
"@typescript-eslint/eslint-plugin": "^5.48.2",
"@typescript-eslint/parser": "^5.48.2",
"eslint": "^8.32.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-airbnb-typescript": "^16.2.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-prettier": "^8.6.0",
"eslint-config-react-app": "7.0.0",
"eslint-import-resolver-typescript": "^2.7.1",
"eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsx-a11y": "6.5.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react": "^7.32.1",
"eslint-plugin-react-hooks": "4.3.0",
"prettier": "^2.7.1",
"typescript": "^4.7.4",
"vite-plugin-pwa": "^0.12.3"
"prettier": "^2.8.3",
"typescript": "^4.9.4",
"vite-plugin-pwa": "^0.12.8"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -58,6 +58,13 @@ const navConfig = [
{ title: 'Hospitals', path: '/hospitals' },
],
},
{
title: 'LOG REQUEST',
path: '/claim-requests',
// children: [
// { title: 'Request', path: '/case-request' },
// ],
},
{
title: 'CASE MANAGEMENT',
path: '/claims',

View 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>
);
}

View 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>
);
}

View 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>
);
}

View File

@@ -0,0 +1,294 @@
// @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 LoadingButton from '@/theme/overrides/LoadingButton';
export default function List() {
const [searchParams, setSearchParams] = useSearchParams();
const [importResult, setImportResult] = useState(null);
const navigate = useNavigate();
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>
</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>
);
}
return (
<Card>
<ImportForm />
<DataTable
isLoading={dataTableIsLoading}
lastRequest={0}
data={dataTableData}
handlePageChange={handlePageChange}
TableContent={<TableContent />}
/>
</Card>
);
}

View File

@@ -218,6 +218,12 @@ export default function List() {
({row.diagnosis?.code}) {row.diagnosis?.name}
</TableCell>
<TableCell align="left">{fCurrency(row.total_claim)}</TableCell>
{ (row.status == 'approved' && (
<TableCell align="left">Approved</TableCell>
)) }
{ (row.status == 'postpone' && (
<TableCell align="left">Postponed</TableCell>
)) }
<TableCell align="right">
<EditRoundedIcon
@@ -271,6 +277,9 @@ export default function List() {
<TableCell style={headStyle} align="left">
Total Claim
</TableCell>
<TableCell style={headStyle} align="left">
Status
</TableCell>
<TableCell style={headStyle} align="right">
Action
</TableCell>

View File

@@ -62,12 +62,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop
const onSubmit = async (data: any) => {
if (!isEdit) {
await axios
.post('/corporates/' + corporate_id + '/divisions', data)
.post('/corporate/' + corporate_id + '/divisions', data)
.then((res) => {
enqueueSnackbar('Division created successfully', { variant: 'success' });
})
.then((res) => {
navigate('/corporates/' + corporate_id + '/divisions', { replace: true });
navigate('/corporate/' + corporate_id + '/divisions', { replace: true });
})
.catch(({ response }) => {
if (response.status === 422) {
@@ -81,12 +81,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop
});
} else {
await axios
.put('/corporates/' + corporate_id + '/divisions/' + currentCorporatePlan?.id, data)
.put('/corporate/' + corporate_id + '/divisions/' + currentCorporatePlan?.id, data)
.then((res) => {
enqueueSnackbar('Division updated successfully', { variant: 'success' });
})
.then((res) => {
navigate('/corporates/' + corporate_id + '/divisions/', { replace: true });
navigate('/corporate/' + corporate_id + '/divisions/', { replace: true });
})
.catch(({ response }) => {
enqueueSnackbar('Update Failed : ' + response.data.message, { variant: 'error' });

Some files were not shown because too many files have changed in this diff Show More