1033 lines
49 KiB
PHP
1033 lines
49 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers;
|
||
|
||
use App\Enums\CreditCardType;
|
||
use App\Enums\DocumentType;
|
||
use App\Enums\Frequency;
|
||
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
|
||
{
|
||
//
|
||
|
||
/**
|
||
* @OA\Post(
|
||
* path="/customers_accounts_requests",
|
||
* summary="Soumettre le formulaire d'ouverture de comptele",
|
||
* tags={"Agency Banking"},
|
||
* security={{"api_key":{}}},
|
||
* @OA\RequestBody(
|
||
* description="Corps de la requete",
|
||
* required=true,
|
||
* @OA\MediaType(
|
||
* mediaType="multipart/form-data",
|
||
* @OA\Schema(
|
||
* @OA\Property(property="user_id",
|
||
* type="integer",
|
||
* example=308,
|
||
* description="ID de l'utilisateur enregistré dans la base de données"
|
||
* ),
|
||
* @OA\Property(property="network_id",
|
||
* type="integer",
|
||
* example=4,
|
||
* description="ID du réseau auquel appartient il souhaitre faire sa demande"
|
||
* ),
|
||
* @OA\Property(property="customer_account_type_id",
|
||
* type="integer",
|
||
* example=101,
|
||
* description="ID du type de compte"
|
||
* ),
|
||
* @OA\Property(property="title",
|
||
* type="string",
|
||
* example = "Mr",
|
||
* description="Title"
|
||
* ),
|
||
* @OA\Property(property="lastname",
|
||
* type="string",
|
||
* example = "John",
|
||
* description="Noms"
|
||
* ),
|
||
* @OA\Property(property="firstname",
|
||
* type="string",
|
||
* example = "Doe",
|
||
* description="Prenoms"
|
||
* ),
|
||
* @OA\Property(property="spouse_name",
|
||
* type="string",
|
||
* example = "Bill",
|
||
* description="Nom Marital"
|
||
* ),
|
||
* @OA\Property(property="nationality",
|
||
* type="string",
|
||
* example = "Camerounaise",
|
||
* description="Nationalité"
|
||
* ),
|
||
* @OA\Property(property="birth_date",
|
||
* type="date",
|
||
* example = "1990-06-15",
|
||
* description=" Date de naissance"
|
||
* ),
|
||
* @OA\Property(property="birth_city",
|
||
* type="string",
|
||
* example = "Douala",
|
||
* description="Ville de naissance"
|
||
* ),
|
||
* @OA\Property(property="birth_country",
|
||
* type="string",
|
||
* example = "Cameroun",
|
||
* description="Pays de naissance"
|
||
* ),
|
||
* @OA\Property(property="birth_locality",
|
||
* type="string",
|
||
* example = "Akwa",
|
||
* description="Lieu exact de naissance"
|
||
* ),
|
||
* @OA\Property(property="father_lastname",
|
||
* type="string",
|
||
* example = "Doe",
|
||
* description="Nom du père"
|
||
* ),
|
||
* @OA\Property(property="father_firstname",
|
||
* type="string",
|
||
* example = "Doe",
|
||
* description="Prénom du père"
|
||
* ),
|
||
* @OA\Property(property="mother_birth_lastname",
|
||
* type="string",
|
||
* example = "Elize",
|
||
* description="Nom de naissance de la mère"
|
||
* ),
|
||
* @OA\Property(property="mother_firstname",
|
||
* type="string",
|
||
* example = "marie",
|
||
* description="Prénom de la mère"
|
||
* ),
|
||
* @OA\Property(property="marital_status",
|
||
* type="string",
|
||
* example = "SINGLE",
|
||
* description="Situation matrimoniale"
|
||
* ),
|
||
* @OA\Property(property="spouse_lastname",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Nom du conjoint"
|
||
* ),
|
||
* @OA\Property(property="spouse_firstname",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Prénom du conjoint"
|
||
* ),
|
||
* @OA\Property(property="profession",
|
||
* type="string",
|
||
* example = "Student",
|
||
* description="Profession"
|
||
* ),
|
||
* @OA\Property(property="business_activity",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Secteur d'activité économique"
|
||
* ),
|
||
* @OA\Property(property="sub_sector_business_activity",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Sous secteur d'activité"
|
||
* ),
|
||
* @OA\Property(property="tax_number",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Numéro Fiscal"
|
||
* ),
|
||
* @OA\Property(property="security_number",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Numéro de sécurité sociale"
|
||
* ),
|
||
* @OA\Property(property="employee_number",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Numéro de l'employeur"
|
||
* ),
|
||
* @OA\Property(property="function",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Fonction"
|
||
* ),
|
||
* @OA\Property(property="employee_name",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Nom de l'employeur"
|
||
* ),
|
||
* @OA\Property(property="employee_address",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Addresse de l'employeur"
|
||
* ),
|
||
* @OA\Property(property="residential_status",
|
||
* type="string",
|
||
* example = "RESIDENT",
|
||
* description="Status de résident"
|
||
* ),
|
||
* @OA\Property(property="residential_country",
|
||
* type="string",
|
||
* example = "Cameroun",
|
||
* description="Pays de résidence"
|
||
* ),
|
||
* @OA\Property(property="residence_permit_number",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Numéro de permis de séjour"
|
||
* ),
|
||
* @OA\Property(property="residence_permit_issued_date",
|
||
* type="date",
|
||
* example = "",
|
||
* description="Date de délivrance du permis"
|
||
* ),
|
||
* @OA\Property(property="residence_permit_expiry_date",
|
||
* type="date",
|
||
* example = "",
|
||
* description="Date d'expiration du permis"
|
||
* ),
|
||
* @OA\Property(property="address_justification_doc",
|
||
* type="string",
|
||
* example = "LOCALISATION_PLAN",
|
||
* description="Justificatif d'adresse"
|
||
* ),
|
||
* @OA\Property(property="address",
|
||
* type="string",
|
||
* example = "Douala",
|
||
* description="Adresse géographique"
|
||
* ),
|
||
* @OA\Property(property="po_box",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Adresse postale"
|
||
* ),
|
||
* @OA\Property(property="phone_number",
|
||
* type="string",
|
||
* example = "+237690716639",
|
||
* description="Numéro de téléphone"
|
||
* ),
|
||
* @OA\Property(property="email_1",
|
||
* type="string",
|
||
* example = "ddietchi@ilink-app.com",
|
||
* description="Email 1"
|
||
* ),
|
||
* @OA\Property(property="email_2",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Email 2"
|
||
* ),
|
||
* @OA\Property(property="person_to_contact_in_case_of_needs_name",
|
||
* type="string",
|
||
* example = "Romeo Doe",
|
||
* description="Personne à contacter en cas de besoin"
|
||
* ),
|
||
* @OA\Property(property="person_to_contact_in_case_of_needs_phone_number",
|
||
* type="string",
|
||
* example = "+237699000102",
|
||
* description="Numéro de téléphone de la personne à contacter en cas de besoin"
|
||
* ),
|
||
* @OA\Property(property="identification_document_type",
|
||
* type="string",
|
||
* example = "CNI",
|
||
* description="Type de pièce"
|
||
* ),
|
||
* @OA\Property(property="identification_document_number",
|
||
* type="string",
|
||
* example = "0987654321",
|
||
* description="Numéro d'identification"
|
||
* ),
|
||
* @OA\Property(property="identification_document_issued_date",
|
||
* type="date",
|
||
* example = "2019-08-03",
|
||
* description="Date de délivrance du document"
|
||
* ),
|
||
* @OA\Property(property="identification_document_expiry_date",
|
||
* type="date",
|
||
* example = "2029-08-03",
|
||
* description="Date d'expiration du document"
|
||
* ),
|
||
* @OA\Property(property="identification_document_issuance_city",
|
||
* type="string",
|
||
* example = "Douala",
|
||
* description="Ville d'émission du document"
|
||
* ),
|
||
* @OA\Property(property="identification_document_issuance_country",
|
||
* type="string",
|
||
* example = "Cameroun",
|
||
* description="Pays d'émission du document"
|
||
* ),
|
||
* @OA\Property(property="customer_under_guardianship",
|
||
* type="boolean",
|
||
* example = "1",
|
||
* description="Client sous tutelle ?"
|
||
* ),
|
||
* @OA\Property(property="guardian_fullname",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Nom(s) et Prénom(s) du tuteur"
|
||
* ),
|
||
* @OA\Property(property="guardian_phone_number",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Numéro de téléphone du tuteur"
|
||
* ),
|
||
* @OA\Property(property="how_did_you_know_company",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Comment avez vous connu l'entreprise ?"
|
||
* ),
|
||
* @OA\Property(property="introducer_fullname",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Nom(s) et Prénom(s) de l'introducteur"
|
||
* ),
|
||
* @OA\Property(property="introducer_address",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Adresse de l'introducteur"
|
||
* ),
|
||
* @OA\Property(property="expected_service",
|
||
* type="string",
|
||
* example = "Services bancaires",
|
||
* description="Service attendu"
|
||
* ),
|
||
* @OA\Property(property="income_sources_and_frequency",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Fréquence de revenus et Plafond des transactions"
|
||
* ),
|
||
* @OA\Property(property="business_partners",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Relation d'affaires"
|
||
* ),
|
||
* @OA\Property(property="bank_references",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Référence bancaires"
|
||
* ),
|
||
* @OA\Property(property="has_account_with_other_bank",
|
||
* type="boolean",
|
||
* example = "1",
|
||
* description="Avez vous des comptes avec d'autres banques ?"
|
||
* ),
|
||
* @OA\Property(property="has_operative_other_bank_account",
|
||
* type="boolean",
|
||
* example = "1",
|
||
* description="Si oui, le compte est-il opérationnel ?"
|
||
* ),
|
||
* @OA\Property(property="has_engagement_with_other_banks",
|
||
* type="boolean",
|
||
* example = "0",
|
||
* description="Avez vous des engagements avec d'autres banques ?"
|
||
* ),
|
||
* @OA\Property(property="is_politically_exposed_person",
|
||
* type="boolean",
|
||
* example = "0",
|
||
* description="Le demandeur est-il une personne politiquement exposée ?"
|
||
* ),
|
||
* @OA\Property(property="is_politically_exposed_person_in_service",
|
||
* type="boolean",
|
||
* example = "0",
|
||
* description="En service ?"
|
||
* ),
|
||
* @OA\Property(property="has_relationship_with_politically_exposed_person",
|
||
* type="boolean",
|
||
* example = "0",
|
||
* description="Le demandeur est-il une relation avec des personnes politiquement exposées ?"
|
||
* ),
|
||
* @OA\Property(property="relationship_with_politically_exposed_person",
|
||
* type="string",
|
||
* example = "",
|
||
* description="Si oui, indiquez leurs noms et la nature de la relation"
|
||
* ),
|
||
* @OA\Property(property="email_alerts",
|
||
* type="boolean",
|
||
* example = "1",
|
||
* description="Alertes Email"
|
||
* ),
|
||
* @OA\Property(property="e_statement_frequency",
|
||
* type="string",
|
||
* example = "MONTHLY",
|
||
* description="Frequence Relevé bancaire"
|
||
* ),
|
||
* @OA\Property(property="e_package",
|
||
* type="boolean",
|
||
* example = "1",
|
||
* description="E Package"
|
||
* ),
|
||
* @OA\Property(property="debit_card_type",
|
||
* type="string",
|
||
* example = "VISA_CLASSIC",
|
||
* description="Type de carte de débit"
|
||
* ),
|
||
* @OA\Property(property="document1",
|
||
* type="file",
|
||
* description="Document 1"
|
||
* ),
|
||
* @OA\Property(property="document2",
|
||
* type="file",
|
||
* description="Document 2"
|
||
* ),
|
||
* )
|
||
* )
|
||
* ),
|
||
* @OA\Response(
|
||
* response=200,
|
||
* description="OK",
|
||
* @OA\JsonContent(
|
||
* ref="#/components/schemas/ApiResponse",
|
||
* example = {
|
||
* "status" : 200,
|
||
* "response" : "Demande d'ouverture de compte client soumise",
|
||
* "error":null
|
||
* }
|
||
* )
|
||
* )
|
||
* )
|
||
* @throws AppException
|
||
*/
|
||
|
||
public function submit(Request $request)
|
||
{
|
||
$this->validate($request,[
|
||
'user_id' => 'required|integer|exists:users,id',
|
||
'network_id' => 'required|integer|exists:networks,id',
|
||
'customer_account_type_id' => 'required|integer|exists:customer_account_types,id',
|
||
'title' => 'required|string',
|
||
'lastname' => 'required|string',
|
||
'firstname' => 'nullable|string',
|
||
'spouse_name' => 'nullable|string',
|
||
'nationality' => 'required|string',
|
||
'birth_date' => 'required|date_format:Y-m-d|before:today',
|
||
'birth_country' => 'required|string',
|
||
'birth_city' => 'required|string',
|
||
'birth_locality' => 'nullable|string',
|
||
'father_lastname' => 'required|string',
|
||
'father_firstname' => 'nullable|string',
|
||
'mother_birth_lastname' => 'required|string',
|
||
'mother_firstname' => 'nullable|string',
|
||
'marital_status' => 'required|string',
|
||
'spouse_lastname' => 'nullable|string',
|
||
'spouse_firstname' => 'nullable|string',
|
||
'profession' => 'nullable|string',
|
||
'business_activity' => 'nullable|string',
|
||
'sub_sector_business_activity' => 'nullable|string',
|
||
'tax_number' => 'nullable|string',
|
||
'security_number' => 'nullable|string',
|
||
'employee_number' => 'nullable|string',
|
||
'function' => 'nullable|string',
|
||
'employee_name' => 'nullable|string',
|
||
'employee_address' => 'nullable|string',
|
||
'residential_status' => 'required|string',
|
||
'residential_country' => 'required|string',
|
||
'residence_permit_number' => 'nullable|string',
|
||
'residence_permit_issued_date' => 'nullable|date_format:Y-m-d|before:today',
|
||
'residence_permit_expiry_date' => 'nullable|date_format:Y-m-d|after:residence_permit_issued_date',
|
||
'address_justification_doc' => 'required|string',
|
||
'address' => 'required|string',
|
||
'po_box' => 'nullable|string',
|
||
'phone_number' => 'required|string',
|
||
'email_1' => 'required|string',
|
||
'email_2' => 'nullable|string',
|
||
'person_to_contact_in_case_of_needs_name' => 'required|string',
|
||
'person_to_contact_in_case_of_needs_phone_number' => 'required|string',
|
||
'identification_document_type' => 'required|string',
|
||
'identification_document_number' => 'required|string',
|
||
'identification_document_issued_date' => 'required|date_format:Y-m-d|before:today',
|
||
'identification_document_expiry_date' => 'required|date_format:Y-m-d|after:identification_document_issued_date',
|
||
'identification_document_issuance_city' => 'required|string',
|
||
'identification_document_issuance_country' => 'required|string',
|
||
'customer_under_guardianship' => 'required|bool',
|
||
'guardian_fullname' => 'nullable|string',
|
||
'guardian_phone_number' => 'nullable|string',
|
||
'how_did_you_know_company' => 'required|string',
|
||
'introducer_fullname' => 'nullable|string',
|
||
'introducer_address' => 'nullable|string',
|
||
'expected_service' => 'required|string',
|
||
'income_sources_and_frequency' => 'nullable|string',
|
||
'business_partners' => 'nullable|string',
|
||
'bank_references' => 'nullable|string',
|
||
'has_account_with_other_bank' => 'required|bool',
|
||
'has_operative_other_bank_account' => 'required|bool',
|
||
'has_engagement_with_other_banks' => 'required|bool',
|
||
'is_politically_exposed_person' => 'required|bool',
|
||
'is_politically_exposed_person_in_service' => 'required|bool',
|
||
'has_relationship_with_politically_exposed_person' => 'required|bool',
|
||
'relationship_with_politically_exposed_person' => 'nullable|string',
|
||
'email_alerts' => 'required|bool',
|
||
'e_statement_frequency' => 'required|string',
|
||
'e_package' => 'nullable|bool',
|
||
'debit_card_type' => 'required|string',
|
||
]);
|
||
|
||
$accountType = CustomerAccountType::with('documents')->find($request->input('customer_account_type_id'));
|
||
$documents = [];
|
||
if(!empty($accountType->documents)){
|
||
|
||
$rules[] = [];
|
||
foreach ($accountType->documents as $document){
|
||
$rules[$document->name] = 'required|image|mimes:jpeg,png,jpg,jpeg|max:1024';
|
||
}
|
||
|
||
$this->validate($request, $rules);
|
||
|
||
foreach ($accountType->documents as $document){
|
||
$doc = [];
|
||
$doc['name'] = $document->name;
|
||
$doc['description'] = $document->description;
|
||
$doc['url'] = $this->uploadImage($request,$document->name, 'CRD', 'requests-docs');
|
||
|
||
$documents[] = $doc;
|
||
}
|
||
|
||
}
|
||
|
||
if(CustomerAccountRequest::where('user_id', $request->input('user_id'))->where('network_id', $request->input('network_id'))
|
||
->where('status', CustomerAccountRequest::UNDER_VALIDATION)->exists()){
|
||
return $this->errorResponse(__('messages.customer_account_opening_request_pending'));
|
||
}
|
||
|
||
try{
|
||
DB::beginTransaction();
|
||
|
||
$accountRequest = CustomerAccountRequest::create(array_merge($request->all(),[
|
||
'opening_amount' => $accountType->opening_amount,
|
||
'unique_id' => strtoupper(Str::random(12))
|
||
]));
|
||
|
||
$documents = array_map(function ($row) use ($accountRequest) {
|
||
$row['request_id'] = $accountRequest->id;
|
||
$row['created_at'] = Carbon::now();
|
||
$row['updated_at'] = Carbon::now();
|
||
return $row;
|
||
}, $documents);
|
||
|
||
CustomerAccountRequestDocument::insert($documents);
|
||
|
||
DB::commit();
|
||
}catch (Throwable $exception){
|
||
Log::error($exception->getMessage());
|
||
DB::rollBack();
|
||
return $this->errorResponse(trans('errors.unexpected_error'), 500);
|
||
}
|
||
|
||
$mailParams = ['name' => $accountRequest->user->lastname, 'request_id' => $accountRequest->unique_id, 'gender' => $accountRequest->title, 'account_type' => $accountRequest->account_type->name,
|
||
'opening_amount' => $this->toMoneyWithNetwork($accountRequest->account_type->opening_amount, $accountRequest->network_id)
|
||
];
|
||
|
||
Event::dispatch(new CustomerAccountRequestEvent($accountRequest, __('messages.customer_account_opening_request'), __('messages.customer_account_opening_request_mail',$mailParams)));
|
||
|
||
return $this->successResponse(__('messages.customer_account_opening_request_submitted'));
|
||
}
|
||
|
||
/**
|
||
* @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)
|
||
{
|
||
$this->validate($request,[
|
||
'user_id' => 'nullable|integer|exists:users,id',
|
||
'network_id' => 'nullable|integer|exists:networks,id'
|
||
]);
|
||
|
||
$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)
|
||
{
|
||
$this->validate($request, [
|
||
'nh_validating_agent_id' => 'required_without:agent_id|nullable|integer|exists:nh_validating_agents,id',
|
||
'agent_id' => 'required_without:nh_validating_agent_id|nullable|integer|exists:agents,id',
|
||
'type' => 'required|in:ACCEPT,REJECT,MORE_INFORMATION',
|
||
'reason' => 'nullable|string'
|
||
]);
|
||
|
||
$accountRequest = CustomerAccountRequest::findOrFail($id);
|
||
if(!in_array($accountRequest->status,[CustomerAccountRequest::UNDER_VALIDATION, CustomerAccountRequest::AWAITING_FURTHER_INFORMATION])){
|
||
return $this->errorResponse(__('errors.request_already_processed'));
|
||
}
|
||
|
||
try {
|
||
DB::beginTransaction();
|
||
$datetime = $this->getCurrentTimeByCountryCode($accountRequest->user->network->country->code_country);
|
||
|
||
$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,
|
||
];
|
||
$notificationParams = ['request_id' => $accountRequest->unique_id];
|
||
|
||
switch ($type){
|
||
case 'REJECT':
|
||
$accountRequest->status = CustomerAccountRequest::REJECTED;
|
||
$mailTitle = trans('messages.customer_account_opening_request_rejected');
|
||
$mailMessage = trans('messages.customer_account_opening_request_rejected_mail', $mailParams);
|
||
$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;
|
||
$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:
|
||
$accountRequest->status = CustomerAccountRequest::AWAITING_FURTHER_INFORMATION;
|
||
$mailTitle = trans('messages.customer_account_opening_request_awaiting_more_information');
|
||
$mailMessage = trans('messages.customer_account_opening_request_awaiting_more_information_mail', $mailParams);
|
||
$notification = trans('messages.customer_account_opening_request_awaiting_more_information_notification', $notificationParams);
|
||
}
|
||
$accountRequest->validating_agent_id = $request->input('nh_validating_agent_id') ?? $request->input('agent_id');
|
||
$accountRequest->reject_reason = $request->input('reason');
|
||
$accountRequest->updated_at = $datetime;
|
||
$accountRequest->save();
|
||
|
||
Event::dispatch(new CustomerAccountRequestEvent($accountRequest, $mailTitle, $mailMessage, $notification));
|
||
DB::commit();
|
||
return $this->successResponse(trans('messages.successful_transaction'));
|
||
} catch (Throwable $e) {
|
||
Log::error($e->getMessage() . '\n' . $e->getTraceAsString());
|
||
DB::rollBack();
|
||
return $this->errorResponse(trans('errors.unexpected_error'), 500);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @OA\Get(
|
||
* path="/customers_accounts_requests/formData",
|
||
* summary="Recuperer les informations necessaires avant la soumission du formulaire",
|
||
* 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=true
|
||
* ),
|
||
* @OA\Parameter(
|
||
* parameter="network_id",
|
||
* name="network_id",
|
||
* description="ID du reseau",
|
||
* @OA\Schema(
|
||
* type="integer",
|
||
* ),
|
||
* in="query",
|
||
* required=true
|
||
* ),
|
||
* @OA\Response(
|
||
* response=200,
|
||
* description="OK",
|
||
* @OA\JsonContent(
|
||
* ref="#/components/schemas/ApiResponse",
|
||
* example = {
|
||
* "status" : 200,
|
||
* "response" : {"identification": { "id": 15, "firstname": "", "lastname": " John doe", "birth_date": "2020-07-28T00:00:00.000000Z", "gender": "M", "town": "Libreville", "country": "Gabon", "identity_document": "Carte d'identité",
|
||
* "id_identity_document": "1234567890", "expiry_date_document": "2020-07-28T00:00:00.000000Z", "id_user": 321, "status": 1, "createdAt": "2020-07-28T17:01:26.000000Z", "user_image": null, "document_image_front": null, "document_image_back": null,
|
||
* "idNetwork": 239, "country_id": null }, "customer_account_types": {{ "id": 1, "name": "Compte courant", "description": null, "children": {{ "id": 4, "name": "Compte courant regulier salarie", "description": "Compte courant regulier", "parent_id": 1,
|
||
* "documents": { { "name": "photo", "description": "photo", "account_type_id": 4 } } } } } }, "marital_status": { { "title": "Single", "value": "SINGLE" } }, "residential_status": { { "title": "Résident", "value": "RESIDENT" } },
|
||
* "address_justification_docs": { { "title": "Plan de localisation", "value": "LOCALISATION_PLAN" } }, "e_statement_frequencies": { { "title": "Daily", "value": "DAILY" } }, "debit_card_types": { { "title": "MASTER Card Classic",
|
||
* "value": "MASTER_CARD_CLASSIC" } }},
|
||
* "error":null
|
||
* }
|
||
* )
|
||
* )
|
||
* )
|
||
*/
|
||
// Fetch mandatory form data before submit request
|
||
public function getFormData(Request $request)
|
||
{
|
||
$this->validate($request,[
|
||
'user_id' => 'required|integer|exists:users,id',
|
||
'network_id' => 'required|integer|exists:networks,id',
|
||
]);
|
||
|
||
if(CustomerAccountRequest::where('user_id', $request->input('user_id'))->where('network_id', $request->input('network_id'))
|
||
->where('status', CustomerAccountRequest::UNDER_VALIDATION)->exists()){
|
||
return $this->errorResponse(__('messages.customer_account_opening_request_pending'));
|
||
}
|
||
|
||
$data['identification'] = Identification::where('id_user',$request->input('user_id'))->first();
|
||
|
||
$data['customer_account_types'] = CustomerAccountType::has('children')->with(['children:id,name,description,parent_id','children.documents:name,description,account_type_id'])
|
||
->where('network_id',$request->input('network_id'))->select(['id','name','description'])->get();
|
||
|
||
|
||
foreach (MaritalStatus::all() as $key => $value){
|
||
$data['marital_status'][] = [
|
||
'title' => $value,
|
||
'value' => $key
|
||
];
|
||
}
|
||
|
||
foreach (ResidentialStatus::all() as $key => $value){
|
||
$data['residential_status'][] = [
|
||
'title' => $value,
|
||
'value' => $key
|
||
];
|
||
}
|
||
|
||
foreach (DocumentType::all() as $key => $value){
|
||
$data['address_justification_docs'][] = [
|
||
'title' => $value,
|
||
'value' => $key
|
||
];
|
||
}
|
||
|
||
foreach (Frequency::all() as $key => $value){
|
||
$data['e_statement_frequencies'][] = [
|
||
'title' => $value,
|
||
'value' => $key
|
||
];
|
||
}
|
||
|
||
|
||
foreach (CreditCardType::all() as $key => $value){
|
||
$data['debit_card_types'][] = [
|
||
'title' => $value,
|
||
'value' => $key
|
||
];
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|