nanosanteservice/app/Http/Controllers/InsuranceInvoiceController.php

407 lines
18 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. 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\InsuranceEvent;
use App\InsuranceAction;
use App\InsuranceInvoiceState;
use App\InsuranceState;
use App\InsuranceSubscriptionAffiliation;
use App\InsuranceSubscriptionState;
use App\Models\AgentPlus;
use App\Models\CountriesCurrency;
use App\Models\Identification;
use App\Models\NhHavingRight;
use App\Models\NhInsurance;
use App\Models\NhInsurancesHavingRight;
use App\Models\NhInsurancesInvoice;
use App\Models\NhInsurancesPayment;
use App\Models\NhInsurancesSubscription;
use App\Models\NhInsurancesSubscriptionsHistory;
use App\Models\NhMonthsPricesGrid;
use App\Models\NhNetworksConfig;
use App\Models\User;
use App\Models\Wallet;
use App\Rules\PasswordValidation;
use App\Traits\Helper;
use Carbon\Carbon;
use DateTime;
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 InsuranceInvoiceController extends Controller
{
/**
* @OA\Get(
* path="/insurances/invoices",
* summary="Afficher la liste des factures",
* tags={"Factures de 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="state",
* name="state",
* description="Etat de la facture",
* in="query",
* required=false,
* @OA\Schema(
* type="string",
* enum={"PAID","UNPAID"}
* )
* ),
* @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" : {{"id":1,"invoice_id":"SFSF6565656","insurance_id":5,"subscription_id":2,"amount":"495\u202f000 FCFA","next_payment_deadline":"2022-04-08 17:31:52","next_payment_reminder":"2022-04-05 17:31:52","state":"NON PAY\u00c9E",
* "reason":"ACTIVATION DE L'ASSURANCE","created_at":"2022-03-29T16:31:52.000000Z","updated_at":"2022-03-29T16:31:52.000000Z","insurance":{"id":5,"network_id":250,"user_id":349,"insured_id":"5DSTKZ7PQZX4","remaining_amount": "0 FCFA",
"paid_amount": "495000 FCFA","months_grid_id":77,"bonus_amount":"150000.00","number_of_beneficiaries":2,"total_bonus_amount":"495000.00","insurance_coverage_amount":"0.00","start_at":null,"end_at":null,"state":"UNDER_ACTIVATION",
* "deadlines":1,"amount_last_payment":"495000.00","amount_per_split":"495000.00","paid_deadlines":0,"created_at":"2022-03-29T16:31:52.000000Z","updated_at":"2022-03-29T16:31:52.000000Z"},
* "subscription":{"id":2,"insurance_subscription_id":"CX36UNA2VVOP","network_id":250,"user_id":349,"months_grid_id":77,"bonus_amount":"150000.00","number_of_beneficiaries":2,"
* total_bonus_amount":"495000.00","state":"ACCEPTED","insurance_action":"ACTIVATION","created_at":"2021-11-10T16:52:32.000000Z","updated_at":"2022-03-29T17:31:52.000000Z","reason":null},"payments": {{ "id": 8, "payment_id": "RRS63SV7VP", "invoice_id": 7,
* "amount": "200000 FCFA", "created_at": "2022-04-29T16:09:59.000000Z", "updated_at": "2022-04-29T16:09:59.000000Z" }}}},
* "error":null
* }
* )
* )
* )
*/
public function getInvoices(Request $request)
{
$this->validate($request, [
'user_id' => 'required|integer|exists:users,id',
'state' => 'nullable|in:PAID,UNPAID',
'pagination' => 'nullable|boolean'
]);
$user_id = $request->input('user_id');
$user = User::findOrFail($user_id);
$currency_code = $user->network->country->currency_code;
$pagination = $request->input('pagination');
$state = $request->input('state');
// $datetime = $this->getCurrentTimeByCountryCode($user->network->country->code_country);
$query = NhInsurancesInvoice::with(['insurance', 'subscription'])
->whereHas('insurance', function ($q) use ($user_id) {
return $q->where('user_id', $user_id);
});
if (!empty($state)) {
// if ($state == 'TO_PAID') {
// $query = $query->where('state', InsuranceInvoiceState::UNPAID)
// ->where('next_payment_deadline', '>=', $datetime);
// } else {
$query = $query->where('state', $state);
// }
} else {
$query = $query->with(['payments']);
}
if ($pagination) {
$invoices = $query->paginate($request->input('perPage', 10));
} else {
$invoices = $query->get();
}
$array = $pagination ? $invoices->items() : $invoices;
foreach ($array as $invoice) {
$paid_amount = floatval($invoice->paid_amount_non_formatted);
$invoice->state = trans('states.' . $invoice->state);
$invoice->reason = trans('states.' . $invoice->reason);
$invoice->remaining_amount = $this->toMoneyWithCurrencyCode($invoice->amount - $paid_amount, $currency_code);
$invoice->paid_amount = $this->toMoneyWithCurrencyCode($paid_amount, $currency_code);
$invoice->amount = $this->toMoneyWithCurrencyCode($invoice->amount, $currency_code);
if (empty($state)) {
foreach ($invoice->payments as $payment) {
$payment->amount = $this->toMoneyWithCurrencyCode($payment->amount, $currency_code);
}
}
}
return $this->successResponse($invoices);
}
/**
* @OA\Put(
* path="/insurances/invoices/{id}/pay",
* summary="Payer la facture de l'assurance",
* tags={"Factures de l'assurance"},
* security={{"api_key":{}}},
* @OA\Parameter(
* parameter="id",
* name="id",
* description="ID de la facture",
* 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(
* @OA\Property(property="password",
* type="string",
* example = "addfdf21",
* description="Mot de passe de l'utilisateur"
* ),
* @OA\Property(property="amount",
* type="number",
* example = 32450,
* description="Montant à payer"
* ),
* @OA\Property(property="payment_method",
* type="string",
* enum = {"wallet" ,"mobile_money","card"},
* example = "wallet",
* description="Methode de paiement"
* )
* ),
* example = {"password":"adbc1215448", "amount" : 50000 , "payment_method" : "wallet" }
* )
* ),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* ref="#/components/schemas/ApiResponse",
* example = {"status":200,"response":"Transaction réussie","error":null}
* )
* )
* )
* @throws \App\Exceptions\AppException
*/
public function payInvoice($id, Request $request)
{
$this->validate($request, [
'password' => 'required|string',
'amount' => 'required|numeric|min:0',
'payment_method' => 'required|in:wallet,mobile_money,card'
]);
$amountToPaid = $request->input('amount');
$payment_method = $request->input('payment_method');
$invoice = NhInsurancesInvoice::findOrFail($id);
$datetime = $this->getCurrentTimeByCountryCode($invoice->insurance->network->country->code_country);
if ($invoice->state == InsuranceInvoiceState::PAID) {
return $this->errorResponse(trans('errors.invoice_already_paid'));
}
$networkConfig = NhNetworksConfig::where('network_id', $invoice->insurance->network_id)->first();
if (!isset($networkConfig) || $networkConfig->configWallet->type != 'ilink_sante') {
return $this->errorResponse(trans('errors.nano_health_not_activated'));
}
$user = $invoice->insurance->user;
$this->userIdentificationVerification($user);
// Validation du mot de passe dépendamment de la configuration du réseau
// $this->validate($request, [
// 'password' => [new PasswordValidation($invoice->insurance->network_id, 'user', $user)]
// ]);
$currency = $this->getNetworkCurrency($invoice->insurance->network_id);
$total_paid_amount = NhInsurancesPayment::where('invoice_id', $id)->sum('amount');
$total_remains_amount = $invoice->amount - $total_paid_amount;
if ($amountToPaid > $total_remains_amount) {
return $this->errorResponse("Le montant maximum à payer est de " . $this->toMoneyWithCurrencyCode($total_remains_amount, $currency));
}
if ($amountToPaid < $invoice->amount_per_split && $amountToPaid < $total_remains_amount) {
if ($total_remains_amount < $invoice->amount_per_split) {
return $this->errorResponse(trans('errors.minimum amount_to_paid', ['amount' => $this->toMoneyWithCurrencyCode($total_remains_amount, $currency)]));
}
return $this->errorResponse(trans('errors.minimum amount_to_paid', ['amount' => $this->toMoneyWithCurrencyCode($invoice->amount_per_split, $currency)]));
}
if ($payment_method == 'wallet' && $user->wallet->balance < $amountToPaid) {
$remains_amount = $amountToPaid - $user->wallet->balance;
return $this->errorResponse(trans('errors.insufficient_balance', ['amount' => $this->toMoneyWithCurrencyCode($remains_amount, $currency)]));
}
try {
DB::beginTransaction();
$hyperviseur = AgentPlus::where('category', 'hyper')->where('network_id', $invoice->insurance->network_id)->firstOrFail();
$walletHyperviseur = Wallet::where('id_networkAgent', $hyperviseur->network_agent_id)->firstOrFail();
$walletHyperviseur->balance_princ += $amountToPaid;
$walletHyperviseur->save();
$user->balance_nano_health += $amountToPaid;
if ($payment_method == 'wallet') {
$user->wallet->balance -= $amountToPaid;
}
$user->wallet->save();
$user->save();
$payment = NhInsurancesPayment::create([
'payment_id' => $this->generateID('nh_insurances_payments', 'payment_id', 10),
'invoice_id' => $invoice->id,
'amount' => $amountToPaid
]);
// Calcul de l'équivalence en nombre d'échéance
if (($total_remains_amount - $amountToPaid) == 0) {
$invoice->paid_deadlines = $invoice->deadlines;
$invoice->next_payment_deadlines_to_paid = 0;
} else {
$paid_deadlines = $amountToPaid < $invoice->amount_per_split ? 1 : intval($amountToPaid / $invoice->amount_per_split);
$invoice->paid_deadlines += $paid_deadlines;
$invoice->next_payment_deadlines_to_paid -= $paid_deadlines;
}
if ($invoice->next_payment_deadlines_to_paid < 0) {
$invoice->next_payment_deadlines_to_paid = 0;
}
if ($invoice->paid_deadlines == $invoice->deadlines) {
$invoice->insurance->state = InsuranceState::PAID;
$invoice->state = InsuranceInvoiceState::PAID;
$isPartialPayment = false;
} else {
if ($invoice->next_payment_deadlines_to_paid == 0) {
$invoice->insurance->state = InsuranceState::PARTIALLY_PAID;
}
$deadline = $invoice->next_payment_deadline;
$invoice->next_payment_deadline = $this->addDaysToDateTime($deadline, $networkConfig->reminder_delay_days + $networkConfig->suspension_delay_days_after_reminder); // 1 semaines + 3 jours
$invoice->next_payment_reminder = $this->addDaysToDateTime($deadline, $networkConfig->reminder_delay_days);
$isPartialPayment = true;
}
// Si c'est le 1er paiement
if ($invoice->paid_deadlines == 1) {
if ($invoice->reason == InsuranceAction::ADDITION_OF_BENEFICIARY) {
$invoice->insurance->bonus_amount = $invoice->subscription->bonus_amount;
$invoice->insurance->total_bonus_amount += $invoice->subscription->total_bonus_amount;
$invoice->insurance->number_of_beneficiaries += $invoice->subscription->number_of_beneficiaries;
$invoice->insurance->updated_at = $datetime;
$invoice->insurance->save();
foreach ($invoice->subscription->beneficiaries as $b) {
NhInsurancesHavingRight::create([
'insurance_id' => $invoice->insurance->id,
'having_right_id' => $b->id
]);
}
}
if (in_array($invoice->reason, [InsuranceAction::ACTIVATION, InsuranceAction::RENEWAL])) {
if (empty($invoice->insurance->monthsGrid->waiting_period_days)) {
$start_at = $datetime;
} else {
$start_at = $this->addDaysToDateTime($datetime, $invoice->insurance->monthsGrid->waiting_period_days)->format('Y-m-d H:i:s');
}
$end_at = $this->addMonthsToDateTime($start_at, $invoice->insurance->monthsGrid->number_of_months);
$invoice->insurance->start_at = $start_at;
$invoice->insurance->end_at = $end_at;
}
}
$invoice->updated_at = $datetime;
$invoice->insurance->updated_at = $datetime;
$invoice->insurance->save();
$invoice->save();
Event::dispatch(new InsuranceEvent($invoice->insurance, $isPartialPayment ? trans('messages.insurance_partially_paid') : trans('messages.insurance_subscription_paid'),
trans('messages.insurance_paid_mail', ['name' => $invoice->insurance->user->lastname, 'insured_id' => $invoice->insurance->insured_id,
'bonus_amount' => $this->toMoneyWithCurrencyCode($invoice->insurance->bonus_amount, $currency), 'total_bonus_amount' => $this->toMoneyWithCurrencyCode($invoice->insurance->total_bonus_amount, $currency), 'number_of_beneficiaries' => $invoice->insurance->number_of_beneficiaries,
'gender' => trans('states.' . $invoice->insurance->user->identification->gender), 'insurance_name' => $invoice->insurance->network->name, 'months' => $invoice->insurance->monthsGrid->number_of_months, 'invoice_id' => $invoice->invoice_id,
'amount' => $this->toMoneyWithCurrencyCode($amountToPaid, $currency), 'paid_amount' => $this->toMoneyWithCurrencyCode($total_paid_amount + $amountToPaid, $currency), 'remains_amount' => $this->toMoneyWithCurrencyCode($total_remains_amount - $amountToPaid, $currency),
'payment_period' => trans('states.' . $invoice->insurance->monthsGrid->payment_period), 'reason' => trans('states.' . $invoice->reason), 'title' => $isPartialPayment ? trans('messages.insurance_partially_paid_title') : trans('messages.insurance_fully_paid_title'),
'waiting_days' => empty($invoice->insurance->monthsGrid->waiting_period_days) ? trans('messages.none') : trans('messages.n_days', ['n' => $invoice->insurance->monthsGrid->waiting_period_days]),
'start_at' => $invoice->insurance->start_at, 'payment_id' => $payment->payment_id
])));
DB::commit();
return $this->successResponse(trans('messages.insurance_invoice_paid', ['amount' => $this->toMoneyWithCurrencyCode($amountToPaid, $currency)]));
} catch (Throwable $e) {
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
DB::rollBack();
return $this->errorResponse(trans('errors.unexpected_error'), 500);
}
}
// public function generateInvoices()
// {
// try {
// DB::beginTransaction();
// $this->generateInsurancesInvoices();
// DB::commit();
// return $this->successResponse("Success");
// } catch (\Throwable $t) {
// DB::rollBack();
// Log::error('-------- Insurances Invoices expired insurance-----------');
// Log::error($t->getMessage() . " :\n" . $t->getTraceAsString());
// return $this->errorResponse("Error");
// }
// }
public function reminderInvoices()
{
try {
$this->reminderInsurancesInvoices();
return $this->successResponse("Success");
} catch (\Throwable $t) {
DB::rollBack();
Log::error('-------- Insurances Invoices expired insurance-----------');
Log::error($t->getMessage() . " :\n" . $t->getTraceAsString());
return $this->errorResponse("Error");
}
}
}