SYNC 20 participate InstantWin Ok
This commit is contained in:
parent
9f73d89e5c
commit
cf0b1a54f0
51 changed files with 667 additions and 352 deletions
|
|
@ -28,7 +28,11 @@ class CodeController extends Controller
|
|||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
$nbCodeBase = Code::query()->count();
|
||||
$nbCodeUsed = Code::query()->where('code_used', true)->count();
|
||||
$nbCodeUsed = Code::query()->whereHas(
|
||||
'participations',
|
||||
operator: '>',
|
||||
count: $settings->nb_unique_code_use
|
||||
)->count();
|
||||
$nbCodeExported = Code::query()->where('code_exported', true)->count();
|
||||
$nbCodeRemainingToExport = Code::query()->where('code_exported', false)->count();
|
||||
return view('back::pages.codes.index', compact(
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class ProductController extends Controller
|
|||
$search,
|
||||
null,
|
||||
'name',
|
||||
'code_ean',
|
||||
'ean_code',
|
||||
);
|
||||
}
|
||||
$searchFields = \sprintf(
|
||||
|
|
|
|||
|
|
@ -10,11 +10,13 @@ use App\Mail\NotifAdmin;
|
|||
use App\Mail\NotifWinAdmin;
|
||||
use App\Mail\PrizeWon;
|
||||
use App\Mail\DiscountWonMail;
|
||||
use App\Mail\Won\PrizeWonAdminMail;
|
||||
use App\Models\Customer;
|
||||
use App\Models\InstantWin;
|
||||
use App\Models\Participation;
|
||||
use App\Models\Discount;
|
||||
use App\Models\Settings;
|
||||
use App\Notifications\Customer\HasWonInstantWin;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
|
|
@ -40,6 +42,7 @@ class ParticipateController extends Controller
|
|||
public function __construct()
|
||||
{
|
||||
$this->middleware(function (Request $request, callable $next) {
|
||||
$this->authorize('fo.gameEnabled');
|
||||
$this->assertUserHasEnoughInfoToUseMesBr();
|
||||
return $next($request);
|
||||
});
|
||||
|
|
@ -71,8 +74,8 @@ class ParticipateController extends Controller
|
|||
/** @var \App\Models\InstantWin|null */
|
||||
$instantWin = InstantWin::query()->lockForUpdate()
|
||||
->where('available_at', '<', now())
|
||||
->where('won', false)
|
||||
->get()->sortBy('available_at', 'ASC')->first();
|
||||
->whereDoesntHave('participation')
|
||||
->get()->sortBy('available_at')->first();
|
||||
|
||||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
|
|
@ -81,9 +84,9 @@ class ParticipateController extends Controller
|
|||
$customer = auth('frontend')->user();
|
||||
|
||||
/** @var \App\Models\Code */
|
||||
$code = $request->post('code');
|
||||
$code = $request->post('unique_code');
|
||||
/** @var \App\Models\Product|null */
|
||||
$product = $request->post('code');
|
||||
$product = $request->post('product');
|
||||
|
||||
// * Make new participation
|
||||
$participation = Participation::makeNew(
|
||||
|
|
@ -94,6 +97,7 @@ class ParticipateController extends Controller
|
|||
);
|
||||
|
||||
// * 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) {
|
||||
|
|
@ -114,20 +118,28 @@ class ParticipateController extends Controller
|
|||
}
|
||||
|
||||
// * Le joueur à remporté un instant gagnant
|
||||
// Ici si fail car unique dupliqué catch.
|
||||
try {
|
||||
// Gain d'un gros lot.
|
||||
$this->instantWin($request, $participation, $instantWin);
|
||||
return view(
|
||||
'theme::pages.participation.won_prize',
|
||||
compact('settings')
|
||||
)->with('prize', $instantWin->prize);
|
||||
} catch (\ErrorException $e) {
|
||||
// Unbind instant gagnant.
|
||||
$participation->instantWin()->delete();
|
||||
// phpcs:ignore
|
||||
// TODO: si erreur il faut envoyer un mail à equipe.web@ldc.fr.
|
||||
} //end try
|
||||
$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
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -152,82 +164,6 @@ class ParticipateController extends Controller
|
|||
|
||||
// * --- PRIVATE METHODS ---
|
||||
|
||||
/**
|
||||
* Handle instant wins
|
||||
*
|
||||
* @param string $serial
|
||||
* @param \App\Models\Participation $participation
|
||||
* @param \App\Models\InstantWin|null $instantWin
|
||||
* @return void
|
||||
*/
|
||||
private function instantWin(
|
||||
string $serial,
|
||||
Participation $participation,
|
||||
InstantWin|null $instantWin
|
||||
): void {
|
||||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
|
||||
$instantWin->won = true;
|
||||
// Should save now to prevent next player win on the same winning moment.
|
||||
$instantWin->save();
|
||||
$participation->instantWin()->save($instantWin);
|
||||
// Envoi du courrier Arcadia.
|
||||
if (
|
||||
$instantWin->prize->arcadia_operation_code !== 0 &&
|
||||
$instantWin->prize->arcadia_support_code !== 0
|
||||
) {
|
||||
$crmId = auth('backend')->user()->crm_id;
|
||||
|
||||
$fields = [
|
||||
'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
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
if ($settings->use_ean_codes === 1) {
|
||||
$codeEan = $request->code_ean;
|
||||
$fields['orderLine'][] = [
|
||||
'fieldName' => 'code_on_pack',
|
||||
'fieldValue' => "$codeEan->code"
|
||||
];
|
||||
}
|
||||
|
||||
$arcadiaMail = $this->apiCrm->ArcadiaOutgoingMail($crmId, $fields, 'game');
|
||||
if ($arcadiaMail->status === 'KO') {
|
||||
Mail::to(config('mail.admin'))->send(new CourrierArcadiaError(auth('backend')->user()));
|
||||
}
|
||||
} //end if
|
||||
|
||||
Mail::to(auth('backend')->user()->email)->send(new PrizeWon(auth('backend')->user(), $instantWin->prize, $settings));
|
||||
$mails = json_decode($settings->notification_emails);
|
||||
foreach ($mails as $mail) {
|
||||
Mail::to($mail->email)->send(new NotifWinAdmin($settings, $participation));
|
||||
}
|
||||
$participation->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Détermine si un BR doit être servi
|
||||
* renvoi la vue de gain BR ou la vue "Perdu"
|
||||
|
|
@ -319,11 +255,15 @@ class ParticipateController extends Controller
|
|||
} //end try
|
||||
|
||||
// * Phase - 2 Mise à jour du coupon dans MesBr
|
||||
/** @var \LDCWEB\MesBR */
|
||||
$mesBR = app('mesBrAPI');
|
||||
/** @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);
|
||||
|
||||
$mesBR->updateCustomer($crmUser->user);
|
||||
$result = $mesBR->updatePanier($crmUser->user, $discount);
|
||||
if ($result["status"] === "OK") {
|
||||
$discount = new Discount();
|
||||
$discount->link = $result["link"];
|
||||
|
|
@ -353,7 +293,7 @@ class ParticipateController extends Controller
|
|||
*/
|
||||
private function assertUserHasEnoughInfoToUseMesBr()
|
||||
{
|
||||
// * Valider que le client dispose des donnés requises pour MesBR
|
||||
// * Valider que le client dispose des donnés requises pour MesBr
|
||||
try {
|
||||
/** @var \App\Models\Customer */
|
||||
$authUser = auth('frontend')->user();
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ class StoreProductRequest extends FormRequest
|
|||
{
|
||||
$rules = [
|
||||
'name' => 'required|string|min:3|max:255',
|
||||
'code_ean' => [
|
||||
'ean_code' => [
|
||||
'required',
|
||||
'numeric',
|
||||
'unique:products,code_ean',
|
||||
'unique:products,ean_code',
|
||||
'regex:/^[0-9]{7}$|^[0-9]{8}$|^[0-9]{13}$/',
|
||||
],
|
||||
'picture_alt' => 'required_with:picture|string|between:3,255',
|
||||
|
|
@ -83,7 +83,7 @@ class StoreProductRequest extends FormRequest
|
|||
'model' => trans('models.classes.product'),
|
||||
]),
|
||||
'picture' => trans('validation.attributes.image'),
|
||||
'code_ean' => trans('validation.custom.ean_code'),
|
||||
'ean_code' => trans('validation.custom.ean_code'),
|
||||
'range_id' => trans('models.classes.range'),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Requests\Bo\Products;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateProductRequest extends StoreProductRequest
|
||||
{
|
||||
|
|
@ -24,10 +25,10 @@ class UpdateProductRequest extends StoreProductRequest
|
|||
public function rules()
|
||||
{
|
||||
return array_merge(parent::rules(), [
|
||||
'code_ean' => [
|
||||
'ean_code' => [
|
||||
'required',
|
||||
'numeric',
|
||||
'unique:products,code_ean,' . $this->route('product')->id . ',id',
|
||||
Rule::unique('products', 'ean_code')->ignore($this->route('product')->id),
|
||||
'regex:/^[0-9]{7}$|^[0-9]{8}$|^[0-9]{13}$/',
|
||||
],
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ class UpdateSettingsRequest extends FormRequest
|
|||
'use_ean_codes' => 'required|boolean',
|
||||
'activated_teaser' => 'required|boolean',
|
||||
'activated_close_page' => 'required|boolean',
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'close_page_active_date' => 'nullable|required_if:activated_close_page,true,1|date|after_or_equal:end_date',
|
||||
'redirect_close' => 'required|url:http,https',
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@ use App\Models\Participation;
|
|||
use App\Models\Product;
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\Serial\Exceptions\SerialCasterException;
|
||||
|
||||
|
|
@ -19,8 +21,15 @@ class ParticipateRequest extends FormRequest
|
|||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = auth('frontend')->user();
|
||||
// * Use rate limiter to prevent brute force sticker code
|
||||
if (RateLimiter::tooManyAttempts("participate:{$customer->id}", $perMinute = 5)) {
|
||||
return false;
|
||||
}
|
||||
RateLimiter::hit("participate:{$customer->id}");
|
||||
return Gate::check('participate', Participation::class);
|
||||
}
|
||||
|
||||
|
|
@ -29,25 +38,51 @@ class ParticipateRequest extends FormRequest
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation()
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
try {
|
||||
$this->merge([
|
||||
'code' => Code::query()->where('id', Code::serialToInt(
|
||||
Str::upper(\strval($this->code))
|
||||
'unique_code' => Code::query()->where('id', Code::serialToInt(
|
||||
Str::upper(\strval($this->input('unique_code')))
|
||||
))->first() ?? false,
|
||||
]);
|
||||
} catch (SerialCasterException) {
|
||||
// * Provoquer l'affichage code incorrect.
|
||||
$this->merge([
|
||||
'code' => false,
|
||||
'unique_code' => false,
|
||||
]);
|
||||
} finally {
|
||||
$this->merge([
|
||||
'code_ean' => (string)$this->string('code_ean')->padLeft(13, '0'),
|
||||
'accept_rules' => $this->boolean('accept_rules')
|
||||
'ean_code' => (string)$this->string('ean_code')->padLeft(13, '0'),
|
||||
'game_rules' => $this->boolean('game_rules')
|
||||
]);
|
||||
}
|
||||
|
||||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
|
||||
// ? Does the game use EAN Codes ?
|
||||
if ($settings->use_ean_codes) {
|
||||
/**
|
||||
* * Check si les codes ean sont utilisés, auquel cas
|
||||
* * on test celui envoyé pour savoir s'il est correct.
|
||||
* Modif demande vincent :
|
||||
* Tester code ean existe avec 13, puis 8 puis 7 chars
|
||||
* Si le code EAN est trouvé dans la liste, alors on prend l'objet correspondant,
|
||||
* sinon on prend le premier objet qui contient les 7 1er chiffres (cas des EAN pds)
|
||||
*
|
||||
* Dans la base chaque code ean doit être rentré dans sa valeur absolue
|
||||
* càd que les code ean 8 sont de longueur 8, 7 de longueur7 et 13 de longueur 13.
|
||||
*/
|
||||
$this->merge([
|
||||
// * Union pour faire des recherches séparée en une seule requête.
|
||||
// ! ean_code is already str_padded to 13
|
||||
'product' => Product::query()->where('ean_code', $this->post('ean_code'))
|
||||
->union(Product::query()->where('ean_code', Str::limit($this->post('ean_code'), 8, '')))
|
||||
->union(Product::query()->where('ean_code', Str::limit($this->post('ean_code'), 7, '')))
|
||||
->first()
|
||||
]);
|
||||
} //end if
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -55,41 +90,31 @@ class ParticipateRequest extends FormRequest
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
|
||||
$rules = [
|
||||
'accept_rules' => 'required|boolean|accepted',
|
||||
'serial' => [
|
||||
'game_rules' => 'required|boolean|accepted',
|
||||
'unique_code' => [
|
||||
'required',
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
function ($attribute, $value, $fail) use ($settings) {
|
||||
function (string $attribute, $value, callable $fail) use ($settings) {
|
||||
// ? Le Code unique est resolved ?
|
||||
if ($value === false or !\is_object($value) or \get_class($value) !== Code::class) {
|
||||
$fail(trans('Code unique incorrect, veuillez réessayer.'));
|
||||
return;
|
||||
}
|
||||
/** @var \App\Models\Code $value */
|
||||
// ? Code unique déjà trop utilisé ?
|
||||
if ($value->code_used) {
|
||||
$fail(trans('Ce code unique n\'est plus utilisable.'));
|
||||
return;
|
||||
}
|
||||
|
||||
/** Request réutilisable */
|
||||
$participationQuery = Participation::query()
|
||||
->whereHas('code', fn (Builder $q) => $q->where('id', $value->id));
|
||||
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = auth('frontend')->user();
|
||||
|
||||
// * Check si l'utilisateur n'a pas déjà utilisé ce code.
|
||||
$query = (clone $participationQuery)->whereHas(
|
||||
'customer',
|
||||
fn (Builder $q) => $q->where('id', $customer->id)
|
||||
);
|
||||
$query = Participation::query()
|
||||
->whereHas('code', fn (Builder $q) => $q->where('id', $value->id))
|
||||
->whereHas('customer', fn (Builder $q) => $q->where('id', $customer->id));
|
||||
// ! Une seule participation avec un code donné par joueur
|
||||
if ($query->exists()) {
|
||||
$fail(trans('Vous avez déjà utilisé ce code unique.'));
|
||||
|
|
@ -98,40 +123,29 @@ class ParticipateRequest extends FormRequest
|
|||
|
||||
// * Gestion du nombre d'utilisation d'un code.
|
||||
// ? Le code unique à été trop utilisé ?
|
||||
if ((clone $participationQuery)->count() >= $settings->nb_unique_code_use) {
|
||||
$value->code_used = true;
|
||||
$value->saveOrFail();
|
||||
$fail(trans('Ce code unique n\'est plus utilisable.'));
|
||||
if ($value->has_been_used_too_many_times) {
|
||||
// * Ne pas laisser d'indices, message générique
|
||||
$fail(trans('Code unique incorrect, veuillez réessayer.'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* * Check si les codes ean sont utilisés, auquel cas
|
||||
* * on test celui envoyé pour savoir s'il est correct.
|
||||
* Modif demande vincent :
|
||||
* Tester code ean existe avec 13, puis 8 puis 7 chars
|
||||
* Si le code EAN est trouvé dans la liste, alors on prend l'objet correspondant,
|
||||
* sinon on prend le premier objet qui contient les 7 1er chiffres (cas des EAN pds)
|
||||
*
|
||||
* Dans la base chaque code ean doit être rentré dans sa valeur absolue
|
||||
* càd que les code ean 8 sont de longueur 8, 7 de longueur7 et 13 de longueur 13.
|
||||
*/
|
||||
|
||||
// ? Does the game use EAN Codes ?
|
||||
if ($settings->use_ean_codes) {
|
||||
$rules = \array_merge($rules, ['code_ean' => [
|
||||
$rules = \array_merge($rules, ['ean_code' => [
|
||||
'required',
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
// * Union pour faire des recherches séparée en une seule requête.
|
||||
// ! code_ean is already str_padded to 13
|
||||
$productQuery = Product::query()->where('code_ean', $this->post('code_ean'))
|
||||
->union(Product::where('code_ean', Str::limit($this->post('code_ean'), 8, '')))
|
||||
->union(Product::where('code_ean', Str::limit($this->post('code_ean'), 7, '')));
|
||||
|
||||
if (!$productQuery->exists()) {
|
||||
// phpcs:enable
|
||||
/** @var \App\Models\Produt|mixed */
|
||||
$product = $this->input('product');
|
||||
if (
|
||||
empty($product) or !is_object($product) or
|
||||
!($product instanceof Model) or !$product->exists
|
||||
) {
|
||||
$fail(trans('Le code barre entré est incorrect, veuillez réessayer.'));
|
||||
}
|
||||
}
|
||||
|
|
@ -145,12 +159,12 @@ class ParticipateRequest extends FormRequest
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes()
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'code_ean' => \trans('code barre'),
|
||||
'serial' => \trans('code unique'),
|
||||
'accept_rules' => \trans('règlements du jeu'),
|
||||
'unique_code' => \trans('validation.custom.unique_code'),
|
||||
'ean_code' => \trans('validation.custom.ean_code'),
|
||||
'game_rules' => \trans('validation.custom.game_rules'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class ProcessUniqueCode implements ShouldQueue, ShouldBeUnique
|
|||
->getColumnListing((new Code())->getTable()))
|
||||
->filter(function ($name) {
|
||||
// * Ignorer les colonnes avec valeurs par défaut sur la table.
|
||||
return !in_array($name, ['id', 'code_used', 'code_exported']);
|
||||
return !in_array($name, ['id', 'code_exported']);
|
||||
})->count() + 1;
|
||||
|
||||
/**
|
||||
|
|
|
|||
73
app/Lib/vendor/LDCWEB/MesBR.php
vendored
73
app/Lib/vendor/LDCWEB/MesBR.php
vendored
|
|
@ -1,73 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace LDCWEB;
|
||||
|
||||
class MesBR
|
||||
{
|
||||
private $endpoint;
|
||||
private $refCamp;
|
||||
public function __construct($endpoint, $refCamp)
|
||||
{
|
||||
$this->endpoint = $endpoint;
|
||||
$this->refCamp = $refCamp;
|
||||
}
|
||||
public function createCustomer(string $hashcode, string $email, string $country)
|
||||
{
|
||||
return $this->callAPI("POST", '/customer', ['hashcode' => $hashcode, 'email' => $email, 'country' => $country]);
|
||||
}
|
||||
public function updateCustomer(string $hashcode, string $email, string $country)
|
||||
{
|
||||
return $this->callAPI("POST", '/customer', ['hashcode' => $hashcode, 'email' => $email, 'country' => $country]);
|
||||
}
|
||||
public function getMurCustomer(string $hashcode)
|
||||
{
|
||||
return $this->callAPI("GET", '/customer/mur', ['refcamp' => $this->refCamp, 'hashcode' => $hashcode]);
|
||||
}
|
||||
public function getMur()
|
||||
{
|
||||
return $this->callAPI("GET", '/mur', ['refcamp' => $this->refCamp]);
|
||||
}
|
||||
public function printCoupons(string $hashcode, array $coupons)
|
||||
{
|
||||
return $this->callAPI("GET", '/coupons/print', ['refcamp' => $this->refCamp, 'hashcode' => $hashcode, 'coupons' => implode(",", $coupons)]);
|
||||
}
|
||||
private function callAPI($method, $url, $data = [])
|
||||
{
|
||||
$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":
|
||||
case "DELETE":
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
|
||||
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);
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
||||
120
app/Lib/vendor/LDCWEB/MesBr.php
vendored
Normal file
120
app/Lib/vendor/LDCWEB/MesBr.php
vendored
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
namespace LDC\MESBR;
|
||||
|
||||
class MesBr
|
||||
{
|
||||
private $endpoint;
|
||||
|
||||
private $refCamp;
|
||||
|
||||
public function __construct($endpoint, $refCamp)
|
||||
{
|
||||
$this->endpoint = $endpoint;
|
||||
$this->refCamp = $refCamp;
|
||||
}
|
||||
|
||||
public function createCustomer(string $hashcode, string $email, string $country)
|
||||
{
|
||||
return $this->callApi("POST", '/customer', ['hashcode' => $hashcode, 'email' => $email, 'country' => $country]);
|
||||
}
|
||||
public function updateCustomer(string $hashcode, string $email, string $country)
|
||||
{
|
||||
return $this->callApi("POST", '/customer', ['hashcode' => $hashcode, 'email' => $email, 'country' => $country]);
|
||||
}
|
||||
public function getMurCustomer(string $hashcode)
|
||||
{
|
||||
return $this->callApi("GET", '/customer/mur', ['refcamp' => $this->refCamp, 'hashcode' => $hashcode]);
|
||||
}
|
||||
public function getMur()
|
||||
{
|
||||
return $this->callApi("GET", '/mur', ['refcamp' => $this->refCamp]);
|
||||
}
|
||||
public function printCoupons(string $hashcode, array $coupons)
|
||||
{
|
||||
return $this->callApi("GET", '/coupons/print', [
|
||||
'refcamp' => $this->refCamp, 'hashcode' => $hashcode, 'coupons' => implode(",", $coupons)
|
||||
]);
|
||||
}
|
||||
private function callApi($method, $url, $data = [])
|
||||
{
|
||||
$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":
|
||||
case "DELETE":
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
|
||||
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);
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
// * Added METHODS
|
||||
|
||||
/** Update panier *
|
||||
* @param $oCrmUser
|
||||
* @param $couponId
|
||||
* @param int $quantity
|
||||
* @return array
|
||||
*/
|
||||
public function updatePanier($oCrmUser, $couponId, $quantity = 1)
|
||||
{
|
||||
$datas = [
|
||||
'refsite' => $this->refSite,
|
||||
'refcamp' => $this->refCamp,
|
||||
'refadherent' => $oCrmUser->crm_id,
|
||||
'nom' => $oCrmUser->lastname,
|
||||
'prenom' => $oCrmUser->firstname,
|
||||
'email' => $oCrmUser->email,
|
||||
'code_postal' => $oCrmUser->postcode,
|
||||
'commune' => $oCrmUser->city,
|
||||
'pays' => $this->getCountry($oCrmUser->country),
|
||||
'panier' => "($quantity)$couponId"
|
||||
];
|
||||
|
||||
$res = $this->callAPI("GET", "/updatebasket", $datas);
|
||||
|
||||
if (!$res) {
|
||||
error_log("MESBR - CODE : 999 - MESSAGE : Cannot read API Response (non json)");
|
||||
return ['status' => 'KO', 'code' => 999, 'message' => 'Cannot read API Response (non json)'];
|
||||
}
|
||||
if ($res->Statut === 'KO') {
|
||||
error_log("MESBR - CODE : $res->Code - MESSAGE : $res->Message");
|
||||
return ['status' => 'KO', 'code' => $res->Code, 'message' => $res->Message];
|
||||
}
|
||||
$panierVerification = $this->endpoint . '/showbasket?basketid=' . $res->Panier->Panier;
|
||||
$panier_link = $this->endpoint . '/?basketid=' . $res->Panier->Panier;
|
||||
return ['status' => 'OK', 'link' => $panier_link, 'verif' => $panierVerification, 'basketId' => $res->Panier->Panier];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class NotifAdmin extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/** @var string */
|
||||
private $msg;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param string $msg
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $msg)
|
||||
{
|
||||
$this->msg = $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
$msg = $this->msg;
|
||||
return $this->subject("{$settings->name} : Erreur")->view('front.basic.notif-admin', compact('msg'));
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ use Illuminate\Mail\Mailables\Address;
|
|||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class DiscountWonMail extends Mailable implements ShouldQueue
|
||||
{
|
||||
|
|
@ -56,6 +57,7 @@ class DiscountWonMail extends Mailable implements ShouldQueue
|
|||
*/
|
||||
public function content(): \Illuminate\Mail\Mailables\Content
|
||||
{
|
||||
View::addNamespace('theme', resource_path('theme/mounted/views'));
|
||||
return new Content(
|
||||
markdown: 'theme::mails.won-discount',
|
||||
with: [
|
||||
|
|
|
|||
90
app/Mail/Won/PrizeWonAdminMail.php
Normal file
90
app/Mail/Won/PrizeWonAdminMail.php
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail\Won;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use LDC\LDCCRM\Models\Customer;
|
||||
|
||||
class PrizeWonAdminMail extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param string $game_name The game name.
|
||||
* @param \Carbon\Carbon $participation_date The customer participation date.
|
||||
* @param string $prize_label The won prize label.
|
||||
* @param \LDC\LDCCRM\Models\Customer $customer The customer who won.
|
||||
* @param string $unique_code The unique code used to participate.
|
||||
* @param string|null $ean_code The product code used to participate if any.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
protected string $game_name,
|
||||
protected Carbon $participation_date,
|
||||
protected string $prize_label,
|
||||
protected Customer $customer,
|
||||
protected string $unique_code,
|
||||
protected string $ean_code
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope(): \Illuminate\Mail\Mailables\Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
subject: trans('Votre gain du jeu :game_name', [
|
||||
'game_name' => $this->game_name
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content(): \Illuminate\Mail\Mailables\Content
|
||||
{
|
||||
$participation = [
|
||||
trans('Participation :'),
|
||||
"Code Unique : {$this->unique_code}",
|
||||
];
|
||||
if ($this->ean_code) {
|
||||
$participation[] = "Code EAN : {$this->ean_code}";
|
||||
}
|
||||
return new Content(
|
||||
htmlString: (new MailMessage())
|
||||
->greeting(trans('Bonjour,'))
|
||||
->line(trans(
|
||||
'Le lot suivant a été gagné :prize_label le :date',
|
||||
[
|
||||
'prize_label' => $this->prize_label,
|
||||
'date' => $this->participation_date->isoFormat('LLLL')
|
||||
]
|
||||
))->lines([
|
||||
trans('Gagnant :'),
|
||||
"{$this->customer->lastname} {$this->customer->firstname}",
|
||||
"{$this->customer->address}",
|
||||
"{$this->customer->address2}",
|
||||
"{$this->customer->postcode} {$this->customer->city} - {$this->customer->country->label}",
|
||||
"{$this->customer->email}",
|
||||
"{$this->customer->phone}",
|
||||
])->lines($participation)->render()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ use Illuminate\Mail\Mailables\Address;
|
|||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class PrizeWonMail extends Mailable implements ShouldQueue
|
||||
{
|
||||
|
|
@ -56,6 +57,8 @@ class PrizeWonMail extends Mailable implements ShouldQueue
|
|||
*/
|
||||
public function content(): \Illuminate\Mail\Mailables\Content
|
||||
{
|
||||
// * Fix for async usage
|
||||
View::addNamespace('theme', resource_path('theme/mounted/views'));
|
||||
return new Content(
|
||||
markdown: 'theme::mails.won-prize',
|
||||
with: [
|
||||
|
|
|
|||
|
|
@ -2,18 +2,20 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Kwaadpepper\Serial\SerialCaster;
|
||||
|
||||
/**
|
||||
* Code.
|
||||
*
|
||||
* @property string $code_unique The unique code matching this code id.
|
||||
* @property boolean $code_used Is the code used too much ?
|
||||
* @property boolean $code_exported Is the code exported ?
|
||||
* @property \Illuminate\Support\Carbon $date_creation Code creation date.
|
||||
*
|
||||
* @property-read string|null $code_unique The unique code
|
||||
* @property-read string|null $code_unique The unique code
|
||||
* @property-read boolean $has_been_used_too_many_times Has this code been used too many times ?
|
||||
*
|
||||
* @method public static function intToSerial($int) Generate a serial from an int.
|
||||
* @method public static function serialToInt($serial) Get an int from a serial.
|
||||
|
|
@ -36,7 +38,6 @@ class Code extends Model
|
|||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'code_used',
|
||||
'code_exported',
|
||||
'date_creation'
|
||||
];
|
||||
|
|
@ -44,10 +45,9 @@ class Code extends Model
|
|||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
* @var array<string,string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'code_used' => 'bool',
|
||||
'code_exported' => 'bool',
|
||||
'date_creation' => 'date',
|
||||
];
|
||||
|
|
@ -59,6 +59,20 @@ class Code extends Model
|
|||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::created(fn () => Cache::forget('codes.count'));
|
||||
static::updated(fn () => Cache::forget('codes.count'));
|
||||
static::deleted(fn () => Cache::forget('codes.count'));
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
|
|
@ -71,18 +85,23 @@ class Code extends Model
|
|||
return $this->hasMany(Participation::class, 'code_unique_id');
|
||||
}
|
||||
|
||||
// * FUNCTIONS
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Generate code_unique attribute
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getCodeUniqueAttribute()
|
||||
public function codeUnique(): Attribute
|
||||
{
|
||||
if (!$this->id or !\is_integer($this->id) or $this->id < 1) {
|
||||
return null;
|
||||
}
|
||||
return self::intToSerial($this->id);
|
||||
return Attribute::make(
|
||||
get: function (): ?string {
|
||||
if (!$this->id or !\is_integer($this->id) or $this->id < 1) {
|
||||
return null;
|
||||
}
|
||||
return self::intToSerial($this->id);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -127,4 +146,26 @@ class Code extends Model
|
|||
config('codes.codeCharList')
|
||||
);
|
||||
}
|
||||
|
||||
// * GETTERS
|
||||
|
||||
/**
|
||||
* Get has_been_used_too_namy_times attribute
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function hasBeenUsedTooManyTimes(): Attribute
|
||||
{
|
||||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
return Attribute::make(
|
||||
get: fn (): bool => self::query()
|
||||
->where('id', $this->id)
|
||||
->whereHas(
|
||||
'participations',
|
||||
operator: '>',
|
||||
count: $settings->nb_unique_code_use
|
||||
)->exists()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use App\Notifications\Customer\ResetPassword;
|
|||
use App\Notifications\Customer\VerifyEmail;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Contracts\Database\Query\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Prunable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
|
|
@ -56,6 +57,8 @@ class Customer extends Authenticatable implements MustVerifyEmail
|
|||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
|
|
@ -71,7 +74,7 @@ class Customer extends Authenticatable implements MustVerifyEmail
|
|||
static::assertEmailIsUnique($model->id, $model->email);
|
||||
});
|
||||
static::deleting(function () {
|
||||
throw new \RuntimeException('This cannot be done à cause de MesBR');
|
||||
throw new \RuntimeException('This cannot be done à cause de MesBr');
|
||||
});
|
||||
static::deleted(function (self $model) {
|
||||
if ($model->forceDeleting) {
|
||||
|
|
@ -241,22 +244,23 @@ class Customer extends Authenticatable implements MustVerifyEmail
|
|||
// * --- END AUTH ---
|
||||
|
||||
/**
|
||||
* Get the crm Data of a customer
|
||||
* Get api_data attribute, the crm Data of a customer
|
||||
*
|
||||
* @return \LDC\LDCCRM\Models\Customer
|
||||
* @throws \LDC\LDCCRM\Exceptions\CrmException If cannot fetch data from crm.
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function getApiDataAttribute(): CrmCustomer
|
||||
public function apiData(): Attribute
|
||||
{
|
||||
return self::cacheCrm($this->hashcode, "apiData", function () {
|
||||
/** @var \LDC\LDCCRM\CrmApiV2 */
|
||||
$crm = app('crmAPI');
|
||||
$crmCustomer = $crm->getCustomer($this->hashcode);
|
||||
if (!$crmCustomer) {
|
||||
throw new CrmException('CRM get Customer returned null');
|
||||
}
|
||||
return $crmCustomer;
|
||||
});
|
||||
return Attribute::make(
|
||||
get: fn (): CrmCustomer => self::cacheCrm($this->hashcode, "apiData", function () {
|
||||
/** @var \LDC\LDCCRM\CrmApiV2 */
|
||||
$crm = app('crmAPI');
|
||||
$crmCustomer = $crm->getCustomer($this->hashcode);
|
||||
if (!$crmCustomer) {
|
||||
throw new CrmException('CRM get Customer returned null');
|
||||
}
|
||||
return $crmCustomer;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ class FaqQuestion extends Model
|
|||
*/
|
||||
protected $with = ['theme'];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ class FaqTheme extends Model
|
|||
*/
|
||||
protected $fillable = ['name'];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,19 +2,21 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Models\IsCachedAsCollection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* InstantWin.
|
||||
*
|
||||
* @property \Illuminate\Support\Carbon $available_at When the instant win will be available.
|
||||
* @property boolean $won Is the prize won ?
|
||||
*
|
||||
* @property-read \App\Models\Prize $prize Associated prize.
|
||||
* @property-read \App\Models\Participation $participation Associated participation.
|
||||
*/
|
||||
class InstantWin extends Model
|
||||
{
|
||||
use IsCachedAsCollection;
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
|
|
@ -29,14 +31,19 @@ class InstantWin extends Model
|
|||
*/
|
||||
protected $with = ['prize'];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @var array
|
||||
* @return void
|
||||
*/
|
||||
protected $casts = [
|
||||
'won' => 'bool'
|
||||
];
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(fn () => self::removeCached());
|
||||
static::updating(fn () => self::removeCached());
|
||||
static::deleting(fn () => self::removeCached());
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use IPLib\Address\AddressInterface;
|
|||
* @property-read \Illuminate\Support\Carbon $created_at Creation Date.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Last update Date.
|
||||
*
|
||||
* @property-read string|null $code_ean Accessor for code_ean, from product table.
|
||||
* @property-read string|null $ean_code Accessor for ean_code, from product table.
|
||||
*
|
||||
* @property-read \App\Models\Customer $customer Associated customer.
|
||||
* @property-read \App\Models\Code $code Associated code.
|
||||
|
|
@ -82,14 +82,14 @@ class Participation extends Model
|
|||
// * GETTERS
|
||||
|
||||
/**
|
||||
* Accessor for code_ean, from product table.
|
||||
* Accessor for ean_code, from product table.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
*/
|
||||
public function codeEan(): Attribute
|
||||
public function eanCode(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => optional($this->product)->code_ean,
|
||||
get: fn () => optional($this->product)->ean_code,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ class Participation extends Model
|
|||
public static function customerAlreadyHasAnInstantWin(Customer $customer): bool
|
||||
{
|
||||
return self::query()->whereHas('instantWin')
|
||||
->whereHas('user', fn (Builder $q) => $q->where('id', $customer->id))
|
||||
->whereHas('customer', fn (Builder $q) => $q->where('id', $customer->id))
|
||||
->exists();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ class Prize extends Model
|
|||
'pdf_winning_proof'
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||
* @property string $picture Path of the picture
|
||||
* @property string $picture_alt Alt text for the picture
|
||||
* @property string $picture_title Title text for the picture
|
||||
* @property integer $code_ean Ean code
|
||||
* @property integer $ean_code Ean code
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Creation Date.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Last update Date.
|
||||
*
|
||||
|
|
@ -37,7 +37,7 @@ class Product extends Model
|
|||
'picture',
|
||||
'picture_alt',
|
||||
'picture_title',
|
||||
'code_ean',
|
||||
'ean_code',
|
||||
'range_id',
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ use App\Casts\AsArrayOfDiscount;
|
|||
use App\Lib\Discount;
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Traits\Models\IsCachedAsCollection;
|
||||
use Carbon\CarbonInterval;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
/**
|
||||
* Settings.
|
||||
|
|
@ -87,6 +90,8 @@ class Settings extends Model
|
|||
'notification_emails' => 'array',
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
|
|
@ -127,6 +132,46 @@ class Settings extends Model
|
|||
return FileStorageHelper::onlyUploadedFilesWithFileStorageHelper(collect($files)->filter()->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the game can be play and report if it cannot.
|
||||
*
|
||||
* Demande Vincent: Methods to check via policy if game can be played
|
||||
*
|
||||
* Besoin:
|
||||
* - Min 1 code unique
|
||||
* - Min 1 Instant gagnant
|
||||
* - Min 1 Product si Settings use_ean_codes
|
||||
* - Min 1 WebCoupon si Settings discounts_activated
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkGameCanBePlayed(): bool
|
||||
{
|
||||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
if (!(bool)Prize::getCached()->count()) {
|
||||
report(new \RuntimeException('Need prizes to enable the game'));
|
||||
return false;
|
||||
}
|
||||
if (!(bool)Cache::remember('codes.count', CarbonInterval::day(), fn () => Code::query()->count())) {
|
||||
report(new \RuntimeException('Need codes to enable the game'));
|
||||
return false;
|
||||
}
|
||||
if (!(bool)InstantWin::getCached()->count()) {
|
||||
report(new \RuntimeException('Need instant win to enable the game'));
|
||||
return false;
|
||||
}
|
||||
if ($settings->use_ean_codes and !(bool)Product::getCached()->count()) {
|
||||
report(new \RuntimeException('Need products to enable the game using ean codes'));
|
||||
return false;
|
||||
}
|
||||
if ($settings->discounts_activated and !(bool)collect($this->web_coupons)->count()) {
|
||||
report(new \RuntimeException('Need MesBr coupons to enable the game using discounts'));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// * GETTERS
|
||||
|
||||
/**
|
||||
|
|
@ -134,11 +179,13 @@ class Settings extends Model
|
|||
*
|
||||
* The game has started ?
|
||||
*
|
||||
* @return boolean
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function getGameHasBegunAttribute(): bool
|
||||
public function gameHasBegun(): Attribute
|
||||
{
|
||||
return $this->start_date->lte(now());
|
||||
return Attribute::make(
|
||||
get: fn (): bool => $this->start_date->lte(now())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -146,11 +193,13 @@ class Settings extends Model
|
|||
*
|
||||
* The game has ended ?
|
||||
*
|
||||
* @return boolean
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function getGameHasEndedAttribute(): bool
|
||||
public function gameHasEnded(): Attribute
|
||||
{
|
||||
return $this->game_has_begun and $this->end_date->lte(now());
|
||||
return Attribute::make(
|
||||
get: fn (): bool => $this->game_has_begun and $this->end_date->lte(now())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -158,11 +207,13 @@ class Settings extends Model
|
|||
*
|
||||
* The game is oppen ?
|
||||
*
|
||||
* @return boolean
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function getGameIsOpenAttribute(): bool
|
||||
public function gameIsOpen(): Attribute
|
||||
{
|
||||
return $this->game_has_begun and !$this->game_has_ended;
|
||||
return Attribute::make(
|
||||
get: fn (): bool => $this->game_has_begun and !$this->game_has_ended
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -170,13 +221,15 @@ class Settings extends Model
|
|||
*
|
||||
* The teaser page has to be displayed ?
|
||||
*
|
||||
* @return boolean
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function getShouldDisplayTeaserPageAttribute(): bool
|
||||
public function shouldDisplayTeaserPage(): Attribute
|
||||
{
|
||||
return !$this->game_has_begun and
|
||||
!$this->game_has_ended and
|
||||
$this->activated_teaser;
|
||||
return Attribute::make(
|
||||
get: fn (): bool => !$this->game_has_begun and
|
||||
!$this->game_has_ended and
|
||||
$this->activated_teaser
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -184,13 +237,15 @@ class Settings extends Model
|
|||
*
|
||||
* The end page has to be displayed ?
|
||||
*
|
||||
* @return boolean
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function getShouldDisplayEndPageAttribute(): bool
|
||||
public function shouldDisplayEndPage(): Attribute
|
||||
{
|
||||
return $this->game_has_begun and
|
||||
$this->game_has_ended and
|
||||
$this->activated_close_page and
|
||||
$this->close_page_active_date->gte(now());
|
||||
return Attribute::make(
|
||||
get: fn (): bool => $this->game_has_begun and
|
||||
$this->game_has_ended and
|
||||
$this->activated_close_page and
|
||||
$this->close_page_active_date->gte(now())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ class StaticPage extends Model
|
|||
'type' => StaticPageType::class,
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Models;
|
|||
|
||||
use App\Enums\Users\RoleEnum;
|
||||
use App\Traits\Models\ActivityLog;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
|
@ -64,6 +65,8 @@ class User extends Authenticatable
|
|||
'published' => 'boolean',
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Notifications\Customer;
|
||||
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Notifications\Customer;
|
||||
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
|
|
|
|||
63
app/Notifications/Customer/HasWonInstantWin.php
Normal file
63
app/Notifications/Customer/HasWonInstantWin.php
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace App\Notifications\Customer;
|
||||
|
||||
use App\Mail\Won\PrizeWonMail;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Prize;
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Mail\Mailable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class HasWonInstantWin extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param \App\Models\Prize $prize The prize that has been won.
|
||||
* @param string $first_name The client first name.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(protected Prize $prize, protected string $first_name)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param object $notifiable
|
||||
* @return array<int, string>
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
*/
|
||||
public function via(object $notifiable): array
|
||||
{
|
||||
// phpcs:enable
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param \App\Models\Customer $notifiable
|
||||
* @return \Illuminate\Contracts\Mail\Mailable
|
||||
*/
|
||||
public function toMail(Customer $notifiable): Mailable
|
||||
{
|
||||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
return (new PrizeWonMail(
|
||||
new Address(
|
||||
$notifiable->email,
|
||||
$this->first_name
|
||||
),
|
||||
$settings->name,
|
||||
$this->prize,
|
||||
config('app.url')
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Notifications\Customer;
|
||||
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Auth\Notifications\ResetPassword as NotificationsResetPassword;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Notifications\Customer;
|
||||
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Notifications\Customer;
|
||||
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Notifications\Customer;
|
||||
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Auth\Notifications\VerifyEmail as NotificationsVerifyEmail;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
|
|
|||
54
app/Notifications/InstantWin/HasBennWon.php
Normal file
54
app/Notifications/InstantWin/HasBennWon.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace App\Notifications\InstantWin;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class HasBennWon extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function via(object $notifiable): array
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*/
|
||||
public function toMail(object $notifiable): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->line('The introduction to the notification.')
|
||||
->action('Notification Action', url('/'))
|
||||
->line('Thank you for using our application!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(object $notifiable): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ use App\Enums\Users\RoleEnum;
|
|||
use App\Models\Customer;
|
||||
use App\Models\FaqQuestion;
|
||||
use App\Models\Product;
|
||||
use App\Models\Settings;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
|
@ -53,6 +54,16 @@ class AuthServiceProvider extends ServiceProvider
|
|||
(bool)FaqQuestion::getCached()->count()
|
||||
);
|
||||
|
||||
Gate::define(
|
||||
'fo.gameEnabled',
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
function (User|Customer|null $user) {
|
||||
/** @var \App\Models\Settings */
|
||||
$settings = app(Settings::class);
|
||||
return $settings->checkGameCanBePlayed();
|
||||
}
|
||||
);
|
||||
|
||||
$this->app->auth->provider('crm', function ($app, array $config) {
|
||||
return new CrmUserProvider($app['hash'], $config['model']);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace App\Providers;
|
|||
use App\Models\Settings;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use LDCWEB\MesBR;
|
||||
use LDC\MESBR\MesBr;
|
||||
|
||||
class MesBrApiServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -20,7 +20,7 @@ class MesBrApiServiceProvider extends ServiceProvider
|
|||
/** @var \App\Models\Settings|null */
|
||||
$settings = app(Settings::class);
|
||||
|
||||
return new MesBR(
|
||||
return new MesBr(
|
||||
config('mesbr.endpoint'),
|
||||
$settings->discounts_site,
|
||||
$settings->discounts_campaign
|
||||
|
|
|
|||
|
|
@ -79,9 +79,9 @@ class RouteServiceProvider extends ServiceProvider
|
|||
}
|
||||
// * Flatten if needed
|
||||
$cspReport = collect(request()->json('csp-report'))
|
||||
->flatMap(function ($v, $k) {
|
||||
return [$k => is_array($v) ? collect($v)->flatten()->implode(', ') : $v];
|
||||
})->all();
|
||||
->flatMap(function ($v, $k) {
|
||||
return [$k => is_array($v) ? collect($v)->flatten()->implode(', ') : $v];
|
||||
})->all();
|
||||
// * Filter array keys
|
||||
$cspReport = collect(array_intersect_key($cspReport, [
|
||||
'blocked-uri' => '', 'document-uri' => '', 'original-policy' => '',
|
||||
|
|
@ -93,7 +93,7 @@ class RouteServiceProvider extends ServiceProvider
|
|||
$cspReport->implode("\n")
|
||||
));
|
||||
})->middleware('throttle:5,2')
|
||||
->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class)
|
||||
->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class)
|
||||
->name('cspReportUri');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/",
|
||||
"LDCWEB\\": "app/Lib/vendor/LDCWEB"
|
||||
"LDC\\MESBR\\": "app/Lib/vendor/LDCWEB"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class ProductFactory extends Factory
|
|||
return [
|
||||
'name' => 'product ' . \fake()->jobTitle(),
|
||||
// * EAN 13 generate
|
||||
'code_ean' => fake()->randomNumber(8, true) . fake()->randomNumber(5, true),
|
||||
'ean_code' => fake()->randomNumber(8, true) . fake()->randomNumber(5, true),
|
||||
'picture_alt' => fake()->sentence(),
|
||||
'picture_title' => fake()->sentence(),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ return new class extends Migration
|
|||
{
|
||||
Schema::create('codes', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('id')->primary();
|
||||
$table->boolean('code_used')->default(0)->comment('Is the code used too much ?');
|
||||
$table->boolean('code_exported')->default(0)->comment('Has the code been exported ?');
|
||||
$table->date('date_creation')->comment('Code creation date');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ return new class extends Migration
|
|||
$table->string('picture_alt')->nullable()->comment('Attribut alt de l\'image du produit');
|
||||
$table->string('picture_title')->nullable()->comment('Attribut title de l\'image du produit');
|
||||
|
||||
$table->unsignedBigInteger('code_ean')->comment('Code EAN du produit pour la participation au jeu');
|
||||
$table->unsignedBigInteger('ean_code')->comment('Code EAN du produit pour la participation au jeu');
|
||||
|
||||
$table->foreignId('range_id')->before('created_at')->references('id')
|
||||
->on('ranges')->onDelete('cascade');
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ return new class extends Migration
|
|||
$table->id();
|
||||
$table->timestamp('available_at')
|
||||
->comment('La date-heure à laquelle l\'instant gagnant pourras être gagné');
|
||||
$table->boolean('won')->default(0)->comment('L\'instant à été gagné ?');
|
||||
|
||||
$table->foreignId('prize_id')->comment('Le lot qui à été gagné')->constrained('prizes');
|
||||
$table->foreignId('participation_id')
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Database\Seeders\Development;
|
|||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Models\Prize;
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
|
@ -11,6 +12,8 @@ use Illuminate\Support\Facades\Schema;
|
|||
|
||||
class PrizeSeeder extends Seeder
|
||||
{
|
||||
use WithoutModelEvents;
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -238,6 +238,7 @@ return [
|
|||
|
||||
'ip' => 'IP',
|
||||
'code' => 'code',
|
||||
'unique_code' => 'code unique',
|
||||
'product' => 'produit',
|
||||
'value' => 'valeur',
|
||||
'question' => 'question',
|
||||
|
|
@ -268,5 +269,6 @@ return [
|
|||
'discounts_site' => 'référence du site',
|
||||
'discounts_campaign' => 'référence de la campagne',
|
||||
'analytics' => 'analytics',
|
||||
'game_rules' => 'règlement du jeu',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{{-- Meta --}}
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
{{-- blade-formatter-disable --}}
|
||||
@hasSection('metaIndex')
|
||||
<meta name="robots" content="@yield('metaIndex')">
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@
|
|||
<dt><span class="h4">{{ __('Voici l\'état du code trouvé') }}</span></dt>
|
||||
<dd>{{ __('Code') }} : <strong>{{ $code->code_unique }}</strong></dd>
|
||||
<dd>{{ __('ID') }} : <strong>{{ $code->id }}</strong></dd>
|
||||
<dd>{{ __('Utilisé ?') }} :
|
||||
<dd>{{ __('À atteint son nombre maximal d\'utilisation ?') }} :
|
||||
<strong>
|
||||
@if ($code->code_used)
|
||||
@if ($code->has_been_used_too_many_times)
|
||||
{{ Str::ucfirst(__('oui')) }}
|
||||
@else
|
||||
{{ Str::ucfirst(__('non')) }}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
{{ __('Top 3 des codes EAN les plus utilisés') }} :
|
||||
<ul class="list-group list-group-horizontal">
|
||||
@foreach ($codesEan as $codeEan)
|
||||
<li class="list-group-item">{{ $codeEan->code_ean }} : <b>{{ $codeEan->nb_usage }}</b></li>
|
||||
<li class="list-group-item">{{ $codeEan->ean_code }} : <b>{{ $codeEan->nb_usage }}</b></li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- CODE_EAN --}}
|
||||
{{-- EAN_CODE --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<fieldset class="container-fluid border p-3">
|
||||
<legend>{{ Str::ucfirst(__('validation.custom.ean_code')) }}</legend>
|
||||
|
|
@ -115,7 +115,7 @@
|
|||
'label' => __(':field', [
|
||||
'field' => Str::ucfirst(__('validation.custom.ean_code')),
|
||||
]),
|
||||
'name' => 'code_ean',
|
||||
'name' => 'ean_code',
|
||||
'required' => true,
|
||||
'model' => $productModel ?? null,
|
||||
'helper' => __('validation.ean', [
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
@include('back::modules.table-col-sorter', [
|
||||
'cols' => [
|
||||
'name' => Str::ucfirst(__('validation.attributes.name')),
|
||||
'code_ean' => Str::ucfirst(__('validation.custom.ean_code')),
|
||||
'ean_code' => Str::ucfirst(__('validation.custom.ean_code')),
|
||||
'range_id' => Str::ucfirst(__('models.classes.range')),
|
||||
],
|
||||
])
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
@foreach ($productModels as $productModel)
|
||||
<tr class="border-bottom list-item">
|
||||
<td class="text-center align-middle">{{ $productModel->name }}</td>
|
||||
<td class="text-center align-middle">{{ $productModel->code_ean }}</td>
|
||||
<td class="text-center align-middle">{{ $productModel->ean_code }}</td>
|
||||
<td class="text-center align-middle">{{ $productModel->range->name }}</td>
|
||||
<td class="text-end align-middle">
|
||||
<form class="btn-group confirmDeleteTS" action="{{ route('bo.products.destroy', $productModel) }}" method="POST"
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
</div>
|
||||
<div class="d-flex justify-content-center flex-column flex-sm-row mb-3">
|
||||
<span class="h3 me-2">{{ Str::ucfirst(__('validation.custom.ean_code')) }}</span>
|
||||
<span class="h3 fw-bold">{{ $productModel->code_ean }}</span>
|
||||
<span class="h3 fw-bold">{{ $productModel->ean_code }}</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center flex-column flex-sm-row mb-3">
|
||||
<span class="h3 me-2">{{ Str::ucfirst(__('models.classes.range')) }}</span>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
'email' => __('Email'),
|
||||
];
|
||||
if ($settings->use_ean_codes === 1) {
|
||||
$cols['code_ean_id'] = __('Code EAN');
|
||||
$cols['ean_code_id'] = __('Code EAN');
|
||||
}
|
||||
$cols['code_unique_id'] = __('Code unique');
|
||||
if ($settings->winning_proof === 1) {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
--}}
|
||||
|
||||
<div class="form-check form-switch ms-2">
|
||||
<label class="col-form-label p-0" type="button" for="{{ $id }}"><b>{{ $label }}</b></label>
|
||||
<label class="col-form-label p-0" for="{{ $id }}"><b>{{ $label }}</b></label>
|
||||
<input
|
||||
id="{{ $id }}"
|
||||
aria-describedby="{{ $id }}Help"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue