Implements payment of customer account opening request
This commit is contained in:
parent
8ba0a973a5
commit
9ef8021dc3
|
@ -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
|
||||
|
|
|
@ -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':
|
||||
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;
|
||||
$mailTitle = trans('messages.customer_account_opening_request_accepted');
|
||||
$mailMessage = trans('messages.customer_account_opening_request_accepted_mail', $mailParams);
|
||||
}
|
||||
|
||||
$mailTitle = trans('messages.customer_account_opening_request_accepted');
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Created by Reliese Model.
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class AgentPlus
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $uid
|
||||
* @property string|null $firstname
|
||||
* @property string $adresse
|
||||
* @property string|null $lastname
|
||||
* @property string|null $email
|
||||
* @property string|null $encrypted_password
|
||||
* @property string|null $salt
|
||||
* @property float|null $longitude
|
||||
* @property float|null $latitude
|
||||
* @property string|null $phone
|
||||
* @property int|null $active
|
||||
* @property Carbon|null $created
|
||||
* @property Carbon|null $openHours
|
||||
* @property Carbon|null $closeHours
|
||||
* @property float|null $solde
|
||||
* @property int|null $etat
|
||||
* @property string $network
|
||||
* @property string $country
|
||||
* @property string $country_code
|
||||
* @property int $id_country
|
||||
* @property string|null $code_parrain
|
||||
* @property string|null $category
|
||||
* @property string|null $code_membre
|
||||
* @property int|null $number_geoBysuper
|
||||
* @property int|null $number_super
|
||||
* @property int $network_id
|
||||
* @property string $code_dial
|
||||
* @property string|null $transactionNumber
|
||||
* @property int $id_network_agent
|
||||
*
|
||||
* @package App\Models
|
||||
*/
|
||||
class AgentPlus extends Model
|
||||
{
|
||||
protected $table = 'agent_plus';
|
||||
public $incrementing = false;
|
||||
public $timestamps = false;
|
||||
|
||||
protected $casts = [
|
||||
'id' => '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'
|
||||
];
|
||||
}
|
|
@ -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');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class InfosCustomerAccountOpeningRequest extends Model
|
||||
{
|
||||
protected $table = 'infos_customer_account_opening_requests';
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class PaymentAggregator extends Model
|
||||
{
|
||||
protected $table = 'payment_aggregators';
|
||||
protected $guarded = ['id'];
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class PaymentTransaction extends Model
|
||||
{
|
||||
protected $table = 'payment_transactions';
|
||||
protected $guarded = ['id'];
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Created by Reliese Model.
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class Wallet
|
||||
*
|
||||
* @property int $id
|
||||
* @property float $balance_princ
|
||||
* @property float $balance_com
|
||||
* @property int $id_agent
|
||||
* @property Carbon $created_date
|
||||
*
|
||||
* @property NetworksAgent $networks_agent
|
||||
*
|
||||
* @package App\Models
|
||||
*/
|
||||
class Wallet extends Model
|
||||
{
|
||||
protected $table = 'wallets';
|
||||
public $timestamps = false;
|
||||
|
||||
protected $casts = [
|
||||
'balance_princ' => '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');
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
<?php
|
||||
return [
|
||||
'send_email' => 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')
|
||||
];
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
");
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
];
|
||||
|
|
|
@ -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",
|
||||
];
|
||||
|
|
|
@ -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'
|
||||
];
|
||||
|
|
|
@ -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"
|
||||
];
|
||||
|
|
|
@ -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",
|
||||
];
|
||||
|
|
|
@ -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É'
|
||||
];
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue