Merge branch 'feature/add-input-benefit-hsp'

This commit is contained in:
ivan-sim
2026-04-07 20:57:18 +07:00
7 changed files with 188 additions and 57 deletions

View File

@@ -10,6 +10,9 @@ use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Modules\HospitalPortal\Helpers\ApiResponse; use Modules\HospitalPortal\Helpers\ApiResponse;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use App\Models\CorporateBenefit;
use App\Models\MemberPlan;
use App\Models\Plan;
class MemberController extends Controller class MemberController extends Controller
{ {
@@ -134,16 +137,20 @@ class MemberController extends Controller
$res_data['companies'] = $companies; $res_data['companies'] = $companies;
$corporateEmployeePremi = DB::table('corporate_employees') $corporateEmployee = DB::table('corporate_employees')
->leftJoin('corporates', 'corporates.id', '=', 'corporate_employees.corporate_id') ->leftJoin('corporates', 'corporates.id', '=', 'corporate_employees.corporate_id')
->leftJoin('corporate_policies', 'corporate_policies.corporate_id', '=', 'corporates.id') ->leftJoin('corporate_policies', 'corporate_policies.corporate_id', '=', 'corporates.id')
->where('corporate_employees.status', 'ACTIVE') // ->where('corporate_employees.status', 'ACTIVE')
->where('corporates.active', 1) ->where('corporates.active', 1)
->where('corporate_policies.active', 1) ->where('corporate_policies.active', 1)
->where('corporate_employees.member_id', $members->id) ->where('corporate_employees.member_id', $members->id)
->value('corporate_policies.total_premi'); ->select(
'corporate_policies.total_premi',
'corporate_employees.corporate_id'
)
->first();
$res_data['total_premi'] = $corporateEmployeePremi ?? 0; $res_data['total_premi'] = $corporateEmployee ?? 0;
$limitRules = DB::table('member_plans') $limitRules = DB::table('member_plans')
->leftJoin('plans', 'plans.id', '=', 'member_plans.plan_id') ->leftJoin('plans', 'plans.id', '=', 'member_plans.plan_id')
@@ -154,6 +161,50 @@ class MemberController extends Controller
$res_data['limit_rules'] = $limitRules ?? 0; $res_data['limit_rules'] = $limitRules ?? 0;
$planMember = MemberPlan::where('member_id', $members->id)->get('plan_id');
$planId = Plan::whereIn('id', $planMember)->where('service_code', 'OP')->first();
$benefit = CorporateBenefit::with(['benefit', 'plan'])->where('plan_id', $planId->id)->get()->toArray();
$benefitData = [];
if (count($benefit)){
foreach($benefit as $data){
$data['benefit']['plan_id'] = $data['plan_id'];
$data['benefit']['limit_amount'] = $data['limit_amount'];
$data['benefit']['family_plan'] = $planId->family_plan;
$data['benefit']['max_frequency_period'] = $data['max_frequency_period'];
$data['benefit']['limit_amount_plan'] = $data['plan']['limit_rules'];
$data['benefit']['family_plan_plans'] = $data['plan']['family_plan'];
array_push($benefitData, $data['benefit']);
}
}
$memberUsage = Helper::getUsageMember($corporateEmployee->corporate_id, $members->id, $benefitData);;
$res_data['used_limit'] = json_decode($memberUsage);
$usedLimit = json_decode($memberUsage, true); // jadi array
$totalUsed = 0;
if (is_array($usedLimit)) {
foreach ($usedLimit as $value) {
$totalUsed += (int) $value;
}
}
$limitRules = (int) $limitRules;
// hitung sisa
$remainingLimit = $limitRules - $totalUsed;
// biar gak minus
if ($remainingLimit < 0) {
$remainingLimit = 0;
}
// set ke response
$res_data['remaining_limit'] = $remainingLimit;
$res_data['total_used_limit'] = $totalUsed;
// specialities // specialities
$specialities = DB::table('specialities') $specialities = DB::table('specialities')
->select( ->select(

View File

@@ -5,4 +5,6 @@ PORT=8000
REACT_APP_HOST_API_URL="http://lms.test" REACT_APP_HOST_API_URL="http://lms.test"
# VITE_API_URL="https://aso-api.linksehat.dev/api/internal" # VITE_API_URL="https://aso-api.linksehat.dev/api/internal"
VITE_API_URL="https://primecenter-api.linksehat.com/api/internal" # VITE_API_URL="https://primecenter-api.linksehat.com/api/internal"
VITE_API_URL="http://localhost:8000/api/internal"

View File

@@ -86,6 +86,77 @@ import { format } from 'date-fns';
export default function Detail() { export default function Detail() {
//dari hospital portal
const [dischargeDate, setDischargeDate] = useState<string>(format(new Date(), "yyyy MMM d HH:mm:ss"));
const [serviceOptions, setServiceOptions] = useState([
{ value: '-', label: '-' }
]);
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("");
const [inputDppj, setInputDppj] = useState("");
function submitRequestFinalLog() {
if(dischargeDate == '')
{
enqueueSnackbar('Tanggal Keluar', { variant: 'warning' });
return false;
}
//cek spesialis
if(!idSpecialities)
{
enqueueSnackbar('Spesialis', { variant: 'warning' });
return false;
}
//cek dpjp
if(!inputDppj)
{
enqueueSnackbar('DPPJ', { variant: 'warning' });
return false;
}
setSubmitLoading(true);
const formData = makeFormData({
// request_logs_id: member.id,
// result_files: fileHasilPenunjangs,
// diagnosa_files: fileDiagnosas,
// kondisi_files: fileKondisis,
discharge_date: fPostFormat(dischargeDate, 'yyyy-MM-dd HH:mm:ss'),
service_code: serviceCode,
spescialis_id: idSpecialities,
dppj: inputDppj,
});
axios
.post('/request-final-log', formData)
.then((response) => {
enqueueSnackbar(response.data.meta.message ?? 'Berhasil membuat data', { variant: 'success' });
// handleSubmitSuccess();
// onClose({ someData: 'example data' }, getData);
})
.catch(({ response }) => {
enqueueSnackbar(response.data.meta.message ?? 'Something Went Wrong', { variant: 'error' });
})
.then(() => {
setSubmitLoading(false);
});
}
//end dari hospital portal
const location = useLocation(); const location = useLocation();
@@ -553,17 +624,17 @@ function submitRequestFinalLog() {
<Stack spacing={2} sx={{ flex: 1 }}> <Stack spacing={2} sx={{ flex: 1 }}>
<Typography variant="subtitle1">Tipe Service </Typography> <Typography variant="subtitle1">Tipe Service </Typography>
<Autocomplete <Autocomplete
id="service_type"
options={serviceOptions} options={serviceOptions}
value={selectedService} getOptionLabel={(option) => option.label || ""}
getOptionLabel={(o) => o.label} value={serviceOptions.find((opt) => opt.value == serviceCode) || null}
isOptionEqualToValue={(o, v) => o.value === v.value} onChange={(event, newValue) => {
onChange={(_, v) => setServiceCode(v?.value ?? '')} setServiceCode(newValue?.value || "");
}}
renderInput={(params) => ( renderInput={(params) => (
<TextField {...params} label="Tipe Service" fullWidth /> <TextField {...params} label='Tipe Service' fullWidth />
)} )}
/> />
<FormHelperText style={{ color: "red" }}></FormHelperText> <FormHelperText style={{ color: "red" }}></FormHelperText>
</Stack> </Stack>
</Stack> </Stack>

View File

@@ -415,7 +415,7 @@ export default function DialogBenefit({requestLog, setOpenDialog, openDialog, cl
</Grid> </Grid>
</Grid> </Grid>
<Grid item xs={width}> <Grid item xs={width} style={{display: "none"}}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="subtitle1" component="div"> <Typography variant="subtitle1" component="div">
@@ -440,7 +440,7 @@ export default function DialogBenefit({requestLog, setOpenDialog, openDialog, cl
</Grid> </Grid>
</Grid> </Grid>
<Grid item xs={width}> <Grid item xs={width} style={{display: "none"}}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="subtitle1" component="div"> <Typography variant="subtitle1" component="div">
@@ -464,7 +464,7 @@ export default function DialogBenefit({requestLog, setOpenDialog, openDialog, cl
</Grid> </Grid>
</Grid> </Grid>
<Grid item xs={width}> <Grid item xs={width} style={{display: "none"}}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="subtitle1" component="div"> <Typography variant="subtitle1" component="div">
@@ -484,7 +484,7 @@ export default function DialogBenefit({requestLog, setOpenDialog, openDialog, cl
</Grid> </Grid>
</Grid> </Grid>
<Grid item xs={2}> <Grid item xs={2} style={{display: "none"}}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="subtitle1" component="div"> <Typography variant="subtitle1" component="div">

View File

@@ -79,7 +79,6 @@ export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,
const amountApproved = parseFloat(watch('amount_approved')); const amountApproved = parseFloat(watch('amount_approved'));
const amountNotApproved = parseFloat(watch('amount_not_approved')); const amountNotApproved = parseFloat(watch('amount_not_approved'));
const excessPaid = parseFloat(watch('excess_paid')); const excessPaid = parseFloat(watch('excess_paid'));
// Hitung total baru // Hitung total baru
const totalAmountIncurred = total.totalAmountIncurred - data?.amount_incurred + amountIncurred; const totalAmountIncurred = total.totalAmountIncurred - data?.amount_incurred + amountIncurred;
const totalAmountApproved = total.totalAmountApproved - data?.amount_approved + amountApproved; const totalAmountApproved = total.totalAmountApproved - data?.amount_approved + amountApproved;
@@ -203,7 +202,6 @@ export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,
<Typography variant="subtitle1" sx={{ fontWeight: 'bold'}}> <Typography variant="subtitle1" sx={{ fontWeight: 'bold'}}>
{data?.benefit?.description} {data?.benefit?.description}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={2}> <Grid item xs={2}>
<Grid container spacing={2}> <Grid container spacing={2}>
@@ -228,7 +226,7 @@ export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,
</Grid> </Grid>
</Grid> </Grid>
<Grid item xs={2}> <Grid item xs={2} style={{display: "none"}}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="subtitle1" component="div"> <Typography variant="subtitle1" component="div">
@@ -252,7 +250,7 @@ export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,
</Grid> </Grid>
</Grid> </Grid>
<Grid item xs={2}> <Grid item xs={2} style={{display: "none"}}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="subtitle1" component="div"> <Typography variant="subtitle1" component="div">
@@ -276,7 +274,7 @@ export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,
</Grid> </Grid>
</Grid> </Grid>
<Grid item xs={2}> <Grid item xs={2} style={{display: "none"}}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="subtitle1" component="div"> <Typography variant="subtitle1" component="div">
@@ -296,7 +294,7 @@ export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,
</Grid> </Grid>
</Grid> </Grid>
<Grid item xs={2}> <Grid item xs={2} style={{display: "none"}}>
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="subtitle1" component="div"> <Typography variant="subtitle1" component="div">

View File

@@ -296,10 +296,10 @@ export default function DetailRequestFinalLog() {
>([]) >([])
useEffect(() => { useEffect(() => {
if (!requestLog?.id_member) return if (!requestLog?.id && !Log_id) return
axios axios
.get('service-member/' + (requestLog?.id_member ?? null)) .get('service-member/' + (requestLog?.id ?? Log_id))
.then((res) => setServiceOptions(res.data)) .then((res) => setServiceOptions(res.data))
.catch(console.error) .catch(console.error)
@@ -307,7 +307,7 @@ export default function DetailRequestFinalLog() {
.get('specialis') .get('specialis')
.then((res) => setSpecialisOptions(res.data)) .then((res) => setSpecialisOptions(res.data))
.catch(console.error) .catch(console.error)
}, [requestLog?.id_member]) }, [requestLog?.id, Log_id])
const [serviceCode, setServiceCode] = useState<string>('') const [serviceCode, setServiceCode] = useState<string>('')
@@ -666,7 +666,8 @@ export default function DetailRequestFinalLog() {
</Grid> </Grid>
{/* Surat persetujuan Tindakan */} {/* Surat persetujuan Tindakan */}
<Grid item xs={12}> <Grid item xs={12} style={{ display: "none" }}
>
<Card sx={{ p: 3 }}> <Card sx={{ p: 3 }}>
<Stack direction="row" justifyContent="space-between" alignItems="flex-start" sx={{ mb: 3 }}> <Stack direction="row" justifyContent="space-between" alignItems="flex-start" sx={{ mb: 3 }}>
<Typography variant="subtitle1" sx={{ color: '#19BBBB', fontWeight: 'bold' }}> <Typography variant="subtitle1" sx={{ color: '#19BBBB', fontWeight: 'bold' }}>

View File

@@ -120,6 +120,14 @@ export default function DialogMember(member:any, handleSubmitSuccess:() => void)
<Typography sx={{width:'50%'}} variant="body2">Limit Peserta</Typography> <Typography sx={{width:'50%'}} variant="body2">Limit Peserta</Typography>
<Typography sx={{width:'50%', fontWeight: 'bold'}} variant="body2">{ member?.limit_rules ? fCurrency(member?.limit_rules) : '-'}</Typography> <Typography sx={{width:'50%', fontWeight: 'bold'}} variant="body2">{ member?.limit_rules ? fCurrency(member?.limit_rules) : '-'}</Typography>
</Stack> </Stack>
<Stack direction="row" justifyContent="space-between">
<Typography sx={{width:'50%'}} variant="body2">Limit Terpakai</Typography>
<Typography sx={{width:'50%', fontWeight: 'bold'}} variant="body2">{ member?.total_used_limit ? fCurrency(member?.total_used_limit) : '-'}</Typography>
</Stack>
<Stack direction="row" justifyContent="space-between">
<Typography sx={{width:'50%'}} variant="body2">Sisa Limit</Typography>
<Typography sx={{width:'50%', fontWeight: 'bold'}} variant="body2">{ member?.remaining_limit ? fCurrency(member?.remaining_limit) : '-'}</Typography>
</Stack>
<Stack direction="row" justifyContent="space-between"> <Stack direction="row" justifyContent="space-between">
<Typography sx={{width:'50%'}} variant="body2">NRIC</Typography> <Typography sx={{width:'50%'}} variant="body2">NRIC</Typography>
<Typography sx={{width:'50%', fontWeight: 'bold'}} variant="body2">{member?.members.nik ?? '-'}</Typography> <Typography sx={{width:'50%', fontWeight: 'bold'}} variant="body2">{member?.members.nik ?? '-'}</Typography>