From 9ef8021dc35cebf1ab4a0acb5be98614f7056d88 Mon Sep 17 00:00:00 2001 From: Djery-Tom Date: Mon, 19 Dec 2022 17:01:23 +0100 Subject: [PATCH] Implements payment of customer account opening request --- .env.example | 9 + .../CustomerAccountOpeningController.php | 337 +++++++++++++++++- app/Models/AgentPlus.php | 110 ++++++ app/Models/CustomerAccountRequest.php | 8 + .../InfosCustomerAccountOpeningRequest.php | 10 + app/Models/PaymentAggregator.php | 11 + app/Models/PaymentTransaction.php | 11 + app/Models/Wallet.php | 53 +++ app/Traits/Helper.php | 118 +----- composer.json | 3 +- config/variables.php | 7 +- ...44_create_customer_account_types_table.php | 1 + ...ustomer_account_opening_requests_table.php | 3 + ...customer_account_opening_requests_view.php | 3 + resources/lang/en/errors.php | 7 +- resources/lang/en/messages.php | 15 +- resources/lang/en/states.php | 3 + resources/lang/fr/errors.php | 7 +- resources/lang/fr/messages.php | 13 +- resources/lang/fr/states.php | 3 + routes/web.php | 6 +- 21 files changed, 608 insertions(+), 130 deletions(-) create mode 100644 app/Models/AgentPlus.php create mode 100644 app/Models/InfosCustomerAccountOpeningRequest.php create mode 100644 app/Models/PaymentAggregator.php create mode 100644 app/Models/PaymentTransaction.php create mode 100755 app/Models/Wallet.php diff --git a/.env.example b/.env.example index 9c49f8d..14d6606 100644 --- a/.env.example +++ b/.env.example @@ -25,3 +25,12 @@ NOTIFICATION_SERVICE_KEY=RfXvPQzQRgwpzQYPnLfWpZzgx4QseHlg SWAGGER_GENERATE_ALWAYS=true SWAGGER_DOCS_TOKEN=Zh7KRQyZGAMNXdTWq0d2f4X8qrMBaHN2 + +DEFAULT_COUNTRY_CODE=CM +DEFAULT_DIAL_CODE=+237 + +PAYMENT_SERVICE_URL=localhost:8087 +PAYMENT_SERVICE_KEY=U14YhuyFhweMeYpIYj8Ft2jm4cVgbMzD + +SEND_MAIL=false +PAYMENT_TEST_AMOUNT=100 diff --git a/app/Http/Controllers/CustomerAccountOpeningController.php b/app/Http/Controllers/CustomerAccountOpeningController.php index ea95ee6..a2d3702 100644 --- a/app/Http/Controllers/CustomerAccountOpeningController.php +++ b/app/Http/Controllers/CustomerAccountOpeningController.php @@ -9,16 +9,26 @@ use App\Enums\MaritalStatus; use App\Enums\ResidentialStatus; use App\Events\CustomerAccountRequestEvent; use App\Exceptions\AppException; +use App\Models\AgentPlus; use App\Models\CustomerAccountRequest; use App\Models\CustomerAccountRequestDocument; use App\Models\CustomerAccountType; use App\Models\Identification; +use App\Models\InfosCustomerAccountOpeningRequest; +use App\Models\PaymentAggregator; +use App\Models\PaymentTransaction; +use App\Models\User; +use App\Models\Wallet; +use App\Models\WalletsUser; +use GuzzleHttp\Client; use Illuminate\Http\Request; +use Illuminate\Http\Response; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; +use OpenApi\Annotations as OA; use Throwable; class CustomerAccountOpeningController extends Controller @@ -508,6 +518,7 @@ class CustomerAccountOpeningController extends Controller DB::beginTransaction(); $accountRequest = CustomerAccountRequest::create(array_merge($request->all(),[ + 'opening_amount' => $accountType->opening_amount, 'unique_id' => strtoupper(Str::random(12)) ])); @@ -536,11 +547,123 @@ class CustomerAccountOpeningController extends Controller return $this->successResponse(__('messages.customer_account_opening_request_submitted')); } - public function getCustomerRequests($user_id) + /** + * @OA\Get( + * path="/customers_accounts_requests", + * summary="Recuperer les demandes d'ouvertures", + * tags={"Agency Banking"}, + * security={{"api_key":{}}}, + * @OA\Parameter( + * parameter="user_id", + * name="user_id", + * description="ID de l'utilisateur", + * @OA\Schema( + * type="integer" + * ), + * in="query", + * required=false + * ), + * @OA\Parameter( + * parameter="network_id", + * name="network_id", + * description="ID du 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":19,"unique_id":"X4UK8JDG1Z0I","user_id":382,"network_id":239,"customer_account_type_id":4,"opening_amount":"80 000 FCFA", + * "opening_amount_payment_deadline":"2022-12-13","status":"EN COURS DE VALIDATION","reject_reason":null,"created_at":"2022-11-28T18:06:09.000000Z","account_type":{"id":4,"name":"Compte courant regulier salarie"}}}, + * "error":null + * } + * ) + * ) + * ) + */ + public function getRequests(Request $request) { - $requests = CustomerAccountRequest::where('user_id', $user_id)->get(); + $this->validate($request,[ + 'user_id' => 'nullable|integer|exists:users,id', + 'network_id' => 'nullable|integer|exists:networks,id' + ]); - return $this->successResponse($requests); + $user_id = $request->input('user_id'); + $network_id = $request->input('network_id'); + + $query = CustomerAccountRequest::with(['account_type:id,name']); + + $query->when($user_id, function ($q , $user_id){ + $q->where('user_id', $user_id); + }); + + $query->when($network_id, function ($q , $network_id){ + $q->where('network_id', $network_id); + }); + + $data = $query->select(['id','unique_id','user_id','network_id','customer_account_type_id','opening_amount','opening_amount_payment_deadline','status','reject_reason','created_at']) + ->get(); + + $data->map(function ($row){ + $this->formatCustomerRequest($row); + }); + + return $this->successResponse($data); + } + + + /** + * @OA\Get( + * path="/customers_accounts_requests/{id}", + * summary="Recuperer les details sur une demande d'ouverture", + * tags={"Agency Banking"}, + * security={{"api_key":{}}}, + * @OA\Parameter( + * parameter="id", + * name="id", + * description="ID de la demande", + * @OA\Schema( + * type="integer" + * ), + * in="path", + * required=true + * ), + * @OA\Response( + * response=200, + * description="OK", + * @OA\JsonContent( + * ref="#/components/schemas/ApiResponse", + * example = { + * "status" : 200, + * "response" : { "id": 19, "unique_id": "X4UK8JDG1Z0I", "user_id": 382, "network_id": 239, "customer_account_type_id": 4, "title": "M", "lastname": "Doe", "firstname": "John", "spouse_name": null, "nationality": "Cameroun", "birth_date": "1988-03-01", "birth_country": "Cameroun", + * "birth_city": "Douala", "birth_locality": null, "father_lastname": "Gates", "father_firstname": "", "mother_birth_lastname": "Marthe", "mother_firstname": null, "marital_status": "SINGLE", "spouse_lastname": null, "spouse_firstname": null, "profession": null, "business_activity": null, + * "sub_sector_business_activity": null, "tax_number": null, "security_number": null, "employee_number": null, "function": null, "employee_name": null, "employee_address": null, "residential_status": "RESIDENT", "residential_country": "Cameroun", "residence_permit_number": null, + * "residence_permit_issued_date": null, "residence_permit_expiry_date": null, "address_justification_doc": "LOCALISATION_PLAN", "address": "Douala", "po_box": null, "phone_number": "+237690716639", "email_1": "ddietchi@ilink-app.com", "email_2": null, "person_to_contact_in_case_of_needs_name": "Mark", + * "person_to_contact_in_case_of_needs_phone_number": "+237690716630", "identification_document_type": "CNI", "identification_document_number": "1232266", "identification_document_issued_date": "2019-03-10", "identification_document_expiry_date": "2039-03-10", "identification_document_issuance_city": "Douala", + * "identification_document_issuance_country": "Cameroun", "customer_under_guardianship": 0, "guardian_fullname": null, "guardian_fullname_phone_number": null, "how_did_you_know_company": "medias", "introducer_fullname": null, "introducer_address": null, "expected_service": "banking", "income_sources_and_frequency": null, + * "business_partners": null, "bank_references": null, "has_account_with_other_bank": 0, "has_operative_other_bank_account": 0, "has_engagement_with_other_banks": 1, "is_politically_exposed_person": 0, "is_politically_exposed_person_in_service": 0, "has_relationship_with_politically_exposed_person": 0, + * "relationship_with_politically_exposed_person": null, "email_alerts": 1, "e_statement_frequency": "DAILY", "e_package": 0, "debit_card_type": "CLASSIC_GOLD", "opening_amount": "80 000 FCFA", "opening_amount_payment_deadline": "2022-12-13", "status": "EN COURS DE VALIDATION", "reject_reason": null, + * "validating_agent_id": null, "created_at": "2022-11-28T18:06:09.000000Z", "updated_at": "2022-11-28T18:06:09.000000Z", "deleted_at": null, "account_type": { "id": 4, "name": "Compte courant regulier salarie" }, "documents": { { "request_id": 19, "name": "photo", "description": "photo", + * "url": "http://127.0.0.1:8088/requests-docs/CRD-23ccdda9-d234-4c18-a8b8-d637295b89c3.png" } } }, + * "error":null + * } + * ) + * ) + * ) + */ + public function getSingleRequest($id) + { + $accountRequest = CustomerAccountRequest::with(['account_type:id,name','documents:request_id,name,description,url'])->where('id', $id)->firstOrFail(); + $this->formatCustomerRequest($accountRequest); + + return $this->successResponse($accountRequest); } public function treatRequest($id, Request $request) @@ -564,7 +687,6 @@ class CustomerAccountOpeningController extends Controller $type = $request->input('type'); $mailParams = ['name' => $accountRequest->user->lastname, 'request_id' => $accountRequest->unique_id, 'reason' => $request->input('reason'), 'gender' => $accountRequest->title, 'account_type' => $accountRequest->account_type->name, - 'opening_amount' => $this->toMoneyWithNetwork($accountRequest->account_type->opening_amount, $accountRequest->network_id) ]; $notificationParams = ['request_id' => $accountRequest->unique_id]; @@ -576,9 +698,18 @@ class CustomerAccountOpeningController extends Controller $notification = trans('messages.customer_account_opening_request_rejected_notification', $notificationParams); break; case 'ACCEPT': - $accountRequest->status = CustomerAccountRequest::ACCEPTED; + if(!empty($accountRequest->opening_amount)){ + $mailParams['opening_amount'] = $this->toMoneyWithNetwork($accountRequest->opening_amount, $accountRequest->network_id); + $accountRequest->status = CustomerAccountRequest::ACCEPTED_UNPAID; + $accountRequest->opening_amount_payment_deadline = Carbon::now()->addDays($accountRequest->account_type->opening_amount_payment_period_days); + $mailParams['deadline'] = $accountRequest->opening_amount_payment_deadline; + $mailMessage = trans('messages.customer_account_opening_request_accepted_unpaid_mail', $mailParams); + }else{ + $accountRequest->status = CustomerAccountRequest::ACCEPTED; + $mailMessage = trans('messages.customer_account_opening_request_accepted_mail', $mailParams); + } + $mailTitle = trans('messages.customer_account_opening_request_accepted'); - $mailMessage = trans('messages.customer_account_opening_request_accepted_mail', $mailParams); $notification = trans('messages.customer_account_opening_request_accepted_notification', $notificationParams); break; default: @@ -704,4 +835,198 @@ class CustomerAccountOpeningController extends Controller return $this->successResponse($data); } + + /** + * @OA\Post( + * path="/customers_accounts_requests/pay", + * summary="Payer le montant requis pour la demande d'ouverture du compte", + * tags={"Agency Banking"}, + * security={{"api_key":{}}}, + * @OA\RequestBody( + * description="Corps de la requete", + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property(property="user_id", + * type="integer", + * example = 10, + * description="ID de l'utilisateur" + * ), + * @OA\Property( property="password", + * type="string", + * example = "1234", + * description="Mot de passe de l'utilisateur" + * ), + * @OA\Property( property="request_id", + * type="integer", + * example = 39, + * description="ID de la demande d'ouverture de compte" + * ), + * @OA\Property(property="payment_method", + * type="string", + * enum = {"wallet" ,"mobile_money","card"}, + * example = "wallet", + * description="Methode de paiement" + * ), + * @OA\Property(property="payment_phone", + * type="string", + * example = "+237690716639", + * description="Numero de telephone avec lequel on souhaite payer de paiement" + * ), + * @OA\Property(property="payment_transaction_id", + * type="string", + * example = "ASMFOSDFFDODF", + * description="ID de la transaction de paiement" + * ), + * @OA\Property(property="payment_token", + * type="string", + * example = "ASMFOSDFFDODF", + * description="Token la transaction de paiement" + * ) + * ) + * ) + * ), + * @OA\Response( + * response=200, + * description="OK", + * @OA\JsonContent( + * ref="#/components/schemas/ApiResponse", + * example = { + * "status" : 200, + * "response" : "Transaction réussie", + * "error":null + * } + * ) + * ) + * ) + */ + public function payOpeningAmount(Request $request) + { + $this->validate($request, [ + 'request_id' => 'required|integer|exists:customer_account_opening_requests,id', + 'user_id' => 'required|integer|exists:users,id', + 'password' => 'required', + 'payment_method' => 'required|string', //wallet,MTN-Money,Orange-Money + 'payment_phone' => 'required_unless:payment_method,wallet,cash|string', + 'payment_transaction_id' => 'nullable|exists:payment_transactions,transaction_id', // A envoyer apres avoir effectuer le paiement + 'payment_token' => 'required_with:payment_transaction_id|string', // A envoyer apres avoir effectuer le paiement, + 'otp' => 'nullable|string' + ]); + + $payment_method = $request->input('payment_method'); + $transaction_id = $request->input('payment_transaction_id'); + + $accountRequest = InfosCustomerAccountOpeningRequest::findOrFail($request->input('request_id')); + if($accountRequest->status != CustomerAccountRequest::ACCEPTED_UNPAID){ + return $this->errorResponse(__('errors.request_already_processed')); + } + + $user = User::findOrFail($request->input('user_id')); + if (!$this->checkPassword($request->input('password'), $user->encrypted_password, $user->salt)) + return $this->errorResponse(trans('messages.incorrect_user_password')); + + $county = $user->network->country; + $amountToPaid = $accountRequest->opening_amount; + + if (empty($transaction_id)) { + + switch ($payment_method) { + case 'wallet': + $walletUser = WalletsUser::where('idUser', $user->id)->firstOrFail(); + if ($walletUser->balance < $amountToPaid) { + return $this->errorResponse(trans('errors.insufficient_balance', ['amount' => $this->toMoneyWithCurrencyCode($amountToPaid, $accountRequest->currency_code)])); + } + break; + default : + $aggregator = PaymentAggregator::where('status', 1)->first(); + if (!$aggregator) { + return $this->errorResponse(trans('errors.payment_not_available')); + } + } + + } else { + $transaction = PaymentTransaction::where('transaction_id', $transaction_id)->where('payment_token', $request->input('payment_token'))->where('state', 'ACCEPTED')->first(); + if (!$transaction) { + return $this->errorResponse(trans('errors.payment_not_found'), 404); + } + + $accountRequest = InfosCustomerAccountOpeningRequest::where('payment_transaction_id', $transaction_id)->first(); + if ($accountRequest) { + return $this->errorResponse(trans('errors.payment_invalid'), 400); + } + } + + $hyperviseur = AgentPlus::where('category', 'hyper')->where('network_id', $accountRequest->network_id)->firstOrFail(); + $walletHyperviseur = Wallet::where('id_agent', $hyperviseur->id)->firstOrFail(); + + $datetime = $this->getCurrentTimeByCountryCode($county->code_country); + + try { + DB::beginTransaction(); + + $walletHyperviseur->balance_princ += $amountToPaid; + $walletHyperviseur->save(); + + if (empty($transaction_id)) { + if ($payment_method == 'wallet') { + $walletUser->balance -= $amountToPaid; + $walletUser->save(); + } else { + // Pay through payment service + $client = new Client([ + 'base_uri' => config('variables.payment_service_url'), + 'headers' => [ + 'Authorization' => config('variables.payment_service_key'), + ] + ]); + + + $paymentResponse = $client->post('/pay', [ + 'json' => [ + 'aggregator_id' => $aggregator->id, + 'amount' => config('variables.payment_test_amount', $amountToPaid), + 'currency' => $accountRequest->currency_code, + 'customer_id' => $user->id, + 'customer_email' => $user->email, + 'customer_name' => $user->lastname, + 'customer_surname' => $user->lastname, + 'customer_phone_number' => $request->input('payment_phone'), + 'customer_address' => $user->adresse, + 'customer_country' => $county->name ?? '', + 'customer_city' => $user->adresse, + 'customer_state' => $county->code_country ?? '', + 'customer_zip_code' => '00237', + 'payment_method' => $request->input('payment_method'), + 'reason' => 'N° '.__('messages.customer_account_opening_request').": ".$accountRequest->unique_id, + 'otp' => $request->input('otp') + ], + 'http_errors' => false + ]); + + $responseData = json_decode($paymentResponse->getBody()->getContents()); + $responseCode = $paymentResponse->getStatusCode(); + if ($responseCode == 200) { +// $transaction_id = $responseData->response->transaction_id; + return $this->successResponse($responseData->response); + } else { + return $this->errorResponse($responseData->error ?? trans('errors.unexpected_error'), $responseCode); + } + } + } + + CustomerAccountRequest::where('id', $accountRequest->id)->update([ + 'status' => CustomerAccountRequest::ACCEPTED_PAID, + 'payment_transaction_id' => $transaction_id, + 'updated_at' => $datetime + ]); + + DB::commit(); + } catch (Throwable $e) { + DB::rollBack(); + Log::error($e->getMessage()); + return $this->errorResponse(trans('errors.unexpected_error')); + } + return $this->successResponse(trans('messages.successful_paid_receipt'),Response::HTTP_CREATED); + } } diff --git a/app/Models/AgentPlus.php b/app/Models/AgentPlus.php new file mode 100644 index 0000000..45de20d --- /dev/null +++ b/app/Models/AgentPlus.php @@ -0,0 +1,110 @@ + 'int', + 'longitude' => 'float', + 'latitude' => 'float', + 'active' => 'int', + 'solde' => 'float', + 'etat' => 'int', + 'id_country' => 'int', + 'number_geoBysuper' => 'int', + 'number_super' => 'int', + 'network_id' => 'int', + 'id_network_agent' => 'int' + ]; + + protected $dates = [ + 'created', + 'openHours', + 'closeHours' + ]; + + protected $hidden = [ + 'encrypted_password' + ]; + + protected $fillable = [ + 'id', + 'uid', + 'firstname', + 'adresse', + 'lastname', + 'email', + 'encrypted_password', + 'salt', + 'longitude', + 'latitude', + 'phone', + 'active', + 'created', + 'openHours', + 'closeHours', + 'solde', + 'etat', + 'network', + 'country', + 'country_code', + 'id_country', + 'code_parrain', + 'category', + 'code_membre', + 'number_geoBysuper', + 'number_super', + 'network_id', + 'code_dial', + 'transactionNumber', + 'id_network_agent' + ]; +} diff --git a/app/Models/CustomerAccountRequest.php b/app/Models/CustomerAccountRequest.php index 7b84b01..c67a13a 100644 --- a/app/Models/CustomerAccountRequest.php +++ b/app/Models/CustomerAccountRequest.php @@ -13,6 +13,9 @@ class CustomerAccountRequest extends Model const AWAITING_FURTHER_INFORMATION = 'AWAITING_FURTHER_INFORMATION'; const ACCEPTED = 'ACCEPTED'; const REJECTED = 'REJECTED'; + const ACCEPTED_UNPAID = 'ACCEPTED_UNPAID'; + const ACCEPTED_PAID = 'ACCEPTED_PAID'; + const CANCELLED = 'CANCELLED'; public function user() { @@ -24,4 +27,9 @@ class CustomerAccountRequest extends Model return $this->belongsTo(CustomerAccountType::class, 'customer_account_type_id'); } + public function documents() + { + return $this->hasMany(CustomerAccountRequestDocument::class, 'request_id'); + } + } diff --git a/app/Models/InfosCustomerAccountOpeningRequest.php b/app/Models/InfosCustomerAccountOpeningRequest.php new file mode 100644 index 0000000..bc56785 --- /dev/null +++ b/app/Models/InfosCustomerAccountOpeningRequest.php @@ -0,0 +1,10 @@ + 'float', + 'balance_com' => 'float', + 'id_agent' => 'int' + ]; + + protected $dates = [ + 'created_date' + ]; + + protected $fillable = [ + 'balance_princ', + 'balance_com', + 'id_agent', + 'created_date' + ]; + + public function agent() + { + return $this->belongsTo(Agent::class, 'id_agent'); + } + + +} diff --git a/app/Traits/Helper.php b/app/Traits/Helper.php index 2f3089e..442b64f 100644 --- a/app/Traits/Helper.php +++ b/app/Traits/Helper.php @@ -5,37 +5,17 @@ namespace App\Traits; use App\Exceptions\AppException; -use App\Models\Agent; -use App\Models\AgentPlus; -use App\Models\CodeGenerer; -use App\Models\ConfigWallet; use App\Models\CountriesCurrency; use App\Models\Country; use App\Models\Identification; -use App\Models\InfosUsersGroup; use App\Models\Network; -use App\Models\NetworksAgent; -use App\Models\User; -use App\Models\UsersDemandesCredit; -use App\Models\Wallet; -use App\Models\WalletAgent; -use App\Models\WalletIlinkTransaction; -use App\Models\WalletsUser; -use Barryvdh\DomPDF\Facade as PDF; -use Brick\Math\RoundingMode; use Brick\Money\Context\AutoContext; -use Brick\Money\CurrencyConverter; -use Brick\Money\ExchangeRateProvider\BaseCurrencyProvider; -use Brick\Money\ExchangeRateProvider\PDOProvider; -use Brick\Money\ExchangeRateProvider\PDOProviderConfiguration; use Brick\Money\Money; -use Carbon\Carbon; use Exception; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\File; -use Illuminate\Support\Facades\Input; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Str; @@ -172,74 +152,6 @@ trait Helper return $money->formatTo(app()->getLocale()); } - private function convertMoney($amount, $init_country, $final_country) - { - // set to whatever your rates are relative to - $baseCurrency = 'USD'; - -// use your own credentials, or re-use your existing PDO connection - $pdo = new PDO('mysql:host=' . env('DB_HOST') . ';dbname=' . env('DB_DATABASE'), env('DB_USERNAME'), env('DB_PASSWORD')); - - $configuration = new PDOProviderConfiguration(); - - $configuration->tableName = 'exchange_rate'; - $configuration->exchangeRateColumnName = 'exchange_rate'; - $configuration->targetCurrencyColumnName = 'target_currency'; - $configuration->sourceCurrencyCode = $baseCurrency; - -// this provider loads exchange rates from your database - $provider = new PDOProvider($pdo, $configuration); - -// this provider calculates exchange rates relative to the base currency - $provider = new BaseCurrencyProvider($provider, $baseCurrency); - -// this currency converter can now handle any currency pair - $converter = new CurrencyConverter($provider); - $init_country = Country::findOrFail($init_country); - $final_country = Country::findOrFail($final_country); - $init_money = Money::of(round($amount, 2), $init_country->currency->code, new AutoContext()); - return $converter->convert($init_money, $final_country->currency->code, RoundingMode::DOWN); - } - - public function toMoneyWithCurrency($amount, $init_country, $final_country) - { - return $this->convertMoney($amount, $init_country, $final_country)->formatTo(app()->getLocale()); - } - - public function toMoneyAmount($amount, $init_country, $final_country) - { - return $this->convertMoney($amount, $init_country, $final_country)->getAmount()->toFloat(); - } - - public function toUSDAmount($amount, $init_country, $final_currency_code = 'USD') - { - // set to whatever your rates are relative to - $baseCurrency = 'USD'; - -// use your own credentials, or re-use your existing PDO connection - $pdo = new PDO('mysql:host=' . env('DB_HOST') . ';dbname=' . env('DB_DATABASE'), env('DB_USERNAME'), env('DB_PASSWORD')); - - $configuration = new PDOProviderConfiguration(); - - $configuration->tableName = 'exchange_rate'; - $configuration->exchangeRateColumnName = 'exchange_rate'; - $configuration->targetCurrencyColumnName = 'target_currency'; - $configuration->sourceCurrencyCode = $baseCurrency; - -// this provider loads exchange rates from your database - $provider = new PDOProvider($pdo, $configuration); - -// this provider calculates exchange rates relative to the base currency - $provider = new BaseCurrencyProvider($provider, $baseCurrency); - -// this currency converter can now handle any currency pair - $converter = new CurrencyConverter($provider); - $init_country = Country::findOrFail($init_country); - $init_money = Money::of(round($amount, 2), $init_country->currency->code, new AutoContext()); - return $converter->convert($init_money, $final_currency_code, RoundingMode::DOWN)->getAmount()->toFloat(); - } - - // public function getTransactionID(){ // $d = new DateTime(); // $first = str_replace(['-',':'], '',$d->format("y-m-d H:i:s.u")); @@ -346,29 +258,6 @@ trait Helper } } - public function generateQRCode($user_id, $user_type) - { - if ($user_type == 'user') { - $user = User::findOrFail($user_id); - } else { - $user = Agent::findOrFail($user_id); - } - - //Check if the directory already exists. - $directoryName = '/qrcodes/' . $user_type . 's/'; - if (!is_dir(public_path() . $directoryName)) { - File::makeDirectory(public_path() . $directoryName, 0777, true); - } - - $path = $directoryName . $user->id . '.pdf'; - $pdf = PDF::loadView('emails.qr_code', ['lastname' => $user->lastname, 'data' => 'type=' . $user_type . '&user_id=' . $user->id]) - ->setPaper('a4', 'portrait')->setWarnings(false)->save(public_path($path)); - - $user->qr_code = config('app.url') . $path; - $user->save(); - - return $pdf; - } /** * @throws Exception @@ -461,4 +350,11 @@ trait Helper return $destination; } + function formatCustomerRequest($request){ + if(!empty($request->opening_amount)) { + $request->opening_amount = $this->toMoneyWithNetwork($request->opening_amount,$request->network_id); + } + $request->status = __('states.'.$request->status); + } + } diff --git a/composer.json b/composer.json index e0f6388..e89ebc3 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "guzzlehttp/guzzle": "^7.5", "laravel/lumen-framework": "^9.0", "ext-gd": "*", - "ext-json": "*" + "ext-json": "*", + "ext-pdo": "*" }, "require-dev": { "fakerphp/faker": "^1.9.1", diff --git a/config/variables.php b/config/variables.php index 8fb3263..647cf09 100644 --- a/config/variables.php +++ b/config/variables.php @@ -1,4 +1,9 @@ env('SEND_EMAIL', true) + 'send_email' => env('SEND_EMAIL', true), + 'default_county_code' => env('DEFAULT_COUNTRY_CODE', 'GA'), + 'default_dial_code' => env('DEFAULT_DIAL_CODE', '+241'), + 'payment_service_url' => env('PAYMENT_SERVICE_URL',''), + 'payment_service_key' => env('PAYMENT_SERVICE_KEY',''), + 'payment_test_amount' => env('PAYMENT_TEST_AMOUNT') ]; diff --git a/database/migrations/2022_10_07_070344_create_customer_account_types_table.php b/database/migrations/2022_10_07_070344_create_customer_account_types_table.php index 9405815..fba7d90 100644 --- a/database/migrations/2022_10_07_070344_create_customer_account_types_table.php +++ b/database/migrations/2022_10_07_070344_create_customer_account_types_table.php @@ -19,6 +19,7 @@ class CreateCustomerAccountTypesTable extends Migration $table->string('name')->unique(); $table->text('description')->nullable(); $table->double('opening_amount')->nullable(); + $table->unsignedInteger('opening_amount_payment_period_days')->nullable(); $table->integer('parent_id')->nullable(); $table->timestamp('created_at')->useCurrent(); $table->timestamp('updated_at')->useCurrent(); diff --git a/database/migrations/2022_10_13_171009_create_customer_account_opening_requests_table.php b/database/migrations/2022_10_13_171009_create_customer_account_opening_requests_table.php index 36ed1e8..1caf499 100644 --- a/database/migrations/2022_10_13_171009_create_customer_account_opening_requests_table.php +++ b/database/migrations/2022_10_13_171009_create_customer_account_opening_requests_table.php @@ -84,6 +84,9 @@ class CreateCustomerAccountOpeningRequestsTable extends Migration $table->string('e_statement_frequency')->nullable(); $table->boolean('e_package')->default(false); $table->string('debit_card_type'); + $table->double('opening_amount')->nullable(); + $table->date('opening_amount_payment_deadline')->nullable(); + $table->string('payment_transaction_id')->unique()->nullable(); $table->string('status')->default('UNDER_VALIDATION'); $table->text('reject_reason')->nullable(); $table->integer('validating_agent_id')->nullable(); diff --git a/database/migrations/2022_10_19_120130_create_infos_customer_account_opening_requests_view.php b/database/migrations/2022_10_19_120130_create_infos_customer_account_opening_requests_view.php index cc2881e..a8932d6 100644 --- a/database/migrations/2022_10_19_120130_create_infos_customer_account_opening_requests_view.php +++ b/database/migrations/2022_10_19_120130_create_infos_customer_account_opening_requests_view.php @@ -18,12 +18,15 @@ class CreateInfosCustomerAccountOpeningRequestsView extends Migration SELECT cr.*, ct.name as customer_account_type_name , ct.description as customer_account_type_description, ct.opening_amount as customer_account_type_opening_amount, + cc.currency_code, `nva`.`lastname` AS `validating_agent_lastname`, `nva`.`firstname` AS `validating_agent_firstname`, `nva`.`phone` AS `validating_agent_phone`, `nva`.`email` AS `validating_agent_email` FROM customer_account_opening_requests cr JOIN customer_account_types ct ON ct.id = cr.customer_account_type_id + JOIN networks nt ON nt.id = cr.network_id + JOIN countries_currencies cc ON cc.id = nt.country_id LEFT JOIN nh_validating_agents nva ON cr.validating_agent_id = nva.id "); } diff --git a/resources/lang/en/errors.php b/resources/lang/en/errors.php index 51527a7..ca7af1f 100755 --- a/resources/lang/en/errors.php +++ b/resources/lang/en/errors.php @@ -4,5 +4,10 @@ return [ 'unexpected_error' => 'Unexpected error. Try later', 'validation_error' => 'The field :field has :validation', 'service_unavailable' => 'Service unavailable', - "amount_not_allowed" => "This amount is not allowed. It must be between :min and :max" + "amount_not_allowed" => "This amount is not allowed. It must be between :min and :max", + "request_already_processed" => "This request has already been processed", + 'insufficient_balance' => 'Your balance is insufficient to complete this transaction. You will need to charge :amount', + 'payment_not_available' => "Payment not available at this time. Please try again later", + 'payment_not_found' => "Payment not found", + 'payment_invalid' => "Invalid payment" ]; diff --git a/resources/lang/en/messages.php b/resources/lang/en/messages.php index 6cc21a6..4fb1ead 100755 --- a/resources/lang/en/messages.php +++ b/resources/lang/en/messages.php @@ -30,16 +30,22 @@ Your customer account opening request is being validated. 'customer_account_opening_request_accepted' => "Customer account opening request accepted", 'customer_account_opening_request_accepted_mail' => ":gender :name, +Your customer account opening request has been accepted. + Request information: + - ID: :request_id + - Account type: :account_type + ", + 'customer_account_opening_request_accepted_unpaid_mail' => ":gender :name, + Your customer account opening request has been accepted. Request information: - ID: :request_id - Account type: :account_type - Opening amount: :opening_amount - Go to the nearest branch to complete the process + You can proceed to pay the opening amount to complete the process before the :deadline. ", - 'customer_account_opening_request_accepted_notification' => "Your customer account opening request :request_id has been accepted. - Please ensure that your wallet has sufficient credit to activate your insurance.", + 'customer_account_opening_request_accepted_notification' => "Your customer account opening request :request_id has been accepted", 'customer_account_opening_request_rejected' => "Customer account opening request rejected", 'customer_account_opening_request_rejected_mail' => ":gender :name, @@ -60,5 +66,6 @@ Your customer account opening request is waiting for more information. - Opening amount: :opening_amount Message: :reason", - 'customer_account_opening_request_awaiting_more_information_notification' => "Your customer account opening request :subscription_id is awaiting more information." + 'customer_account_opening_request_awaiting_more_information_notification' => "Your customer account opening request :subscription_id is awaiting more information.", + 'successful_paid_customer_account_opening_request' => "Customer account opening request paid successfully", ]; diff --git a/resources/lang/en/states.php b/resources/lang/en/states.php index ba06dae..1cabfb3 100755 --- a/resources/lang/en/states.php +++ b/resources/lang/en/states.php @@ -20,4 +20,7 @@ return [ 'VISA_CARD_CLASSIC' => 'VISA Card Classic', 'VISA_CARD_GOLD' => 'VISA Card Gold', 'VISA_CARD_PLATINUM' => 'VISA Card Platinum', + 'UNDER_VALIDATION' => 'UNDER VALIDATION', + 'ACCEPTED_UNPAID' => 'ACCEPTED UNPAID', + 'ACCEPTED_PAID' => 'ACCEPTED PAID' ]; diff --git a/resources/lang/fr/errors.php b/resources/lang/fr/errors.php index d178516..db59bd8 100755 --- a/resources/lang/fr/errors.php +++ b/resources/lang/fr/errors.php @@ -4,5 +4,10 @@ return [ 'unexpected_error' => 'Erreur inattendue. Essayer plus tard', 'validation_error' => 'Le champ :field a :validation', 'service_unavailable' => 'Service non disponible', - "amount_not_allowed" => "Ce montant n'est pas autorisé. Il doit être compris entre :min et :max" + "amount_not_allowed" => "Ce montant n'est pas autorisé. Il doit être compris entre :min et :max", + "request_already_processed" => "Cette requete a déja ete traitée", + 'insufficient_balance' => 'Votre solde est insuffisant pour effectuer cette transaction. Vous devrez recharger :amount', + 'payment_not_available' => "Paiement non disponible pour le moment. Veuillez réessayer plus tard", + 'payment_not_found' => "Paiement non trouvé", + 'payment_invalid' => "Paiement invalide" ]; diff --git a/resources/lang/fr/messages.php b/resources/lang/fr/messages.php index af651c2..dbe99c0 100755 --- a/resources/lang/fr/messages.php +++ b/resources/lang/fr/messages.php @@ -30,16 +30,22 @@ Votre demande d'ouverture de compte client est en cours de validation. 'customer_account_opening_request_accepted' => "Demande d'ouverture de compte client acceptée", 'customer_account_opening_request_accepted_mail' => ":gender :name , +Votre demande d'ouverture de compte client a été acceptée. + Informations de la demande : + - ID : :request_id + - Type de compte : :account_type + ", + 'customer_account_opening_request_accepted_unpaid_mail' => ":gender :name , + Votre demande d'ouverture de compte client a été acceptée. Informations de la demande : - ID : :request_id - Type de compte : :account_type - Montant d'ouverture: :opening_amount - Rendez-vous à l'agence la plus proche pour terminer le processus + Vous pouvez procéder au paiement du montant d'ouverture pour terminer le processus avant le :deadline. ", - 'customer_account_opening_request_accepted_notification' => "Votre demande d'ouverture de compte client :request_id a été acceptée. - Assurer-vous que votre wallet a le crédit suffisant pour activer votre assurance", + 'customer_account_opening_request_accepted_notification' => "Votre demande d'ouverture de compte client :request_id a été acceptée", 'customer_account_opening_request_rejected' => "Demande d'ouverture de compte client rejetée", 'customer_account_opening_request_rejected_mail' => ":gender :name , @@ -61,4 +67,5 @@ Votre demande d'ouverture de compte client est en attente de plus d'informations Message : :reason", 'customer_account_opening_request_awaiting_more_information_notification' => "Votre demande d'ouverture de compte client :subscription_id est en attente de plus d'informations.", + 'successful_paid_customer_account_opening_request' => "Demande d'ouverture de compte client payée avec succès", ]; diff --git a/resources/lang/fr/states.php b/resources/lang/fr/states.php index 0c64b88..efca48f 100755 --- a/resources/lang/fr/states.php +++ b/resources/lang/fr/states.php @@ -19,4 +19,7 @@ return [ 'VISA_CARD_CLASSIC' => 'VISA Card Classic', 'VISA_CARD_GOLD' => 'VISA Card Gold', 'VISA_CARD_PLATINUM' => 'VISA Card Platinum', + 'UNDER_VALIDATION' => 'EN COURS DE VALIDATION', + 'ACCEPTED_UNPAID' => 'ACCEPTÉ NON PAYÉ', + 'ACCEPTED_PAID' => 'ACCEPTÉ PAYÉ' ]; diff --git a/routes/web.php b/routes/web.php index d8e4c10..fcf77c3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -17,8 +17,10 @@ $router->group(['prefix' => '', 'middleware' => 'auth'], function () use ($route // Customers opening account $router->group(['prefix' => '/customers_accounts_requests'], function () use ($router) { $router->get('formData', 'CustomerAccountOpeningController@getFormData'); + $router->post('pay', 'CustomerAccountOpeningController@payOpeningAmount'); $router->post('', 'CustomerAccountOpeningController@submit'); - $router->get('{user_id}', 'CustomerAccountOpeningController@getCustomerRequests'); - $router->put('{id}/treat', 'CustomerAccountOpeningController@treatRequest'); + $router->get('', 'CustomerAccountOpeningController@getRequests'); + $router->get('{id}', 'CustomerAccountOpeningController@getSingleRequest'); + $router->put('{id}', 'CustomerAccountOpeningController@treatRequest'); }); });