feat: added archive for stats
This commit is contained in:
parent
22bb989ed6
commit
b3a7f6043f
16 changed files with 820 additions and 6 deletions
49
app/Console/Commands/ArchiveStatsCommand.php
Normal file
49
app/Console/Commands/ArchiveStatsCommand.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Jobs\ArchiveStatsJob;
|
||||
use App\Models\ArchiveSite;
|
||||
use App\Models\ArchiveStat;
|
||||
use App\Statistique;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ArchiveStatsCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'uwil:stats:archive';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Archives mesbr stats';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$baseArchiveStatCount = ArchiveStat::count();
|
||||
$baseStatCount = Statistique::count();
|
||||
|
||||
(new ArchiveStatsJob())->handle();
|
||||
|
||||
$this->info(sprintf(
|
||||
'%s archive(s) created',
|
||||
ArchiveStat::count() - $baseArchiveStatCount
|
||||
));
|
||||
$this->info(sprintf(
|
||||
'%s stat(s) deleted',
|
||||
$baseStatCount - Statistique::count()
|
||||
));
|
||||
$this->info('Stats archived 👌');
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ use Illuminate\Console\Scheduling\Schedule;
|
|||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
use App\Site;
|
||||
use App\Campagne;
|
||||
use App\Jobs\ArchiveStatsJob;
|
||||
use App\Jobs\CleanOldDatasJob;
|
||||
use App\User;
|
||||
use App\Notification;
|
||||
|
|
@ -35,6 +36,9 @@ class Kernel extends ConsoleKernel
|
|||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
// Archive stats every day at 2:00 AM (to prevent time difference between the server and the reality).
|
||||
$schedule->job(ArchiveStatsJob::class)->dailyAt('2:00');
|
||||
|
||||
// Clean datas older than 3 years every day at midnight.
|
||||
$schedule->job(CleanOldDatasJob::class)->daily();
|
||||
|
||||
|
|
|
|||
67
app/Jobs/ArchiveStatsJob.php
Normal file
67
app/Jobs/ArchiveStatsJob.php
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\ArchiveStat;
|
||||
use App\Statistique;
|
||||
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\Log;
|
||||
|
||||
class ArchiveStatsJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithQueue;
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Construct method.
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
try {
|
||||
DB::transaction(function () {
|
||||
Statistique::query()
|
||||
->where('date', '<', now())
|
||||
->each(function ($stat) {
|
||||
$archiveStat = new ArchiveStat();
|
||||
$archiveStat->quantity = $stat->stat_couponPrinted;
|
||||
$archiveStat->date = $stat->date;
|
||||
$archiveStat->archive_coupon_id = $stat->stat_couponId;
|
||||
$archiveStat->archive_campaign_id = $stat->stat_campId;
|
||||
$archiveStat->saveOrFail();
|
||||
});
|
||||
|
||||
Statistique::query()
|
||||
->where('date', '<', now())
|
||||
->delete();
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
Log::error(
|
||||
sprintf(
|
||||
"ArchiveStatsJob failed - Code : %s - %s",
|
||||
$e->getCode(),
|
||||
$e->getMessage(),
|
||||
)
|
||||
);
|
||||
\report($e);
|
||||
} //end try
|
||||
}
|
||||
}
|
||||
104
app/Lib/Helpers/ToolboxHelper.php
Normal file
104
app/Lib/Helpers/ToolboxHelper.php
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
namespace App\Lib\Helpers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
|
||||
class ToolboxHelper
|
||||
{
|
||||
/**
|
||||
* Mutltibyte string replace.
|
||||
*
|
||||
* @param array|string $search
|
||||
* @param array|string $replace
|
||||
* @param array|string $subject
|
||||
* @param integer $count
|
||||
* @return array|string|false
|
||||
*/
|
||||
public static function mbReplace(
|
||||
$search,
|
||||
$replace,
|
||||
$subject,
|
||||
int &$count = 0
|
||||
) {
|
||||
if (!is_array($search) && is_array($replace)) {
|
||||
return false;
|
||||
}
|
||||
if (is_array($subject)) {
|
||||
// Call mb_replace for each single string in $subject .
|
||||
foreach ($subject as &$string) {
|
||||
$string = &self::mbReplace($search, $replace, $string, $count);
|
||||
}
|
||||
} elseif (is_array($search)) {
|
||||
if (!is_array($replace)) {
|
||||
foreach ($search as &$string) {
|
||||
$subject = self::mbReplace($string, $replace, $subject, $count);
|
||||
}
|
||||
} else {
|
||||
$n = max(count($search), count($replace));
|
||||
while ($n--) {
|
||||
$subject = self::mbReplace(current($search), current($replace), $subject, $count);
|
||||
next($search);
|
||||
next($replace);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$parts = mb_split(preg_quote($search), $subject);
|
||||
$count = count($parts) - 1;
|
||||
$subject = implode($replace, $parts);
|
||||
} //end if
|
||||
return $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the field is unique.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $field
|
||||
* @param string|integer|float|boolean|null|array $value
|
||||
* @param integer|null $id
|
||||
* @param callable|null $query
|
||||
* @return void
|
||||
* @throws \Illuminate\Validation\ValidationException If the field is not unique.
|
||||
*/
|
||||
public static function assertFieldIsUnique(
|
||||
string $table,
|
||||
string $field,
|
||||
$value,
|
||||
?int $id = null,
|
||||
?callable $query = null
|
||||
): void {
|
||||
if (!$query) {
|
||||
Validator::make([$field => $value], [
|
||||
self::mbReplace('.', '\.', $field) => Rule::unique($table, $field)->ignore($id),
|
||||
], [
|
||||
self::mbReplace('.', '\.', "{$field}.unique")
|
||||
=> trans('crud.libs.toolbox.assertFieldIsUnique', ['attribute' => $field, 'value' => $value])
|
||||
])->validate();
|
||||
return;
|
||||
}
|
||||
Validator::make([$field => $value], [
|
||||
$field => Rule::unique($table)->where($query)->ignore($id),
|
||||
], [
|
||||
$field . '.unique' => trans(
|
||||
'crud.libs.toolbox.assertFieldIsUnique',
|
||||
['attribute' => $field, 'value' => $value]
|
||||
)
|
||||
])->validate();
|
||||
}
|
||||
}
|
||||
82
app/Models/ArchiveCampaign.php
Normal file
82
app/Models/ArchiveCampaign.php
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Site;
|
||||
use App\Traits\HasUniqueField;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property string $name Name of the archived campaign.
|
||||
* @property string $campaign_id Id of the archived campaign.
|
||||
* @property-read \Carbon\Carbon $created_at Created date.
|
||||
* @property-read \Carbon\Carbon $updated_at Updated date.
|
||||
*
|
||||
* @property-read \App\Models\ArchiveStat $archiveStat ArchiveStat Has many relationship.
|
||||
* @property-read \App\Models\ArchiveSite $archiveSite ArchiveSite Belongs to relationship.
|
||||
*/
|
||||
class ArchiveCampaign extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use HasUniqueField;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'campaign_id',
|
||||
'archive_site_id'
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
$model->assertFieldIsUnique('campaign_id', $model->campaign_id);
|
||||
$site = Site::query()->where('site_id', $model->archive_site_id)->firstOrFail();
|
||||
$archiveSite = ArchiveSite::query()->firstOrCreate(
|
||||
[
|
||||
'site_id' => $model->archive_site_id
|
||||
],
|
||||
[
|
||||
'name' => $site->site_nom
|
||||
]
|
||||
);
|
||||
$model->archiveSite()->associate($archiveSite);
|
||||
});
|
||||
static::updating(function () {
|
||||
throw new \RuntimeException('Updating an archived campaign is not authorized');
|
||||
});
|
||||
static::deleting(function () {
|
||||
throw new \RuntimeException('Deleting an archived campaign is not authorized');
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* ArchiveSite model relation
|
||||
* @return Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function archiveSite()
|
||||
{
|
||||
return $this->belongsTo(ArchiveSite::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArchiveSite model relation
|
||||
* @return Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function archiveStat()
|
||||
{
|
||||
return $this->hasMany(ArchiveStat::class);
|
||||
}
|
||||
}
|
||||
60
app/Models/ArchiveCoupon.php
Normal file
60
app/Models/ArchiveCoupon.php
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\HasUniqueField;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property string $name Name of the archived coupon.
|
||||
* @property string $coupon_code Treatment code of the archived coupon.
|
||||
* @property-read \Carbon\Carbon $created_at Created date.
|
||||
* @property-read \Carbon\Carbon $updated_at Updated date.
|
||||
*
|
||||
* @property-read \App\Models\ArchiveStat $archiveStat ArchiveStat Has many relationship.
|
||||
*/
|
||||
class ArchiveCoupon extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use HasUniqueField;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'coupon_code',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
$model->assertFieldIsUnique('coupon_code', $model->coupon_code);
|
||||
});
|
||||
static::updating(function () {
|
||||
throw new \RuntimeException('Updating an archived coupon is not authorized');
|
||||
});
|
||||
static::deleting(function () {
|
||||
throw new \RuntimeException('Deleting an archived coupon is not authorized');
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* ArchiveStat model relation
|
||||
* @return Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function archiveStat()
|
||||
{
|
||||
return $this->hasMany(ArchiveStat::class);
|
||||
}
|
||||
}
|
||||
60
app/Models/ArchiveSite.php
Normal file
60
app/Models/ArchiveSite.php
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\HasUniqueField;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property string $name Name of the archived site.
|
||||
* @property string $site_id Id of the archived site.
|
||||
* @property-read \Carbon\Carbon $created_at Created date.
|
||||
* @property-read \Carbon\Carbon $updated_at Updated date.
|
||||
*
|
||||
* @property-read \App\Models\ArchiveCampaign $archiveCampaign ArchiveCampaign Has many relationship.
|
||||
*/
|
||||
class ArchiveSite extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use HasUniqueField;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'site_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
$model->assertFieldIsUnique('site_id', $model->site_id);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
throw new \RuntimeException('Updating an archived site is not authorized');
|
||||
});
|
||||
static::deleting(function () {
|
||||
throw new \RuntimeException('Deleting an archived site is not authorized');
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* ArchiveCampaign model relation
|
||||
* @return Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function archiveCampaign()
|
||||
{
|
||||
return $this->hasMany(ArchiveCampaign::class);
|
||||
}
|
||||
}
|
||||
91
app/Models/ArchiveStat.php
Normal file
91
app/Models/ArchiveStat.php
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Campagne;
|
||||
use App\Coupon;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $quantity Quantity of distributed coupons.
|
||||
* @property \Carbon\Carbon $date Date when the coupon has been distributed.
|
||||
* @property-read \Carbon\Carbon $created_at Created date.
|
||||
* @property-read \Carbon\Carbon $updated_at Updated date.
|
||||
*
|
||||
* @property-read \App\Models\ArchiveCoupon $archiveCoupon ArchiveCoupon Belongs to relationship.
|
||||
* @property-read \App\Models\ArchiveCampaign $archiveCampaign ArchiveCampaign Belongs to relationship.
|
||||
*/
|
||||
class ArchiveStat extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'date',
|
||||
'quantity',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
$campaign = Campagne::withTrashed()->where('camp_id', $model->archive_campaign_id)->firstOrFail();
|
||||
$archiveCampaign = ArchiveCampaign::query()->firstOrCreate(
|
||||
[
|
||||
'campaign_id' => $model->archive_campaign_id
|
||||
],
|
||||
[
|
||||
'name' => $campaign->camp_name,
|
||||
'archive_site_id' => $campaign->camp_siteId,
|
||||
]
|
||||
);
|
||||
$model->archiveCampaign()->associate($archiveCampaign);
|
||||
|
||||
$coupon = Coupon::withTrashed()->where('coupon_id', $model->archive_coupon_id)->firstOrFail();
|
||||
$archiveCoupon = ArchiveCoupon::query()->firstOrCreate(
|
||||
[
|
||||
'coupon_code' => $model->archive_coupon_id
|
||||
],
|
||||
[
|
||||
'name' => $coupon->coupon_code,
|
||||
]
|
||||
);
|
||||
$model->archiveCoupon()->associate($archiveCoupon);
|
||||
});
|
||||
static::updating(function () {
|
||||
throw new \RuntimeException('Upating an archived stat is not authorized');
|
||||
});
|
||||
static::deleting(function () {
|
||||
throw new \RuntimeException('Deleting an archived stat is not authorized');
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* ArchiveCoupon model relation
|
||||
* @return Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function archiveCoupon()
|
||||
{
|
||||
return $this->belongsTo(ArchiveCoupon::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArchiveCampaign model relation
|
||||
* @return Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function archiveCampaign()
|
||||
{
|
||||
return $this->belongsTo(ArchiveCampaign::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -25,9 +25,37 @@ class Statistique extends Model
|
|||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
protected $fillable = [
|
||||
'stat_campId',
|
||||
'stat_couponId',
|
||||
'stat_couponPrinted'
|
||||
'stat_couponPrinted',
|
||||
'date'
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'date' => 'date'
|
||||
];
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* ArchiveCoupon model relation
|
||||
* @return Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function campaign()
|
||||
{
|
||||
return $this->belongsTo(Campagne::class, 'stat_campId', 'camp_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* ArchiveCampaign model relation
|
||||
* @return Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function coupon()
|
||||
{
|
||||
return $this->belongsTo(Coupon::class, 'stat_couponId', 'coupon_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use Illuminate\Http\Request;
|
|||
use App\Coupon;
|
||||
use App\Models\PrintedCoupons;
|
||||
use App\Site;
|
||||
use App\Statistique;
|
||||
|
||||
trait GenerateBR
|
||||
{
|
||||
|
|
@ -557,13 +558,22 @@ trait GenerateBR
|
|||
|
||||
imagedestroy($mask);
|
||||
|
||||
// Save stat.
|
||||
$this->saveStat($campagne, $coupon);
|
||||
|
||||
return "data:image/jpeg;base64," . base64_encode($contents);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save 'printed_coupons' line.
|
||||
*
|
||||
* @param Campagne $campagne
|
||||
* @param Customers $customer
|
||||
* @param Coupon $coupon
|
||||
* @return PrintedCoupons
|
||||
*/
|
||||
public function savePrintedCoupon(Campagne $campagne, Customers $customer, Coupon $coupon): PrintedCoupons
|
||||
{
|
||||
// ----- mémorise l'impression
|
||||
$mur = new PrintedCoupons();
|
||||
$mur->camp_id = $campagne->camp_id;
|
||||
$mur->customer_id = $customer->id;
|
||||
|
|
@ -573,8 +583,28 @@ trait GenerateBR
|
|||
return $mur;
|
||||
}
|
||||
|
||||
private function addMarketingDirectCode()
|
||||
/**
|
||||
* Save stats in the 'statistiques' table.
|
||||
*
|
||||
* @param Campagne $campagne
|
||||
* @param Coupon $coupon
|
||||
* @return Statistique
|
||||
*/
|
||||
public function saveStat(Campagne $campagne, Coupon $coupon): Statistique
|
||||
{
|
||||
|
||||
$stat = Statistique::query()->firstOrCreate(
|
||||
[
|
||||
'date' => now()->toDateString(),
|
||||
'stat_campId' => $campagne->camp_id,
|
||||
'stat_couponId' => $coupon->coupon_id,
|
||||
],
|
||||
[
|
||||
'stat_couponPrinted' => 0,
|
||||
]
|
||||
);
|
||||
$stat->stat_couponPrinted += 1;
|
||||
$stat->save();
|
||||
|
||||
return $stat;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
app/Traits/HasUniqueField.php
Normal file
31
app/Traits/HasUniqueField.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use \Illuminate\Support\Str;
|
||||
|
||||
trait HasUniqueField
|
||||
{
|
||||
/**
|
||||
* Asserts using validation that the field is unique
|
||||
*
|
||||
* @param string $field
|
||||
* @param string|null $value
|
||||
* @param integer|null $id
|
||||
* @param string|null $slugField
|
||||
* @return void
|
||||
* @throws \Illuminate\Validation\ValidationException If the given field already exists.
|
||||
*/
|
||||
private function assertFieldIsUnique(string $field, ?string $value = null, ?int $id = null, ?string $slugField = null): void
|
||||
{
|
||||
if (!is_null($value)) {
|
||||
$table = $this->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, $field, $value, $id);
|
||||
|
||||
if (!is_null($slugField)) {
|
||||
ToolboxHelper::assertFieldIsUnique($table, $slugField, Str::slug($value), $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AlterStatistiquesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
DB::transaction(function () {
|
||||
// Added 'date' column (nullable to avoid SQL errors).
|
||||
Schema::table('statistiques', function (Blueprint $table) {
|
||||
$table->date('date')->nullable()->after('stat_couponPrinted');
|
||||
});
|
||||
|
||||
// Fill the previously created column with created_at date.
|
||||
DB::table('statistiques')->update([
|
||||
'date' => DB::raw('DATE(created_at)')
|
||||
]);
|
||||
|
||||
// Remove nullable option.
|
||||
Schema::table('statistiques', function (Blueprint $table) {
|
||||
$table->date('date')->nullable(false)->change();
|
||||
});
|
||||
|
||||
// Create a temp table with only groupped datas.
|
||||
DB::statement('CREATE TEMPORARY TABLE temp_statistiques AS
|
||||
SELECT stat_campId, stat_couponId, date, SUM(stat_couponPrinted) AS quantity
|
||||
FROM statistiques
|
||||
GROUP BY stat_campId, stat_couponId, date');
|
||||
|
||||
// Remove all datas from the origin table.
|
||||
DB::table('statistiques')->truncate();
|
||||
|
||||
// Insert datas from the temp table to the old one.
|
||||
DB::statement('INSERT INTO statistiques (stat_campId, stat_couponId, date, stat_couponPrinted)
|
||||
SELECT stat_campId, stat_couponId, date, quantity FROM temp_statistiques');
|
||||
|
||||
Schema::table('statistiques', function (Blueprint $table) {
|
||||
$table->foreign('stat_campId')->references('camp_id')->on('campagne');
|
||||
$table->foreign('stat_couponId')->references('coupon_id')->on('coupon');
|
||||
$table->unique(['stat_campId', 'stat_couponId', 'date']);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
DB::transaction(function () {
|
||||
Schema::table('statistiques', function (Blueprint $table) {
|
||||
$table->dropColumn('date');
|
||||
$table->dropForeign('statistiques_stat_campid_foreign');
|
||||
$table->dropForeign('statistiques_stat_couponid_foreign');
|
||||
$table->dropUnique('statistiques_stat_campid_stat_couponid_date_unique');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateArchiveSitesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('archive_sites', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->comment('Name of the archived site');
|
||||
$table->string('site_id', 50)->unique()->comment('Id of the archived site');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('archive_sites');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateArchiveCouponsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('archive_coupons', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 500)->comment('Name of the archived coupon');
|
||||
$table->string('coupon_code', 50)->unique()->comment('Treatment code of the archived coupon');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('archive_coupons');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateArchiveCampaignsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('archive_campaigns', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 500)->comment('Name of the archived campaign');
|
||||
$table->unsignedBigInteger('campaign_id')->unique()->comment('Id of the archived campaign');
|
||||
$table->foreignId('archive_site_id')->constrained();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('archive_campaigns');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateArchiveStatsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('archive_stats', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedInteger('quantity')->comment('Quantity of distributed coupons this day');
|
||||
$table->date('date');
|
||||
$table->foreignId('archive_coupon_id')->constrained();
|
||||
$table->foreignId('archive_campaign_id')->constrained();
|
||||
$table->unique(['date', 'archive_coupon_id', 'archive_campaign_id']);
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('archive_stats');
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue