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={"Assurances"}, * 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="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, [ 'network_id' => 'required|integer|exists:networks,id', 'month_price_id' => 'required|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' ]); $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(); if (!isset($monthPrice)) return $this->errorResponse(trans('errors.incorrect_selected_amount')); $bonus = $monthPrice->min_amount; foreach ($request->input('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={"Assurances"}, * 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="integer", * example=300, * 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')); // 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(); $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; $subscription->state = InsuranceSubscriptionState::UNDER_VALIDATION; $subscription->save(); $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->save(); } $subscription->total_bonus_amount = ($subscription->bonus_amount + $beneficiariesBonus); $subscription->save(); NhInsurancesSubscriptionsHistory::create([ 'action' => 'ADD', 'insurance_subscription_id' => $subscription->insurance_subscription_id, 'insurance_subscription_state' => $subscription->state, 'insurance_subscription' => json_encode($subscription) ]); 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 l'assurance", * tags={"Assurances"}, * 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:8192' ]); $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); } } private function generateSubscriptionID(): string { do { $code = $this->generateTransactionCode(); $codeCorrect = NhInsurancesSubscription::where('insurance_subscription_id', $code)->count() < 0; } while ($codeCorrect); return $code; } }