middleware(function (Request $request, callable $next) { $this->authorize('fo.gameEnabled'); $this->assertUserHasEnoughInfoToUseMesBr(); return $next($request); }); } /** * Display participation form * * @return \Illuminate\Contracts\View\View */ public function participate(): View { if (!Gate::check('participate', Participation::class)) { return view('theme::pages.participation-exhausted'); } return view('theme::pages.participate'); } /** * Participate Method * * @param \App\Http\Requests\Fo\ParticipateRequest $request * @return \Illuminate\Contracts\View\View */ public function participateSubmit(ParticipateRequest $request): View { return DB::transaction(function () use ($request) { // ! On verrouille le ou les instants gagnant /** @var \App\Models\InstantWin|null */ $instantWin = InstantWin::query()->lockForUpdate() ->where('available_at', '<', now()) ->whereDoesntHave('participation') ->get()->sortBy('available_at')->first(); /** @var \App\Models\Settings */ $settings = app(Settings::class); /** @var \App\Models\Customer */ $customer = auth('frontend')->user(); /** @var \App\Models\Code */ $code = $request->post('unique_code'); /** @var \App\Models\Product|null */ $product = $request->post('product'); // * Make new participation $participation = Participation::makeNew( app('clientIp'), $customer, $code, $product ); // * Si l'utilisateur actuel à déjà gagné un gros lot, pas d'instant gagnant. // ? As-t-on un instant gagnant ? if (Participation::customerAlreadyHasAnInstantWin($customer) or !$instantWin) { // ? Les BR sont activés ? if (!$settings->discounts_activated) { // * On enregistre la participation du joueur. $participation->save(); // * Pas de coupons disponibles, le joueur à perdu return view('theme::pages.participation.loose'); } // * Le joueur à gagné un coupon. $responseView = $this->serveCouponWin($settings, $participation); // * On enregistre la participation du joueur. $participation->save(); return $responseView; } // * Le joueur à remporté un instant gagnant $participation->instantWin()->save($instantWin); $participation->save(); // * Notify customer for his win $customer->notify(new HasWonInstantWin( $instantWin->prize, $customer->api_data->firstname )); // * Dispatch notification to mail list Mail::to($settings->notification_emails)->send(new PrizeWonAdminMail( $settings->name, $participation->created_at, $instantWin->prize->label, $customer->api_data, $code->code_unique, optional($product)->ean_code )); return view('theme::pages.participation.won', [ 'prizeModel' => $instantWin->prize ]); }); } /** * Undocumented function * * @return \Illuminate\Http\Response */ public function formWinningProof() { $participation = Participation::where([ ['user_id', Auth::user()->id], ['sticker', null], ['ticket', null], ['barcode', null] ])->has('instantWin')->first(); if ($participation) { return view('theme::winning-proof', compact('participation')); } return redirect()->route('fo.homepage'); } // * --- PRIVATE METHODS --- /** * Détermine si un BR doit être servi * renvoi la vue de gain BR ou la vue "Perdu" * * @param \App\Models\Settings $settings The game settings. * @param \App\Models\Participation $participation The actual participation * * @return \Illuminate\Contracts\View\View */ private function serveCouponWin(Settings $settings, Participation $participation): View { /** @var \App\Lib\Discount */ $discount = Arr::get( $settings->web_coupons, $this->getRandomWeightedElementIndex($settings->web_coupons) ); // return response((new DiscountWonMail( // new Address( // $user->email, // $user->first_name // ), // $settings->name, // $discount, // config('app.url') // ))->render()); $crmCoupon = $this->setDiscountAsWon($discount); // * On associe le coupon à la participation $participation->discount()->associate($discount); if (!$crmCoupon) { $participation->delete(); return back()->withErrors("Une erreur est survenue, merci de réessayez ultérieurement."); } Mail::to(Auth::user()->email)->send(new DiscountWonMail(Auth::user(), $coupon, $settings, $crmCoupon)); return view('theme::discount', compact('crmCoupon', 'coupon')); } /** * Try Call CRM + MesBr to setup disount * * @param \App\Models\Customer $customer * @param \App\Models\Discount $discount * @return void * @throws \Illuminate\Http\Exceptions\HttpResponseException * @throws \Psr\Container\NotFoundExceptionInterface * @throws \Psr\Container\ContainerExceptionInterface * @throws \InvalidArgumentException * @throws \Illuminate\Database\Eloquent\InvalidCastException */ private function setDiscountAsWon(Customer $customer, Discount $discount): void { // * Phase - 1 Recupération des informations CRM /** @var \LDC\LDCCRM\Models\Customer|null */ $crmUser = null; try { $crmUser = $customer->api_data; // ? Le compte du joueur est vérifié ? if (!$crmUser->status) { // * Le joueur doit avoir un compte vérifié pour participer. response()->redirectToRoute('fo.verification.notice') ->with('error', trans('Pour participer votre compte doit être activé')) ->throwResponse(); } } catch (ApiErrorException $e) { // * Customer is not found. if ($e->getApiError()->equals(ApiError::modelNotFound())) { // * Déconnexion immédiate et retour maison. auth('frontend')->logout(); response()->redirectToRoute('fo.home') ->with('error', trans('Une erreur est survenue, compte introuvable.')) ->throwResponse(); } report($e); Log::error('Unhandled response ' . $e->getApiError()->label); // * Retenter ? back()->with('error', trans('Une erreur est survenue, veuillez réssayer.'))->throwResponse(); } catch (CrmException | \Exception $e) { report($e); // * Retenter ? back()->with('error', trans('Une erreur est survenue, veuillez réssayer.'))->throwResponse(); } //end try // * Phase - 2 Mise à jour du coupon dans MesBr /** @var \LDC\MESBR\MesBr */ $mesBr = app('mesBrAPI'); $mesBr->updateCustomer($crmUser->hashcode, $crmUser->email, $crmUser->country); $result = $mesBr->getMurCustomer($crmUser->user, $discount); $mesBR->updatePanier($crmUser->user, $discount); if ($result["status"] === "OK") { $discount = new Discount(); $discount->link = $result["link"]; $discount->verification = $result["verif"]; $discount->basket_id = $result["basketId"]; $discount->save(); } else { Mail::to(config('mail.admin')) ->send(new NotifAdmin(\sprintf( 'MESBR : Une erreur est survenue. Code : %s Message : %s', $result["code"], $result["message"] ))); } // return $discount; } /** * Assert that user has enough info filled on his profile to win a Discount * Or redirect him to the fill form * ! Also validates its birth date (because beeing an adult is required to participate) * * @return void * @throws \Illuminate\Http\Exceptions\HttpResponseException If customer data doest not validate * or and error occurs. */ private function assertUserHasEnoughInfoToUseMesBr() { // * Valider que le client dispose des donnés requises pour MesBr try { /** @var \App\Models\Customer */ $authUser = auth('frontend')->user(); $crmCustomer = $authUser->api_data; // * On valide les données selon les critères du site $rules = collect((new CreateAccountRequest())->rules()); Validator::make( [ 'birth_date' => $crmCustomer->birth_date, 'address' => $crmCustomer->address, 'postcode' => $crmCustomer->postcode, 'country' => $crmCustomer->country->value, 'city' => $crmCustomer->city ], [ 'birth_date' => $rules->get('birth_date'), 'address' => $rules->get('address'), 'postcode' => $rules->get('postcode'), 'country' => $rules->get('country'), 'city' => $rules->get('city') ] )->validate(); Session::remove('needCrmInfoUpdate'); } catch (ValidationException) { response()->redirectToRoute('fo.profil.verify') ->with('warning', trans( 'Vous devez compléter des informations sur votre profil pour pouvoir participer.' ))->throwResponse(); } catch (\Exception $e) { report($e); // * Retenter ? response()->redirectToRoute('fo.homepage') ->with('error', trans('Une erreur est survenue, veuillez réssayer.')) ->throwResponse(); } //end try } // * --- END PRIVATE METHODS --- }