diff --git a/Modules/Linksehat/Http/Controllers/Api/AuthController.php b/Modules/Linksehat/Http/Controllers/Api/AuthController.php index ee65a7df..f6205819 100644 --- a/Modules/Linksehat/Http/Controllers/Api/AuthController.php +++ b/Modules/Linksehat/Http/Controllers/Api/AuthController.php @@ -3,10 +3,12 @@ namespace Modules\Linksehat\Http\Controllers\Api; use App\Http\Controllers\Controller; +use App\Models\Person; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; +use Laravel\Socialite\Facades\Socialite; use Modules\Linksehat\Transformers\UserProfileResource; use Validator; @@ -18,8 +20,8 @@ class AuthController extends Controller // 'phone' => 'required' 'phone_or_email' => 'required' ]); - - if(filter_var($request->phone_or_email, FILTER_VALIDATE_EMAIL)) { + + if (filter_var($request->phone_or_email, FILTER_VALIDATE_EMAIL)) { $user = User::updateOrCreate([ 'email' => $request->phone_or_email ], [ @@ -27,8 +29,7 @@ class AuthController extends Controller 'otp' => rand(1000, 9999), 'otp_created_at' => now() ]); - } - else { + } else { $user = User::updateOrCreate([ 'phone' => $request->phone_or_email ], [ @@ -40,9 +41,9 @@ class AuthController extends Controller if (!$user) { return response()->json([ - 'message' => filter_var($request->phone_or_email, FILTER_VALIDATE_EMAIL) ? - "User dengan alamat email ".$request->phone_or_email." tidak ditemukan" : - "User dengan nomor telepon ".$request->phone_or_email." tidak ditemukan" + 'message' => filter_var($request->phone_or_email, FILTER_VALIDATE_EMAIL) ? + "User dengan alamat email " . $request->phone_or_email . " tidak ditemukan" : + "User dengan nomor telepon " . $request->phone_or_email . " tidak ditemukan" ], 404); } @@ -60,7 +61,7 @@ class AuthController extends Controller ] ]); } - + public function login(Request $request) { $request->validate([ @@ -76,14 +77,14 @@ class AuthController extends Controller if ($loginType == 'email') { $user = User::query() - ->where('email', $request->phone_or_email) - ->first(); + ->where('email', $request->phone_or_email) + ->first(); } if ($loginType == 'phone') { $user = User::query() - ->where('phone', $request->phone_or_email) - ->first(); + ->where('phone', $request->phone_or_email) + ->first(); } if (!isset($user) || empty($user)) { @@ -115,7 +116,7 @@ class AuthController extends Controller 'email' => 'required|email|unique:users,email', 'password' => [ 'required', - 'confirmed', + 'confirmed', 'min:8', 'regex:/.*[0-9].*/', 'regex:/.*[a-z].*/', @@ -155,7 +156,7 @@ class AuthController extends Controller $request->validate([ 'phone_or_email' => 'required' ]); - + $user = User::where((filter_var($request->phone_or_email, FILTER_VALIDATE_EMAIL) ? 'email' : 'phone'), $request->phone_or_email)->first(); if ($user) { @@ -173,6 +174,44 @@ class AuthController extends Controller 'message' => 'User Tidak Ditemukan' ], 404); } + } + public function redirectSocialLogin($provider) + { + return Socialite::driver($provider)->redirect(); + } + + public function handleSocialLoginCallback(Request $request, $provider) + { + // get the provider's user. (In the provider server) + $providerUser = Socialite::driver($provider)->user(); + + // check if access token exists etc.. + // search for a user in our server with the specified provider id and provider name + $user = User::where('email', $providerUser->email)->first(); + + // // if there is no record with these data, create a new user + if (!$user) { + $user = User::query()->create([ + 'email' => $providerUser->email, + ]); + + $person = Person::query()->create([ + 'owner_user_id' => $user->id, + 'name' => $providerUser->name, + 'email' => $providerUser->email, + ]); + + User::query()->find($user->id)->update([ + 'person_id' => $person->id + ]); + } + + // // return the token for usage + return response([ + 'message' => 'Selamat Datang', + 'user' => UserProfileResource::make($user), + 'token' => $user->createToken('app')->plainTextToken + ]); } } diff --git a/Modules/Linksehat/Http/Controllers/Api/DashboardController.php b/Modules/Linksehat/Http/Controllers/Api/DashboardController.php new file mode 100644 index 00000000..70adf454 --- /dev/null +++ b/Modules/Linksehat/Http/Controllers/Api/DashboardController.php @@ -0,0 +1,67 @@ +with([ + 'person' => function ($query) { + $query->select(['name']); + }, + 'speciality' => function ($query) { + $query->select(['id', 'name']); + }, + ]) + ->where('active', 1) + ->whereNot('speciality_id') + ->get(['id', 'practitioner_id', 'speciality_id']) + ->random($limit); + + return $queryDoctors; + + $data = DoctorResourceDashboard::collection($queryDoctors); + } elseif ($query === 'hospitals') { + $queryHospitals = Organization::query() + ->leftJoin('addresses', function ($query) { + $query->on('organizations.main_address_id', '=', 'addresses.id'); + $query->where('addresses.addressable_type', '=', Organization::class); + }) + ->where('organizations.type', 'hospital') + ->where('organizations.status', 'active') + ->when($request->lat && $request->lng, function ($query) use ($request) { + $query->selectRaw("organizations.id, organizations.name, addresses.text AS currentAddress, 6371 * acos (cos ( radians($request->lat) ) * cos( radians( addresses.lat ) ) * cos( radians( addresses.lng ) - radians($request->lng) ) + sin ( radians($request->lat) ) * sin( radians( addresses.lat ) )) as distance"); + $query->orderBy('distance', 'ASC'); + }, function ($query) { + $query->select(['organizations.id', 'organizations.name', 'addresses.text AS currentAddress']); + $query->orderBy('organizations.name', 'asc'); + }) + ->limit($limit) + ->get(); + + $data = HospitalResourceDashboard::collection($queryHospitals); + } elseif ($query === 'articles') { + $data = ArticleResourceDashboard::collection(json_decode(Http::get('https://linksehat.com/api/medical-assistance-articles'))); + } + + return response()->json([ + 'status' => 'success', + 'statusCode' => Response::HTTP_OK, + 'message' => 'Data berhasil di ambil', + 'data' => $data, + ]); + } +} diff --git a/Modules/Linksehat/Http/Controllers/Api/DoctorController.php b/Modules/Linksehat/Http/Controllers/Api/DoctorController.php index bf7ec224..687b0c50 100644 --- a/Modules/Linksehat/Http/Controllers/Api/DoctorController.php +++ b/Modules/Linksehat/Http/Controllers/Api/DoctorController.php @@ -5,12 +5,13 @@ namespace Modules\Linksehat\Http\Controllers\Api; use App\Helpers\Helper; use App\Models\Practitioner; use App\Models\PractitionerRole; +use App\Models\PractitionerRoleAvailability; use DB; use Illuminate\Contracts\Support\Renderable; use Illuminate\Http\Request; use Illuminate\Routing\Controller; use Modules\Linksehat\Transformers\DoctorResource; -use Modules\Linksehat\Transformers\PractitionerRoleToDoctorDetailResource; +use Modules\Linksehat\Transformers\Doctors\DoctorResourceDetail; use Modules\Linksehat\Transformers\PractitionerRoleToDoctorResource; class DoctorController extends Controller @@ -22,36 +23,37 @@ class DoctorController extends Controller public function index(Request $request) { $doctors = PractitionerRole::query() - ->with(['practitioner.person', 'speciality', 'practitioner.metas', 'metas', - 'organization' => function ($query) use ($request) { - if ($request->has('lat') && !empty($request->lat) && $request->has('lng') && !empty($request->lng)) { - return $query->leftJoin('addresses', function($q) { - $q->on('organizations.main_address_id', '=', 'addresses.id'); - $q->where('addresses.addressable_type', '=', Organization::class); - }) - ->select([ - "organizations.*", - "addresses.lat", - "addresses.lng", - // DB::raw("ST_Distance_Sphere(point(addresses.lng,addresses.lat), point(".$request->lng.",".$request->lat.")) /1000 as distance_km"), - DB::raw("6371 * acos (cos ( radians($request->lat) ) * cos( radians( addresses.lat ) ) * cos( radians( addresses.lng ) - radians($request->lng) ) + sin ( radians($request->lat) ) * sin( radians( addresses.lat ) )) as distance_km") - ]); - } - }, - ]) - ->when($request->search ?? null, function($query, $search) { - $query->whereHas('practitioner.person', function($person) use ($search) { - $person->where('name', 'LIKE', '%'.$search.'%'); - }); - }) - ->whereHas('speciality'); + ->with([ + 'practitioner.person', 'speciality', 'practitioner.metas', 'metas', + 'organization' => function ($query) use ($request) { + if ($request->has('lat') && !empty($request->lat) && $request->has('lng') && !empty($request->lng)) { + return $query->leftJoin('addresses', function ($q) { + $q->on('organizations.main_address_id', '=', 'addresses.id'); + $q->where('addresses.addressable_type', '=', Organization::class); + }) + ->select([ + "organizations.*", + "addresses.lat", + "addresses.lng", + // DB::raw("ST_Distance_Sphere(point(addresses.lng,addresses.lat), point(".$request->lng.",".$request->lat.")) /1000 as distance_km"), + DB::raw("6371 * acos (cos ( radians($request->lat) ) * cos( radians( addresses.lat ) ) * cos( radians( addresses.lng ) - radians($request->lng) ) + sin ( radians($request->lat) ) * sin( radians( addresses.lat ) )) as distance_km") + ]); + } + }, + ]) + ->when($request->search ?? null, function ($query, $search) { + $query->whereHas('practitioner.person', function ($person) use ($search) { + $person->where('name', 'LIKE', '%' . $search . '%'); + }); + }) + ->whereHas('speciality'); if ($request->has('hospital_id_in')) { $hospital_ids = explode(',', $request->hospital_id_in); $doctors->whereIn('organization_id', $hospital_ids); } else if ($request->has('hospital_id')) { $doctors->where('organization_id', $request->hospital_id); } - + $limit = $request->limit ?? 6; if ($limit > 20) { $limit = 20; @@ -91,32 +93,22 @@ class DoctorController extends Controller */ public function show(Request $request, $id) { - $doctor = Practitioner::query() - ->with([ - 'practitionerRoles', - 'practitionerRoles.metas', - 'practitionerRoles.speciality', - 'practitionerRoles.organization' => function ($query) use ($request) { - if ($request->has('lat') && !empty($request->lat) && $request->has('lng') && !empty($request->lng)) { - $query->leftJoin('addresses', function($q) { - $q->on('organizations.main_address_id', '=', 'addresses.id'); - $q->where('addresses.addressable_type', '=', Organization::class); - }); - $query->select([ - "organizations.*", - // DB::raw("ST_Distance_Sphere(point(addresses.lng,addresses.lat), point(".$request->lng.",".$request->lat.")) /1000 as distance_km"), - DB::raw("6371 * acos (cos ( radians($request->lat) ) * cos( radians( addresses.lat ) ) * cos( radians( addresses.lng ) - radians($request->lng) ) + sin ( radians($request->lat) ) * sin( radians( addresses.lat ) )) as distance_km") - ]); - } - }, - 'practitionerRoles.practices', - 'practitionerRoles.availabilities', - 'person', - 'metas', - ]) - ->findOrFail($id); - - return response()->json(DoctorResource::make($doctor)); + $queryDoctor = PractitionerRole::query() + ->with([ + 'practitioner', + 'speciality', + 'practices.prices' + ]) + ->findOrFail($id); + + $queryAvailables = PractitionerRoleAvailability::query()->with(['days' => function ($query) { + $query->select(['availability_id', 'day']); + }])->where('practitioner_role_id', $id)->get(['id', 'start_time']); + + $doctor = DoctorResourceDetail::make($queryDoctor); + $doctor['day_available'] = Helper::dailyAvailabilities($queryAvailables); + + return response()->json(compact('doctor')); } /** @@ -162,12 +154,12 @@ class DoctorController extends Controller if ($request->type == 'walkin') { $practitionerRole = PractitionerRole::query() - ->where('practitioner_id', $id) - ->where('organization_id', $request->hospital_id) - ->where('speciality_id', $request->speciality_id) - ->with(['availabilities', 'availabilities.days']) - ->first(); - + ->where('practitioner_id', $id) + ->where('organization_id', $request->hospital_id) + ->where('speciality_id', $request->speciality_id) + ->with(['availabilities', 'availabilities.days']) + ->first(); + if ($practitionerRole) { $schedules = [ @@ -181,25 +173,23 @@ class DoctorController extends Controller ]; foreach ($practitionerRole->daily_availabilities as $day => $times) { - $schedules[$day] = array_unique( array_merge($schedules[$day], $times) ); + $schedules[$day] = array_unique(array_merge($schedules[$day], $times)); } - } - } else if ($request->type == 'teleconsultation') { $practitioner = Practitioner::query() - ->with([ - 'practitionerRoles' => function($practitionerRole) use ($request) { - if (!empty($request->hospital_id)) { - $practitionerRole->where('organization_id', $request->hospital_id); - } - }, - 'practitionerRoles.availabilities', - 'practitionerRoles.availabilities.days' - ]) - ->where('id', $id) - ->first(); + ->with([ + 'practitionerRoles' => function ($practitionerRole) use ($request) { + if (!empty($request->hospital_id)) { + $practitionerRole->where('organization_id', $request->hospital_id); + } + }, + 'practitionerRoles.availabilities', + 'practitionerRoles.availabilities.days' + ]) + ->where('id', $id) + ->first(); $schedules = [ 'Senin' => [], @@ -212,24 +202,22 @@ class DoctorController extends Controller ]; foreach ($practitioner->practitionerRoles as $role) { - + foreach ($role->daily_availabilities as $day => $times) { // Merge All Role Availabilities - $schedules[$day] = array_unique( array_merge($schedules[$day], $times) ); + $schedules[$day] = array_unique(array_merge($schedules[$day], $times)); // $schedules[] = [ // 'day' => $day, // 'times' => array_unique( array_merge($schedules[$day], $times) ) // ]; } - } - } - - $datesAvailabilities = Helper::dailyAvailabilitiesToDate( $schedules, $request->start_date, $request->end_date ?? null); + + $datesAvailabilities = Helper::dailyAvailabilitiesToDate($schedules, $request->start_date, $request->end_date ?? null); return response()->json($datesAvailabilities); diff --git a/Modules/Linksehat/Http/Controllers/Api/HospitalController.php b/Modules/Linksehat/Http/Controllers/Api/HospitalController.php index 9abb91ef..15c7336c 100644 --- a/Modules/Linksehat/Http/Controllers/Api/HospitalController.php +++ b/Modules/Linksehat/Http/Controllers/Api/HospitalController.php @@ -9,6 +9,7 @@ use Illuminate\Contracts\Support\Renderable; use Illuminate\Http\Request; use Illuminate\Routing\Controller; use Modules\Linksehat\Transformers\HospitalResource; +use Modules\Linksehat\Transformers\Hospitals\HospitalResourceDetail; class HospitalController extends Controller { @@ -19,13 +20,13 @@ class HospitalController extends Controller public function index(Request $request) { $hospitals = Organization::query() - ->with(['currentAddress']) - ->where('organizations.type', 'hospital') - ->when($request->search ?? null, function($query, $search) { - $query->where('name', 'LIKE', '%'.$search.'%'); - }); + ->with(['currentAddress']) + ->where('organizations.type', 'hospital') + ->when($request->search ?? null, function ($query, $search) { + $query->where('name', 'LIKE', '%' . $search . '%'); + }); if ($request->has('lat') && !empty($request->lat) && $request->has('lng') && !empty($request->lng)) { - $hospitals->leftJoin('addresses', function($q) { + $hospitals->leftJoin('addresses', function ($q) { $q->on('organizations.main_address_id', '=', 'addresses.id'); $q->where('addresses.addressable_type', '=', Organization::class); }); @@ -34,7 +35,7 @@ class HospitalController extends Controller // DB::raw("ST_Distance_Sphere(point(addresses.lng,addresses.lat), point(".$request->lng.",".$request->lat.")) /1000 as distance_km"), DB::raw("6371 * acos (cos ( radians($request->lat) ) * cos( radians( addresses.lat ) ) * cos( radians( addresses.lng ) - radians($request->lng) ) + sin ( radians($request->lat) ) * sin( radians( addresses.lat ) )) as distance_km") ]); - + $hospitals->orderBy('distance_km', 'asc'); } else { $hospitals->orderBy('organizations.name', 'asc'); @@ -62,10 +63,10 @@ class HospitalController extends Controller if ($limit > 20) { $limit = 20; } - + $hospitals = $hospitals->paginate($limit); // dd($hospitals->toArray()); - + return response()->json([ 'message' => 'Sukses mengambil data Rumah Sakit', @@ -97,11 +98,19 @@ class HospitalController extends Controller * @param int $id * @return Renderable */ - public function show($id) + public function show(Request $request, $id) { - $hospital = Organization::query()->findOrFail($id); + $queryHospitals = Organization::query() + ->leftJoin('addresses', function ($q) { + $q->on('organizations.main_address_id', '=', 'addresses.id'); + $q->where('addresses.addressable_type', '=', Organization::class); + }); + if ($request->has('lat') && !empty($request->lat) && $request->has('lng') && !empty($request->lng)) { + $queryHospitals = $queryHospitals->selectRaw("organizations.*, addresses.text AS currentAddress, 6371 * acos (cos ( radians($request->lat) ) * cos( radians( addresses.lat ) ) * cos( radians( addresses.lng ) - radians($request->lng) ) + sin ( radians($request->lat) ) * sin( radians( addresses.lat ) )) as distance")->orderBy('distance', 'ASC'); + } + $queryHospitals = $queryHospitals->orderBy('organizations.name', 'asc')->findOrFail($id); - return response()->json(HospitalResource::make($hospital)); + return HospitalResourceDetail::make($queryHospitals); } /** diff --git a/Modules/Linksehat/Http/Controllers/Api/PersonController.php b/Modules/Linksehat/Http/Controllers/Api/PersonController.php new file mode 100644 index 00000000..c629a48c --- /dev/null +++ b/Modules/Linksehat/Http/Controllers/Api/PersonController.php @@ -0,0 +1,132 @@ +organization_id; + $specialityId = $request->speciality_id; + + if (empty($organizationId) || empty($specialityId)) { + $messageorganizationId = !empty($organizationId) ? ' ' : ' organization_id or '; + $messageSpecialityId = !empty($specialityId) ? ' ' : 'speciality_id'; + + abort(400, 'missing parameter' . $messageorganizationId . $messageSpecialityId); + } + + $doctors = PractitionerRole::query()->with(['practitioner.person', 'speciality'])->where('organization_id', $organizationId)->where('speciality_id', $specialityId)->get(); + + foreach ($doctors as $key => $doctor) { + $specialisName = $doctor->speciality->name; + } + + // Price belum ke ambil + return response()->json([ + 'status' => true, + 'statusCode' => 200, + 'message' => 'Data Berhasil di ambil', + 'data' => [ + 'title' => 'Spesialis ' . $specialisName, + 'doctors' => SpecialityResource::collection($doctors) + ] + ]); + } + + public function searchSpecialityOrPerson(Request $request) + { + $doctors = PractitionerRole::query() + ->with(['practitioner.person', 'speciality']) + ->whereHas('practitioner.person', function ($query) use ($request) { + $query->where('name', 'LIKE', "%{$request->value}%"); + }) + // ->whereHas('speciality', function ($query) use ($request) { + // $query->where('name', 'LIKE', "%{$request->value}%"); + // }) + ->get(); + + return $doctors; + + // Price belum ke ambil + // return response()->json([ + // 'status' => true, + // 'statusCode' => 200, + // 'message' => 'Data Berhasil di ambil', + // 'data' => [ + // 'title' => 'Spesialis ' . $specialisName, + // 'doctors' => SpecialityResource::collection($doctors) + // ] + // ]); + } + + /** + * Show the form for creating a new resource. + * @return Renderable + */ + public function 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(Request $request, $id) + { + // + } + + /** + * Show the form for editing the specified resource. + * @param int $id + * @return Renderable + */ + public function edit($id) + { + // + } + + /** + * Update the specified resource in storage. + * @param Request $request + * @param int $id + * @return Renderable + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * @param int $id + * @return Renderable + */ + public function destroy($id) + { + // + } +} diff --git a/Modules/Linksehat/Http/Controllers/Api/SpecialityController.php b/Modules/Linksehat/Http/Controllers/Api/SpecialityController.php new file mode 100644 index 00000000..03e0d293 --- /dev/null +++ b/Modules/Linksehat/Http/Controllers/Api/SpecialityController.php @@ -0,0 +1,141 @@ +organization_id; + $specialityId = $request->speciality_id; + + if (empty($organizationId) || empty($specialityId)) { + $messageorganizationId = !empty($organizationId) ? ' ' : ' organization_id or '; + $messageSpecialityId = !empty($specialityId) ? ' ' : 'speciality_id'; + + abort(Response::HTTP_BAD_REQUEST, 'Missing Parameter' . $messageorganizationId . $messageSpecialityId); + } + + $doctors = PractitionerRole::query() + ->with(['practitioner.person', 'speciality', 'prices']) + ->whereHas('prices', function ($query) { + $query->where('priceable_type', Practice::class); + }) + ->where('organization_id', $organizationId) + ->where('speciality_id', $specialityId) + ->get(); + + foreach ($doctors as $key => $doctor) { + $specialisName = $doctor->speciality->name; + } + + return response()->json([ + 'status' => 'success', + 'statusCode' => Response::HTTP_OK, + 'message' => 'Data Berhasil di ambil', + 'data' => [ + 'title' => 'Spesialis ' . $specialisName, + 'doctors' => SpecialityResource::collection($doctors) + ] + ]); + } + + public function searchSpecialityOrPerson(Request $request) + { + $doctors = PractitionerRole::query() + ->with(['prices']) + ->whereHas('prices', function ($query) { + $query->where('priceable_type', Practice::class); + }) + ->leftJoin('specialities', function ($query) { + $query->on('practitioner_roles.speciality_id', '=', 'specialities.id'); + }) + ->leftJoin('persons', function ($query) { + $query->on('practitioner_roles.practitioner_id', '=', 'persons.id'); + }) + ->whereRaw("(persons.name LIKE '%{$request->value}%' OR specialities.name LIKE '%{$request->value}%')") + ->where('organization_id', $request->organization_id) + ->get(['persons.name AS person_name', 'specialities.name AS speciality_name', 'practitioner_id', 'practitioner_roles.id']); + + return response()->json([ + 'status' => 'success', + 'statusCode' => Response::HTTP_OK, + 'message' => 'Data Berhasil di ambil', + 'data' => [ + 'doctors' => SpecialityResource::collection($doctors) + ] + ]); + } + + /** + * Show the form for creating a new resource. + * @return Renderable + */ + public function 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(Request $request, $id) + { + // + } + + /** + * Show the form for editing the specified resource. + * @param int $id + * @return Renderable + */ + public function edit($id) + { + // + } + + /** + * Update the specified resource in storage. + * @param Request $request + * @param int $id + * @return Renderable + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * @param int $id + * @return Renderable + */ + public function destroy($id) + { + // + } +} diff --git a/Modules/Linksehat/Providers/RouteServiceProvider.php b/Modules/Linksehat/Providers/RouteServiceProvider.php index 421f1d37..a921c6f7 100644 --- a/Modules/Linksehat/Providers/RouteServiceProvider.php +++ b/Modules/Linksehat/Providers/RouteServiceProvider.php @@ -62,6 +62,7 @@ class RouteServiceProvider extends ServiceProvider protected function mapApiRoutes() { Route::middleware('api') + ->prefix('api') ->namespace($this->moduleNamespace) ->group(module_path('Linksehat', '/Routes/api.php')); } diff --git a/Modules/Linksehat/Routes/api.php b/Modules/Linksehat/Routes/api.php index 39487993..e2e9374c 100644 --- a/Modules/Linksehat/Routes/api.php +++ b/Modules/Linksehat/Routes/api.php @@ -1,10 +1,11 @@ group(function () { - Route::post('otp-request', [AuthController::class, 'otpRequest']); - Route::post('mock-otp', [AuthController::class, 'mockOtp']); - Route::post('login', [AuthController::class, 'login']); - Route::post('register', [AuthController::class, 'register']); - - // Route::get('articles', [ArticleController::class, 'index']); - // Route::get('articles/id', [ArticleController::class, 'show']); - - Route::get('hospitals', [HospitalController::class, 'index']); - Route::get('hospitals/{id}', [HospitalController::class, 'show']); - - Route::get('doctors/online', [DoctorController::class, 'index'])->name('doctors.online'); - Route::get('doctors', [DoctorController::class, 'index'])->name('doctors.index'); - Route::get('doctors/{id}', [DoctorController::class, 'show'])->name('doctors.show'); - Route::post('doctors/{id}/schedule', [DoctorController::class, 'schedule'])->name('doctors.schedule'); - - // Route::middleware('auth:api')->get('/linksehat', function (Request $request) { - // return $request->user(); - // }); + Route::get('dashboard/{query}/{limit?}', [DashboardController::class, 'index']); + + Route::controller(AuthController::class)->group(function () { + Route::post('otp-request', 'otpRequest'); + Route::post('mock-otp', 'mockOtp'); + Route::post('login', 'login'); + Route::post('register', 'register'); + Route::get('social-login/{provider}', 'redirectSocialLogin'); + Route::get('social-login/{provider}/callback', 'handleSocialLoginCallback'); + }); + + Route::controller(SpecialityController::class)->group(function () { + Route::get('specialities', 'index'); + Route::get('search', 'searchSpecialityOrPerson'); + }); + + Route::controller(HospitalController::class)->group(function () { + Route::get('hospitals', 'index'); + Route::get('hospitals/{id}', 'show'); + }); + + Route::controller(DoctorController::class)->group(function () { + Route::get('doctors/online', 'index')->name('doctors.online'); + Route::get('doctors', 'index')->name('doctors.index'); + Route::get('doctors/{id}', 'show')->name('doctors.show'); + Route::post('doctors/{id}/schedule', 'schedule')->name('doctors.schedule'); + }); - Route::middleware('auth:sanctum')->group(function () { Route::get('profile', [ProfileController::class, 'index'])->name('profile'); Route::post('profile', [ProfileController::class, 'update'])->name('profile.update'); }); -}); \ No newline at end of file +}); diff --git a/Modules/Linksehat/Transformers/Dashboard/ArticleResource.php b/Modules/Linksehat/Transformers/Dashboard/ArticleResource.php new file mode 100644 index 00000000..70bb1f2f --- /dev/null +++ b/Modules/Linksehat/Transformers/Dashboard/ArticleResource.php @@ -0,0 +1,28 @@ + $this->nID, + 'sSlug' => $this->sSlug, + 'title' => $this->sJudulArtikel, + 'deskripsi' => $this->sMetaDeskripsi, + 'photos' => [ + 'title' => $this->sSlug, + 'url' => $this->sImages + ] + ]; + } +} diff --git a/Modules/Linksehat/Transformers/Dashboard/DoctorResource.php b/Modules/Linksehat/Transformers/Dashboard/DoctorResource.php new file mode 100644 index 00000000..099f183a --- /dev/null +++ b/Modules/Linksehat/Transformers/Dashboard/DoctorResource.php @@ -0,0 +1,27 @@ + $this->practitioner_id, + 'name' => $this->person->name ?? '', + 'specialis' => "Spesialis " . $this->speciality->name ?? '', + 'photos' => [ + 'title' => 'doctors-avatar-' . $this->practitioner_id, + 'url' => asset('images/default-doctor-avatar.png') + ] + ]; + } +} diff --git a/Modules/Linksehat/Transformers/Dashboard/HospitalResource.php b/Modules/Linksehat/Transformers/Dashboard/HospitalResource.php new file mode 100644 index 00000000..7de0dbd7 --- /dev/null +++ b/Modules/Linksehat/Transformers/Dashboard/HospitalResource.php @@ -0,0 +1,29 @@ + $this->id, + 'name' => $this->name ?? '', + 'address' => $this->currentAddress ?? '', + 'distance' => $this->distance ? ($this->distance < 1 ? round($this->distance * 1000, 2) . " m" : round($this->distance, 2) . " km") : null, + 'photos' => [ + 'title' => Str::slug($this->name), + 'url' => asset('images/default-hospital-image.png'), + ] + ]; + } +} diff --git a/Modules/Linksehat/Transformers/DoctorResource.php b/Modules/Linksehat/Transformers/DoctorResource.php index 9dd06382..1bbd951e 100644 --- a/Modules/Linksehat/Transformers/DoctorResource.php +++ b/Modules/Linksehat/Transformers/DoctorResource.php @@ -25,7 +25,7 @@ class DoctorResource extends JsonResource // 'speciality' => SpecialityResource::make($practitionerRole->speciality), // 'str' => '3121100888826697', // 'sip' => '73/B.16/31.71.05.1003.01.015.S.2/4/-1.779.3/e/2020', - + // 'is_chat_available' => $practitionerRole->is_chat_available, // 'is_video_available' => $practitionerRole->is_video_available, // 'is_walkin_available' => $practitionerRole->is_walkin_available, @@ -52,7 +52,7 @@ class DoctorResource extends JsonResource // 'hospital' => HospitalResource::make($practitionerRole->organization), // 'str' => '3121100888826697', // 'sip' => '73/B.16/31.71.05.1003.01.015.S.2/4/-1.779.3/e/2020', - + // 'is_chat_available' => $practitionerRole->is_chat_available, // 'is_video_available' => $practitionerRole->is_video_available, // 'is_walkin_available' => $practitionerRole->is_walkin_available, @@ -61,7 +61,7 @@ class DoctorResource extends JsonResource $hospitals[$practitionerRole->organization_id]['id'] = $practitionerRole->hospital_id; - $hospitals[$practitionerRole->organization_id]['code'] = $practitionerRole->organization->code; + // $hospitals[$practitionerRole->organization_id]['code'] = $practitionerRole->organization->code; $hospitals[$practitionerRole->organization_id]['name'] = $practitionerRole->organization->name; $hospitals[$practitionerRole->organization_id]['description'] = $practitionerRole->organization->description; $hospitals[$practitionerRole->organization_id]['address'] = $practitionerRole->organization->currentAddress->text; @@ -81,7 +81,7 @@ class DoctorResource extends JsonResource 'speciality' => SpecialityResource::make($practitionerRole->speciality), 'str' => '3121100888826697', 'sip' => '73/B.16/31.71.05.1003.01.015.S.2/4/-1.779.3/e/2020', - + 'is_chat_available' => $practitionerRole->is_chat_available, 'is_video_available' => $practitionerRole->is_video_available, 'is_walkin_available' => $practitionerRole->is_walkin_available, @@ -110,7 +110,7 @@ class DoctorResource extends JsonResource 'name_suffix' => $this->person->name_suffix ?? null, 'gender' => $this->person->gender ?? null, 'is_online' => false, - 'is_insurance_covered' => rand(0,1) == 1, + 'is_insurance_covered' => rand(0, 1) == 1, 'price_range' => 'Rp 100.000 - Rp 350.000', 'price_start' => '100000', 'price_end' => '350000', diff --git a/Modules/Linksehat/Transformers/Doctors/DoctorResourceDetail.php b/Modules/Linksehat/Transformers/Doctors/DoctorResourceDetail.php new file mode 100644 index 00000000..8890da13 --- /dev/null +++ b/Modules/Linksehat/Transformers/Doctors/DoctorResourceDetail.php @@ -0,0 +1,66 @@ +practices as $practice) { + $prices[$practice->service_code] = Helper::currencyIdrFormat($practice->price); + } + + $award[] = explode("\n", $this->practitioner->meta->award); + $education[] = explode("\n", $this->practitioner->meta->education); + + $queryHospitals = Organization::query() + ->without('meta') + ->where('organizations.type', 'hospital') + ->leftJoin('addresses', function ($q) { + $q->on('organizations.main_address_id', '=', 'addresses.id'); + $q->where('addresses.addressable_type', '=', Organization::class); + }); + if ($request->has('lat') && !empty($request->lat) && $request->has('lng') && !empty($request->lng)) { + $queryHospitals = $queryHospitals->selectRaw("organizations.*, addresses.text AS currentAddress, 6371 * acos (cos ( radians($request->lat) ) * cos( radians( addresses.lat ) ) * cos( radians( addresses.lng ) - radians($request->lng) ) + sin ( radians($request->lat) ) * sin( radians( addresses.lat ) )) as distance")->orderBy('distance', 'ASC'); + } + $queryHospitals = $queryHospitals->orderBy('organizations.name', 'asc')->where('organizations.id', $this->organization_id)->get(); + + return [ + 'name' => $this->practitioner->person->full_name, + 'length_of_work_year' => rand(1, 20), + 'price' => $prices, + 'rating' => rand(50, 100), + 'photos' => [ + 'title' => 'doctor-avatar-' . $this->practitioner->person->id, + 'url' => asset('images/default-doctor-avatar.png') + ], + 'spesialis' => [ + [ + 'name' => 'Spesialis ' . $this->speciality->name, + 'str' => random_int(1000000000000000, 5000000000000000) + ], + ], + 'award' => $award, + 'education' => $education, + 'location_practect' => HospitalResource::collection($queryHospitals), + 'available' => [ + 'is_chat_available' => $this->is_chat_available, + 'is_video_available' => $this->is_video_available, + 'is_walkin_available' => $this->is_walkin_available, + 'is_instant_chat_available' => $this->is_instant_chat_available, + 'day_available' => $this->day_available + ] + ]; + } +} diff --git a/Modules/Linksehat/Transformers/Hospitals/HospitalResourceDetail.php b/Modules/Linksehat/Transformers/Hospitals/HospitalResourceDetail.php new file mode 100644 index 00000000..e9534681 --- /dev/null +++ b/Modules/Linksehat/Transformers/Hospitals/HospitalResourceDetail.php @@ -0,0 +1,51 @@ +with(['speciality']) + ->where('organization_id', $this->id) + ->whereNotNull('speciality_id') + ->orderBy('speciality_id') + ->groupBy('speciality_id') + ->get(['speciality_id']); + + foreach ($querySpecialitys as $indexSpeciality => $speciality) { + $specialitys[$indexSpeciality]['id'] = $speciality->speciality->id; + $specialitys[$indexSpeciality]['name'] = $speciality->speciality->name; + $specialitys[$indexSpeciality]['avatar'] = asset('images/default-specialisasi-image.png'); + } + + if (empty($this->distance)) { + $address = $this->currentAddress->text; + } else { + $address = $this->currentAddress; + } + + return [ + 'id' => $this->id, + 'name' => $this->name, + 'address' => $address ?? null, + 'distance' => $this->distance ? ($this->distance < 1 ? round($this->distance * 1000, 2) . " m" : round($this->distance, 2) . " km") : null, + 'photos' => [ + 'title' => Str::slug($this->name), + 'url' => asset('images/default-hospital-image.png'), + ], + 'specialitys' => $specialitys + ]; + } +} diff --git a/Modules/Linksehat/Transformers/Speciality/SpecialityResource.php b/Modules/Linksehat/Transformers/Speciality/SpecialityResource.php new file mode 100644 index 00000000..b4477951 --- /dev/null +++ b/Modules/Linksehat/Transformers/Speciality/SpecialityResource.php @@ -0,0 +1,41 @@ +practices as $practice) { + if ($practice->service_code === 'walkin') { + $practices[] = $practice->id; + } + } + + foreach ($this->prices as $price) { + if (in_array($price->priceable_id, $practices)) { + $prices = $price->price_net; + } + } + + return [ + 'doctors' => [ + 'id' => isset($this->practitioner->person->id) ? $this->practitioner->person->id : $this->practitioner_id, + 'name' => isset($this->practitioner->person->name) ? $this->practitioner->person->name : $this->person_name, + 'specialis' => 'Spesialis ' . (isset($this->speciality->name) ? $this->speciality->name : $this->speciality_name), + 'experience' => rand(5, 12), + 'rating' => rand(20, 100), + 'price' => Helper::currencyIdrFormat($prices), + ] + ]; + } +} diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 008b40fa..9dc538c1 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -2,7 +2,13 @@ namespace App\Exceptions; +use Illuminate\Auth\Access\AuthorizationException; +use Illuminate\Auth\AuthenticationException; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Illuminate\Validation\ValidationException; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Throwable; class Handler extends ExceptionHandler @@ -47,4 +53,64 @@ class Handler extends ExceptionHandler // }); } + + public function render($request, Throwable $exception) + { + if ($request->wantsJson()) { + if ($exception instanceof AuthenticationException) { + return response()->json([ + 'status' => 'error', + 'statusCode' => Response::HTTP_UNAUTHORIZED, + 'message' => 'Unauthenticated', + 'errors' => [ + 'Unauthenticated' + ] + ], Response::HTTP_UNAUTHORIZED); + } + + if ($exception instanceof AuthorizationException) { + return response()->json([ + 'status' => 'error', + 'statusCode' => Response::HTTP_FORBIDDEN, + 'message' => 'This action is unauthorized.', + 'errors' => [ + 'This action is unauthorized.' + ] + ], Response::HTTP_FORBIDDEN); + } + + if ($exception instanceof NotFoundHttpException) { + return response()->json([ + 'status' => 'error', + 'statusCode' => Response::HTTP_NOT_FOUND, + 'message' => 'Route Not Found', + 'errors' => [ + 'Route Not Found' + ] + ], Response::HTTP_NOT_FOUND); + } + + if ($exception instanceof ModelNotFoundException) { + return response()->json([ + 'status' => 'error', + 'statusCode' => Response::HTTP_NOT_FOUND, + 'message' => 'Record for ' . str_replace('App', '', str_replace('\\Models\\', '', $exception->getModel())) . ' not found', + 'errors' => [ + 'Record for ' . str_replace('App', '', str_replace('\\Models\\', '', $exception->getModel())) . ' not found' + ] + ], Response::HTTP_NOT_FOUND); + } + + if ($exception instanceof ValidationException) { + return response()->json([ + 'status' => 'error', + 'statusCode' => Response::HTTP_UNPROCESSABLE_ENTITY, + 'message' => 'The given data was invalid.', + 'errors' => collect($exception->errors())->flatten() + ], Response::HTTP_UNPROCESSABLE_ENTITY); + } + } + + return parent::render($request, $exception); + } } diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 2caf886e..85f56d8c 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -4,63 +4,147 @@ namespace App\Helpers; use Carbon\Carbon; use Carbon\CarbonPeriod; -use Illuminate\Support\Collection; -class Helper{ +class Helper +{ public static function genderNormalization($anyGenderCode) { - if ($anyGenderCode == 'M') { - return 'male'; - } else if ($anyGenderCode == 'F') { - return 'female'; - } else if ($anyGenderCode == 'O') { - return 'others'; - } else if ($anyGenderCode == 'U') { - return 'unknown'; - } else { - return null; - } + if ($anyGenderCode == 'M') { + return 'male'; + } else if ($anyGenderCode == 'F') { + return 'female'; + } else if ($anyGenderCode == 'O') { + return 'others'; + } else if ($anyGenderCode == 'U') { + return 'unknown'; + } else { + return null; + } } public static function paginateResources($resource) { - return [ - 'current_page' => $resource->currentPage(), - 'data' => $resource->items(), - 'first_page_url' => '', - 'from' => $resource->firstItem(), - 'last_page' => $resource->lastPage(), - 'last_page_url' => '', - 'links' => $resource->links(null, $resource->items()), - 'next_page_url' => $resource->nextPageUrl(), - ]; + return [ + 'current_page' => $resource->currentPage(), + 'data' => $resource->items(), + 'first_page_url' => '', + 'from' => $resource->firstItem(), + 'last_page' => $resource->lastPage(), + 'last_page_url' => '', + 'links' => $resource->links(null, $resource->items()), + 'next_page_url' => $resource->nextPageUrl(), + ]; } - public static function dailyAvailabilitiesToDate($dailyAvailabilities, $startDate, $endDate = null) { - - Carbon::setLocale('id'); + public static function dailyAvailabilitiesToDate($dailyAvailabilities, $startDate, $endDate = null) + { - $startDate = Carbon::parse($startDate); - if ( empty($endDate) ) { - $endDate = $startDate; - } else { - $endDate = Carbon::parse($endDate); - } - $ranges = CarbonPeriod::create($startDate, $endDate); + Carbon::setLocale('id'); - $datesAvailabilities = []; - foreach ( $ranges as $date ) { - - $datesAvailabilities[] = [ - 'date' => $date->format('Y-m-d'), - 'day' => $date->dayName, - 'slot' => $dailyAvailabilities[$date->dayName], - 'timezone' => 'WIB' + $startDate = Carbon::parse($startDate); + if (empty($endDate)) { + $endDate = $startDate; + } else { + $endDate = Carbon::parse($endDate); + } + $ranges = CarbonPeriod::create($startDate, $endDate); + + $datesAvailabilities = []; + foreach ($ranges as $date) { + + $datesAvailabilities[] = [ + 'date' => $date->format('Y-m-d'), + 'day' => $date->dayName, + 'slot' => $dailyAvailabilities[$date->dayName], + 'timezone' => 'WIB' + ]; + } + + return $datesAvailabilities; + } + + public static function dailyAvailabilities($availabilities) + { + $hours = [ + 'Pagi' => [], + 'Siang' => [], + 'Sore' => [], + 'Petang' => [], + 'Malam' => [] ]; - } + foreach ($availabilities as $availability) { + $time = explode(':', $availability->start_time); - return $datesAvailabilities; + if (count($availability->days)) { + foreach ($availability->days as $key => $day) { + $periods = CarbonPeriod::create(now(), now()->lastOfMonth()->addDays(1)) + ->filter(function (Carbon $date) use ($day) { + switch ($day->day) { + case 'Senin': + return $date->isMonday(); + break; + case 'Selasa': + return $date->isTuesday(); + break; + case 'Rabu': + return $date->isWednesday(); + break; + case 'Kamis': + return $date->isThursday(); + break; + case 'Jumat': + return $date->isFriday(); + break; + case 'Sabtu': + return $date->isSaturday(); + break; + case 'Minggu': + return $date->isSunday(); + break; + } + })->toArray(); + } + foreach ($periods as $day) { + foreach ($hours as $hour => $value) { + if (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(05, 00, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(10, 59, 00)->timestamp && $hour === "Pagi") { + $schedules[Carbon::create($day)->day][$hour][] = substr($availability->start_time, 0, -3); + } elseif (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(11, 00, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(15, 00, 00)->timestamp && $hour === "Siang") { + $schedules[Carbon::create($day)->day][$hour][] = substr($availability->start_time, 0, -3); + } elseif (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(15, 01, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(18, 00, 00)->timestamp && $hour === "Sore") { + $schedules[Carbon::create($day)->day][$hour][] = substr($availability->start_time, 0, -3); + } elseif (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(18, 00, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(19, 00, 00)->timestamp && $hour === "Petang") { + $schedules[Carbon::create($day)->day][$hour][] = substr($availability->start_time, 0, -3); + } elseif (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(19, 00, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(24, 00, 00)->timestamp && $hour === "Malam") { + $schedules[Carbon::create($day)->day][$hour][] = substr($availability->start_time, 0, -3); + } + } + } + } else { + foreach ($hours as $hour => $value) { + for ($i = Carbon::now()->day; $i <= Carbon::now()->daysInMonth; $i++) { + if (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(05, 00, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(10, 59, 00)->timestamp && $hour === "Pagi") { + $schedules[$i][$hour][] = substr($availability->start_time, 0, -3); + } elseif (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(11, 00, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(15, 00, 00)->timestamp && $hour === "Siang") { + $schedules[$i][$hour][] = substr($availability->start_time, 0, -3); + } elseif (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(15, 01, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(18, 00, 00)->timestamp && $hour === "Sore") { + $schedules[$i][$hour][] = substr($availability->start_time, 0, -3); + } elseif (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(18, 00, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(19, 00, 00)->timestamp && $hour === "Petang") { + $schedules[$i][$hour][] = substr($availability->start_time, 0, -3); + } elseif (Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp >= Carbon::createFromTime(19, 00, 00)->timestamp && Carbon::createFromTime($time[0], $time[1], $time[2])->timestamp <= Carbon::createFromTime(24, 00, 00)->timestamp && $hour === "Malam") { + $schedules[$i][$hour][] = substr($availability->start_time, 0, -3); + } + } + } + } + } + + return (object) $schedules; + } + + public static function currencyIdrFormat($price) + { + return "Rp. " . number_format($price, 0, ',', '.'); } } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index c3be2544..bf500999 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -21,6 +21,7 @@ class Kernel extends HttpKernel \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + \Illuminate\Session\Middleware\StartSession::class, ]; /** diff --git a/app/Models/Organization.php b/app/Models/Organization.php index 2e1c6fbe..0990877c 100644 --- a/app/Models/Organization.php +++ b/app/Models/Organization.php @@ -27,7 +27,7 @@ class Organization extends Model public $appends = [ 'meta' ]; - + public function setCodeAttribute($value) { $this->attributes['code'] = !empty($value) ? $value : Str::upper(Str::random('6')); diff --git a/app/Models/Practice.php b/app/Models/Practice.php index 09e5e0b5..a349eefd 100644 --- a/app/Models/Practice.php +++ b/app/Models/Practice.php @@ -18,6 +18,22 @@ class Practice extends Model 'deleted_by' ]; + public function getPriceAttribute() + { + return $this->prices->where('priceable_id', $this->id)->max('price_net'); + } + + public function getPricesGroupOneAttribute() + { + $orgPrices = []; + + foreach ($this->prices->where('price_group_id', 1) as $price) { + $orgPrices[$this->service_code] = $price->price_net; + } + + return $orgPrices; + } + public function prices() { return $this->morphMany(Price::class, 'priceable'); diff --git a/app/Models/PractitionerRole.php b/app/Models/PractitionerRole.php index ae2363ec..19efe922 100644 --- a/app/Models/PractitionerRole.php +++ b/app/Models/PractitionerRole.php @@ -39,39 +39,6 @@ class PractitionerRole extends Model return $this->practices->where('service_code', 'instant-chat')->where('active', 1)->count() >= 1; } - public function getDailyAvailabilitiesAttribute() - { - $schedules = [ - 'Senin' => [], - 'Selasa' => [], - 'Rabu' => [], - 'Kamis' => [], - 'Jumat' => [], - 'Sabtu' => [], - 'Minggu' => [] - ]; - - foreach ($this->availabilities as $availability) { - - if (count($availability->days)) { - - foreach ($availability->days as $day) { - $schedules[$day][] = $availability->start_time; - } - - } else { - - foreach ($schedules as $day => $times) { - $schedules[$day][] = $availability->start_time; - } - - } - - } - - return $schedules; - } - public function metas() { return $this->morphMany(Meta::class, 'metaable'); @@ -97,8 +64,18 @@ class PractitionerRole extends Model return $this->hasMany(Practice::class, 'practitioner_role_id'); } + public function prices() + { + return $this->hasManyThrough(Price::class, Practice::class, 'practitioner_role_id', 'id'); + } + public function availabilities() { return $this->hasMany(PractitionerRoleAvailability::class, 'practitioner_role_id'); } + + public function person() + { + return $this->hasOneThrough(Person::class, Practitioner::class, 'person_id', 'id'); + } } diff --git a/composer.json b/composer.json index 3cd6473f..a2ad5205 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ "guzzlehttp/guzzle": "^7.2", "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", diff --git a/composer.lock b/composer.lock index 562677ee..ba7ef8a6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b90f9f090c04c5bbe673dadc0237e57d", + "content-hash": "d08dff996a3db932c1ac6127c81d2c82", "packages": [ { "name": "box/spout", @@ -1322,6 +1322,75 @@ }, "time": "2022-02-11T19:23:53+00:00" }, + { + "name": "laravel/socialite", + "version": "v5.5.5", + "source": { + "type": "git", + "url": "https://github.com/laravel/socialite.git", + "reference": "ce8b2f967eead5a6bae74449e207be6f8046edc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/socialite/zipball/ce8b2f967eead5a6bae74449e207be6f8046edc3", + "reference": "ce8b2f967eead5a6bae74449e207be6f8046edc3", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0", + "illuminate/http": "^6.0|^7.0|^8.0|^9.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0", + "league/oauth1-client": "^1.10.1", + "php": "^7.2|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0", + "phpunit/phpunit": "^8.0|^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Socialite\\SocialiteServiceProvider" + ], + "aliases": { + "Socialite": "Laravel\\Socialite\\Facades\\Socialite" + } + } + }, + "autoload": { + "psr-4": { + "Laravel\\Socialite\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", + "homepage": "https://laravel.com", + "keywords": [ + "laravel", + "oauth" + ], + "support": { + "issues": "https://github.com/laravel/socialite/issues", + "source": "https://github.com/laravel/socialite" + }, + "time": "2022-08-20T21:32:07+00:00" + }, { "name": "laravel/tinker", "version": "v2.7.2", @@ -1724,6 +1793,82 @@ ], "time": "2022-04-17T13:12:02+00:00" }, + { + "name": "league/oauth1-client", + "version": "v1.10.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth1-client.git", + "reference": "d6365b901b5c287dd41f143033315e2f777e1167" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/d6365b901b5c287dd41f143033315e2f777e1167", + "reference": "d6365b901b5c287dd41f143033315e2f777e1167", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-openssl": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "guzzlehttp/psr7": "^1.7|^2.0", + "php": ">=7.1||>=8.0" + }, + "require-dev": { + "ext-simplexml": "*", + "friendsofphp/php-cs-fixer": "^2.17", + "mockery/mockery": "^1.3.3", + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5||9.5" + }, + "suggest": { + "ext-simplexml": "For decoding XML-based responses." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev", + "dev-develop": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth1\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Corlett", + "email": "bencorlett@me.com", + "homepage": "http://www.webcomm.com.au", + "role": "Developer" + } + ], + "description": "OAuth 1.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "bitbucket", + "identity", + "idp", + "oauth", + "oauth1", + "single sign on", + "trello", + "tumblr", + "twitter" + ], + "support": { + "issues": "https://github.com/thephpleague/oauth1-client/issues", + "source": "https://github.com/thephpleague/oauth1-client/tree/v1.10.1" + }, + "time": "2022-04-15T14:02:14+00:00" + }, { "name": "maatwebsite/excel", "version": "3.1.40", @@ -9126,5 +9271,5 @@ "php": "^8.0.2" }, "platform-dev": [], - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.3.0" } diff --git a/config/app.php b/config/app.php index d9b54f83..7b65882a 100644 --- a/config/app.php +++ b/config/app.php @@ -69,7 +69,7 @@ return [ | */ - 'timezone' => 'UTC', + 'timezone' => 'Asia/Jakarta', /* |-------------------------------------------------------------------------- @@ -82,7 +82,7 @@ return [ | */ - 'locale' => 'en', + 'locale' => 'id', /* |-------------------------------------------------------------------------- diff --git a/config/services.php b/config/services.php index 0ace530e..e1904897 100644 --- a/config/services.php +++ b/config/services.php @@ -31,4 +31,10 @@ return [ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), ], + 'google' => [ + 'client_id' => env('GOOGLE_CLIENT_ID'), + 'client_secret' => env('GOOGLE_CLIENT_SECRET'), + 'redirect' => env('GOOGLE_REDIRECT_URI'), + ], + ]; diff --git a/database/migrations/2022_07_28_032235_create_icd_table.php b/database/migrations/2022_07_28_032235_create_icd_table.php index 39d95fd5..0baf30b1 100644 --- a/database/migrations/2022_07_28_032235_create_icd_table.php +++ b/database/migrations/2022_07_28_032235_create_icd_table.php @@ -18,13 +18,13 @@ return new class extends Migration $table->string('rev'); $table->string('version')->nullable(); $table->string('code'); - $table->string('name'); + $table->string('name', 256); $table->text('description')->nullable(); $table->string('parent_code')->nullable()->index(); - + $table->timestamps(); $table->softDeletes(); - + $table->foreignId('created_by')->nullable(); $table->foreignId('updated_by')->nullable(); $table->foreignId('deleted_by')->nullable(); diff --git a/database/seeders/PractitionerSeeder.php b/database/seeders/PractitionerSeeder.php index 44334af2..2504244b 100644 --- a/database/seeders/PractitionerSeeder.php +++ b/database/seeders/PractitionerSeeder.php @@ -21,15 +21,15 @@ class PractitionerSeeder extends Seeder public function run() { $organizations = Organization::query() - ->whereHas('metas', function ($meta) { - $meta->where('type', 'KodeRS'); - }) - ->with('metas') - ->get(); + ->whereHas('metas', function ($meta) { + $meta->where('type', 'KodeRS'); + }) + ->with('metas') + ->get(); $specialities = Speciality::pluck('id', 'name')->toArray(); - + foreach ($organizations as $organization) { - $response = Http::get('https://api.primaya.id/temp/practitioners?code='.$organization->meta->KodeRS); + $response = Http::get('https://app.primaya.id/temp/practitioners?code=' . $organization->meta->KodeRS); foreach ($response->json()['practitioners'] as $practitioner) { $practitioner = json_decode(json_encode($practitioner)); @@ -57,7 +57,7 @@ class PractitionerSeeder extends Seeder $newPractitioner = Practitioner::updateOrCreate([ 'person_id' => $newPerson->id - ],[ + ], [ 'person_id' => $newPerson->id ]); $newPractitioner->metas()->create([ @@ -95,7 +95,7 @@ class PractitionerSeeder extends Seeder 'type' => 'description', 'value' => $practitioner->doctor->description ?? null, ]); - + @@ -109,23 +109,23 @@ class PractitionerSeeder extends Seeder if (empty($newPractitionerRole->speciality_id)) { $newPractitionerRole->metas()->updateOrCreate([ 'type' => 'speciality_code', - ],[ + ], [ 'system' => 'default', 'type' => 'speciality_code', 'value' => $practitioner->speciality->code ?? null, ]); - + $newPractitionerRole->metas()->updateOrCreate([ 'type' => 'speciality', - ],[ + ], [ 'system' => 'default', 'type' => 'speciality', 'value' => $practitioner->speciality->name ?? null, ]); - + $newPractitionerRole->metas()->updateOrCreate([ 'type' => 'speciality_image', - ],[ + ], [ 'system' => 'default', 'type' => 'speciality_image', 'value' => $practitioner->speciality->name ?? null, @@ -135,7 +135,7 @@ class PractitionerSeeder extends Seeder $newPractitionerRole->metas()->updateOrCreate([ 'type' => 'primaya-his', 'type' => 'DokterID', - ],[ + ], [ 'system' => 'primaya-his', 'type' => 'DokterID', 'value' => $practitioner->meta->DokterID ?? null, diff --git a/database/seeders/PriceSeeder.php b/database/seeders/PriceSeeder.php new file mode 100644 index 00000000..df7da014 --- /dev/null +++ b/database/seeders/PriceSeeder.php @@ -0,0 +1,44 @@ +service_code === 'instant-chat') { + $price = 20000; + } elseif ($practitionerRole->service_code === 'chat') { + $price = 50000; + } elseif ($practitionerRole->service_code === 'video') { + $price = 70000; + } elseif ($practitionerRole->service_code === 'walkin') { + $price = 90000; + } + + $practitionerRole->prices()->insert([ + 'priceable_type' => 'App\Models\Practice', + 'priceable_id' => $practitionerRole->id, + 'price_group_id' => 1, + 'price_gross' => $price, + 'price_net' => $price, + 'has_tax' => 0, + 'discount_type' => 'percentage', + 'discount_percentage' => '', + 'discount_absolute' => '' + ]); + } + }); + } +}