Compare commits
3 Commits
5c55441e6c
...
refactor/s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27d51ffdb1 | ||
|
|
53d4d5768b | ||
|
|
3ff89d43ed |
@@ -33,7 +33,7 @@ export function useToast() {
|
|||||||
message,
|
message,
|
||||||
type,
|
type,
|
||||||
visible: true,
|
visible: true,
|
||||||
duration: type === 'error' ? 0 : duration,
|
duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toasts.value.length >= MAX_TOASTS) {
|
if (toasts.value.length >= MAX_TOASTS) {
|
||||||
@@ -42,8 +42,7 @@ export function useToast() {
|
|||||||
|
|
||||||
toasts.value.push(toast)
|
toasts.value.push(toast)
|
||||||
|
|
||||||
// Only auto-dismiss non-error toasts
|
if (duration > 0) {
|
||||||
if (type !== 'error' && duration > 0) {
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
removeToast(id)
|
removeToast(id)
|
||||||
}, duration)
|
}, duration)
|
||||||
@@ -56,8 +55,8 @@ export function useToast() {
|
|||||||
return showToast(message, 'success', duration)
|
return showToast(message, 'success', duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
const showError = (message: string): number => {
|
const showError = (message: string, duration = 8000): number => {
|
||||||
return showToast(message, 'error', 0)
|
return showToast(message, 'error', duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
const showWarning = (message: string, duration = 6000): number => {
|
const showWarning = (message: string, duration = 6000): number => {
|
||||||
|
|||||||
@@ -715,10 +715,12 @@
|
|||||||
</p>
|
</p>
|
||||||
<p class="text-base-content/70 leading-relaxed mb-4">
|
<p class="text-base-content/70 leading-relaxed mb-4">
|
||||||
<strong>Pourquoi ?</strong> Certaines informations n'ont de sens que quand
|
<strong>Pourquoi ?</strong> Certaines informations n'ont de sens que quand
|
||||||
l'element est monte sur une machine. Par exemple, la "position sur la machine"
|
l'element est monte sur une machine. Prenons l'exemple d'un palier : sur une
|
||||||
d'une pompe : dans le catalogue, la pompe n'est montee nulle part, donc ce champ
|
machine, vous en avez souvent deux, un en haut (le palier de tete) et un en
|
||||||
ne sert a rien. Mais quand on regarde cette pompe depuis la fiche d'une machine,
|
bas (le palier de pied). Dans le catalogue, le palier n'est monte nulle part,
|
||||||
on veut savoir ou elle est installee.
|
donc savoir s'il est "en haut" ou "en bas" ne veut rien dire. Mais des qu'on
|
||||||
|
regarde ce palier depuis la fiche d'une machine, on veut savoir lequel des
|
||||||
|
deux c'est.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -731,16 +733,16 @@
|
|||||||
<p class="text-xs text-base-content/40 mb-4">Quand on consulte l'element tout seul</p>
|
<p class="text-xs text-base-content/40 mb-4">Quand on consulte l'element tout seul</p>
|
||||||
<div class="space-y-2 text-sm">
|
<div class="space-y-2 text-sm">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span class="text-base-content/70">Debit max</span>
|
<span class="text-base-content/70">Diametre interieur</span>
|
||||||
<span>120 L/min</span>
|
<span>50 mm</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span class="text-base-content/70">ATEX</span>
|
<span class="text-base-content/70">Type</span>
|
||||||
<span>Oui</span>
|
<span>Roulement a billes</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-dashed border-base-300 pt-2 mt-2">
|
<div class="border-t border-dashed border-base-300 pt-2 mt-2">
|
||||||
<div class="flex justify-between opacity-30">
|
<div class="flex justify-between opacity-30">
|
||||||
<span class="line-through">Position sur la machine</span>
|
<span class="line-through">Emplacement</span>
|
||||||
<span class="text-xs italic">pas affiche ici</span>
|
<span class="text-xs italic">pas affiche ici</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -753,17 +755,17 @@
|
|||||||
<p class="text-xs text-base-content/40 mb-4">Quand on regarde l'element dans sa machine</p>
|
<p class="text-xs text-base-content/40 mb-4">Quand on regarde l'element dans sa machine</p>
|
||||||
<div class="space-y-2 text-sm">
|
<div class="space-y-2 text-sm">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span class="text-base-content/70">Debit max</span>
|
<span class="text-base-content/70">Diametre interieur</span>
|
||||||
<span>120 L/min</span>
|
<span>50 mm</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span class="text-base-content/70">ATEX</span>
|
<span class="text-base-content/70">Type</span>
|
||||||
<span>Oui</span>
|
<span>Roulement a billes</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-primary/20 pt-2 mt-2">
|
<div class="border-t border-primary/20 pt-2 mt-2">
|
||||||
<div class="flex justify-between bg-primary/10 rounded px-2 py-1.5">
|
<div class="flex justify-between bg-primary/10 rounded px-2 py-1.5">
|
||||||
<span class="text-base-content font-medium">Position sur la machine</span>
|
<span class="text-base-content font-medium">Emplacement</span>
|
||||||
<span class="font-bold">Secteur B - Ligne 3</span>
|
<span class="font-bold">Haut (palier de tete)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
106
migrations/Version20260506140000_FixComposantCascadeFKs.php
Normal file
106
migrations/Version20260506140000_FixComposantCascadeFKs.php
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20260506140000_FixComposantCascadeFKs extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Add missing CASCADE FKs documents.composantid and machine_component_links.composantid; cleanup pre-existing orphan rows';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// 1. Trace des suppressions à venir dans audit_logs (actor = NULL = "system").
|
||||||
|
// On copie un snapshot minimal avant DELETE pour cohérence avec les autres "delete".
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
INSERT INTO audit_logs (id, entitytype, entityid, action, snapshot, actorprofileid, createdat)
|
||||||
|
SELECT
|
||||||
|
'cl' || substring(md5(random()::text || clock_timestamp()::text), 1, 24),
|
||||||
|
'document',
|
||||||
|
d.id,
|
||||||
|
'delete',
|
||||||
|
json_build_object(
|
||||||
|
'id', d.id,
|
||||||
|
'name', d.name,
|
||||||
|
'filename', d.filename,
|
||||||
|
'composantId', d.composantid,
|
||||||
|
'note', 'Cleaned by FK cascade fix migration (Version20260506140000) - referenced composant no longer existed'
|
||||||
|
),
|
||||||
|
NULL,
|
||||||
|
NOW()
|
||||||
|
FROM documents d
|
||||||
|
WHERE d.composantid IS NOT NULL
|
||||||
|
AND d.composantid NOT IN (SELECT id FROM composants)
|
||||||
|
SQL);
|
||||||
|
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
INSERT INTO audit_logs (id, entitytype, entityid, action, snapshot, actorprofileid, createdat)
|
||||||
|
SELECT
|
||||||
|
'cl' || substring(md5(random()::text || clock_timestamp()::text), 1, 24),
|
||||||
|
'machine_component_link',
|
||||||
|
l.id,
|
||||||
|
'delete',
|
||||||
|
json_build_object(
|
||||||
|
'id', l.id,
|
||||||
|
'machineId', l.machineid,
|
||||||
|
'composantId', l.composantid,
|
||||||
|
'note', 'Cleaned by FK cascade fix migration (Version20260506140000) - referenced composant no longer existed'
|
||||||
|
),
|
||||||
|
NULL,
|
||||||
|
NOW()
|
||||||
|
FROM machine_component_links l
|
||||||
|
WHERE l.composantid IS NOT NULL
|
||||||
|
AND l.composantid NOT IN (SELECT id FROM composants)
|
||||||
|
SQL);
|
||||||
|
|
||||||
|
// 2. Nettoyage des orphelins.
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DELETE FROM documents
|
||||||
|
WHERE composantid IS NOT NULL
|
||||||
|
AND composantid NOT IN (SELECT id FROM composants)
|
||||||
|
SQL);
|
||||||
|
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DELETE FROM machine_component_links
|
||||||
|
WHERE composantid IS NOT NULL
|
||||||
|
AND composantid NOT IN (SELECT id FROM composants)
|
||||||
|
SQL);
|
||||||
|
|
||||||
|
// 3. Ajout idempotent des 2 FK manquantes (alignement avec les entités Doctrine).
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DO $$ BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.table_constraints
|
||||||
|
WHERE constraint_name = 'fk_documents_composant' AND table_name = 'documents'
|
||||||
|
) THEN
|
||||||
|
ALTER TABLE documents ADD CONSTRAINT fk_documents_composant
|
||||||
|
FOREIGN KEY (composantid) REFERENCES composants(id) ON DELETE CASCADE;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
SQL);
|
||||||
|
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DO $$ BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.table_constraints
|
||||||
|
WHERE constraint_name = 'fk_mcl_composant' AND table_name = 'machine_component_links'
|
||||||
|
) THEN
|
||||||
|
ALTER TABLE machine_component_links ADD CONSTRAINT fk_mcl_composant
|
||||||
|
FOREIGN KEY (composantid) REFERENCES composants(id) ON DELETE CASCADE;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE documents DROP CONSTRAINT IF EXISTS fk_documents_composant');
|
||||||
|
$this->addSql('ALTER TABLE machine_component_links DROP CONSTRAINT IF EXISTS fk_mcl_composant');
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user