Update Request LOG

This commit is contained in:
ivan-sim
2026-02-25 14:05:08 +07:00
parent d81d38ada4
commit 6ffc1bcfa5
9 changed files with 433 additions and 75 deletions

View File

@@ -72,7 +72,7 @@ class RequestLogBenefitController extends Controller
'amount_approved' => $value['amount_approved'],
'amount_not_approved' => $value['amount_not_approved'],
'excess_paid' => $value['excess_paid'],
'keterangan' => $value['keterangan'],
'keterangan' => $value['keterangan'] ?? '',
'created_by' => auth()->user()->id,
// 'reason' => $value['reason'] ? $value['reason'] : null ,

View File

@@ -96,6 +96,9 @@ Route::prefix('internal')->group(function () {
Route::get('signa', [AutocompleteController::class, 'signaList']);
Route::post('signa-add', [AutocompleteController::class, 'signaAdd']);
Route::get('service-member/{id}', [AutocompleteController::class, 'serviceCode']);
Route::get('specialis', [AutocompleteController::class, 'specialisList']);
Route::middleware('auth:sanctum')->group(function () {

View File

@@ -145,6 +145,7 @@ class RequestLogShowResource extends JsonResource
'dppj' => $dppj,
'code_claim' => $claimCode,
'member_id' => $requestLog['member']['member_id'],
'id_member' => $requestLog['member']['id'],
'type_of_member' => $requestLog['type_of_member'],
'corporate_id' => $corporateId,
'policy_number' =>$policyNumber->code ? $policyNumber->code : '-',
@@ -177,8 +178,8 @@ class RequestLogShowResource extends JsonResource
'keterangan' => $requestLog['keterangan'],
'hak_kamar_pasien' => $requestLog['hak_kamar_pasien'],
'penempatan_kamar' => $requestLog['penempatan_kamar'],
'nominal' => $requestLog['nominal'],
'status_approval' => $requestLog['status_approval'],
'nominal' => $requestLog['nominal'] ?? 0,
'status_approval' => $requestLog['status_approval'] ?? '',
'catatan' => $requestLog['catatan'],
'reason' => $requestLog['reason'],
'diagnosis' => $icd,

View File

@@ -0,0 +1,63 @@
<?php
namespace Modules\Primaya\Http\Controllers\Api;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Validator;
use Modules\Primaya\Helpers\ApiResponse;
use Illuminate\Support\Facades\DB;
use Modules\Internal\Http\Controllers\Api\RequestLogController as primeCenterRequestLog;
use App\Helpers\Helper;
use App\Models\Benefit;
use App\Models\File;
use Dompdf\Dompdf;
use Dompdf\Options;
use Illuminate\Support\Facades\View;
use App\Models\Member;
use App\Models\RequestLog;
use App\Models\Organization;
use App\Services\ClaimRequestService;
use App\Models\ClaimRequest;
use App\Models\CorporateBenefit;
use App\Models\RequestLogBenefit;
use App\Models\Speciality;
class MasterController extends Controller
{
public function specialities()
{
$data = Speciality::select('id', 'name')->get();
return response()->json([
'status' => 'success',
'data' => $data
]);
}
public function benefits()
{
$corporateId = auth('corporate-api')->user()->corporate_id;
$data = Benefit::whereHas('corporateBenefits', function ($q) use ($corporateId) {
$q->where('corporate_id', $corporateId);
})
->select('id', 'description')
->get();
return response()->json([
'status' => 'success',
'data' => $data
]);
}
public function organizations()
{
$data = Organization::select('id', 'name', 'code')->get();
return response()->json([
'status' => 'success',
'data' => $data
]);
}
}

View File

@@ -0,0 +1,249 @@
<?php
namespace Modules\Primaya\Http\Controllers\Api;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Validator;
use Modules\Primaya\Helpers\ApiResponse;
use Illuminate\Support\Facades\DB;
use Modules\Internal\Http\Controllers\Api\RequestLogController as primeCenterRequestLog;
use App\Helpers\Helper;
use App\Models\File;
use Dompdf\Dompdf;
use Dompdf\Options;
use Illuminate\Support\Facades\View;
use App\Models\Member;
use App\Models\RequestLog;
use App\Models\Organization;
use App\Services\ClaimRequestService;
use App\Models\ClaimRequest;
use App\Models\RequestLogBenefit;
class RequestLogController extends Controller
{
/**
* Display a listing of the resource.
* @return Renderable
*/
private static $code_prefix = 'CLAIM';
public function requestLog(Request $request)
{
$data = [
'member_id' => $request->member_id,
'service_code' => $request->service_code,
'organization_id' => $request->organization_id,
'organization_name' => !empty($request->organization_name) ? $request->organization_name : null,
'address_provider' => !empty($request->address_provider) ? $request->address_provider : null,
'submission_date' => $request->submission_date,
'discharge_date' => $request->discharge_date,
'corporate_id_partner' => !empty($request->corporate_id_partner) ? $request->corporate_id_partner : [],
'specialities_id' => $request->specialities_id,
'dppj' => $request->dppj
];
$validator = Validator::make($request->all(), [
'member_id' => 'required',
'service_code' => 'required',
'submission_date' => 'required',
'discharge_date' => 'required',
'specialities_id' => 'required',
'dppj' => 'required',
], [
'member_id.required' => trans('Validation.required',['attribute' => 'Member ID']),
'service_code.required' => trans('Validation.required',['attribute' => 'Service Code']),
'submission_date.required' => trans('Validation.required',['attribute' => 'Submission Date']),
'discharge_date.required' => trans('Validation.required',['attribute' => 'Discharge Date']),
'specialities_id.required' => trans('Validation.required',['attribute' => 'Specialities']),
'dppj.required' => trans('Validation.required',['attribute' => 'DPJP']),
]);
if(!empty($request->organization_id))
{
$validator = Validator::make($request->all(), [
'organization_id' => 'required',
'member_id' => 'required',
'service_code' => 'required',
'submission_date' => 'required',
'discharge_date' => 'required',
'specialities_id' => 'required',
'dppj' => 'required',
], [
'organization_id.required' => trans('Validation.required',['attribute' => 'Provider ID']),
'member_id.required' => trans('Validation.required',['attribute' => 'Member ID']),
'service_code.required' => trans('Validation.required',['attribute' => 'Service Code']),
'submission_date.required' => trans('Validation.required',['attribute' => 'Submission Date']),
'discharge_date.required' => trans('Validation.required',['attribute' => 'Discharge Date']),
'specialities_id.required' => trans('Validation.required',['attribute' => 'Specialities']),
'dppj.required' => trans('Validation.required',['attribute' => 'DPJP']),
]);
}
if ($validator->fails())
{
return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400);
}
else
{
//insert data to organization
try {
if (!empty($request->organization_name) && !empty($request->address_provider))
{
// Memulai transaksi
DB::beginTransaction();
// Membuat singkatan dari nama rumah sakit
$singkatan = "";
$words = explode(' ', $request->organization_name);
foreach ($words as $word) {
$singkatan .= strtoupper(substr($word, 0, 2));
}
// Membuat kode organisasi
$kodeOrganisasi = "ORG000" . $singkatan;
// Insert data ke tabel organizations
$organization_id = DB::table('organizations')
->insertGetId([
'name' => $request->organization_name,
'code' => $kodeOrganisasi,
'type' => 'hospital',
'corporate_id_partner' => $request->corporate_id_partner ? implode(',', $request->corporate_id_partner) : null,
'created_at' => now(),
'created_by' => auth()->user()->id
]);
// Insert data ke tabel addresses
$address_id = DB::table('addresses')
->insertGetId([
'text'=> $request->address_provider,
'addressable_type' => 'App\Models\Organization',
'addressable_id' => $organization_id,
'type' => 'hospital',
'created_at' => now(),
'created_by' => auth()->user()->id
]);
// Update main_address_id di tabel organizations
DB::table('organizations')
->where('organizations.id', '=', $organization_id)
->update(['main_address_id' => $address_id]);
// Commit transaksi
DB::commit();
$request->merge(['organization_id' => $organization_id]);
}
try {
DB::beginTransaction();
$requestLogControllerInstance = new PrimeCenterRequestLog();
$code = $requestLogControllerInstance->getNextCode($request);
$member = Member::find($request->member_id);
$requestLogData = [
'code' => $code,
'member_id' => $request->member_id,
'submission_date' => $request->submission_date ?? now(),
'discharge_date' => $request->discharge_date ?? now(),
'status' => 'approved',
'status_final_log' => 'approved',
'final_log' => 1,
'payment_type' => 'cashless',
'service_code' => $request->service_code,
'policy_id' => $member->currentPolicy->id ?? null,
'organization_id' => $request->organization_id ?? 0,
'source' => $request->source,
'specialities_id' => $request->specialities_id,
'dppj' => $request->dppj
];
// SIMPAN LOG
$requestLog = RequestLog::create($requestLogData);
/*
===============================
INSERT BENEFIT DI SINI
===============================
*/
if (!empty($request->benefits)) {
$benefitData = [];
foreach ($request->benefits as $benefit) {
$benefitData[] = [
'request_log_id' => $requestLog->id,
'benefit_id' => $benefit['benefit_id'],
'amount_incurred' => $benefit['amount_incurred'] ?? 0,
'amount_approved' => $benefit['amount_approved'] ?? 0,
'amount_not_approved' => $benefit['amount_not_approved'] ?? 0,
'excess_paid' => $benefit['excess_paid'] ?? 0,
'keterangan' => $benefit['keterangan'] ?? '',
];
}
$insertBenefit = $this->insertBenefit($benefitData);
if (!$insertBenefit) {
throw new \Exception('Insert Benefit Gagal');
}
}
DB::commit();
return ApiResponse::apiResponse(
'Success Create Log',
$requestLog,
'Berhasil create LOG dan Benefit',
200
);
} catch (\Exception $e) {
DB::rollBack();
return ApiResponse::apiResponse(
'Server Error Create Log',
$data,
$e->getMessage(),
500
);
}
} catch (\Exception $e) {
// Rollback transaksi jika terjadi kesalahan
DB::rollBack();
// Handle error, bisa di-log atau dikembalikan sebagai response
return ApiResponse::apiResponse('Server Error 3', $data, $e->getMessage(), 500);
}
}
}
public function insertBenefit($benefitData)
{
if (count($benefitData) > 0) {
foreach ($benefitData as $value) {
$data = [
'request_log_id' => $value['request_log_id'],
'benefit_id' => $value['benefit_id'],
'amount_incurred' => $value['amount_incurred'],
'amount_approved' => $value['amount_approved'],
'amount_not_approved' => $value['amount_not_approved'],
'excess_paid' => $value['excess_paid'],
'keterangan' => $value['keterangan'] ?? '',
'created_by' => auth()->user()->id,
];
RequestLogBenefit::create($data);
}
return true;
}
return true;
}
}

View File

@@ -2,7 +2,9 @@
use Illuminate\Http\Request;
use Modules\Primaya\Http\Controllers\Api\AuthController;
use Modules\Primaya\Http\Controllers\Api\MasterController;
use Modules\Primaya\Http\Controllers\Api\MemberController;
use Modules\Primaya\Http\Controllers\Api\RequestLogController;
use Modules\Primaya\Http\Middleware\Authentication;
use Modules\Primaya\Http\Middleware\Authorization;
@@ -32,6 +34,19 @@ Route::prefix('v1')->group(function () {
Route::post('search-member', [MemberController::class, 'search']);
});
// Request LOG
Route::controller(RequestLogController::class)->group(function () {
Route::post('request-log', 'requestLog');
});
Route::prefix('master')->group(function () {
Route::get('specialities', [MasterController::class, 'specialities']);
Route::get('benefits', [MasterController::class, 'benefits']);
Route::get('organizations', [MasterController::class, 'organizations']);
});
});
});

View File

@@ -57,4 +57,8 @@ class Benefit extends Model
// TODO corporate_benefits pivot
]);
}
public function corporateBenefits()
{
return $this->hasMany(CorporateBenefit::class, 'benefit_id');
}
}

View File

@@ -85,7 +85,67 @@ import { format } from 'date-fns';
// ----------------------------------------------------------------------
export default function Detail() {
//dari hospital portal
const location = useLocation();
const queryParams = new URLSearchParams(location.search);
const navigate = useNavigate();
const { themeStretch } = useSettings();
const [requestLog, setRequestLog] = useState<DetailFinalLogType>();
const [isReversal, setIsReversal] = useState(false);
const [submitLoading, setSubmitLoading] = useState(false);
const defaultValues: any = {nominal : 0};
const validationSchema = Yup.object().shape({nominal: Yup.number().typeError('Nominal harus berupa angka').required('Nominal harus diisi')})
const methods = useForm<any>({
resolver: yupResolver(validationSchema),
defaultValues
});
const { handleSubmit, reset, watch, setValue, formState: { isDirty, isSubmitting, errors } } = methods;
const onSubmit = async (data: any) => {
setSubmitLoading(true);
const formData = makeFormData({
request_logs_id: id,
approval_files: fileApprovals,
nominal: data.nominal,
});
axios
.post(`/customer-service/request/${id}/approval_files`, formData)
.then((response) => {
enqueueSnackbar('Berhasil membuat data', { variant: 'success' });
window.location.reload()
})
.catch(({ response }) => {
enqueueSnackbar('Something Went Wrong', { variant: 'error' });
})
.then(() => {
setSubmitLoading(false);
});
}
useEffect(() => {
if (!requestLog?.id_member) return
axios.get('service-member/'+ (requestLog?.id_member ?? null))
.then((response) => {
setServiceOptions(response.data);
}).catch((error) => {
console.error('Error fetching ICD options:', error);
});
axios.get('specialis')
.then((response) => {
setSpecialisOptions(response.data);
}).catch((error) => {
console.error('Error fetching ICD options:', error);
});
}, [requestLog?.id_member]);
//dari hospital portal
const [dischargeDate, setDischargeDate] = useState<string>(format(new Date(), "yyyy MMM d HH:mm:ss"));
const [serviceOptions, setServiceOptions] = useState([
{ value: '-', label: '-' }
@@ -93,25 +153,31 @@ export default function Detail() {
const [specialisOptions, setSpecialisOptions] = useState([
{ value: '-', label: '-' }
]);
useEffect(() => {
axios.get('service-member/'+1)
.then((response) => {
setServiceOptions(response.data);
}).catch((error) => {
console.error('Error fetching ICD options:', error);
});
axios.get('specialis')
.then((response) => {
setSpecialisOptions(response.data);
}).catch((error) => {
console.error('Error fetching ICD options:', error);
});
const [serviceCode, setServiceCode] = useState<string>('')
const [idSpecialities, setIdSpecialities] = useState<number | null>(null)
const [inputDppj, setInputDppj] = useState<string>('')
useEffect(() => {
if (!requestLog) return
setServiceCode(requestLog.service_code ?? '')
setIdSpecialities(requestLog.specialitiesID ?? null)
setInputDppj(requestLog.dppj ?? '')
}, [requestLog])
const selectedService = useMemo(
() =>
serviceOptions.find(
(o) => String(o.value) === String(serviceCode)
) || null,
[serviceOptions, serviceCode]
)
}, []);
const [serviceCode, setServiceCode] = useState<string>("");
const [idSpecialities, setIdSpecialities] = useState("");
const [inputDppj, setInputDppj] = useState("");
const selectedSpecialis = useMemo(
() =>
specialisOptions.find(
(o) => Number(o.value) === Number(idSpecialities)
) || null,
[specialisOptions, idSpecialities]
)
function submitRequestFinalLog() {
if(dischargeDate == '')
{
@@ -156,49 +222,6 @@ function submitRequestFinalLog() {
});
}
//end dari hospital portal
const location = useLocation();
const queryParams = new URLSearchParams(location.search);
const navigate = useNavigate();
const { themeStretch } = useSettings();
const [requestLog, setRequestLog] = useState<DetailFinalLogType>();
const [isReversal, setIsReversal] = useState(false);
const [submitLoading, setSubmitLoading] = useState(false);
const defaultValues: any = {nominal : 0};
const validationSchema = Yup.object().shape({nominal: Yup.number().typeError('Nominal harus berupa angka').required('Nominal harus diisi')})
const methods = useForm<any>({
resolver: yupResolver(validationSchema),
defaultValues
});
const { handleSubmit, reset, watch, setValue, formState: { isDirty, isSubmitting, errors } } = methods;
const onSubmit = async (data: any) => {
setSubmitLoading(true);
const formData = makeFormData({
request_logs_id: id,
approval_files: fileApprovals,
nominal: data.nominal,
});
axios
.post(`/customer-service/request/${id}/approval_files`, formData)
.then((response) => {
enqueueSnackbar('Berhasil membuat data', { variant: 'success' });
window.location.reload()
})
.catch(({ response }) => {
enqueueSnackbar('Something Went Wrong', { variant: 'error' });
})
.then(() => {
setSubmitLoading(false);
});
}
const updateApproval = async () => {
setSubmitLoading(true);
axios
@@ -530,17 +553,17 @@ function submitRequestFinalLog() {
<Stack spacing={2} sx={{ flex: 1 }}>
<Typography variant="subtitle1">Tipe Service </Typography>
<Autocomplete
id="service_type"
options={serviceOptions}
getOptionLabel={(option) => option.label || ""}
value={serviceOptions.find((opt) => opt.value == serviceCode) || null}
onChange={(event, newValue) => {
setServiceCode(newValue?.value || "");
}}
value={selectedService}
getOptionLabel={(o) => o.label}
isOptionEqualToValue={(o, v) => o.value === v.value}
onChange={(_, v) => setServiceCode(v?.value ?? '')}
renderInput={(params) => (
<TextField {...params} label='Tipe Service' fullWidth />
<TextField {...params} label="Tipe Service" fullWidth />
)}
/>
/>
<FormHelperText style={{ color: "red" }}></FormHelperText>
</Stack>
</Stack>

View File

@@ -296,10 +296,10 @@ export default function DetailRequestFinalLog() {
>([])
useEffect(() => {
if (!requestLog?.id && !Log_id) return
if (!requestLog?.id_member) return
axios
.get('service-member/' + (requestLog?.id ?? Log_id))
.get('service-member/' + (requestLog?.id_member ?? null))
.then((res) => setServiceOptions(res.data))
.catch(console.error)
@@ -307,7 +307,7 @@ export default function DetailRequestFinalLog() {
.get('specialis')
.then((res) => setSpecialisOptions(res.data))
.catch(console.error)
}, [requestLog?.id, Log_id])
}, [requestLog?.id_member])
const [serviceCode, setServiceCode] = useState<string>('')