WIP (A tester MANQUE MESBR): Add CRM V3 + Remove Arcadia Stuff + Some refactor + Win List Save comments + MAIL_ADMIN check on boot + add Swal + Vues blades mis à jour (pas dans basic example)

This commit is contained in:
Jérémy Munsch 2022-03-18 14:42:11 +01:00
parent fbcb8bc5bf
commit 2093fc32e3
No known key found for this signature in database
GPG key ID: 55196BEE445F6049
63 changed files with 1786 additions and 115538 deletions

View file

@ -32,5 +32,7 @@ MAIL_ADMIN=informatique.internet@ldc.fr
# CRM # CRM
CRM_ENDPOINT= CRM_ENDPOINT=
CRM_TOKEN= CRM_TOKEN=
CRM_PASSWORD=
# MESBR # MESBR
MESBR_ENDPOINT= MESBR_ENDPOINT=

View file

@ -33,14 +33,11 @@ class PrizesController extends Controller
if ($prize->id !== null) { if ($prize->id !== null) {
$p = Prize::findOrFail($prize->id); $p = Prize::findOrFail($prize->id);
$p->arcadia_id = $prize->arcadia_id; $p->label_one = $prize->label_one;
$p->label_one = $prize->label_one; $p->label_many = $prize->label_many;
$p->label_many = $prize->label_many; $p->quantity = $prize->quantity;
$p->quantity = $prize->quantity; $p->need_proof = $prize->need_proof;
$p->arcadia_operation_code = $prize->arcadia_operation_code; $p->gain_view_id = $prize->gain_view_id;
$p->arcadia_support_code = $prize->arcadia_support_code;
$p->need_proof = $prize->need_proof;
$p->gain_view_id = $prize->gain_view_id;
if (isset($pdfs[$i])) { if (isset($pdfs[$i])) {
$fileName = Str::slug($prize->label_one) . '-' . $fileName = Str::slug($prize->label_one) . '-' .
@ -52,15 +49,12 @@ class PrizesController extends Controller
$p->save(); $p->save();
} else { } else {
$p = new Prize(); $p = new Prize();
$p->arcadia_id = $prize->arcadia_id; $p->label_one = $prize->label_one;
$p->label_one = $prize->label_one; $p->label_many = $prize->label_many;
$p->label_many = $prize->label_many; $p->quantity = $prize->quantity;
$p->quantity = $prize->quantity; $p->need_proof = $prize->need_proof;
$p->arcadia_operation_code = $prize->arcadia_operation_code; $p->gain_view_id = $prize->gain_view_id;
$p->arcadia_support_code = $prize->arcadia_support_code;
$p->need_proof = $prize->need_proof;
$p->gain_view_id = $prize->gain_view_id;
if (isset($pdfs[$i])) { if (isset($pdfs[$i])) {
$fileName = Str::slug($prize->label_one) . '-' . $fileName = Str::slug($prize->label_one) . '-' .

View file

@ -3,28 +3,14 @@
namespace App\Http\Controllers\Bo; namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Mail\CourrierArcadiaError; use App\Http\Requests\Bo\UpdateWinInfosRequest;
use App\Models\InstantWin;
use App\Models\Participation; use App\Models\Participation;
use App\Models\Settings; use App\Models\Settings;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Cache;
class WinnersListController extends Controller class WinnersListController extends Controller
{ {
/**
* crm Api
*
* @var \LDCCRM\ApiV1
*/
private $apiCrm;
/**
* WinnersListController
*/
public function __construct()
{
$this->apiCrm = new \LDCCRM\ApiV1(config('crm.endpoint'), config('crm.token'));
}
/** /**
* Show Instant win list * Show Instant win list
* *
@ -32,118 +18,48 @@ class WinnersListController extends Controller
*/ */
public function index() public function index()
{ {
$winnersList = Participation::has('instantWin')->get(); $participations = Participation::whereHas('instantWin')->with('code')
$settings = Settings::select('use_ean_codes', 'winning_proof')->first(); ->with('instantWin.prize')->with('customer')->with('codeEan')->get();
return view('bo.winners-list.index', compact('winnersList', 'settings')); $settings = Settings::select('use_ean_codes', 'winning_proof')->first();
// * Generate code to show up in front + format date + customer info
$participations = $participations->map(function (Participation $participation) {
$participation->created = $participation->created_at->format('d/m/Y à H:i');
$participation->code->code = $participation->code->code_unique;
$participation->code->code = $participation->code->code_unique;
$participation->customer->setRawAttributes(['data' => Cache::remember(
'winnerList' . $participation->customer->id,
90,
function () use ($participation) {
/** @var \LDC\LDCCRM\Models\Customer|null $crmCustomer */
$crmCustomer = $participation->customer->apiData;
$data = [];
if ($crmCustomer) {
$countryLabel = $crmCustomer->country->label;
$data = collect($crmCustomer)->all();
$data['country'] = $countryLabel;
}
return $data;
}
)]);
return $participation;
});
return view('bo.winners-list.index', compact('participations', 'settings'));
} }
/** /**
* Crete and show courrier arcadia * Update Instant win info
* *
* @param mixed $id * @param UpdateWinInfosRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory * @param InstantWin $instantWin
* @return \Illuminate\Http\JsonResponse
*/ */
public function courrierArcadia($id) public function updateInstantWinInfos(UpdateWinInfosRequest $request, InstantWin $instantWin)
{ {
/** @var \App\Models\Participation $participation */ $instantWin->done = $request->done;
$participation = Participation::findOrFail($id); $instantWin->comment = $request->comment;
if ($instantWin->save()) {
/** @var \App\Models\Customer $customer */ return response()->json();
$customer = $participation->customer;
$crmUser = $this->apiCrm->getCustomer($customer->crm_id);
if ($crmUser->status === 'NOK') {
return back()->withErrors("Erreur lors de la récupération de l'utilisateur dans la CRM : Code : " .
$crmUser->code . " Message : " . $crmUser->message);
} }
return response()->json([], 500);
$crmId = $customer->crm_id;
$crmUser = $crmUser->user;
$corps = '<arcadia>' . "\n";
$corps .= '<Commande> ' . "\n";
$corps .= "\t" . '<Num_Commande></Num_Commande>' . "\n";
$corps .= "\t" . '<Date_Commande>' . date('d/m/Y') . '</Date_Commande>' . "\n";
$corps .= "\t" . '<Operation></Operation> ' . "\n";
$corps .= "\t" . '<Civilite></Civilite>' . "\n";
$corps .= "\t" . '<Nom><![CDATA[' . trim($crmUser->firstname) . ']]></Nom>' . "\n";
$corps .= "\t" . '<Prenom><![CDATA[' . trim($crmUser->lastname) . ']]></Prenom>' . "\n";
$corps .= "\t" . '<Adresse><![CDATA[' . trim($crmUser->address) . ']]></Adresse>' . "\n";
// phpcs:ignore Generic.Files.LineLength.TooLong
$corps .= "\t" . '<Adresse_Complementaire><![CDATA[' . trim($crmUser->address2) . ']]></Adresse_Complementaire>' . "\n";
$corps .= "\t" . '<CP><![CDATA[' . trim($crmUser->postcode) . ']]></CP>' . "\n";
$corps .= "\t" . '<Ville><![CDATA[' . trim($crmUser->city) . ']]></Ville>' . "\n";
$corps .= '<Ligne_de_Commande>' . "\n";
$corps .= "\t" . '<Code_Support></Code_Support> ' . "\n";
$corps .= "\t" . '<Libelle_Type_Support></Libelle_Type_Support> ' . "\n";
$corps .= "\t" . '<Quantite>1</Quantite>' . "\n";
$corps .= "\t" . '<Poids_Unitaire_Colis></Poids_Unitaire_Colis>' . "\n";
$corps .= '</Ligne_de_Commande>' . "\n";
$corps .= '</Commande> ' . "\n";
$corps .= '</arcadia>';
return view('bo.winners-list.arcadia', compact('participation', 'corps', 'crmId'));
}
/**
* Send Arcadia mail
*
* @param mixed $id
* @return \Illuminate\Http\RedirectResponse
*/
public function createCourrierArcadia($id)
{
$participation = Participation::findOrFail($id);
$instantWin = $participation->instantWin;
/** @var \App\Models\Customer $customer */
$customer = $participation->customer;
if ($instantWin->prize->arcadia_operation_code !== 0 && $instantWin->prize->arcadia_support_code !== 0) {
$fields = [
'root' => [
[
'fieldName' => 'order_date',
'fieldValue' => date('d/m/Y')
],
[
'fieldName' => 'operation',
'fieldValue' => $instantWin->prize->arcadia_operation_code
]
],
'orderLine' => [
[
'fieldName' => 'code_unique',
'fieldValue' => $participation->code->code_unique
],
[
'fieldName' => 'support_code',
'fieldValue' => $instantWin->prize->arcadia_support_code
],
[
'fieldName' => 'label_type_support',
'fieldValue' => 'Gain du lot : ' . $instantWin->prize->label_one
]
]
];
/** @var \App\Models\Settings $settings */
$settings = app(Settings::class);
if ($settings->use_ean_codes) {
$fields['orderLine'][] = [
'fieldName' => 'code_on_pack',
'fieldValue' => $participation->codeEan->code
];
}
$arcadiaMail = $this->apiCrm->ArcadiaOutgoingMail($customer->crm_id, $fields, 'game');
if ($arcadiaMail->status === 'NOK') {
Mail::to(config('mail.MAIL_ADMIN'))->send(new CourrierArcadiaError($customer));
return back()->withErrors("Erreur lors de l'envoi du courrier Arcadia. Code : " .
$arcadiaMail->code . " Message : " . $arcadiaMail->message);
}
}//end if
return back()->with('success', 'Courrier envoyé !');
} }
} }

View file

@ -1,7 +0,0 @@
<?php
namespace App\Http\Controllers;
class CustomerController extends Controller
{
}

View file

@ -0,0 +1,54 @@
<?php
namespace App\Http\Controllers\Fo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Fo\CompleteInfosRequest;
use Illuminate\Support\Facades\Session;
use LDC\LDCCRM\Exceptions\ApiErrorException;
use LDC\LDCCRM\Exceptions\CrmException;
use LDC\LDCCRM\Exceptions\ValidationException;
class CustomerController extends Controller
{
/**
* Show customer complete form
*
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function completeInfos()
{
/** @var \App\Models\Customer $customer */
$customer = auth('customer')->user();
return view('front.basic.complete-infos', ['customer' => $customer]);
}
/**
* Update account info
*
* @param CompleteInfosRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function completeInfosSubmit(CompleteInfosRequest $request)
{
/** @var \App\Models\Customer $customer */
$customer = auth('customer')->user();
try {
/** @var \LDC\LDCCRM\Models\Customer $crmCustomer */
$crmCustomer = $customer->apiData;
$crmCustomer->fill($request->validated());
$crmCustomer->save();
Session::remove('needCrmInfoUpdate');
return redirect()->route('saisir-code');
} catch (ApiErrorException | ValidationException $e) {
return back()->withErrors($e->getMessage());
} catch (\Exception | \TypeError | CrmException $e) {
\report($e);
} //end try
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
}
}

View file

@ -4,7 +4,6 @@ namespace App\Http\Controllers\Fo;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\Fo\ParticipateRequest; use App\Http\Requests\Fo\ParticipateRequest;
use App\Mail\CourrierArcadiaError;
use App\Mail\NotifAdmin; use App\Mail\NotifAdmin;
use App\Mail\NotifWinAdmin; use App\Mail\NotifWinAdmin;
use App\Mail\PrizeWon; use App\Mail\PrizeWon;
@ -16,25 +15,12 @@ use App\Models\Participation;
use App\Models\Reduction; use App\Models\Reduction;
use LDCWeb\MesBR; use LDCWeb\MesBR;
use App\Models\Settings; use App\Models\Settings;
use Illuminate\Http\Request; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
class EnterCodeController extends Controller class EnterCodeController extends Controller
{ {
/**
*
* @var \LDCCRM\ApiV1
*/
private $apiCrm;
/**
* EnterCodeController
*/
public function __construct()
{
$this->apiCrm = new \LDCCRM\ApiV1(config('crm.endpoint'), config('crm.token'));
}
/** /**
* Show enter code form * Show enter code form
* *
@ -68,141 +54,115 @@ class EnterCodeController extends Controller
*/ */
public function participate(ParticipateRequest $request) public function participate(ParticipateRequest $request)
{ {
// Récupération des données à utilisées. try {
/** @var \App\Models\Settings $settings */ return DB::transaction(function () use ($request) {
$settings = app(Settings::class); // Récupération des données à utilisées.
/** @var \App\Models\Settings $settings */
$settings = app(Settings::class);
/** @var \App\Models\Customer $customer */ /** @var \App\Models\Customer $customer */
$customer = auth('customer')->user(); $customer = auth('customer')->user();
// * Cas IP bannie. /** @var \LDC\LDCCRM\Models\Customer $crmCustomer */
$ipBanned = BannedIp::where('ip', app('clientIp'))->first() === null ? 0 : 1; $crmCustomer = $customer->apiData;
if ($ipBanned) {
return view('front.basic.participation-exhausted', compact('settings'));
}
// * Cas nombre de participation maximale atteint. // * Cas IP bannie.
$nbParticipations = Participation::whereHas('customer', function ($q) use ($customer) { if (BannedIp::where('ip', app('clientIp'))->exists()) {
$q->whereId($customer->id); return view('front.basic.participation-exhausted', compact('settings'));
})->count(); }
if ($nbParticipations >= $settings->nb_participation_player) {
return view('front.basic.participation-exhausted', compact('settings'));
}
// * Tous les cas "bloquants" sont passé, l'utilisateur participe à partir d'ici. // * Cas nombre de participation maximale atteint.
$participation = new Participation(); $nbParticipations = Participation::whereHas('customer', function ($q) use ($customer) {
$participation->code_unique_id = $request->code->id; $q->whereId($customer->id);
$participation->code_ean_id = $request->code_ean ? $request->code_ean->id : null; })->count();
$participation->ip = app('clientIp'); if ($nbParticipations >= $settings->nb_participation_player) {
$participation->customer()->associate($customer); return view('front.basic.participation-exhausted', compact('settings'));
$participation->save(); }
// * Gestion des instants gagnants. // * Tous les cas "bloquants" sont passé, l'utilisateur participe à partir d'ici.
$userAlreadyWon = Participation::has('instantWin') $participation = new Participation();
->whereHas('customer', function ($q) use ($customer) { $participation->code_unique_id = $request->code->id;
$q->whereId($customer->id); $participation->code_ean_id = $request->code_ean ? $request->code_ean->id : null;
})->first(); $participation->ip = app('clientIp');
$participation->customer()->associate($customer);
$participation->saveOrFail();
// * Si l'utilisateur actuel à déjà gagné un gros lot, pas d'instant gagnant. // * Gestion des instants gagnants.
if ($userAlreadyWon) { $userAlreadyWon = Participation::has('instantWin')
return $this->serveCouponWin($settings, $participation, $customer); ->whereHas('customer', function ($q) use ($customer) {
} $q->whereId($customer->id);
})->first();
$instantWin = InstantWin::where([['appear_date', '<', now()], ['won', 0]]) // * Si l'utilisateur actuel à déjà gagné un gros lot, pas d'instant gagnant.
->orderBy('appear_date', 'ASC')->first(); if ($userAlreadyWon) {
if ($instantWin) { return $this->serveCouponWin($settings, $participation, $crmCustomer);
// Ici si fail car unique dupliqué catch. }
try {
// Gain d'un gros lot. /** @var \App\Models\InstantWin|null */
return $this->instantWin($settings, $request, $participation, $customer, $instantWin); $instantWin = InstantWin::where('appear_date', '<', now())
} catch (\ErrorException $e) { ->whereDoesntHave('participation')->orderBy('appear_date', 'ASC')
// Unbind instant gagnant. ->lockForUpdate()->first();
$participation->instantWin()->delete(); if ($instantWin) {
// TODO: si erreur il faut envoyer un mail à equipe.web@ldc.fr. // Ici si fail car unique dupliqué catch.
} //end try try {
} // Gain d'un gros lot.
return $this->serveCouponWin( return $this->instantWin(
$settings, $settings,
$participation, $participation,
$customer $crmCustomer,
); $instantWin
);
} catch (\ErrorException $e) {
report($e);
// Unbind instant gagnant.
$participation->instantWin()->deleteOrFail();
} //end try
}
return $this->serveCouponWin(
$settings,
$participation,
$crmCustomer
);
});
} catch (\ErrorException $e) {
report($e);
return back()
->withErrors('Une erreur est survenue, merci de réessayez ultérieurement.');
}//end try
} }
/** /**
* Handle instant wins * Handle instant wins
* *
* @param Settings $settings * @param Settings $settings
* @param Request $request * @param Participation $participation
* @param Participation $participation * @param CrmCustomer $crmCustomer
* @param Customer $customer * @param InstantWin $instantWin
* @param InstantWin|null $instantWin
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory * @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/ */
private function instantWin( private function instantWin(
Settings $settings, Settings $settings,
Request $request,
Participation &$participation, Participation &$participation,
Customer $customer, CrmCustomer $crmCustomer,
$instantWin InstantWin $instantWin
) { ) {
$instantWin->won = true;
// Should save now to prevent next player win on the same winning moment.
$instantWin->save();
$participation->instantWin()->save($instantWin); $participation->instantWin()->save($instantWin);
// Envoi du courrier Arcadia.
if (
$instantWin->prize->arcadia_operation_code !== 0 &&
$instantWin->prize->arcadia_support_code !== 0
) {
$crmId = $customer->crm_id;
$fields = [ Mail::to($crmCustomer->email)->send(new PrizeWon($crmCustomer, $instantWin->prize, $settings));
'root' => [
[
'fieldName' => 'order_date',
'fieldValue' => date('d/m/Y')
],
[
'fieldName' => 'operation',
'fieldValue' => $instantWin->prize->arcadia_operation_code
]
],
'orderLine' => [
[
'fieldName' => 'code_unique',
'fieldValue' => $request->serial
],
[
'fieldName' => 'support_code',
'fieldValue' => $instantWin->prize->arcadia_support_code
],
[
'fieldName' => 'label_type_support',
'fieldValue' => 'Gain du lot : ' . $instantWin->prize->label_one
]
]
];
if ($settings->use_ean_codes) {
$codeEan = $request->code_ean;
$fields['orderLine'][] = [
'fieldName' => 'code_on_pack',
'fieldValue' => "$codeEan"
];
}
$arcadiaMail = $this->apiCrm->ArcadiaOutgoingMail($crmId, $fields, 'game');
if ($arcadiaMail->status === 'KO') {
Mail::to(config('mail.MAIL_ADMIN'))->send(new CourrierArcadiaError($customer));
}
} //end if
Mail::to($customer->email)->send(new PrizeWon($customer, $instantWin->prize, $settings));
$mails = collect($settings->notification_emails); $mails = collect($settings->notification_emails);
foreach ($mails as $mail) { // ? Is settings.notification_emails empty ?
Mail::to($mail)->send(new NotifWinAdmin($settings, $participation)); if (!$mails->count()) {
// ! Send to null (will send to MAIL_ADMIN and print warning in mail object)
$mails = [null];
} }
$participation->save(); foreach ($mails as $mail) {
Mail::to($mail)->send(new NotifWinAdmin(
$crmCustomer,
$settings,
$participation
));
}
return view("front.basic." . $instantWin->prize->gain_view->file_name, compact('settings')) return view("front.basic." . $instantWin->prize->gain_view->file_name, compact('settings'))
->with('prize', $instantWin->prize); ->with('prize', $instantWin->prize);
} }
@ -213,23 +173,29 @@ class EnterCodeController extends Controller
* *
* @param Settings $settings * @param Settings $settings
* @param Participation $participation * @param Participation $participation
* @param Customer $customer * @param CrmCustomer $crmCustomer
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory * @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
* @throws \ErrorException If no web coupons are available.
*/ */
private function serveCouponWin(Settings $settings, Participation $participation, Customer $customer) private function serveCouponWin(Settings $settings, Participation $participation, CrmCustomer $crmCustomer)
{ {
// Si le jeu est 100% gagnant. // Si le jeu est 100% gagnant.
if ($settings->reductions_activated) { if ($settings->reductions_activated) {
if (!($coupon = $this->getRandomCoupon($settings))) { if (!($coupon = $this->getRandomCoupon($settings))) {
throw new \ErrorException('No web coupons are available'); throw new \ErrorException('No web coupons are available');
} }
// ! FIXME: repair this !! $reduction = $this->updateCoupon(
$crmCoupon = $this->updateCoupon($settings, $coupon->web_coupon_identifiant, $participation, $customer); $settings,
if (!$crmCoupon) { $coupon['web_coupon_identifiant'],
$participation->delete(); $participation,
return back()->withErrors("Une erreur est survenue, merci de réessayez ultérieurement."); $crmCustomer
);
if (!$reduction) {
$participation->deleteOrFail();
abort(back()->withErrors('Une erreur est survenue, merci de réessayez ultérieurement.'));
} }
Mail::to(auth('customer')->user()->email)->send(new ReductionWon($customer, $coupon, $settings, $crmCoupon)); Mail::to($crmCustomer->email)
->send(new ReductionWon($crmCustomer, $coupon['face_value'], $settings, $reduction));
return view('front.basic.reduction', compact('crmCoupon', 'coupon')); return view('front.basic.reduction', compact('crmCoupon', 'coupon'));
} else { } else {
return view('front.basic.loose'); return view('front.basic.loose');
@ -240,9 +206,9 @@ class EnterCodeController extends Controller
* Get a random coupon * Get a random coupon
* *
* @param Settings $settings * @param Settings $settings
* @return string|null * @return array|null
*/ */
private function getRandomCoupon(Settings $settings): ?string private function getRandomCoupon(Settings $settings): ?array
{ {
$webCoupons = $settings->web_coupons; $webCoupons = $settings->web_coupons;
if (count($webCoupons) > 1) { if (count($webCoupons) > 1) {
@ -265,33 +231,34 @@ class EnterCodeController extends Controller
/** /**
* Update a coupon * Update a coupon
* *
* FIXME: When mes BR will be updated.
*
* @param Settings $settings * @param Settings $settings
* @param mixed $coupon * @param integer $couponId
* @param Participation $participation * @param Participation $participation
* @param Customer $customer * @param CrmCustomer $crmCustomer
* @return \App\Models\Reduction|null * @return \App\Models\Reduction|null
*/ */
private function updateCoupon( private function updateCoupon(
Settings $settings, Settings $settings,
$coupon, int $couponId,
Participation $participation, Participation $participation,
Customer $customer CrmCustomer $crmCustomer
) { ) {
$reduction = null; $reduction = null;
$mesBR = new MesBR(config('mesbr.endpoint'), $settings->reductions_site, $settings->reductions_campaign); $mesBR = new MesBR(config('mesbr.endpoint'), $settings->reductions_site, $settings->reductions_campaign);
$crmUser = $this->apiCrm->getCustomer($customer->crm_id);
if ($crmUser->status === 'OK') { if ($crmUser->status === 'OK') {
$mesBR->updateContact($crmUser->user); $mesBR->updateContact($crmUser->user);
$result = $mesBR->updatePanier($crmUser->user, $coupon); $result = $mesBR->updatePanier($crmUser->user, $couponId);
if ($result["status"] === "OK") { if ($result["status"] === "OK") {
$reduction = new Reduction(); $reduction = new Reduction();
$reduction->link = $result["link"]; $reduction->link = $result["link"];
$reduction->verification = $result["verif"]; $reduction->verification = $result["verif"];
$reduction->basket_id = $result["basketId"]; $reduction->basket_id = $result["basketId"];
$reduction->save(); $reduction->saveOrFail();
$participation->reduction_id = $reduction->id; $participation->reduction_id = $reduction->id;
$participation->save(); $participation->saveOrFail();
} else { } else {
Mail::to(config('mail.MAIL_ADMIN')) Mail::to(config('mail.MAIL_ADMIN'))
->send(new NotifAdmin(\sprintf( ->send(new NotifAdmin(\sprintf(

View file

@ -4,7 +4,9 @@ namespace App\Http\Controllers\Fo;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\Fo\AuthenticateRequest; use App\Http\Requests\Fo\AuthenticateRequest;
use App\Http\Requests\Fo\RegisterRequest;
use App\Http\Requests\Fo\UpdatePasswordRequest; use App\Http\Requests\Fo\UpdatePasswordRequest;
use App\Http\Requests\Fo\ForgotPasswordRequest;
use App\Lib\ToolboxHelper; use App\Lib\ToolboxHelper;
use App\Mail\PasswordReset; use App\Mail\PasswordReset;
use App\Mail\VerifyEmail; use App\Mail\VerifyEmail;
@ -13,26 +15,18 @@ use App\Models\Settings;
use App\Models\User; use App\Models\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
use LDC\LDCCRM\Enums\ApiError;
use LDC\LDCCRM\Exceptions\ApiErrorException;
use LDC\LDCCRM\Exceptions\CrmException;
use LDC\LDCCRM\Exceptions\ValidationException;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
class LoginController extends Controller class LoginController extends Controller
{ {
/**
* apiCRM
*
* @var \LDCCRM\ApiV1
*/
private $apiCrm;
/**
* LoginController
*/
public function __construct()
{
$this->apiCrm = new \LDCCRM\ApiV1(config('crm.endpoint'), config('crm.token'));
}
/** /**
* Show login form * Show login form
* *
@ -61,6 +55,171 @@ class LoginController extends Controller
->withErrors('Les identifiants entrés sont incorrects.'); ->withErrors('Les identifiants entrés sont incorrects.');
} }
/**
* Log out
*
* @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
*/
public function logout()
{
auth('web')->logout();
auth('customer')->logout();
return redirect()->route('home');
}
/**
* Confirm Email
*
* @param mixed $verifyToken
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function confirmEmail($verifyToken)
{
$result = false;
/** @var \App\Models\Customer $customer */
if (!($customer = Customer::select('hashcode')->where('email_verify_token', $verifyToken)->first())) {
return view('front.basic.confirm-email', compact('result'));
}
try {
/** @var \LDC\LDCCRM\Models\Customer $crmCustomer */
$crmCustomer = $customer->apiData;
if ($crmCustomer->activate()) {
$result = true;
}
} catch (ApiErrorException $e) {
if ($e->getApiError()->equals(ApiError::customerAlreadyActive())) {
return view('front.auth.activate')
->with(
'message',
'Votre compte est déjà activé, vous pouvez dès à présent vous connecter avec celui-ci.'
);
}
// ! Une erreur critique est survenue avec la CRM.
report($e);
} catch (CrmException $e) {
// ! Une erreur critique est survenue avec la CRM.
report($e);
} //end try
return view('front.basic.confirm-email', compact('result'));
}
/**
* Forgot Password form
*
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function forgotPassword()
{
return view('front.basic.forgot-password');
}
/**
* forgotPassword submit
*
* @param ForgotPasswordRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function forgotPasswordSubmit(ForgotPasswordRequest $request)
{
if (!($crmCustomer = $this->getCustomerFromCrm($request->email))) {
return back()->withInput($request->only('email'))
->withErrors('Le mail que vous avez entré n\'est pas enregistré dans nos services.');
}
/** @var \App\Models\Customer $customer */
$customer = $this->createLocalCustomer($crmCustomer);
$customer->password_token = Str::uuid();
$customer->saveOrFail();
/** @var \App\Models\Settings $settings */
$settings = app(Settings::class);
Mail::to($request->email)->send(new PasswordReset($customer, $settings));
return redirect()->route('login')
->with('success', 'Un mail de réinitialisation de votre mot de passe vous a été envoyé(e).');
}
/**
* Forgot password form show
*
* @param Request $request
* @param mixed $token
* @return \Illuminate\Http\RedirectResponse
*/
public function forgotPasswordReset(Request $request, $token)
{
if (!$request->hasValidSignature(false)) {
return redirect()->route('login')
->withErrors('Le lien de changement de votre mot de passe n\'est plus valide, veuillez réessayer. ');
}
if (!Customer::where('password_token', $token)->exists()) {
return redirect()->route('forgot-password', ['tokenValid' => false])
->withErrors('Le lien de changement du mot de passe est incorrect.');
}
return view('front.basic.forgot-password', [
'tokenValid' => true,
'token' => $token
]);
}
/**
* Change password form submit
*
* @param UpdatePasswordRequest $request
* @param mixed $token
* @return \Illuminate\Http\RedirectResponse
*/
public function forgotPasswordResetSubmit(UpdatePasswordRequest $request, $token)
{
/** @var \App\Models\Customer $customer */
if (!$request->hasValidSignature(false) or !($customer = Customer::where('password_token', $token)->first())) {
return redirect()->route('forgot-password', ['tokenValid' => false])
->withErrors('Le lien de changement du mot de passe est incorrect.');
}
/** @var \LDC\LDCCRM\CrmApiV2 */
$crm = app('crmAPI');
try {
// Ne devrait pas survenir, $crm->login throws ApiError::authFailed() .
if ($crm->login($customer->email, $request->password)) {
// Mauvais identifiants.
return back()->withErrors('Vous ne pouvez pas utiliser un de vos anciens mot de passe.');
}
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
} catch (ApiErrorException $e) {
// * Continue
} catch (\TypeError | CrmException | ApiErrorException $e) {
report($e);
// ! Une erreur critique est survenue avec la CRM.
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
}
try {
if (!($crmCustomer = $crm->getCustomer($customer->hashcode))) {
return back()->withErrors('Changement impossible, compte inexistant.');
}
$crmCustomer->password = $request->password;
$crmCustomer->save();
$customer->password_token = null;
$customer->saveOrFail();
return redirect()->route('login')
->with('success', 'Vous pouvez désormais vous connecter avec votre nouveau mot de passe.');
} catch (\TypeError | CrmException | ApiErrorException $e) {
report($e);
// ! Une erreur critique est survenue avec la CRM
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
} catch (ValidationException $e) {
return back()->withErrors(sprintf('Nouveau mot de passe : %s', $e->getMessage()));
}
}
/** /**
* Try Login User if exists (email) * Try Login User if exists (email)
* *
@ -93,291 +252,192 @@ class LoginController extends Controller
* @return void * @return void
* @throws \Symfony\Component\HttpKernel\Exception\HttpException If user is logged in. * @throws \Symfony\Component\HttpKernel\Exception\HttpException If user is logged in.
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException If redirect route is not found. * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException If redirect route is not found.
* @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.Missing
*/ */
private function authenticateCustomer(AuthenticateRequest $request) private function authenticateCustomer(AuthenticateRequest $request)
{ {
/** @var \App\Models\Customer|null $customerLocal */ /** @var \App\Models\Customer|null $customerLocal */
$customerLocal = Customer::where('email', $request->email)->first(); $customer = Customer::where('email', $request->email)->first();
$connect = $this->apiCrm->loginCustomer($request->email, $request->password); /** @var \LDC\LDCCRM\CrmApiV2 */
$crm = app('crmAPI');
if (\optional($connect)->code === 500) { try {
abort(back()->withInput($request->except("password")) $crm->login($request->email, $request->password);
->withErrors("La connexion est impossible pour le moment, veuillez réessayer plus tard."));
}
// * Compte existant mais non activé. if (!($crmCustomer = $this->getCustomerFromCrm($request->email))) {
if (\optional($connect)->code === 116) { abort(back()->withInput($request->except('password'))
/** @var \App\Models\Customer $customerLocal */ ->withErrors('Une erreur est survenue veuillez réssayer plus tard.'));
$customerLocal = Customer::create([
'crm_id' => $connect->user->crm_id,
'firstname' => $connect->user->firstname,
'lastname' => $connect->user->lastname,
'birth_date' => $connect->user->birth_date,
'email' => $request->email,
// TODO : MOTDEPASSE ???.
'password' => Hash::make("MOTDEPASSE"),
'address' => $connect->user->address,
'address2' => $connect->user->address2,
'town' => $connect->user->city,
'postal_code' => $connect->user->postcode,
'country' => $connect->user->country
]);
$customerLocal->email_verify_token = Str::uuid();
$customerLocal->saveOrFail();
Mail::to($request->email)->send(new VerifyEmail($customerLocal));
abort(back()->withInput($request->except("password"))
// phpcs:ignore Generic.Files.LineLength.TooLong
->withErrors("Votre compte existe mais votre email n'est pas confirmé, merci de vérifier vos emails."));
} //end if
// * Connexion OK
if (!$customerLocal and $connect->status === 'OK') {
/** @var \App\Models\Customer $customerLocal */
$customerLocal = Customer::create([
'crm_id' => $connect->user->crm_id,
'firstname' => $connect->user->firstname,
'lastname' => $connect->user->lastname,
'birth_date' => $connect->user->birth_date,
'email' => $request->email,
// TODO : MOTDEPASSE ???.
'password' => Hash::make("MOTDEPASSE"),
'address' => $connect->user->address,
'address2' => $connect->user->address2,
'town' => $connect->user->city,
'postal_code' => $connect->user->postcode,
'country' => $connect->user->country,
'email_verified' => true
]);
} //end if
// * Pas de customer (non trouvé ou mot de pass invalide)
if (!$customerLocal or \optional($connect)->code === 117) {
abort(back()->withInput($request->except("password"))
->withErrors("Email ou mot de passe incorrect."));
}
if ($connect->status !== 'OK') {
abort(back()->withInput($request->except("password"))
->withErrors('Une erreur est survenue'));
}
// * Enregistrer Customer is besoin
$customerLocal->saveOrFail();
// * Email non vérifié
if (!$customerLocal->email_verified) {
$customerLocal->email_verify_token = Str::uuid();
$customerLocal->saveOrFail();
Mail::to($request->email)->send(new VerifyEmail($customerLocal));
abort(back()->withInput($request->except("password"))
->withErrors(
'Votre compte existe mais votre email n\'est pas confirmé, merci de vérifier vos emails.'
));
} //end if
// ??? Pas sûr.
$tmpPwd = "MOTDEPASSE";
if ($customerLocal and $customerLocal->isLocal()) {
$tmpPwd = $request->password;
}
// * Authentification locale
if (auth('customer')->attempt(["email" => $request->email, "password" => $tmpPwd], $request->remember)) {
abort(redirect()->route('saisir-code'));
}
}
/**
* Log out
*
* @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
*/
public function logout()
{
auth('web')->logout();
auth('customer')->logout();
return redirect()->route('home');
}
/**
* Confirm Email
*
* @param mixed $verifyToken
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function confirmEmail($verifyToken)
{
$result = false;
/** @var \App\Models\Customer $customer */
$customer = Customer::where('email_verify_token', $verifyToken)->first();
if (!$customer) {
return view('front.basic.confirm-email', compact('result'));
}
$activation = $this->apiCrm->activateCustomer($customer->crm_id);
if ($activation->status === 'OK') {
$customer->email_verified = true;
$customer->email_verify_token = null;
$customer->saveOrFail();
$result = true;
} else {
// User already active.
if ($activation->code === 110) {
$customer->email_verified = true;
$customer->email_verify_token = null;
$customer->saveOrFail();
$result = true;
} }
}
return view('front.basic.confirm-email', compact('result')); // ? Test is user data valid ?
} try {
/**
/** * On va tester de mettre a jour uniquement les champs
* Forgot Password form * requis pour mes br afin de detecter si ils doivent etre mis à jour
* * la validation va se faire par la crm (ou le client).
* @param Request $request */
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory $crmCustomer->fill([
*/ 'birth_date' => $crmCustomer->birth_date,
public function forgotPassword(Request $request) 'address' => $crmCustomer->address,
{ 'postcode' => $crmCustomer->postcode,
if ($request->tokenValid && $request->token) { 'country' => $crmCustomer->country,
$tokenValid = $request->tokenValid; 'city' => $crmCustomer->city
$token = $request->token;
return view('front.basic.forgot-password', compact('tokenValid', 'token'));
}
return view('front.basic.forgot-password');
}
/**
* Send password reset mail
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function mailPassword(Request $request)
{
$email = filter_var($request->email, FILTER_SANITIZE_STRING);
/** @var \App\Models\Customer $customer */
$customer = Customer::where('email', $email)->first();
if (!$customer) {
$userCrm = $this->apiCrm->getCustomerByEmail($email);
if ($userCrm->status === 'OK') {
/** @var \App\Models\Customer $customer */
$customer = Customer::create([
'crm_id' => $userCrm->user->crm_id,
'firstname' => $userCrm->user->firstname,
'lastname' => $userCrm->user->lastname,
'birth_date' => $userCrm->user->birth_date,
'email' => $email,
// TODO : MOTDEPASSE ???
'password' => Hash::make("MOTDEPASSE"),
'address' => $userCrm->user->address,
'address2' => $userCrm->user->address2,
'town' => $userCrm->user->city,
'postal_code' => $userCrm->user->postcode,
'country' => $userCrm->user->country,
'email_verified' => true
]); ]);
if ($userCrm->user->status === 0) { // * On valide les données selon les critères de registerController
$customer->email_verified = false; $rules = collect((new RegisterRequest())->rules());
$customer->email_verify_token = Str::uuid(); $validator = Validator::make(
$customer->saveOrFail(); [
Mail::to($email)->send(new VerifyEmail($customer)); 'birth_date' => $crmCustomer->birth_date,
return back()->withInput($request->except("password")) 'address' => $crmCustomer->address,
// phpcs:ignore Generic.Files.LineLength.TooLong 'postcode' => $crmCustomer->postcode,
->withErrors("Votre compte existe mais votre email n'est pas confirmé, merci de vérifier vos emails."); 'country' => $crmCustomer->country->value,
} 'city' => $crmCustomer->city
} else { ],
if ($userCrm->code === 101) { [
return back()->withInput($request->only('email')) 'birth_date' => $rules->get('birth_date'),
->withErrors("Le mail que vous avez entré n'est pas enregistré dans nos services."); 'address' => $rules->get('address'),
'postcode' => $rules->get('postcode'),
'country' => $rules->get('country'),
'city' => $rules->get('city')
]
);
if ($validator->fails()) {
throw new ValidationException();
} else { } else {
return back()->withErrors("Une erreur est survenue, veuillez réessayer plus tard."); Session::remove('needCrmInfoUpdate', true);
} }
} //end if } catch (ValidationException $e) {
} //end if Session::push('needCrmInfoUpdate', true);
} catch (ApiErrorException $e) {
if (!$e->getApiError()->equals(ApiError::validationFailed())) {
throw $e;
}
Session::push('needCrmInfoUpdate', true);
} //end try
$customer->password_token = Str::uuid(); // * Si pas de compte local mais existe en CRM.
$customer->saveOrFail(); if (!$customer) {
$customer = $this->createLocalCustomer($crmCustomer);
}
/** @var \App\Models\Settings $settings */ abort($this->processLogin($customer, $request->remember));
$settings = app(Settings::class); } catch (ApiErrorException $e) {
abort($this->handleLoginApiErrorException($e, $request));
Mail::to($email)->send(new PasswordReset($customer, $settings)); } catch (CrmException $e) {
\report($e);
return redirect()->route('login') abort(back()->withInput($request->except('password'))
->with('success', 'Un mail de réinitialisation de votre mot de passe vous a été envoyé(e).'); ->withErrors('La connexion est impossible pour le moment, veuillez réessayer plus tard.'));
} //end try
} }
/** /**
* Forgot password form show * Handle Api error exception
* *
* @param Request $request * @param ApiErrorException $e
* @param mixed $token * @param AuthenticateRequest $request
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
public function forgotPasswordReset(Request $request, $token) private function handleLoginApiErrorException(ApiErrorException $e, AuthenticateRequest $request)
{ {
if (!$request->hasValidSignature(false)) { /** @var Customers|null */
return redirect()->route('login') $customer = Customer::where('email', $request->email)->first();
->withErrors("Le lien de changement de votre mot de passe n'est plus valide, veuillez réessayer."); /** @var \LDC\LDCCRM\CrmApiV2 */
} $crm = app('crmAPI');
switch ($e->getApiError()) {
case ApiError::authFailed():
// * Mauvais identifiants
return back()->withInput($request->except('password'))
->withErrors('Email ou mot de passe incorrect.');
case ApiError::customerNotActivated():
// * Le compte n'est pas activé
try {
if (!($crmCustomer = $crm->getCustomer($request->email))) {
Log::critical(sprintf('Customer %s could not be retrieved from crm', $request->email));
return back()->withErrors(
__('Une erreur est survenue, merci de réessayer ultérieurement.')
);
}
if (!$customer) {
$customer = $this->createLocalCustomer($crmCustomer);
}
$tokenMail = Str::uuid();
$tokenValid = false; Mail::to($request->email)->send(new VerifyEmail($crmCustomer, $tokenMail));
$customer->email_verify_token = $tokenMail;
if (!Customer::where('password_token', $token)->exists()) { $customer->saveOrFail();
return redirect()->route('forgot-password', compact('tokenValid')) return back()
->withErrors('Le lien de changement du mot de passe est incorrect.'); ->withErrors(
} __('Votre compte n\'est pas activé, vérifiez dans vos emails pour y trouver
le mail de confirmation. Un lien d\'activation vous a été renvoyé.')
$tokenValid = true; );
return redirect()->route('forgot-password', compact('tokenValid', 'token')); } catch (CrmException | ApiErrorException $e) {
report($e);
// ! Une erreur critique est survenue avec la CRM
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
} //end try
default:
report($e);
// ! Une erreur non gérée
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
} //end switch
} }
/** /**
* Change password form submit * Get Local customer using email and update info from crm.
* *
* @param UpdatePasswordRequest $request * @param string $email
* @return \Illuminate\Http\RedirectResponse * @return CrmCustomer|null
*/ */
public function changePassword(UpdatePasswordRequest $request) private function getCustomerFromCrm(string $email): ?CrmCustomer
{
try {
return CrmCustomer::findWithEmail($email);
} catch (ApiErrorException $e) {
if ($e->getApiError()->equals(ApiError::modelNotFound())) {
return null;
}
abort(back()->withErrors($e->getMessage()));
} catch (CrmException $e) {
report($e);
abort(back()->withErrors('Une erreur est survenue'));
}
}
/**
* Create a local customer
*
* @param CrmCustomer $crmCustomer
* @return Customer
*/
private function createLocalCustomer(CrmCustomer $crmCustomer): Customer
{ {
/** @var \App\Models\Customer $customer */ /** @var \App\Models\Customer $customer */
$customer = Customer::where( $customer = Customer::firstOrNew([
'password_token', 'email' => $crmCustomer->email
filter_var($request->token, FILTER_SANITIZE_STRING) ]);
)->first(); $customer->hashcode = $crmCustomer->hashcode;
$customer->saveOrFail();
if (!$customer) { return $customer;
return back()->withErrors('Le lien de changement de votre mot de passe est incorrect, veuillez réessayer.'); }
}
// TODO : Ajouter controle du contenu du mot de passe. /**
$newPassword = $request->password; * Login a customer
*
$update = $this->apiCrm->changePwdCustomer($customer->crm_id, $newPassword); * @param Customer $customer
* @param boolean $remember
if ($update->status === 'OK') { * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
$customer->password_token = null; */
$customer->saveOrFail(); private function processLogin(Customer $customer, bool $remember)
return redirect()->route('login') {
->with('success', 'Vous pouvez désormais vous connecter avec votre nouveau mot de passe.'); /** @var \Illuminate\Auth\SessionGuard */
} else { $guard = auth('customer');
if ($update->code === 123) { $guard->login($customer, $remember);
return back() $url = Session::pull('url.intended');
// phpcs:ignore Generic.Files.LineLength.TooLong Session::forget('url.intended');
->withErrors("Il semblerait que vous ayez déjà utilisé ce mot de passe pour votre compte. Veuillez réessayer en changeant de mot de passe."); Session::save();
} else { return $url ? redirect()->to($url) : response()->redirectToRoute('saisir-code');
return back()->withErrors("Une erreur est survenue, veuillez réessayer plus tard.");
}
}
} }
} }

View file

@ -6,33 +6,17 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\Fo\RegisterRequest; use App\Http\Requests\Fo\RegisterRequest;
use App\Mail\VerifyEmail; use App\Mail\VerifyEmail;
use App\Models\Customer; use App\Models\Customer;
use App\Providers\RouteServiceProvider; use Illuminate\Support\Carbon;
use Carbon\Carbon;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use LDC\LDCCRM\Enums\ApiError;
use LDC\LDCCRM\Exceptions\ApiErrorException;
use LDC\LDCCRM\Exceptions\CrmException;
use LDC\LDCCRM\Exceptions\ValidationException;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
class RegisterController extends Controller class RegisterController extends Controller
{ {
use RegistersUsers;
// TODO : Utilité ??
protected $redirectTo = RouteServiceProvider::HOME;
/**
* @var \LDCCRM\ApiV1
*/
private $apiCrm;
/**
* RegisterController
*/
public function __construct()
{
$this->apiCrm = new \LDCCRM\ApiV1(config('crm.endpoint'), config('crm.token'));
}
/** /**
* Register form * Register form
* *
@ -51,121 +35,70 @@ class RegisterController extends Controller
*/ */
public function registerSubmit(RegisterRequest $request) public function registerSubmit(RegisterRequest $request)
{ {
$lastname = filter_var($request->lastname, FILTER_SANITIZE_STRING); if (!Carbon::parse($request->birth_date)->lessThanOrEqualTo(Carbon::now()->subYears(18))) {
$firstname = filter_var($request->firstname, FILTER_SANITIZE_STRING);
$birthdate = $request->birth_date;
$email = filter_var($request->email, FILTER_SANITIZE_EMAIL);
$password = $request->password;
$address = filter_var($request->address, FILTER_SANITIZE_STRING);
$address2 = $request->address2 !== null ? filter_var($request->address2, FILTER_SANITIZE_STRING) : null;
$town = filter_var($request->town, FILTER_SANITIZE_STRING);
$postcode = filter_var($request->postal_code, FILTER_SANITIZE_STRING);
$country = filter_var($request->country, FILTER_SANITIZE_STRING);
$optin = $request->news !== null ? 1 : 0;
$tokenMail = Str::uuid();
$MJ = Carbon::now()->subYears(18);
if ($this->isSqlDate($birthdate)) {
$d = Carbon::createFromFormat('Y-m-d', $birthdate);
if (!$d->lessThanOrEqualTo($MJ)) {
return back()
->withInput($request->except('password'))
->withErrors("Vous devez être majeur pour vous inscrire au jeu.");
}
} elseif ($this->isFormDate($birthdate)) {
$d = Carbon::createFromFormat('d/m/Y', $birthdate);
if (!$d->lessThanOrEqualTo($MJ)) {
return back()
->withInput($request->except('password'))
->withErrors("Vous devez être majeur pour vous inscrire au jeu.");
}
$birthdate = $d->toDateString();
} else {
return back() return back()
->withInput($request->except('password')) ->withInput($request->except('password'))
->withErrors("Erreur sur le champs : date de naissance."); ->withErrors("Vous devez être majeur pour vous inscrire au jeu.");
} //end if }
$crmUser = $this->apiCrm->createCustomer( $crmCustomer = null;
$email, try {
$password, $crmCustomer = new CrmCustomer(\array_intersect_key(
$firstname, $request->validated(),
$lastname, [
$optin, 'firstname' => '',
$birthdate, 'lastname' => '',
null, 'birth_date' => '',
$address, 'address' => '',
$address2, 'postcode' => '',
$town, 'country' => '',
$postcode, 'city' => '',
ucfirst($country) 'phone' => '',
); 'email' => '',
'password' => '',
'opt_in' => '',
]
));
$crmCustomer->password = $request->password;
$crmCustomer->save();
if ($crmUser->status === 'OK') { $tokenMail = Str::uuid();
$customer = Customer::create([
'crm_id' => $crmUser->user->crm_id, Mail::to($request->email)->send(new VerifyEmail($crmCustomer, $tokenMail));
'firstname' => $firstname,
'lastname' => $lastname, $customer = new Customer();
'birth_date' => $birthdate, $customer->email = $crmCustomer->email;
'email' => $email, $customer->hashcode = $crmCustomer->hashcode;
'password' => Hash::make("MOTDEPASSE"), $customer->email_verify_token = $tokenMail;
// TODO : ??? $customer->saveOrFail();
'address' => $address,
'address2' => $address2,
'town' => $town,
'postal_code' => $postcode,
'country' => ucfirst($country),
'email_verify_token' => $tokenMail,
]);
Mail::to($email)->send(new VerifyEmail($customer));
return redirect()->route('login') return redirect()->route('login')
->with('success', "Pour finaliser votre inscription, merci de cliquer sur le lien qui vient de vous être envoyé par email<br>" . ->with('success', sprintf(
"Informations complémentaires :<br>" . '%s %s %s %s %s',
"- Vérifiez vos spams : l'email de confirmation s'y trouve peut-être<br>" . 'Pour finaliser votre inscription, merci de cliquer sur le lien qui vient de vous être envoyé par',
"- Attention : le mail peut parfois mettre quelques minutes à vous parvenir<br>" . 'email<br> Informations complémentaires :<br>',
"- L'activation de votre compte doit se faire dans les 24 heures qui suivent la demande de création."); '- Vérifiez vos spams : l\'email de confirmation s\'y trouve peut-être<br>',
} //end if '- Attention : le mail peut parfois mettre quelques minutes à vous parvenir<br>',
//phpcs:ignore Generic.Files.LineLength.TooLong
if ($crmUser->code === 103) { '- L\'activation de votre compte doit se faire dans les 24 heures qui suivent la demande de création.'
return back() ));
->withInput($request->except('password')) } catch (ApiErrorException $e) {
->withErrors("Un compte utilisateur est déjà associé à votre email."); if ($e->getApiError()->equals(ApiError::customerExists())) {
} return back()->withErrors('Un compte est déjà associé à cette adresse email.');
}
return back() if ($e->getApiError()->equals(ApiError::validationFailed())) {
->withInput($request->except('password')) return back()->withErrors($e->getMessage());
->withErrors("Une erreur est survenue, merci de recommencer."); }
} report($e);
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
/** } catch (ValidationException $e) {
* Regex is SQL date return back()->withErrors($e->getMessage());
* } catch (\Exception | \TypeError | CrmException $e) {
* @param mixed $date \report($e);
* @return boolean // ! Une erreur critique est survenue avec la CRM.
*/ return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
private function isSqlDate($date) } //end try
{ return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $date)) {
return true;
}
return false;
}
/**
* Regex is form date
*
* @param mixed $date
* @return boolean
*/
private function isFormDate($date)
{
if (preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/[0-9]{4}$/", $date)) {
return true;
}
return false;
} }
} }

View file

@ -3,121 +3,114 @@
namespace App\Http\Controllers\Fo; namespace App\Http\Controllers\Fo;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\Fo\SubmitWinningProof; use App\Http\Requests\Fo\SubmitWinningProofRequest;
use App\Mail\NotifAdmin;
use App\Mail\WinningProofMail; use App\Mail\WinningProofMail;
use App\Models\Participation; use App\Models\Participation;
use App\Models\Settings; use App\Models\Settings;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use LDC\LDCCRM\Exceptions\ApiErrorException;
use LDC\LDCCRM\Exceptions\CrmException;
use LDC\LDCCRM\Exceptions\ValidationException;
class WinningProofController extends Controller class WinningProofController extends Controller
{ {
/**
* @var \LDCCRM\ApiV1
*/
private $apiCrm;
/**
* WinningProofController
*/
public function __construct()
{
$this->apiCrm = new \LDCCRM\ApiV1(config('crm.endpoint'), config('crm.token'));
}
/** /**
* Submit Winning proof * Submit Winning proof
* *
* @param SubmitWinningProof $request * @param SubmitWinningProofRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory * @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/ */
public function sendWinningProof(SubmitWinningProof $request) public function sendWinningProof(SubmitWinningProofRequest $request)
{ {
/** @var \App\Models\Customer $customer */ try {
$customer = auth('customer')->user(); return DB::transaction(function () use ($request) {
/** @var \App\Models\Customer $customer */
$customer = auth('customer')->user();
// On récupère la participation gagnante en attente des infos. /** @var \LDC\LDCCRM\Models\Customer $crmCustomer */
/** @var \App\Models\Participation|null $participation */ $crmCustomer = $customer->apiData;
$participation = Participation::whereHas('customer', function ($q) use ($customer) {
$q->whereId($customer->id);
})->whereHas('instantWin')->where([
['sticker', null],
['ticket', null],
['barcode', null]
])->first();
if (!$participation) { // On récupère la participation gagnante en attente des infos.
return redirect()->route('home'); /** @var \App\Models\Participation|null $participation */
} $participation = Participation::whereHas('customer', function ($q) use ($customer) {
$q->whereId($customer->id);
})->whereHas('instantWin')->where([
['sticker', null],
['ticket', null],
['barcode', null]
])->first();
/** @var \Illuminate\Http\UploadedFile $sticker */ if (!$participation) {
$sticker = $request->sticker; return redirect()->route('home');
/** @var \Illuminate\Http\UploadedFile $ticket */ }
$ticket = $request->ticket;
/** @var \Illuminate\Http\UploadedFile $barcode */
$barcode = $request->barcode;
// * Mise à jour de l'utilisateur en local. /** @var \Illuminate\Http\UploadedFile $sticker */
/** @var \App\Models\Customer $customer */ $sticker = $request->sticker;
$customer->fill($request->validated()); /** @var \Illuminate\Http\UploadedFile $ticket */
$customer->saveOrFail(); $ticket = $request->ticket;
/** @var \Illuminate\Http\UploadedFile $barcode */
$barcode = $request->barcode;
// Mise à jour utilisateur dans la CRM. // * Mise à jour utilisateur dans la CRM.
$update = $this->apiCrm->updateCustomer( try {
$customer->crm_id, $crmCustomer->fill(\array_intersect_key($request->validated(), [
$customer->firstname, 'firstname' => '',
$customer->lastname, 'lastname' => '',
null, 'address' => '',
null, 'postcode' => '',
$customer->phone, 'country' => '',
$customer->address, 'city' => '',
$customer->address2, 'phone' => '',
$customer->town, ]));
$customer->postal_code, $crmCustomer->save();
ucfirst($request->country) } catch (ApiErrorException | ValidationException $e) {
); return back()->withErrors($e->getMessage());
if ($update->status !== 'OK') { } catch (\Exception | \TypeError | CrmException $e) {
Log::warning('Erreur lors de la mise a jour du user (crm_id : ' . $customer->crm_id . \report($e);
') - code : ' . $update->code . ' - message : ' . $update->message); } //end try
Mail::to(config('mail.MAIL_ADMIN'))->send(new NotifAdmin(
'CRM : Erreur lors de la mise a jour du user (crm_id : ' .
$customer->crm_id . ') - code : ' . $update->code . ' - message : ' . $update->message
));
}
$participationId = $participation->id; $participationId = $participation->id;
$stickerFileName = $participationId . '-sticker.' . $sticker->extension(); $stickerFileName = $participationId . '-sticker.' . $sticker->extension();
$sticker->move(public_path('fichiers/preuve-de-gain/' . $participationId . '/'), $stickerFileName); $sticker->move(public_path('fichiers/preuve-de-gain/' . $participationId . '/'), $stickerFileName);
$stickerPath = public_path() . '/fichiers/preuve-de-gain/' . $participationId . '/' . $stickerFileName; $stickerPath = public_path() . '/fichiers/preuve-de-gain/' . $participationId . '/' . $stickerFileName;
$ticketFileName = $participationId . '-ticket.' . $ticket->extension(); $ticketFileName = $participationId . '-ticket.' . $ticket->extension();
$ticket->move(public_path('fichiers/preuve-de-gain/' . $participationId . '/'), $ticketFileName); $ticket->move(public_path('fichiers/preuve-de-gain/' . $participationId . '/'), $ticketFileName);
$ticketPath = public_path() . '/fichiers/preuve-de-gain/' . $participationId . '/' . $ticketFileName; $ticketPath = public_path() . '/fichiers/preuve-de-gain/' . $participationId . '/' . $ticketFileName;
$barcodeFileName = $participationId . '-code-barre.' . $barcode->extension(); $barcodeFileName = $participationId . '-code-barre.' . $barcode->extension();
$barcode->move(public_path('fichiers/preuve-de-gain/' . $participationId . '/'), $barcodeFileName); $barcode->move(public_path('fichiers/preuve-de-gain/' . $participationId . '/'), $barcodeFileName);
$barcodePath = public_path() . '/fichiers/preuve-de-gain/' . $participationId . '/' . $barcodeFileName; $barcodePath = public_path() . '/fichiers/preuve-de-gain/' . $participationId . '/' . $barcodeFileName;
$participation->sticker = $stickerFileName; $participation->sticker = $stickerFileName;
$participation->ticket = $ticketFileName; $participation->ticket = $ticketFileName;
$participation->barcode = $barcodeFileName; $participation->barcode = $barcodeFileName;
$participation->saveOrFail(); $participation->saveOrFail();
/** @var \App\Models\Settings $settings */ /** @var \App\Models\Settings $settings */
$settings = app(Settings::class); $settings = app(Settings::class);
$mails = \collect($settings->notification_emails); $mails = \collect($settings->notification_emails);
foreach ($mails as $mail) { // ? Is settings.notification_emails empty ?
Mail::to($mail)->send(new WinningProofMail( if (!$mails->count()) {
$stickerPath, // ! Send to null (will send to MAIL_ADMIN and print warning in mail object)
$ticketPath, $mails = [null];
$barcodePath, }
$participation, foreach ($mails as $mail) {
$customer, Mail::to($mail)->send(new WinningProofMail(
$settings $stickerPath,
)); $ticketPath,
} $barcodePath,
$participation,
return view('front.basic.replay'); $crmCustomer,
$settings
));
}
return view('front.basic.replay');
});
} catch (\Exception $e) {
report($e);
return back()->withErrors('Une erreur est survenue, merci de réessayez ultérieurement.');
}//end try
} }
} }

View file

@ -65,5 +65,6 @@ class Kernel extends HttpKernel
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'crmInfosMustBeComplete' => \App\Http\Middleware\MustCompleteCrmInfo::class
]; ];
} }

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Session;
class MustCompleteCrmInfo
{
/**
* Handle an incoming request.
*
* @param mixed $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
/**
* IF session has need crm completion
* then redirect to completion page
*/
if (
Session::get('needCrmInfoUpdate') and
($request->route() and !\in_array($request->route()->getName(), ['completeInfos', 'completeInfosSubmit']))
) {
return response()->redirectToRoute('completeInfos');
}
return $next($request);
}
}

View file

@ -55,7 +55,7 @@ class UpdateSettingsRequest extends FormRequest
'reductions_campaign' => 'required_if:reductions_activated,1|string|min:1|max:255', 'reductions_campaign' => 'required_if:reductions_activated,1|string|min:1|max:255',
'web_coupons' => 'nullable|array', 'web_coupons' => 'nullable|array',
'web_coupons.*' => 'required|array', 'web_coupons.*' => 'required|array',
'web_coupons.*.web_coupon_identifiant' => 'required|string|min:2|max:50', 'web_coupons.*.web_coupon_identifiant' => 'required|numeric|min:2|max:50',
'web_coupons.*.percentage' => 'required|numeric', 'web_coupons.*.percentage' => 'required|numeric',
'web_coupons.*.face_value' => 'required|numeric', 'web_coupons.*.face_value' => 'required|numeric',
'web_coupons.*.valid_on' => 'required|string|min:2|max:150', 'web_coupons.*.valid_on' => 'required|string|min:2|max:150',

View file

@ -0,0 +1,35 @@
<?php
namespace App\Http\Requests\Bo;
use Illuminate\Foundation\Http\FormRequest;
class UpdateWinInfosRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
$this->merge([
'done' => $this->done ? true : false,
'comment' => $this->comment ?? ''
]);
return $this->ajax() and auth('web')->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'done' => 'required|boolean',
'comment' => 'required|string|max:255'
];
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace App\Http\Requests\Fo;
class CompleteInfosRequest extends RegisterRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
$this->merge([
'opt_in' => $this->opt_in ? true : false,
'agree' => $this->agree ? true : false
]);
return auth('customer')->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return \array_intersect_key(parent::rules(), [
'firstname' => '',
'lastname' => '',
'birth_date' => '',
'address' => '',
'postcode' => '',
'country' => '',
'city' => '',
'phone' => '',
'opt_in' => ''
]);
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Fo;
use Illuminate\Foundation\Http\FormRequest;
class ForgotPasswordRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth('customer')->guest();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'email' => 'required|email:rfc,filter|max:255'
];
}
}

View file

@ -84,38 +84,45 @@ class ParticipateRequest extends FormRequest
) { ) {
$fail('Code incorrect, veuillez réessayer.'); $fail('Code incorrect, veuillez réessayer.');
return false; return false;
} elseif ($value->code_used === 1) {
$fail('Ce code n\'est plus utilisable.');
return false;
} }
/** @var \App\Models\Code $code */
$code = $value;
// * Check si l'utilisateur n'a pas déjà utilisé ce code. // * Check si l'utilisateur n'a pas déjà utilisé ce code.
$query = Participation::whereHas('customer', function ($q) use ($customer) { $query = Participation::whereHas('customer', function ($q) use ($customer) {
$q->whereId($customer->id); $q->whereId($customer->id);
})->whereHas('code', function ($q) { })->whereHas('code', function ($q) use ($code) {
$q->whereId($this->code->id); $q->whereId($code->id);
}); });
if ($query->exists()) { if ($query->exists()) {
$fail('Vous avez déjà utilisé ce code.'); $fail('Vous avez déjà utilisé ce code.');
return false;
}
if ($code->code_used) {
$fail('Ce code n\'est plus utilisable.');
return false;
} }
/** @var \App\Models\Settings $settings */ /** @var \App\Models\Settings $settings */
$settings = app(Settings::class); $settings = app(Settings::class);
$codeNbUsage = Participation::whereHas('code', function ($q) { $codeNbUsage = Participation::whereHas('code', function ($q) use ($code) {
$q->whereId($this->code->id); $q->whereId($code->id);
})->count(); })->count();
// * Gestion du nombre d'utilisation d'un code. // * Gestion du nombre d'utilisation d'un code.
if ($codeNbUsage >= $settings->nb_unique_code_use) { if ($codeNbUsage >= $settings->nb_unique_code_use) {
$this->code->code_used = 1; $code->code_used = true;
return back()->withErrors("Ce code n'est plus utilisable."); $code->saveOrFail();
} else { } else {
if ($codeNbUsage + 1 >= $settings->nb_unique_code_use) { if ($codeNbUsage + 1 >= $settings->nb_unique_code_use) {
$this->code->code_used = 1; $code->code_used = true;
$code->saveOrFail();
} }
} }
$this->code->saveOrFail();
} }
] ]
]; ];

View file

@ -2,10 +2,32 @@
namespace App\Http\Requests\Fo; namespace App\Http\Requests\Fo;
use ArondeParon\RequestSanitizer\Sanitizers\FilterVars;
use ArondeParon\RequestSanitizer\Sanitizers\Trim;
use ArondeParon\RequestSanitizer\Traits\SanitizesInputs;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Password;
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
use LDC\LDCCRM\Enums\Country;
class RegisterRequest extends FormRequest class RegisterRequest extends FormRequest
{ {
use SanitizesInputs;
/**
* Using these sanitizers before proceeding the request
* @var array
*/
protected $sanitizers = [
'email' => Trim::class,
'firstname' => [Trim::class, FilterVars::class => ['filter' => FILTER_SANITIZE_STRING]],
'lastname' => [Trim::class, FilterVars::class => ['filter' => FILTER_SANITIZE_STRING]],
'address' => [Trim::class, FilterVars::class => ['filter' => FILTER_SANITIZE_STRING]],
'address2' => [Trim::class, FilterVars::class => ['filter' => FILTER_SANITIZE_STRING]],
'phone' => [Trim::class, FilterVars::class => ['filter' => FILTER_SANITIZE_STRING]],
'city' => [Trim::class, FilterVars::class => ['filter' => FILTER_SANITIZE_STRING]],
];
/** /**
* Determine if the user is authorized to make this request. * Determine if the user is authorized to make this request.
* *
@ -13,6 +35,10 @@ class RegisterRequest extends FormRequest
*/ */
public function authorize() public function authorize()
{ {
$this->merge([
'opt_in' => $this->opt_in ? true : false,
'agree' => $this->agree ? true : false
]);
return auth('customer')->guest(); return auth('customer')->guest();
} }
@ -24,17 +50,29 @@ class RegisterRequest extends FormRequest
public function rules() public function rules()
{ {
return [ return [
'email' => 'required|email:rfc,dns,spoof,filter|max:255|unique:customers,email',
'firstname' => 'required|string|min:1|max:255',
'lastname' => 'required|string|max:255', 'lastname' => 'required|string|max:255',
'firstname' => 'required|string|max:255', 'birth_date' => 'required|string|date_format:Y-m-d',
'birth_date' => 'required|string|max:10', 'address' => 'required|string|min:2|max:255',
'email' => 'required|string|email:spoof,rfc,filter,dns|max:255|unique:users|confirmed', 'address2' => 'sometimes|string|max:255',
'password' => 'required|string|min:8|confirmed', 'phone' => 'sometimes|string|max:255',
'address' => 'required|string|max:255', 'city' => 'required|string|min:2|max:255',
'address2' => 'max:255', 'country' => [
'town' => 'required|string|max:255', 'required', new EnumIsValidRule(Country::class)
'postal_code' => 'required|string|max:255', ],
'country' => 'required|string|max:255', 'postcode' => 'required|numeric|digits_between:4,5',
'reglement' => 'accepted', 'password' => [
'required', 'confirmed', 'min:8', 'max:255',
Password::min(8)
->mixedCase()
->letters()
->numbers()
->symbols()
->uncompromised()
],
'opt_in' => 'required|boolean',
'agree' => 'required|boolean'
]; ];
} }
} }

View file

@ -2,9 +2,7 @@
namespace App\Http\Requests\Fo; namespace App\Http\Requests\Fo;
use Illuminate\Foundation\Http\FormRequest; class SubmitWinningProofRequest extends RegisterRequest
class SubmitWinningProof extends FormRequest
{ {
/** /**
* Determine if the user is authorized to make this request. * Determine if the user is authorized to make this request.
@ -23,18 +21,18 @@ class SubmitWinningProof extends FormRequest
*/ */
public function rules() public function rules()
{ {
return [ return \array_merge(\array_intersect_key(parent::rules(), [
'lastname' => 'required|string|max:255', 'firstname' => '',
'firstname' => 'required|string|max:255', 'lastname' => '',
'address' => 'required|string|max:255', 'address' => '',
'address2' => 'nullable|string|max:255', 'postcode' => '',
'town' => 'required|string|max:255', 'country' => '',
'postal_code' => 'required|max:255', 'city' => '',
'country' => 'required|string|max:255', 'phone' => '',
'phone' => 'required|string|max:50', ]), [
'sticker' => 'required|mimes:jpeg,png,jpg,pdf|max:2048', 'sticker' => 'required|mimes:jpeg,png,jpg,pdf|max:2048',
'ticket' => 'required|mimes:jpeg,png,jpg,pdf|max:2048', 'ticket' => 'required|mimes:jpeg,png,jpg,pdf|max:2048',
'barcode' => 'required|mimes:jpeg,png,jpg,pdf|max:2048', 'barcode' => 'required|mimes:jpeg,png,jpg,pdf|max:2048',
]; ]);
} }
} }

View file

@ -3,6 +3,7 @@
namespace App\Http\Requests\Fo; namespace App\Http\Requests\Fo;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Password;
class UpdatePasswordRequest extends FormRequest class UpdatePasswordRequest extends FormRequest
{ {
@ -13,6 +14,7 @@ class UpdatePasswordRequest extends FormRequest
*/ */
public function authorize() public function authorize()
{ {
// * Autorisation vérifiée dans le controlleur.
return true; return true;
} }
@ -24,7 +26,15 @@ class UpdatePasswordRequest extends FormRequest
public function rules() public function rules()
{ {
return [ return [
'password' => 'required|min:8|confirmed' 'password' => [
'required', 'confirmed', 'min:8', 'max:255',
Password::min(8)
->mixedCase()
->letters()
->numbers()
->symbols()
->uncompromised()
]
]; ];
} }
} }

View file

@ -1,45 +0,0 @@
<?php
namespace App\Mail;
use App\Models\Customer;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class CourrierArcadiaError extends Mailable implements ShouldQueue
{
use Queueable;
use SerializesModels;
/**
* Customer
*
* @var \App\Models\Customer
*/
private $customer;
/**
* Create a new message instance.
*
* @param \App\Models\Customer $customer
* @return void
*/
public function __construct(Customer $customer)
{
$this->customer = $customer;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$customer = $this->customer;
return $this->subject("Erreur envoi courrier arcadia")
->view('front.basic.error-arcadia-email', compact('customer'));
}
}

View file

@ -12,14 +12,15 @@ class NotifAdmin extends Mailable implements ShouldQueue
use Queueable; use Queueable;
use SerializesModels; use SerializesModels;
/** @var string */
private $msg; private $msg;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @return void * @param string $msg
*/ */
public function __construct($msg) public function __construct(string $msg)
{ {
$this->msg = $msg; $this->msg = $msg;
} }
@ -32,6 +33,7 @@ class NotifAdmin extends Mailable implements ShouldQueue
public function build() public function build()
{ {
$msg = $this->msg; $msg = $this->msg;
return $this->subject(config('app.name') . " : Erreur")->view('front.basic.notif-admin', compact('msg')); return $this->subject(config('app.name') . ': Erreur')
->view('front.basic.notif-admin', compact('msg'));
} }
} }

View file

@ -2,25 +2,38 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Participation;
use App\Models\Settings;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
class NotifWinAdmin extends Mailable implements ShouldQueue class NotifWinAdmin extends Mailable implements ShouldQueue
{ {
use Queueable; use Queueable;
use SerializesModels; use SerializesModels;
private $settings, $participation; /** @var Settings */
private $settings;
/** @var Settings */
private $participation;
/** @var CrmCustomer */
private $crmCustomer;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @return void * @param CrmCustomer $crmCustomer
* @param Settings $settings
* @param Participation $participation
*/ */
public function __construct($settings, $participation) public function __construct(CrmCustomer $crmCustomer, Settings $settings, Participation $participation)
{ {
$this->crmCustomer = $crmCustomer;
$this->settings = $settings; $this->settings = $settings;
$this->participation = $participation; $this->participation = $participation;
} }
@ -32,8 +45,16 @@ class NotifWinAdmin extends Mailable implements ShouldQueue
*/ */
public function build() public function build()
{ {
$participation = $this->participation; $subject = '';
return $this->subject($this->settings->name . " : un lot a été gagné") if (!collect($this->to)->count()) {
->view('front.basic.notif-win-admin-email', compact('participation')); $this->to(config('mail.MAIL_ADMIN'));
$subject = '!!! AUCUNE Valeur configurée dans settings email list. !!!';
}
$subject .= $this->settings->name . ' : un lot a été gagné';
return $this->subject($subject)
->view('front.basic.notif-win-admin-email', [
'crmCustomer' => $this->crmCustomer,
'participation' => $this->participation
]);
} }
} }

View file

@ -2,43 +2,40 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Customer;
use App\Models\Prize; use App\Models\Prize;
use App\Models\Settings; use App\Models\Settings;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
class PrizeWon extends Mailable implements ShouldQueue class PrizeWon extends Mailable implements ShouldQueue
{ {
use Queueable; use Queueable;
use SerializesModels; use SerializesModels;
/** @var \App\Models\User $user */ /** @var CrmCustomer */
private $user; private $crmCustomer;
/** @var \App\Models\Prize $prize */ /** @var \App\Models\Prize */
private $prize; private $prize;
/** @var \App\Models\Settings $settings */ /** @var \App\Models\Settings */
private $settings; private $settings;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @param Customer $customer * @param CrmCustomer $crmCustomer
* @param Prize $prize * @param Prize $prize
* @param Settings $settings * @param Settings $settings
*/ */
public function __construct( public function __construct(CrmCustomer $crmCustomer, Prize $prize, Settings $settings)
Customer $customer, {
Prize $prize, $this->crmCustomer = $crmCustomer;
Settings $settings $this->prize = $prize;
) { $this->settings = $settings;
$this->customer = $customer;
$this->prize = $prize;
$this->settings = $settings;
} }
/** /**
@ -48,9 +45,13 @@ class PrizeWon extends Mailable implements ShouldQueue
*/ */
public function build() public function build()
{ {
return $this->subject("Félicitations " . $this->customer->firstname . return $this->subject("Félicitations " . $this->crmCustomer->firstname .
", vous avez remporté 1 " . $this->prize->label_one . " !") ", vous avez remporté 1 " . $this->prize->label_one . " !")
->view('front.basic.prize-mail') ->view('front.basic.prize-mail')
->with(['customer' => $this->customer, 'prize' => $this->prize, 'settings' => $this->settings]); ->with([
'crmCustomer' => $this->crmCustomer,
'prize' => $this->prize,
'settings' => $this->settings
]);
} }
} }

View file

@ -2,39 +2,45 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Customer; use App\Models\Reduction;
use App\Models\Settings;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
class ReductionWon extends Mailable implements ShouldQueue class ReductionWon extends Mailable implements ShouldQueue
{ {
use Queueable; use Queueable;
use SerializesModels; use SerializesModels;
/** /** @var CrmCustomer */
* Customer private $crmCustomer;
*
* @var Customer
*/
private $customer;
private $coupon, /** @var integer */
private $settings, private $faceValue;
private $crmCoupon;
/** @var Settings */
private $settings;
/** @var Reduction */
private $reduction;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @return void * @param CrmCustomer $crmCustomer
* @param integer $faceValue
* @param Settings $settings
* @param Reduction $reduction
*/ */
public function __construct(Customer $customer, $coupon, $settings, $crmCoupon) public function __construct(CrmCustomer $crmCustomer, int $faceValue, Settings $settings, Reduction $reduction)
{ {
$this->customer = $customer; $this->crmCustomer = $crmCustomer;
$this->coupon = $coupon; $this->faceValue = $faceValue;
$this->settings = $settings; $this->settings = $settings;
$this->crmCoupon = $crmCoupon; $this->reduction = $reduction;
} }
/** /**
@ -47,10 +53,10 @@ class ReductionWon extends Mailable implements ShouldQueue
return $this->subject($this->customer->firstname . ", n'attendez plus pour imprimer votre bon d'achat " . return $this->subject($this->customer->firstname . ", n'attendez plus pour imprimer votre bon d'achat " .
$this->settings->name . " !")->view('front.basic.reduction-mail') $this->settings->name . " !")->view('front.basic.reduction-mail')
->with([ ->with([
'customer' => $this->customer, 'crmCustomer' => $this->crmCustomer,
'coupon' => $this->coupon, 'faceValue' => $this->faceValue,
'settings' => $this->settings, 'settings' => $this->settings,
'crmCoupon' => $this->crmCoupon 'link' => $this->reduction->link
]); ]);
} }
} }

View file

@ -2,28 +2,33 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Customer;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use LDC\LDCCRM\Models\Customer;
class VerifyEmail extends Mailable implements ShouldQueue class VerifyEmail extends Mailable implements ShouldQueue
{ {
use Queueable; use Queueable;
use SerializesModels; use SerializesModels;
/** @var \App\Models\Customer $customer */ /** @var \LDC\LDCCRM\Models\Customer $customer */
protected $customer; protected $customer;
/** @var string $emailCheckToken */
protected $emailCheckToken;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @param Customer $customer * @param Customer $customer
* @param string $emailCheckToken
*/ */
public function __construct(Customer $customer) public function __construct(Customer $customer, string $emailCheckToken)
{ {
$this->customer = $customer; $this->customer = $customer;
$this->emailCheckToken = $emailCheckToken;
} }
/** /**
@ -35,6 +40,7 @@ class VerifyEmail extends Mailable implements ShouldQueue
{ {
return $this->subject("Activation du compte") return $this->subject("Activation du compte")
->view('front.basic.verifyemail') ->view('front.basic.verifyemail')
->with('customer', $this->customer); ->with('customer', $this->customer)
->with('emailCheckToken', $this->emailCheckToken);
} }
} }

View file

@ -2,13 +2,13 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Customer;
use App\Models\Participation; use App\Models\Participation;
use App\Models\Settings; use App\Models\Settings;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
class WinningProofMail extends Mailable implements ShouldQueue class WinningProofMail extends Mailable implements ShouldQueue
{ {
@ -34,9 +34,9 @@ class WinningProofMail extends Mailable implements ShouldQueue
/** /**
* Customer * Customer
* *
* @var Customer * @var CrmCustomer
*/ */
private $customer; private $crmCustomer;
/** /**
* Settings * Settings
@ -52,7 +52,7 @@ class WinningProofMail extends Mailable implements ShouldQueue
* @param string $ticketPath * @param string $ticketPath
* @param string $barcodePath * @param string $barcodePath
* @param Participation $participation * @param Participation $participation
* @param Customer $customer * @param CrmCustomer $crmCustomer
* @param Settings $settings * @param Settings $settings
*/ */
public function __construct( public function __construct(
@ -60,14 +60,14 @@ class WinningProofMail extends Mailable implements ShouldQueue
string $ticketPath, string $ticketPath,
string $barcodePath, string $barcodePath,
Participation $participation, Participation $participation,
Customer $customer, CrmCustomer $crmCustomer,
Settings $settings Settings $settings
) { ) {
$this->stickerPath = $stickerPath; $this->stickerPath = $stickerPath;
$this->ticketPath = $ticketPath; $this->ticketPath = $ticketPath;
$this->barcodePath = $barcodePath; $this->barcodePath = $barcodePath;
$this->participation = $participation; $this->participation = $participation;
$this->customer = $customer; $this->crmCustomer = $crmCustomer;
$this->settings = $settings; $this->settings = $settings;
} }
@ -80,10 +80,14 @@ class WinningProofMail extends Mailable implements ShouldQueue
{ {
$participation = $this->participation; $participation = $this->participation;
$customer = $this->customer; $customer = $this->customer;
return $this->subject( $subject = '';
$this->settings->name . " : Preuves de gain de " . if (!collect($this->to)->count()) {
$customer->lastname . " " . $customer->firstname $this->to(config('mail.MAIL_ADMIN'));
)->view( $subject = '!!! AUCUNE Valeur configurée dans settings email list. !!!';
}
$subject .= $this->settings->name . ' : Preuves de gain de ' .
$customer->lastname . ' ' . $customer->firstname;
return $this->subject($subject)->view(
'front.basic.winning-proof-email', 'front.basic.winning-proof-email',
compact('participation', 'customer') compact('participation', 'customer')
)->attach($this->stickerPath)->attach($this->ticketPath) )->attach($this->stickerPath)->attach($this->ticketPath)

View file

@ -4,6 +4,8 @@ namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use LDC\LDCCRM\Exceptions\CrmException;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
class Customer extends Authenticatable class Customer extends Authenticatable
{ {
@ -15,20 +17,9 @@ class Customer extends Authenticatable
* @var array * @var array
*/ */
protected $fillable = [ protected $fillable = [
'crm_id', 'hashcode',
'civility',
'firstname',
'lastname',
'birth_date',
'email', 'email',
'password', 'email_verify_token'
'address',
'address2',
'town',
'postal_code',
'country',
'email_verify_token',
'email_verified'
]; ];
/** /**
@ -37,26 +28,7 @@ class Customer extends Authenticatable
* @var array * @var array
*/ */
protected $hidden = [ protected $hidden = [
'password', 'remember_token', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified' => 'boolean',
'email_verified_at' => 'datetime',
];
/**
* Map attribute names to enum classes.
*
* @var array
*/
protected $enumCasts = [
'role' => UserRole::class
]; ];
// * RELATIONSHIPS // * RELATIONSHIPS
@ -94,4 +66,56 @@ class Customer extends Authenticatable
{ {
return false; return false;
} }
/**
* Get the crm Data of a customer
*
* @return \LDC\LDCCRM\Models\Customer
* @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
* Possibles are : - modelNotFound, If this customer hashcode could not be found.
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
* @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
*/
public function getApiDataAttribute(): CrmCustomer
{
/** @var \LDC\LDCCRM\CrmApiV2 */
$crm = app('crmAPI');
$crmCustomer = $crm->getCustomer($this->hashcode);
if (!$crmCustomer) {
throw new CrmException('CRM get Customer returned null');
}
return $crmCustomer;
}
/**
* This mutate Customer attributes to array
* including only non critical properties and crm values
* (One that can be send to front office without security breach)
*
* @return array
*/
public function toArray()
{
if ($this->hashcode) {
return collect(array_merge(
parent::toArray(),
(array)$this->apiData
))->intersectByKeys([
'email' => '',
'firstname' => '',
'lastname' => '',
'address' => '',
'address2' => '',
'postcode' => '',
'birth_date' => '',
'city' => '',
'country' => '',
'opt_in' => '',
'phone' => ''
])->toArray();
} else {
return parent::toArray();
}
}
} }

View file

@ -26,8 +26,8 @@ class InstantWin extends Model
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'won' => 'bool', 'appear_date' => 'datetime',
'appear_date' => 'datetime' 'done' => 'bool'
]; ];
// * RELATIONSHIPS // * RELATIONSHIPS
@ -51,4 +51,16 @@ class InstantWin extends Model
{ {
return $this->belongsTo(Participation::class); return $this->belongsTo(Participation::class);
} }
// * Methods
/**
* Get won attribute
*
* @return boolean
*/
public function getWonAttribute(): bool
{
return $this->participation()->exists();
}
} }

View file

@ -11,7 +11,10 @@ use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\View; use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\URL; use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\ValidationException;
use LDC\LDCCRM\Enums\Country;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {
@ -19,6 +22,7 @@ class AppServiceProvider extends ServiceProvider
* Bootstrap any application services. * Bootstrap any application services.
* *
* @return void * @return void
* @throws \ErrorException If MAIL_ADMIN is not set in .env .
*/ */
public function boot() public function boot()
{ {
@ -56,7 +60,36 @@ class AppServiceProvider extends ServiceProvider
return $settings; return $settings;
}); });
// * AvailableCountries
View::share('availableCountries', [
Country::france(),
Country::belgium(),
Country::luxembourg(),
Country::guadeloupe(),
Country::martinique(),
Country::frenchGuiana(),
Country::reunion(),
Country::saintPierreAndMiquelon(),
Country::mayotte(),
Country::saintBarthelemy(),
Country::saintMartinFrenchPart(),
Country::wallisAndFutuna(),
Country::frenchPolynesia(),
Country::newCaledonia()
]);
if (!app()->runningInConsole()) { if (!app()->runningInConsole()) {
// ! MAIL_ADMIN est obligatoire dans le .env
try {
Validator::validate(['mail' => config('mail.MAIL_ADMIN')], [
'mail' => 'required|email:rfc,strict,spoof'
]);
} catch (ValidationException $e) {
throw new \ErrorException(
'La valeur mail doit contenir une adresse email valide dans la configuration.'
);
}
// On ramène le nom du jeu et le nom de la société sur toute les pages. // On ramène le nom du jeu et le nom de la société sur toute les pages.
$settingsGlobal = Cache::get('settingsGlobal'); $settingsGlobal = Cache::get('settingsGlobal');
if (!$settingsGlobal) { if (!$settingsGlobal) {

View file

@ -0,0 +1,26 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\ServiceProvider;
use LDC\LDCCRM\CrmApiV2;
class CrmApiServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
App::singleton('crmAPI', function () {
return new CrmApiV2(
config('crm.endpoint'),
config('crm.token'),
config('crm.password')
);
});
}
}

View file

@ -1,162 +0,0 @@
<?php
namespace LDCCRM;
class ApiV1
{
private $endpoint;
private $api_key;
public function __construct($endpoint, $api_key)
{
$this->endpoint = $endpoint;
$this->api_key = $api_key;
}
public function getCustomer($id){
return $this->callAPI('GET', "/customer/id/$id");
}
public function getCustomerByEmail($email){
return $this->callAPI('GET', "/customer/email/$email");
}
public function createCustomer($email, $password, $firstname, $lastname, $optin, $birthdate = null, $phone = null, $address = null, $address2 = null, $city = null, $postcode = null, $country = null){
$user = [
'email' => $email,
'password' => $password,
'firstname' => $firstname,
'lastname' => $lastname,
'opt_in' => $optin,
'birth_date' => $birthdate,
'phone' => $phone,
'address' => $address,
'address2' => $address2,
'city' => $city,
'postcode' => $postcode,
'country' => $country
];
return $this->callAPI('POST', '/customer/create', $user);
}
public function updateCustomer($crmId, $firstname = null, $lastname = null, $optin = null, $birthdate = null, $phone = null, $address = null, $address2 = null, $city = null, $postcode = null, $country = null){
$user = [];
if ($firstname !== null)
$user['firstname'] = $firstname;
if ($lastname !== null)
$user['lastname'] = $lastname;
if ($optin !== null)
$user['opt_in'] = $optin;
if ($birthdate !== null)
$user['birth_date'] = $birthdate;
if ($phone !== null)
$user['phone'] = $phone;
if ($address !== null)
$user['address'] = $address;
if ($address2 !== null)
$user['address2'] = $address2;
if ($city !== null)
$user['city'] = $city;
if ($postcode !== null)
$user['postcode'] = $postcode;
if ($country !== null)
$user['country'] = $country;
return $this->callAPI('PUT', "/customer/$crmId", $user);
}
public function deleteCustomer($id){
return $this->callAPI('DELETE', "/customer/$id");
}
public function changePwdCustomer($id, $password){
return $this->callAPI('POST', "/customer/$id/change-password", ['password' => $password]);
}
public function activateCustomer($id){
return $this->callAPI('POST', "/customer/$id/activate");
}
public function toggleOptInCustomer($id){
return $this->callAPI('POST', "/customer/$id/toggle-optin");
}
public function loginCustomer($email, $password){
return $this->callAPI('POST', "/customer/login", ['email' => $email, 'password' => $password]);
}
public function createSingleOptin($email){
return $this->callAPI('POST', '/single-optin', ['email' => $email]);
}
public function ArcadiaOutgoingMail($crm_id, $fields, $type){
return $this->callAPI('POST', '/arcadia/outgoing-mail', ['crm_id' => $crm_id, 'fields' => json_encode($fields), 'type' => $type]);
}
private function callAPI($method, $url, $data = false){
if (strpos($this->endpoint, "dev")){
if ($data !== false){
$data = array_merge($data, ['api_token' => $this->api_key]);
}else{
$data = ['api_token' => $this->api_key];
}
}
$url = $this->endpoint . '/api/v1' . $url;
$curl = curl_init();
switch ($method){
case "POST":
curl_setopt($curl, CURLOPT_POST, 1);
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
case "PUT":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
break;
case "DELETE":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
break;
default:
if ($data)
$url = sprintf("%s?%s", $url, http_build_query($data));
}
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_COOKIESESSION, TRUE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
if (!strpos($this->endpoint, "dev")) {
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Accept: application/json',
'Authorization: Bearer ' . $this->api_key
));
}
$result = curl_exec($curl);
if (!curl_errno($curl)) {
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if (!in_array($http_code, [200, 201]))
return (object) ['status' => 'KO', 'code' => 500, 'message' => 'Connection to API failed - Code HTTP : '. $http_code];
} else {
return (object) ['status' => 'KO', 'code' => 500, 'message' => 'Connection to API failed : '. curl_error($curl)];
}
curl_close($curl);
return json_decode($result);
}
}

View file

@ -11,6 +11,7 @@
"php": "^7.3", "php": "^7.3",
"ext-curl": "*", "ext-curl": "*",
"ext-json": "*", "ext-json": "*",
"arondeparon/laravel-request-sanitizer": "^5.0",
"fideloper/proxy": "^4.2", "fideloper/proxy": "^4.2",
"fruitcake/laravel-cors": "^2.0", "fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1", "guzzlehttp/guzzle": "^7.0.1",
@ -19,7 +20,8 @@
"kwaadpepper/serial-int-caster": "^1.0", "kwaadpepper/serial-int-caster": "^1.0",
"laravel/framework": "^8.0", "laravel/framework": "^8.0",
"laravel/tinker": "^2.0", "laravel/tinker": "^2.0",
"laravel/ui": "^3.0" "laravel/ui": "^3.0",
"ldc/ldccrmv2client": "^3.0"
}, },
"require-dev": { "require-dev": {
"doctrine/dbal": "^2.0", "doctrine/dbal": "^2.0",
@ -39,6 +41,13 @@
"dealerdirect/phpcodesniffer-composer-installer": true "dealerdirect/phpcodesniffer-composer-installer": true
} }
}, },
"repositories": [
{
"name": "ldc/ldccrmv2client",
"type": "vcs",
"url": "https://voight001.lesidc.com/crm-client"
}
],
"extra": { "extra": {
"laravel": { "laravel": {
"dont-discover": [] "dont-discover": []

241
composer.lock generated
View file

@ -4,8 +4,71 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "7b08999e5a20a4f175350f32648b750e", "content-hash": "e302257a30144196d93a920095284dc8",
"packages": [ "packages": [
{
"name": "arondeparon/laravel-request-sanitizer",
"version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/ArondeParon/laravel-request-sanitizer.git",
"reference": "3b5a29d3ee8e1e12b07f32d1e10afb2d1fada3d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ArondeParon/laravel-request-sanitizer/zipball/3b5a29d3ee8e1e12b07f32d1e10afb2d1fada3d8",
"reference": "3b5a29d3ee8e1e12b07f32d1e10afb2d1fada3d8",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0",
"symfony/http-foundation": "^4.3.4|>=5.1.3|^6.0"
},
"require-dev": {
"mockery/mockery": "^1.4",
"orchestra/testbench": "^5.0|^6.0|^7.0",
"phpunit/phpunit": "^8.0 || ^9.0"
},
"type": "library",
"autoload": {
"psr-4": {
"ArondeParon\\RequestSanitizer\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Aron Rotteveel",
"email": "hi@aron.codes",
"homepage": "https://github.com/arondeparon",
"role": "Developer"
}
],
"description": "An easy to use request sanitizer that allows you to sanitize your form data before validating it.",
"homepage": "https://github.com/arondeparon/laravel-request-sanitizer",
"keywords": [
"arondeparon",
"form",
"laravel",
"request",
"sanitizer",
"validation"
],
"support": {
"issues": "https://github.com/ArondeParon/laravel-request-sanitizer/issues",
"source": "https://github.com/ArondeParon/laravel-request-sanitizer/tree/5.0.0"
},
"funding": [
{
"url": "https://github.com/arondeparon",
"type": "github"
}
],
"time": "2022-02-28T08:23:21+00:00"
},
{ {
"name": "asm89/stack-cors", "name": "asm89/stack-cors",
"version": "v2.1.1", "version": "v2.1.1",
@ -1466,6 +1529,58 @@
}, },
"time": "2022-02-21T14:59:16+00:00" "time": "2022-02-21T14:59:16+00:00"
}, },
{
"name": "ldc/ldccrmv2client",
"version": "3.0.1",
"source": {
"type": "git",
"url": "https://voight001.lesidc.com/crm-client",
"reference": "01be799d20268b8f91356ca8ef5d664ff090ced0"
},
"require": {
"ext-curl": "^7.3",
"guzzlehttp/guzzle": "^7.4",
"kwaadpepper/enum": "^2.1",
"php": "^7.3",
"respect/validation": "^2.2"
},
"require-dev": {
"orchestra/testbench": "^6.13",
"phpunit/phpunit": "~9.0",
"slevomat/coding-standard": "^7.0",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
"autoload": {
"psr-4": {
"LDC\\LDCCRM\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LDC\\LDCCRM\\Tests\\": "tests"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Jérémy Munsch",
"email": "jeremy.munsch@ldc.fr",
"homepage": "https://jeremydev.ovh"
}
],
"description": "LDC CRM Client V2",
"homepage": "https://github.com/kwaadpepper",
"keywords": [
"CRM",
"Client",
"LDC",
"Laravel"
],
"time": "2022-02-11T13:57:22+00:00"
},
{ {
"name": "league/commonmark", "name": "league/commonmark",
"version": "1.6.7", "version": "1.6.7",
@ -2754,6 +2869,130 @@
], ],
"time": "2021-09-25T23:10:38+00:00" "time": "2021-09-25T23:10:38+00:00"
}, },
{
"name": "respect/stringifier",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/Respect/Stringifier.git",
"reference": "e55af3c8aeaeaa2abb5fa47a58a8e9688cc23b59"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Respect/Stringifier/zipball/e55af3c8aeaeaa2abb5fa47a58a8e9688cc23b59",
"reference": "e55af3c8aeaeaa2abb5fa47a58a8e9688cc23b59",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.8",
"malukenho/docheader": "^0.1.7",
"phpunit/phpunit": "^6.4"
},
"type": "library",
"autoload": {
"files": [
"src/stringify.php"
],
"psr-4": {
"Respect\\Stringifier\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Respect/Stringifier Contributors",
"homepage": "https://github.com/Respect/Stringifier/graphs/contributors"
}
],
"description": "Converts any value to a string",
"homepage": "http://respect.github.io/Stringifier/",
"keywords": [
"respect",
"stringifier",
"stringify"
],
"support": {
"issues": "https://github.com/Respect/Stringifier/issues",
"source": "https://github.com/Respect/Stringifier/tree/0.2.0"
},
"time": "2017-12-29T19:39:25+00:00"
},
{
"name": "respect/validation",
"version": "2.2.3",
"source": {
"type": "git",
"url": "https://github.com/Respect/Validation.git",
"reference": "4c21a7ffc9a4915673cb2c2843963919e664e627"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Respect/Validation/zipball/4c21a7ffc9a4915673cb2c2843963919e664e627",
"reference": "4c21a7ffc9a4915673cb2c2843963919e664e627",
"shasum": ""
},
"require": {
"php": "^7.3 || ^8.0",
"respect/stringifier": "^0.2.0",
"symfony/polyfill-mbstring": "^1.2"
},
"require-dev": {
"egulias/email-validator": "^3.0",
"malukenho/docheader": "^0.1",
"mikey179/vfsstream": "^1.6",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-deprecation-rules": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^9.3",
"psr/http-message": "^1.0",
"respect/coding-standard": "^3.0",
"squizlabs/php_codesniffer": "^3.5",
"symfony/validator": "^3.0||^4.0",
"zendframework/zend-validator": "^2.1"
},
"suggest": {
"egulias/email-validator": "Strict (RFC compliant) email validation",
"ext-bcmath": "Arbitrary Precision Mathematics",
"ext-fileinfo": "File Information",
"ext-mbstring": "Multibyte String Functions",
"symfony/validator": "Use Symfony validator through Respect\\Validation",
"zendframework/zend-validator": "Use Zend Framework validator through Respect\\Validation"
},
"type": "library",
"autoload": {
"psr-4": {
"Respect\\Validation\\": "library/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Respect/Validation Contributors",
"homepage": "https://github.com/Respect/Validation/graphs/contributors"
}
],
"description": "The most awesome validation engine ever created for PHP",
"homepage": "http://respect.github.io/Validation/",
"keywords": [
"respect",
"validation",
"validator"
],
"support": {
"issues": "https://github.com/Respect/Validation/issues",
"source": "https://github.com/Respect/Validation/tree/2.2.3"
},
"time": "2021-03-19T14:12:45+00:00"
},
{ {
"name": "swiftmailer/swiftmailer", "name": "swiftmailer/swiftmailer",
"version": "v6.3.0", "version": "v6.3.0",

View file

@ -174,6 +174,7 @@ return [
// App\Providers\BroadcastServiceProvider::class, // App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class, App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class, App\Providers\RouteServiceProvider::class,
App\Providers\CrmApiServiceProvider::class,
], ],
@ -227,6 +228,8 @@ return [
'Validator' => Illuminate\Support\Facades\Validator::class, 'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class, 'View' => Illuminate\Support\Facades\View::class,
// * Custom class load
'Country' => LDC\LDCCRM\Enums\Country::class
], ],
]; ];

View file

@ -3,4 +3,5 @@
return [ return [
'endpoint' => env('CRM_ENDPOINT'), 'endpoint' => env('CRM_ENDPOINT'),
'token' => env('CRM_TOKEN'), 'token' => env('CRM_TOKEN'),
'password' => env('CRM_PASSWORD'),
]; ];

View file

@ -12,6 +12,6 @@ return [
* so you can receive email if things go mad * so you can receive email if things go mad
*/ */
'contactsList' => [ 'contactsList' => [
env('MAIL_LIST_SERVICEWEB', 'equipe.web@ldc.fr') env('MAIL_ADMIN', 'equipe.web@ldc.fr')
] ]
]; ];

View file

@ -15,7 +15,7 @@ return [
'default' => env('MAIL_MAILER', 'smtp'), 'default' => env('MAIL_MAILER', 'smtp'),
// Mail admin pour l'envoi de mail comme la fin de la génération des codes uniques // ! Mail admin pour l'envoi de mail comme la fin de la génération des codes uniques
'MAIL_ADMIN' => env('MAIL_ADMIN'), 'MAIL_ADMIN' => env('MAIL_ADMIN'),
'contactsList' => [ 'contactsList' => [

View file

@ -15,21 +15,10 @@ class CreateCustomersTable extends Migration
{ {
Schema::create('customers', function (Blueprint $table) { Schema::create('customers', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('firstname'); $table->string('hashcode')->unique();
$table->string('lastname');
$table->date('birth_date')->nullable();
$table->string('email')->unique(); $table->string('email')->unique();
$table->string('password');
$table->string('address')->nullable();
$table->string('address2')->nullable();
$table->string('town')->nullable();
$table->string('postal_code')->nullable();
$table->string('country')->nullable();
$table->string('phone')->nullable();
$table->string('email_verify_token')->nullable(); $table->string('email_verify_token')->nullable();
$table->boolean('email_verified')->default(0);
$table->string('password_token')->nullable(); $table->string('password_token')->nullable();
$table->integer('crm_id')->nullable();
$table->rememberToken(); $table->rememberToken();
$table->timestamps(); $table->timestamps();
}); });

View file

@ -18,11 +18,8 @@ class CreatePrizes extends Migration
$table->string("label_one"); $table->string("label_one");
$table->string("label_many"); $table->string("label_many");
$table->integer("quantity"); $table->integer("quantity");
$table->integer("arcadia_operation_code")->default(0);
$table->integer("arcadia_support_code")->default(0);
$table->string("pdf_winning_proof")->nullable(); $table->string("pdf_winning_proof")->nullable();
$table->boolean("need_proof")->default(false); $table->boolean("need_proof")->default(false);
$table->unsignedBigInteger("arcadia_id");
$table->foreignId("gain_view_id")->constrained("gain_views"); $table->foreignId("gain_view_id")->constrained("gain_views");
$table->timestamps(); $table->timestamps();
}); });

View file

@ -16,7 +16,10 @@ class CreateInstantWins extends Migration
Schema::create('instant_wins', function (Blueprint $table) { Schema::create('instant_wins', function (Blueprint $table) {
$table->id(); $table->id();
$table->dateTime('appear_date'); $table->dateTime('appear_date');
$table->boolean('won')->default(0); $table->boolean('done')->default(false)
->comment('Permet de dire si l\'instant gagnant à été traité');
$table->string('comment')->default('')
->comment('Commentaire libre à propos de l\'instant gagnant');
$table->foreignId('prize_id')->constrained('prizes'); $table->foreignId('prize_id')->constrained('prizes');
$table->foreignId('participation_id')->nullable() $table->foreignId('participation_id')->nullable()
->constrained('participations')->unique(); ->constrained('participations')->unique();

View file

@ -21,7 +21,6 @@ class PrizeSeeder extends Seeder
$gainview->save(); $gainview->save();
$prize = new Prize(); $prize = new Prize();
$prize->arcadia_id = 0;
$prize->label_one = 'Lot 1'; $prize->label_one = 'Lot 1';
$prize->label_many = 'Lots 1'; $prize->label_many = 'Lots 1';
$prize->quantity = 1; $prize->quantity = 1;
@ -34,7 +33,6 @@ class PrizeSeeder extends Seeder
$gainview->save(); $gainview->save();
$prize = new Prize(); $prize = new Prize();
$prize->arcadia_id = 1;
$prize->label_one = 'Lot '; $prize->label_one = 'Lot ';
$prize->label_many = 'Lots 2'; $prize->label_many = 'Lots 2';
$prize->quantity = 2; $prize->quantity = 2;

View file

@ -34,6 +34,7 @@
"jquery": "^3.5.1", "jquery": "^3.5.1",
"popper.js": "^1.16.1", "popper.js": "^1.16.1",
"scratchcard-js": "^1.4.10", "scratchcard-js": "^1.4.10",
"sweetalert2": "^11.4.5",
"swiper": "^6.6.1", "swiper": "^6.6.1",
"v-clipboard": "^2.2.3" "v-clipboard": "^2.2.3"
} }

10941
public/css/app.css vendored

File diff suppressed because one or more lines are too long

103205
public/js/app.js vendored

File diff suppressed because one or more lines are too long

17
resources/js/app.js vendored
View file

@ -7,11 +7,27 @@
require('./bootstrap'); require('./bootstrap');
require('@fancyapps/fancybox'); require('@fancyapps/fancybox');
import Swal from 'sweetalert2';
// bootstrap styling
window.Swal = Swal.mixin({
customClass: {
confirmButton: 'btn btn-lg btn-success ml-3 mr-3',
cancelButton: 'btn btn-lg btn-danger ml-3 mr-3'
},
buttonsStyling: false
})
window.Vue = require('vue').default; window.Vue = require('vue').default;
import Clipboard from 'v-clipboard'; import Clipboard from 'v-clipboard';
import Chart from 'chart.js'; import Chart from 'chart.js';
if (window.vueDebug) {
Vue.config.devtools = true;
Vue.config.debug = true;
}
Vue.use(Clipboard); Vue.use(Clipboard);
/** /**
@ -25,6 +41,7 @@ Vue.use(Clipboard);
// const files = require.context('./', true, /\.vue$/i) // const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default)) // files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
Vue.component('win-list', require('./components/WinList.vue').default);
Vue.component('win-notification', require('./components/WinNotification.vue').default); Vue.component('win-notification', require('./components/WinNotification.vue').default);
Vue.component('gain-views', require('./components/GainViews.vue').default); Vue.component('gain-views', require('./components/GainViews.vue').default);
Vue.component('prizes', require('./components/Prizes.vue').default); Vue.component('prizes', require('./components/Prizes.vue').default);

View file

@ -114,7 +114,10 @@
this.setPages(); this.setPages();
this.page = this.pages.length; this.page = this.pages.length;
} else { } else {
window.alert("L'IP entrée est déjà dans la liste."); Swal.fire({
text: 'L\'IP entrée est déjà dans la liste.',
icon: 'error'
})
} }
}, },
// Supprime une ligne dans la base si elle existait déjà // Supprime une ligne dans la base si elle existait déjà
@ -157,7 +160,9 @@
self.processing = false; self.processing = false;
let messages = Object.values(error?.response?.data?.errors ?? {}) let messages = Object.values(error?.response?.data?.errors ?? {})
if(Array.isArray(messages)) { if(Array.isArray(messages)) {
alert(messages.join(',')) Swal.fire({
text: messages.join(',')
})
} }
}); });
}, },

View file

@ -116,7 +116,10 @@
this.setPages(); this.setPages();
this.page = this.pages.length; this.page = this.pages.length;
} else { } else {
window.alert('Le code entré existe déjà !'); Swal.fire({
text: 'Le code entré existe déjà !',
icon: 'error'
})
} }
}, },
// Supprime une ligne dans la base si elle existait déjà // Supprime une ligne dans la base si elle existait déjà

View file

@ -26,16 +26,9 @@
<!-- TODO : Mettre chaque lot en onglet --> <!-- TODO : Mettre chaque lot en onglet -->
<div class="card-body"> <div class="card-body">
<div class="col-md-10 offset-md-1"> <div class="col-md-10 offset-md-1">
<div v-for="(item, index) in datas"> <div v-for="(item, index) in datas" :key="index">
<table class="table table-bordered"> <table class="table table-bordered">
<tbody> <tbody>
<tr>
<td class="w-50">
ID du lot <span class="required-asterisk">*</span><br/>
<small class="text-muted">ATTENTION ! Bien vérifier que chaque id de lot est unique et correspond bien aux id de la table des IG</small>
</td>
<td class="w-50 align-middle"><input class="form-control form-control-sm" v-model="item.arcadia_id" type="number" required></td>
</tr>
<tr> <tr>
<td> <td>
Libellé au singulier <span class="required-asterisk">*</span> Libellé au singulier <span class="required-asterisk">*</span>
@ -54,20 +47,6 @@
</td> </td>
<td class="align-middle"><input class="form-control form-control-sm" v-model="item.quantity" type="number" required></td> <td class="align-middle"><input class="form-control form-control-sm" v-model="item.quantity" type="number" required></td>
</tr> </tr>
<tr>
<td>
Code Opération Arcadia <span class="required-asterisk">*</span><br/>
<small class="text-muted">Si ce champ est renseigné, un courrier sera créé en CRM pour l'export Arcadia</small>
</td>
<td class="align-middle"><input class="form-control form-control-sm" v-model="item.arcadia_operation_code" type="number" required></td>
</tr>
<tr>
<td>
Code Support Arcadia <span class="required-asterisk">*</span><br/>
<small class="text-muted">Si ce champ est renseigné, un courrier sera créé en CRM pour l'export Arcadia</small>
</td>
<td class="align-middle"><input class="form-control form-control-sm" v-model="item.arcadia_support_code" type="number" required></td>
</tr>
<tr> <tr>
<td> <td>
Pdf preuve de gain Pdf preuve de gain
@ -157,27 +136,30 @@
if (!this.pdf_winning_proof[index]) { if (!this.pdf_winning_proof[index]) {
event.preventDefault(); event.preventDefault();
alert('Aucun fichier choisi.'); Swal.fire({
timer: 2500,
title: 'Aucun fichier choisi.',
})
return; return;
} }
if (this.pdf_winning_proof[index].size > (1024 * 1024) * 20) { if (this.pdf_winning_proof[index].size > (1024 * 1024) * 20) {
event.preventDefault(); event.preventDefault();
alert('Fichier trop volumineux (> 20MB)'); Swal.fire({
timer: 2500,
text: 'Fichier trop volumineux (> 20MB)'
})
return; return;
} }
}, },
newItem() { newItem() {
this.datas.push({ this.datas.push({
id: null, id: null,
arcadia_id: null,
label_one: '', label_one: '',
label_many: '', label_many: '',
quantity: 0, quantity: 0,
notifications: 0, notifications: 0,
additional_form: 0, additional_form: 0,
arcadia_operation_code: null,
arcadia_support_code: null,
pdf_winning_proof: null, pdf_winning_proof: null,
need_proof: 1, need_proof: 1,
gain_view_id: null gain_view_id: null

View file

@ -0,0 +1,158 @@
<template>
<div class="row">
<div class="col-12">
<table class="table border">
<thead class="thead-light">
<th scope="col">Date participation</th>
<th scope="col">Lot</th>
<th scope="col">Email</th>
<th v-if="settings.use_ean_codes" scope="col">Code EAN</th>
<th scope="col">Code unique</th>
<th v-if="settings.winning_proof" scope="col">Sticker</th>
<th v-if="settings.winning_proof" scope="col">Code barre</th>
<th v-if="settings.winning_proof" scope="col">Ticket</th>
<th scope="col">Traité</th>
<th scope="col">Commentaire</th>
<th scope="col" colspan="2"></th>
</thead>
<tbody>
<tr v-for="(participation, index) in participations" :key="participation.id">
<td>{{ participation.created }}</td>
<td>{{ participation.instant_win.prize.label_one}}</td>
<td>{{ participation.customer.email }}</td>
<td v-if="settings.use_ean_codes">{{ participation.code_ean.code }}</td>
<td>{{ participation.code.code }}</td>
<td v-if="settings.winning_proof" class="text-center">
<a v-if="participation.sticker" :href="'/fichiers/preuve-de-gain/' + participation.id +'/'+participation.sticker" class="btn btn-success btn-sm" target="_blank">Voir</a>
<span v-if="!participation.sticker">-</span>
</td>
<td v-if="settings.winning_proof" class="text-center">
<a v-if="participation.barcode !== null" :href="'/fichiers/preuve-de-gain/' + participation.id +'/'+ participation.barcode" class="btn btn-success btn-sm" target="_blank">Voir</a>
<span v-if="participation.barcode === null">-</span>
</td>
<td v-if="settings.winning_proof" class="text-center">
<a v-if="participation.ticket !== null" :href="'/fichiers/preuve-de-gain/' + participation.id +'/'+ participation.ticket" class="btn btn-success btn-sm" target="_blank">Voir</a>
<span v-if="participation.ticket === null">-</span>
</td>
<td><input type="checkbox" @change="updateComment($event, index, 0, participation)" :checked="participation.instant_win.done"></td>
<td><input type="text" @input="updateComment($event, index, 1, participation)" :value="participation.instant_win.comment"></td>
<td><button class="btn btn-sm btn-warning" v-on:click.prevent="showCustomerInfo(participation)">Infos</button></td>
<td><button class="btn btn-sm btn-primary" v-on:click.prevent="updateInstantWinInfo(index, participation)" :disabled="!participation.updated">Enregister</button></td>
</tr>
</tbody>
</table>
<div id="winListCustomerInfo" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Gagnant {{ customerInfo.firstname }} {{ customerInfo.lastname }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<table class="table border">
<tbody>
<tr><td>Hashcode</td><td>{{ customerInfo.hashcode }}</td></tr>
<tr><td>E-mail</td><td>{{ customerInfo.email }}</td></tr>
<tr><td>Nom</td><td>{{ customerInfo.lastname }}</td></tr>
<tr><td>Prénom</td><td>{{ customerInfo.firstname }}</td></tr>
<tr><td>Date de naissance</td><td>{{ customerInfo.birth_date }}</td></tr>
<tr><td>Téléphone</td><td>{{ customerInfo.phone }}</td></tr>
<tr><td>Adresse</td><td>{{ customerInfo.address }}</td></tr>
<tr><td>Adresse (complément)</td><td>{{ customerInfo.address2 }}</td></tr>
<tr><td>Code postal</td><td>{{ customerInfo.postcode }}</td></tr>
<tr><td>Ville</td><td>{{ customerInfo.city }}</td></tr>
<tr><td>Pays</td><td>{{ customerInfo.country }}</td></tr>
<tr><td>Optin</td><td>{{ customerInfo.opt_in ? 'Oui' : 'Non' }}</td></tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Fermer</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
this.participations = JSON.parse(this.dbParticipations)
this.settings = JSON.parse(this.dbSettings)
},
props: [
'dbParticipations',
'dbSettings',
],
data() {
return {
participations: [],
settings: {},
customerInfo : {}
}
},
watch: {
},
methods: {
showCustomerInfo(participation) {
this.$set(this, 'customerInfo', participation.customer.data)
this.$forceUpdate()
$('#winListCustomerInfo').modal('show')
},
updateComment(e, index, type, participation) {
if(!type) {
participation.instant_win.done = (e.target.checked ? true : false)
} else {
participation.instant_win.comment = e.target.value ?? ''
}
let participations = this.participations
participation.updated = true
participations[index] = participation
this.$set(this, 'participations', participations)
this.$forceUpdate()
},
updateInstantWinInfo(index, participation) {
let participations = this.participations
axios.put(__GGW.routes.updateWinInfo.replace('NULL', participation.instant_win.id), {
done: participation.instant_win.done,
comment: participation.instant_win.comment,
}).then((reponse) => {
if(reponse.status != 200) {
Swal.fire({
title: 'Une erreur est survenue',
text: 'Les données n\'ont pas été enregistré veuillez recharger la page.',
icon: 'error'
})
} else {
Swal.fire({
timer: 1500,
title: 'Enregisté',
icon: 'success'
})
}
}).catch((error) => {
let message = 'Les données n\'ont pas été enregistré veuillez recharger la page.'
if(error.response.status == 422) {
message = _.flatten(_.map(error.response.data.errors, (val, key) => {
return '\n' + val.join('\n');
}))
}
Swal.fire({
title: 'Une erreur est survenue',
text: message,
icon: 'error'
})
})
participation.updated = false
participations[index] = participation
this.$set(this, 'participations', participations)
this.$forceUpdate()
}
}
}
</script>

View file

@ -128,6 +128,7 @@ return [
| specify a specific custom language line for a given attribute rule. | specify a specific custom language line for a given attribute rule.
| |
*/ */
'phone' => 'The :attribute field contains an invalid number.',
'custom' => [ 'custom' => [
'attribute-name' => [ 'attribute-name' => [

View file

@ -1,128 +1,128 @@
{ {
"A fresh verification link has been sent to your email address.": "Un nouveau lien de vérification a été envoyé à votre adresse email.", "A fresh verification link has been sent to your email address.": "Un nouveau lien de vérification a été envoyé à votre adresse email.",
"A new verification link has been sent to the email address you provided during registration.": "Un nouveau lien de vérification a été envoyé à l'adresse email que vous avez indiquée lors de votre inscription.", "A new verification link has been sent to the email address you provided during registration.": "Un nouveau lien de vérification a été envoyé à l'adresse email que vous avez indiquée lors de votre inscription.",
"Add a new team member to your team, allowing them to collaborate with you." : "Ajoutez un nouveau membre de l'équipe à votre équipe, permettant de collaborer avec vous.", "Add a new team member to your team, allowing them to collaborate with you.": "Ajoutez un nouveau membre de l'équipe à votre équipe, permettant de collaborer avec vous.",
"Add additional security to your account using two factor authentication." : "Ajoutez une sécurité supplémentaire à votre compte en utilisant l'authentification à deux facteurs.", "Add additional security to your account using two factor authentication.": "Ajoutez une sécurité supplémentaire à votre compte en utilisant l'authentification à deux facteurs.",
"Add Team Member" : "Ajoutez un membre d'équipe", "Add Team Member": "Ajoutez un membre d'équipe",
"Add" : "Ajoutez", "Add": "Ajoutez",
"Added." : "Ajouté", "Added.": "Ajouté",
"Administrator" : "Administrateur", "Administrator": "Administrateur",
"Administrator users can perform any action." : "Les administrateurs peuvent faire n'importe quelle action.", "Administrator users can perform any action.": "Les administrateurs peuvent faire n'importe quelle action.",
"All of the people that are part of this team." : "Toutes les personnes qui font partie de cette équipe.", "All of the people that are part of this team.": "Toutes les personnes qui font partie de cette équipe.",
"All rights reserved.": "Tous droits réservés.", "All rights reserved.": "Tous droits réservés.",
"Already registered?": "Déjà inscrit(e) ?", "Already registered?": "Déjà inscrit(e) ?",
"API Token Permissions" : "Autorisations de jeton API", "API Token Permissions": "Autorisations de jeton API",
"API Token" : "Jeton API", "API Token": "Jeton API",
"API tokens allow third-party services to authenticate with our application on your behalf." : "Les jetons API permettent à des services tiers de s'authentifier auprès de notre application en votre nom.", "API tokens allow third-party services to authenticate with our application on your behalf.": "Les jetons API permettent à des services tiers de s'authentifier auprès de notre application en votre nom.",
"API Tokens" : "Jeton API", "API Tokens": "Jeton API",
"Are you sure you want to delete this team? Once a team is deleted, all of its resources and data will be permanently deleted." : "Êtes-vous sûr de vouloir supprimer cette équipe ? Lorsqu'une équipe est supprimée, toutes les ressources et données associées seront supprimées de manière définitive.", "Are you sure you want to delete this team? Once a team is deleted, all of its resources and data will be permanently deleted.": "Êtes-vous sûr de vouloir supprimer cette équipe ? Lorsqu'une équipe est supprimée, toutes les ressources et données associées seront supprimées de manière définitive.",
"Are you sure you want to delete your account? Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account." : "Êtes-vous sûr de vouloir supprimer votre compte ? Une fois que votre compte est supprimé, toutes les données associées seront supprimées définitivement. Pour confirmer que vous voulez supprimer définitivement votre compte, renseignez votre mot de passe.", "Are you sure you want to delete your account? Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.": "Êtes-vous sûr de vouloir supprimer votre compte ? Une fois que votre compte est supprimé, toutes les données associées seront supprimées définitivement. Pour confirmer que vous voulez supprimer définitivement votre compte, renseignez votre mot de passe.",
"Are you sure you would like to delete this API token?" : "Êtes-vous sûr de vouloir supprimer ce jeton API ?", "Are you sure you would like to delete this API token?": "Êtes-vous sûr de vouloir supprimer ce jeton API ?",
"Are you sure you would like to leave this team?" : "Êtes-vous sûr de vouloir quitter cette équipe ?", "Are you sure you would like to leave this team?": "Êtes-vous sûr de vouloir quitter cette équipe ?",
"Are you sure you would like to remove this person from the team?" : "Êtes-vous sûr de vouloir supprimer cette personne de cette équipe ?", "Are you sure you would like to remove this person from the team?": "Êtes-vous sûr de vouloir supprimer cette personne de cette équipe ?",
"Before proceeding, please check your email for a verification link.": "Avant de continuer, veuillez vérifier vos emails, vous devriez avoir reçu un lien de vérification.", "Before proceeding, please check your email for a verification link.": "Avant de continuer, veuillez vérifier vos emails, vous devriez avoir reçu un lien de vérification.",
"Browser Sessions" : "Sessions de navigateur", "Browser Sessions": "Sessions de navigateur",
"click here to request another": "cliquez ici pour faire une nouvelle demande", "click here to request another": "cliquez ici pour faire une nouvelle demande",
"Close" : "Fermer", "Close": "Fermer",
"Code" : "Code", "Code": "Code",
"Confirm Password": "Confirmez votre mot de passe", "Confirm Password": "Confirmez votre mot de passe",
"Confirm" : "Confirmer", "Confirm": "Confirmer",
"Create a new team to collaborate with others on projects." : "Créer une nouvelle équipe pour collaborer avec d'autres personnes sur des projets.", "Create a new team to collaborate with others on projects.": "Créer une nouvelle équipe pour collaborer avec d'autres personnes sur des projets.",
"Create API Token" : "Créer un jeton API", "Create API Token": "Créer un jeton API",
"Create New Team" : "Créer une nouvelle équipe", "Create New Team": "Créer une nouvelle équipe",
"Create Team" : "Créer l'équipe", "Create Team": "Créer l'équipe",
"Create" : "Créer", "Create": "Créer",
"Created." : "Créé.", "Created.": "Créé.",
"Current Password" : "Mot de passe actuel", "Current Password": "Mot de passe actuel",
"Dashboard": "Tableau de bord", "Dashboard": "Tableau de bord",
"Delete Account" : "Supprimer le compte", "Delete Account": "Supprimer le compte",
"Delete API Token" : "Supprimer le jeton API", "Delete API Token": "Supprimer le jeton API",
"Delete Team" : "Supprimer l'équipe", "Delete Team": "Supprimer l'équipe",
"Delete" : "Supprimer", "Delete": "Supprimer",
"Disable" : "Désactiver", "Disable": "Désactiver",
"Done." : "Terminé.", "Done.": "Terminé.",
"E-Mail Address": "Adresse email", "E-Mail Address": "Adresse email",
"Editor" : "Editeur", "Editor": "Editeur",
"Editor users have the ability to read, create, and update." : "Les éditeurs peuvent lire, créer et mettre à jour", "Editor users have the ability to read, create, and update.": "Les éditeurs peuvent lire, créer et mettre à jour",
"Email Password Reset Link": "Lien de réinitialisation du mot de passe", "Email Password Reset Link": "Lien de réinitialisation du mot de passe",
"Email": "Email", "Email": "Email",
"Enable" : "Activé", "Enable": "Activé",
"Ensure your account is using a long, random password to stay secure." : "Assurez-vous d'utiliser un mot de passe long et aléatoire pour sécuriser votre compte", "Ensure your account is using a long, random password to stay secure.": "Assurez-vous d'utiliser un mot de passe long et aléatoire pour sécuriser votre compte",
"Error": "Erreur", "Error": "Erreur",
"For your security, please confirm your password to continue." : "Par mesure de sécurité, veuillez confirmer votre mot de passe pour continuer.", "For your security, please confirm your password to continue.": "Par mesure de sécurité, veuillez confirmer votre mot de passe pour continuer.",
"Forbidden": "Interdit", "Forbidden": "Interdit",
"Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.": "Mot de passe oublié ? Pas de soucis. Veuillez nous indiquer votre adresse email et nous vous enverrons un lien de réinitialisation du mot de passe.", "Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.": "Mot de passe oublié ? Pas de soucis. Veuillez nous indiquer votre adresse email et nous vous enverrons un lien de réinitialisation du mot de passe.",
"Forgot your password?": "Vous avez oublié votre mot de passe ?", "Forgot your password?": "Vous avez oublié votre mot de passe ?",
"Forgot Your Password?": "Vous avez oublié votre mot de passe ?", "Forgot Your Password?": "Vous avez oublié votre mot de passe ?",
"Go Home": "Aller à l'accueil", "Go Home": "Aller à l'accueil",
"Go to page :page" : "Aller à la page :page", "Go to page :page": "Aller à la page :page",
"Hello!": "Bonjour !", "Hello!": "Bonjour !",
"hi": "salut", "hi": "salut",
"If necessary, you may logout of all of your other browser sessions across all of your devices. Some of your recent sessions are listed below; however, this list may not be exhaustive. If you feel your account has been compromised, you should also update your password." : "Si nécessaire, vous pouvez vous déconnecter de toutes vos sessions de navigateur de tous vos appareils. Certaines de vos sessions sont listées plus bas ; pourtant, cette liste peut ne pas être exhaustive. Si vous sentez que votre compte a été compromis, vous pouvez aussi mettre à jour votre mot de passe.", "If necessary, you may logout of all of your other browser sessions across all of your devices. Some of your recent sessions are listed below; however, this list may not be exhaustive. If you feel your account has been compromised, you should also update your password.": "Si nécessaire, vous pouvez vous déconnecter de toutes vos sessions de navigateur de tous vos appareils. Certaines de vos sessions sont listées plus bas ; pourtant, cette liste peut ne pas être exhaustive. Si vous sentez que votre compte a été compromis, vous pouvez aussi mettre à jour votre mot de passe.",
"If you did not create an account, no further action is required.": "Si vous n'avez pas créé de compte, vous pouvez ignorer ce message.", "If you did not create an account, no further action is required.": "Si vous n'avez pas créé de compte, vous pouvez ignorer ce message.",
"If you did not receive the email": "Si vous n'avez pas reçu l'email", "If you did not receive the email": "Si vous n'avez pas reçu l'email",
"If you did not request a password reset, no further action is required.": "Si vous n'avez pas demandé de réinitialisation de mot de passe, vous pouvez ignorer ce message.", "If you did not request a password reset, no further action is required.": "Si vous n'avez pas demandé de réinitialisation de mot de passe, vous pouvez ignorer ce message.",
"If you’re having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Si le bouton \":actionText\" ne fonctionne pas, copiez/collez l'adresse ci-dessous dans votre navigateur :\n", "If you’re having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Si le bouton \":actionText\" ne fonctionne pas, copiez/collez l'adresse ci-dessous dans votre navigateur :\n",
"Invalid signature.": "Signature invalide", "Invalid signature.": "Signature invalide",
"Last active" : "Dernier actif", "Last active": "Dernier actif",
"Last used" : "Dernière utilisation", "Last used": "Dernière utilisation",
"Leave Team" : "Quitter l'équipe", "Leave Team": "Quitter l'équipe",
"Leave" : "Quitter", "Leave": "Quitter",
"Login": "Connexion", "Login": "Connexion",
"Logout Other Browser Sessions" : "Déconnecter les sessions ouvertes sur d'autres navigateurs.", "Logout Other Browser Sessions": "Déconnecter les sessions ouvertes sur d'autres navigateurs.",
"Logout": "Déconnexion", "Logout": "Déconnexion",
"Manage Account" : "Gérer le compte", "Manage Account": "Gérer le compte",
"Manage and logout your active sessions on other browsers and devices." : "Gérer et déconnecter vos sessions actives sur les autres navigateurs et appareils.", "Manage and logout your active sessions on other browsers and devices.": "Gérer et déconnecter vos sessions actives sur les autres navigateurs et appareils.",
"Manage API Tokens" : "Gérer les jetons API", "Manage API Tokens": "Gérer les jetons API",
"Manage Role" : "Gérer le rôle", "Manage Role": "Gérer le rôle",
"Manage Team" : "Gérer l'équipe", "Manage Team": "Gérer l'équipe",
"Name": "Nom", "Name": "Nom",
"Nevermind" : "Peu importe", "Nevermind": "Peu importe",
"New Password" : "Nouveau mot de passe", "New Password": "Nouveau mot de passe",
"Not Found": "Non trouvé", "Not Found": "Non trouvé",
"of" : "de", "of": "de",
"Oh no": "Oh non", "Oh no": "Oh non",
"Once a team is deleted, all of its resources and data will be permanently deleted. Before deleting this team, please download any data or information regarding this team that you wish to retain." : "Une fois qu'une équipe est supprimée, toutes ses données seront supprimées définitivement. Avant de supprimer cette équipe, veuillez télécharger toutes données ou informations de cette équipe.", "Once a team is deleted, all of its resources and data will be permanently deleted. Before deleting this team, please download any data or information regarding this team that you wish to retain.": "Une fois qu'une équipe est supprimée, toutes ses données seront supprimées définitivement. Avant de supprimer cette équipe, veuillez télécharger toutes données ou informations de cette équipe.",
"Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain." : "Une fois que votre compte est supprimé, toutes vos données sont supprimées définitivement. Avant de supprimer votre compte, veuillez télécharger vos données.", "Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.": "Une fois que votre compte est supprimé, toutes vos données sont supprimées définitivement. Avant de supprimer votre compte, veuillez télécharger vos données.",
"Page Expired": "Page expirée", "Page Expired": "Page expirée",
"Page Not Found": "Page introuvable", "Page Not Found": "Page introuvable",
"Pagination Navigation": "Pagination", "Pagination Navigation": "Pagination",
"Password": "Mot de passe", "Password": "Mot de passe",
"Permanently delete this team." : "Supprimer définitivement cette team.", "Permanently delete this team.": "Supprimer définitivement cette team.",
"Permanently delete your account." : "Supprimer définitivement ce compte.", "Permanently delete your account.": "Supprimer définitivement ce compte.",
"Permissions" : "Permissions", "Permissions": "Permissions",
"Photo" : "Image", "Photo": "Image",
"Please click the button below to verify your email address.": "Veuillez cliquer sur le bouton ci-dessous pour vérifier votre adresse email :", "Please click the button below to verify your email address.": "Veuillez cliquer sur le bouton ci-dessous pour vérifier votre adresse email :",
"Please confirm access to your account by entering one of your emergency recovery codes.": "Veuillez confirmer l'accès à votre compte en entrant l'un des codes de récupération d'urgence.", "Please confirm access to your account by entering one of your emergency recovery codes.": "Veuillez confirmer l'accès à votre compte en entrant l'un des codes de récupération d'urgence.",
"Please confirm access to your account by entering the authentication code provided by your authenticator application.": "Veuillez confirmer l'accès à votre compte en entrant le code d'authentification fourni par votre application d'authentification.", "Please confirm access to your account by entering the authentication code provided by your authenticator application.": "Veuillez confirmer l'accès à votre compte en entrant le code d'authentification fourni par votre application d'authentification.",
"Please confirm your password before continuing.": "Veuillez confirmer votre mot de passe avant de continuer", "Please confirm your password before continuing.": "Veuillez confirmer votre mot de passe avant de continuer",
"Please copy your new API token. For your security, it won't be shown again." : "Veuillez copier votre nouveau token API. Pour votre sécurité, il ne sera pas ré-affiché.", "Please copy your new API token. For your security, it won't be shown again.": "Veuillez copier votre nouveau token API. Pour votre sécurité, il ne sera pas ré-affiché.",
"Please enter your password to confirm you would like to logout of your other browser sessions across all of your devices." : "Veuillez entrer votre mot de passe pour confirmer que vous voulez déconnecter toutes les autres sessions navigateur sur l'ensemble de vos appareils.", "Please enter your password to confirm you would like to logout of your other browser sessions across all of your devices.": "Veuillez entrer votre mot de passe pour confirmer que vous voulez déconnecter toutes les autres sessions navigateur sur l'ensemble de vos appareils.",
"Please provide the email address of the person you would like to add to this team. The email address must be associated with an existing account." : "Veuillez renseigner l'adresse email de la personne que vous voulez ajouter à cette équipe. L'adresse email doit être associée à un compte existant.", "Please provide the email address of the person you would like to add to this team. The email address must be associated with an existing account.": "Veuillez renseigner l'adresse email de la personne que vous voulez ajouter à cette équipe. L'adresse email doit être associée à un compte existant.",
"Profile Information" : "Information du profil", "Profile Information": "Information du profil",
"Profile" : "Profil", "Profile": "Profil",
"Recovery Code" : "Code de récupération", "Recovery Code": "Code de récupération",
"Regards": "Cordialement", "Regards": "Cordialement",
"Regenerate Recovery Codes" : "Régénérer les codes de récupération", "Regenerate Recovery Codes": "Régénérer les codes de récupération",
"Register": "Inscription", "Register": "Inscription",
"Remember me" : "Se souvenir de moi", "Remember me": "Se souvenir de moi",
"Remember Me": "Se souvenir de moi", "Remember Me": "Se souvenir de moi",
"Remove Photo" : "Supprimer l'image", "Remove Photo": "Supprimer l'image",
"Remove Team Member" : "Supprimer le membre d'équipe", "Remove Team Member": "Supprimer le membre d'équipe",
"Remove" : "Supprimer", "Remove": "Supprimer",
"Resend Verification Email": "Renvoyer l'email de vérification", "Resend Verification Email": "Renvoyer l'email de vérification",
"Reset Password Notification": "Notification de réinitialisation du mot de passe", "Reset Password Notification": "Notification de réinitialisation du mot de passe",
"Reset Password": "Réinitialisation du mot de passe", "Reset Password": "Réinitialisation du mot de passe",
"results" : "résultats", "results": "résultats",
"Role" : "Rôle", "Role": "Rôle",
"Save" : "Sauvegarder", "Save": "Sauvegarder",
"Saved." : "Sauvegardé", "Saved.": "Sauvegardé",
"Select A New Photo" : "Sélectionner une nouvelle image", "Select A New Photo": "Sélectionner une nouvelle image",
"Send Password Reset Link": "Envoyer le lien de réinitialisation du mot de passe", "Send Password Reset Link": "Envoyer le lien de réinitialisation du mot de passe",
"Server Error": "Erreur serveur", "Server Error": "Erreur serveur",
"Service Unavailable": "Service indisponible", "Service Unavailable": "Service indisponible",
"Show Recovery Codes" : "Voir les codes de récupération", "Show Recovery Codes": "Voir les codes de récupération",
"Showing" : "Montrant", "Showing": "Montrant",
"Sorry, the page you are looking for could not be found.": "Désolé, la page que vous recherchez est introuvable.", "Sorry, the page you are looking for could not be found.": "Désolé, la page que vous recherchez est introuvable.",
"Sorry, we are doing some maintenance. Please check back soon.": "Désolé, nous sommes en maintenance. Veuillez revenir plus tard.", "Sorry, we are doing some maintenance. Please check back soon.": "Désolé, nous sommes en maintenance. Veuillez revenir plus tard.",
"Sorry, you are forbidden from accessing this page.": "Désolé, vous ne pouvez accéder à cette page.", "Sorry, you are forbidden from accessing this page.": "Désolé, vous ne pouvez accéder à cette page.",
@ -130,56 +130,74 @@
"Sorry, you are not authorized to access this page.": "Désolé, vous n'êtes pas autorisé à accéder à cette page.", "Sorry, you are not authorized to access this page.": "Désolé, vous n'êtes pas autorisé à accéder à cette page.",
"Sorry, your session has expired. Please refresh and try again.": "Désolé, votre session a expiré. Veuillez actualiser la page et réessayer.", "Sorry, your session has expired. Please refresh and try again.": "Désolé, votre session a expiré. Veuillez actualiser la page et réessayer.",
"Store these recovery codes in a secure password manager. They can be used to recover access to your account if your two factor authentication device is lost.": "Enregistrez ces codes dans un gestionnaire de mot de passe sécurisé. Ils peuvent être réutilisés pour accéder à votre compte si l'authentification à deux facteurs n'abouti pas.", "Store these recovery codes in a secure password manager. They can be used to recover access to your account if your two factor authentication device is lost.": "Enregistrez ces codes dans un gestionnaire de mot de passe sécurisé. Ils peuvent être réutilisés pour accéder à votre compte si l'authentification à deux facteurs n'abouti pas.",
"Switch Teams" : "Permuter les équipes", "Switch Teams": "Permuter les équipes",
"Team Details" : "Détails de l'équipe", "Team Details": "Détails de l'équipe",
"Team Members" : "Membres de l'équipe", "Team Members": "Membres de l'équipe",
"Team Name" : "Nom de l'équipe", "Team Name": "Nom de l'équipe",
"Team Owner" : "Propriétaire de l'équipe", "Team Owner": "Propriétaire de l'équipe",
"Team Settings" : "Préférences de l'équipe", "Team Settings": "Préférences de l'équipe",
"Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn't receive the email, we will gladly send you another.":"Merci de vous être inscrit(e) ! Avant de commencer, veuillez vérifier votre adresse email en cliquant sur le lien que nous venons de vous envoyer. Si vous n'avez pas reçu cet email, nous vous en enverrons un nouveau avec plaisir.", "Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn't receive the email, we will gladly send you another.": "Merci de vous être inscrit(e) ! Avant de commencer, veuillez vérifier votre adresse email en cliquant sur le lien que nous venons de vous envoyer. Si vous n'avez pas reçu cet email, nous vous en enverrons un nouveau avec plaisir.",
"The :attribute must be a valid role.": "Le :attribute doit être un rôle valide.", "The :attribute must be a valid role.": "Le :attribute doit être un rôle valide.",
"The :attribute must be at least :length characters and contain at least one number." : "Le champ :attribute doit avoir au moins :length caractères et contenir au moins un chiffre.", "The :attribute must be at least :length characters and contain at least one number.": "Le champ :attribute doit avoir au moins :length caractères et contenir au moins un chiffre.",
"The :attribute must be at least :length characters and contain at least one special character." : "Le champ :attribute doit avoir au moins :length caractères et contenir au moins un caractère spécial.", "The :attribute must be at least :length characters and contain at least one special character.": "Le champ :attribute doit avoir au moins :length caractères et contenir au moins un caractère spécial.",
"The :attribute must be at least :length characters and contain at least one uppercase character and one number." : "Le champ :attribute doit avoir au moins :length caractères et contenir au moins une majuscule et un chiffre.", "The :attribute must be at least :length characters and contain at least one uppercase character and one number.": "Le champ :attribute doit avoir au moins :length caractères et contenir au moins une majuscule et un chiffre.",
"The :attribute must be at least :length characters and contain at least one uppercase character and one special character." : "Le champ :attribute doit avoir au moins :length caractères et contenir au moins une majuscule et un caractère spécial.", "The :attribute must be at least :length characters and contain at least one uppercase character and one special character.": "Le champ :attribute doit avoir au moins :length caractères et contenir au moins une majuscule et un caractère spécial.",
"The :attribute must be at least :length characters and contain at least one uppercase character, one number, and one special character." : "Le champ :attribute doit avoir au moins :length caractères, et contenir au moins une majuscule, un chiffre et un caractère spécial.", "The :attribute must be at least :length characters and contain at least one uppercase character, one number, and one special character.": "Le champ :attribute doit avoir au moins :length caractères, et contenir au moins une majuscule, un chiffre et un caractère spécial.",
"The :attribute must be at least :length characters and contain at least one uppercase character." : "Le champ :attribute doit avoir au moins :length caractères et au moins une majuscule.", "The :attribute must be at least :length characters and contain at least one uppercase character.": "Le champ :attribute doit avoir au moins :length caractères et au moins une majuscule.",
"The :attribute must be at least :length characters." : "Le champ :attribute doit avoir au moins :length caractères.", "The :attribute must be at least :length characters.": "Le champ :attribute doit avoir au moins :length caractères.",
"The provided password does not match your current password." : "Le mot de passe indiqué ne correspond pas à votre mot de passe actuel.", "The provided password does not match your current password.": "Le mot de passe indiqué ne correspond pas à votre mot de passe actuel.",
"The provided password was incorrect." : "Le mot de passé indiqué est incorrect.", "The provided password was incorrect.": "Le mot de passé indiqué est incorrect.",
"The provided two factor authentication code was invalid." : "Le code d'authentification double facteur fourni est incorrect.", "The provided two factor authentication code was invalid.": "Le code d'authentification double facteur fourni est incorrect.",
"The team's name and owner information." : "Les informations concernant l'équipe et son propriétaire.", "The team's name and owner information.": "Les informations concernant l'équipe et son propriétaire.",
"This action is unauthorized.": "Cette action n'est pas autorisée.", "This action is unauthorized.": "Cette action n'est pas autorisée.",
"This device" : "Cet appareil", "This device": "Cet appareil",
"This password does not match our records.": "Ce mot de passe ne correspond pas à nos enregistrements.", "This password does not match our records.": "Ce mot de passe ne correspond pas à nos enregistrements.",
"This password reset link will expire in :count minutes.": "Ce lien de réinitialisation du mot de passe expirera dans :count minutes.", "This password reset link will expire in :count minutes.": "Ce lien de réinitialisation du mot de passe expirera dans :count minutes.",
"This user already belongs to the team.": "Cet utilisateur appartient déjà à l'équipe.", "This user already belongs to the team.": "Cet utilisateur appartient déjà à l'équipe.",
"to" : "à", "to": "à",
"Toggle navigation": "Basculer la navigation", "Toggle navigation": "Basculer la navigation",
"Token Name" : "Nom du jeton", "Token Name": "Nom du jeton",
"Too Many Attempts.": "Trop de tentatives.", "Too Many Attempts.": "Trop de tentatives.",
"Too Many Requests": "Trop de requêtes", "Too Many Requests": "Trop de requêtes",
"Two factor authentication is now enabled. Scan the following QR code using your phone's authenticator application.": "L'authentification à deux facteurs est maintenant activée. Enregistrez ce QR code dans votre application d'authentification.", "Two factor authentication is now enabled. Scan the following QR code using your phone's authenticator application.": "L'authentification à deux facteurs est maintenant activée. Enregistrez ce QR code dans votre application d'authentification.",
"Two Factor Authentication" : "Double authentification", "Two Factor Authentication": "Double authentification",
"Unauthorized": "Non autorisé", "Unauthorized": "Non autorisé",
"Update Password" : "Mettre à jour le mot de passe", "Update Password": "Mettre à jour le mot de passe",
"Update your account's profile information and email address." : "Modifier le profil associé à votre compte ainsi que votre adresse email.", "Update your account's profile information and email address.": "Modifier le profil associé à votre compte ainsi que votre adresse email.",
"Use a recovery code": "Utilisez un code de récupération", "Use a recovery code": "Utilisez un code de récupération",
"Use an authentication code": "Utilisez un code d'authentification", "Use an authentication code": "Utilisez un code d'authentification",
"Verify Email Address": "Vérification de l'adresse email", "Verify Email Address": "Vérification de l'adresse email",
"Verify Your Email Address": "Vérifiez votre adresse email", "Verify Your Email Address": "Vérifiez votre adresse email",
"We were unable to find a registered user with this email address.": "Nous n'avons pas pu trouver un utilisateur enregistré avec cette adresse e-mail.", "We were unable to find a registered user with this email address.": "Nous n'avons pas pu trouver un utilisateur enregistré avec cette adresse e-mail.",
"We won't ask for your password again for a few hours.": "Nous ne vous demanderons plus votre mot de passe pour quelques heures", "We won't ask for your password again for a few hours.": "Nous ne vous demanderons plus votre mot de passe pour quelques heures",
"When two factor authentication is enabled, you will be prompted for a secure, random token during authentication. You may retrieve this token from your phone's Google Authenticator application." : "Lorsque l'authentification à deux facteurs est activée, vous serez invité à saisir un jeton aléatoire sécurisé lors de l'authentification. Vous pouvez récupérer ce jeton depuis l'application Google Authenticator de votre téléphone.", "When two factor authentication is enabled, you will be prompted for a secure, random token during authentication. You may retrieve this token from your phone's Google Authenticator application.": "Lorsque l'authentification à deux facteurs est activée, vous serez invité à saisir un jeton aléatoire sécurisé lors de l'authentification. Vous pouvez récupérer ce jeton depuis l'application Google Authenticator de votre téléphone.",
"Whoops! Something went wrong." : "Oups ! Un problème est survenu.", "Whoops! Something went wrong.": "Oups ! Un problème est survenu.",
"Whoops!": "Oups !", "Whoops!": "Oups !",
"Whoops, something went wrong on our servers.": "Oups, une erreur s'est produite sur nos serveurs.", "Whoops, something went wrong on our servers.": "Oups, une erreur s'est produite sur nos serveurs.",
"You are logged in!": "Vous êtes connecté !", "You are logged in!": "Vous êtes connecté !",
"You are receiving this email because we received a password reset request for your account.": "Vous recevez cet email car nous avons reçu une demande de réinitialisation de mot de passe pour votre compte.", "You are receiving this email because we received a password reset request for your account.": "Vous recevez cet email car nous avons reçu une demande de réinitialisation de mot de passe pour votre compte.",
"You have enabled two factor authentication." : "Vous avez activé la double authentification.", "You have enabled two factor authentication.": "Vous avez activé la double authentification.",
"You have not enabled two factor authentication." : "Vous n'avez pas activé la double authentification.", "You have not enabled two factor authentication.": "Vous n'avez pas activé la double authentification.",
"You may delete any of your existing tokens if they are no longer needed." : "Vous pouvez supprimer n'importe lequel de vos jetons existants s'ils ne sont plus nécessaires.", "You may delete any of your existing tokens if they are no longer needed.": "Vous pouvez supprimer n'importe lequel de vos jetons existants s'ils ne sont plus nécessaires.",
"You may not delete your personal team.": "Vous ne pouvez pas supprimer votre équipe personnelle.", "You may not delete your personal team.": "Vous ne pouvez pas supprimer votre équipe personnelle.",
"You may not leave a team that you created.": "Vous ne pouvez pas quitter une équipe que vous avez créée.", "You may not leave a team that you created.": "Vous ne pouvez pas quitter une équipe que vous avez créée.",
"Your email address is not verified.": "Votre adresse email n'a pas été vérifiée." "Your email address is not verified.": "Votre adresse email n'a pas été vérifiée.",
"firstname": "Prénom",
"address": "Adresse",
"email": "E-mail",
"postcode": "Code postal",
"town": "Ville",
"phone": "Téléphone",
"The :attribute must contain at least one uppercase and one lowercase letter.": ":attribute doit contenir au moins une lettre majuscule et une lettre minuscule.",
"The :attribute must contain at least one letter.": ":attribute doit contenir au moins une lettre.",
"The :attribute must contain at least one symbol.": ":attribute doit contenir au moins un caractère spécial.",
"The :attribute must contain at least one number.": ":attribute doit contenir au moins un nombre.",
"The given :attribute has appeared in a data leak. Please choose a different :attribute.": ":attribute apparait dans une fuite de données sur le web. Merci de choisir un :attribute différent.",
"Belgium": "Belgique",
"French Guiana": "Guyane Française",
"Saint Pierre and Miquelon": "Saint Pierre et Miquelon",
"Saint Martin (French part)": "Saint Martin",
"Wallis and Futuna": "Wallis et Futuna",
"French Polynesia": "Polynésie Française",
"New Caledonia": "Nouvelle Calédonie"
} }

View file

@ -13,5 +13,6 @@ return [
*/ */
'failed' => 'Ces identifiants ne correspondent pas à nos enregistrements', 'failed' => 'Ces identifiants ne correspondent pas à nos enregistrements',
'password' => 'Le mot de passe fourni est incorrect.',
'throttle' => 'Tentatives de connexion trop nombreuses. Veuillez essayer de nouveau dans :seconds secondes.', 'throttle' => 'Tentatives de connexion trop nombreuses. Veuillez essayer de nouveau dans :seconds secondes.',
]; ];

View file

@ -129,6 +129,8 @@ return [
| |
*/ */
'phone' => 'Le champ :attribute n\'est pas un numéro de téléphone valide.',
'custom' => [ 'custom' => [
'attribute-name' => [ 'attribute-name' => [
'rule-name' => 'custom-message', 'rule-name' => 'custom-message',
@ -176,6 +178,11 @@ return [
'time' => 'heure', 'time' => 'heure',
'available' => 'disponible', 'available' => 'disponible',
'size' => 'taille', 'size' => 'taille',
'birth_date' => 'date de naissance', 'answers' => 'réponses',
'answers.*' => 'réponse',
'postal_code' => 'code postal',
'postcode' => 'code postal',
'picture' => 'image',
'breeder_code' => 'code éleveur'
], ],
]; ];

View file

@ -1,31 +0,0 @@
@extends('layouts.bo')
@section('content')
<div class="card">
<div class="card-header">
Envoyer le courrier à Arcadia pour {{ $participation->customer->lastname }} {{ $participation->customer->firstname }}
<a href="{{ route('bo.winners-list') }}" class="btn btn-sm btn-primary float-right">Retour</a>
</div>
<div class="card-body">
<form method="POST" action="{{ route('bo.courrier-arcadia', $crmId) }}">
@csrf
<div class="form-row">
<div class="col">
ID CRM de l'utilisateur : <b>{{ $crmId }}</b>
<input type="hidden" name="crm_id" value="{{ $crmId }}">
</div>
</div>
<div class="form-group">
<label class="col-form-label">Corps du courrier :</label>
<textarea class="form-control" rows="20" spellcheck="false" name="corps" disabled>{{ $corps }}</textarea>
</div>
<label>
<input type="checkbox" name="confirm" required>
Confirmer l'envoi du courrier
</label>
<input type="submit" class="btn btn-sm btn-success float-right" value="Envoyer le courrier">
</form>
</div>
</div>
@endsection

View file

@ -7,54 +7,21 @@
</div> </div>
<div class="card-body"> <div class="card-body">
<table class="table"> <win-list
<thead class="thead-light"> db-participations='@json($participations)'
<th scope="col">Date participation</th> db-settings='@json($settings)'></win-list>
<th scope="col">Lot</th>
<th scope="col">Email</th>
@if ($settings->use_ean_codes)
<th scope="col">Code EAN</th>
@endif
<th scope="col">Code unique</th>
@if ($settings->winning_proof === 1)
<th scope="col">Sticker</th>
<th scope="col">Code barre</th>
<th scope="col">Ticket</th>
@endif
<th scope="col">Arcadia</th>
</thead>
<tbody>
@foreach($winnersList as $participation)
<tr>
<td>{{ \Carbon\Carbon::parse($participation->created_at)->format('d/m/Y à H:i') }}</td>
<td>{{$participation->instantWin->prize->label_one}}</td>
<td>{{$participation->customer->email}}</td>
@if ($settings->use_ean_codes)
<td>{{$participation->code_ean}}</td>
@endif
<td>{{$participation->code->code_unique}}</td>
@if ($settings->winning_proof === 1)
@if ($participation->sticker !== null)
<td class="text-center"><a href="/fichiers/preuve-de-gain/{{$participation->id}}/{{$participation->sticker}}" class="btn btn-success btn-sm" target="_blank">Voir</a></td>
@else
<td class="text-center">-</td>
@endif
@if ($participation->barcode !== null)
<td class="text-center"><a href="/fichiers/preuve-de-gain/{{$participation->id}}/{{$participation->barcode}}" class="btn btn-success btn-sm" target="_blank">Voir</a></td>
@else
<td class="text-center">-</td>
@endif
@if ($participation->ticket !== null)
<td class="text-center"><a href="/fichiers/preuve-de-gain/{{$participation->id}}/{{$participation->ticket}}" class="btn btn-success btn-sm" target="_blank">Voir</a></td>
@else
<td class="text-center">-</td>
@endif
@endif
<td><a href="{{ route('bo.winners-arcadia', $participation->id) }}" class="btn btn-sm btn-primary">Envoyer</a></td>
</tr>
@endforeach
</tbody>
</table>
</div> </div>
</div> </div>
@endsection @endsection
@push('scripts')
<script>
if(!__GGW) {
var __GGW = {};
}
if(!__GGW.routes) {
__GGW.routes = {};
}
__GGW.routes.updateWinInfo = '{{ route('bo.winners-list.updateInstantWinInfos', ['instantWin' => 'NULL']) }}';
</script>
@endpush

View file

@ -1,3 +0,0 @@
<p>Bonjour,</p>
<p>Le courrier arcadia pour le gain de lot de {{ $user->lastname }} {{ $user->firstname }} est tombé en erreur.</p>
<p>ID CRM de l'utilisateur : {{ $user->crm_id }}, email de l'utilisateur : {{ $user->email }}</p>

View file

@ -6,26 +6,22 @@
<p>Lots (valeur à 0 ou 1 : 0 = faux, 1 = vrai) :</p> <p>Lots (valeur à 0 ou 1 : 0 = faux, 1 = vrai) :</p>
<table class="table table-border"> <table class="table table-border">
<thead class="thead-light"> <thead class="thead-light">
<th scope="col">ID Arcadia</th>
<th scope="col">Label singulier</th> <th scope="col">Label singulier</th>
<th scope="col">Label pluriel</th> <th scope="col">Label pluriel</th>
<th scope="col">Quantité</th> <th scope="col">Quantité</th>
<th scope="col">Notification activé</th> <th scope="col">Notification activé</th>
<th scope="col">Formulaire suppl.</th> <th scope="col">Formulaire suppl.</th>
<th scope="col">ID mail Arcadia</th>
<th scope="col">Pdf preuve de gain</th> <th scope="col">Pdf preuve de gain</th>
<th scope="col">Lot par défaut</th> <th scope="col">Lot par défaut</th>
</thead> </thead>
<tbody> <tbody>
@foreach ($prizesGlobal as $p) @foreach ($prizesGlobal as $p)
<tr> <tr>
<td>{{$p->arcadia_id}}</td>
<td>{{$p->label_one}}</td> <td>{{$p->label_one}}</td>
<td>{{$p->label_many}}</td> <td>{{$p->label_many}}</td>
<td>{{$p->quantity}}</td> <td>{{$p->quantity}}</td>
<td>{{$p->notifications}}</td> <td>{{$p->notifications}}</td>
<td>{{$p->additional_form}}</td> <td>{{$p->additional_form}}</td>
<td>{{$p->arcadia_mail_id}}</td>
<td><span class="badge badge-info">{{$p->pdf_winning_proof}}</span></td> <td><span class="badge badge-info">{{$p->pdf_winning_proof}}</span></td>
<td>{{$p->need_proof}}</td> <td>{{$p->need_proof}}</td>
</tr> </tr>

View file

@ -23,26 +23,22 @@
<p>Lots (valeur à 0 ou 1 : 0 = faux, 1 = vrai) :</p> <p>Lots (valeur à 0 ou 1 : 0 = faux, 1 = vrai) :</p>
<table class="table table-border"> <table class="table table-border">
<thead class="thead-light"> <thead class="thead-light">
<th scope="col">ID Arcadia</th>
<th scope="col">Label singulier</th> <th scope="col">Label singulier</th>
<th scope="col">Label pluriel</th> <th scope="col">Label pluriel</th>
<th scope="col">Quantité</th> <th scope="col">Quantité</th>
<th scope="col">Notification activé</th> <th scope="col">Notification activé</th>
<th scope="col">Formulaire suppl.</th> <th scope="col">Formulaire suppl.</th>
<th scope="col">ID mail Arcadia</th>
<th scope="col">Pdf preuve de gain</th> <th scope="col">Pdf preuve de gain</th>
<th scope="col">Lot par défaut</th> <th scope="col">Lot par défaut</th>
</thead> </thead>
<tbody> <tbody>
@foreach ($prizesGlobal as $p) @foreach ($prizesGlobal as $p)
<tr> <tr>
<td>{{$p->arcadia_id}}</td>
<td>{{$p->label_one}}</td> <td>{{$p->label_one}}</td>
<td>{{$p->label_many}}</td> <td>{{$p->label_many}}</td>
<td>{{$p->quantity}}</td> <td>{{$p->quantity}}</td>
<td>{{$p->notifications}}</td> <td>{{$p->notifications}}</td>
<td>{{$p->additional_form}}</td> <td>{{$p->additional_form}}</td>
<td>{{$p->arcadia_mail_id}}</td>
<td><span class="badge badge-info">{{$p->pdf_winning_proof}}</span></td> <td><span class="badge badge-info">{{$p->pdf_winning_proof}}</span></td>
<td>{{$p->need_proof}}</td> <td>{{$p->need_proof}}</td>
</tr> </tr>

View file

@ -6,26 +6,22 @@
<p>Lots (valeur à 0 ou 1 : 0 = faux, 1 = vrai) :</p> <p>Lots (valeur à 0 ou 1 : 0 = faux, 1 = vrai) :</p>
<table class="table table-border"> <table class="table table-border">
<thead class="thead-light"> <thead class="thead-light">
<th scope="col">ID Arcadia</th>
<th scope="col">Label singulier</th> <th scope="col">Label singulier</th>
<th scope="col">Label pluriel</th> <th scope="col">Label pluriel</th>
<th scope="col">Quantité</th> <th scope="col">Quantité</th>
<th scope="col">Notification activé</th> <th scope="col">Notification activé</th>
<th scope="col">Formulaire suppl.</th> <th scope="col">Formulaire suppl.</th>
<th scope="col">ID mail Arcadia</th>
<th scope="col">Pdf preuve de gain</th> <th scope="col">Pdf preuve de gain</th>
<th scope="col">Lot par défaut</th> <th scope="col">Lot par défaut</th>
</thead> </thead>
<tbody> <tbody>
@foreach ($prizesGlobal as $p) @foreach ($prizesGlobal as $p)
<tr> <tr>
<td>{{$p->arcadia_id}}</td>
<td>{{$p->label_one}}</td> <td>{{$p->label_one}}</td>
<td>{{$p->label_many}}</td> <td>{{$p->label_many}}</td>
<td>{{$p->quantity}}</td> <td>{{$p->quantity}}</td>
<td>{{$p->notifications}}</td> <td>{{$p->notifications}}</td>
<td>{{$p->additional_form}}</td> <td>{{$p->additional_form}}</td>
<td>{{$p->arcadia_mail_id}}</td>
<td><span class="badge badge-info">{{$p->pdf_winning_proof}}</span></td> <td><span class="badge badge-info">{{$p->pdf_winning_proof}}</span></td>
<td>{{$p->need_proof}}</td> <td>{{$p->need_proof}}</td>
</tr> </tr>

View file

@ -7,26 +7,22 @@
<p>Lots (valeur à 0 ou 1 : 0 = faux, 1 = vrai) :</p> <p>Lots (valeur à 0 ou 1 : 0 = faux, 1 = vrai) :</p>
<table class="table table-border"> <table class="table table-border">
<thead class="thead-light"> <thead class="thead-light">
<th scope="col">ID Arcadia</th>
<th scope="col">Label singulier</th> <th scope="col">Label singulier</th>
<th scope="col">Label pluriel</th> <th scope="col">Label pluriel</th>
<th scope="col">Quantité</th> <th scope="col">Quantité</th>
<th scope="col">Notification activé</th> <th scope="col">Notification activé</th>
<th scope="col">Formulaire suppl.</th> <th scope="col">Formulaire suppl.</th>
<th scope="col">ID mail Arcadia</th>
<th scope="col">Pdf preuve de gain</th> <th scope="col">Pdf preuve de gain</th>
<th scope="col">Lot par défaut</th> <th scope="col">Lot par défaut</th>
</thead> </thead>
<tbody> <tbody>
@foreach ($prizesGlobal as $p) @foreach ($prizesGlobal as $p)
<tr> <tr>
<td>{{$p->arcadia_id}}</td>
<td>{{$p->label_one}}</td> <td>{{$p->label_one}}</td>
<td>{{$p->label_many}}</td> <td>{{$p->label_many}}</td>
<td>{{$p->quantity}}</td> <td>{{$p->quantity}}</td>
<td>{{$p->notifications}}</td> <td>{{$p->notifications}}</td>
<td>{{$p->additional_form}}</td> <td>{{$p->additional_form}}</td>
<td>{{$p->arcadia_mail_id}}</td>
<td><span class="badge badge-info">{{$p->pdf_winning_proof}}</span></td> <td><span class="badge badge-info">{{$p->pdf_winning_proof}}</span></td>
<td>{{$p->need_proof}}</td> <td>{{$p->need_proof}}</td>
</tr> </tr>

View file

@ -24,6 +24,10 @@
<!-- Styles --> <!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet"> <link href="{{ asset('css/app.css') }}" rel="stylesheet">
@yield('styles') @yield('styles')
@if(config('app.env') === 'local')
<script>window.vueDebug = true;</script>
@endif
</head> </head>
<body> <body>
<div id="app"> <div id="app">

View file

@ -67,10 +67,8 @@ Route::prefix('bo')
Route::post('/codes/export', [CodesController::class, 'export'])->name('export-codes'); Route::post('/codes/export', [CodesController::class, 'export'])->name('export-codes');
// Liste des gagnants. // Liste des gagnants.
Route::get('/winners-list', [WinnersListController::class, 'index'])->name('winners-list'); Route::get('/winners-list', [WinnersListController::class, 'index'])->name('winners-list');
Route::get('/winners-list/arcadia/{id}', [WinnersListController::class, 'courrierArcadia']) Route::put('/winners-list/{instantWin}/update', [WinnersListController::class, 'updateInstantWinInfos'])
->name('winners-arcadia'); ->name('winners-list.updateInstantWinInfos');
Route::post('/winners-list/arcadia/{id}/send', [WinnersListController::class, 'createCourrierArcadia'])
->name('courrier-arcadia');
// Produits porteurs. // Produits porteurs.
Route::resource('products', ProductsController::class) Route::resource('products', ProductsController::class)
->withoutMiddleware('is-super-admin'); ->withoutMiddleware('is-super-admin');

View file

@ -1,5 +1,6 @@
<?php <?php
use App\Http\Controllers\Fo\CustomerController;
use App\Http\Controllers\Fo\EndPageController; use App\Http\Controllers\Fo\EndPageController;
use App\Http\Controllers\Fo\EnterCodeController; use App\Http\Controllers\Fo\EnterCodeController;
use App\Http\Controllers\Fo\FAQController; use App\Http\Controllers\Fo\FAQController;
@ -26,18 +27,24 @@ Route::group(['middleware' => ['game-date']], function () {
Route::get('/produits-porteurs', [ProduitsController::class, 'index'])->name('produits-porteurs'); Route::get('/produits-porteurs', [ProduitsController::class, 'index'])->name('produits-porteurs');
Route::get('/confirmation-email/{verifyToken}', [LoginController::class, 'confirmEmail'])->name('confirm-email'); Route::get('/confirmation-email/{verifyToken}', [LoginController::class, 'confirmEmail'])->name('confirm-email');
Route::get('/mot-de-passe-oublie', [LoginController::class, 'forgotPassword'])->name('forgot-password'); Route::get('/mot-de-passe-oublie', [LoginController::class, 'forgotPassword'])->name('forgot-password');
Route::post('/mot-de-passe-oublie', [LoginController::class, 'forgotPasswordSubmit'])
->name('forgot-passwordSubmit');
Route::get('/mot-de-passe-oublie/reset/{token}', [LoginController::class, 'forgotPasswordReset']) Route::get('/mot-de-passe-oublie/reset/{token}', [LoginController::class, 'forgotPasswordReset'])
->name('forgot-password-reset'); ->name('forgot-password-reset');
Route::put('/mail-mot-de-passe', [LoginController::class, 'mailPassword'])->name('mail-password'); Route::put('/mot-de-passe-oublie/reset/{token}', [LoginController::class, 'forgotPasswordResetSubmit'])
Route::put('/change-mot-de-passe', [LoginController::class, 'changePassword'])->name('change-password'); ->name('forgot-password-resetSubmit');
// Front nécessitant d'être connecté. // Front nécessitant d'être connecté.
Route::middleware('auth:customer')->group(function () { Route::middleware(['auth:customer', 'crmInfosMustBeComplete'])->group(function () {
Route::get('/saisir-code', [EnterCodeController::class, 'index'])->name('saisir-code'); Route::get('/saisir-code', [EnterCodeController::class, 'index'])->name('saisir-code');
Route::post('/saisir-code', [EnterCodeController::class, 'participate'])->name('participate'); Route::post('/saisir-code', [EnterCodeController::class, 'participate'])->name('participate');
Route::put('/saisir-code', [EnterCodeController::class, 'formWinningProof'])->name('winning-proof'); Route::put('/saisir-code', [EnterCodeController::class, 'formWinningProof'])->name('winning-proof');
Route::put('/rejouer', [WinningProofController::class, 'sendWinningProof'])->name('send-winning-proof'); Route::put('/rejouer', [WinningProofController::class, 'sendWinningProof'])->name('send-winning-proof');
Route::post('/logout', [LoginController::class, 'logout'])->name('logout'); Route::post('/logout', [LoginController::class, 'logout'])->name('logout');
Route::get('/complete-infos', [CustomerController::class, 'completeInfos'])
->withoutMiddleware('crmInfosMustBeComplete')->name('completeInfos');
Route::put('/complete-infos', [CustomerController::class, 'completeInfosSubmit'])
->withoutMiddleware('crmInfosMustBeComplete')->name('completeInfosSubmit');
}); });
// Authentification. // Authentification.