fixed build-report refactored enum status and HasStatusTrait
This commit is contained in:
parent
a7a333fb0f
commit
645929ae4e
33
laravel_app/app/Console/Commands/BuildReports.php
Normal file
33
laravel_app/app/Console/Commands/BuildReports.php
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Models\Project;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class BuildReports extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'smartcane:build-reports';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Command description';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
Project::find(1)->schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,8 +12,8 @@ class Kernel extends ConsoleKernel
|
||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule): void
|
protected function schedule(Schedule $schedule): void
|
||||||
{
|
{
|
||||||
// $schedule->command('invoices:create')->weekdays()->twiceDaily(9,17)->timezone('Europe/Amsterdam');
|
|
||||||
$schedule->command('queue:work --sansdaemon')->everyMinute()->withoutOverlapping();
|
$schedule->command('queue:work --sansdaemon')->everyMinute()->withoutOverlapping();
|
||||||
|
$schedule->command('smartcane:build-reports')->dailyAt('2:00');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
10
laravel_app/app/Enums/Status.php
Normal file
10
laravel_app/app/Enums/Status.php
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
enum Status: string
|
||||||
|
{
|
||||||
|
case Failed = 'failed';
|
||||||
|
case Pending = 'pending';
|
||||||
|
case Success = 'success';
|
||||||
|
}
|
||||||
40
laravel_app/app/Jobs/NullJob.php
Normal file
40
laravel_app/app/Jobs/NullJob.php
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Models\ProjectDownload;
|
||||||
|
use App\Models\ProjectMosaic;
|
||||||
|
use App\Models\ProjectReport;
|
||||||
|
use Illuminate\Bus\Batchable;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
class NullJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Batchable, Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
logger('NullJob construct called');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
logger('NullJob handle called');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Enums\Status;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\ProjectDownload;
|
use App\Models\ProjectDownload;
|
||||||
use Illuminate\Bus\Batchable;
|
use Illuminate\Bus\Batchable;
|
||||||
|
|
@ -50,14 +51,14 @@ public function handle(): void
|
||||||
logger('error', $process->getErrorOutput());
|
logger('error', $process->getErrorOutput());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->download->update(['status' => 'completed']);
|
$this->download->setStatusSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function handleForDate(Project $project, Carbon $date)
|
public static function handleForDate(Project $project, Carbon $date)
|
||||||
{
|
{
|
||||||
$filename = $date->format('Y-m-d') . '.tif';
|
$filename = $date->format('Y-m-d') . '.tif';
|
||||||
if ($project->downloads()->where(['status' => 'completed', 'name' => $filename])->count() > 0) {
|
if ($project->downloads()->statusSuccess()->where(['name' => $filename])->exists()) {
|
||||||
return;
|
return new NullJob();
|
||||||
}
|
}
|
||||||
|
|
||||||
$path = $project->download_path . '/merged_final_tif/' . $filename;
|
$path = $project->download_path . '/merged_final_tif/' . $filename;
|
||||||
|
|
@ -65,7 +66,6 @@ public static function handleForDate(Project $project, Carbon $date)
|
||||||
$project->downloads()->create([
|
$project->downloads()->create([
|
||||||
'name' => $filename,
|
'name' => $filename,
|
||||||
'path' => $path,
|
'path' => $path,
|
||||||
'status' => 'completed',
|
|
||||||
]),
|
]),
|
||||||
$date
|
$date
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Enums\Status;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\ProjectDownload;
|
use App\Models\ProjectDownload;
|
||||||
use App\Models\ProjectMosaic;
|
use App\Models\ProjectMosaic;
|
||||||
|
|
@ -53,6 +54,7 @@ public function handle(): void
|
||||||
$process->setEnv(['PATH' => $currentPath.':/usr/local/Cellar/pandoc/3.1.8/bin/pandoc']);
|
$process->setEnv(['PATH' => $currentPath.':/usr/local/Cellar/pandoc/3.1.8/bin/pandoc']);
|
||||||
// $process->setTimeout(36000); // stel een geschikte timeout in
|
// $process->setTimeout(36000); // stel een geschikte timeout in
|
||||||
$process->start();
|
$process->start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$myOutput = [];
|
$myOutput = [];
|
||||||
$process->wait(function ($type, $buffer) use (&$myOutput) {
|
$process->wait(function ($type, $buffer) use (&$myOutput) {
|
||||||
|
|
@ -61,25 +63,30 @@ public function handle(): void
|
||||||
logger($buffer);
|
logger($buffer);
|
||||||
});
|
});
|
||||||
$this->processOutput = collect($myOutput)->join('\n');
|
$this->processOutput = collect($myOutput)->join('\n');
|
||||||
|
$this->mosaic->setStatusSuccess();
|
||||||
|
|
||||||
} catch (ProcessFailedException $exception) {
|
} catch (ProcessFailedException $exception) {
|
||||||
echo $exception->getMessage();
|
echo $exception->getMessage();
|
||||||
|
$this->mosaic->setStatusFailed();
|
||||||
|
|
||||||
}
|
}
|
||||||
$this->mosaic->update([
|
|
||||||
'status' => 'complete',
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function handleFor(Project $project, $year, $startWeekNumber) {
|
public static function handleFor(Project $project, $year, $startWeekNumber)
|
||||||
if ($project->mosaics()->where(['status' => 'complete', 'year' => $year, 'week' => $startWeekNumber])->count() > 0) {
|
{
|
||||||
return;
|
if ($project->hasInvalidMosaicFor($year, $startWeekNumber)) {
|
||||||
|
return new NullJob();
|
||||||
}
|
}
|
||||||
$mosaic = $project->mosaics()->create([
|
|
||||||
'name' => sprintf('Week %d, %d', $startWeekNumber, $year),
|
$mosaic = $project->mosaics()->updateOrCreate(
|
||||||
'path' => sprintf('%s/%s/%s', $project->download_path, 'mosaics', sprintf('week_%d_%d.tif', $startWeekNumber, $year)),
|
[
|
||||||
'year' => $year,
|
'year' => $year,
|
||||||
'week' => $startWeekNumber,
|
'week' => $startWeekNumber,
|
||||||
'status' => 'pending',
|
],
|
||||||
|
[
|
||||||
|
'name' => sprintf('Week %d, %d', $startWeekNumber, $year),
|
||||||
|
'path' => sprintf('%s/%s/%s', $project->download_path, 'mosaics',
|
||||||
|
sprintf('week_%d_%d.tif', $startWeekNumber, $year)),
|
||||||
]);
|
]);
|
||||||
return new self($mosaic);
|
return new self($mosaic);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Livewire\Forms\MailingForm;
|
||||||
use App\Models\ProjectReport;
|
use App\Models\ProjectReport;
|
||||||
use Illuminate\Bus\Batchable;
|
use Illuminate\Bus\Batchable;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
|
|
@ -18,22 +19,22 @@ class ProjectReportGeneratorJob implements ShouldQueue
|
||||||
|
|
||||||
public $timeout = 220;
|
public $timeout = 220;
|
||||||
private ProjectReport $projectReport;
|
private ProjectReport $projectReport;
|
||||||
|
private bool $sendMail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
*/
|
*/
|
||||||
public function __construct(ProjectReport $projectReport)
|
public function __construct(ProjectReport $projectReport, $sendMail = false)
|
||||||
{
|
{
|
||||||
$this->projectReport = $projectReport;
|
$this->projectReport = $projectReport;
|
||||||
//
|
$this->sendMail = $sendMail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the job.
|
* Execute the job.
|
||||||
*/
|
*/
|
||||||
public function handle(): void
|
public function handle()
|
||||||
{
|
{
|
||||||
logger('in handle');
|
|
||||||
$this->projectReport->weeksAgo();
|
$this->projectReport->weeksAgo();
|
||||||
|
|
||||||
$projectFolder = base_path('../');
|
$projectFolder = base_path('../');
|
||||||
|
|
@ -68,6 +69,19 @@ public function handle(): void
|
||||||
$this->projectReport->setStatusFailed();
|
$this->projectReport->setStatusFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
$this->sendMail();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendMail(): void
|
||||||
|
{
|
||||||
|
if ($this->sendMail && $this->projectReport->statusIsSuccessful()) {
|
||||||
|
logger('sendMail');
|
||||||
|
MailingForm::saveAndSendMailing(
|
||||||
|
$this->projectReport,
|
||||||
|
$this->projectReport->project->mail_subject,
|
||||||
|
$this->projectReport->project->mail_template,
|
||||||
|
$this->projectReport->project->emailRecipients()->get(['email', 'name'])->toArray()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
laravel_app/app/Listeners/UpdateMailingStatus.php
Normal file
28
laravel_app/app/Listeners/UpdateMailingStatus.php
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Models\ProjectMailing;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Events\MessageSent;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
|
||||||
|
class UpdateMailingStatus
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*/
|
||||||
|
public function handle(MessageSent $event): void
|
||||||
|
{
|
||||||
|
ProjectMailing::where('id', $event->data['mailing']['id'])
|
||||||
|
->update(['status' => 'success']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -28,26 +28,30 @@ public function setReport(ProjectReport $report)
|
||||||
$this->subject = $report->project->mail_subject;
|
$this->subject = $report->project->mail_subject;
|
||||||
$this->message = $report->project->mail_template;
|
$this->message = $report->project->mail_template;
|
||||||
$this->recipients = $this->report->project->emailRecipients()->get(['email', 'name'])->toArray();
|
$this->recipients = $this->report->project->emailRecipients()->get(['email', 'name'])->toArray();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save()
|
public function save()
|
||||||
{
|
{
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
self::saveAndSendMailing($this->report, $this->subject, $this->message, $this->recipients);
|
||||||
|
|
||||||
$mailing = $this->report->project->mailings()->create([
|
$this->setReport($this->report);
|
||||||
'subject' => $this->subject,
|
}
|
||||||
'message' => $this->message,
|
|
||||||
|
public static function saveAndSendMailing($report, $subject, $message, $recipients) {
|
||||||
|
$mailing = $report->project->mailings()->create([
|
||||||
|
'subject' => $subject,
|
||||||
|
'message' => $message,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$mailing->attachments()->create([
|
$mailing->attachments()->create([
|
||||||
'name' => $this->report->name,
|
'name' => $report->name,
|
||||||
'path' => $this->report->path,
|
'path' => $report->path,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$mailing->recipients()->createMany($this->recipients);
|
$mailing->recipients()->createMany($recipients);
|
||||||
|
|
||||||
$this->setReport($this->report);
|
|
||||||
|
|
||||||
|
|
||||||
Mail::to($mailing->recipients()->pluck('email')->toArray())
|
Mail::to($mailing->recipients()->pluck('email')->toArray())
|
||||||
->send(new \App\Mail\ReportMailer($mailing));
|
->send(new \App\Mail\ReportMailer($mailing));
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ public function saveMosaic(){
|
||||||
'year' => $this->formData['year'],
|
'year' => $this->formData['year'],
|
||||||
'week' => $this->formData['week'],
|
'week' => $this->formData['week'],
|
||||||
],[
|
],[
|
||||||
'status' => 'pending',
|
|
||||||
'path' => $this->project->getMosaicPath(),
|
'path' => $this->project->getMosaicPath(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ private function resetFormData()
|
||||||
|
|
||||||
public function saveProjectReport()
|
public function saveProjectReport()
|
||||||
{
|
{
|
||||||
sleep(1);
|
|
||||||
$this->validate([
|
$this->validate([
|
||||||
'formData.week' => ['required', 'integer', 'min:1', 'max:53' ],
|
'formData.week' => ['required', 'integer', 'min:1', 'max:53' ],
|
||||||
'formData.year' => 'required|integer|min:2020|max:'.now()->addYear()->year,
|
'formData.year' => 'required|integer|min:2020|max:'.now()->addYear()->year,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ class ReportMailer extends Mailable
|
||||||
public function __construct(ProjectMailing $mailing)
|
public function __construct(ProjectMailing $mailing)
|
||||||
{
|
{
|
||||||
$this->mailing = $mailing;
|
$this->mailing = $mailing;
|
||||||
|
$this->withSwiftMessage(function ($message) use ($mailing) {
|
||||||
|
$message->getHeaders()->addTextHeader('X-Mailing-ID', $mailing->id);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -56,11 +59,18 @@ public function content(): Content
|
||||||
public function attachments(): array
|
public function attachments(): array
|
||||||
{
|
{
|
||||||
return $this->mailing->attachments()->get()->map(function (ProjectMailingAttachment $attachment) {
|
return $this->mailing->attachments()->get()->map(function (ProjectMailingAttachment $attachment) {
|
||||||
|
$mime = 'application/pdf'; // default MIME type
|
||||||
|
$extension = pathinfo($attachment->path, PATHINFO_EXTENSION);
|
||||||
|
|
||||||
|
if ($extension === 'docx') {
|
||||||
|
$mime = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
|
||||||
|
}
|
||||||
|
|
||||||
return Attachment::fromStorage(
|
return Attachment::fromStorage(
|
||||||
path: $attachment->mailing->project->download_path.$attachment->path
|
path: $attachment->mailing->project->download_path."/".$attachment->path
|
||||||
)
|
)
|
||||||
->as($attachment->name)
|
->as($attachment->path)
|
||||||
->withMime('application/pdf');
|
->withMime($mime);
|
||||||
})->toArray();
|
})->toArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
use App\Jobs\ProjectDownloadTiffJob;
|
use App\Jobs\ProjectDownloadTiffJob;
|
||||||
use App\Jobs\ProjectMosiacGeneratorJob;
|
use App\Jobs\ProjectMosiacGeneratorJob;
|
||||||
use App\Jobs\ProjectReportGeneratorJob;
|
use App\Jobs\ProjectReportGeneratorJob;
|
||||||
|
use App\Livewire\Forms\MailingForm;
|
||||||
use Carbon\CarbonPeriod;
|
use Carbon\CarbonPeriod;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
@ -243,12 +244,12 @@ public function getMergedTiffList()
|
||||||
|
|
||||||
public function hasPendingDownload(): bool
|
public function hasPendingDownload(): bool
|
||||||
{
|
{
|
||||||
return $this->downloads()->where('status', 'pending')->count() > 0;
|
return $this->downloads()->statusPending()->count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasPendingMosaic(): bool
|
public function hasPendingMosaic(): bool
|
||||||
{
|
{
|
||||||
return $this->mosaics()->where('status', 'pending')->count() > 0;
|
return $this->mosaics()->statusPending()->count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function startDownload(Carbon $date)
|
public function startDownload(Carbon $date)
|
||||||
|
|
@ -260,29 +261,69 @@ public function startDownload(Carbon $date)
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'path' => sprintf('%s/%s/%s.tif', $this->download_path, 'merged_final_tif', $date->format('Y-m-d')),
|
'path' => sprintf('%s/%s/%s.tif', $this->download_path, 'merged_final_tif', $date->format('Y-m-d')),
|
||||||
'status' => 'pending',
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
ProjectDownloadTiffJob::dispatch($downloadRequest, $date);
|
ProjectDownloadTiffJob::dispatch($downloadRequest, $date);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scheduleReport($year, $week)
|
public function schedule()
|
||||||
{
|
{
|
||||||
// if ($this->reports()->where(['year' => $year, 'week' => $week])->count() > 0) {
|
if ($this->shouldSchedule()) {
|
||||||
// return;
|
$this->scheduleReport();
|
||||||
// }
|
}
|
||||||
|
$this->mail_frequency = 'weekly';
|
||||||
|
$this->mail_day = 'friday';
|
||||||
|
$this->scheduleReport();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldSchedule(): bool
|
||||||
|
{
|
||||||
|
if (strtolower($this->mail_day) === strtolower(now()->englishDayOfWeek)) {
|
||||||
|
return strtolower($this->mail_frequency) === 'weekly' || now()->day <= 7;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasInvalidMosaicFor($year, $week): bool
|
||||||
|
{
|
||||||
|
$dayOfWeekIso = Carbon::parse($this->mail_day)->dayOfWeekIso;
|
||||||
|
$min_updated_at_date = now()
|
||||||
|
->setISODate($year, $week)
|
||||||
|
->startOfWeek()
|
||||||
|
->addDays($dayOfWeekIso - 1)
|
||||||
|
->format('Y-m-d');
|
||||||
|
|
||||||
|
return $this->mosaics()
|
||||||
|
->where('updated_at', '>=', $min_updated_at_date)
|
||||||
|
->statusSuccess()
|
||||||
|
->where(['year' => $year, 'week' => $week])
|
||||||
|
->exists();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scheduleReport($year = null, $week = null)
|
||||||
|
{
|
||||||
|
// if year, week is in the future set year and week to null;
|
||||||
|
if (now()->year < $year || (now()->year === $year && now()->weekOfYear < $week)) {
|
||||||
|
$year = null;
|
||||||
|
$week = null;
|
||||||
|
logger('year and week is in the future default to now');
|
||||||
|
}
|
||||||
|
|
||||||
|
$year = $year ?? now()->year;
|
||||||
|
$week = $week ?? now()->weekOfYear;
|
||||||
|
|
||||||
Bus::chain([
|
Bus::chain([
|
||||||
Bus::batch(self::getFileDownloadsFor($year, $week)),
|
Bus::batch($this->getFileDownloadsFor($year, $week)),
|
||||||
Bus::batch(self::getMosaicsFor($year, $week)),
|
Bus::batch($this->getMosaicsFor($year, $week)),
|
||||||
Bus::batch(self::getReportFor($year, $week)),
|
Bus::batch($this->getReportFor($year, $week, true)),
|
||||||
])->dispatch();
|
])
|
||||||
|
->dispatch();
|
||||||
return "done";
|
return "done";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getReportFor($year, $week)
|
public function getReportFor($year, $week, $sendMail = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
$report = $this->reports()->create([
|
$report = $this->reports()->create([
|
||||||
'name' => 'Report for week '.$week.' of '.$year,
|
'name' => 'Report for week '.$week.' of '.$year,
|
||||||
'week' => $week,
|
'week' => $week,
|
||||||
|
|
@ -290,27 +331,30 @@ public function getReportFor($year, $week)
|
||||||
'path' => 'reports/week_'.$week.'_'.$year.'.docx',
|
'path' => 'reports/week_'.$week.'_'.$year.'.docx',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return new ProjectReportGeneratorJob($report);
|
return [new ProjectReportGeneratorJob($report, $sendMail)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFileDownloadsFor($year, $startWeekNumber)
|
public function getFileDownloadsFor($year, $startWeekNumber)
|
||||||
{
|
{
|
||||||
$endOfRange = \Illuminate\Support\Carbon::now()->setISODate($year, $startWeekNumber)->endOfWeek();
|
$endOfRange = now()->setISODate($year, $startWeekNumber)->endOfWeek();
|
||||||
$startOfRange = (clone $endOfRange)->subWeeks(3)->startOfWeek();
|
$startOfRange = (clone $endOfRange)->subWeeks(3)->startOfWeek();
|
||||||
|
|
||||||
$dateRange = CarbonPeriod::create($startOfRange, $endOfRange);
|
$dateRange = CarbonPeriod::create($startOfRange, $endOfRange);
|
||||||
|
|
||||||
return collect($dateRange)
|
$return = collect($dateRange)
|
||||||
->map(fn($date) => ProjectDownloadTiffJob::handleForDate($this, $date))
|
->map(fn($date) => ProjectDownloadTiffJob::handleForDate($this, $date))
|
||||||
->filter()
|
->filter()
|
||||||
->toArray();
|
->toArray();
|
||||||
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMosaicsFor($year, $startWeekNumber)
|
public function getMosaicsFor($year, $startWeekNumber)
|
||||||
{
|
{
|
||||||
return collect(range(0, 3))
|
$return = collect(range(0, 3))
|
||||||
->map(fn($weekDiff) => ProjectMosiacGeneratorJob::handleFor($this, $year, $startWeekNumber - $weekDiff))
|
->map(fn($weekDiff) => ProjectMosiacGeneratorJob::handleFor($this, $year, $startWeekNumber - $weekDiff))
|
||||||
->filter()
|
->filter()
|
||||||
->toArray();
|
->toArray();
|
||||||
|
|
||||||
|
return $return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,19 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\HasStatus;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class ProjectDownload extends Model
|
class ProjectDownload extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use HasStatus;
|
||||||
|
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
'path',
|
'path',
|
||||||
'status',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public function project(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
public function project(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\HasStatus;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
|
|
@ -12,6 +14,7 @@
|
||||||
class ProjectMailing extends Model
|
class ProjectMailing extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use HasStatus;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'subject',
|
'subject',
|
||||||
|
|
@ -51,4 +54,13 @@ public function attachments()
|
||||||
{
|
{
|
||||||
return $this->hasMany(ProjectMailingAttachment::class);
|
return $this->hasMany(ProjectMailingAttachment::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function subject(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::make(
|
||||||
|
set: function ($value) {
|
||||||
|
return str_replace(['{date}'], [now()->toDateString()], $value);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,11 @@
|
||||||
class ProjectMosaic extends Model
|
class ProjectMosaic extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use \App\Traits\HasStatus;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
'path',
|
'path',
|
||||||
'status',
|
|
||||||
'year',
|
|
||||||
'week',
|
'week',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use App\Jobs\ProjectDownloadTiffJob;
|
use App\Jobs\ProjectDownloadTiffJob;
|
||||||
use App\Jobs\ProjectMosiacGeneratorJob;
|
use App\Jobs\ProjectMosiacGeneratorJob;
|
||||||
|
use App\Traits\HasStatus;
|
||||||
use Carbon\CarbonPeriod;
|
use Carbon\CarbonPeriod;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
@ -12,19 +13,10 @@
|
||||||
|
|
||||||
class ProjectReport extends Model
|
class ProjectReport extends Model
|
||||||
{
|
{
|
||||||
protected $fillable = ['name', 'path', 'week', 'year', 'status'];
|
use HasStatus;
|
||||||
|
protected $fillable = ['name', 'path', 'week', 'year'];
|
||||||
|
|
||||||
public function setStatusSuccess()
|
|
||||||
{
|
|
||||||
$this->status = 'success';
|
|
||||||
$this->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setStatusFailed()
|
|
||||||
{
|
|
||||||
$this->status = 'failed';
|
|
||||||
$this->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function project()
|
public function project()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Listeners\UpdateMailingStatus;
|
||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
|
use Illuminate\Mail\Events\MessageSent;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
|
|
||||||
class EventServiceProvider extends ServiceProvider
|
class EventServiceProvider extends ServiceProvider
|
||||||
|
|
@ -18,6 +20,9 @@ class EventServiceProvider extends ServiceProvider
|
||||||
Registered::class => [
|
Registered::class => [
|
||||||
SendEmailVerificationNotification::class,
|
SendEmailVerificationNotification::class,
|
||||||
],
|
],
|
||||||
|
MessageSent::class => [
|
||||||
|
UpdateMailingStatus::class,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
67
laravel_app/app/Traits/HasStatus.php
Normal file
67
laravel_app/app/Traits/HasStatus.php
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use App\Enums\Status;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
|
trait HasStatus
|
||||||
|
{
|
||||||
|
public function setStatus(string $status)
|
||||||
|
{
|
||||||
|
if (!Status::isValid($status)) {
|
||||||
|
throw new \InvalidArgumentException("Invalid status");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->status = $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStatusSuccess()
|
||||||
|
{
|
||||||
|
$this->status = Status::Success;
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStatusFailed()
|
||||||
|
{
|
||||||
|
$this->status = Status::Failed;
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStatusPending()
|
||||||
|
{
|
||||||
|
$this->status = Status::Pending;
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeStatusSuccess(Builder $query): Builder
|
||||||
|
{
|
||||||
|
return $query->where('status', Status::Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeStatusFailed(Builder $query): Builder
|
||||||
|
{
|
||||||
|
return $query->where('status', Status::Failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeStatusPending(Builder $query): Builder
|
||||||
|
{
|
||||||
|
return $query->where('status', Status::Pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function statusIsSuccessful(): bool
|
||||||
|
{
|
||||||
|
return $this->status === Status::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function statusHasFailed(): bool
|
||||||
|
{
|
||||||
|
return $this->status === Status::Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function statusIsPending(): bool
|
||||||
|
{
|
||||||
|
return $this->status === Status::Pending;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\Status;
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
@ -16,7 +17,7 @@ public function up(): void
|
||||||
$table->foreignId('project_id');
|
$table->foreignId('project_id');
|
||||||
$table->string('subject');
|
$table->string('subject');
|
||||||
$table->text('message');
|
$table->text('message');
|
||||||
$table->string('status')->default('pending');
|
$table->string('status')->default(Status::Pending);
|
||||||
// $table->text('recipients');
|
// $table->text('recipients');
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -62,13 +62,13 @@ private function createChembaProject()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($chembaProject->getMergedTiffList() as $mergedTiff) {
|
foreach ($chembaProject->getMergedTiffList() as $mergedTiff) {
|
||||||
$chembaProject->downloads()->create([
|
$download = $chembaProject->downloads()->create([
|
||||||
'name' => basename($mergedTiff),
|
'name' => basename($mergedTiff),
|
||||||
'path' => $mergedTiff,
|
'path' => $mergedTiff,
|
||||||
'status' => 'completed',
|
|
||||||
'created_at' => '2021-01-01 00:00:00',
|
'created_at' => '2021-01-01 00:00:00',
|
||||||
'updated_at' => '2021-01-01 00:00:00'
|
'updated_at' => '2021-01-01 00:00:00'
|
||||||
]);
|
]);
|
||||||
|
$download->setStatusSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
$chembaProject->emailRecipients()->createMany([
|
$chembaProject->emailRecipients()->createMany([
|
||||||
|
|
@ -89,19 +89,20 @@ private function createChembaProject()
|
||||||
[
|
[
|
||||||
'subject' => 'Chemba 2021-01-01',
|
'subject' => 'Chemba 2021-01-01',
|
||||||
'message' => 'Chemba 2021-01-01',
|
'message' => 'Chemba 2021-01-01',
|
||||||
'status' => 'completed', // 'pending
|
|
||||||
'created_at' => '2021-01-01 00:00:00',
|
'created_at' => '2021-01-01 00:00:00',
|
||||||
'updated_at' => '2021-01-01 00:00:00',
|
'updated_at' => '2021-01-01 00:00:00',
|
||||||
], [
|
], [
|
||||||
'subject' => 'Chemba 2021-01-08',
|
'subject' => 'Chemba 2021-01-08',
|
||||||
'message' => 'Chemba 2021-01-08',
|
'message' => 'Chemba 2021-01-08',
|
||||||
'status' => 'completed',
|
|
||||||
'created_at' => '2021-01-08 00:00:00',
|
'created_at' => '2021-01-08 00:00:00',
|
||||||
'updated_at' => '2021-01-08 00:00:00',
|
'updated_at' => '2021-01-08 00:00:00',
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
foreach ($chembaProject->mailings as $mailing) {
|
foreach ($chembaProject->mailings as $mailing) {
|
||||||
|
$mailing->setStatusSuccess();
|
||||||
|
|
||||||
$mailing->recipients()->createMany([
|
$mailing->recipients()->createMany([
|
||||||
[
|
[
|
||||||
'name' => 'Martin Folkerts',
|
'name' => 'Martin Folkerts',
|
||||||
|
|
@ -184,19 +185,18 @@ private function createXinavaneProject()
|
||||||
[
|
[
|
||||||
'subject' => 'Xinavane 2021-01-01',
|
'subject' => 'Xinavane 2021-01-01',
|
||||||
'message' => 'Xinavane 2021-01-01',
|
'message' => 'Xinavane 2021-01-01',
|
||||||
'status' => 'completed',
|
|
||||||
'created_at' => '2021-01-01 00:00:00',
|
'created_at' => '2021-01-01 00:00:00',
|
||||||
'updated_at' => '2021-01-01 00:00:00',
|
'updated_at' => '2021-01-01 00:00:00',
|
||||||
], [
|
], [
|
||||||
'subject' => 'Xinavane 2021-01-08',
|
'subject' => 'Xinavane 2021-01-08',
|
||||||
'message' => 'Xinavane 2021-01-08',
|
'message' => 'Xinavane 2021-01-08',
|
||||||
'status' => 'completed',
|
|
||||||
'created_at' => '2021-01-08 00:00:00',
|
'created_at' => '2021-01-08 00:00:00',
|
||||||
'updated_at' => '2021-01-08 00:00:00',
|
'updated_at' => '2021-01-08 00:00:00',
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($project->mailings as $mailing) {
|
foreach ($project->mailings as $mailing) {
|
||||||
|
$mailing->setStatusSuccess();
|
||||||
$mailing->recipients()->createMany([
|
$mailing->recipients()->createMany([
|
||||||
[
|
[
|
||||||
'name' => 'Martin Folkerts',
|
'name' => 'Martin Folkerts',
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
@props([
|
@props([
|
||||||
'status' => 'success',
|
'status' => \App\Enums\Status::Success,
|
||||||
])
|
])
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
@ -12,14 +12,18 @@
|
||||||
'pending' => ['bg' => 'bg-gray-100', 'text' => 'text-gray-600'],
|
'pending' => ['bg' => 'bg-gray-100', 'text' => 'text-gray-600'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// If status is an object, try to convert it to a string
|
||||||
|
if (is_object($status)) {
|
||||||
|
$status = (string) $status;
|
||||||
|
}
|
||||||
|
|
||||||
// Default to 'success' if the provided status is not in the defined array
|
// Default to 'success' if the provided status is not in the defined array
|
||||||
if (!array_key_exists($status, $statusToColors)) {
|
if (!array_key_exists($status, $statusToColors)) {
|
||||||
$status = 'success';
|
$status = \App\Enums\Status::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the color class for the given status
|
// Get the color class for the given status
|
||||||
$colorClasses = $statusToColors[$status];
|
$colorClasses = $statusToColors[$status];
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<span {{ $attributes }} class="inline-flex items-center rounded-md {{ $colorClasses['bg'] }} px-1.5 py-0.5 text-xs font-medium {{ $colorClasses['text'] }}">
|
<span {{ $attributes }} class="inline-flex items-center rounded-md {{ $colorClasses['bg'] }} px-1.5 py-0.5 text-xs font-medium {{ $colorClasses['text'] }}">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8">{{ $report->name }}</td>
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8">{{ $report->name }}</td>
|
||||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||||
@if($report->status == 'pending')
|
@if($report->status == \App\Enums\Status::Pending)
|
||||||
<x-badge status="pending" wire:poll.1s=""></x-badge>
|
<x-badge status="pending" wire:poll.1s=""></x-badge>
|
||||||
@else
|
@else
|
||||||
<x-badge :status="$report->status"></x-badge>
|
<x-badge :status="$report->status"></x-badge>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
<h1 class="text-base font-semibold leading-6 text-gray-900">Downloads</h1>
|
<h1 class="text-base font-semibold leading-6 text-gray-900">Downloads</h1>
|
||||||
<p class="mt-2 text-sm text-gray-700">
|
<p class="mt-2 text-sm text-gray-700">
|
||||||
@if ($project->hasPendingDownload())
|
@if ($project->hasPendingDownload())
|
||||||
Pending downloads for this project: {{ $project->downloads()->where('status', 'pending')->count() }}
|
Pending downloads for this project: {{ $project->downloads()->statusPending()->count() }}
|
||||||
@endif
|
@endif
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,8 @@ public function it_can_get_the_full_path_name()
|
||||||
'year' => 2021,
|
'year' => 2021,
|
||||||
'week' => 41,
|
'week' => 41,
|
||||||
'path' => 'path/doc.pdf',
|
'path' => 'path/doc.pdf',
|
||||||
'status' => 'success',
|
|
||||||
]);
|
]);
|
||||||
|
$projectReport->setStatusSuccess();
|
||||||
$this->assertEquals(storage_path('app/project_download_path/path/doc.pdf'), $projectReport->getFullPathName());
|
$this->assertEquals(storage_path('app/project_download_path/path/doc.pdf'), $projectReport->getFullPathName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,8 +79,8 @@ public function it_can_return_the_reportDate($expected, $mail_day, $week, $year)
|
||||||
'year' => $year,
|
'year' => $year,
|
||||||
'week' => $week,
|
'week' => $week,
|
||||||
'path' => 'path/doc.pdf',
|
'path' => 'path/doc.pdf',
|
||||||
'status' => 'success',
|
|
||||||
]);
|
]);
|
||||||
|
$projectReport->setStatusSuccess();
|
||||||
$this->assertEquals($expected, $projectReport->getReportDate());
|
$this->assertEquals($expected, $projectReport->getReportDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
BIN
r_app/Rplots.pdf
BIN
r_app/Rplots.pdf
Binary file not shown.
Loading…
Reference in a new issue