380 lines
17 KiB
PHP
380 lines
17 KiB
PHP
<?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",
|
|
* "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}}},
|
|
* "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);
|
|
// }
|
|
}
|
|
|
|
if ($pagination) {
|
|
$invoices = $query->paginate($request->input('perPage', 10));
|
|
} else {
|
|
$invoices = $query->get();
|
|
}
|
|
|
|
$array = $pagination ? $invoices->items() : $invoices;
|
|
foreach ($array as $invoice) {
|
|
$invoice->state = trans('states.' . $invoice->state);
|
|
$invoice->reason = trans('states.' . $invoice->reason);
|
|
$invoice->amount = $this->toMoneyWithCurrencyCode($invoice->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"
|
|
* )
|
|
* ),
|
|
* example = {"password":"adbc1215448"}
|
|
* )
|
|
* ),
|
|
* @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'
|
|
]);
|
|
|
|
$amountToPaid = $request->input('amount');
|
|
$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 ($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;
|
|
$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'equivalence en nombre d'echeance
|
|
$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($invoice->amount, $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'));
|
|
} 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");
|
|
}
|
|
}
|
|
}
|