nanosanteservice/app/Http/Controllers/InsuranceController.php

785 lines
38 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Events\InsuranceEvent;
use App\Events\InsuranceSubscriptionAccepted;
use App\InsuranceSubscriptionAffiliation;
use App\InsuranceSubscriptionState;
use App\Models\CountriesCurrency;
use App\Models\Identification;
use App\Models\NhInsurancesHavingRight;
use App\Models\NhInsurancesSubscription;
use App\Models\NhInsurancesSubscriptionsHistory;
use App\Models\NhMonthsPricesGrid;
use App\Models\NhNetworksConfig;
use App\Models\User;
use App\Traits\Helper;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;
use Throwable;
class InsuranceController extends Controller
{
use Helper;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* @OA\Get(
* path="/insurances",
* summary="Afficher la liste des assurances ( par pays )",
* tags={"Assurances"},
* security={{"api_key":{}}},
* @OA\Parameter(
* parameter="country_id",
* name="country_id",
* description="ID du pays",
* in="query",
* required=true,
* @OA\Schema(
* type="integer",
* default=78
* )
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : {{"id":250,"name":"Cnamgs-pharmacies", "age_limit_of_insured_and_spouse" : 30 ,
* "age_limit_of_child_beneficiary": 25 , "max_number_of_beneficiaries":"5", "months_prices":{{"id": 1,"number_of_months":"3","min_amount":"150000 XAF"}}}},
* "error":null
* }
* )
* )
* )
*/
public function getInsurances(Request $request)
{
$this->validate($request, [
'country_id' => 'nullable|integer|exists:countries,id'
]);
$country = CountriesCurrency::findOrFail($request->input('country_id'));
$insurances = DB::select("SELECT n.id , n.name , nhc.age_limit_of_insured_and_spouse, nhc.age_limit_of_child_beneficiary, nhc.max_number_of_beneficiaries, nhc.id as nhc_id
FROM networks n JOIN configWallet cw ON cw.id_network = n.id JOIN nh_networks_configs nhc
ON nhc.network_id = n.id WHERE n.country_id = :countryId AND cw.type = 'ilink_sante' AND n.status = 1", ['countryId' => $request->input('country_id')]);
foreach ($insurances as $insurance) {
$months_prices = DB::select("SELECT id, number_of_months , min_amount FROM nh_months_prices_grid WHERE nh_network_config_id = :nhc_id",
['nhc_id' => $insurance->nhc_id]);
foreach ($months_prices as $mp) {
$mp->min_amount = $this->toMoneyWithCurrencyCode($mp->min_amount, $country->currency_code ?? 'XAF');
}
$insurance->months_prices = $months_prices;
unset($insurance->nhc_id);
}
return $this->successResponse($insurances);
}
/**
* @OA\Post(
* path="/insurances/subscriptions/bonus-amount",
* summary="Calculer le montant de la prime",
* tags={"Souscriptions à l'assurance"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(property="subscription_id",
* type="integer",
* example = 2,
* description="ID de la souscription"
* ),
* @OA\Property(property="network_id",
* type="integer",
* example = 250,
* description="ID du reseau de l'assureur"
* ),
* @OA\Property(property="month_price_id",
* type="integer",
* example=2,
* description="ID de la grille de prix choisit lors de la souscription"
* ),
* @OA\Property(
* property="beneficiaries",
* description="Listes de quelques infos sur les beneficiaires ou ayants droit",
* example = {{"birthdate":"1998-10-05","affiliation":"CHILD"}}
* ),
* ),
* example = {"network_id":250,"month_price_id":3,"beneficiaries":{{"birthdate":"1998-10-05","affiliation":"CHILD"}}}
* )
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {"status":200,"response":{"bonus_amount":75000,"bonus_amount_formatted":"75 000FCFA"},"error":null},
* )
* )
* )
*/
public function calculateBonusAmount(Request $request)
{
$this->validate($request, [
'subscription_id' => 'nullable|integer|exists:nh_insurances_subscriptions,id',
'network_id' => 'required_without:subscription_id|integer|exists:networks,id',
'month_price_id' => 'required_without:subscription_id|integer|exists:nh_months_prices_grid,id',
'beneficiaries' => 'nullable|array',
'beneficiaries.*.birthdate' => 'required|date_format:Y-m-d|before:today',
'beneficiaries.*.affiliation' => 'required|in:CHILD,SPOUSE'
]);
if ($request->has('subscription_id')) {
$subscription = NhInsurancesSubscription::findOrFail($request->input('subscription_id'));
$networkConfig = $subscription->nhNetworkConfig;
$monthPrice = $networkConfig->monthsPricesGrid()->where('number_of_months', $subscription->number_of_months)->first();
$beneficiaries = array_merge($subscription->beneficiaries->toArray(), $request->input('beneficiaries'));
} else {
$networkConfig = NhNetworksConfig::where('network_id', $request->input('network_id'))->first();
if (!isset($networkConfig) || $networkConfig->configWallet->type != 'ilink_sante')
return $this->errorResponse(trans('errors.nano_health_not_activated'));
$monthPrice = $networkConfig->monthsPricesGrid()->where('id', $request->input('month_price_id'))->first();
$beneficiaries = $request->input('beneficiaries');
}
if (!isset($monthPrice))
return $this->errorResponse(trans('errors.incorrect_selected_amount'));
$bonus = $monthPrice->min_amount;
foreach ($beneficiaries as $b) {
$bonus += $this->calculateBeneficiaryBonusAmount(new NhInsurancesHavingRight($b), $networkConfig->yearsPricesGrid, $monthPrice);
}
return $this->successResponse([
'bonus_amount' => $bonus,
'bonus_amount_formatted' => $this->toMoneyWithNetwork($bonus, $request->input('network_id'))
]);
}
// Caculer le montant de la prime d'un ayant droit ou beneficiaire
private function calculateBeneficiaryBonusAmount(NhInsurancesHavingRight $beneficiary, Collection $yearsPricesGrid,
NhMonthsPricesGrid $monthPrice)
{
$bonus = 0;
if ($beneficiary->affiliation == 'CHILD') {
$age = date_diff(date_create($beneficiary->birthdate), date_create('now'))->y;
$levels = $yearsPricesGrid->filter(function ($level) use ($age) {
return $level->min_age <= $age && $level->max_age >= $age;
});
foreach ($levels as $level) {
$bonus += (100 + $level->markup_percentage) * $monthPrice->min_amount / 100;
}
} else {
$bonus = $monthPrice->min_amount;
}
return $bonus;
}
/**
* @OA\Post(
* path="/insurances/subscriptions",
* summary="Souscrire à une assurance",
* tags={"Souscriptions à l'assurance"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/subscribe_incurance"),
* example = {"network_id":250,"user_id":20,"password" : "1234", "month_price_id":3,"beneficiaries":{{"lastname":"Djery","firstname":"DI","gender":"M","birthdate":"2001-10-05",
* "affiliation":"CHILD","birthdate_proof":"CERTIFIED_COPY","birthdate_proof_doc":"birth.jpg","justice_doc":"just.png","marriage_certificate_doc":"mariage.png",
* "id_document_type":"CNI","id_document_front":"cni_front.jpg","id_document_back":"cni_front.jpg"}}}
* )
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {"status":200,"response":"Transaction réussie","error":null}
* )
* )
* )
*/
public function subscribe(Request $request)
{
/**
* @OA\Schema(
* schema="subscribe_incurance",
* title = "Souscription à une assurance",
* required={"network_id", "user_id" , "password", "month_price_id", "beneficiaries"},
* @OA\Property(property="network_id",
* type="integer",
* example = 250,
* description="ID du reseau de l'assureur"
* ),
* @OA\Property(property="user_id",
* type="integer",
* example=300,
* description="ID l'utilisateur identifié"
* ),
* @OA\Property(property="password",
* type="string",
* example="20214666",
* description="Mot de passe de l'utilisateur identifié"
* ),
* @OA\Property(property="month_price_id",
* type="integer",
* example=2,
* description="ID de la grille de prix choisit lors de la souscription"
* ),
* @OA\Property(property="beneficiaries",
* type="array",
* description="Listes des beneficiaires ou ayants droit",
* @OA\Items(ref="#/components/schemas/beneficiaries")
* )
* )
*
* @OA\Schema(
* schema="beneficiaries",
* title = "Beneficiaires ou ayants droit",
* required={"lastname","gender", "birthdate", "affiliation" },
* @OA\Property(property="lastname",
* type="string",
* example = "Djery",
* description="Noms"
* ),
* @OA\Property(property="firstname",
* type="string",
* example="DI",
* description="Prenoms"
* ),
* @OA\Property(property="gender",
* type="string",
* enum = {"M" ,"F"},
* example= "M",
* description="Sexe"
* ),
* @OA\Property(property="birthdate",
* type="string",
* example= "2001-10-05",
* description="Date de naissance"
* ),
* @OA\Property(property="affiliation",
* type="string",
* enum = {"CHILD" ,"SPOUSE"},
* example= "CHILD",
* description="Affiliation"
* ),
* @OA\Property(property="birthdate_proof",
* type="string",
* enum = {"CERTIFIED_COPY" ,"CERTIFICATE"},
* example="CERTIFIED_COPY",
* description="Copie légalisée acte de naissance ou certificat de naissance"
* ),
* @OA\Property(property="birthdate_proof_doc",
* type="string",
* example="birthdate_proof_doc.jpg",
* description="Copie légalisée acte de naissance ou certificat de naissance"
* ),
* @OA\Property(property="justice_doc",
* type="string",
* example="justice_doc.jpg",
* description="Une page document de justice si enfant adopté ou sous tutelle"
* ),
* @OA\Property(property="marriage_certificate_doc",
* type="string",
* example="marriage_certificate_doc.jpg",
* description="Une page de l'acte de mariage"
* ),
* @OA\Property(property="id_document_type",
* type="string",
* example="CNI",
* description="Type de piece d'identité cni , carte sejour, permis"
* ),
* @OA\Property(property="id_document_front",
* type="string",
* example="id_document_front.jpg",
* description="Pièce identité recto"
* ),
* @OA\Property(property="id_document_back",
* type="string",
* example="id_document_back.jpg",
* description="Pièce identité verso"
* ),
* )
*/
$this->validate($request, [
'network_id' => 'required|integer|exists:networks,id',
'user_id' => 'required|integer|exists:users,id',
'password' => 'required|string',
'month_price_id' => 'required|integer|exists:nh_months_prices_grid,id',
'beneficiaries' => 'nullable|array',
'beneficiaries.*.lastname' => 'required|string',
'beneficiaries.*.gender' => 'required|in:M,F',
'beneficiaries.*.birthdate' => 'required|date_format:Y-m-d|before:today',
'beneficiaries.*.affiliation' => 'required|in:CHILD,SPOUSE',
'beneficiaries.*.birthdate_proof' => 'required_if:beneficiaries.*.affiliation,CHILD|in:CERTIFIED_COPY,CERTIFICATE',
'beneficiaries.*.birthdate_proof_doc' => 'required_if:beneficiaries.*.affiliation,CHILD|string',
'beneficiaries.*.justice_doc' => 'nullable|string',
'beneficiaries.*.marriage_certificate_doc' => 'required_if:beneficiaries.*.affiliation,SPOUSE|string',
'beneficiaries.*.id_document_type' => 'required_if:beneficiaries.*.affiliation,SPOUSE|string',
'beneficiaries.*.id_document_front' => 'required_if:beneficiaries.*.affiliation,SPOUSE|string',
'beneficiaries.*.id_document_back' => 'required_if:beneficiaries.*.affiliation,SPOUSE|string',
]);
$identification = Identification::where('id_user', $request->input('user_id'))->first();
if (!isset($identification) || $identification->status == 0)
return $this->errorResponse(trans('errors.user_identification_required'));
if (!$this->checkPassword($request->password, $identification->user->encrypted_password, $identification->user->salt))
return $this->errorResponse(trans('messages.incorrect_user_password'));
$networkConfig = NhNetworksConfig::where('network_id', $request->input('network_id'))->first();
if (!isset($networkConfig) || $networkConfig->configWallet->type != 'ilink_sante')
return $this->errorResponse(trans('errors.nano_health_not_activated'));
$currentSubscription = NhInsurancesSubscription::where('network_id', $request->input('network_id'))->where('user_id', $request->input('user_id'))
->whereNotIn('state', [InsuranceSubscriptionState::REJECTED, InsuranceSubscriptionState::STOPPED])->first();
if (isset($currentSubscription)) {
return $this->errorResponse(trans('errors.cannot_subscribe_again', ['state' => mb_strtolower(trans('states.' . $currentSubscription->state), 'UTF-8')]));
}
// Verification de l'age du beneficiaire
$insuredAge = date_diff(date_create($identification->birth_date), date_create('now'))->y;
if ($insuredAge > $networkConfig->age_limit_of_insured_and_spouse) {
return $this->errorResponse(trans('errors.minimal_age_required'));
}
$networkConfig = NhNetworksConfig::where('network_id', $request->input('network_id'))->first();
if (sizeof($request->input('beneficiaries')) > $networkConfig->max_number_of_beneficiaries)
return $this->errorResponse(trans('errors.number_of_beneficiaries_exceeded'));
$monthPrice = $networkConfig->monthsPricesGrid()->where('id', $request->input('month_price_id'))->first();
if (!isset($monthPrice))
return $this->errorResponse(trans('errors.incorrect_selected_amount'));
try {
DB::beginTransaction();
$datetime = $this->getCurrentTimeByCountryCode($networkConfig->network->country->code_country);
$subscription = new NhInsurancesSubscription($request->all());
$subscription->number_of_beneficiaries = sizeof($request->input('beneficiaries'));
$subscription->insurance_subscription_id = $this->generateSubscriptionID();
$subscription->number_of_months = $monthPrice->number_of_months;
$subscription->bonus_amount = $monthPrice->min_amount;
$beneficiariesBonus = $this->storeBeneficiariesAndGetBonus($subscription, $request, $networkConfig, $monthPrice, $datetime);
$subscription->total_bonus_amount = ($subscription->bonus_amount + $beneficiariesBonus);
$subscription->created_at = $subscription->updated_at = $datetime;
$subscription->save();
NhInsurancesSubscriptionsHistory::create([
'action' => 'ADD',
'insurance_subscription_id' => $subscription->insurance_subscription_id,
'insurance_subscription_state' => $subscription->state,
'insurance_subscription' => json_encode($subscription),
'created_at' => $datetime, 'updated_at' => $datetime,
]);
Event::dispatch(new InsuranceEvent($subscription, trans('messages.insurance_subscription'), trans('messages.insurance_subscription_mail', ['name' => $subscription->user->lastname, 'subscription_id' => $subscription->insurance_subscription_id,
'bonus_amount' => $this->toMoneyWithNetwork($subscription->total_bonus_amount, $subscription->network_id), 'number_of_beneficiaries' => $subscription->number_of_beneficiaries])));
DB::commit();
return $this->successResponse(trans('messages.insurance_subscription_successful'));
} catch (Throwable $e) {
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
DB::rollBack();
return $this->errorResponse(trans('errors.unexpected_error'), 500);
}
}
/**
* @OA\Post(
* path="/insurances/subscriptions/upload-images",
* summary="Uploader les images de la souscription à l'assurance",
* tags={"Souscriptions à l'assurance"},
* security={{"api_key":{}}},
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="multipart/form-data",
* @OA\Schema(
* @OA\Property(
* property="files[]",
* description = "Liste des documents à uploader",
* type="array",
* @OA\Items(type="string", format="binary")
* )
* ),
* )
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {"status":200,"response":"Transaction réussie","error":null}
* )
* )
* )
*/
public function uploadImages(Request $request)
{
$this->validate($request, [
'files' => 'required',
'files.*' => 'mimes:jpeg,png,jpg,jpeg|max:10240' // 10 Mb
]);
$files = [];
if ($request->hasfile('files')) {
foreach ($request->file('files') as $file) {
$filename = $this->uploadImage($file, 'NH', 'insurances-subscriptions-docs');
array_push($files, $filename);
}
}
return $this->successResponse($files);
}
public function validateSubscription($id, Request $request)
{
$this->validate($request, [
'agent_id' => 'required|integer|exists:agents,id'
]);
try {
DB::beginTransaction();
$subscription = NhInsurancesSubscription::findOrFail($id);
$subscription->state = InsuranceSubscriptionState::ACCEPTED;
$subscription->save();
NhInsurancesSubscriptionsHistory::create([
'action' => 'EDIT',
'insurance_subscription_id' => $subscription->insurance_subscription_id,
'insurance_subscription_state' => $subscription->state,
'agent_id' => $request->input('agent_id'),
'insurance_subscription' => json_encode($subscription)
]);
Event::dispatch(new InsuranceEvent($subscription, trans('messages.insurance_subscription_accepted'), trans('messages.insurance_subscription_accepted_mail', ['name' => $subscription->user->lastname, 'subscription_id' => $subscription->insurance_subscription_id,
'bonus_amount' => $this->toMoneyWithNetwork($subscription->total_bonus_amount, $subscription->network_id), 'user_code' => $subscription->user->user_code,
'number_of_beneficiaries' => $subscription->number_of_beneficiaries]), trans('messages.insurance_subscription_accepted_notification', ['subscription_id' => $subscription->insurance_subscription_id])));
DB::commit();
return $this->successResponse(trans('messages.successful_transaction'));
} catch (Throwable $e) {
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
DB::rollBack();
return $this->errorResponse(trans('errors.unexpected_error'), 500);
}
}
public function rejectSubscription($id, Request $request)
{
$this->validate($request, [
'agent_id' => 'required|integer|exists:agents,id',
'reason' => 'required'
]);
try {
DB::beginTransaction();
$subscription = NhInsurancesSubscription::findOrFail($id);
$subscription->reason = $request->input('reason');
$subscription->state = InsuranceSubscriptionState::REJECTED;
$subscription->save();
NhInsurancesSubscriptionsHistory::create([
'action' => 'EDIT',
'insurance_subscription_id' => $subscription->insurance_subscription_id,
'insurance_subscription_state' => $subscription->state,
'agent_id' => $request->input('agent_id'),
'insurance_subscription' => json_encode($subscription)
]);
Event::dispatch(new InsuranceEvent($subscription, trans('messages.insurance_subscription_rejected'), trans('messages.insurance_subscription_rejected_mail', ['name' => $subscription->user->lastname, 'subscription_id' => $subscription->insurance_subscription_id,
'bonus_amount' => $this->toMoneyWithNetwork($subscription->total_bonus_amount, $subscription->network_id), 'reason' => $request->input('reason'),
'number_of_beneficiaries' => $subscription->number_of_beneficiaries]), trans('messages.insurance_subscription_rejected_notification', ['subscription_id' => $subscription->insurance_subscription_id])));
DB::commit();
return $this->successResponse(trans('messages.successful_transaction'));
} catch (Throwable $e) {
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
DB::rollBack();
return $this->errorResponse(trans('errors.unexpected_error'), 500);
}
}
/**
* @OA\Get(
* path="/insurances/subscriptions",
* summary="Afficher la liste des souscriptions d'assurances ( par utilisateur , par type)",
* tags={"Souscriptions à l'assurance"},
* security={{"api_key":{}}},
* @OA\Parameter(
* parameter="user_id",
* name="user_id",
* description="ID de l'utilisateur",
* in="query",
* required=true,
* @OA\Schema(
* type="integer",
* default=325
* )
* ),
* @OA\Parameter(
* parameter="type",
* name="type",
* description="Type de souscription",
* in="query",
* required=true,
* @OA\Schema(
* type="string",
* enum={"ALL","EDITABLE"}
* )
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {
* "status" : 200,
* "response" : {{"id":1,"insurance_subscription_id":"BOKWRWZ245JX","network_id":250,"user_id":321,"number_of_months":3,
* "bonus_amount":"150\u202f000\u00a0FCFA","number_of_beneficiaries":2,"total_bonus_amount":"495\u202f000\u00a0FCFA","state":"EN COURS DE VALIDATION",
* "created_at":"2021-10-29T14:26:05.000000Z","updated_at":"2021-10-29T14:26:05.000000Z","start_at":null,"end_at":null,"reason":null,
* "beneficiaries":{{"id":1,"insurance_subscription_id":"BOKWRWZ245JX","lastname":"Djery","firstname":"DI","gender":"M","birthdate":"2001-10-05T00:00:00.000000Z",
* "affiliation":"CHILD","bonus_amount":"195\u202f000\u00a0FCFA","birthdate_proof":"CERTIFIED_COPY","birthdate_proof_doc":"birth.jpg","justice_doc":"just.png",
* "marriage_certificate_doc":null,"id_document_type":null,"id_document_front":null,"id_document_back":null,"deleted_at":null,"created_at":"2021-10-29T14:26:05.000000Z",
* "updated_at":"2021-10-29T14:26:05.000000Z","affiliation_tr":"ENFANT"}}}},
* "error":null
* }
* )
* )
* )
*/
public function getSubscriptions(Request $request)
{
$this->validate($request, [
'user_id' => 'nullable|integer|exists:users,id',
'type' => 'nullable|in:ALL,EDITABLE'
]);
$user = User::findOrFail($request->input('user_id'));
$currency_code = $user->network->country->currency_code;
$query = NhInsurancesSubscription::with(['network:id,name', 'beneficiaries']);
if ($request->has('user_id')) {
$query = $query->where('user_id', $request->input('user_id'));
}
if ($request->has('type')) {
$type = $request->input('type');
if ($type == 'EDITABLE') {
$query = $query->whereIn('state', [InsuranceSubscriptionState::UNDER_VALIDATION, InsuranceSubscriptionState::ACCEPTED]);
}
}
$subscriptions = $query->get();
foreach ($subscriptions as $subscription) {
$subscription->state = trans('states.' . $subscription->state);
$subscription->bonus_amount = $this->toMoneyWithCurrencyCode($subscription->bonus_amount, $currency_code);
$subscription->total_bonus_amount = $this->toMoneyWithCurrencyCode($subscription->total_bonus_amount, $currency_code);
foreach ($subscription->beneficiaries as $b) {
$b->bonus_amount = $this->toMoneyWithCurrencyCode($b->bonus_amount, $currency_code);
}
}
return $this->successResponse($subscriptions);
}
/**
* @OA\Put(
* path="/insurances/subscriptions/{id}",
* summary="Ajouter des ayants droits ou beneficiaires à une souscription",
* tags={"Souscriptions à l'assurance"},
* security={{"api_key":{}}},
* @OA\Parameter(
* parameter="id",
* name="id",
* description="ID de la souscription",
* in="path",
* required=true,
* @OA\Schema(
* type="integer",
* default=12
* )
* ),
* @OA\RequestBody(
* description="Corps de la requete",
* required=true,
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/add_beneficiaries"),
* example = {"password" : "1234", "beneficiaries":{{"lastname":"Djery","firstname":"DI","gender":"M","birthdate":"2001-10-05",
* "affiliation":"CHILD","birthdate_proof":"CERTIFIED_COPY","birthdate_proof_doc":"birth.jpg","justice_doc":"just.png","marriage_certificate_doc":"mariage.png",
* "id_document_type":"CNI","id_document_front":"cni_front.jpg","id_document_back":"cni_front.jpg"}}}
* )
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {"status":200,"response":"Transaction réussie","error":null}
* )
* )
* )
*/
public function addBeneficiaries(Request $request, $id)
{
/**
* @OA\Schema(
* schema="add_beneficiaries",
* title = "Ajouter des beneficiaires à une assurance",
* required={"password", "beneficiaries"},
* @OA\Property(property="password",
* type="string",
* example="2021469",
* description="Mot de passe de l'utilisateur assuré"
* ),
* @OA\Property(property="beneficiaries",
* type="array",
* description="Listes des beneficiaires ou ayants droit",
* @OA\Items(ref="#/components/schemas/beneficiaries")
* )
* )
*
*/
$this->validate($request, [
'password' => 'required|string',
'beneficiaries' => 'nullable|array',
'beneficiaries.*.lastname' => 'required|string',
'beneficiaries.*.gender' => 'required|in:M,F',
'beneficiaries.*.birthdate' => 'required|date_format:Y-m-d|before:today',
'beneficiaries.*.affiliation' => 'required|in:CHILD,SPOUSE',
'beneficiaries.*.birthdate_proof' => 'required_if:beneficiaries.*.affiliation,CHILD|in:CERTIFIED_COPY,CERTIFICATE',
'beneficiaries.*.birthdate_proof_doc' => 'required_if:beneficiaries.*.affiliation,CHILD|string',
'beneficiaries.*.justice_doc' => 'nullable|string',
'beneficiaries.*.marriage_certificate_doc' => 'required_if:beneficiaries.*.affiliation,SPOUSE|string',
'beneficiaries.*.id_document_type' => 'required_if:beneficiaries.*.affiliation,SPOUSE|string',
'beneficiaries.*.id_document_front' => 'required_if:beneficiaries.*.affiliation,SPOUSE|string',
'beneficiaries.*.id_document_back' => 'required_if:beneficiaries.*.affiliation,SPOUSE|string',
]);
$subscription = NhInsurancesSubscription::findOrFail($id);
if (!in_array($subscription->state, [InsuranceSubscriptionState::UNDER_VALIDATION, InsuranceSubscriptionState::ACCEPTED])) {
return $this->errorResponse(trans('errors.subscription_cannot_be_updated'));
}
$user = $subscription->user;
$identification = $subscription->user->identification;
if (!isset($identification) || $identification->status == 0)
return $this->errorResponse(trans('errors.user_identification_required'));
if (!$this->checkPassword($request->password, $user->encrypted_password, $user->salt))
return $this->errorResponse(trans('messages.incorrect_user_password'));
$nbOfBeneficiaries = $subscription->beneficiaries()->count();
$networkConfig = NhNetworksConfig::where('network_id', $subscription->network_id)->first();
if ((sizeof($request->input('beneficiaries')) + $nbOfBeneficiaries) > $networkConfig->max_number_of_beneficiaries)
return $this->errorResponse(trans('errors.number_of_beneficiaries_exceeded'));
$monthPrice = $networkConfig->monthsPricesGrid()->where('number_of_months', $subscription->number_of_months)->first();
if (!isset($monthPrice))
return $this->errorResponse(trans('errors.incorrect_selected_amount'));
try {
DB::beginTransaction();
$datetime = $this->getCurrentTimeByCountryCode($networkConfig->network->country->code_country);
$subscription->number_of_beneficiaries += sizeof($request->input('beneficiaries'));
$beneficiariesBonus = $this->storeBeneficiariesAndGetBonus($subscription, $request, $networkConfig, $monthPrice, $datetime);
$subscription->total_bonus_amount += $beneficiariesBonus;
$subscription->created_at = $subscription->updated_at = $datetime;
$subscription->save();
NhInsurancesSubscriptionsHistory::create([
'action' => 'EDIT',
'insurance_subscription_id' => $subscription->insurance_subscription_id,
'insurance_subscription_state' => $subscription->state,
'insurance_subscription' => json_encode($subscription),
'created_at' => $datetime, 'updated_at' => $datetime,
]);
Event::dispatch(new InsuranceEvent($subscription, trans('messages.insurance_subscription_updated'), trans('messages.insurance_subscription_mail', ['name' => $subscription->user->lastname, 'subscription_id' => $subscription->insurance_subscription_id,
'bonus_amount' => $this->toMoneyWithNetwork($subscription->total_bonus_amount, $subscription->network_id), 'number_of_beneficiaries' => $subscription->number_of_beneficiaries])));
DB::commit();
return $this->successResponse(trans('messages.insurance_subscription_updated_successful'));
} catch (Throwable $e) {
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
DB::rollBack();
return $this->errorResponse(trans('errors.unexpected_error'), 500);
}
}
private function generateSubscriptionID(): string
{
do {
$code = $this->generateTransactionCode();
$codeCorrect = NhInsurancesSubscription::where('insurance_subscription_id', $code)->count() < 0;
} while ($codeCorrect);
return $code;
}
private function storeBeneficiariesAndGetBonus(NhInsurancesSubscription $subscription, Request $request,
$networkConfig, NhMonthsPricesGrid $monthPrice, string $datetime)
{
$subscription->state = InsuranceSubscriptionState::UNDER_VALIDATION;
$beneficiariesBonus = 0;
foreach ($request->input('beneficiaries') as $b) {
$beneficiary = new NhInsurancesHavingRight($b);
$beneficiary->insurance_subscription_id = $subscription->insurance_subscription_id;
$beneficiary->bonus_amount = $this->calculateBeneficiaryBonusAmount($beneficiary, $networkConfig->yearsPricesGrid, $monthPrice);
$beneficiariesBonus += $beneficiary->bonus_amount;
if ($beneficiary->affiliation == InsuranceSubscriptionAffiliation::CHILD) {
$beneficiary->marriage_certificate_doc = null;
$beneficiary->id_document_type = null;
$beneficiary->id_document_back = null;
$beneficiary->id_document_front = null;
} else {
$beneficiary->justice_doc = null;
$beneficiary->birthdate_proof_doc = null;
$beneficiary->birthdate_proof = null;
}
$beneficiary->created_at = $beneficiary->updated_at = $datetime;
$beneficiary->save();
}
return $beneficiariesBonus;
}
}