+ Refund and Guarantee Nano credit demand

This commit is contained in:
Djery-Tom 2020-08-18 15:10:03 +01:00
parent be09ba1917
commit 9502c6a355
11 changed files with 379 additions and 47 deletions

View File

@ -2,25 +2,20 @@
namespace App\Http\Controllers;
use App\Models\AgentPlus;
use App\Models\CodeGenerer;
use App\Models\ConfigWallet;
use App\Models\Identification;
use App\Models\Network;
use App\Models\NetworksAgent;
use App\Models\TransfertCommissionTransaction;
use App\Models\UsersDemandesCredit;
use App\Models\UsersGroup;
use App\Models\UsersGroupsDemandesValidation;
use App\Models\Wallet;
use App\Models\WalletAgent;
use App\Models\WalletsUser;
use App\Models\WalletTransaction;
use App\Traits\ApiResponser;
use App\Traits\Helper;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
class NanoCreditController extends Controller
{
@ -41,7 +36,6 @@ class NanoCreditController extends Controller
public function askNanoCredit(Request $request)
{
$this->validate($request, [
'type_caution' => 'required|in:groupe,individuel',
'duree_mois' => 'required|integer|min:0|not_in:0',
@ -75,6 +69,11 @@ class NanoCreditController extends Controller
$demande_credit = new UsersDemandesCredit();
$demande_credit->fill($request->all());
// Derniere demande de nano credit
$last_demand = UsersDemandesCredit::where('id_user', $request->id_user)->where('etat', 'VALIDE')->first();
if ($last_demand)
return $this->errorResponse(trans('errors.last_nano_credit_not_refunded'));
if ($request->type_caution == 'groupe') {
$group = UsersGroup::find($user->group_id);
@ -96,7 +95,7 @@ class NanoCreditController extends Controller
$demande_credit->frais = $this->calculateFees($paliers, $request->montant, $request->duree_mois);
$demande_credit->taxe = $this->calculateTax($taxes, $demande_credit->frais);
$demande_credit->date_demande = new \DateTime();
$demande_credit->date_rembourssement = $demande_credit->date_demande->modify('+' . $request->duree_mois . ' month');
$demande_credit->date_remboursement_prevu = $demande_credit->date_demande->modify('+' . $request->duree_mois . ' month');
$demande_credit->etat = 'VALIDE';
$demande_credit->id_demande = $this->getNanoCreditDemandID();
@ -111,7 +110,7 @@ class NanoCreditController extends Controller
$message = trans('messages.successful_user_group_nano_credit_demand',
['id_demand' => $demande_credit->id_demande, 'amount' => $this->toMoney($montant_total, $init_country),
'net' => $this->toMoney($demande_credit->montant, $init_country), 'fees' => $this->toMoney($demande_credit->frais + $demande_credit->taxe, $init_country),
'date' => $demande_credit->date_rembourssement]);
'date' => $demande_credit->date_remboursement_prevu]);
$this->sendMail($user->email, trans('messages.successful_nano_credit_demand'), $message);
return $this->successResponse($message . trans('messages.sent_by_mail'));
@ -138,6 +137,143 @@ class NanoCreditController extends Controller
}
public function cautionnerCredit(Request $request)
{
$this->validate($request, [
'id_demande' => 'required',
'id_wallet_agent' => 'required|integer|min:0|not_in:0',
'password' => 'required',
]);
$walletAgent = Wallet::findOrFail($request->get('id_wallet_agent'));
$network_agent = NetworksAgent::findOrFail($walletAgent->id_networkAgent);
$agent_country = $network_agent->network->country->id;
// Recuperation des wallets hyperviseur et superviseur
$codeGenerer = CodeGenerer::findOrFail($network_agent->codeGenerer_id);
$superviseur = AgentPlus::where('code_membre', $codeGenerer->code_parrain)->firstOrFail();
$hyperviseur = AgentPlus::where('code_membre', $superviseur->code_parrain)->firstOrFail();
$wallet_agent_hyp = WalletAgent::where('agent_id', $hyperviseur->id)->firstOrFail();
$walletHyperviseur = Wallet::findOrFail($wallet_agent_hyp->wallet_id);
$agent = AgentPlus::findOrFail($network_agent->agent_id);
if (!$this->checkPassword($request->password, $agent->encrypted_password, $agent->salt))
return $this->errorResponse(trans('messages.incorrect_user_password'));
$demande_credit = UsersDemandesCredit::where('id_demande', $request->id_demande)->first();
if (!$demande_credit)
return $this->errorResponse(trans('errors.nano_credit_not_found'));
if ($demande_credit->type_caution != 'individuel')
return $this->errorResponse(trans('errors.nano_credit_not_individual'));
if ($demande_credit->etat == 'VALIDE')
return $this->errorResponse(trans('messages.treated_demand'));
$user = User::findOrFail($demande_credit->id_user);
$user_country = $user->network->country->id;
if ($user_country != $agent_country)
return $this->errorResponse('errors.operation_cannot_performed_in_country');
$montant_total = $demande_credit->montant + $demande_credit->frais + $demande_credit->taxe;
if ($montant_total > $walletAgent->balance_princ)
return $this->errorResponse(trans('errors.insufficient_balance'));
$demande_credit->date_demande = new \DateTime();
$demande_credit->date_remboursement_prevu = $demande_credit->date_demande->modify('+' . $demande_credit->duree_mois . ' month');
$demande_credit->etat = 'VALIDE';
$demande_credit->id_wallet_agent = $walletAgent->id;
$user->balance_credit += $montant_total;
$walletHyperviseur->balance_princ += $demande_credit->montant;
$walletAgent->balance_princ -= $montant_total;
$walletAgent->save();
$walletHyperviseur->save();
$user->save();
$demande_credit->save();
$user_message = trans('messages.successful_guarantee_user_individual_nano_credit_demand',
['id_demand' => $demande_credit->id_demande, 'amount' => $this->toMoney($montant_total, $agent_country),
'net' => $this->toMoney($demande_credit->montant, $agent_country), 'fees' => $this->toMoney($demande_credit->frais + $demande_credit->taxe, $agent_country),
'date' => $demande_credit->date_remboursement_prevu, 'agent_name' => $agent->lastname . ' ' . $agent->firstname, 'code_agent' => $agent->code_membre]);
$agent_message = trans('messages.successful_guarantee_agent_individual_nano_credit_demand',
['id_demand' => $demande_credit->id_demande, 'amount' => $this->toMoney($montant_total, $agent_country),
'net' => $this->toMoney($demande_credit->montant, $agent_country), 'fees' => $this->toMoney($demande_credit->frais + $demande_credit->taxe, $agent_country),
'date' => $demande_credit->date_remboursement_prevu, 'user_name' => $user->lastname . ' ' . $user->firstname, 'code_user' => $user->user_code]);
$this->sendMail($user->email, trans('messages.successful_guarantee_nano_credit_demand'), $user_message);
$this->sendMail($agent->email, trans('messages.successful_guarantee_nano_credit_demand'), $agent_message);
return $this->successResponse($agent_message . trans('messages.sent_by_mail'));
}
public function rembourserCredit(Request $request)
{
$this->validate($request, [
'id_demande' => 'required',
'id_user' => 'required|integer|min:0|not_in:0',
'password' => 'required',
]);
$user = User::findOrFail($request->id_user);
if (!$this->checkPassword($request->password, $user->encrypted_password, $user->salt))
return $this->errorResponse(trans('messages.incorrect_user_password'));
$walletUser = WalletsUser::where('idUser', $request->id_user)->firstOrFail();
$demande_credit = UsersDemandesCredit::where('id_demande', $request->id_demande)->first();
if (!$demande_credit)
return $this->errorResponse(trans('errors.nano_credit_not_found'));
if ($demande_credit->etat == 'REMBOURSE')
return $this->errorResponse(trans('errors.nano_credit_already_refunded'));
$init_country = $user->network->country->id;
$montant_total = $demande_credit->montant + $demande_credit->frais + $demande_credit->taxe;
if ($montant_total > $walletUser->balance)
return $this->errorResponse(trans('errors.insufficient_balance'));
$user->balance_credit -= $montant_total;
$walletUser->balance -= $montant_total;
$demande_credit->etat = 'REMBOURSE';
if ($demande_credit->type_caution == 'individuel') {
$walletAgent = Wallet::findOrFail($demande_credit->id_wallet_agent);
$network_agent = NetworksAgent::findOrFail($walletAgent->id_networkAgent);
// Recuperation des wallets hyperviseur et superviseur
$codeGenerer = CodeGenerer::findOrFail($network_agent->codeGenerer_id);
$superviseur = AgentPlus::where('code_membre', $codeGenerer->code_parrain)->firstOrFail();
$hyperviseur = AgentPlus::where('code_membre', $superviseur->code_parrain)->firstOrFail();
$wallet_agent_hyp = WalletAgent::where('agent_id', $hyperviseur->id)->firstOrFail();
$walletHyperviseur = Wallet::findOrFail($wallet_agent_hyp->wallet_id);
$walletAgent->balance_princ += $demande_credit->montant;
$walletHyperviseur->balance_princ -= $demande_credit->montant;
$walletAgent->save();
$walletHyperviseur->save();
}
$demande_credit->date_remboursement = new \DateTime();
$walletUser->save();
$user->save();
$demande_credit->save();
$message = trans('messages.successful_nano_credit_demand_refunded',
['id_demand' => $demande_credit->id_demande, 'amount' => $this->toMoney($montant_total, $init_country),
'net' => $this->toMoney($demande_credit->montant, $init_country), 'fees' => $this->toMoney($demande_credit->frais + $demande_credit->taxe, $init_country),
'caution' => $demande_credit->type_caution == 'groupe' ? 'Groupe' : 'Individuel']);
$this->sendMail($user->email, trans('messages.successful_nano_credit_refunded'), $message);
return $this->successResponse($message . trans('messages.sent_by_mail'));
}
// Calculer les frais
private function calculateFees(array $paliers, $montant, $duree)
{

View File

@ -4,23 +4,14 @@ namespace App\Http\Controllers;
use App\Models\ConfigWallet;
use App\Models\Identification;
use App\Models\Network;
use App\Models\NetworksAgent;
use App\Models\TransfertCommissionTransaction;
use App\Models\UsersDemandesCredit;
use App\Models\UsersGroup;
use App\Models\UsersGroupsDemandesValidation;
use App\Models\Wallet;
use App\Models\WalletsUser;
use App\Models\WalletTransaction;
use App\Traits\ApiResponser;
use App\Traits\Helper;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
class UserGroupController extends Controller
{
@ -361,7 +352,8 @@ class UserGroupController extends Controller
public function getGroupDemand($id_demand)
{
$demand = collect(DB::select('SELECT * FROM users_groups_demandes_validations ugd
$demand = collect(DB::select('SELECT ugd.* , ug.code_groupe , ug.nom , ug.limite_credit , ug.nombre_validation, ug.actif, ug.nombre_utilisateurs,
ug.date_creation , ug.createur , ug.sponsor1 , ug.sponsor2 , ug.sponsor3, ug.country, ug.currency_code FROM users_groups_demandes_validations ugd
INNER JOIN infos_users_groups ug ON ug.id = ugd.id_group WHERE ugd.id = :id;', ['id' => $id_demand]))->first();
if ($demand)
return $this->successResponse($demand);

View File

@ -21,9 +21,10 @@ use Illuminate\Database\Eloquent\Model;
* @property float $frais
* @property float $taxe
* @property Carbon $date_demande
* @property Carbon $date_rembourssement
* @property Carbon $date_remboursement_prevu
* @property Carbon $date_remboursement
* @property int $id_user
* @property int $id_agent
* @property int $id_wallet_agent
*
* @package App\Models
*/
@ -40,12 +41,13 @@ class UsersDemandesCredit extends Model
'frais' => 'float',
'taxe' => 'float',
'id_user' => 'int',
'id_agent' => 'int'
'id_wallet_agent' => 'int'
];
protected $dates = [
'date_demande',
'date_rembourssement'
'date_remboursement_prevu',
'date_remboursement'
];
protected $fillable = [
@ -57,8 +59,9 @@ class UsersDemandesCredit extends Model
'frais',
'taxe',
'date_demande',
'date_rembourssement',
'date_remboursement_prevu',
'date_remboursement',
'id_user',
'id_agent'
'id_wallet_agent'
];
}

View File

@ -61,6 +61,7 @@ $app->singleton(
$app->configure('app');
$app->configure('mail');
$app->configure('queue');
$app->alias('mailer', Illuminate\Mail\Mailer::class);
$app->alias('mailer', Illuminate\Contracts\Mail\Mailer::class);
$app->alias('mailer', Illuminate\Contracts\Mail\MailQueue::class);

85
composer.lock generated
View File

@ -172,20 +172,20 @@
},
{
"name": "doctrine/lexer",
"version": "1.2.0",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6"
"reference": "e864bbf5904cb8f5bb334f99209b48018522f042"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
"reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042",
"reference": "e864bbf5904cb8f5bb334f99209b48018522f042",
"shasum": ""
},
"require": {
"php": "^7.2"
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^6.0",
@ -230,7 +230,21 @@
"parser",
"php"
],
"time": "2019-10-30T14:39:59+00:00"
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer",
"type": "tidelift"
}
],
"time": "2020-05-25T17:44:05+00:00"
},
{
"name": "dragonmantank/cron-expression",
@ -3099,25 +3113,25 @@
},
{
"name": "symfony/finder",
"version": "v5.0.7",
"version": "v5.1.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "600a52c29afc0d1caa74acbec8d3095ca7e9910d"
"reference": "4298870062bfc667cb78d2b379be4bf5dec5f187"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/600a52c29afc0d1caa74acbec8d3095ca7e9910d",
"reference": "600a52c29afc0d1caa74acbec8d3095ca7e9910d",
"url": "https://api.github.com/repos/symfony/finder/zipball/4298870062bfc667cb78d2b379be4bf5dec5f187",
"reference": "4298870062bfc667cb78d2b379be4bf5dec5f187",
"shasum": ""
},
"require": {
"php": "^7.2.5"
"php": ">=7.2.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
"dev-master": "5.1-dev"
}
},
"autoload": {
@ -3144,7 +3158,21 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2020-03-27T16:56:45+00:00"
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-05-20T17:43:50+00:00"
},
{
"name": "symfony/http-foundation",
@ -3361,16 +3389,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.15.0",
"version": "v1.18.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14"
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454",
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454",
"shasum": ""
},
"require": {
@ -3382,7 +3410,11 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-master": "1.18-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
@ -3415,7 +3447,21 @@
"polyfill",
"portable"
],
"time": "2020-02-27T09:26:54+00:00"
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-07-14T12:35:20+00:00"
},
{
"name": "symfony/polyfill-iconv",
@ -5087,6 +5133,7 @@
"keywords": [
"tokenizer"
],
"abandoned": true,
"time": "2019-09-17T06:23:10+00:00"
},
{

89
config/queue.php Executable file
View File

@ -0,0 +1,89 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Queue Connection Name
|--------------------------------------------------------------------------
|
| Laravel's queue API supports an assortment of back-ends via a single
| API, giving you convenient access to each back-end using the same
| syntax for every one. Here you may define a default connection.
|
*/
'default' => env('QUEUE_CONNECTION', 'sync'),
/*
|--------------------------------------------------------------------------
| Queue Connections
|--------------------------------------------------------------------------
|
| Here you may configure the connection information for each server that
| is used by your application. A default configuration has been added
| for each back-end shipped with Laravel. You are free to add more.
|
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
*/
'connections' => [
'sync' => [
'driver' => 'sync',
],
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
'beanstalkd' => [
'driver' => 'beanstalkd',
'host' => 'localhost',
'queue' => 'default',
'retry_after' => 90,
'block_for' => 0,
],
'sqs' => [
'driver' => 'sqs',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
'queue' => env('SQS_QUEUE', 'your-queue-name'),
'suffix' => env('SQS_SUFFIX'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
],
/*
|--------------------------------------------------------------------------
| Failed Queue Jobs
|--------------------------------------------------------------------------
|
| These options configure the behavior of failed queue job logging so you
| can control which database and table are used to store the jobs that
| have failed. You may change them to any database / table you wish.
|
*/
'failed' => [
'driver' => env('QUEUE_FAILED_DRIVER', 'database'),
'database' => env('DB_CONNECTION', 'mysql'),
'table' => 'failed_jobs',
],
];

View File

@ -49,5 +49,8 @@ Paying network : :network :country',
'your_group_not_active' => "Your group is not active. Talk to your sponsor",
'your_group_not_valid' => "Your group is not valid. Talk to your sponsor",
'nano_credit_amount_must_be_less_than_group_limit' => "The amount of credit requested must be less than or equal to the group credit limit",
"nano_credit_not_found" => "This nano credit request does not exist",
"nano_credit_not_individual" => "This nano credit request is not individual",
"last_nano_credit_not_refunded" => "Your last nano credit request was not refunded",
"nano_credit_already_refunded" => "Repayment of credit already made"
];

View File

@ -177,4 +177,28 @@ Request Information:
- Net amount to be collected: :net
Go to a geolocated agent who agrees to back you up by validating your credit request",
'successful_guarantee_user_individual_nano_credit_demand' => "Guaranteed nanocredit request
Request Information:
- Request number: :id_demand
- Type of deposit: Individual
- Credit amount: :amount
- Fees: :fees
- Net amount received: :net
- Redemption date: :date
- Agent names: :agent_name
- Agent code: :code_agent",
'successful_guarantee_agent_individual_nano_credit_demand' => "Guaranteed nanocredit request
Request Information:
- Request number: :id_demand
- Type of deposit: Individual
- Credit amount: :amount
- Fees: :fees
- Net amount received: :net
- Redemption date: :date
- Client names: :user_name
- Client code: :code_user
NB: The reimbursement process is automatic on the due date if the reimbursement is not initiated",
'successful_guarantee_nano_credit_demand' => 'Guaranteed nanocredit request',
'successful_nano_credit_refunded' => 'Nano credit repayment made',
];

View File

@ -49,4 +49,8 @@ Réseau payeur : :network :country',
'your_group_not_active' => "Votre groupe n'est pas actif. Adressez-vous à votre sponsor",
'your_group_not_valid' => "Votre groupe n'est pas valide. Adressez-vous à votre sponsor",
'nano_credit_amount_must_be_less_than_group_limit' => "Le montant du crédit demandé doit être inférieur ou égal à la limite crédit groupe",
"nano_credit_not_found" => "Cette demande de nano crédit n'existe pas",
"nano_credit_not_individual" => "Cette demande de nano crédit n'est pas individuelle",
"last_nano_credit_not_refunded" => "Votre derniere demande de nano crédit n'a pas été remboursée",
"nano_credit_already_refunded" => "Remboursement de crédit deja effectué"
];

View File

@ -177,4 +177,35 @@ Informations de la demande :
- Montant net à percevoir : :net
Rendez vous chez un agent geolocalisé qui accepte de vous cautionner en validant votre demande de crédit",
'successful_guarantee_user_individual_nano_credit_demand' => "Demande de nano crédit cautionnée
Informations de la demande :
- Numéro de la demande : :id_demand
- Type de caution : Individuel
- Montant du crédit : :amount
- Frais : :fees
- Montant net percu : :net
- Date de remboursement : :date
- Noms de l'agent : :agent_name
- Code de l'agent : :code_agent",
'successful_guarantee_agent_individual_nano_credit_demand' => "Demande de nano crédit cautionnée
Informations de la demande :
- Numéro de la demande : :id_demand
- Type de caution : Individuel
- Montant du crédit : :amount
- Frais : :fees
- Montant net à percu : :net
- Date de remboursement : :date
- Noms du client : :user_name
- Code du client : :code_user
NB: Le processus de remboursement est automatique à la date d'échéance si le remboursement n'est pas initié",
'successful_guarantee_nano_credit_demand' => 'Demande de nano crédit cautionnée',
'successful_nano_credit_refunded' => 'Remboursement de nano crédit effectué',
'successful_nano_credit_demand_refunded' => "Nano crédit remboursé
Informations de la demande :
- Numéro de la demande : :id_demand
- Type de caution : :caution
- Montant du crédit : :amount
- Frais : :fees
- Montant net à percu : :net",
];

View File

@ -83,5 +83,7 @@ $router->group(['prefix' => '/groups'], function () use ($router) {
$router->post('validate', 'UserGroupController@validateGroupDemand');
$router->post('cancel', 'UserGroupController@cancelGroupDemand');
$router->post('askNanoCredit', 'NanoCreditController@askNanoCredit');
$router->post('guaranteeNanoCredit', 'NanoCreditController@cautionnerCredit');
$router->post('refundNanoCredit', 'NanoCreditController@rembourserCredit');
});
});