From f1e8d90af18d450f088aae3d517254a305786606 Mon Sep 17 00:00:00 2001 From: Djery-Tom Date: Wed, 26 Jan 2022 00:16:26 +0100 Subject: [PATCH] Implements Cron task to generate invoice and route to get history of invoices --- .gitignore | 2 +- app/Console/Kernel.php | 140 +++++++++++- app/Http/Controllers/InvoiceController.php | 200 ++++++++---------- app/Models/AgentPlus.php | 5 + app/Models/Network.php | 5 + app/Models/NhInfosInvoice.php | 68 ++++++ app/Traits/Helper.php | 41 ++++ ...date_nh_infos_health_care_sheets_view3.php | 51 +++++ routes/web.php | 1 + 9 files changed, 402 insertions(+), 111 deletions(-) create mode 100644 app/Models/NhInfosInvoice.php create mode 100644 database/migrations/2022_01_25_183554_update_nh_infos_health_care_sheets_view3.php diff --git a/.gitignore b/.gitignore index 446ec14..0f6a0c3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,5 @@ Homestead.yaml /public/swagger-ui-assets /public/insurances-subscriptions-docs /public/qrcodes -/public/invoices +/public/invoices-docs composer.lock diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index ad6e311..87584ac 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,11 +2,26 @@ namespace App\Console; +use App\BillingPeriodType; +use App\InsuranceSubscriptionState; +use App\Models\AgentPlus; +use App\Models\CountriesCurrency; +use App\Models\NhHealthCareSheet; +use App\Models\NhInvoice; +use App\Models\NhNetworksConfig; +use App\Traits\Helper; +use Barryvdh\DomPDF\Facade as PDF; +use DateTime; use Illuminate\Console\Scheduling\Schedule; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Mail; use Laravel\Lumen\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { + use Helper; + /** * The Artisan commands provided by your application. * @@ -24,6 +39,129 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - // + // Generer les factures chaque dimanche à minuit + $schedule->call(function () { + + $date = new DateTime(); + Log::info('-------- Weekly Invoice Generation Start ' . $date->format("d/m/Y") . ' -----------'); + $hypers = AgentPlus::whereHas('network', function ($query) { + return $query->has('nh_network_config'); + })->where('category', 'hyper')->get(); + + foreach ($hypers as $hyper) { + $config = NhNetworksConfig::where('network_id', $hyper->network_id)->first(); + if (!isset($config)) { + continue; + } + + $agents = AgentPlus::where('network_id', $hyper->network_id)->where('category', 'geolocated')->get(); + foreach ($agents as $agent) { + + $start_at = new DateTime(); + switch ($config->provider_billing_period) { + case BillingPeriodType::WEEKLY: + $start_at->modify('-7 days'); + break; + case BillingPeriodType::BIMONTHLY: + $start_at->modify('-14 days'); + break; + case BillingPeriodType::MONTHLY: + $start_at->modify('-28 days'); + break; + default: + $start_at = new DateTime(); + } + + $end_at = new DateTime(); + + + $invoice_id = $this->generateInvoiceID($agent->code_membre); + $country = CountriesCurrency::findOrFail($agent->country_id); + $datetime = $this->getCurrentTimeByCountryCode($country->code_country); + + $totalInsurerAmount = 0; + $totalInsuredAmount = 0; + $sheets = NhHealthCareSheet::with(['insurance'])->where('network_agent_id', $agent->network_agent_id)->where('state', InsuranceSubscriptionState::ACCEPTED) + ->where('created_at', '>=', $start_at)->where('created_at', '<=', $end_at)->orderBy('created_at', 'DESC')->get(); + + if (sizeof($sheets) == 0) { + Log::info("Periode " . $date->format("d/m/Y") . " - " . $date->format("d/m/Y") + . "\n Network " . $hyper->network . "\n Aucune feuille de soins acceptée"); + continue; + } + + foreach ($sheets as $sheet) { + $this->fetchHealthCareSheetAmounts($sheet); + + $totalInsuredAmount += $sheet->insured_amount; + $totalInsurerAmount += $sheet->insurer_amount; + + $sheet->date = $sheet->created_at->format('d/m/Y'); + } + + try { + DB::beginTransaction(); + + $directoryName = '/invoices-docs/'; + $filename = $start_at->format('dmY') . '_' . $end_at->format('dmY') . '_' . $agent->code_membre . '.pdf'; + + $invoice = NhInvoice::create([ + 'invoice_id' => $invoice_id, + 'network_agent_id' => $agent->network_agent_id, + 'amount' => $totalInsuredAmount + $totalInsurerAmount, + 'insured_amount' => $totalInsuredAmount, + 'insurer_amount' => $totalInsurerAmount, + 'period_start_at' => $start_at, + 'period_end_at' => $end_at, + 'file_url' => config('services.app_url') . $directoryName . $filename, + 'created_at' => $datetime, + 'updated_at' => $datetime + ]); + + $invoice->amount = $this->toMoneyWithCurrencyCode($invoice->amount, $country->currency_code); + $invoice->insured_amount = $this->toMoneyWithCurrencyCode($invoice->insured_amount, $country->currency_code); + $invoice->insurer_amount = $this->toMoneyWithCurrencyCode($invoice->insurer_amount, $country->currency_code); + $invoice->home_visit_fees = $this->toMoneyWithCurrencyCode($invoice->home_visit_fees, $country->currency_code); + + $ids = array_map(function ($r) { + return $r['id']; + }, $sheets->toArray()); + + DB::update("UPDATE nh_health_care_sheets SET state = :state_ , invoice_id = :id WHERE id IN (" . implode(',', $ids) . ")", + ['id' => $invoice->id, 'state_' => InsuranceSubscriptionState::INVOICE_ISSUED]); + + $invoice->sheets = $sheets; + $invoice->agent = $agent; + $invoice->hyper = $hyper; + $invoice->period = $start_at->format('d/m/Y') . ' ' . trans('messages.to') . ' ' . $end_at->format('d/m/Y'); + + //Check if the directory already exists. + if (!is_dir(public_path($directoryName))) { + //Directory does not exist, so lets create it. + mkdir(public_path($directoryName), 0755); + } + + $title = trans('messages.invoice') . ' ' . $invoice->period; + $message = $title; + + $file = PDF::loadView('emails.invoice', $invoice->toArray())->setPaper('a4', 'landscape')->setWarnings(false)->save(public_path($directoryName . $filename)); + + DB::commit(); + $recipients = [preg_replace("/\s+/", "", $hyper->email)]; // Supprimer les espaces dans le mail + Mail::mailer('smtp')->raw($message, function ($message) use ($recipients, $title, $file) { + $message->subject($title) + ->to($recipients) + ->attachData($file->output(), str_replace(' ', '-', $title) . '.pdf'); + }); + + } catch (\Throwable $t) { + DB::rollBack(); + Log::error('-------- Mail not sent -----------'); + Log::error($t->getMessage() . " :\n" . $t->getTraceAsString()); + } + } + } + Log::info('-------- Weekly Invoice Generation End ' . $date->format("d/m/Y") . '-----------'); + })->weekly()->runInBackground(); } } diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index e8aea7b..cba75a1 100755 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -7,95 +7,18 @@ use App\BillingPeriodType; use App\InsuranceSubscriptionState; use App\Models\AgentPlus; use App\Models\CountriesCurrency; -use App\Models\Network; use App\Models\NhHealthCareSheet; -use App\Models\NhInsurance; +use App\Models\NhInfosInvoice; use App\Models\NhInvoice; use App\Models\NhNetworksConfig; -use App\Models\User; -use App\Models\WalletsUser; -use App\Traits\ApiResponser; -use App\Traits\Helper; use Barryvdh\DomPDF\Facade as PDF; use DateTime; use Illuminate\Http\Request; -use Illuminate\Http\Response; -use Illuminate\Support\Facades\Date; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; -use Moment\Moment; -use Propaganistas\LaravelPhone\PhoneNumber; -use stdClass; - class InvoiceController extends Controller { - - - /** - * @OA\Get( - * path="/insured", - * summary="Rechercher un assuré (par reseau , par nom ou par numero de telephone)", - * tags={"Assurés"}, - * security={{"api_key":{}}}, - * @OA\Parameter( - * parameter="network_id", - * name="network_id", - * description="ID du reseau", - * @OA\Schema( - * type="integer" - * ), - * in="query", - * required=true - * ), - * @OA\Parameter( - * parameter="insured_id", - * name="insured_id", - * description="Numero d'assuré", - * @OA\Schema( - * type="string" - * ), - * in="query", - * required=false - * ), - * @OA\Parameter( - * parameter="name", - * name="name", - * description="Nom de l'utilisateur", - * @OA\Schema( - * type="string" - * ), - * in="query", - * required=false - * ), - * @OA\Parameter( - * parameter="phone", - * name="phone", - * description="Telephone de l'utilisateur", - * @OA\Schema( - * type="string" - * ), - * in="query", - * required=false - * ), - * @OA\Response( - * response=200, - * description="OK", - * @OA\JsonContent( - * ref="#/components/schemas/ApiResponse", - * example = { - * "status" : 200, - * "response" : {{"id":4,"network_id":250,"user_id":349,"insured_id":"GJKS8ZGBEJTL","number_of_months":3,"bonus_amount":"150000.00", - * "number_of_beneficiaries":2,"total_bonus_amount":"495000.00","start_at":"2021-11-11T21:54:02.000000Z","end_at":"2022-02-11T21:54:02.000000Z", - * "state":"PAID","created_at":"2021-11-11T20:54:02.000000Z","updated_at":"2021-11-11T20:54:02.000000Z","user":{"id":349, - * "firstname":null,"lastname":"Tom Di","phone":"+237690716648","email":"ddoubletom@gmail.com"},"network":{"id":250,"name":"Cnamgs-pharmacies"}}}, - * "error":null - * } - * ) - * ) - * ) - */ // Generer les factures periodiquement pour chaque agent public function generateInvoice(Request $request) { @@ -136,36 +59,17 @@ class InvoiceController extends Controller $totalInsurerAmount = 0; $totalInsuredAmount = 0; $sheets = NhHealthCareSheet::with(['insurance'])->where('network_agent_id', $network_agent_id)->where('state', InsuranceSubscriptionState::ACCEPTED) - ->where('created_at', '>=', $start_at)->where('created_at', '<=', $end_at)->get(); + ->where('created_at', '>=', $start_at)->where('created_at', '<=', $end_at)->orderBy('created_at', 'DESC')->get(); if (sizeof($sheets) == 0) { return $this->errorResponse("Aucune feuille de soins acceptée"); } foreach ($sheets as $sheet) { - $insurerAmount = 0; - $insuredAmount = 0; + $this->fetchHealthCareSheetAmounts($sheet); - foreach ($sheet->performances as $p) { - $insurerAmount += ($p->moderator_ticket ?? 0); - $insuredAmount += ($p->insurance_amount ?? 0); - } - - foreach ($sheet->performances as $p) { - $insurerAmount += ($p->insured_paid_amount ?? 0); - $insuredAmount += ($p->insurer_paid_amount ?? 0); - } - - foreach ($sheet->performances as $p) { - $insurerAmount += ($p->insured_paid_amount ?? 0); - $insuredAmount += ($p->insurer_paid_amount ?? 0); - } - - $sheet->insurer_amount = $insurerAmount; - $sheet->insured_amount = $insuredAmount; - - $totalInsuredAmount += $insuredAmount; - $totalInsurerAmount += $insurerAmount; + $totalInsuredAmount += $sheet->insured_amount; + $totalInsurerAmount += $sheet->insurer_amount; $sheet->date = $sheet->created_at->format('d/m/Y'); } @@ -173,7 +77,7 @@ class InvoiceController extends Controller try { DB::beginTransaction(); - $directoryName = '/invoices/'; + $directoryName = '/invoices-docs/'; $filename = $start_at->format('dmY') . '_' . $end_at->format('dmY') . '_' . $agent->code_membre . '.pdf'; $invoice = NhInvoice::create([ @@ -219,11 +123,11 @@ class InvoiceController extends Controller DB::commit(); $recipients = [preg_replace("/\s+/", "", $hyper->email)]; // Supprimer les espaces dans le mail - Mail::mailer('smtp')->raw($message, function ($message) use ($recipients, $title, $file) { - $message->subject($title) - ->to($recipients) - ->attachData($file->output(), str_replace(' ', '-', $title) . '.pdf'); - }); +// Mail::mailer('smtp')->raw($message, function ($message) use ($recipients, $title, $file) { +// $message->subject($title) +// ->to($recipients) +// ->attachData($file->output(), str_replace(' ', '-', $title) . '.pdf'); +// }); } catch (\Throwable $t) { DB::rollBack(); @@ -234,8 +138,86 @@ class InvoiceController extends Controller return $this->successResponse("Invoice generated"); } - private function generateInvoiceID($agent_code) + /** + * @OA\Get( + * path="/invoices", + * summary="Lister les factures", + * tags={"Factures"}, + * security={{"api_key":{}}}, + * @OA\Parameter( + * parameter="network_id", + * name="network_id", + * description="ID du reseau", + * @OA\Schema( + * type="integer" + * ), + * in="query", + * required=false + * ), + * @OA\Parameter( + * parameter="network_agent_id", + * name="insured_id", + * description="ID de l'agent dans le reseau", + * @OA\Schema( + * type="integer" + * ), + * in="query", + * required=false + * ), + * @OA\Response( + * response=200, + * description="OK", + * @OA\JsonContent( + * ref="#/components/schemas/ApiResponse", + * example = { + * "status" : 200, + * "response" : {{"id":12,"invoice_id":"25\/01\/2022\/aon8K9BZOn","network_agent_id":43510,"amount":"110\u202f600 FCFA","insured_amount":"104\u202f320 FCFA", + * "insurer_amount":"6\u202f280 FCFA","period_start_at":"2021-12-28T00:00:00.000000Z","period_end_at":"2022-01-25T00:00:00.000000Z","file_url":"http:\/\/localhost:8086\/invoices-docs\/28122021_25012022_aon8K9BZOn.pdf", + * "created_at":"2022-01-25T19:54:44.000000Z","updated_at":"2022-01-25T19:54:44.000000Z","institution_name":"Agent 2 cnamgs fond 4","institution_code":"aon8K9BZOn","network_id":250,"currency_code":"XAF", + * "health_care_sheets":{{"id":72,"invoice_id":12,"health_care_sheet_id":"LG83D7QFGM3X","type":"CONSULTATION","practitioner_lastname":"DIETCHI","practitioner_firstname":"Djery","practitioner_provider_class":"Chirugien", + * "patient_lastname":"Zele","patient_firstname":"Brice","institution_name":"Agent 2 cnamgs fond 4","institution_code":"aon8K9BZOn","amount":"5\u202f000 FCFA","insurerAmount":"1\u202f000 FCFA","insuredAmount":"4\u202f000 FCFA"}}}}, + * "error":null + * } + * ) + * ) + * ) + */ + public function getInvoices(Request $request) { - return date('d') . '/' . date('m') . '/' . date('Y') . '/' . $agent_code; + $this->validate($request, [ + 'network_id' => 'required_without:network_agent_id|integer|exists:networks,id', + 'network_agent_id' => 'required_without:network_id|integer|exists:networks_agents,id' + ]); + + $network_id = $request->input('network_id'); + $network_agent_id = $request->input('network_agent_id'); + + $query = NhInfosInvoice::with(['health_care_sheets:id,invoice_id,health_care_sheet_id,type,practitioner_lastname,practitioner_firstname,practitioner_provider_class,patient_lastname,patient_firstname,institution_name,institution_code']); + + if (!empty($network_id)) { + $query = $query->where('network_id', $network_id); + } + + if (!empty($network_agent_id)) { + $query = $query->where('network_agent_id', $network_agent_id); + } + + $invoices = $query->orderBy('created_at', 'DESC')->get(); + foreach ($invoices as $i) { + $i->amount = $this->toMoneyWithCurrencyCode($i->amount, $i->currency_code); + $i->insured_amount = $this->toMoneyWithCurrencyCode($i->insured_amount, $i->currency_code); + $i->insurer_amount = $this->toMoneyWithCurrencyCode($i->insurer_amount, $i->currency_code); + + + foreach ($i->health_care_sheets as $sheet) { + $this->fetchHealthCareSheetAmounts($sheet); + + $sheet->amount = $this->toMoneyWithCurrencyCode($sheet->insured_amount + $sheet->insurer_amount, $i->currency_code); + $sheet->insurerAmount = $this->toMoneyWithCurrencyCode($sheet->insurer_amount, $i->currency_code); + $sheet->insuredAmount = $this->toMoneyWithCurrencyCode($sheet->insured_amount, $i->currency_code); + + } + } + return $this->successResponse($invoices); } } diff --git a/app/Models/AgentPlus.php b/app/Models/AgentPlus.php index 59fb512..7dfdf44 100755 --- a/app/Models/AgentPlus.php +++ b/app/Models/AgentPlus.php @@ -90,4 +90,9 @@ class AgentPlus extends Model 'transactionNumber', 'network_agent_id' ]; + + public function network() + { + return $this->belongsTo(Network::class, 'network_id'); + } } diff --git a/app/Models/Network.php b/app/Models/Network.php index b638161..515dec9 100755 --- a/app/Models/Network.php +++ b/app/Models/Network.php @@ -53,4 +53,9 @@ class Network extends Model { return $this->belongsTo(CountriesCurrency::class, 'country_id'); } + + public function nh_network_config() + { + return $this->hasOne(NhNetworksConfig::class, 'network_id'); + } } diff --git a/app/Models/NhInfosInvoice.php b/app/Models/NhInfosInvoice.php new file mode 100644 index 0000000..c1be556 --- /dev/null +++ b/app/Models/NhInfosInvoice.php @@ -0,0 +1,68 @@ + 'int', + 'network_agent_id' => 'int', + 'network_id' => 'int' + ]; + + protected $dates = [ + 'period_start_at', + 'period_end_at' + ]; + + protected $fillable = [ + 'id', + 'invoice_id', + 'network_agent_id', + 'amount', + 'insured_amount', + 'insurer_amount', + 'period_start_at', + 'period_end_at', + 'file_url', + 'institution_name', + 'institution_code', + 'network_id', + 'currency_code' + ]; + + public function health_care_sheets() + { + return $this->hasMany(NhInfosHealthCareSheets::class, 'invoice_id', 'id'); + } +} diff --git a/app/Traits/Helper.php b/app/Traits/Helper.php index 9e16b94..342ccf5 100644 --- a/app/Traits/Helper.php +++ b/app/Traits/Helper.php @@ -9,6 +9,8 @@ use App\InsuranceSubscriptionState; use App\Models\CountriesCurrency; use App\Models\Country; use App\Models\NhHavingRight; +use App\Models\NhHealthCareSheet; +use App\Models\NhInfosHealthCareSheets; use App\Models\NhInsurance; use App\Models\NhInsurancesHavingRight; use App\Models\NhInsurancesSubscription; @@ -157,4 +159,43 @@ trait Helper return $code; } + public function generateInvoiceID($agent_code) + { + return date('d') . '/' . date('m') . '/' . date('Y') . '/' . $agent_code; + } + + public function fetchHealthCareSheetAmounts($sheet): void + { + $insurerAmount = 0; + $insuredAmount = 0; + + $sum = $sheet->performances()->selectRaw('SUM(moderator_ticket) as moderator_ticket , SUM(insurance_amount) as insurance_amount') + ->groupBy('nh_health_care_sheets_performances.id')->first(); + + if (isset($sum)) { + $insurerAmount += $sum->moderator_ticket; + $insuredAmount += $sum->insurance_amount; + } + + + $sum = $sheet->prescriptions()->selectRaw('SUM(insured_paid_amount) as insured_paid_amount , SUM(insurer_paid_amount) as insurer_paid_amount') + ->groupBy('nh_health_care_sheets_prescriptions.id')->first(); + + if (isset($sum)) { + $insurerAmount += $sum->insured_paid_amount; + $insuredAmount += $sum->insurer_paid_amount; + } + + $sum = $sheet->exams()->selectRaw('SUM(insured_paid_amount) as insured_paid_amount , SUM(insurer_paid_amount) as insurer_paid_amount') + ->groupBy('nh_health_care_sheets_exams.id')->first(); + + + if (isset($sum)) { + $insurerAmount += $sum->insured_paid_amount; + $insuredAmount += $sum->insurer_paid_amount; + } + + $sheet->insurer_amount = $insurerAmount; + $sheet->insured_amount = $insuredAmount; + } } diff --git a/database/migrations/2022_01_25_183554_update_nh_infos_health_care_sheets_view3.php b/database/migrations/2022_01_25_183554_update_nh_infos_health_care_sheets_view3.php new file mode 100644 index 0000000..46cb6e5 --- /dev/null +++ b/database/migrations/2022_01_25_183554_update_nh_infos_health_care_sheets_view3.php @@ -0,0 +1,51 @@ +group(['prefix' => '', 'middleware' => 'auth'], function () use ($route $router->get('health-care-sheets/{id}', 'HealthCareSheetController@getOneHealthCareSheets'); $router->put('health-care-sheets/{id}', 'HealthCareSheetController@updateHealthCareSheet'); + $router->get('invoices', 'InvoiceController@getInvoices'); $router->get('generate-invoice', 'InvoiceController@generateInvoice'); });