nanosanteservice/app/Http/Controllers/InsuranceInvoiceController.php

342 lines
15 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","payment_deadline":"2022-04-08 17:31:52","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('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"
* )
* ),
* 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',
// ]);
$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'));
}
// if ($invoice->payment_deadline < $datetime) {
// return $this->errorResponse(trans('errors.payment_deadline_reached'));
// }
$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);
$amountToPaid = $invoice->amount;
if ($user->wallet->balance < $amountToPaid) {
$amount = $amountToPaid - $user->wallet->balance;
return $this->errorResponse(trans('errors.insufficient_balance', ['amount' => $this->toMoneyWithCurrencyCode($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();
$invoice->update(['state' => InsuranceInvoiceState::PAID, 'updated_at' => $datetime]);
$invoice->insurance->paid_deadlines++;
if ($invoice->insurance->paid_deadlines == $invoice->insurance->deadlines) {
$invoice->insurance->state = InsuranceState::PAID;
$isPartialPayment = false;
} else {
$countUnpaidInvoices = NhInsurancesInvoice::where('insurance_id', $invoice->insurance->id)->where('state', InsuranceInvoiceState::UNPAID)->count();
if ($countUnpaidInvoices == 0) {
$invoice->insurance->state = InsuranceState::PARTIALLY_PAID;
}
$isPartialPayment = true;
}
// Si c'est le 1er paiement
if ($invoice->insurance->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->insurance->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_deadlines' => $invoice->insurance->paid_deadlines, 'remains_deadlines' => $invoice->insurance->deadlines - $invoice->insurance->paid_deadlines,
'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'),
'deadlines' => $invoice->insurance->deadlines, 'amount_per_split' => $this->toMoneyWithCurrencyCode($invoice->insurance->amount_per_split, $currency), 'amount_last_payment' => $this->toMoneyWithCurrencyCode($invoice->insurance->amount_last_payment, $currency),
'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
])));
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");
}
}
}