- composer require kwaadpepper/serial-int-caster
- add code parameters into config - add code length parameter into settings - add total possible codes to generate in generation page - add GenerateRequest validation - changed job ProcessUniqueCode to increase performances using mass insert and pagination - changed singletoned Settings instance to increase performances - Fix process export code put datetime in file name - aded storage to gitignore file - fixed export to guess export codes, also non recursive now - changed refactorize a bit EnterCodeController::participate + add request - Add request to export and generate codes requests
This commit is contained in:
parent
7f557963ab
commit
9ee2123928
32 changed files with 775 additions and 227 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -26,3 +26,4 @@ package-lock.json
|
|||
composer.lock
|
||||
resources/front
|
||||
.vscode
|
||||
storage
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class ExportCodesUniques extends Command
|
|||
$this->info("L'archive CodesUniques_" . date('dmY') . ".zip a ete creer.");
|
||||
|
||||
// Envoi de mail à MAIL_ADMIN avec le nom du ZIP "CodesUniques_". date('dmY') .".zip"
|
||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new MailExportCodesUniques(Settings::find(1)->name, $nbCodeFic, $nbCodeTot, $nbCodeLigne));
|
||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new MailExportCodesUniques(app(Settings::class)->name, $nbCodeFic, $nbCodeTot, $nbCodeLigne));
|
||||
}
|
||||
|
||||
private function process($nbCodeFic, $nbCodeTot, $nbCodeLigne, $totalExportedCodes, $currentFilename, $currentExportedCodes, $currentLineCodes, $lastExportedCodeId = null)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class EndPageController extends Controller
|
|||
{
|
||||
public function index()
|
||||
{
|
||||
$settings = Settings::find(1)->select('start_date', 'end_date', 'activated_close_page', 'close_page_active_date', 'redirect_close')->first();
|
||||
$settings = app(Settings::class)->select('start_date', 'end_date', 'activated_close_page', 'close_page_active_date', 'redirect_close')->first();
|
||||
if ($settings->end_date < now() && $settings->activated_close_page === 1 && $settings->close_page_active_date > now()) {
|
||||
return view('front.basic.end', compact('settings'));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\ParticipateRequest;
|
||||
use App\Mail\CourrierArcadiaError;
|
||||
use App\Mail\NotifAdmin;
|
||||
use App\Mail\NotifWinAdmin;
|
||||
|
|
@ -34,27 +35,21 @@ class EnterCodeController extends Controller
|
|||
public function index()
|
||||
{
|
||||
$nbParticipations = Participation::where('user_id', Auth::user()->id)->count();
|
||||
$settings = Settings::find(1)->select('use_ean_codes', 'nb_participation_player')->first();
|
||||
$settings = app(Settings::class)->select('use_ean_codes', 'nb_participation_player')->first();
|
||||
if ($nbParticipations >= $settings->nb_participation_player) {
|
||||
return view('front.basic.participation-exhausted', compact('settings'));
|
||||
}
|
||||
return view('front.basic.enter-code', compact('settings'));
|
||||
}
|
||||
|
||||
public function participate(Request $request)
|
||||
public function participate(ParticipateRequest $request)
|
||||
{
|
||||
// TODO : VALIDATE avec / sans code ean
|
||||
// Récupération des données à utilisées
|
||||
$code = strtoupper($request->code);
|
||||
$codeBase = Codes::where('code_unique', $code)->first();
|
||||
$settings = Settings::find(1);
|
||||
// Récupération des données à utilisées.
|
||||
$codeBase = Codes::whereId(Codes::serialToInt($request->code))->first();
|
||||
$settings = app(Settings::class);
|
||||
|
||||
$rules = $request->accept_rules === null ? false : true;
|
||||
if (!$rules) {
|
||||
return back()->withErrors("Pour participer, vous devez accepter le règlement du jeu.");
|
||||
}
|
||||
|
||||
// Cas IP bannie
|
||||
// * Cas IP bannie.
|
||||
if (config('app.env') == "local") {
|
||||
$ipBanned = BannedIP::where('ip', $_SERVER['REMOTE_ADDR'])->first() === null ? 0 : 1;
|
||||
} else {
|
||||
|
|
@ -64,13 +59,13 @@ class EnterCodeController extends Controller
|
|||
return view('front.basic.participation-exhausted', compact('settings'));
|
||||
}
|
||||
|
||||
// Cas nombre de participation maximale atteint
|
||||
// * Cas nombre de participation maximale atteint.
|
||||
$nbParticipations = Participation::where('user_id', Auth::user()->id)->count();
|
||||
if ($nbParticipations >= $settings->nb_participation_player) {
|
||||
return view('front.basic.participation-exhausted', compact('settings'));
|
||||
}
|
||||
|
||||
// Check le code pour savoir s'il est encore utilisable
|
||||
// * Check le code pour savoir s'il est encore utilisable.
|
||||
if (!$codeBase) {
|
||||
return back()->withErrors("Code incorrect, veuillez réessayer.");
|
||||
}
|
||||
|
|
@ -78,7 +73,7 @@ class EnterCodeController extends Controller
|
|||
return back()->withErrors("Ce code n'est plus utilisable.");
|
||||
}
|
||||
|
||||
// Check si l'utilisateur n'a pas déjà utiliser ce code
|
||||
// * Check si l'utilisateur n'a pas déjà utiliser ce code.
|
||||
$participUser = Participation::where([
|
||||
['code_unique_id', $codeBase->id],
|
||||
['user_id', Auth::user()->id]
|
||||
|
|
@ -87,7 +82,7 @@ class EnterCodeController extends Controller
|
|||
return back()->withErrors("Vous avez déjà utilisé ce code.");
|
||||
}
|
||||
|
||||
// Check si les codes ean sont utilisés, auquel cas on test celui envoyé pour savoir s'il est correct
|
||||
// * Check si les codes ean sont utilisés, auquel cas on test celui envoyé pour savoir s'il est correct.
|
||||
$codeEan = null;
|
||||
// TODO : Task Algo Sebastien
|
||||
if ($settings->use_ean_codes === 1) {
|
||||
|
|
@ -103,7 +98,7 @@ class EnterCodeController extends Controller
|
|||
|
||||
$codeNbUsage = Participation::where('code_unique_id', $codeBase->id)->count();
|
||||
|
||||
// Gestion du nombre d'utilisation d'un code
|
||||
// * Gestion du nombre d'utilisation d'un code.
|
||||
if ($codeNbUsage >= $settings->nb_unique_code_use) {
|
||||
$codeBase->code_used = 1;
|
||||
$codeBase->save();
|
||||
|
|
@ -114,7 +109,7 @@ class EnterCodeController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
// Tous les cas "bloquants" sont passé, l'utilisateur participe à partir d'ici
|
||||
// * Tous les cas "bloquants" sont passé, l'utilisateur participe à partir d'ici.
|
||||
$participation = new Participation();
|
||||
$participation->user_id = Auth::user()->id;
|
||||
$participation->code_unique_id = $codeBase->id;
|
||||
|
|
@ -126,13 +121,13 @@ class EnterCodeController extends Controller
|
|||
}
|
||||
$participation->save();
|
||||
|
||||
// Gestion des instants gagnants
|
||||
// * Gestion des instants gagnants.
|
||||
$userAlreadyWon = Participation::where([
|
||||
['user_id', Auth::user()->id],
|
||||
['instant_win_id', '<>', null]
|
||||
])->first();
|
||||
|
||||
// Si l'utilisateur actuel à déjà gagné un gros lot, pas d'instant gagnant
|
||||
// * Si l'utilisateur actuel à déjà gagné un gros lot, pas d'instant gagnant.
|
||||
if ($userAlreadyWon) {
|
||||
return $this->serveCouponWin($settings,$participation);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ class LoginController extends Controller
|
|||
|
||||
$user->password_token = Str::uuid();
|
||||
$user->save();
|
||||
$settings = Settings::find(1);
|
||||
$settings = app(Settings::class);
|
||||
Mail::to($email)->send(new PasswordReset($user, $settings));
|
||||
return redirect()->route('login')->with('success', 'Un mail de réinitialisation de votre mot de passe vous a été envoyé(e).');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class TeaserController extends Controller
|
|||
{
|
||||
public function index()
|
||||
{
|
||||
$settings = Settings::find(1)->select('start_date', 'end_date', 'activated_teaser', 'teaser_end_activity')->first();
|
||||
$settings = app(Settings::class)->select('start_date', 'end_date', 'activated_teaser', 'teaser_end_activity')->first();
|
||||
if ($settings->activated_teaser === 1 && $settings->teaser_end_activity > now()) {
|
||||
return view('front.basic.teaser', compact('settings'));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ class WinningProofController extends Controller
|
|||
$participation->barcode = $barcodeFileName;
|
||||
$participation->save();
|
||||
|
||||
$settings = Settings::find(1);
|
||||
$settings = app(Settings::class);
|
||||
$mails = json_decode($settings->notification_emails);
|
||||
foreach ($mails as $mail) {
|
||||
Mail::to($mail->email)->send(new WinningProof($stickerPath, $ticketPath, $barcodePath, $participation, $user, $settings));
|
||||
|
|
|
|||
|
|
@ -3,42 +3,74 @@
|
|||
namespace App\Http\Controllers\bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ExportCodesRequest;
|
||||
use App\Http\Requests\GenerateCodesRequest;
|
||||
use App\Jobs\ProcessExportCodesUniques;
|
||||
use App\Jobs\ProcessUniqueCode;
|
||||
use App\Models\Codes;
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CodesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show code form to generate and export
|
||||
*
|
||||
* @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$settings = app(Settings::class);
|
||||
$nbCodeBase = Codes::count();
|
||||
$nbCodeUsed = Codes::where('code_used', 1)->count();
|
||||
$nbCodeExported = Codes::where('code_exported', 1)->count();
|
||||
$nbCodeRemainingToExport = Codes::where('code_exported', 0)->count();
|
||||
return view('bo.codes.index', compact('nbCodeBase', 'nbCodeUsed', 'nbCodeExported', 'nbCodeRemainingToExport'));
|
||||
return view('bo.codes.index', compact(
|
||||
'settings',
|
||||
'nbCodeBase',
|
||||
'nbCodeUsed',
|
||||
'nbCodeExported',
|
||||
'nbCodeRemainingToExport'
|
||||
));
|
||||
}
|
||||
|
||||
public function generate(Request $request)
|
||||
/**
|
||||
* Run generate codes action
|
||||
*
|
||||
* @param GenerateCodesRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function generate(GenerateCodesRequest $request)
|
||||
{
|
||||
$quantity = $request->quantity;
|
||||
$codeLength = $request->code_length;
|
||||
$settings = Settings::find(1);
|
||||
ProcessUniqueCode::dispatch(
|
||||
$request->quantity,
|
||||
$request->code_length
|
||||
);
|
||||
|
||||
ProcessUniqueCode::dispatch($quantity, $codeLength, $settings);
|
||||
|
||||
return back()->with('success', "La génération à commencée, un mail de notification sera envoyé à l'adresse " . config('mail.MAIL_ADMIN') . " lorsque le traitement sera terminé.");
|
||||
return back()->with(
|
||||
'success',
|
||||
"La génération à commencée, un mail de notification sera envoyé à l'adresse " .
|
||||
config('mail.MAIL_ADMIN') . " lorsque le traitement sera terminé."
|
||||
);
|
||||
}
|
||||
|
||||
public function export(Request $request)
|
||||
/**
|
||||
* Run export codes
|
||||
*
|
||||
* @param ExportCodesRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function export(ExportCodesRequest $request)
|
||||
{
|
||||
$nbCodeFic = intval($request->nb_code_fic);
|
||||
$nbCodeTot = intval($request->nb_code_tot);
|
||||
$nbCodeLigne = intval($request->nb_code_ligne);
|
||||
ProcessExportCodesUniques::dispatch(
|
||||
intval($request->nb_code_fic),
|
||||
intval($request->nb_code_tot),
|
||||
intval($request->nb_code_ligne)
|
||||
);
|
||||
|
||||
ProcessExportCodesUniques::dispatch($nbCodeFic, $nbCodeTot, $nbCodeLigne);
|
||||
|
||||
return back()->with('success', "L'export des codes à commencé, un mail de notification sera envoyé à l'adresse " . config('mail.MAIL_ADMIN') . " lorsque le traitement sera terminé.");
|
||||
return back()->with(
|
||||
'success',
|
||||
"L'export des codes à commencé, un mail de notification sera envoyé à l'adresse " .
|
||||
config('mail.MAIL_ADMIN') . " lorsque le traitement sera terminé."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class DashboardController extends Controller
|
|||
public function index()
|
||||
{
|
||||
// Pour les stats
|
||||
$settings = Settings::find(1);
|
||||
$settings = app(Settings::class);
|
||||
$participations = Participation::selectRaw("COUNT(*) AS count, DATE(created_at) AS date")->groupByRaw("DATE(created_at)")->get();
|
||||
$participationsUniquePerDay = Participation::selectRaw("DISTINCT user_id AS user, COUNT(*) AS count, DATE(created_at) AS date")->groupByRaw("DATE(created_at), user")->get();
|
||||
$statsUnique = [];
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class SettingsController extends Controller
|
|||
{
|
||||
public function manage(Request $request)
|
||||
{
|
||||
$settings = Settings::find(1);
|
||||
$settings = app(Settings::class);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$name = $request->name;
|
||||
|
|
@ -76,7 +76,7 @@ class SettingsController extends Controller
|
|||
|
||||
$settings->save();
|
||||
|
||||
$settingsGlobal = Settings::find(1)->select('name', 'company', 'analytics', 'start_date', 'end_date')->first();
|
||||
$settingsGlobal = app(Settings::class)->select('name', 'company', 'analytics', 'start_date', 'end_date')->first();
|
||||
Cache::put('settingsGlobal', $settingsGlobal);
|
||||
|
||||
$success = "Modifications enregistrés !";
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class WinnersListController extends Controller
|
|||
]
|
||||
];
|
||||
|
||||
$settings = Settings::find(1);
|
||||
$settings = app(Settings::class);
|
||||
if ($settings->use_ean_codes === 1) {
|
||||
$fields['orderLine'][] = [
|
||||
'fieldName' => 'code_on_pack',
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class re7Controller extends Controller
|
|||
|
||||
public function teaser()
|
||||
{
|
||||
$settings = Settings::find(1)->select('start_date', 'end_date', 'activated_teaser', 'teaser_end_activity')->first();
|
||||
$settings = app(Settings::class)->select('start_date', 'end_date', 'activated_teaser', 'teaser_end_activity')->first();
|
||||
return view('front.basic.teaser', compact('settings'));
|
||||
}
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ class re7Controller extends Controller
|
|||
|
||||
public function br()
|
||||
{
|
||||
$settings = Settings::find(1);
|
||||
$settings = app(Settings::class);
|
||||
$coupon = $this->getRandomCoupon($settings);
|
||||
$crmCoupon = new Reductions();
|
||||
return view('front.basic.reduction', compact('coupon', 'crmCoupon'));
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class GameCheckDate
|
|||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$settings = Settings::find(1);
|
||||
$settings = app(Settings::class);
|
||||
|
||||
// Check si le teaser est actif
|
||||
if ($settings->start_date > now()) {
|
||||
|
|
|
|||
62
app/Http/Requests/ExportCodesRequest.php
Normal file
62
app/Http/Requests/ExportCodesRequest.php
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Codes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ExportCodesRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder */
|
||||
$codesAvailableToExport = Codes::whereCodeExported(false);
|
||||
$lastExportedId = Codes::whereCodeExported(true)
|
||||
->orderBy('id', 'desc')->first()->id ?? null;
|
||||
if ($lastExportedId) {
|
||||
$codesAvailableToExport = $codesAvailableToExport
|
||||
->where('id', '>', $lastExportedId);
|
||||
}
|
||||
$this->merge([
|
||||
'available_export' => $codesAvailableToExport->count()
|
||||
]);
|
||||
// ? Is auth and super admin, also is json ?
|
||||
return auth()->check() and
|
||||
auth()->user()->role === 1 and $this->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'nb_code_fic' => 'required|integer|min:1',
|
||||
'nb_code_tot' => 'required|integer|min:1',
|
||||
'nb_code_ligne' => 'required|integer|min:1',
|
||||
'available_export' => 'required|integer|gte:nb_code_tot'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'nb_code_fic' => 'Nombre total de codes à exporter',
|
||||
'nb_code_tot' => 'Nombre de codes par fichier',
|
||||
'nb_code_ligne' => 'Nombre de codes par ligne',
|
||||
'available_export' => 'Nombre de codes restant à exporté(s)'
|
||||
];
|
||||
}
|
||||
}
|
||||
32
app/Http/Requests/GenerateCodesRequest.php
Normal file
32
app/Http/Requests/GenerateCodesRequest.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class GenerateCodesRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
// ? Is auth and super admin
|
||||
return auth()->check() and auth()->user()->role === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'quantity' => 'required|integer|min:1',
|
||||
'code_length' => 'required|integer|min:1',
|
||||
];
|
||||
}
|
||||
}
|
||||
62
app/Http/Requests/ParticipateRequest.php
Normal file
62
app/Http/Requests/ParticipateRequest.php
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Codes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\Serial\Exceptions\SerialCasterException;
|
||||
|
||||
class ParticipateRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
$this->merge([
|
||||
'code' => is_string($this->code) ? Str::upper($this->code) : $this->code,
|
||||
'accept_rules' => $this->accept_rules ? true : false
|
||||
]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'accept_rules' => [
|
||||
'required', 'boolean',
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
if (!$value) {
|
||||
$fail('Pour participer, vous devez accepter le règlement du jeu.');
|
||||
}
|
||||
}
|
||||
],
|
||||
'code' => [
|
||||
'required', 'string',
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
try {
|
||||
$int = Codes::serialToInt($value);
|
||||
if (!Codes::whereId(Codes::serialToInt($value))->exists()) {
|
||||
throw new SerialCasterException();
|
||||
}
|
||||
} catch (SerialCasterException $e) {
|
||||
dd($e);
|
||||
Log::debug($e->getMessage(), $e->getTrace());
|
||||
$fail('Code incorrect, veuillez réessayer.');
|
||||
}
|
||||
}
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -5,13 +5,13 @@ namespace App\Jobs;
|
|||
use App\Mail\ExportCodesUniques;
|
||||
use App\Mail\JobFailed;
|
||||
use App\Models\Codes;
|
||||
use App\Models\Settings;
|
||||
use Exception;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class ProcessExportCodesUniques implements ShouldQueue
|
||||
|
|
@ -21,14 +21,51 @@ class ProcessExportCodesUniques implements ShouldQueue
|
|||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
private $nbCodeFic, $nbCodeTot, $nbCodeLigne;
|
||||
/**
|
||||
* The number of seconds the job can run before timing out.
|
||||
*
|
||||
* 7200 seconds (2 hours)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $timeout = 7200;
|
||||
|
||||
/**
|
||||
* Nombre de codes par fichiers.
|
||||
* @var integer
|
||||
*/
|
||||
private $nbCodeFic;
|
||||
|
||||
/**
|
||||
* Nombre total de codes à exporter.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $nbCodeTot;
|
||||
|
||||
/**
|
||||
* Nombre de codes par ligne.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $nbCodeLigne;
|
||||
|
||||
/**
|
||||
* The export file name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $exportFileName = null;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param integer $nbCodeFic Nombre de codes par fichiers.
|
||||
* @param integer $nbCodeTot Nombre total de codes à exporter.
|
||||
* @param integer $nbCodeLigne Nombre de codes par ligne.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($nbCodeFic, $nbCodeTot, $nbCodeLigne)
|
||||
public function __construct(int $nbCodeFic, int $nbCodeTot, int $nbCodeLigne)
|
||||
{
|
||||
$this->nbCodeFic = $nbCodeFic;
|
||||
$this->nbCodeTot = $nbCodeTot;
|
||||
|
|
@ -42,108 +79,134 @@ class ProcessExportCodesUniques implements ShouldQueue
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
$nbCodeFic = $this->nbCodeFic; // Nombre de code par fichier
|
||||
$nbCodeTot = $this->nbCodeTot; // Nombre total de code à exporter
|
||||
$nbCodeLigne = $this->nbCodeLigne; // Nombre de code par ligne
|
||||
|
||||
$totalExportedCodes = 0;
|
||||
$currentFilename = 1;
|
||||
$currentExportedCodes = 0;
|
||||
$currentLineCodes = ($nbCodeLigne === 1 ? 1 : 0);
|
||||
$this->exportFileName = sprintf(
|
||||
'CodesUniques_%s',
|
||||
date('dmY_His')
|
||||
);
|
||||
|
||||
$this->process($nbCodeFic, $nbCodeTot, $nbCodeLigne, $totalExportedCodes, $currentFilename, $currentExportedCodes, $currentLineCodes);
|
||||
$lastExportedCodeId = Codes::whereCodeExported(true)
|
||||
->orderBy('id', 'desc')->first()->id ?? null;
|
||||
|
||||
// Compression des fichiers
|
||||
$filesPath = $this->generateCsvFiles($lastExportedCodeId);
|
||||
|
||||
// * Compression des fichiers.
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open(storage_path('export_codes_uniques/') . "CodesUniques_" . date('dmY') . ".zip", \ZipArchive::CREATE) === true) {
|
||||
if ($handle = opendir(storage_path('export_codes_uniques/tmp'))) {
|
||||
while (false !== ($file_to_zip = readdir($handle))) {
|
||||
if (pathinfo($file_to_zip, PATHINFO_EXTENSION) != 'csv') {
|
||||
continue;
|
||||
}
|
||||
$zip->addFile(storage_path('export_codes_uniques/tmp/') . $file_to_zip, "$file_to_zip");
|
||||
if (
|
||||
$zip->open(
|
||||
storage_path(sprintf('export_codes_uniques/%s.zip', $this->exportFileName)),
|
||||
\ZipArchive::CREATE
|
||||
) === true
|
||||
) {
|
||||
foreach ($filesPath as $filePath) {
|
||||
if (File::exists($filePath)) {
|
||||
$zip->addFile($filePath, \pathinfo($filePath, \PATHINFO_BASENAME));
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
// On vide le dossier temporaire des fichiers csv
|
||||
if ($handle = opendir(storage_path('export_codes_uniques/tmp'))) {
|
||||
while (false !== ($file_to_zip = readdir($handle))) {
|
||||
if (pathinfo($file_to_zip, PATHINFO_EXTENSION) != 'csv') {
|
||||
continue;
|
||||
}
|
||||
unlink(storage_path('export_codes_uniques/tmp/') . $file_to_zip);
|
||||
// * On vide le dossier temporaire des fichiers csv.
|
||||
foreach ($filesPath as $filePath) {
|
||||
if (File::exists($filePath)) {
|
||||
File::delete($filePath);
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
|
||||
// Envoi de mail à MAIL_ADMIN avec le nom du ZIP "CodesUniques_". date('dmY') .".zip"
|
||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new ExportCodesUniques(Settings::find(1)->name, $nbCodeFic, $nbCodeTot, $nbCodeLigne));
|
||||
// * Envoi de mail à MAIL_ADMIN avec le nom du ZIP "CodesUniques_". date('dmY_His') .".zip".
|
||||
Mail::to(config('mail.MAIL_ADMIN'))
|
||||
->send(new ExportCodesUniques(
|
||||
$this->nbCodeFic,
|
||||
$this->nbCodeTot,
|
||||
$this->nbCodeLigne
|
||||
));
|
||||
}
|
||||
|
||||
private function process($nbCodeFic, $nbCodeTot, $nbCodeLigne, $totalExportedCodes, $currentFilename, $currentExportedCodes, $currentLineCodes, $lastExportedCodeId = null)
|
||||
/**
|
||||
* Generate CSV File using the job parameters
|
||||
*
|
||||
* @param integer|null $lastExportedCodeId
|
||||
* @return array Array of temp files
|
||||
*/
|
||||
private function generateCsvFiles($lastExportedCodeId = null): array
|
||||
{
|
||||
$paginate = config('codes.paginate');
|
||||
$outPaths = [];
|
||||
$totalExportedCodes = 0;
|
||||
$currentFilename = 1;
|
||||
$currentExportedCodes = 0;
|
||||
$currentLineCodes = ($this->nbCodeLigne === 1 ? 1 : 0);
|
||||
|
||||
if ($nbCodeTot < $paginate) {
|
||||
$nbCodeToRetrieve = $nbCodeTot;
|
||||
} else {
|
||||
if ($totalExportedCodes + $paginate > $nbCodeTot) {
|
||||
$nbCodeToRetrieve = $nbCodeTot - $totalExportedCodes;
|
||||
} else {
|
||||
$nbCodeToRetrieve = $paginate;
|
||||
}
|
||||
$paginate = intval(config('codes.paginate', 65535));
|
||||
|
||||
// ! Guess code ids instead of getting thme from base.
|
||||
$codes = [];
|
||||
$id = ($lastExportedCodeId ?? 0) + 1;
|
||||
for ($i = 0; $i < $this->nbCodeTot; $i++) {
|
||||
$codes[] = $id++;
|
||||
}
|
||||
|
||||
if ($lastExportedCodeId === null) {
|
||||
$codes = Codes::where('code_exported', 0)->take($nbCodeToRetrieve)->get();
|
||||
} else {
|
||||
$codes = Codes::where([
|
||||
['code_exported', '=', 0],
|
||||
['id', '>', $lastExportedCodeId]
|
||||
])->take($nbCodeToRetrieve)->get();
|
||||
}
|
||||
|
||||
$countCodes = count($codes);
|
||||
|
||||
$exportedCodesId = [];
|
||||
|
||||
foreach ($codes as $k => $code) {
|
||||
if ($currentExportedCodes < $nbCodeTot) {
|
||||
if ($currentLineCodes === ($nbCodeLigne === 1 ? 1 : $nbCodeLigne - 1)) {
|
||||
file_put_contents(storage_path('export_codes_uniques/tmp/') . $currentFilename . ".csv", $code->code_unique . PHP_EOL, FILE_APPEND);
|
||||
$totalExportedCodes++;
|
||||
$currentExportedCodes++;
|
||||
$currentLineCodes = ($nbCodeLigne === 1 ? 1 : 0);
|
||||
$tempFilePath = \storage_path(\sprintf(
|
||||
'export_codes_uniques/tmp/%s_%s.csv',
|
||||
$this->exportFileName,
|
||||
$currentFilename
|
||||
));
|
||||
$outPaths[] = $tempFilePath;
|
||||
|
||||
foreach ($codes as $code) {
|
||||
if ($currentExportedCodes < $this->nbCodeTot) {
|
||||
if ($currentLineCodes === ($this->nbCodeLigne === 1 ? 1 : $this->nbCodeLigne - 1)) {
|
||||
File::append($tempFilePath, Codes::intToSerial($code) . "\n");
|
||||
$currentLineCodes = ($this->nbCodeLigne === 1 ? 1 : 0);
|
||||
} else {
|
||||
file_put_contents(storage_path('export_codes_uniques/tmp/') . $currentFilename . ".csv", $code->code_unique . ";", FILE_APPEND);
|
||||
$totalExportedCodes++;
|
||||
$currentExportedCodes++;
|
||||
File::append($tempFilePath, Codes::intToSerial($code) . ';');
|
||||
$currentLineCodes++;
|
||||
}
|
||||
} //end if
|
||||
|
||||
array_push($exportedCodesId, $code->id);
|
||||
$lastExportedCodeId = $code->id;
|
||||
$totalExportedCodes++;
|
||||
$currentExportedCodes++;
|
||||
|
||||
if ($currentExportedCodes === $nbCodeFic) {
|
||||
$exportedCodesId[] = $code;
|
||||
|
||||
if ($currentExportedCodes === $this->nbCodeFic) {
|
||||
$currentFilename++;
|
||||
$currentExportedCodes = 0;
|
||||
|
||||
$tempFilePath = \storage_path(\sprintf(
|
||||
'export_codes_uniques/tmp/%s_%s.csv',
|
||||
$this->exportFileName,
|
||||
$currentFilename
|
||||
));
|
||||
$outPaths[] = $tempFilePath;
|
||||
}
|
||||
if ((($k + 1) === $countCodes) && $totalExportedCodes < $nbCodeTot) {
|
||||
// ? Have we reached pagination limit for mass saving ?
|
||||
if (count($exportedCodesId) === $paginate) {
|
||||
Codes::whereIn('id', $exportedCodesId)->update(['code_exported' => 1]);
|
||||
return $this->process($nbCodeFic, $nbCodeTot, $nbCodeLigne, $totalExportedCodes, $currentFilename, $currentExportedCodes, $currentLineCodes, $lastExportedCodeId);
|
||||
$exportedCodesId = [];
|
||||
}
|
||||
if (($k + 1) === $countCodes) {
|
||||
Codes::whereIn('id', $exportedCodesId)->update(['code_exported' => 1]);
|
||||
}
|
||||
}
|
||||
} //end if
|
||||
} //end foreach
|
||||
|
||||
// ? Are there exported codes to save ?
|
||||
if (count($exportedCodesId)) {
|
||||
Codes::whereIn('id', $exportedCodesId)->update(['code_exported' => 1]);
|
||||
}
|
||||
return $outPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of job failure
|
||||
*
|
||||
* @param Exception $exception
|
||||
* @return void
|
||||
*/
|
||||
public function failed(Exception $exception)
|
||||
{
|
||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new JobFailed("ProcessExportCodeUnique", ['message' => $exception->getMessage(), 'trace' => $exception->getTraceAsString()]));
|
||||
Mail::to(config('mail.MAIL_ADMIN'))
|
||||
->send(new JobFailed("ProcessExportCodeUnique", [
|
||||
'message' => $exception->getMessage(),
|
||||
'trace' => $exception->getTraceAsString()
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@ namespace App\Jobs;
|
|||
use App\Mail\CodeGenerationEnd;
|
||||
use App\Mail\JobFailed;
|
||||
use App\Models\Codes;
|
||||
use App\Models\Settings;
|
||||
use Exception;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class ProcessUniqueCode implements ShouldQueue
|
||||
|
|
@ -20,71 +22,107 @@ class ProcessUniqueCode implements ShouldQueue
|
|||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The number of seconds the job can run before timing out.
|
||||
*
|
||||
* 7200 seconds (2 hours)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $timeout = 7200;
|
||||
|
||||
/**
|
||||
* Quantity of code to generate
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $quantity;
|
||||
|
||||
/**
|
||||
* Length of code to generate
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $length;
|
||||
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param integer $quantity
|
||||
* @param integer $length
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($quantity, $length, $settings)
|
||||
public function __construct(int $quantity, int $length)
|
||||
{
|
||||
$this->quantity = $quantity;
|
||||
$this->length = $length;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
* TODO: Mettre tout ce bordel dans une transaction quand les serveur de leurs morts auront été mis à jour Uu.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
set_time_limit(0);
|
||||
for ($ib = 1; $ib <= $this->quantity;) {
|
||||
try {
|
||||
$code = new Codes();
|
||||
$code->code_unique = $this->getCode($this->length);
|
||||
$code->date_creation = now();
|
||||
$code->save();
|
||||
if ($code) {
|
||||
$ib++;
|
||||
}
|
||||
} catch (\PDOException $e) {
|
||||
if (!strpos($e->getMessage(), 'Duplicate entry')) {
|
||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new JobFailed("ProcessUniqueCode", ['message' => $e->getMessage(), 'trace' => $e->getTraceAsString()]));
|
||||
die();
|
||||
}
|
||||
}
|
||||
$settings = app(Settings::class);
|
||||
|
||||
$maxSQLPlaceholders = 65535;
|
||||
|
||||
$insertColumns = collect(DB::getSchemaBuilder()
|
||||
->getColumnListing((new Codes())->getTable()))
|
||||
->filter(function ($name) {
|
||||
// * Ignorer les colonnes avec valeurs par défaut sur la table.
|
||||
return !in_array($name, ['id', 'code_used', 'code_exported']);
|
||||
})->count();
|
||||
|
||||
/**
|
||||
* Nombre d'insertions max sur un seule requète
|
||||
* @var integer $perPage
|
||||
*/
|
||||
$perPage = $maxSQLPlaceholders / $insertColumns;
|
||||
|
||||
/**
|
||||
* Nombre de page totale à insérer.
|
||||
* @var integer $totalPages
|
||||
*/
|
||||
$totalPages = \ceil($this->quantity / $perPage);
|
||||
|
||||
$totalGeneratedInserts = 0;
|
||||
|
||||
for ($currentPage = 1; $currentPage <= $totalPages; $currentPage++) {
|
||||
$inserts = [];
|
||||
$insertToGenerate = min($perPage, $this->quantity - $totalGeneratedInserts);
|
||||
do {
|
||||
$inserts[] = [
|
||||
'date_creation' => now()->format('Y-m-d'),
|
||||
];
|
||||
} while ($totalGeneratedInserts < $this->quantity and --$insertToGenerate);
|
||||
|
||||
// * Mass insert
|
||||
Codes::insert($inserts);
|
||||
|
||||
$totalGeneratedInserts += count($inserts);
|
||||
}
|
||||
// ---- Fin de la génération
|
||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new CodeGenerationEnd($this->quantity, $this->settings));
|
||||
}
|
||||
|
||||
private function getCode($car)
|
||||
{
|
||||
$chaine = "ABCDEFGHJKMNPQRSTUWXYZ123456789"; // Caractères autorisés
|
||||
$valprec = "";
|
||||
$string = "";
|
||||
srand();
|
||||
for ($i = 0; $i < $car;) {
|
||||
$val = $chaine[rand() % strlen($chaine)];
|
||||
if ($val != $valprec) {
|
||||
$string .= $val;
|
||||
$valprec = $val;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
return $string;
|
||||
|
||||
// * Fin de la génération.
|
||||
Mail::to(config('mail.MAIL_ADMIN'))
|
||||
->send(new CodeGenerationEnd($this->quantity, $settings->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of job failure
|
||||
*
|
||||
* @param Exception $exception
|
||||
* @return void
|
||||
*/
|
||||
public function failed(Exception $exception)
|
||||
{
|
||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new JobFailed("ProcessUniqueCode", ['message' => $exception->getMessage(), 'trace' => $exception->getTraceAsString()]));
|
||||
Mail::to(config('mail.MAIL_ADMIN'))
|
||||
->send(new JobFailed("ProcessUniqueCode", [
|
||||
'message' => $exception->getMessage(),
|
||||
'trace' => $exception->getTraceAsString()
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,16 +11,31 @@ class CodeGenerationEnd extends Mailable
|
|||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Number of codes generated
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $quantity;
|
||||
|
||||
/**
|
||||
* The game name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $gameName;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param integer $quantity
|
||||
* @param string $gameName
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($quantity, $settings)
|
||||
public function __construct(int $quantity, string $gameName)
|
||||
{
|
||||
$this->quantity = $quantity;
|
||||
$this->settings = $settings;
|
||||
$this->gameName = $gameName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -30,6 +45,8 @@ class CodeGenerationEnd extends Mailable
|
|||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->subject('Fin de génération des codes uniques')->view('bo.mails.generate-end-email')->with(['quantity' => $this->quantity, 'settings' => $this->settings]);
|
||||
return $this->subject('Fin de génération des codes uniques')
|
||||
->view('bo.mails.generate-end-email')
|
||||
->with(['quantity' => $this->quantity, 'gameName' => $this->gameName]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
|
|
@ -12,16 +13,36 @@ class ExportCodesUniques extends Mailable implements ShouldQueue
|
|||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
private $name, $nbCodeFic, $nbCodeTot, $nbCodeLigne;
|
||||
/**
|
||||
* Nombre de codes par fichiers.
|
||||
* @var integer
|
||||
*/
|
||||
private $nbCodeFic;
|
||||
|
||||
/**
|
||||
* Nombre total de codes à exporter.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $nbCodeTot;
|
||||
|
||||
/**
|
||||
* Nombre de codes par ligne.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $nbCodeLigne;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param integer $nbCodeFic Nombre de codes par fichiers.
|
||||
* @param integer $nbCodeTot Nombre total de codes à exporter.
|
||||
* @param integer $nbCodeLigne Nombre de codes par ligne.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($name, $nbCodeFic, $nbCodeTot, $nbCodeLigne)
|
||||
public function __construct(int $nbCodeFic, int $nbCodeTot, int $nbCodeLigne)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->nbCodeFic = $nbCodeFic;
|
||||
$this->nbCodeTot = $nbCodeTot;
|
||||
$this->nbCodeLigne = $nbCodeLigne;
|
||||
|
|
@ -37,7 +58,7 @@ class ExportCodesUniques extends Mailable implements ShouldQueue
|
|||
$nbCodeFic = $this->nbCodeFic;
|
||||
$nbCodeTot = $this->nbCodeTot;
|
||||
$nbCodeLigne = $this->nbCodeLigne;
|
||||
return $this->subject("Fin de l'export des codes uniques pour " . $this->name)
|
||||
return $this->subject("Fin de l'export des codes uniques pour " . app(Settings::class)->name)
|
||||
->view('bo.mails.export-codes-unique-email', compact('nbCodeFic', 'nbCodeTot', 'nbCodeLigne'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,83 @@
|
|||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Kwaadpepper\Serial\SerialCaster;
|
||||
|
||||
class Codes extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'code_used', 'code_exported',
|
||||
'date_creation'
|
||||
];
|
||||
|
||||
protected $fillable = ['code_unique', 'code_used', 'code_exported', 'date_creation'];
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* Has many Participation relation
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function participations()
|
||||
{
|
||||
return $this->hasMany('App\Models\Participation', 'code_unique_id');
|
||||
return $this->hasMany(Participation::class, 'code_unique_id');
|
||||
}
|
||||
|
||||
// * FUNCTIONS
|
||||
/**
|
||||
* Generate code_unique attribute
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getCodeUniqueAttribute()
|
||||
{
|
||||
if (!$this->id or !\is_integer($this->id) or $this->id < 1) {
|
||||
return null;
|
||||
}
|
||||
return self::intToSerial($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a serial from an int.
|
||||
*
|
||||
* @param integer $int
|
||||
* @return string The serial
|
||||
* @throws SerialCasterException If an error happens du to config.
|
||||
*/
|
||||
public static function intToSerial(int $int): string
|
||||
{
|
||||
return SerialCaster::encode(
|
||||
$int,
|
||||
\abs(\crc32(config('app.key'))),
|
||||
app(Settings::class)->code_length,
|
||||
config('codes.codeCharList')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a serial from an int.
|
||||
*
|
||||
* @param string $serial
|
||||
* @return integer The ID represented
|
||||
* @throws SerialCasterException If an error happens due to config or wrong serial is given.
|
||||
*/
|
||||
public static function serialToInt(string $serial): int
|
||||
{
|
||||
return SerialCaster::decode(
|
||||
$serial,
|
||||
\abs(\crc32(config('app.key'))),
|
||||
config('codes.codeCharList')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,11 +34,18 @@ class AppServiceProvider extends ServiceProvider
|
|||
|
||||
setlocale(LC_TIME, config('app.locale') . "_" . strtoupper(config('app.locale')) . '.utf8');
|
||||
|
||||
app()->singleton(Settings::class, function () {
|
||||
if (!($settings = Settings::find(1))) {
|
||||
throw new \ErrorException('Settings not found in DB');
|
||||
}
|
||||
return $settings;
|
||||
});
|
||||
|
||||
if (!app()->runningInConsole()) {
|
||||
// On ramène le nom du jeu et le nom de la société sur toute les pages
|
||||
$settingsGlobal = Cache::get('settingsGlobal');
|
||||
if (!$settingsGlobal) {
|
||||
$settingsGlobal = Settings::find(1)->select('name', 'company', 'analytics', 'start_date', 'end_date')->first();
|
||||
$settingsGlobal = app(Settings::class)->select('name', 'company', 'analytics', 'start_date', 'end_date')->first();
|
||||
Cache::put('settingsGlobal', $settingsGlobal);
|
||||
}
|
||||
View::share('settingsGlobal', $settingsGlobal);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"fideloper/proxy": "^4.2",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"kwaadpepper/serial-int-caster": "^1.0",
|
||||
"laravel/framework": "^7.24",
|
||||
"laravel/tinker": "^2.0",
|
||||
"laravel/ui": "2.4"
|
||||
|
|
|
|||
82
composer.lock
generated
82
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "556b0ac601a71abe129f7ed12da116f6",
|
||||
"content-hash": "a1071d5ef8b5a8f12e458a6866973b27",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asm89/stack-cors",
|
||||
|
|
@ -765,6 +765,50 @@
|
|||
},
|
||||
"time": "2021-04-26T09:17:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kwaadpepper/serial-int-caster",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Kwaadpepper/serial-int-caster.git",
|
||||
"reference": "bbba003ff5379576f05114386b5ebe8b33bc4705"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Kwaadpepper/serial-int-caster/zipball/bbba003ff5379576f05114386b5ebe8b33bc4705",
|
||||
"reference": "bbba003ff5379576f05114386b5ebe8b33bc4705",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"squizlabs/php_codesniffer": "^3.6"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Kwaadpepper\\Serial\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jérémy Munsch",
|
||||
"email": "github@jeremydev.ovh"
|
||||
}
|
||||
],
|
||||
"description": "Convert int To as serial number and reverse",
|
||||
"support": {
|
||||
"issues": "https://github.com/Kwaadpepper/serial-int-caster/issues",
|
||||
"source": "https://github.com/Kwaadpepper/serial-int-caster/tree/1.0.1"
|
||||
},
|
||||
"time": "2021-05-16T15:50:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v7.30.4",
|
||||
|
|
@ -7351,32 +7395,32 @@
|
|||
},
|
||||
{
|
||||
"name": "slevomat/coding-standard",
|
||||
"version": "7.0.13",
|
||||
"version": "7.0.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slevomat/coding-standard.git",
|
||||
"reference": "122a9bf9a4a2195f74100f47dfb8375982f43cc9"
|
||||
"reference": "cc80e59f9b4ca642f02dc1b615c37a9afc2a0f80"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/122a9bf9a4a2195f74100f47dfb8375982f43cc9",
|
||||
"reference": "122a9bf9a4a2195f74100f47dfb8375982f43cc9",
|
||||
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/cc80e59f9b4ca642f02dc1b615c37a9afc2a0f80",
|
||||
"reference": "cc80e59f9b4ca642f02dc1b615c37a9afc2a0f80",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
|
||||
"php": "^7.1 || ^8.0",
|
||||
"phpstan/phpdoc-parser": "0.5.1 - 0.5.5",
|
||||
"phpstan/phpdoc-parser": "0.5.1 - 0.5.6",
|
||||
"squizlabs/php_codesniffer": "^3.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phing/phing": "2.16.4",
|
||||
"php-parallel-lint/php-parallel-lint": "1.3.0",
|
||||
"phpstan/phpstan": "0.12.93",
|
||||
"phing/phing": "2.17.0",
|
||||
"php-parallel-lint/php-parallel-lint": "1.3.1",
|
||||
"phpstan/phpstan": "0.12.98",
|
||||
"phpstan/phpstan-deprecation-rules": "0.12.6",
|
||||
"phpstan/phpstan-phpunit": "0.12.21",
|
||||
"phpstan/phpstan-strict-rules": "0.12.10",
|
||||
"phpunit/phpunit": "7.5.20|8.5.5|9.5.7"
|
||||
"phpstan/phpstan-phpunit": "0.12.22",
|
||||
"phpstan/phpstan-strict-rules": "0.12.11",
|
||||
"phpunit/phpunit": "7.5.20|8.5.5|9.5.9"
|
||||
},
|
||||
"type": "phpcodesniffer-standard",
|
||||
"extra": {
|
||||
|
|
@ -7396,7 +7440,7 @@
|
|||
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
|
||||
"support": {
|
||||
"issues": "https://github.com/slevomat/coding-standard/issues",
|
||||
"source": "https://github.com/slevomat/coding-standard/tree/7.0.13"
|
||||
"source": "https://github.com/slevomat/coding-standard/tree/7.0.15"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -7408,20 +7452,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-07-29T14:30:22+00:00"
|
||||
"time": "2021-09-09T10:29:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "squizlabs/php_codesniffer",
|
||||
"version": "3.6.0",
|
||||
"version": "3.6.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
|
||||
"reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625"
|
||||
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
|
||||
"reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625",
|
||||
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
|
||||
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -7464,7 +7508,7 @@
|
|||
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
|
||||
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
|
||||
},
|
||||
"time": "2021-04-09T00:54:41+00:00"
|
||||
"time": "2021-12-12T21:44:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'paginate' => env('CODE_PAGINATE', 65530)
|
||||
// Export pagination.
|
||||
'paginate' => env('CODE_PAGINATE', 65530),
|
||||
|
||||
// Dictionnary of chars to use fo generating unique codes.
|
||||
'codeCharList' => 'ABCDEFGHJKMNPQRSTUWXYZ123456789',
|
||||
// Code length.
|
||||
'codeLength' => 8
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class RemoveCodeUniqueFromCodes extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('codes', function (Blueprint $table) {
|
||||
$table->dropColumn('code_unique');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('codes', function (Blueprint $table) {
|
||||
$table->string('code_unique')->unique();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddCodeLengthToSettingsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->smallInteger('code_length')
|
||||
->default(config('codes.codeLength'))->after('nb_unique_code_use');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropColumn('code_length');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,10 @@
|
|||
@section('content')
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
Gestion des codes uniques
|
||||
{{ __('Gestion des codes uniques') }}
|
||||
<!-- Button modal -->
|
||||
<button type="button" class="btn btn-sm btn-success float-right" data-toggle="modal" data-target="#exportModal">
|
||||
<i class="fas fa-file-export"></i> Export
|
||||
<i class="fas fa-file-export"></i> {{ __('Export') }}
|
||||
</button>
|
||||
|
||||
<!-- Modal -->
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exportModalLabel">Export des codes uniques</h5>
|
||||
<h5 class="modal-title" id="exportModalLabel">{{ __('Export des codes uniques') }}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
|
@ -23,21 +23,21 @@
|
|||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="form-group form-row">
|
||||
<label class="col-form-label col" for="nb_code_tot">Nombre total de codes à exporter</label>
|
||||
<label class="col-form-label col" for="nb_code_tot">{{ __('Nombre total de codes à exporter') }}</label>
|
||||
<input type="number" name="nb_code_tot" id="nb_code_tot" class="form-control col" required>
|
||||
</div>
|
||||
<div class="form-group form-row">
|
||||
<label class="col-form-label col" for="nb_code_fic">Nombre de codes par fichier</label>
|
||||
<label class="col-form-label col" for="nb_code_fic">{{ __('Nombre de codes par fichier') }}</label>
|
||||
<input type="number" name="nb_code_fic" id="nb_code_fic" class="form-control col" required>
|
||||
</div>
|
||||
<div class="form-group form-row">
|
||||
<label class="col-form-label col" for="nb_code_ligne">Nombre de codes par ligne</label>
|
||||
<label class="col-form-label col" for="nb_code_ligne">{{ __('Nombre de codes par ligne') }}</label>
|
||||
<input type="number" name="nb_code_ligne" id="nb_code_ligne" class="form-control col" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Fermer</button>
|
||||
<button type="submit" class="btn btn-sm btn-success">Lancer l'export</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">{{ __('Fermer') }}</button>
|
||||
<button type="submit" class="btn btn-sm btn-success">{{ __('Lancer l\'export') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -48,38 +48,61 @@
|
|||
<form action="{{route('bo.codes')}}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="card-body">
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
@if (session('success'))
|
||||
<div class="alert alert-success">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
<p>Nombre de code(s)</p>
|
||||
<p>{{__('Nombre de code(s)') }}</p>
|
||||
<ul>
|
||||
<li>en base : {{$nbCodeBase}}</li>
|
||||
<li>utilisé(s) : {{$nbCodeUsed}}</li>
|
||||
<li>déjà exporté(s) : {{ $nbCodeExported }}</li>
|
||||
<li>restant à exporté(s) : {{$nbCodeRemainingToExport}}</li>
|
||||
<li>{{ __('en base') }} : {{$nbCodeBase}}</li>
|
||||
<li>{{ __('utilisé(s)') }} : {{$nbCodeUsed}}</li>
|
||||
<li>{{ __('déjà exporté(s)') }} : {{ $nbCodeExported }}</li>
|
||||
<li>{{ __('restant à exporté(s)') }} : {{$nbCodeRemainingToExport}}</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<div class="form-group form-row">
|
||||
<label class="col-form-label text-center col">Nombre de codes à générer <span class="required-asterisk">*</span></label>
|
||||
<label class="col-form-label text-center col">{{ __('Nombre de codes à générer') }} <span class="required-asterisk">*</span></label>
|
||||
<input class="form-control col" type="number" name="quantity" min="0">
|
||||
<label class="col-form-label text-center col">Longueur des codes <span class="required-asterisk">*</span></label>
|
||||
<input class="form-control col" type="number" name="code_length" min="0">
|
||||
<label class="col-form-label text-center col">{{__('Longueur des codes') }} <span class="required-asterisk">*</span></label>
|
||||
<input id="codeLengthInput" class="form-control col" type="number" name="code_length" min="0" value="{{ $settings->code_length ?? config('codes.codeLength') }}">
|
||||
</div>
|
||||
<small >{{ __('Il est possible de générer') }} <span id="maxCodes" class="text-danger">0</span> {{ __('codes uniques.') }}</small><br>
|
||||
<small class="text-muted">{{ __('!! Si la longueur des codes est changé l\'export pourra prendre plus de temps. !!') }}</small>
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
<button type="submit" class="btn btn-success"><i class="fas fa-cog"></i> Générer</button>
|
||||
<button type="submit" class="btn btn-success"><i class="fas fa-cog"></i> {{ __('Générer') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
let codeLenghtInput = document.getElementById('codeLengthInput'),
|
||||
smallWarning = document.getElementById('maxCodes')
|
||||
|
||||
/**
|
||||
* Fonction factorielle
|
||||
*/
|
||||
let fact = (nbr) => {
|
||||
let i, f = 1
|
||||
for(i = 1; i <= nbr; i++)
|
||||
{
|
||||
f = f * i; // ou f *= i;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
let calculateMax = () => {
|
||||
let p = Number.parseInt({{ strlen(config('codes.codeCharList')) }}),
|
||||
n = codeLenghtInput.value
|
||||
return Math.pow(p, n)-1 - Number.parseInt({{ $nbCodeBase }});
|
||||
}
|
||||
let numberWithCommas = (x) => {
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
smallWarning.innerText = numberWithCommas(calculateMax())
|
||||
|
||||
codeLenghtInput.addEventListener('input', () => {
|
||||
smallWarning.innerText = numberWithCommas(calculateMax())
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
|
|||
|
|
@ -48,4 +48,4 @@
|
|||
console.error( error );
|
||||
} );
|
||||
</script>
|
||||
@endsection
|
||||
@endpush
|
||||
|
|
|
|||
|
|
@ -51,4 +51,4 @@
|
|||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@endpush
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
<p>Génération des {{$quantity}} codes uniques terminés sur le jeu {{$settings->name}}.</p>
|
||||
<p>Génération des {{$quantity}} codes uniques terminés sur le jeu {{$gameName}}.</p>
|
||||
|
|
|
|||
|
|
@ -72,12 +72,24 @@
|
|||
<td>
|
||||
<label class="col-form-label" for="nb_unique_code_use">
|
||||
Nombre d'utilisation du code unique <span class="required-asterisk">*</span><br/>
|
||||
<small class="text-muted">{{ __('Nombre d\'utilisations possible au total d\'un code unique.') }}</small>
|
||||
</label>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<input class="form-control" type="number" name="nb_unique_code_use" value="{{$settings->nb_unique_code_use}}" required>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="form-group">
|
||||
<td>
|
||||
<label class="col-form-label" for="code_length">
|
||||
{{ __('Longueur des code uniques') }} <span class="required-asterisk">*</span><br/>
|
||||
<small class="text-muted">{{ __('!! Cette valeur ne doit pas varier en cour de jeu !!') }}</small>
|
||||
</label>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<input class="form-control" type="number" name="code_length" value="{{$settings->code_length}}" readonly>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="form-group">
|
||||
<td>
|
||||
<label class="col-form-label" for="ean_codes">
|
||||
|
|
@ -334,7 +346,7 @@
|
|||
</div>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
@push('scripts')
|
||||
<script type="text/javascript" defer>
|
||||
|
||||
// Gestion du tableau pour reduction
|
||||
|
|
@ -382,4 +394,4 @@
|
|||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@endpush
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue