nanosanteservice/app/Http/Controllers/HealthCareSheetController.php

2272 lines
104 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers;
use App\Events\InsuredConsultation;
use App\Exceptions\AppException;
use App\HealthCareSheetType;
use App\InsuranceState;
use App\InsuranceSubscriptionState;
use App\Models\AgentPlus;
use App\Models\NhAct;
use App\Models\NhAuthorizationOfCareRequest;
use App\Models\NhDrugsAndDevice;
use App\Models\NhExam;
use App\Models\NhHavingRight;
use App\Models\NhHealthCareSheet;
use App\Models\NhHealthCareSheetsExam;
use App\Models\NhHealthCareSheetsHistory;
use App\Models\NhHealthCareSheetsPerformance;
use App\Models\NhHealthCareSheetsPrescription;
use App\Models\NhInfosHealthCareSheets;
use App\Models\NhInsurance;
use App\Models\NhMedicalPrescription;
use App\Models\NhNetworksConfig;
use App\Models\NhPerformance;
use App\Models\NhProviderClass;
use App\Models\NhTmpHealthCareSheet;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;
use stdClass;
use Throwable;
class HealthCareSheetController extends Controller
{
/**
* @OA\Get(
* path="/drugs-and-devices",
* summary="Rechercher les medicaments / appareillaages ( par reseau et par nom)",
* tags={"Médicaments / Appareillages"},
* security={{"api_key":{}}},
* @OA\Parameter(
* parameter="network_id",
* name="network_id",
* description="ID du reseau",
* @OA\Schema(
* type="integer",
* default = 250
* ),
* in="query",
* required=true
* ),
* @OA\Parameter(
* parameter="name",
* name="name",
* description="Nom du médicament / appareillage",
* @OA\Schema(
* type="string"
* ),
* in="query",
* required=true
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : {{"id":2,"network_id":250,"code":"ABD","name":"Nivaquine","type":"Comprimé",
* "on_prescription":false,"created_at":"2021-11-16T09:13:30.000000Z","updated_at":"2021-11-16T09:13:30.000000Z"}},
* "error":null
* }
* )
* )
* )
*/
public function getDrugsAndDevices(Request $request)
{
$this->validate($request, [
'network_id' => 'required|integer',
'name' => 'required|string'
]);
$drugs = NhDrugsAndDevice::where('network_id', $request->input('network_id'))
->where('name', 'like', '%' . $request->input('name') . '%')->get();
foreach ($drugs as $drug) {
$drug->type = trans('states.' . $drug->type);
}
return $this->successResponse($drugs);
}
/**
* @OA\Post(
* path="/drugs-and-devices",
* summary="Ajouter les medicaments / appareillages",
* tags={"Médicaments / Appareillages"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="network_id",
* description = "ID du reseau",
* type="integer",
* example= 250
* ),
* @OA\Property(
* property="code",
* description = "Code du médicament / appareillage",
* type="string",
* example= "ABD"
* ),
* @OA\Property(
* property="name",
* description = "Nom du médicament / appareillage",
* type="string",
* example= "Nivaquine"
* ),
* @OA\Property(
* property="type",
* description = "Type de médicament / appareillage",
* type="string",
* enum={"COMPRESSED","SYRUP","SOLUTION","SUPPOSITORY","DEVICE"},
* example= "COMPRESSED"
* ),
* @OA\Property(
* property="on_prescription",
* description = "Sous ordornance ou pas",
* type="bool",
* example= "false"
* )
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : {"network_id":250,"code":"ABD","name":"Nivaquine","type":"COMPRESSED","on_prescription":false,"updated_at":"2021-11-29T11:32:31.000000Z","created_at":"2021-11-29T11:32:31.000000Z","id":4},
* "error":null
* }
* )
* )
* )
*/
public function storeDrugsAndDevices(Request $request)
{
$this->validate($request, [
'network_id' => 'required|integer|exists:networks,id',
'name' => 'required|string',
'code' => 'required|string',
'type' => 'required|string|in:COMPRESSED,SYRUP,SOLUTION,SUPPOSITORY,DEVICE',
'on_prescription' => 'required|boolean'
]);
$drug = NhDrugsAndDevice::where('network_id', $request->input('network_id'))
->where('code', $request->input('code'))->first();
if (isset($drug)) {
return $this->errorResponse(trans('errors.drug_device_already_exists'));
}
$drug = NhDrugsAndDevice::create($request->all());
return $this->successResponse($drug);
}
/**
* @OA\Get(
* path="/provider-classes",
* summary="Obtenir toutes les classes de prestataires d'un reseau",
* tags={"Classes de prestataires"},
* security={{"api_key":{}}},
* @OA\Parameter(
* parameter="network_id",
* name="network_id",
* description="ID du reseau",
* @OA\Schema(
* type="integer",
* default = 250
* ),
* in="query",
* required=true
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : {{"id":2,"name":"Pharmacien"}},
* "error":null
* }
* )
* )
* )
*/
public function getNetworkProviderClasses(Request $request)
{
$this->validate($request, [
'network_id' => 'required|integer|exists:networks,id',
]);
$network_id = $request->input('network_id');
$classes = NhProviderClass::whereHas('network_config', function ($query) use ($network_id) {
return $query->where('network_id', $network_id);
})->get(['id', 'name']);
return $this->successResponse($classes);
}
/**
* @OA\Get(
* path="/acts",
* summary="Obtenir ou rechercher par code tous les actes d'un reseau",
* tags={"Actes"},
* security={{"api_key":{}}},
* @OA\Parameter(
* parameter="network_id",
* name="network_id",
* description="ID du reseau",
* @OA\Schema(
* type="integer",
* default = 250
* ),
* in="query",
* required=true
* ),
* @OA\Parameter(
* parameter="code",
* name="code",
* description="Code de l'acte",
* @OA\Schema(
* type="string",
* ),
* in="query",
* required=false
* ),
* @OA\Parameter(
* parameter="authorization_type",
* name="authorization_type",
* description="Type d'autorisation",
* @OA\Schema(
* type="string",
* enum = {"FREE","PRIOR"},
* ),
* in="query",
* required=false
* ),
* @OA\Parameter(
* parameter="user_id",
* name="user_id",
* description="ID de utilisateur de l'assuré principal",
* @OA\Schema(
* type="integer",
* ),
* in="query",
* required=false
* ),
* @OA\Parameter(
* parameter="beneficiary_id",
* name="beneficiary_id",
* description="ID du beneficiaire , s'il s'agit d'une feuille de soins pour beneficiaire",
* @OA\Schema(
* type="integer",
* ),
* in="query",
* required=false
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : {{"id":2,"code": "CODE2", "name":"Les actes infirmiers"}},
* "error":null
* }
* )
* )
* )
*/
public function getNetworkActs(Request $request)
{
$this->validate($request, [
'network_id' => 'required|integer|exists:networks,id',
'user_id' => 'nullable|string|exists:users,id',
'beneficiary_id' => 'nullable|string|exists:nh_having_rights,id',
'code' => 'nullable|string',
'authorization_type' => 'nullable|in:FREE,PRIOR'
]);
$network_id = $request->input('network_id');
$authorization_type = $request->input('authorization_type');
$user_id = $request->input('user_id');
$beneficiary_id = $request->input('beneficiary_id');
$code = $request->input('code');
$query = NhAct::whereHas('network_config', function ($query) use ($network_id) {
return $query->where('network_id', $network_id);
});
if (!empty($code)) {
$query = $query->where('code', 'like', '%' . $code . '%');
}
if (!empty($authorization_type)) {
$query = $query->where('authorization_type', $authorization_type);
}
if (!empty($user_id)) {
$query = $query->where('authorization_type', 'FREE');
// Recuperer les actes autorisés
$authorized_ids_query = NhAuthorizationOfCareRequest::whereHas('insurance', function ($q) use ($user_id) {
return $q->where('user_id', $user_id);
});
if (!empty($beneficiary_id)) {
$authorized_ids_query = $authorized_ids_query->where('beneficiary_id', $beneficiary_id);
} else {
$authorized_ids_query = $authorized_ids_query->whereNull('beneficiary_id');
}
$authorized_ids = $authorized_ids_query->where('state', InsuranceSubscriptionState::ACCEPTED)->pluck('act_id')->toArray();
$query = $query->orWhereIn('id', $authorized_ids);
}
$classes = $query->select('id', 'code', 'name')->get();
return $this->successResponse($classes);
}
/**
* @OA\Post(
* path="/health-care-sheets/performances-amount",
* summary="Calculer le montant des prestations lors d'une consulation",
* tags={"Feuilles de soins"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(property="network_id",
* type="integer",
* example = 250,
* description="ID du reseau de l'assureur"
* ),
* @OA\Property(property="care_condition",
* description = "Condition de prise en charge",
* type="string",
* enum={"CURRENT_AFFECTION","LONG_TERM_AFFECTION","EXONERATION"},
* example= "CURRENT_AFFECTION"
* ),
* @OA\Property(property="amount",
* type="integer",
* example = 20000,
* description="Montant de la prestation"
* ),
* ),
* example = {"network_id":250,"care_condition":"CURRENT_AFFECTION","amount":20000 }
* )
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {"status":200,"response":{"moderator_ticket":"4\u202f000 FCFA","insurance_amount":"16\u202f000 FCFA"},"error":null},
* )
* )
* )
*/
public function calculateConsultationPerformancesAmount(Request $request)
{
$this->validate($request, [
'network_id' => 'required|integer|exists:networks,id',
'care_condition' => 'required|in:CURRENT_AFFECTION,LONG_TERM_AFFECTION,EXONERATION',
'amount' => 'required|numeric',
]);
$nhConfig = NhNetworksConfig::where('network_id', $request->input('network_id'))->first();
if (!isset($nhConfig)) {
return $this->errorResponse(trans('errors.nano_health_not_activated'));
}
$currency_code = $this->getNetworkCurrency($request->input('network_id'));
$parts = $this->getConfigInsuranceParts($nhConfig, $request->input('care_condition'));
$result = new stdClass();
$result->moderator_ticket = $this->toMoneyWithCurrencyCode($parts->insured_part * $request->input('amount'), $currency_code);
$result->insurance_amount = $this->toMoneyWithCurrencyCode($parts->insurer_part * $request->input('amount'), $currency_code); //
return $this->successResponse($result);
}
/**
* @OA\Post(
* path="/health-care-sheets/consultation",
* summary="Consulter ou prescritpion d'un assuré",
* tags={"Feuilles de soins"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* schema="consult_health_care_sheet",
* title = "Consulter ou prescrire une feuille de soins",
* required={"insured_id", "network_agent_id", "password", "practitioner_lastname", "practitioner_provider_class_id", "care_condition",
* "performances"},
* @OA\Property(
* property="insured_id",
* description = "Numéro immatriculation de lassuré",
* type="string",
* example= "INSUF45548"
* ),
* @OA\Property(
* property="network_agent_id",
* description = "ID de l'agent qui saisit la feuille de soin dans le reseau",
* type="integer",
* example= 4325
* ),
* @OA\Property(
* property="password",
* description = "Mot de passe de l'agent",
* type="string",
* example= "password"
* ),
* @OA\Property(
* property="beneficiary_id",
* description = "ID du beneficiaire , s'il s'agit d'une feuille de soins pour beneficiaire",
* type="integer",
* example= 4
* ),
* @OA\Property(
* property="patient_firstname",
* description = "Prenom du patient",
* type="string",
* example= "BOBOL"
* ),
* @OA\Property(
* property="practitioner_lastname",
* description = "Nom du pratricien",
* type="string",
* example= "Dr DIETCHI"
* ),
* @OA\Property(
* property="practitioner_firstname",
* description = "Prenom du pratricien",
* type="string",
* example= "Djery"
* ),
* @OA\Property(
* property="practitioner_provider_class_id",
* description = "ID de la classe de prestataire du praticien",
* type="integer",
* example= 12
* ),
* @OA\Property(
* property="care_condition",
* description = "Condition de prise en charge",
* type="string",
* enum={"CURRENT_AFFECTION","LONG_TERM_AFFECTION","EXONERATION"},
* example= "CURRENT_AFFECTION"
* ),
* @OA\Property(
* property="accident_date",
* description = "Date de l'accident en cas d'accident",
* type="string",
* example= "2021-10-01"
* ),
* @OA\Property(
* property="pregnancy_start_at",
* description = "Date de début de la grossesse (si grossesse)",
* type="string",
* example= "2021-01-01"
* ),
* @OA\Property(
* property="pregnancy_end_at",
* description = "Date de fin de la grossese (si grossesse)",
* type="string",
* example= "2021-09-01"
* ),
* @OA\Property(property="performances",
* type="array",
* description="Listes des prestations",
* @OA\Items(ref="#/components/schemas/add_performance")
* ),
* @OA\Property(property="prescriptions",
* type="array",
* description="Listes des prescriptions medicales",
* @OA\Items(ref="#/components/schemas/add_prescription")
* ),
* @OA\Property(property="exams",
* type="array",
* description="Listes des examens",
* @OA\Items(ref="#/components/schemas/add_exam")
* )
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : "Consultation ou prescription effectuée",
* "error":null
* }
* )
* )
* )
* @throws \App\Exceptions\AppException
*/
public function storeHealthCareSheetConsultation(Request $request)
{
/**
* @OA\Schema(
* schema="add_performance",
* title = "Ajouter une prestation",
* required={"act_id", "amount"},
* @OA\Property(property="act_id",
* type="integer",
* example = 2,
* description="ID de l'acte "
* ),
* @OA\Property(property="amount",
* type="number",
* example=30000,
* description="Montant de la prestation"
* ),
* @OA\Property(property="home_visit_fees",
* type="number",
* example=5000,
* description="Frais de deplacement pour visiste à domicile "
* )
* )
*
* @OA\Schema(
* schema="add_prescription",
* title = "Ajouter une prescription medicale",
* required={"drug_or_device_id", "dosage", "quantity"},
* @OA\Property(property="drug_or_device_id",
* type="integer",
* example = 2,
* description="ID du medicament ou appareillage"
* ),
* @OA\Property(property="dosage",
* type="string",
* example="3 fois / jour pendant 1e semaine",
* description="Posologie ou frequence de consommation"
* ),
* @OA\Property(property="quantity",
* type="int",
* example=5,
* description="Quantité"
* )
* )
*
* @OA\Schema(
* schema="add_exam",
* title = "Ajouter un examen",
* required={"act_id", "description", "quantity"},
* @OA\Property(property="act_id",
* type="integer",
* example = 2,
* description="ID de l'acte"
* ),
* @OA\Property(property="description",
* type="string",
* example="Une descrition de l'examen",
* description="Description de l'examene"
* ),
* @OA\Property(property="quantity",
* type="int",
* example=5,
* description="Quantité"
* )
* )
*/
$this->validate($request, [
'insured_id' => 'required|string',
'network_agent_id' => 'required|integer|exists:networks_agents,id',
'password' => 'required|string',
'beneficiary_id' => 'nullable|int|exists:nh_having_rights,id',
// 'patient_lastname' => 'required|string',
// 'patient_firstname' => 'nullable|string',
'practitioner_lastname' => 'required|string',
'practitioner_firstname' => 'nullable|string',
'practitioner_provider_class_id' => 'required|integer',
'care_condition' => 'required|in:CURRENT_AFFECTION,LONG_TERM_AFFECTION,EXONERATION',
'accident_date' => 'nullable|date_format:Y-m-d|before:today',
'pregnancy_start_at' => 'nullable|date_format:Y-m-d|before:today',
'pregnancy_end_at' => 'nullable|date_format:Y-m-d|after:pregnancy_start_at',
'performances' => 'required|array',
'performances.*.act_id' => 'required|integer|exists:nh_acts,id',
'performances.*.amount' => 'required|numeric',
'performances.*.home_visit_fees' => 'nullable|numeric',
'prescriptions' => 'nullable|array',
'prescriptions.*.drug_or_device_id' => 'required|integer|exists:nh_drugs_and_devices,id',
'prescriptions.*.dosage' => 'required|string',
'prescriptions.*.quantity' => 'required|integer',
'exams' => 'nullable|array',
'exams.*.act_id' => 'required|integer|exists:nh_acts,id',
'exams.*.description' => 'required|string',
'exams.*.quantity' => 'required|integer',
]);
$insurance = NhInsurance::where('insured_id', $request->input('insured_id'))->where('state', InsuranceState::PAID)->first();
if (!isset($insurance)) {
return $this->errorResponse(trans('errors.not_insured'));
}
$this->agentCredentialsVerification($request->input('network_agent_id'), $request->input('password'));
$beneficiary_id = $request->input('beneficiary_id');
if (!empty($beneficiary_id)) {
$beneficiary = $insurance->beneficiaries()->where('nh_having_rights.id', $beneficiary_id)->first();
if (!isset($beneficiary)) {
return $this->errorResponse(trans('errors.beneficiary_not_found'));
}
} else {
$beneficiary_id = null;
}
$nhConfig = NhNetworksConfig::where('network_id', $insurance->network_id)->first();
if (!isset($nhConfig)) {
return $this->errorResponse(trans('errors.nano_health_not_activated'));
}
$parts = $this->getConfigInsuranceParts($nhConfig, $request->input('care_condition'));
$currency_code = $this->getNetworkCurrency($insurance->network_id);
try {
DB::beginTransaction();
$datetime = $this->getCurrentTimeByCountryCode($insurance->network->country->code_country);
$accident_date = $request->input('accident_date');
$pregnancy_start_at = $request->input('pregnancy_start_at');
$pregnancy_end_at = $request->input('pregnancy_end_at');
$healthCareSheet = NhHealthCareSheet::create([
'health_care_sheet_id' => $this->generateSheetID(),
'beneficiary_id' => $beneficiary_id,
'network_agent_id' => $request->input('network_agent_id'),
'care_condition' => $request->input('care_condition'),
'practitioner_lastname' => $request->input('practitioner_lastname'),
'practitioner_firstname' => $request->input('practitioner_firstname'),
'practitioner_provider_class_id' => $request->input('practitioner_provider_class_id'),
'insurance_id' => $insurance->id,
'patient_lastname' => isset($beneficiary) ? $beneficiary->lastname : $insurance->user->lastname,
'patient_firstname' => isset($beneficiary) ? $beneficiary->firstname : $insurance->user->firstname,
'patient_situation' => isset($beneficiary) ? 'HAVING_RIGHT' : 'INSURED',
'type' => HealthCareSheetType::CONSULTATION,
'state' => InsuranceSubscriptionState::UNDER_VALIDATION,
'accident_date' => (!empty($accident_date)) ? $accident_date : null,
'pregnancy_start_at' => (!empty($pregnancy_start_at)) ? $pregnancy_start_at : null,
'pregnancy_end_at' => (!empty($pregnancy_end_at)) ? $pregnancy_end_at : null,
]);
$healthCareSheet->created_at = $healthCareSheet->updated_at = $datetime;
$healthCareSheet->save();
foreach ($request->input('performances', []) as $p) {
$fees = !empty($p['home_visit_fees']) ? $p['home_visit_fees'] : 0;
$performance = NhPerformance::create([
'act_id' => $p['act_id'],
'amount' => $p['amount'],
'home_visit_fees' => $fees != 0 ? $fees : null,
'moderator_ticket' => $parts->insured_part * ($p['amount'] + $fees), // to calculate,
'insurance_amount' => $parts->insurer_part * ($p['amount'] + $fees), // to calculate, montant de l'assurance
]);
$performance->created_at = $performance->updated_at = $datetime;
$performance->save();
$nhp = NhHealthCareSheetsPerformance::create([
'sheet_id' => $healthCareSheet->id,
'performance_id' => $performance->id,
]);
$nhp->created_at = $nhp->updated_at = $datetime;
$nhp->save();
$this->useAuthorizationRequest($p['act_id'], $insurance->id, $beneficiary_id, $healthCareSheet->id, $datetime);
}
// Calculer les parts de l'assurance et l'assuré pour cette feuille de soins
$this->calculateInsuranceAmounts($healthCareSheet);
// Verification de la limite de couverture
$this->verifyInsuranceCoverageAmount($nhConfig, $insurance, $healthCareSheet, $beneficiary ?? null, $currency_code);
// Mettre à jour la couverture d'assurance de l'assuré
$this->updateInsuranceCoverageAmount($healthCareSheet, $insurance, $datetime, $beneficiary ?? null);
foreach ($request->input('prescriptions', []) as $p) {
$prescription = NhMedicalPrescription::create($p);
$prescription->created_at = $prescription->updated_at = $datetime;
$prescription->save();
NhHealthCareSheetsPrescription::create([
'sheet_id' => $healthCareSheet->id,
'prescription_id' => $prescription->id,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
}
foreach ($request->input('exams', []) as $e) {
$exam = NhExam::create([
'act_id' => $e['act_id'],
'description' => $e['description'],
'quantity' => $e['quantity'] ?? null,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
NhHealthCareSheetsExam::create([
'sheet_id' => $healthCareSheet->id,
'exam_id' => $exam->id,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
$this->useAuthorizationRequest($e['act_id'], $insurance->id, $beneficiary_id, $healthCareSheet->id, $datetime);
}
NhHealthCareSheetsHistory::create([
'action' => 'ADD',
'health_care_sheet_id' => $healthCareSheet->health_care_sheet_id,
'state' => $healthCareSheet->state,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
$healthCareSheet->user = $insurance->user;
$patient_name = $healthCareSheet->patient_lastname . ' ' . $healthCareSheet->patient_firstname;
$institution_name = $healthCareSheet->institution->lastname;
$practitioner_name = $healthCareSheet->practitioner_lastname . ' ' . $healthCareSheet->practitioner_firstname;
Event::dispatch(new InsuredConsultation($healthCareSheet, trans('messages.consultation_or_prescription_carried_out'), trans('messages.consultation_or_prescription_carried_out_mail', ['name' => $insurance->user->lastname, 'insured_id' => $insurance->insured_id,
'patient_name' => $patient_name, 'patient_situation' => trans('states.' . $healthCareSheet->patient_situation), 'care_condition' => trans('states.' . $healthCareSheet->care_condition),
'gender' => trans('states.' . $insurance->user->identification->gender), 'insurance_name' => $nhConfig->network->name, 'practitioner_name' => $practitioner_name, 'institution_name' => $institution_name]),
trans('messages.consultation_or_prescription_carried_out_notification', ['patient_name' => $patient_name, 'practitioner_name' => $practitioner_name, 'institution_name' => $institution_name])));
DB::commit();
return $this->successResponse(trans('messages.consultation_or_prescription_carried_out'));
} catch (AppException $e) {
return $this->errorResponse($e->getMessage(), $e->getCode());
} catch (Throwable $e) {
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
DB::rollBack();
return $this->errorResponse(trans('errors.unexpected_error'), 500);
}
}
/**
* @throws AppException
*/
// Verification de la limite de couverture
private function verifyInsuranceCoverageAmount(NhNetworksConfig $nhConfig, NhInsurance $insurance, NhHealthCareSheet $sheet, NhHavingRight $beneficiary = null,
$currency_code = 'XAF', $currentInsuranceAmount = 0) // Current Insurance Amount en cas de mise à jour de la feuille de soins pour ne pas prendre en compte la couverture deja affecté
{
$insurance_coverage_amount = isset($beneficiary) ? $beneficiary->insurance_coverage_amount : $insurance->insurance_coverage_amount;
$insurance_amount = $sheet->insurance_amount;
$monthPrice = $nhConfig->monthsPricesGrid()->where('nh_network_config_id', $nhConfig->id)
->where('number_of_months', $insurance->number_of_months)->first();
if (!isset($monthPrice))
throw new AppException(trans('errors.month_price_grid_not_found'));
if (!$nhConfig->family_coverage_sharing) {
$total_insurance_amount = $insurance_coverage_amount + $insurance_amount - $currentInsuranceAmount;
if ($total_insurance_amount > $monthPrice->max_insurance_coverage_amount) {
DB::rollBack();
throw new AppException(trans('errors.insurance_coverage_amount_exceeded', [
'consumption' => $this->toMoneyWithCurrencyCode($insurance_coverage_amount, $currency_code),
'remaining' => $this->toMoneyWithCurrencyCode($monthPrice->max_insurance_coverage_amount - $insurance_coverage_amount, $currency_code),
]));
}
} else {
// Montant de l'assurance deja consomé à date
$family_consumed_amount = $insurance->insurance_coverage_amount;
foreach ($insurance->beneficiaries as $b) {
$family_consumed_amount += $b->insurance_coverage_amount;
}
$total_insurance_amount = $family_consumed_amount + $insurance_amount - $currentInsuranceAmount;
$family_limit_amount = $monthPrice->max_insurance_coverage_amount * ($insurance->number_of_beneficiaries + 1);
if ($total_insurance_amount > $family_limit_amount) {
DB::rollBack();
throw new AppException(trans('errors.insurance_coverage_amount_exceeded', [
'consumption' => $this->toMoneyWithCurrencyCode($family_consumed_amount, $currency_code),
'remaining' => $this->toMoneyWithCurrencyCode($family_limit_amount - $family_consumed_amount, $currency_code),
]));
}
}
}
private function useAuthorizationRequest($act_id, $insurance_id, $beneficiary_id, $sheet_id, $datetime): void
{
$authorization_request = NhAuthorizationOfCareRequest::where('act_id', $act_id)->where('insurance_id', $insurance_id);
if (empty($beneficiary_id)) {
$authorization_request = $authorization_request->whereNull('beneficiary_id');
} else {
$authorization_request = $authorization_request->where('beneficiary_id', $beneficiary_id);
}
$authorization_request->update([
'state' => 'USED',
'health_care_sheet_id' => $sheet_id,
'updated_at' => $datetime
]);
}
private function updateInsuranceCoverageAmount(NhHealthCareSheet $sheet, NhInsurance $insurance, $datetime,
NhHavingRight $beneficiary = null, $currentInsuranceAmount = 0): void
{ // Current Insurance Amount en cas de mise à jour de la feuille de soins pour ne pas prendre en compte la couverture deja affecté)
$sheet->insurance_consumed_at = $datetime;
if (!empty($beneficiary)) {
$beneficiary->insurance_coverage_amount += ($sheet->insurance_amount - $currentInsuranceAmount);
$beneficiary->save();
} else {
$insurance->insurance_coverage_amount += ($sheet->insurance_amount - $currentInsuranceAmount);
$insurance->save();
}
$sheet->save();
}
/**
* @OA\Post(
* path="/health-care-sheets/execution",
* summary="Execution de la prescription d'un assuré",
* tags={"Feuilles de soins"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* schema="execution_health_care_sheet",
* title = "Consulter ou prescrire une feuille de soins",
* required={"health_care_sheet_id", "network_agent_id", "password", "practitioner_lastname", "practitioner_provider_class_id",
* "prescriptions" , "exams"},
* @OA\Property(
* property="health_care_sheet_id",
* description = "ID de la feuille de soins",
* type="integer",
* example= 23
* ),
* @OA\Property(
* property="network_agent_id",
* description = "ID de l'agent qui saisit la feuille de soin dans le reseau",
* type="integer",
* example= 4325
* ),
* @OA\Property(
* property="password",
* description = "Mot de passe de l'agent",
* type="string",
* example= "password"
* ),
* @OA\Property(
* property="practitioner_lastname",
* description = "Nom du pratricien",
* type="string",
* example= "Dr DIETCHI"
* ),
* @OA\Property(
* property="practitioner_firstname",
* description = "Prenom du pratricien",
* type="string",
* example= "Djery"
* ),
* @OA\Property(
* property="practitioner_provider_class_id",
* description = "ID de la classe de prestataire du praticien",
* type="integer",
* example= 12
* ),
* @OA\Property(property="prescriptions",
* type="array",
* description="Listes des prescriptions medicales",
* @OA\Items(ref="#/components/schemas/execution_schema")
* ),
* @OA\Property(property="exams",
* type="array",
* description="Listes des examens",
* @OA\Items(ref="#/components/schemas/execution_schema")
* )
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : "Execution de prescription effectuée",
* "error":null
* }
* )
* )
* )
* @throws \App\Exceptions\AppException
*/
public function storeHealthCareSheetExecution(Request $request)
{
/**
* @OA\Schema(
* schema="execution_schema",
* title = "Faire une execution de prescriton deja existance",
* required={"id", "unit_price"},
* @OA\Property(property="id",
* type="integer",
* example = 2,
* description="ID de l'operation"
* ),
* @OA\Property(property="unit_price",
* type="float",
* example= 5000,
* description="Prix unitaire"
* )
* )
*/
$this->validate($request, [
'health_care_sheet_id' => 'required|integer|exists:nh_health_care_sheets,id',
'network_agent_id' => 'required|integer|exists:networks_agents,id',
'password' => 'required|string',
'practitioner_lastname' => 'required|string',
'practitioner_firstname' => 'nullable|string',
'practitioner_provider_class_id' => 'required|integer',
'prescriptions' => 'nullable|array',
'prescriptions.*.id' => 'required|integer|exists:nh_medical_prescriptions,id',
'prescriptions.*.unit_price' => 'required|numeric',
'exams' => 'nullable|array',
'exams.*.id' => 'required|integer|exists:nh_exams,id',
'exams.*.unit_price' => 'required|numeric',
]);
$prescriptions = $request->input('prescriptions', []);
$exams = $request->input('exams', []);
$sheet = NhHealthCareSheet::findOrFail($request->input('health_care_sheet_id'));
if ($sheet->state != InsuranceSubscriptionState::ACCEPTED) {
return $this->errorResponse("Cette feuille de soin n'a pas été accepte");
}
if ($sheet->type != HealthCareSheetType::CONSULTATION) {
return $this->errorResponse("Cette feuille de soin ne provient pas d'une consultation");
}
$this->agentCredentialsVerification($request->input('network_agent_id'), $request->input('password'));
$nhConfig = NhNetworksConfig::where('network_id', $sheet->insurance->network_id)->first();
if (!isset($nhConfig)) {
return $this->errorResponse(trans('errors.nano_health_not_activated'));
}
$parts = $this->getConfigInsuranceParts($nhConfig, $sheet->care_condition);
$currency_code = $this->getNetworkCurrency($sheet->insurance->network_id);
$prescriptionsIds = array_map(function ($r) {
return $r['id'];
}, $prescriptions);
$examsIds = array_map(function ($r) {
return $r['id'];
}, $exams);
try {
DB::beginTransaction();
$datetime = $this->getCurrentTimeByCountryCode($sheet->insurance->network->country->code_country);
$healthCareSheet = $sheet->replicate();
$healthCareSheet->health_care_sheet_id = $this->generateSheetID();
$healthCareSheet->network_agent_id = $request->input('network_agent_id');
$healthCareSheet->practitioner_lastname = $request->input('practitioner_lastname');
$healthCareSheet->practitioner_firstname = $request->input('practitioner_firstname');
$healthCareSheet->practitioner_provider_class_id = $request->input('practitioner_provider_class_id');
$healthCareSheet->type = HealthCareSheetType::EXECUTION;
$healthCareSheet->state = InsuranceSubscriptionState::UNDER_VALIDATION;
$healthCareSheet->prescription_sheet_id = $sheet->id;
$healthCareSheet->created_at = $healthCareSheet->updated_at = $datetime;
$healthCareSheet->push();
$insurance = $sheet->insurance;
#Clone relations
//reset relations on EXISTING MODEL (this way you can control which ones will be loaded
$sheet->setRelations([]);
//load relations on EXISTING MODEL
$sheet->load('prescriptions', 'exams'); // Cloner uniquement les prescriptions et les examens
//re-sync everything
// foreach ($sheet->relations as $relationName => $values){
// $healthCareSheet->{$relationName}()->sync($values);
// }
foreach ($sheet->getRelations() as $relation => $items) {
foreach ($items as $i) {
$item = $i->replicate();
if ($relation == 'prescriptions') {
if (!in_array($i->id, $prescriptionsIds)) {
continue;
}
$itemIndex = array_search($i->id, $prescriptionsIds);
if ($i->billed) {
return $this->errorResponse(__('errors.prescription_already_invoiced', ['id' => $itemIndex + 1]));
}
$item->unit_price = $prescriptions[$itemIndex]['unit_price'];
}
if ($relation == 'exams') {
if (!in_array($i->id, $examsIds)) {
continue;
}
$itemIndex = array_search($i->id, $examsIds);
if ($i->billed) {
return $this->errorResponse(__('errors.exam_already_invoiced', ['id' => $itemIndex + 1]));
}
$item->unit_price = $exams[$itemIndex]['unit_price'];
}
unset($item->laravel_through_key);
$item->insured_paid_amount = $parts->insured_part * $item->unit_price * ($item->quantity ?? 1);
$item->insurer_paid_amount = $parts->insurer_part * $item->unit_price * ($item->quantity ?? 1);
$item->created_at = $item->updated_at = $datetime;
$item->billed = true;
$item->push();
$i->billed = true;
$i->save();
if ($relation == 'prescriptions') {
NhHealthCareSheetsPrescription::create([
'sheet_id' => $healthCareSheet->id,
'prescription_id' => $item->id,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
}
if ($relation == 'exams') {
NhHealthCareSheetsExam::create([
'sheet_id' => $healthCareSheet->id,
'exam_id' => $item->id,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
}
}
}
// Calculer les parts de l'assurance et l'assuré pour cette feuille de soins
$this->calculateInsuranceAmounts($healthCareSheet);
// Verification de la limite de couverture
$this->verifyInsuranceCoverageAmount($nhConfig, $sheet->insurance, $healthCareSheet, $sheet->beneficiary, $currency_code);
// Mettre à jour la couverture d'assurance de l'assuré
$this->updateInsuranceCoverageAmount($healthCareSheet, $sheet->insurance, $datetime, $sheet->beneficiary,);
#Clone pivots
// $performances = NhHealthCareSheetsPerformance::where('sheet_id', $sheet->id)->get();
// foreach ($performances as $pf) {
// $p = $pf->replicate();
// $p->sheet_id = $healthCareSheet->id;
// $p->push();
// }
NhHealthCareSheetsHistory::create([
'action' => 'ADD',
'health_care_sheet_id' => $healthCareSheet->health_care_sheet_id,
'state' => $healthCareSheet->state,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
$healthCareSheet->user = $insurance->user;
$patient_name = $healthCareSheet->patient_lastname . ' ' . $healthCareSheet->patient_firstname;
$institution_name = $healthCareSheet->institution->lastname;
$practitioner_name = $healthCareSheet->practitioner_lastname . ' ' . $healthCareSheet->practitioner_firstname;
Event::dispatch(new InsuredConsultation($healthCareSheet, trans('messages.execution_carried_out'), trans('messages.execution_carried_out_mail', ['name' => $insurance->user->lastname, 'insured_id' => $insurance->insured_id,
'patient_name' => $patient_name, 'patient_situation' => trans('states.' . $healthCareSheet->patient_situation), 'care_condition' => trans('states.' . $healthCareSheet->care_condition),
'gender' => trans('states.' . $insurance->user->identification->gender), 'insurance_name' => $nhConfig->network->name, 'practitioner_name' => $practitioner_name, 'institution_name' => $institution_name]),
trans('messages.execution_carried_out', ['patient_name' => $patient_name, 'practitioner_name' => $practitioner_name, 'institution_name' => $institution_name])));
DB::commit();
return $this->successResponse(trans('messages.execution_carried_out'));
} catch (AppException $e) {
return $this->errorResponse($e->getMessage(), $e->getCode());
} catch (Throwable $e) {
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
DB::rollBack();
return $this->errorResponse(trans('errors.unexpected_error'), 500);
}
}
/**
* @OA\Get(
* path="/health-care-sheets",
* summary="Obtenir les feuilles de soins d'un utilisateur",
* tags={"Feuilles de soins"},
* security={{"api_key":{}}},
* @OA\Parameter(
* parameter="user_id",
* name="user_id",
* description="ID de l'utilisateur",
* @OA\Schema(
* type="integer",
* default = 349
* ),
* in="query",
* required=false
* ),
* @OA\Parameter(
* parameter="beneficiary_id",
* name="beneficiary_id",
* description="ID du beneficiaire",
* @OA\Schema(
* type="integer",
* default = 3
* ),
* in="query",
* required=false
* ),
* @OA\Parameter(
* parameter="network_agent_id",
* name="network_agent_id",
* description="ID de l'agent dans le reseau",
* @OA\Schema(
* type="integer",
* default = 43510
* ),
* in="query",
* required=false
* ),
* @OA\Parameter(
* parameter="network_id",
* name="network_id",
* description="ID du reseau",
* @OA\Schema(
* type="integer",
* default = 250
* ),
* in="query",
* required=false
* ),
* @OA\Parameter(
* parameter="type",
* name="type",
* description="Type des feuilles de soins",
* @OA\Schema(
* type="string",
* enum = {"CONSULTATION","EXECUTION"},
* default = "CONSULTATION"
* ),
* in="query",
* required=false
* ),
* @OA\Parameter(
* parameter="state",
* name="state",
* description="Status des feuilles de soins",
* @OA\Schema(
* type="string",
* enum = {"UNTREATED","TREATED","ACCEPTED","TO_BILL","ALL","UNTREATED_ALL"},
* default = "UNTREATED"
* ),
* in="query",
* required=false
* ),
* @OA\Parameter(
* parameter="page",
* name="page",
* description="Page",
* in="query",
* required=false,
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Parameter(
* parameter="perPage",
* name="perPage",
* description="Pas de pagination",
* in="query",
* required=false,
* @OA\Schema(
* type="integer"
* )
* ),
* @OA\Parameter(
* parameter="pagination",
* name="pagination",
* description="pagination",
* in="query",
* required=false,
* @OA\Schema(
* type="boolean",
* )
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : {{"insured_id":"GJKS8ZGBEJTL","network_id":250,"user_id":349,"id":8,"health_care_sheet_id":"XLLLCY75OU8H","insurance_id":4,"network_agent_id":43510,"patient_lastname":"Dietchi",
* "patient_firstname":"Djery","patient_situation":"AYANT DROIT","practitioner_lastname":"Dr Luc","practitioner_firstname":"Boris","practitioner_provider_class_id":"1","care_condition":"AFFECTION COURANTE",
* "accident_date":null,"pregnancy_start_at":null,"pregnancy_end_at":null,"state":"EN COURS DE VALIDATION","created_at":"2021-11-25T04:39:06.000000Z","updated_at":"2021-11-25T04:39:06.000000Z","type":"CONSULTATION",
* "practitioner_provider_class":"Chirugien","institution_name":"Agent 2 cnamgs fond 4","institution_code":"aon8K9BZOn","currency_code":"XAF","performances":{{"id":10,"act_id":5,"amount":"5 000 FCFA","moderator_ticket":"1 000 FCFA",
* "insurance_amount":"4 000 FCFA","home_visit_fees":"2 000 FCFA","created_at":"2021-11-25T05:39:06.000000Z","updated_at":"2021-11-25T05:39:06.000000Z","act":{"id":5,"code":"CODE2","name":"Les actes infirmiers"}}},"exams":{{"id":2,"act_id":7,"description":"Une description de l'examen","quantity":5,"unit_price":null,"insured_paid_amount":null,"insurer_paid_amount":null,"created_at":"2021-11-25T04:39:06.000000Z",
* "updated_at":"2021-11-25T04:39:06.000000Z","laravel_through_key":8,"act":{"id":7,"code":"CODE4","name":"Les analyses de biologie m\u00e9dicale"}}},"prescriptions":{{"id":4,"drug_or_device_id":1,"dosage":"3 fois\/jour","quantity":5,"unit_price":null,"insured_paid_amount":null,"insurer_paid_amount":null,"created_at":"2021-11-25T05:39:06.000000Z","updated_at":"2021-11-25T05:39:06.000000Z",
* "drug_or_device":{"id":1,"name":"Paracetamol"}}}}},
* "error":null
* }
* )
* )
* )
*/
public function getHealthCareSheets(Request $request)
{
$this->validate($request, [
'user_id' => 'required_without_all:network_agent_id,network_id|integer|exists:users,id',
'beneficiary_id' => 'nullable|integer|exists:nh_having_rights,id',
'network_id' => 'nullable|integer|exists:networks,id',
'network_agent_id' => 'required_without_all:user_id,network_id|integer|exists:networks_agents,id',
'type' => 'nullable|in:CONSULTATION,EXECUTION',
'state' => 'nullable|in:UNTREATED,TREATED,ACCEPTED,TO_BILL,ALL,UNTREATED_ALL',
'pagination' => 'nullable|boolean'
]);
$type = $request->input('type');
$state = $request->input('state');
$user_id = $request->input('user_id');
$beneficiary_id = $request->input('beneficiary_id');
$network_agent_id = $request->input('network_agent_id');
$network_id = $request->input('network_id');
$pagination = $request->input('pagination');
if (!empty($user_id)) {
$query = NhInfosHealthCareSheets::where('user_id', $user_id);
if (!empty($beneficiary_id)) {
$query = $query->where('beneficiary_id', $beneficiary_id);
} else {
if (!in_array($state, ['ALL', 'UNTREATED_ALL'])) {
$query = $query->whereNull('beneficiary_id');
}
}
if (!empty($network_agent_id)) {
$query = $query->where('network_agent_id', $network_agent_id);
}
} else if (!empty($network_agent_id)) {
$query = NhInfosHealthCareSheets::where('network_agent_id', $network_agent_id);
} else if (!empty($network_id)) {
$query = NhInfosHealthCareSheets::where('network_id', $network_id);
}
$query = $query->with(['network:id,name', 'performances.act:id,code,name', 'exams.act:id,code,name', 'prescriptions.drug_or_device:id,name']);
if (!empty($state) && $state == 'TO_BILL') {
// Liste des feuilles de soins a afficher pour l'execution
$query = NhInfosHealthCareSheets::with(['performances.act:id,code,name', 'exams' => function ($q) {
return $q->with(['act:id,code,name'])->where('billed', 0);
}, 'prescriptions' => function ($q) {
return $q->with(['drug_or_device:id,name'])->where('billed', 0);
}])->where('state', InsuranceSubscriptionState::ACCEPTED)
->where('user_id', $request->input('user_id'));
if (!empty($beneficiary_id)) {
$query = $query->where('beneficiary_id', $beneficiary_id);
} else {
$query = $query->whereNull('beneficiary_id');
}
}
if (!empty($type)) {
$query = $query->where('type', $type);
}
if (!empty($state)) {
switch ($state) {
case 'UNTREATED' :
case 'UNTREATED_ALL' :
$query = $query->where('state', InsuranceSubscriptionState::UNDER_VALIDATION);
break;
case 'TREATED' :
$query = $query->where('state', '!=', InsuranceSubscriptionState::UNDER_VALIDATION);
break;
case 'ACCEPTED' :
$query = $query->where('state', InsuranceSubscriptionState::ACCEPTED);
break;
}
}
$query = $query->orderBy('created_at', 'DESC');
if ($pagination) {
$sheets = $query->paginate($request->input('perPage', 10));
} else {
$sheets = $query->get();
}
if (!empty($state) && $state == 'TO_BILL') {
// Liste des feuilles de soins a afficher pour l'execution ,
// Retirer les feuilles de soins qui n'ont ni exams ou prescriptions non soldes
$notEmptySheets = [];
$array = $pagination ? $sheets->items() : $sheets;
foreach ($array as $s) {
if (sizeof($s->exams) == 0 && sizeof($s->prescriptions) == 0) {
continue;
}
$notEmptySheets[] = $s;
}
if ($pagination) {
$sheets->setCollection(collect($notEmptySheets));
} else {
$sheets = $notEmptySheets;
}
}
$array = $pagination ? $sheets->items() : $sheets;
foreach ($array as $sheet) {
$this->formalizeHealthCareSheet($sheet);
}
return $this->successResponse($sheets);
}
/**
* @OA\Get(
* path="/health-care-sheets/{id}",
* summary="Obtenir une feuilles de soins par son id",
* tags={"Feuilles de soins"},
* security={{"api_key":{}}},
* @OA\Parameter(
* parameter="id",
* name="id",
* description="ID de la feuille de soins",
* @OA\Schema(
* type="integer",
* default = 349
* ),
* in="path",
* required=true
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : {"insured_id":"GJKS8ZGBEJTL","network_id":250,"user_id":349,"id":8,"health_care_sheet_id":"XLLLCY75OU8H","insurance_id":4,"network_agent_id":43510,"patient_lastname":"Dietchi",
* "patient_firstname":"Djery","patient_situation":"AYANT DROIT","practitioner_lastname":"Dr Luc","practitioner_firstname":"Boris","practitioner_provider_class_id":"1","care_condition":"AFFECTION COURANTE",
* "accident_date":null,"pregnancy_start_at":null,"pregnancy_end_at":null,"state":"EN COURS DE VALIDATION","created_at":"2021-11-25T04:39:06.000000Z","updated_at":"2021-11-25T04:39:06.000000Z","type":"CONSULTATION",
* "practitioner_provider_class":"Chirugien","institution_name":"Agent 2 cnamgs fond 4","institution_code":"aon8K9BZOn","currency_code":"XAF","performances":{{"id":10,"act_id":5,"amount":"5 000 FCFA","moderator_ticket":"1 000 FCFA",
* "insurance_amount":"4 000 FCFA","home_visit_fees":"2 000 FCFA","created_at":"2021-11-25T05:39:06.000000Z","updated_at":"2021-11-25T05:39:06.000000Z","act":{"id":5,"code":"CODE2","name":"Les actes infirmiers"}}},"exams":{{"id":2,"act_id":7,"description":"Une description de l'examen","quantity":5,"unit_price":null,"insured_paid_amount":null,"insurer_paid_amount":null,"created_at":"2021-11-25T04:39:06.000000Z",
* "updated_at":"2021-11-25T04:39:06.000000Z","laravel_through_key":8,"act":{"id":7,"code":"CODE4","name":"Les analyses de biologie m\u00e9dicale"}}},"prescriptions":{{"id":4,"drug_or_device_id":1,"dosage":"3 fois\/jour","quantity":5,"unit_price":null,"insured_paid_amount":null,"insurer_paid_amount":null,"created_at":"2021-11-25T05:39:06.000000Z","updated_at":"2021-11-25T05:39:06.000000Z",
* "drug_or_device":{"id":1,"name":"Paracetamol"}}}},
* "error":null
* }
* )
* )
* )
*/
public function getOneHealthCareSheets($id)
{
$sheet = NhInfosHealthCareSheets::with(['performances.act:id,code,name', 'exams.act:id,code,name', 'prescriptions.drug_or_device:id,name'])->where('id', $id)->firstOrFail();
$this->formalizeHealthCareSheet($sheet);
return $this->successResponse($sheet);
}
private function formatExamAndPrescriptionAmounts($e, $sheet): void
{
if (isset($e->unit_price)) {
$e->total_price = $this->toMoneyWithCurrencyCode($e->unit_price * $e->quantity, $sheet->currency_code);
$e->unit_price_formatted = isset($e->unit_price) ? $this->toMoneyWithCurrencyCode($e->unit_price, $sheet->currency_code) : null;
} else {
$e->total_price = null;
$e->unit_price_formatted = null;
}
$e->insured_paid_amount_formatted = isset($e->insured_paid_amount) ? $this->toMoneyWithCurrencyCode($e->insured_paid_amount, $sheet->currency_code) : null;
$e->insurer_paid_amount_formatted = isset($e->insurer_paid_amount) ? $this->toMoneyWithCurrencyCode($e->insurer_paid_amount, $sheet->currency_code) : null;
}
/**
* @OA\Put(
* path="/health-care-sheets",
* summary="Accepter ou Rejeter une feuille de soins",
* tags={"Feuilles de soins"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* required={"health_care_sheet_id", "user_id", "action"},
* @OA\Property(
* property="health_care_sheet_id",
* description = "ID de la feuille de soins",
* type="integer",
* example= 4
* ),
* @OA\Property(
* property="user_id",
* description = "ID de l'utilisateur",
* type="integer",
* example= 349
* ),
* @OA\Property(
* property="action",
* description = "Action à effectuer",
* enum={"ACCEPT","REJECT","RESUBMIT"},
* example= "ACCEPT"
* ),
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : "La feuille de soins a été acceptée",
* "error":null
* }
* )
* )
* )
*/
public function treatHealthCareSheet(Request $request)
{
$this->validate($request, [
'health_care_sheet_id' => 'required|integer|exists:nh_health_care_sheets,id',
'user_id' => 'required|integer|exists:users,id',
'action' => 'required|in:ACCEPT,REJECT,RESUBMIT'
]);
$action = $request->input('action');
$user_id = $request->input('user_id');
$sheet = NhHealthCareSheet::findOrFail($request->input('health_care_sheet_id'));
if ($sheet->insurance->user_id != $user_id) {
return $this->errorResponse(trans('errors.unauthorized'));
}
if ($action != 'RESUBMIT' && $sheet->state != InsuranceSubscriptionState::UNDER_VALIDATION) {
return $this->errorResponse(trans('errors.care_sheet_already_been_processed'));
}
$datetime = $this->getCurrentTimeByCountryCode($sheet->insurance->network->country->code_country);
try {
DB::beginTransaction();
if ($action == 'ACCEPT') {
$sheet->state = InsuranceSubscriptionState::ACCEPTED;
$message = trans('messages.care_sheet_accepted');
} else if ($action == 'REJECT') {
$sheet->state = InsuranceSubscriptionState::REJECTED;
$message = trans('messages.care_sheet_rejected');
} else {
$sheet->state = InsuranceSubscriptionState::UNDER_VALIDATION;
$sheet->created_at = $datetime;
$message = trans('messages.care_sheet_resubmitted');
}
$sheet->updated_at = $datetime;
$sheet->save();
DB::commit();
return $this->successResponse($message);
} catch (Throwable $e) {
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
DB::rollBack();
return $this->errorResponse(trans('errors.unexpected_error'), 500);
}
}
private function getConfigInsuranceParts(NhNetworksConfig $nhConfig, $care_condition): stdClass
{
$insuredPart = 0;
$insurerPart = 0;
switch ($care_condition) {
case 'CURRENT_AFFECTION':
$insurerPart = $nhConfig->current_affection_percentage_insurer / 100;
$insuredPart = $nhConfig->current_affection_percentage_insured / 100;
break;
case 'LONG_TERM_AFFECTION':
$insurerPart = $nhConfig->long_term_affection_percentage_insurer / 100;
$insuredPart = $nhConfig->long_term_affection_percentage_insured / 100;
break;
case 'EXONERATION':
$insurerPart = $nhConfig->exoneration_percentage_insurer / 100;
$insuredPart = $nhConfig->exoneration_percentage_insured / 100;
break;
}
$result = new stdClass();
$result->insured_part = $insuredPart;
$result->insurer_part = $insurerPart;
return $result;
}
/**
* @OA\Put(
* path="/health-care-sheets/{id}",
* summary="Modifier une feuille de soins",
* tags={"Feuilles de soins"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* schema="update_health_care_sheet",
* title = "Modfiier une feuille de soins",
* required={"insured_id", "network_agent_id", "password", "practitioner_lastname", "practitioner_provider_class_id"},
* @OA\Property(
* property="network_agent_id",
* description = "ID de l'agent qui saisit la feuille de soin dans le reseau",
* type="integer",
* example= 4325
* ),
* @OA\Property(
* property="password",
* description = "Mot de passe de l'agent",
* type="string",
* example= "password"
* ),
* @OA\Property(
* property="beneficiary_id",
* description = "ID du beneficiaire , s'il s'agit d'une feuille de soins pour beneficiaire",
* type="integer",
* example= 4
* ),
* @OA\Property(
* property="practitioner_lastname",
* description = "Nom du pratricien",
* type="string",
* example= "Dr DIETCHI"
* ),
* @OA\Property(
* property="practitioner_firstname",
* description = "Prenom du pratricien",
* type="string",
* example= "Djery"
* ),
* @OA\Property(
* property="practitioner_provider_class_id",
* description = "ID de la classe de prestataire du praticien",
* type="integer",
* example= 12
* ),
* @OA\Property(
* property="care_condition",
* description = "Condition de prise en charge",
* type="string",
* enum={"CURRENT_AFFECTION","LONG_TERM_AFFECTION","EXONERATION"},
* example= "CURRENT_AFFECTION"
* ),
* @OA\Property(
* property="accident_date",
* description = "Date de l'accident en cas d'accident",
* type="string",
* example= "2021-10-01"
* ),
* @OA\Property(
* property="pregnancy_start_at",
* description = "Date de début de la grossesse (si grossesse)",
* type="string",
* example= "2021-01-01"
* ),
* @OA\Property(
* property="pregnancy_end_at",
* description = "Date de fin de la grossese (si grossesse)",
* type="string",
* example= "2021-09-01"
* ),
* @OA\Property(property="performances",
* type="array",
* description="Listes des prestations",
* @OA\Items(ref="#/components/schemas/update_performance")
* ),
* @OA\Property(property="prescriptions",
* type="array",
* description="Listes des prescriptions medicales",
* @OA\Items(ref="#/components/schemas/update_prescription")
* ),
* @OA\Property(property="exams",
* type="array",
* description="Listes des examens",
* @OA\Items(ref="#/components/schemas/update_exam")
* )
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : "Consultation ou prescription mis à jour",
* "error":null
* }
* )
* )
* )
* @throws \App\Exceptions\AppException
*/
public function updateHealthCareSheet(Request $request, $id)
{
/**
* @OA\Schema(
* schema="update_performance",
* title = "Modifier une prestation",
* @OA\Property(property="id",
* type="integer",
* example = 1,
* description="ID de la prestation"
* ),
* @OA\Property(property="act_id",
* type="integer",
* example = 2,
* description="ID de l'acte "
* ),
* @OA\Property(property="amount",
* type="number",
* example=30000,
* description="Montant de la prestation"
* ),
* @OA\Property(property="home_visit_fees",
* type="number",
* example=5000,
* description="Frais de deplacement pour visiste à domicile "
* ),
* @OA\Property(property="to_delete",
* type="boolean",
* example=true,
* description="A supprimer"
* )
* )
*
* @OA\Schema(
* schema="update_prescription",
* title = "Modifier une prescription medicale",
* @OA\Property(property="id",
* type="integer",
* example = 1,
* description="ID de la prescription medicale"
* ),
* @OA\Property(property="drug_or_device_id",
* type="integer",
* example = 2,
* description="ID du medicament ou appareillage"
* ),
* @OA\Property(property="dosage",
* type="string",
* example="3 fois / jour pendant 1e semaine",
* description="Posologie ou frequence de consommation"
* ),
* @OA\Property(property="quantity",
* type="int",
* example=5,
* description="Quantité"
* ),
* @OA\Property(property="unit_price",
* type="number",
* example=3000,
* description="Prix unitaire"
* ),
* @OA\Property(property="to_delete",
* type="boolean",
* example=true,
* description="A supprimer"
* )
* )
*
* @OA\Schema(
* schema="update_exam",
* title = "Modifier un examen",
* @OA\Property(property="id",
* type="integer",
* example = 1,
* description="ID de l'examen"
* ),
* @OA\Property(property="act_id",
* type="integer",
* example = 2,
* description="ID de l'acte"
* ),
* @OA\Property(property="description",
* type="string",
* example="Une descrition de l'examen",
* description="Description de l'examene"
* ),
* @OA\Property(property="quantity",
* type="int",
* example=5,
* description="Quantité"
* ),
* @OA\Property(property="unit_price",
* type="number",
* example=5000,
* description="Prix unitaire"
* ),
* @OA\Property(property="to_delete",
* type="boolean",
* example=true,
* description="A supprimer"
* )
* )
*/
$this->validate($request, [
'network_agent_id' => 'required|integer|exists:networks_agents,id',
'password' => 'required|string',
// 'beneficiary_id' => 'nullable|int|exists:nh_having_rights,id',
'practitioner_lastname' => 'nullable|string',
'practitioner_firstname' => 'nullable|string',
'practitioner_provider_class_id' => 'nullable|integer',
'care_condition' => 'nullable|in:CURRENT_AFFECTION,LONG_TERM_AFFECTION,EXONERATION',
'accident_date' => 'nullable|date_format:Y-m-d|before:today',
'pregnancy_start_at' => 'nullable|date_format:Y-m-d|before:today',
'pregnancy_end_at' => 'nullable|date_format:Y-m-d|after:pregnancy_start_at',
'performances' => 'nullable|array',
'performances.*.id' => 'nullable|integer|exists:nh_performances,id',
'performances.*.act_id' => 'required_with:performances.*.id|integer|exists:nh_acts,id',
'performances.*.amount' => 'required_with:performances.*.id|numeric',
'performances.*.home_visit_fees' => 'nullable|numeric',
'performances.*.to_delete' => 'nullable|boolean',
'prescriptions' => 'nullable|array',
'prescriptions.*.id' => 'nullable|integer|exists:nh_medical_prescriptions,id',
'prescriptions.*.drug_or_device_id' => 'required_with:prescriptions.*.id|integer|exists:nh_drugs_and_devices,id',
'prescriptions.*.dosage' => 'required_with:prescriptions.*.id|string',
'prescriptions.*.quantity' => 'required_with:prescriptions.*.id|integer',
'prescriptions.*.unit_price' => 'nullable|numeric',
'prescriptions.*.to_delete' => 'nullable|boolean',
'exams' => 'nullable|array',
'exams.*.id' => 'nullable|integer|exists:nh_exams,id',
'exams.*.act_id' => 'required_with:exams.*.id|integer|exists:nh_acts,id',
'exams.*.description' => 'required_with:exams.*.id|string',
'exams.*.quantity' => 'required_with:exams.*.id|integer',
'exams.*.unit_price' => 'nullable|numeric',
'exams.*.to_delete' => 'nullable|boolean',
]);
$sheet = NhHealthCareSheet::where('id', $id)->where('state', InsuranceSubscriptionState::UNDER_VALIDATION)->first();
if (!isset($sheet)) {
return $this->errorResponse(__('errors.sheet_cannot_be_modified'));
}
if ($sheet->network_agent_id != $request->input('network_agent_id')) {
return $this->errorResponse(__('errors.unauthorized_to_update_sheet'), 403);
}
$this->agentCredentialsVerification($request->input('network_agent_id'), $request->input('password'));
// $beneficiary_id = $request->input('beneficiary_id');
// if (!empty($beneficiary_id)) {
// $beneficiary = $sheet->insurance->beneficiaries()->where('nh_having_rights.id', $beneficiary_id)->first();
// if (!isset($beneficiary)) {
// return $this->errorResponse(trans('errors.beneficiary_not_found'));
// }
// $sheet->beneficiary_id = $beneficiary_id;
// }
$nhConfig = NhNetworksConfig::where('network_id', $sheet->insurance->network_id)->first();
if (!isset($nhConfig)) {
return $this->errorResponse(trans('errors.nano_health_not_activated'));
}
$parts = $this->getConfigInsuranceParts($nhConfig, $request->input('care_condition', $sheet->care_condition));
$currency_code = $this->getNetworkCurrency($sheet->insurance->network_id);
$performances = $request->input('performances', []);
$prescriptions = $request->input('prescriptions', []);
$exams = $request->input('exams', []);
$performancesIds = array_map(function ($r) {
return $r['id'] ?? null;
}, $performances);
$prescriptionsIds = array_map(function ($r) {
return $r['id'] ?? null;
}, $prescriptions);
$examsIds = array_map(function ($r) {
return $r['id'] ?? null;
}, $exams);
try {
DB::beginTransaction();
$datetime = $this->getCurrentTimeByCountryCode($sheet->insurance->network->country->code_country);
$sheet->updated_at = $datetime;
$sheet->practitioner_lastname = $request->input('practitioner_lastname', $sheet->practitioner_lastname);
$sheet->practitioner_firstname = $request->input('practitioner_firstname', $sheet->practitioner_firstname);
$sheet->practitioner_provider_class_id = $request->input('practitioner_provider_class_id', $sheet->practitioner_provider_class_id);
if ($sheet->type == HealthCareSheetType::CONSULTATION) {
$accident_date = $request->input('accident_date');
$pregnancy_start_at = $request->input('pregnancy_start_at');
$pregnancy_end_at = $request->input('pregnancy_end_at');
$sheet->care_condition = $request->input('care_condition', $sheet->care_condition);
$sheet->accident_date = !empty($accident_date) ? $accident_date : null;
$sheet->pregnancy_start_at = !empty($pregnancy_start_at) ? $pregnancy_start_at : null;
$sheet->pregnancy_end_at = !empty($pregnancy_end_at) ? $pregnancy_end_at : null;
// if (isset($beneficiary)) {
// $sheet->patient_lastname = $beneficiary->lastname;
// $sheet->patient_firstname = $beneficiary->firstname;
// $sheet->patient_situation = 'HAVING_RIGHT';
// }
foreach ($request->input('performances', []) as $p) {
if (!empty($p['to_delete'])) {
NhPerformance::find($p['id'])->delete();
NhHealthCareSheetsPerformance::where('sheet_id', $sheet->id)->where('performance_id', $p['id'])->delete();
continue;
}
if (!empty($p['id'])) {
$shPerformance = NhHealthCareSheetsPerformance::where('sheet_id', $sheet->id)->where('performance_id', $p['id'])->first();
if (!isset($shPerformance)) {
return $this->errorResponse(__('errors.performance_not_belong_to_sheet', ['id' => array_search($p['id'], $performancesIds) + 1]));
}
$performance = NhPerformance::findOrFail($p['id']);
} else {
$performance = new NhPerformance();
$performance->created_at = $datetime;
}
$performance->act_id = !empty($p['act_id']) ? $p['act_id'] : $performance->act_id;
$performance->home_visit_fees = !empty($p['home_visit_fees']) ? $p['home_visit_fees'] : $performance->home_visit_fees;
$fees = !empty($performance->home_visit_fees) ? $performance->home_visit_fees : 0;
if (!empty($p['amount'])) {
$performance->amount = $p['amount'];
$performance->moderator_ticket = $parts->insured_part * ($p['amount'] + $fees); // to calculate,
$performance->insurance_amount = $parts->insurer_part * ($p['amount'] + $fees); // to calculate, montant de l'assurance
}
$performance->updated_at = $datetime;
$performance->save();
if (empty($p['id'])) {
NhHealthCareSheetsPerformance::create([
'sheet_id' => $sheet->id,
'performance_id' => $performance->id,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
}
}
}
foreach ($request->input('prescriptions', []) as $p) {
if (!empty($p['to_delete'])) {
NhMedicalPrescription::find($p['id'])->delete();
NhHealthCareSheetsPrescription::where('sheet_id', $sheet->id)->where('prescription_id', $p['id'])->delete();
continue;
}
if (!empty($p['id'])) {
$shPrescription = NhHealthCareSheetsPrescription::where('sheet_id', $sheet->id)->where('prescription_id', $p['id'])->first();
if (!isset($shPrescription)) {
return $this->errorResponse(__('errors.prescription_not_belong_to_sheet', ['id' => array_search($p['id'], $prescriptionsIds) + 1]));
}
$prescription = NhMedicalPrescription::findOrFail($p['id']);
} else {
$prescription = new NhMedicalPrescription();
$prescription->created_at = $datetime;
}
if ($sheet->type == HealthCareSheetType::CONSULTATION) {
$prescription->drug_or_device_id = !empty($p['drug_or_device_id']) ? $p['drug_or_device_id'] : $prescription->drug_or_device_id;
$prescription->dosage = !empty($p['dosage']) ? $p['dosage'] : $prescription->dosage;
$prescription->quantity = !empty($p['quantity']) ? $p['quantity'] : $prescription->quantity;
} else {
if (!empty($p['unit_price'])) {
$prescription->unit_price = $p['unit_price'];
$prescription->insured_paid_amount = $parts->insured_part * $prescription->unit_price * ($prescription->quantity ?? 1);
$prescription->insurer_paid_amount = $parts->insurer_part * $prescription->unit_price * ($prescription->quantity ?? 1);
}
}
$prescription->updated_at = $datetime;
$prescription->save();
if (empty($p['id'])) {
NhHealthCareSheetsPrescription::create([
'sheet_id' => $sheet->id,
'prescription_id' => $prescription->id,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
}
}
foreach ($request->input('exams', []) as $p) {
if (!empty($p['to_delete'])) {
NhExam::find($p['id'])->delete();
NhHealthCareSheetsExam::where('sheet_id', $sheet->id)->where('exam_id', $p['id'])->delete();
continue;
}
if (!empty($p['id'])) {
$shExam = NhHealthCareSheetsExam::where('sheet_id', $sheet->id)->where('exam_id', $p['id'])->first();
if (!isset($shExam)) {
return $this->errorResponse(__('errors.prescription_not_belong_to_sheet', ['id' => array_search($p['id'], $examsIds) + 1]));
}
$exam = NhExam::findOrFail($p['id']);
} else {
$exam = new NhExam();
$exam->created_at = $datetime;
}
if ($sheet->type == HealthCareSheetType::CONSULTATION) {
$exam->act_id = !empty($p['act_id']) ? $p['act_id'] : $exam->act_id;
$exam->description = !empty($p['description']) ? $p['description'] : $exam->description;
$exam->quantity = !empty($p['quantity']) ? $p['quantity'] : $exam->quantity;
} else {
if (!empty($p['unit_price'])) {
$exam->unit_price = $p['unit_price'];
$exam->insured_paid_amount = $parts->insured_part * $exam->unit_price * ($exam->quantity ?? 1);
$exam->insurer_paid_amount = $parts->insurer_part * $exam->unit_price * ($exam->quantity ?? 1);
}
}
$exam->updated_at = $datetime;
$exam->save();
if (empty($p['id'])) {
NhHealthCareSheetsExam::create([
'sheet_id' => $sheet->id,
'exam_id' => $exam->id,
'created_at' => $datetime, 'updated_at' => $datetime,
]);
}
}
$currentInsuranceAmount = $sheet->insurance_amount;
// Calculer les parts de l'assurance et l'assuré pour cette feuille de soins
$this->calculateInsuranceAmounts($sheet);
// Verification de la limite de couverture
$this->verifyInsuranceCoverageAmount($nhConfig, $sheet->insurance, $sheet, $sheet->beneficiary, $currency_code, $currentInsuranceAmount);
// Mettre à jour la couverture d'assurance de l'assuré
$this->updateInsuranceCoverageAmount($sheet, $sheet->insurance, $datetime, $sheet->beneficiary, $currentInsuranceAmount);
$sheet->save();
DB::commit();
return $this->successResponse(trans('messages.consultation_or_prescription_updated'));
} catch (AppException $e) {
return $this->errorResponse($e->getMessage(), $e->getCode());
} catch (Throwable $e) {
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
DB::rollBack();
return $this->errorResponse(trans('errors.unexpected_error'), 500);
}
}
private function generateSheetID(): string
{
do {
$code = generateTransactionCode();
$codeCorrect = NhHealthCareSheet::where('health_care_sheet_id', $code)->count() < 0;
} while ($codeCorrect);
return $code;
}
/**
* @param $sheet
* @return void
*/
private function formalizeHealthCareSheet($sheet): void
{
$sheet->state = trans('states.' . $sheet->state);
$sheet->patient_situation = trans('states.' . $sheet->patient_situation);
$sheet->_care_condition = $sheet->care_condition;
$sheet->care_condition = trans('states.' . $sheet->care_condition);
$sheet->insurance_amount = $this->toMoneyWithCurrencyCode($sheet->insurance_amount, $sheet->currency_code);
$sheet->insured_amount = $this->toMoneyWithCurrencyCode($sheet->insured_amount, $sheet->currency_code);
foreach ($sheet->performances as $p) {
$p->amount_formatted = $this->toMoneyWithCurrencyCode($p->amount, $sheet->currency_code);
$p->moderator_ticket_formatted = $this->toMoneyWithCurrencyCode($p->moderator_ticket, $sheet->currency_code);
$p->insurance_amount_formatted = $this->toMoneyWithCurrencyCode($p->insurance_amount, $sheet->currency_code);
$p->home_visit_fees_formatted = isset($p->home_visit_fees) ? $this->toMoneyWithCurrencyCode($p->home_visit_fees, $sheet->currency_code) : null;
}
foreach ($sheet->exams as $e) {
$this->formatExamAndPrescriptionAmounts($e, $sheet);
}
foreach ($sheet->prescriptions as $p) {
$this->formatExamAndPrescriptionAmounts($p, $sheet);
}
}
/**
* @OA\Post(
* path="/health-care-sheets/check-insurance-coverage-amount",
* summary="Verifier si une ligne de la feuille est applicable",
* tags={"Feuilles de soins"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* schema="check_insurance_coverage_amount",
* title = "Verifier si une ligne de la feuille est applicable",
* @OA\Property(
* property="tmp_sheet_id",
* description = "ID de temporaire de le feuille de soins generrée par le frontend",
* type="string",
* example= "XXXXXXXXXXXXXXXXXXX"
* ),
* @OA\Property(
* property="insurance_id",
* description = "ID de l'assurance",
* type="integer",
* example= 4
* ),
* @OA\Property(
* property="beneficiary_id",
* description = "ID du beneficiaire , s'il s'agit d'une feuille de soins pour beneficiaire",
* type="integer",
* example= 4
* ),
* @OA\Property(
* property="care_condition",
* description = "Condition de prise en charge",
* type="string",
* enum={"CURRENT_AFFECTION","LONG_TERM_AFFECTION","EXONERATION"},
* example= "CURRENT_AFFECTION"
* ),
* @OA\Property(
* property="act_action",
* description = "Action effectuéé sur la feuille de soins",
* type="string",
* enum={"INSERT","UPDATE"},
* example= "INSERT"
* ),
* @OA\Property(
* property="act_type",
* description = "Type d'acte qui correspond au type de la ligne dans la feuille de soins",
* type="string",
* enum={"PRESCRIPTION","EXAM","PRESCRIPTION"},
* example= "PRESCRIPTION"
* ),
* @OA\Property(
* property="act_id",
* description = "Id de l'acte",
* type="integer",
* example= 10
* ),
* @OA\Property(property="performances",
* type="array",
* description="Listes des prestations",
* @OA\Items(ref="#/components/schemas/check_insurance_performances")
* ),
* @OA\Property(property="prescriptions",
* type="array",
* description="Listes des prescriptions medicales",
* @OA\Items(ref="#/components/schemas/check_insurance_prescriptions")
* ),
* @OA\Property(property="exams",
* type="array",
* description="Listes des examens",
* @OA\Items(ref="#/components/schemas/check_insurance_exams")
* )
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : "Acceptable",
* "error":null
* }
* )
* )
* )
* @throws \App\Exceptions\AppException
*/
// Ce route sera appélé à chaque insertion/modification de prestations, examens ou prescriptions dans une feuille de soins
public function checkInsuranceCoverageAmount(Request $request)
{
/**
* @OA\Schema(
* schema="check_insurance_performances",
* @OA\Property(property="amount",
* type="number",
* example=30000,
* description="Montant de la prestation"
* ),
* @OA\Property(property="home_visit_fees",
* type="number",
* example=5000,
* description="Frais de deplacement pour visiste à domicile "
* ),
* )
*
* @OA\Schema(
* schema="check_insurance_prescriptions",
* @OA\Property(property="quantity",
* type="int",
* example=5,
* description="Quantité"
* ),
* @OA\Property(property="unit_price",
* type="number",
* example=3000,
* description="Prix unitaire"
* )
* )
*
* @OA\Schema(
* schema="check_insurance_exams",
* @OA\Property(property="quantity",
* type="int",
* example=5,
* description="Quantité"
* ),
* @OA\Property(property="unit_price",
* type="number",
* example=5000,
* description="Prix unitaire"
* )
* )
*/
$this->validate($request, [
'tmp_sheet_id' => 'required|string',// Temporal sheet ID generate by frontend
'insurance_id' => 'required|exists:nh_insurances,id',
'beneficiary_id' => 'nullable|exists:nh_having_rights,id',
'care_condition' => 'required|in:CURRENT_AFFECTION,LONG_TERM_AFFECTION,EXONERATION',
'act_action' => 'required|in:INSERT,UPDATE', // Insertion ou modification de l'acte ( Create ou modification de la feuille de soins)
'act_type' => 'required|in:PERFORMANCE,EXAM,PRESCRIPTION',
'act_id' => 'required_if:act_action,UPDATE|integer', // Requis lors de la modification de la feuille de soins (UPDATE)
'performances' => 'required_if:act_type,PERFORMANCE|array',
'performances.*.amount' => 'required_if:act_type,PERFORMANCE|numeric',
'performances.*.home_visit_fees' => 'nullable|numeric',
'prescriptions' => 'required_if:act_type,PRESCRIPTION|array',
'prescriptions.*.quantity' => 'required|integer|min:1',
'prescriptions.*.unit_price' => 'required|numeric',
'exams' => 'required_if:act_type,EXAM|array',
'exams.*.quantity' => 'required|integer|min:1',
'exams.*.unit_price' => 'required|numeric',
]);
$beneficiary = NhHavingRight::find($request->input('beneficiary_id'));
$insurance = NhInsurance::find($request->input('insurance_id'));
$act_id = $request->input('act_id');
$act_action = $request->input('act_action');
$act_type = $request->input('act_type');
$performances = $request->input('performances', []);
$exams = $request->input('exams', []);
$prescriptions = $request->input('prescriptions', []);
if (sizeof($performances) > 1 || sizeof($exams) > 1 || sizeof($prescriptions) > 1) {
return $this->errorResponse("La verification se fait sur une seule ligne à la fois");
}
$nhConfig = NhNetworksConfig::where('network_id', $insurance->network_id)->first();
if (!isset($nhConfig)) {
return $this->errorResponse(trans('errors.nano_health_not_activated'));
}
$monthPrice = $nhConfig->monthsPricesGrid()->where('nh_network_config_id', $nhConfig->id)
->where('number_of_months', $insurance->number_of_months)->first();
if (!isset($monthPrice))
return $this->errorResponse(trans('errors.month_price_grid_not_found'));
$parts = $this->getConfigInsuranceParts($nhConfig, $request->input('care_condition'));
$currency_code = $this->getNetworkCurrency($insurance->network_id);
$insurance_amount = 0;
switch ($act_type) {
case 'PERFORMANCE':
foreach ($performances as $p) {
$fees = !empty($p['home_visit_fees']) ? $p['home_visit_fees'] : 0;
$insurance_amount += ($parts->insurer_part * ($p['amount'] + $fees));
}
$act = NhPerformance::find($act_id);
break;
case 'EXAM':
foreach ($exams as $e) {
$insurance_amount += ($parts->insurer_part * $e['unit_price'] * $e['quantity']);
}
$act = NhExam::find($act_id);
break;
case 'PRESCRIPTION':
foreach ($prescriptions as $p) {
$insurance_amount += ($parts->insurer_part * $p['unit_price'] * $p['quantity']);
}
$act = NhMedicalPrescription::find($act_id);
break;
default:
return $this->errorResponse(trans('errors.unexpected_error'));
}
// Montant temporaire de la feuille de soins
$tmp_sheet_amount = NhTmpHealthCareSheet::where('sheet_id', $request->input('tmp_sheet_id'))->sum('insurance_amount');
$insurance_coverage_amount = isset($beneficiary) ? $beneficiary->insurance_coverage_amount : $insurance->insurance_coverage_amount;
$current_insurance_amount = 0;
if ($act_action == 'UPDATE') {
if (!isset($act)) {
return $this->errorResponse(trans('errors.act_not_found'));
}
// En cas de modification d'une feuille de soins, considéré le montant de couverture actuel de l'acte deja pris en compte
switch ($act_type) {
case 'PERFORMANCE':
$current_insurance_amount = $act->insurance_amount;
break;
case 'EXAM':
case 'PRESCRIPTION':
$current_insurance_amount = $act->insurer_paid_amount;
break;
}
}
if (!$nhConfig->family_coverage_sharing) {
// Montant de l'assurance deja consomé à date
$insurance_consumed_amount = $insurance_coverage_amount + $tmp_sheet_amount;
$total_insurance_amount = $insurance_consumed_amount + $insurance_amount - $current_insurance_amount;
if ($total_insurance_amount > $monthPrice->max_insurance_coverage_amount) {
return $this->errorResponse(trans('errors.insurance_coverage_amount_exceeded', [
'consumption' => $this->toMoneyWithCurrencyCode($insurance_consumed_amount, $currency_code),
'remaining' => $this->toMoneyWithCurrencyCode($monthPrice->max_insurance_coverage_amount - $insurance_consumed_amount, $currency_code),
]));
}
} else {
// Montant de l'assurance deja consomé à date
$insurance_consumed_amount = $insurance->insurance_coverage_amount + $tmp_sheet_amount;
foreach ($insurance->beneficiaries as $b) {
$insurance_consumed_amount += $b->insurance_coverage_amount;
}
$total_insurance_amount = $insurance_consumed_amount + $insurance_amount - $current_insurance_amount;
$family_limit_amount = $monthPrice->max_insurance_coverage_amount * ($insurance->number_of_beneficiaries + 1);
if ($total_insurance_amount > $family_limit_amount) {
return $this->errorResponse(trans('errors.insurance_coverage_amount_exceeded', [
'consumption' => $this->toMoneyWithCurrencyCode($insurance_consumed_amount, $currency_code),
'remaining' => $this->toMoneyWithCurrencyCode($family_limit_amount - $insurance_consumed_amount, $currency_code),
]));
}
}
NhTmpHealthCareSheet::create([
'sheet_id' => $request->input('tmp_sheet_id'),
'insurance_amount' => $insurance_amount
]);
return $this->successResponse("Can be applied");
}
}