feat: 💩 trying to fix invoices sorting, trying to make the delete cascade for site

This commit is contained in:
Nicolas Demangeat 2025-06-18 11:10:46 +02:00
parent c63f2b62e9
commit de14d846c5
11 changed files with 127 additions and 14 deletions

View file

@ -28,11 +28,11 @@ class SiteController extends Controller
if ($user->isAdmin()) {
/** @var \Illuminate\Database\Eloquent\Builder $siteModels */
$siteModels = Site::query();
$siteModels = Site::query()->with(['invoices', 'tickets']);
} else {
/** @var \Illuminate\Database\Eloquent\Builder $siteModels */
$siteModels = Site::whereHas('users', function (\Illuminate\Database\Eloquent\Builder $query) use ($user) {
$query->where('id', $user->id);
$query->where('id', $user->id)->with(['invoices', 'tickets']);
});
}

View file

@ -10,6 +10,7 @@ use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Mccarlosen\LaravelMpdf\LaravelMpdf;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* @property string $ref
@ -32,6 +33,7 @@ use Mccarlosen\LaravelMpdf\LaravelMpdf;
class Invoice extends Model
{
use HasFactory;
use SoftDeletes;
/**
* The attributes that are fillable.

View file

@ -57,6 +57,10 @@ class Site extends Model
static::updating(function (self $model) {
self::manageFields($model);
});
static::deleted(function ($site) {
$site->invoices()->delete();
$site->tickets()->delete();
});
}
// * METHODS
@ -84,7 +88,7 @@ class Site extends Model
* HasMany Message relation
* The users of type client that would have access to this site tickets
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
* @return \Illuminate\Database\Eloquent\Relations\belongsToMany
*/
public function users()
{
@ -101,6 +105,16 @@ class Site extends Model
return $this->hasMany(Ticket::class, 'site_id');
}
/**
* HasMany Invoices relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function invoices()
{
return $this->hasMany(Invoice::class, 'site_id');
}
/**
* BelongsTo Brand relation
*

View file

@ -16,12 +16,14 @@ use App\Models\Ticket\TicketType;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class Ticket extends Model
{
use HasFactory;
use SoftDeletes;
/**
* The attributes that are fillable.

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::table('invoices', function (Blueprint $table) {
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::table('invoices', function (Blueprint $table) {
$table->dropColumn('deleted_at');
});
}
};

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::table('tickets', function (Blueprint $table) {
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::table('tickets', function (Blueprint $table) {
$table->dropColumn('deleted_at');
});
}
};

View file

@ -5,9 +5,8 @@ window.addEventListener("DOMContentLoaded", () => {
/**
* Popup delete item.
*/
const elements = document.getElementsByClassName(
"confirmDeleteTS"
) as HTMLCollectionOf<Element>;
const elements = document.getElementsByClassName("confirmDeleteTS") as HTMLCollectionOf<Element>;
for (const element of elements) {
element.addEventListener("submit", function (e) {
e.preventDefault();
@ -17,15 +16,33 @@ window.addEventListener("DOMContentLoaded", () => {
"confirmDoneJS can only be executed on an exising form"
);
}
const event = e as SubmitEvent;
let submitter: HTMLButtonElement | null = null;
if (event.submitter) {
submitter = event.submitter as HTMLButtonElement;
} else {
submitter = document.activeElement as HTMLButtonElement;
}
const tickets_number = submitter?.dataset.tickets ?? "0";
const invoices_number = submitter?.dataset.invoices ?? "0";
const message = `Toutes les données vont être perdues.
<br>Tickets concernés : ${tickets_number}
Devis concernées : ${invoices_number}`;
sweetalert.methods.confirm(
"Êtes-vous sûr ?",
"Toutes les données vont être perdu",
message,
el as HTMLFormElement,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function (response: SweetAlertResult<any>) {
(el as HTMLFormElement).submit();
},
{ icon: "warning" }
{ icon: "warning", html: "true" },
true
);
return false;
});

View file

@ -11,7 +11,8 @@ export default {
text: string = "",
self: Object,
after: (response: SweetAlertResult<any>) => void = () => {},
options: SweetAlertOptions = {}
options: SweetAlertOptions = {},
html: Boolean = false
) {
if (!self) {
throw Error("self is needed to set \"this\" on callback");
@ -19,10 +20,12 @@ export default {
if (!after) {
throw Error("callback is needed when using confirm");
}
const icon = options.icon ?? "warning";
Swal.fire({
// define options to fire
const saOptions = {
title: title,
text: text,
color: getComputedStyle(document.body).getPropertyValue("--bs-body-color"),
icon: icon,
showCancelButton: true,
@ -40,7 +43,16 @@ export default {
},
buttonsStyling: false,
background: getComputedStyle(document.body).getPropertyValue("--bs-body-bg"),
}).then((result) => {
};
// Enable HTML content interpretation in the modal options
let htmlActive = {};
if (html) {
htmlActive = {html: text};
}
const fullOptions = {...saOptions, ...htmlActive};
Swal.fire(fullOptions).then((result) => {
if (result.isConfirmed) {
if (after) {
after.apply(self, [result]);

View file

@ -53,7 +53,7 @@
<td class="text-center align-middle"><span class="badge bg-info">{{ $invoiceModel->sent_client_date }}</span></td>
<td class="text-center align-middle"><span class="badge bg-info">{{ $invoiceModel->signed_date }}</span></td>
<td class="text-center align-middle"><span class="badge bg-info">{{ $invoiceModel->sent_accounting_date }}</span></td>
<td class="text-center align-middle">{{ $invoiceModel->site->name }}</td>
<td class="text-center align-middle">{{ $invoiceModel->site?->name }}</td>
<td class="text-center align-middle"><span class="badge bg-info">{{ $invoiceModel->updated_at }}</span></td>
<td class="text-end align-middle">
<div class="btn-group">

View file

@ -78,6 +78,8 @@
@method('DELETE')
<button type="submit"
class="btn btn-sm btn-danger"
data-tickets="{{ $siteModel->tickets()->count() }}"
data-invoices="{{ $siteModel->invoices()->count() }}"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.actions.delete') }}">

View file

@ -18,7 +18,7 @@
</h1>
@if (session('tickets.pr'))
@php
$projectManager = \App\Models\Site::query()->find(session('tickets.pr'))->projectManager;
$projectManager = \App\Models\Site::query()->find(session('tickets.pr')) ? \App\Models\Site::query()->find(session('tickets.pr'))->projectManager : false;
@endphp
@if($projectManager)
<h2>{{ __("Chef de projet") }} : {{ $projectManager->name }}</h2>