From d54288106b1008b079924317c2986e19603d6f0e Mon Sep 17 00:00:00 2001 From: R Date: Tue, 4 Apr 2023 16:41:59 +0700 Subject: [PATCH 1/6] Remove Unused Files --- public/images/unsplash_ZCztndOWdjs (2).png:Zone.Identifier | 3 --- 1 file changed, 3 deletions(-) delete mode 100755 public/images/unsplash_ZCztndOWdjs (2).png:Zone.Identifier diff --git a/public/images/unsplash_ZCztndOWdjs (2).png:Zone.Identifier b/public/images/unsplash_ZCztndOWdjs (2).png:Zone.Identifier deleted file mode 100755 index 72dcb06b..00000000 --- a/public/images/unsplash_ZCztndOWdjs (2).png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -HostUrl=https://www.figma.com/ From cca2310f54d107f6e200d28960fe3d723da699cf Mon Sep 17 00:00:00 2001 From: R Date: Thu, 6 Apr 2023 05:03:38 +0700 Subject: [PATCH 2/6] [WIP] Add Linksehat Payment Report --- .../Api/Linksehat/PaymentController.php | 131 ++++ .../Http/Controllers/Api/OptionController.php | 9 + Modules/Internal/Routes/api.php | 3 + .../Transformers/ClaimShowResource.php | 3 + .../Transformers/LinksehatPaymentResource.php | 30 + app/Models/Member.php | 17 - app/Models/OLDLMS/Appointment.php | 32 +- .../AutocompleteLinksehatHealthcare.tsx | 64 ++ .../layouts/dashboard/navbar/NavConfig.tsx | 1 + .../components/DialogDocumentRequest.tsx | 70 ++ .../components/DialogHistoryPerawatan.tsx | 4 +- .../src/pages/Claims/components/Documents.tsx | 101 ++- .../pages/Report/LinksehatPayments/Create.tsx | 93 +++ .../pages/Report/LinksehatPayments/Form.tsx | 260 +++++++ .../pages/Report/LinksehatPayments/Index.tsx | 35 + .../pages/Report/LinksehatPayments/List.tsx | 637 ++++++++++++++++++ .../pages/Report/LinksehatPayments/Show.tsx | 53 ++ .../pages/Report/LinksehatPayments/View.tsx | 275 ++++++++ .../src/pages/Report/Livechat/Index.tsx | 8 +- frontend/dashboard/src/routes/index.tsx | 6 + 20 files changed, 1786 insertions(+), 46 deletions(-) create mode 100644 Modules/Internal/Http/Controllers/Api/Linksehat/PaymentController.php create mode 100644 Modules/Internal/Transformers/LinksehatPaymentResource.php create mode 100644 frontend/dashboard/src/components/autocomplete/AutocompleteLinksehatHealthcare.tsx create mode 100644 frontend/dashboard/src/pages/Claims/components/DialogDocumentRequest.tsx create mode 100644 frontend/dashboard/src/pages/Report/LinksehatPayments/Create.tsx create mode 100644 frontend/dashboard/src/pages/Report/LinksehatPayments/Form.tsx create mode 100644 frontend/dashboard/src/pages/Report/LinksehatPayments/Index.tsx create mode 100644 frontend/dashboard/src/pages/Report/LinksehatPayments/List.tsx create mode 100644 frontend/dashboard/src/pages/Report/LinksehatPayments/Show.tsx create mode 100644 frontend/dashboard/src/pages/Report/LinksehatPayments/View.tsx diff --git a/Modules/Internal/Http/Controllers/Api/Linksehat/PaymentController.php b/Modules/Internal/Http/Controllers/Api/Linksehat/PaymentController.php new file mode 100644 index 00000000..8d6e035f --- /dev/null +++ b/Modules/Internal/Http/Controllers/Api/Linksehat/PaymentController.php @@ -0,0 +1,131 @@ +toArray(); + $appointments = Appointment::query() + ->where('sPaymentStatus', 'settlement') + ->with(['healthCare', 'detail', 'user', 'doctor', 'doctor.user']); + + if ($request->has('search')) { + $appointments->where(function ($query) use ($request) { + $query->where('nID', $request->search) + ->orWhere('sBookingCode', $request->search) + ->orWhereHas('detail', function (Builder $detail) use ($request) { + $detail->where('sPaymentDetails', 'LIKE', '%' . $request->search . "%"); + }); + }); + } + + if (($request->has('appointment_start') || $request->has('appointment_end')) + && !empty($request->appointment_start) + && !empty($request->appointment_end) + ) { + $appointments = $appointments->whereHas('detail', function (Builder $detail) use ($request) { + + // Appointment Start + // if ($request->has('appointment_start')) { + $detail->where('dTanggalAppointment', '>=', $request->appointment_start); + // } else { + // $detail->where('dTanggalAppointment', '>', now()->format('Y-m-d')); + // } + + // if ($request->has('appointment_end')) { + $detail->where('dTanggalAppointment', '<=', $request->appointment_end); + // } else { + // $detail->where('dTanggalAppointment', '<', now()->addDay(1)->format('Y-m-d')); + // } + + }); + } + + if ($request->has('payment_status') && $request->payment_status != 'semua') { + $appointments->where('sPaymentStatus', $request->payment_status); + } + + if ($request->has('healthcare_id') && !empty($request->healthcare_id)) { + $appointments->where('nIDHealthCare', $request->healthcare_id); + } + + $appointments = $appointments->orderBy('dUpdateOn', 'DESC') + ->paginate(); + + return Helper::responseJson(Helper::paginateResources(LinksehatPaymentResource::collection($appointments))); + } + + /** + * 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) + { + // + } +} diff --git a/Modules/Internal/Http/Controllers/Api/OptionController.php b/Modules/Internal/Http/Controllers/Api/OptionController.php index 050c9867..2d46b506 100644 --- a/Modules/Internal/Http/Controllers/Api/OptionController.php +++ b/Modules/Internal/Http/Controllers/Api/OptionController.php @@ -3,6 +3,7 @@ namespace Modules\Internal\Http\Controllers\Api; use App\Models\Icd; +use App\Models\OLDLMS\Healthcare; use App\Models\Organization; use App\Models\Practitioner; use Illuminate\Contracts\Support\Renderable; @@ -61,6 +62,14 @@ class OptionController extends Controller return $healthcares; break; + case 'linksehat-healthcares': + $healthcares = Healthcare::query() + ->where('sHealthCare', 'LIKE', '%'.$request->search.'%') + ->limit('10') + ->get(); + + return $healthcares; + break; default: # code... diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index cc097ef1..efbd0baf 100755 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -21,6 +21,7 @@ use Modules\Internal\Http\Controllers\Api\DivisionController; use Modules\Internal\Http\Controllers\Api\DoctorController; use Modules\Internal\Http\Controllers\Api\DrugController; use Modules\Internal\Http\Controllers\Api\FormulariumController; +use Modules\Internal\Http\Controllers\Api\Linksehat\PaymentController; use Modules\Internal\Http\Controllers\Api\LivechatController; use Modules\Internal\Http\Controllers\Api\MemberController; use Modules\Internal\Http\Controllers\Api\OptionController; @@ -49,6 +50,8 @@ Route::prefix('internal')->group(function () { Route::post('forget-password', [AuthController::class, 'forgetPassword'])->name('forget-password'); Route::post('verify-email', [AuthController::class, 'verifyEmail'])->name('verify-email'); + Route::get('linksehat/payments', [PaymentController::class, 'index']); + Route::middleware('auth:sanctum')->group(function () { diff --git a/Modules/Internal/Transformers/ClaimShowResource.php b/Modules/Internal/Transformers/ClaimShowResource.php index c4a48e10..e4375c24 100644 --- a/Modules/Internal/Transformers/ClaimShowResource.php +++ b/Modules/Internal/Transformers/ClaimShowResource.php @@ -41,6 +41,9 @@ class ClaimShowResource extends JsonResource $encounterData = EncounterResource::make($encounter); return $encounterData; }); + + // $memberDiagnosisHistories = $this->member-> + return $data; } } diff --git a/Modules/Internal/Transformers/LinksehatPaymentResource.php b/Modules/Internal/Transformers/LinksehatPaymentResource.php new file mode 100644 index 00000000..fe5fcc2f --- /dev/null +++ b/Modules/Internal/Transformers/LinksehatPaymentResource.php @@ -0,0 +1,30 @@ + $this->healthCare->name ?? '', + // 'health_care' => $this->healthCare, + // 'nID' => $this->nID, + // 'sBookingCode' => $this->sBookingCode, + // 'doctor' => $this->doctor, + // 'user' => $this->user, + // 'payment_method' => $this->payment_method, + // 'detail' => $this->detail + // ]; + } +} diff --git a/app/Models/Member.php b/app/Models/Member.php index e6bf5ca4..1bdb4e8c 100755 --- a/app/Models/Member.php +++ b/app/Models/Member.php @@ -124,24 +124,7 @@ class Member extends Model public function currentCorporate() { - // return $this->belongsToMany(Corporate::class, 'corporate_employees', 'corporate_id', 'member_id') - // // ->withPivot([ - // // 'branch_code', - // // 'divison_id', - // // 'nik', - // // 'status', - // // 'start', - // // 'end' - // // ]) - // ->where('start', '<', now()) - // ->where('end', '>', now()); - - return $this->hasOneThrough(Corporate::class, CorporateEmployee::class, 'member_id', 'id', 'id', 'corporate_id'); - // ->where('corporate_policies.start', '<', now()) - // ->where('corporate_policies.end', '>', now()) - // ->where('member_policies.start', '<', now()) - // ->where('member_policies.end', '>', now()); } public function memberPlans() diff --git a/app/Models/OLDLMS/Appointment.php b/app/Models/OLDLMS/Appointment.php index c04215b8..b403902e 100644 --- a/app/Models/OLDLMS/Appointment.php +++ b/app/Models/OLDLMS/Appointment.php @@ -31,6 +31,20 @@ class Appointment extends Model 5 => 'Voucher', ]; + public $sPaymentStatusName = [ + 'settlement' => 'Diterima', + 'expired' => 'Kadaluarsa', + 'capture' => 'Captured', + 'deny' => 'Ditolak', + 'pending' => 'Menunggu Pembayaran', + 'cancel' => 'Dibatalkan', + 'refund' => 'Dikembalikan', + 'expire' => 'Kadaluarsa', + 'cod' => 'COD', + 'FAILED' => 'Gagal', + 'COMPLETED' => 'Complete', + ]; + public $nIDJenisBookingNames = [ 1 => 'Rawat Jalan', 2 => 'Telekonsultasi', @@ -60,7 +74,8 @@ class Appointment extends Model protected $appends = [ 'status_name', 'payment_method', - 'type' + 'type', + 'payment_status' ]; protected function statusName(): Attribute @@ -71,6 +86,16 @@ class Appointment extends Model }, ); } + + + protected function paymentStatus(): Attribute + { + return Attribute::make( + get: function ($value) { + return $this->sPaymentStatusName[$this->sPaymentStatus] ?? $this->sPaymentStatus; + }, + ); + } protected function paymentMethod(): Attribute { @@ -96,6 +121,11 @@ class Appointment extends Model return $this->hasOne(AppointmentDetail::class, 'nIDAppointment', 'nID'); } + public function detail() + { + return $this->hasOne(AppointmentDetail::class, 'nIDAppointment', 'nID'); + } + public function doctor() { return $this->belongsTo(Dokter::class, 'nIDDokter', 'nID'); diff --git a/frontend/dashboard/src/components/autocomplete/AutocompleteLinksehatHealthcare.tsx b/frontend/dashboard/src/components/autocomplete/AutocompleteLinksehatHealthcare.tsx new file mode 100644 index 00000000..8f873d1a --- /dev/null +++ b/frontend/dashboard/src/components/autocomplete/AutocompleteLinksehatHealthcare.tsx @@ -0,0 +1,64 @@ +import axios from '@/utils/axios'; +import { Autocomplete, TextField, CircularProgress } from '@mui/material'; +import { useEffect, useMemo, useState } from 'react'; +import { IcdType } from '@/@types/diagnosis'; +import { Controller } from 'react-hook-form'; + +type autocompleteHealthcareType = { + onChange: any; + textLabel: string; + currentValue: any | null; + currentOptions: IcdType[]; + filter: object | null; +}; + +export default function AutocompleteLinksehatHealthcare({ + onChange, + currentValue, + textLabel, + currentOptions = [], + ...other +}: autocompleteHealthcareType) { + const [options, setOptions] = useState(currentOptions); + const [loading, setLoading] = useState(false); + + + function healthcaresToOptions(healthcares: any[]): any[] { + return healthcares.map(function (healthcare: any) { + return healthcare; + }); + } + + // To Receive Options from Props + useEffect(() => { + setOptions(healthcaresToOptions(currentOptions)); + }, [currentOptions]); + + const getOptions = (search: string) => { + axios + .get('options?type=linksehat-healthcares&search=' + search) + .then((res) => { + setOptions(healthcaresToOptions(res.data)); + }) + .then(() => { + setLoading(false); + }); + }; + + return ( + (`${option.sHealthCare}`)} + value={currentValue} + isOptionEqualToValue={(option, value) => option.nID == value.nID} + onChange={(event: any, newValue: any) => { + // setValue('primary_diagnosis_id', newValue?.id ?? null); + onChange(newValue); + }} + loading={loading} + renderInput={(params) => ( + {getOptions(event.target.value)}}/> + )} + /> + ); +} diff --git a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx index ed6d188f..2c21a84f 100755 --- a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx +++ b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx @@ -81,6 +81,7 @@ const navConfig = [ children: [ { title: 'Appointment', path: '/report/appointments' }, { title: 'Live Chat', path: '/report/live-chat' }, + { title: 'Linksehat Payment', path: '/report/linksehat-payments' }, ], }, { diff --git a/frontend/dashboard/src/pages/Claims/components/DialogDocumentRequest.tsx b/frontend/dashboard/src/pages/Claims/components/DialogDocumentRequest.tsx new file mode 100644 index 00000000..53ba44ce --- /dev/null +++ b/frontend/dashboard/src/pages/Claims/components/DialogDocumentRequest.tsx @@ -0,0 +1,70 @@ +import MuiDialog from '@/components/MuiDialog'; +import axios from '@/utils/axios'; +import { Button, Checkbox, Typography } from '@mui/material'; +import { Paper } from '@mui/material'; +import { Stack } from '@mui/material'; +import { enqueueSnackbar } from 'notistack'; +import React, { useState } from 'react'; +import FormHistoryPerawatan from './FormHistoryPerawatan'; + +type DialogDocumentRequestType = { + openDialog: boolean; + setOpenDialog: React.Dispatch; + onSubmit?: void; + claim: any; // TODO create ClaimType + encounter?: any; +} + +export default function DialogDocumentRequest({ openDialog, setOpenDialog, onSubmit, claim } : DialogDocumentRequestType) { + + const handleSubmit = (data) => { + + axios.post(`claims/${claim.id}/encounters`, data) + .then((res) => { + enqueueSnackbar(res.data.message, {variant: 'success'}) + setOpenDialog(false); + }) + .catch((err) => { + enqueueSnackbar(err.message, {variant: 'error'}) + }) + + onSubmit() + }; + + const documentTypes = [ + { + type: "result", + name: "Dokumen Hasil Penunjang" + }, + { + type: "claim-diagnosis", + name: "Dokumen Diagnosa" + }, + { + type: "claim-diagnosis", + name: "Dokumen Diagnosa" + } + ]; + + + const getContent = () => ( + + {documentTypes.map((document, index) => ( + + + {document.name} + + ))} + + ); + + return ( + + ); +} diff --git a/frontend/dashboard/src/pages/Claims/components/DialogHistoryPerawatan.tsx b/frontend/dashboard/src/pages/Claims/components/DialogHistoryPerawatan.tsx index e32752d5..ed183def 100644 --- a/frontend/dashboard/src/pages/Claims/components/DialogHistoryPerawatan.tsx +++ b/frontend/dashboard/src/pages/Claims/components/DialogHistoryPerawatan.tsx @@ -4,12 +4,12 @@ import { Button, Checkbox, Typography } from '@mui/material'; import { Paper } from '@mui/material'; import { Stack } from '@mui/material'; import { enqueueSnackbar } from 'notistack'; -import { useState } from 'react'; +import React, { useState } from 'react'; import FormHistoryPerawatan from './FormHistoryPerawatan'; type DialogHistoryPerawatanType = { openDialog: boolean; - setOpenDialog: void; + setOpenDialog: React.Dispatch; onSubmit?: void; claim: any; // TODO create ClaimType encounter?: any; diff --git a/frontend/dashboard/src/pages/Claims/components/Documents.tsx b/frontend/dashboard/src/pages/Claims/components/Documents.tsx index fefe2a94..34523f21 100644 --- a/frontend/dashboard/src/pages/Claims/components/Documents.tsx +++ b/frontend/dashboard/src/pages/Claims/components/Documents.tsx @@ -1,33 +1,57 @@ +import { IconButtonAnimate } from '@/components/animate'; import Iconify from '@/components/Iconify'; +import MuiDialog from '@/components/MuiDialog'; +import { Box, Tooltip } from '@mui/material'; import { Paper, Stack, Typography } from '@mui/material'; import { useState } from 'react'; +import DialogDocumentRequest from './DialogDocumentRequest'; export default function Documents({ files }) { // -------------------------------------------------------------- // Dialog Request Document const [openDialogRequestDocument, setOpenDialogRequestDocument] = useState(false); + const [openDialogConfirmRequestDocument, setOpenDialogConfirmRequestDocument] = useState(false); - function FileItem({item}) { + function FileItem({ item }) { function fileCategory(type: string) { - switch(type) { - case 'claim-result': - return 'Claim Result'; - case 'claim-diagnosis': - return 'Claim Diagnosis'; - case 'claim-condition': - return 'Claim Condition'; - default: - return 'Other File'; - } + switch (type) { + case 'claim-result': + return 'Claim Result'; + case 'claim-diagnosis': + return 'Claim Diagnosis'; + case 'claim-condition': + return 'Claim Condition'; + default: + return 'Other File'; + } } + const documentTypes = [ + { + type: 'result', + name: 'Dokumen Hasil Penunjang', + }, + { + type: 'claim-diagnosis', + name: 'Dokumen Diagnosa', + }, + { + type: 'claim-diagnosis', + name: 'Dokumen Diagnosa', + }, + ]; + return ( - - { fileCategory(item.type) } - - { item.name } + + {fileCategory(item.type)} + + + + {item.name} + + @@ -51,18 +75,51 @@ export default function Documents({ files }) { - { files.length > 0 ? ( - - { files.map((file, index) => ( - - )) } + + + Dokumen Diagnosa + + {}}> + + {/* */} + + + + kasjdnkajsdnkasdnaksjdnaksdjnkasdnkajsdn + )} + /> - ) : ( + + Dokumen Diagnosa + + + Dokumen Diagnosa + + + + + {files.length > 0 ? ( + + {files.map((file, index) => ( + + ))} + + ) : ( - Belum ada History Perawatan + Belum ada dokumen )} + + ); } diff --git a/frontend/dashboard/src/pages/Report/LinksehatPayments/Create.tsx b/frontend/dashboard/src/pages/Report/LinksehatPayments/Create.tsx new file mode 100644 index 00000000..efb7a395 --- /dev/null +++ b/frontend/dashboard/src/pages/Report/LinksehatPayments/Create.tsx @@ -0,0 +1,93 @@ +import { useEffect, useState } from 'react'; +import { paramCase } from 'change-case'; +import { useParams, useLocation } from 'react-router-dom'; +// @mui +import { Container, Stack } from '@mui/material'; +import useSettings from '../../../hooks/useSettings'; +import Page from '../../../components/Page'; +import Form from './Form'; +import HeaderBreadcrumbs from '../../../components/HeaderBreadcrumbs'; +import axios from '../../../utils/axios'; +import { Practitioner } from '../../../@types/doctor'; +import ButtonBack from '../../../components/ButtonBack'; + +export default function Create() { + const { themeStretch } = useSettings(); + const { id } = useParams(); + + const isEdit = id ? true : false; + + const [currentPractitioner, setCurrentPractitioner] = useState(); + + useEffect(() => { + if (isEdit) { + axios.get('/doctors/' + id).then((res) => { + setCurrentPractitioner(res.data); + }); + } + }, [id]); + + return ( + + + + {/* */} + + + +
+ + + ); +} +// const pageTitle = 'Create Data Dokter'; +// return ( +// +// +// + +// +// +// +// +// +// +// +// +// +// ); +// } diff --git a/frontend/dashboard/src/pages/Report/LinksehatPayments/Form.tsx b/frontend/dashboard/src/pages/Report/LinksehatPayments/Form.tsx new file mode 100644 index 00000000..39885db8 --- /dev/null +++ b/frontend/dashboard/src/pages/Report/LinksehatPayments/Form.tsx @@ -0,0 +1,260 @@ +import * as Yup from 'yup'; +import { useSnackbar } from 'notistack'; +import { useNavigate } from 'react-router-dom'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import MenuItem from '@mui/material/MenuItem'; + +import Select, { SelectChangeEvent } from '@mui/material/Select'; +import * as React from 'react'; + +// form +import { useForm } from 'react-hook-form'; +import { yupResolver } from '@hookform/resolvers/yup'; +// @mui +import { styled } from '@mui/material/styles'; +import { LoadingButton } from '@mui/lab'; +import { + Box, + Avatar, + Button, + ButtonGroup, + Card, + FormHelperText, + Grid, + Stack, + Typography, + TextField, + Chip, +} from '@mui/material'; + +import CancelIcon from '@mui/icons-material/Cancel'; + +// components +import { + FormProvider, + RHFTextField, + RHFRadioGroup, + RHFUploadAvatar, + RHFSwitch, + RHFEditor, + RHFDatepicker, + RHFMultiCheckbox, + RHFCheckbox, + RHFCustomMultiCheckbox, +} from '../../../components/hook-form'; +import axios from '../../../utils/axios'; +import { fCurrency } from '../../../utils/formatNumber'; +import { Practitioner } from '../../../@types/doctor'; + +import { Label, Rowing } from '@mui/icons-material'; + +const LabelStyle = styled(Typography)(({ theme }) => ({ + ...theme.typography.subtitle2, + color: theme.palette.text.secondary, + marginBottom: theme.spacing(1), +})); + +const HeaderStyle = styled('header')(({ theme }) => ({ + paddingBottom: theme.spacing(5), + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', +})); + +const Title = styled(Typography)(({ theme }) => ({ + ...theme.typography.h4, + boxShadow: 'none', + // paddingBottom: theme.spacing(3), + fontWeight: 700, + color: '#005B7F', +})); + +interface FormValuesProps extends Partial { + taxes: boolean; + inStock: boolean; +} + +type Props = { + isEdit: boolean; + currentPractitioner?: Practitioner; +}; + +const Span = styled(Typography)(({ theme }) => ({ + boxShadow: 'none', + paddingBottom: theme.spacing(1), +})); + +const Text = styled(Typography)(({ theme }) => ({ + boxShadow: 'none', + paddingBottom: theme.spacing(3), +})); + +export default function PractitionerForm({ isEdit, currentPractitioner }: Props) { + const navigate = useNavigate(); + const [practitioner_group, setPractitionerGroups] = useState([]); + + // const [ errors, setErrors ] = useState<{ [key: string]: string }>({}); + + const { enqueueSnackbar } = useSnackbar(); + + const NewCorporateSchema = Yup.object().shape({ + name: Yup.string().required('Name is required'), + // file: Yup.boolean().required('Corporate Status is required'), + }); + + const defaultValues = useMemo( + () => ({ + id: currentPractitioner?.id, + name: currentPractitioner?.name || '', + address: currentPractitioner?.address || '', + birth_date: currentPractitioner?.birth_date || '', + gender: currentPractitioner?.gender || '', + description: currentPractitioner?.description || '', + birth_place: currentPractitioner?.birth_place || '', + active: currentPractitioner?.active === 1 ? true : false, + avatar_url: currentPractitioner?.avatar_url || '', + doctor_id: currentPractitioner?.doctor_id || '', + organizations: currentPractitioner?.organizations || [], + specialities: currentPractitioner?.specialities || [], + }), + // eslint-disable-next-line react-hooks/exhaustive-deps + [currentPractitioner] + ); + + console.log('defaultValues', defaultValues); + + function StatusLabel({ value }: { value: boolean }) { + return ( + + ); + } + const methods = useForm({ + resolver: yupResolver(NewCorporateSchema), + defaultValues, + }); + + const { + reset, + watch, + control, + setValue, + getValues, + setError, + handleSubmit, + formState: { isSubmitting }, + } = methods; + + const values = watch(); + + useEffect(() => { + if (isEdit && currentPractitioner) { + reset(defaultValues); + } + if (!isEdit) { + reset(defaultValues); + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isEdit, currentPractitioner]); + + const handleActivate = (event: React.ChangeEvent) => { + setValue('active', event.target.checked); + + console.log('event.target.checked', event.target.checked); + + const formData = new FormData(); + formData.append('active', event.target.checked ? '1' : '0'); + formData.append('_method', 'PUT'); + axios.post('/doctors/' + currentPractitioner?.id ?? '', formData); + + enqueueSnackbar('active Updated Successfully!', { variant: 'success' }); + }; + + return ( + + + + {/* */} + + + + Data Dokter + + + {/* Status Rumah Sakit */} + + + + + Informasi Umum + + + + + Nama Dokter + {currentPractitioner?.name ? currentPractitioner?.name : '-'} + No Telp + {currentPractitioner?.phone ? currentPractitioner?.phone : '-'} + Tempat Lahir + + {currentPractitioner?.birth_place ? currentPractitioner?.birth_place : '-'} + + Alamat + {currentPractitioner?.address ? currentPractitioner?.address : '-'} + + + Jenis Kelamin + {currentPractitioner?.gender ? currentPractitioner?.gender : '-'} + Email + {currentPractitioner?.email ? currentPractitioner?.email : '-'} + Tanggal Lahir + + {currentPractitioner?.birth_date ? currentPractitioner?.birth_date : '-'} + + + + + + Tempat Praktik + {currentPractitioner?.organizations?.map((item, index) => ( + + + + {item.name} + + + + ))} + + + Spesialisasi + {currentPractitioner?.specialities?.map((item, index) => ( + + + + {item.name} + + + + ))} + + + + + ); +} diff --git a/frontend/dashboard/src/pages/Report/LinksehatPayments/Index.tsx b/frontend/dashboard/src/pages/Report/LinksehatPayments/Index.tsx new file mode 100644 index 00000000..396c047b --- /dev/null +++ b/frontend/dashboard/src/pages/Report/LinksehatPayments/Index.tsx @@ -0,0 +1,35 @@ +import { Card, Grid, Container } from '@mui/material'; +import { useParams } from 'react-router-dom'; +import HeaderBreadcrumbs from '../../../components/HeaderBreadcrumbs'; +import Page from '../../../components/Page'; +import useSettings from '../../../hooks/useSettings'; +import List from './List'; + +export default function LinksehatPayments() { + const { themeStretch } = useSettings(); + + const { id } = useParams(); + + const pageTitle = 'Appointments'; + return ( + + + + + + + + ); +} diff --git a/frontend/dashboard/src/pages/Report/LinksehatPayments/List.tsx b/frontend/dashboard/src/pages/Report/LinksehatPayments/List.tsx new file mode 100644 index 00000000..2c5f45fb --- /dev/null +++ b/frontend/dashboard/src/pages/Report/LinksehatPayments/List.tsx @@ -0,0 +1,637 @@ +import { + Box, + Button, + Card, + Collapse, + Paper, + Select, + SelectChangeEvent, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, + Typography, + Stack, + ButtonGroup, + Grid, + Chip, + Dialog, + DialogContent, + DialogContentText, + DialogActions, + FormControl, + Autocomplete, + InputAdornment, + IconButton, + InputLabel, +} from '@mui/material'; + +import { + Link, + NavLink as RouterLink, + useSearchParams, + useNavigate, + useParams, +} from 'react-router-dom'; +// hooks +import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react'; +import useSettings from '../../../hooks/useSettings'; +// components +import AutocompleteHealthcare from '@/components/autocomplete/AutocompleteHealthcare'; +import axios from '../../../utils/axios'; +import { LaravelPaginatedData } from '../../../@types/paginated-data'; +import { Icd } from '../../../@types/diagnosis'; +import BasePagination from '../../../components/BasePagination'; +import { Practitioner } from '../../../@types/doctor'; +import CreateIcon from '@mui/icons-material/Create'; +import { Props } from '../../../components/editor/index'; +import { red } from '@mui/material/colors'; +import { margin, padding } from '@mui/system'; +import { enqueueSnackbar } from 'notistack'; +import { fNumber } from '@/utils/formatNumber'; +import { Controller } from 'react-hook-form'; + +import SvgIconStyle from '../../../components/SvgIconStyle'; +import { GridSearchIcon } from '@mui/x-data-grid'; +import { Search } from '@mui/icons-material'; +import { Icon } from '@iconify/react'; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; +import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; +import { DesktopDatePicker, LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; +import { MenuItem } from '@mui/material'; +import { fPostFormat } from '@/utils/formatTime'; +import AutocompleteLinksehatHealthcare from '@/components/autocomplete/AutocompleteLinksehatHealthcare'; + +// ---------------------------------------------------------------------- + +export default function List() { + // Generate the every row of the table + + const navigate = useNavigate(); + const { organization_id } = useParams(); + const [searchParams, setSearchParams] = useSearchParams(); + const [organizationOptions, setOrganizationOptions] = useState([]); + const [searchParamsPaymentStatus, setSearchParamsPaymentStatus] = useSearchParams(); + const [searchParamsOrganizations, setSearchParamsOrganizations] = useSearchParams(); + const [searchParamsSpecialities, setSearchParamsSpecialities] = useSearchParams(); + const [searchParamsFilter, setSearchParamsFilter] = useSearchParams(); + + useEffect(() => { + + // axios.get(`/search-organizations`).then((response) => { + // setOrganizationOptions(response.data); + // }); + + }, []) + + function Filter(props: any) { + // SEARCH + const searchInput = useRef(null); + const [searchText, setSearchText] = useState(''); + + //handle search + const handleSearchChange = (event: any) => { + const newSearchText = event.target.value ?? ''; + setSearchText(newSearchText); + }; + + const handleSearchSubmit = (event: any) => { + event.preventDefault(); + + props.onSearch(searchText); + }; + + const handleSearchStatus = (event: any) => { + console.log('search status', 'Yeet'); + }; + + useEffect(() => { + // Trigger First Search + setSearchText(searchParams.get('search') ?? ''); + }, []); + + const item = [ + { + id: '', + value: '', + name: 'Semua', + }, + ]; + + const paymentStatusOptions = { + 'settlement' : 'Diterima', + 'expired' : 'Kadaluarsa', + 'capture' : 'Captured', + 'deny' : 'Ditolak', + 'pending' : 'Menunggu Pembayaran', + 'cancel' : 'Dibatalkan', + 'refund' : 'Dikembalikan', + 'expire' : 'Kadaluarsa', + 'cod' : 'COD', + 'FAILED' : 'Gagal', + 'COMPLETED' : 'Complete', + }; + + const dataOrganizations = []; + + return ( + + + + { + if (event.key === 'Enter') { + // handleSearchSubmit(event); + + const filter = Object.fromEntries([...searchParams.entries(), ['search', searchText]]); + setSearchParams(filter) + loadDataTableData(filter) + } + }} + label="Search" + value={searchText} + InputProps={{ + // startAdornment: ( + // + // + // + // ), + placeholder: 'Id Pemesanan, Transaction ID', + }} + /> + + + + + Payment Status + + + + + + { + if (value) { + const filter = Object.fromEntries([...searchParams.entries(), ['healthcare_id', value.nID ?? '']]); + setSearchParams(filter) + loadDataTableData(filter) + setOrganizationOptions([value]) + } else { + const filter = Object.fromEntries([...searchParams.entries(), ['healthcare_id', '']]); + setSearchParams(filter) + loadDataTableData(filter) + setOrganizationOptions([]) + } + }} + currentOptions={organizationOptions} + currentValue={organizationOptions?.find((org) => org?.nID == searchParams.get('healthcare_id'))} + textLabel="Rumah Sakit" + placeholder="Nama" + /> + + + + + { + + try { + + if (value && !!Date.parse(value)) { + + const date = value ? fPostFormat(value) : '' + var entries = [...searchParams.entries(), ['appointment_start', date ?? '']]; + if (!searchParams.get('appointment_end')) { + entries = [...entries, ['appointment_end', date ?? '']]; + } + const filter = Object.fromEntries(entries); + + setSearchParams(filter) + loadDataTableData(filter) + } + } catch (e) {} + }} + renderInput={(params) => ( + + )} + /> + + + + + + { + try { + + if (value && !!Date.parse(value)) { + + const date = fPostFormat(value) + var entries = [...searchParams.entries(), ['appointment_end', date ?? '']]; + if (!searchParams.get('appointment_start')) { + entries = [...entries, ['appointment_start', date ?? '']]; + } + const filter = Object.fromEntries(entries); + + setSearchParams(filter) + loadDataTableData(filter) + } + } catch (e) {} + }} + renderInput={(params) => ( + + )} + /> + + + + + ); + } + + function FilterForm(props: any) { + // IMPORT + return ( + + + + + + ); + } + + //TODO Create PaymentType + function createData(payments: any): any { + return { + ...payments, + }; + } + + function Row(props: { row: ReturnType }) { + const { row } = props; + const [open, setOpen] = React.useState(false); + const [openDialog, setOpenDialog] = React.useState(false); + + const handleDelete = (model: any) => { + axios + .delete(`/doctors/${row.id}`) + .then((res) => { + setDataTableData({ + ...dataTableData, + data: dataTableData.data.filter((model) => model.id != row.id), + }); + enqueueSnackbar('Data berhasil dihapus', { variant: 'success' }); + }) + .catch((error) => { + enqueueSnackbar( + error.response.data.message ?? error.message ?? 'Failed Processing Request', + { variant: 'error' } + ); + }); + }; + + return ( + + + + setOpen(!open)}> + {open ? : } + + + {row.health_care?.sHealthCare ?? '-'} + {row.detail?.sPaymentDetails?.settlement_time ?? '-'} + {row.detail?.dTanggalAppointment ?? ''} + {row.nID} + {row.sBookingCode ?? ''} + {row.doctor?.user?.full_name ?? '-'} + {row.user?.full_name ?? '-'} + {row.user?.sEmail ?? '-'} + {row.type ?? '-'} + {row.payment_method ?? '-'} + {'-'} + + {fNumber(parseInt(row.detail?.sPaymentDetails?.gross_amount ?? 0))} + + {'-'} + {'-'} + {fNumber(parseInt(row.nAdminFee ?? 0))} + {row.payment_status} + {/* + + + + + + */} + + + + + + + Midtrans + + + + + + Transaction ID + + + : {row.detail?.sPaymentDetails?.transaction_id} + + + Order ID + + + : {row.detail?.sPaymentDetails?.order_id} + + + Payment Type + + + : {row.detail?.sPaymentDetails?.payment_type} + + + Transaction Time + + + : {row.detail?.sPaymentDetails?.transaction_time} + + + + + + + + + + { + setOpenDialog(false); + }} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + + + + Apakah anda yakin ingin menghapus + + + {row.name}? + + + + + + + + + ); + } + + const headStyle = { + fontWeight: 'bold', + }; + // Dummy Default Data + const [dataTableIsLoading, setDataTableLoading] = useState(true); + const [dataTableLastRequest, setDataTableLastRequest] = useState(0); + const [dataTableResponseState, setDataTableResponseState] = useState('idle'); + const [dataTableData, setDataTableData] = useState({ + current_page: 1, + data: [], + path: '', + first_page_url: '', + last_page: 1, + last_page_url: '', + next_page_url: '', + prev_page_url: '', + per_page: 10, + from: 0, + to: 0, + total: 0, + }); + const [dataTablePage, setDataTablePage] = useState(5); + + const loadDataTableData = async (appliedFilter: any | null = null) => { + setDataTableLoading(true); + const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); + const response = await axios.get( + '/linksehat/payments', + { + params: filter, + } + ); + setDataTableLoading(false); + setDataTableData(response.data.data); + }; + + // const applyFilter = async (searchFilter: string) => { + // await loadDataTableData({ search: searchFilter }); + // setSearchParams({ search: searchFilter }); + // }; + + const applyItems = async ( + searchFilter: string, + searchFilterOrganization: string, + searchFilterPaymentStatus: string, + searchFilterAppointmentStart: string, + searchFilterAppointmentEnd: string, + ) => { + await loadDataTableData({ + search: searchFilter, + organization_id: searchFilterOrganization, + payment_status: searchFilterPaymentStatus, + appointment_start: searchFilterAppointmentStart, + appointment_end: searchFilterAppointmentEnd, + }); + setSearchParamsFilter({ + search: searchFilter, + organization_id: searchFilterOrganization, + payment_status: searchFilterPaymentStatus, + appointment_start: searchFilterAppointmentStart, + appointment_end: searchFilterAppointmentEnd, + }); + }; + + const handlePageChange = (event: ChangeEvent, value: number) => { + const filter = Object.fromEntries([...searchParams.entries(), ['page', value]]); + loadDataTableData(filter); + setSearchParams(filter); + }; + + useEffect(() => { + loadDataTableData(); + }, []); + + return ( + + {/* */} + + + + + {/* The Main Table */} + + + + + + + Faskes + + + Tanggal Bayar + + + Tanggal Konsultasi + + + ID Pemesanan + + + Kode Pemesanan + + + Dokter + + + Pasien + + + Email + + + Tipe + + + Metode Pembayaran + + + Jenis Benefit + + + Total Transfer (Rp) + + + Konsultasi (Rp) + + + Komisi (Rp) + + + Biaya Administrasi (Rp) + + + Status + + + + {/* + Aksi + */} + + + {dataTableIsLoading ? ( + + + + Loading + + + + ) : dataTableData.data.length == 0 ? ( + + + + No Data + + + + ) : ( + + {dataTableData.data.map((row) => ( + + ))} + + )} +
+
+ + +
+
+ ); +} diff --git a/frontend/dashboard/src/pages/Report/LinksehatPayments/Show.tsx b/frontend/dashboard/src/pages/Report/LinksehatPayments/Show.tsx new file mode 100644 index 00000000..be9d1c46 --- /dev/null +++ b/frontend/dashboard/src/pages/Report/LinksehatPayments/Show.tsx @@ -0,0 +1,53 @@ +import { useEffect, useState } from 'react'; +import { paramCase } from 'change-case'; +import { useParams, useLocation } from 'react-router-dom'; +// @mui +import { Container, Stack } from '@mui/material'; +import useSettings from '../../../hooks/useSettings'; +import Page from '../../../components/Page'; +import View from './View'; +import HeaderBreadcrumbs from '../../../components/HeaderBreadcrumbs'; +import axios from '../../../utils/axios'; +import { Appointment } from '../../../@types/doctor'; + +export default function Create() { + const { themeStretch } = useSettings(); + const { id } = useParams(); + + const isEdit = id ? true : false; + + const [currentAppointment, setCurrentAppointment] = useState(); + + useEffect(() => { + if (isEdit) { + axios.get('/appointments/' + id).then((res) => { + setCurrentAppointment(res.data); + }); + } + }, [id]); + + return ( + + + + + + + + + + ); +} diff --git a/frontend/dashboard/src/pages/Report/LinksehatPayments/View.tsx b/frontend/dashboard/src/pages/Report/LinksehatPayments/View.tsx new file mode 100644 index 00000000..8105b8b1 --- /dev/null +++ b/frontend/dashboard/src/pages/Report/LinksehatPayments/View.tsx @@ -0,0 +1,275 @@ +import * as Yup from 'yup'; +import { useSnackbar } from 'notistack'; +import { useNavigate } from 'react-router-dom'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import MenuItem from '@mui/material/MenuItem'; + +import Select, { SelectChangeEvent } from '@mui/material/Select'; +import * as React from 'react'; + +// form +import { useForm } from 'react-hook-form'; +import { yupResolver } from '@hookform/resolvers/yup'; +// @mui +import { styled } from '@mui/material/styles'; +import { LoadingButton } from '@mui/lab'; +import { + Box, + Avatar, + Button, + ButtonGroup, + Card, + FormHelperText, + Grid, + Stack, + Typography, + TextField, + Chip, + Badge, + Divider, +} from '@mui/material'; + +import CancelIcon from '@mui/icons-material/Cancel'; + +// components +import { + FormProvider, + RHFTextField, + RHFRadioGroup, + RHFUploadAvatar, + RHFSwitch, + RHFEditor, + RHFDatepicker, + RHFMultiCheckbox, + RHFCheckbox, + RHFCustomMultiCheckbox, +} from '../../../components/hook-form'; +import axios from '../../../utils/axios'; +import { fCurrency } from '../../../utils/formatNumber'; +import { Appointment } from '../../../@types/doctor'; + +import { Label, Rowing, Spa } from '@mui/icons-material'; +import { border } from '@mui/system'; + +const LabelStyle = styled(Typography)(({ theme }) => ({ + ...theme.typography.subtitle2, + color: theme.palette.text.secondary, + marginBottom: theme.spacing(1), +})); + +const HeaderStyle = styled('header')(({ theme }) => ({ + paddingBottom: theme.spacing(5), + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', +})); + +const Title = styled(Typography)(({ theme }) => ({ + ...theme.typography.h4, + boxShadow: 'none', + // paddingBottom: theme.spacing(3), + fontWeight: 700, + color: '#005B7F', +})); + +interface FormValuesProps extends Partial { + taxes: boolean; + inStock: boolean; +} + +type Props = { + isEdit: boolean; + currentAppointment?: Appointment; +}; + +const Span = styled(Typography)(({ theme }) => ({ + boxShadow: 'none', + paddingBottom: theme.spacing(1), +})); + +const Text = styled(Typography)(({ theme }) => ({ + boxShadow: 'none', + paddingBottom: theme.spacing(3), +})); + +export default function AppointmentForm({ isEdit, currentAppointment }: Props) { + const navigate = useNavigate(); + + // const [ errors, setErrors ] = useState<{ [key: string]: string }>({}); + + const { enqueueSnackbar } = useSnackbar(); + + const NewCorporateSchema = Yup.object().shape({ + name: Yup.string().required('Name is required'), + // file: Yup.boolean().required('Corporate Status is required'), + }); + + const defaultValues = useMemo( + () => ({ + id: currentAppointment?.id, + name: currentAppointment?.name || '', + address: currentAppointment?.address || '', + birth_date: currentAppointment?.birth_date || '', + gender: currentAppointment?.gender || '', + description: currentAppointment?.description || '', + birth_place: currentAppointment?.birth_place || '', + active: currentAppointment?.active === 1 ? true : false, + avatar_url: currentAppointment?.avatar_url || '', + doctor_id: currentAppointment?.doctor_id || '', + organizations: currentAppointment?.organizations || [], + specialities: currentAppointment?.specialities || [], + }), + // eslint-disable-next-line react-hooks/exhaustive-deps + [currentAppointment] + ); + + const methods = useForm({ + resolver: yupResolver(NewCorporateSchema), + defaultValues, + }); + + const { + reset, + watch, + control, + setValue, + getValues, + setError, + handleSubmit, + formState: { isSubmitting }, + } = methods; + + const values = watch(); + + useEffect(() => { + if (isEdit && currentAppointment) { + reset(defaultValues); + } + if (!isEdit) { + reset(defaultValues); + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isEdit, currentAppointment]); + + return ( + + + + {/* */} + + + + } + spacing={2} + > + Data Appointment + + + + + + + + + + + Tanggal Booking : + + {currentAppointment?.date_created ? currentAppointment?.date_created : '-'} + + + + + + Tanggal Appointment : + + {currentAppointment?.date_appointment + ? currentAppointment?.date_appointment + : '-'} + + + + + + + Nama Dokter + + {currentAppointment?.doctor_name ? currentAppointment?.doctor_name : '-'} + + Faskes + + {currentAppointment?.health_care ? currentAppointment?.health_care : '-'} + + + + Spesialis + {currentAppointment?.speciality ? currentAppointment?.speciality : '-'} + Appointment Via Web/App + + {currentAppointment?.appointment_media + ? currentAppointment?.appointment_media + : '-'} + + + + + + + + Data Pembayaran + + + + {currentAppointment?.payment_detail !== null ? ( + + + Metode Pembayaran + + {currentAppointment?.payment_method ? currentAppointment?.payment_method : '-'} + + Harga + + {currentAppointment?.payment_detail?.gross_amount + ? currentAppointment?.payment_detail?.gross_amount + : '-'} + + Mata Uang + + {currentAppointment?.payment_detail?.currency + ? currentAppointment?.payment_detail?.currency + : '-'} + + + + Tipe Pembayaran + + {currentAppointment?.payment_detail?.payment_type + ? currentAppointment?.payment_detail?.payment_type + : '-'} + + Waktu Transaksi + + {currentAppointment?.payment_detail?.transaction_time + ? currentAppointment?.payment_detail?.transaction_time + : '-'} + + Status + + {currentAppointment?.payment_detail?.status_message + ? currentAppointment?.payment_detail?.status_message + : '-'} + + + + ) : ( + Belum ada pembayaran + )} + + + + + ); +} diff --git a/frontend/dashboard/src/pages/Report/Livechat/Index.tsx b/frontend/dashboard/src/pages/Report/Livechat/Index.tsx index 8d02c936..f246bfd9 100644 --- a/frontend/dashboard/src/pages/Report/Livechat/Index.tsx +++ b/frontend/dashboard/src/pages/Report/Livechat/Index.tsx @@ -5,12 +5,12 @@ import Page from '../../../components/Page'; import useSettings from '../../../hooks/useSettings'; import List from './List'; -export default function Doctors() { +export default function Doctor() { const { themeStretch } = useSettings(); const { id } = useParams(); - const pageTitle = 'Live Chat'; + const pageTitle = 'Payment'; return ( @@ -22,8 +22,8 @@ export default function Doctors() { href: '/report', }, { - name: 'Live Chat', - href: '/report/live-chat', + name: 'Payment', + href: '/report/payment', }, ]} /> diff --git a/frontend/dashboard/src/routes/index.tsx b/frontend/dashboard/src/routes/index.tsx index c5df9faf..0c7b6acf 100755 --- a/frontend/dashboard/src/routes/index.tsx +++ b/frontend/dashboard/src/routes/index.tsx @@ -265,6 +265,10 @@ export default function Router() { path: 'report/live-chat/:id/edit', element: , }, + { + path: 'report/linksehat-payments', + element: , + }, { path: 'claims', @@ -385,6 +389,8 @@ const Livechat = Loadable(lazy(() => import('../pages/Report/Livechat/Index'))); const LivechatCreate = Loadable(lazy(() => import('../pages/Report/Livechat/Create'))); const LivechatShow = Loadable(lazy(() => import('../pages/Report/Livechat/Show'))); +const LinksehatPayment = Loadable(lazy(() => import('../pages/Report/LinksehatPayments/Index'))); + const MasterDrug = Loadable(lazy(() => import('../pages/Master/Drug/Index'))); const MasterFormularium = Loadable(lazy(() => import('../pages/Master/Formularium/Index'))); From 53075d0ce84d2306a04337fec6eb7466519f79d4 Mon Sep 17 00:00:00 2001 From: R Date: Thu, 6 Apr 2023 05:06:35 +0700 Subject: [PATCH 3/6] Add Accounting dummy password --- database/seeders/DummyMemberSeeder.php | 3 ++- database/seeders/RoleSeeder.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/database/seeders/DummyMemberSeeder.php b/database/seeders/DummyMemberSeeder.php index 9c3391c7..13206593 100755 --- a/database/seeders/DummyMemberSeeder.php +++ b/database/seeders/DummyMemberSeeder.php @@ -20,7 +20,8 @@ class DummyMemberSeeder extends Seeder 'admin@linksehat.dev' => ['administrator'], 'manager+one@gmail.com' => ['corporate-manager'], 'manager+two@gmail.com' => ['corporate-manager'], - 'hospitaladmin@gmail.com' => ['hospital-admin'] + 'hospitaladmin@gmail.com' => ['hospital-admin'], + 'accounting@linksehat.com' => ['accounting'], ]; foreach ($userEmails as $email => $roles) { diff --git a/database/seeders/RoleSeeder.php b/database/seeders/RoleSeeder.php index 5d1477d2..ed352de8 100644 --- a/database/seeders/RoleSeeder.php +++ b/database/seeders/RoleSeeder.php @@ -18,7 +18,8 @@ class RoleSeeder extends Seeder $roles = [ 'administrator', 'corporate-manager', - 'hospital-admin' + 'hospital-admin', + 'accounting' ]; foreach ($roles as $name) { From 97486da90f68079f13c90fd215c7a9b0d8b28e66 Mon Sep 17 00:00:00 2001 From: R Date: Thu, 6 Apr 2023 06:25:52 +0700 Subject: [PATCH 4/6] Fix Komisi --- .../dashboard/src/pages/Report/LinksehatPayments/List.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/dashboard/src/pages/Report/LinksehatPayments/List.tsx b/frontend/dashboard/src/pages/Report/LinksehatPayments/List.tsx index 2c5f45fb..3d4bcb87 100644 --- a/frontend/dashboard/src/pages/Report/LinksehatPayments/List.tsx +++ b/frontend/dashboard/src/pages/Report/LinksehatPayments/List.tsx @@ -354,8 +354,8 @@ export default function List() { {fNumber(parseInt(row.detail?.sPaymentDetails?.gross_amount ?? 0))} - {'-'} - {'-'} + {fNumber(parseInt(row.share_konsultasi))} + {fNumber(parseInt(row.share_komisi))} {fNumber(parseInt(row.nAdminFee ?? 0))} {row.payment_status} {/* From 3ff0cc1b29624230c518075c388f486b3e2fdf07 Mon Sep 17 00:00:00 2001 From: R Date: Thu, 6 Apr 2023 06:49:04 +0700 Subject: [PATCH 5/6] Fix Komisi --- .../Api/Linksehat/PaymentController.php | 2 +- .../Transformers/LinksehatPaymentResource.php | 7 ++++- app/Models/OLDLMS/Appointment.php | 26 ++++++++++++++++++ app/Models/OLDLMS/Healthcare.php | 5 ++++ app/Models/OLDLMS/HealthcareCommission.php | 27 +++++++++++++++++++ 5 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 app/Models/OLDLMS/HealthcareCommission.php diff --git a/Modules/Internal/Http/Controllers/Api/Linksehat/PaymentController.php b/Modules/Internal/Http/Controllers/Api/Linksehat/PaymentController.php index 8d6e035f..9fdc6b35 100644 --- a/Modules/Internal/Http/Controllers/Api/Linksehat/PaymentController.php +++ b/Modules/Internal/Http/Controllers/Api/Linksehat/PaymentController.php @@ -21,7 +21,7 @@ class PaymentController extends Controller // return $request->toArray(); $appointments = Appointment::query() ->where('sPaymentStatus', 'settlement') - ->with(['healthCare', 'detail', 'user', 'doctor', 'doctor.user']); + ->with(['healthCare', 'healthCare.commission', 'detail', 'user', 'doctor', 'doctor.user']); if ($request->has('search')) { $appointments->where(function ($query) use ($request) { diff --git a/Modules/Internal/Transformers/LinksehatPaymentResource.php b/Modules/Internal/Transformers/LinksehatPaymentResource.php index fe5fcc2f..472f037c 100644 --- a/Modules/Internal/Transformers/LinksehatPaymentResource.php +++ b/Modules/Internal/Transformers/LinksehatPaymentResource.php @@ -14,7 +14,12 @@ class LinksehatPaymentResource extends JsonResource */ public function toArray($request) { - return parent::toArray($request); + $data = parent::toArray($request); + + $data['share_komisi'] = $this->share_komisi; + $data['share_konsultasi'] = $this->share_konsultasi; + + return $data; // return [ // // 'healthcare_name' => $this->healthCare->name ?? '', diff --git a/app/Models/OLDLMS/Appointment.php b/app/Models/OLDLMS/Appointment.php index b403902e..70011769 100644 --- a/app/Models/OLDLMS/Appointment.php +++ b/app/Models/OLDLMS/Appointment.php @@ -115,6 +115,32 @@ class Appointment extends Model ); } + protected function shareKonsultasi(): Attribute + { + return Attribute::make( + get: function() { + return ((float) $this->detail->sPaymentDetails['gross_amount'] ?? 0) - $this->nAdminFee; + } + ); + } + + protected function shareKomisi(): Attribute + { + return Attribute::make( + get: function() { + // return $this->healthCare->commission; + if ( $this->nIDJenisBooking == 3 ) { // Telekonsultasi Sekarang + return $this->shareKonsultasi * ($this->healthCare->commission->nCommissionATC) / 100; + } + else if ( $this->nIDJenisBooking == 2 ) { // Telekonsultasi + return $this->shareKonsultasi * ($this->healthCare->commission->nCommissionTC) / 100; + } + else { // Walk In + return $this->shareKonsultasi * ($this->nCommission) / 100; + } + } + ); + } public function appointmentDetail() { diff --git a/app/Models/OLDLMS/Healthcare.php b/app/Models/OLDLMS/Healthcare.php index 9987b57d..6a25aa35 100644 --- a/app/Models/OLDLMS/Healthcare.php +++ b/app/Models/OLDLMS/Healthcare.php @@ -20,6 +20,11 @@ class Healthcare extends Model protected $primaryKey = 'nID'; + public function commission() + { + return $this->hasOne(HealthcareCommission::class, 'nIDHealthcare', 'nID')->where('sStatus', 1); + } + public function jadwalDokter() { return $this->hasMany(JadwalDokter::class, 'nIDHealthCare', 'nID'); diff --git a/app/Models/OLDLMS/HealthcareCommission.php b/app/Models/OLDLMS/HealthcareCommission.php new file mode 100644 index 00000000..371966e3 --- /dev/null +++ b/app/Models/OLDLMS/HealthcareCommission.php @@ -0,0 +1,27 @@ +belongsTo(Healthcare::class, 'nIDHealthcare', 'nID'); + } +} From 7d198583a427190e2b32436d50dbe44b992cf753 Mon Sep 17 00:00:00 2001 From: R Date: Thu, 6 Apr 2023 07:32:47 +0700 Subject: [PATCH 6/6] Fix Commision --- app/Models/OLDLMS/Appointment.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/app/Models/OLDLMS/Appointment.php b/app/Models/OLDLMS/Appointment.php index 70011769..32801ab7 100644 --- a/app/Models/OLDLMS/Appointment.php +++ b/app/Models/OLDLMS/Appointment.php @@ -119,7 +119,16 @@ class Appointment extends Model { return Attribute::make( get: function() { - return ((float) $this->detail->sPaymentDetails['gross_amount'] ?? 0) - $this->nAdminFee; + $consulPrice = ((float) $this->detail->sPaymentDetails['gross_amount'] ?? 0) - $this->nAdminFee; + if ( $this->nIDJenisBooking == 3 ) { // Telekonsultasi Sekarang + return $consulPrice * (100-$this->healthCare->commission->nCommissionATC) / 100; + } + else if ( $this->nIDJenisBooking == 2 ) { // Telekonsultasi + return $consulPrice * (100-$this->healthCare->commission->nCommissionTC) / 100; + } + else { // Walk In + return $consulPrice * (100-$this->healthCare->commission->nCommission) / 100; + } } ); } @@ -128,15 +137,15 @@ class Appointment extends Model { return Attribute::make( get: function() { - // return $this->healthCare->commission; + $consulPrice = ((float) $this->detail->sPaymentDetails['gross_amount'] ?? 0) - $this->nAdminFee; if ( $this->nIDJenisBooking == 3 ) { // Telekonsultasi Sekarang - return $this->shareKonsultasi * ($this->healthCare->commission->nCommissionATC) / 100; + return $consulPrice * ($this->healthCare->commission->nCommissionATC) / 100; } else if ( $this->nIDJenisBooking == 2 ) { // Telekonsultasi - return $this->shareKonsultasi * ($this->healthCare->commission->nCommissionTC) / 100; + return $consulPrice * ($this->healthCare->commission->nCommissionTC) / 100; } else { // Walk In - return $this->shareKonsultasi * ($this->nCommission) / 100; + return $consulPrice * ($this->healthCare->commission->nCommission) / 100; } } );