altre migrations sistemate
This commit is contained in:
@@ -578,3 +578,27 @@ if (!empty($contatto['individuo_id'])) { create }
|
||||
- Test IMAP OAuth: sync email via connessione OAuth
|
||||
- Verificare refresh token automatico allo scadere
|
||||
- Verificare revoca e riconnessione
|
||||
|
||||
## 2026-06-17 — Fix: tutte le migration + seeders idempotenti
|
||||
|
||||
### Problema
|
||||
`php artisan migrate` falliva su tabelle già esistenti (`tenants`, `tipologie_documenti`, ecc.).
|
||||
`php artisan db:seed` creava duplicati su re-run (admin user, diocesi, comuni).
|
||||
Migrations con `insert` dopo il guard `hasTable` violavano unique constraint al re-run.
|
||||
|
||||
### Migration: hasTable guard su 28 CREATE mancanti
|
||||
Aggiunto `if (!Schema::hasTable('table_name')) { ... }` wrapper a 28 migration file (45 `Schema::create()` calls) via script Node.js, più `2026_06_17_000001_create_google_oauth_connections_table.php` manualmente.
|
||||
|
||||
### Fix: insert fuori dai guard (4 file)
|
||||
- `2026_05_10_000001_create_tipologie_documenti_table.php` — spostato insert dentro l'if
|
||||
- `2026_05_26_000001_create_tipologie_eventi_table.php` — spostato insert dentro l'if
|
||||
- `2026_05_12_000001_create_ruoli_table.php` — spostato insert dentro l'if
|
||||
- `2026_05_11_000006_add_email_attachment_tipologia.php` — `insert()` → `updateOrInsert()`
|
||||
|
||||
### Seeder: firstOrCreate
|
||||
- `DiocesiSeeder.php`: `Diocesi::create()` → `::firstOrCreate(['nome' => ...])`
|
||||
- `ComuniSeeder.php`: `Comune::create()` → `::firstOrCreate(['codice_istat' => ...])`
|
||||
- `DatabaseSeeder.php`: `User::create()` → `::firstOrCreate(['email' => ...])` + guardia `role_preset_id`
|
||||
|
||||
### Risultato
|
||||
`php artisan migrate --seed` è ora completamente idempotente. Zero errori su 64 migration + 6 seeder. Re-run è un no-op.
|
||||
|
||||
@@ -17,18 +17,18 @@ return new class extends Migration
|
||||
$table->boolean('attiva')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
$defaultTipologie = ['avatar', 'galleria', 'documento', 'statuto', 'altro'];
|
||||
foreach ($defaultTipologie as $i => $nome) {
|
||||
DB::table('tipologie_documenti')->insert([
|
||||
'nome' => $nome,
|
||||
'descrizione' => ucfirst($nome),
|
||||
'ordine' => $i,
|
||||
'attiva' => true,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
$defaultTipologie = ['avatar', 'galleria', 'documento', 'statuto', 'altro'];
|
||||
foreach ($defaultTipologie as $i => $nome) {
|
||||
DB::table('tipologie_documenti')->insert([
|
||||
'nome' => $nome,
|
||||
'descrizione' => ucfirst($nome),
|
||||
'ordine' => $i,
|
||||
'attiva' => true,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,15 @@ return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
DB::table('tipologie_documenti')->insert([
|
||||
'nome' => 'email_attachment',
|
||||
'descrizione' => 'Allegato email',
|
||||
'ordine' => 100,
|
||||
'attiva' => true,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
DB::table('tipologie_documenti')->updateOrInsert(
|
||||
['nome' => 'email_attachment'],
|
||||
[
|
||||
'descrizione' => 'Allegato email',
|
||||
'ordine' => 100,
|
||||
'attiva' => true,
|
||||
'updated_at' => now(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
|
||||
@@ -17,27 +17,27 @@ return new class extends Migration
|
||||
$table->boolean('attiva')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
$defaultRuoli = [
|
||||
['nome' => 'Membro', 'descrizione' => 'Membro del gruppo'],
|
||||
['nome' => 'Catechista', 'descrizione' => 'Catechista del gruppo'],
|
||||
['nome' => 'Animatore', 'descrizione' => 'Animatore del gruppo'],
|
||||
['nome' => 'Responsabile', 'descrizione' => 'Responsabile del gruppo'],
|
||||
['nome' => 'Vice Responsabile', 'descrizione' => 'Vice responsabile del gruppo'],
|
||||
['nome' => 'Segretario', 'descrizione' => 'Segretario del gruppo'],
|
||||
['nome' => 'Tesoriere', 'descrizione' => 'Tesoriere del gruppo'],
|
||||
];
|
||||
$defaultRuoli = [
|
||||
['nome' => 'Membro', 'descrizione' => 'Membro del gruppo'],
|
||||
['nome' => 'Catechista', 'descrizione' => 'Catechista del gruppo'],
|
||||
['nome' => 'Animatore', 'descrizione' => 'Animatore del gruppo'],
|
||||
['nome' => 'Responsabile', 'descrizione' => 'Responsabile del gruppo'],
|
||||
['nome' => 'Vice Responsabile', 'descrizione' => 'Vice responsabile del gruppo'],
|
||||
['nome' => 'Segretario', 'descrizione' => 'Segretario del gruppo'],
|
||||
['nome' => 'Tesoriere', 'descrizione' => 'Tesoriere del gruppo'],
|
||||
];
|
||||
|
||||
foreach ($defaultRuoli as $i => $ruolo) {
|
||||
DB::table('ruoli')->insert([
|
||||
'nome' => $ruolo['nome'],
|
||||
'descrizione' => $ruolo['descrizione'],
|
||||
'ordine' => $i,
|
||||
'attiva' => true,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
foreach ($defaultRuoli as $i => $ruolo) {
|
||||
DB::table('ruoli')->insert([
|
||||
'nome' => $ruolo['nome'],
|
||||
'descrizione' => $ruolo['descrizione'],
|
||||
'ordine' => $i,
|
||||
'attiva' => true,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Schema::hasColumn('gruppo_individuo', 'ruolo_id')) {
|
||||
|
||||
@@ -19,18 +19,18 @@ return new class extends Migration
|
||||
$table->boolean('attiva')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
DB::table('tipologie_eventi')->insert([
|
||||
['nome' => 'catechesi', 'descrizione' => 'Catechesi', 'ordine' => 0, 'attiva' => true],
|
||||
['nome' => 'liturgia', 'descrizione' => 'Liturgia', 'ordine' => 1, 'attiva' => true],
|
||||
['nome' => 'animazione', 'descrizione' => 'Animazione', 'ordine' => 2, 'attiva' => true],
|
||||
['nome' => 'formazione', 'descrizione' => 'Formazione', 'ordine' => 3, 'attiva' => true],
|
||||
['nome' => 'incontro', 'descrizione' => 'Incontro', 'ordine' => 4, 'attiva' => true],
|
||||
['nome' => 'riunione', 'descrizione' => 'Riunione', 'ordine' => 5, 'attiva' => true],
|
||||
['nome' => 'festa', 'descrizione' => 'Festa / Sagra', 'ordine' => 6, 'attiva' => true],
|
||||
['nome' => 'altro', 'descrizione' => 'Altro', 'ordine' => 7, 'attiva' => true],
|
||||
]);
|
||||
DB::table('tipologie_eventi')->insert([
|
||||
['nome' => 'catechesi', 'descrizione' => 'Catechesi', 'ordine' => 0, 'attiva' => true],
|
||||
['nome' => 'liturgia', 'descrizione' => 'Liturgia', 'ordine' => 1, 'attiva' => true],
|
||||
['nome' => 'animazione', 'descrizione' => 'Animazione', 'ordine' => 2, 'attiva' => true],
|
||||
['nome' => 'formazione', 'descrizione' => 'Formazione', 'ordine' => 3, 'attiva' => true],
|
||||
['nome' => 'incontro', 'descrizione' => 'Incontro', 'ordine' => 4, 'attiva' => true],
|
||||
['nome' => 'riunione', 'descrizione' => 'Riunione', 'ordine' => 5, 'attiva' => true],
|
||||
['nome' => 'festa', 'descrizione' => 'Festa / Sagra', 'ordine' => 6, 'attiva' => true],
|
||||
['nome' => 'altro', 'descrizione' => 'Altro', 'ordine' => 7, 'attiva' => true],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
|
||||
@@ -10,6 +10,10 @@ return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (Schema::hasTable('google_oauth_connections')) {
|
||||
return;
|
||||
}
|
||||
|
||||
Schema::create('google_oauth_connections', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
|
||||
|
||||
Vendored
+4
-1
@@ -14,7 +14,10 @@ if (PHP_VERSION_ID < 50600) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException($err);
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
+4
-25
@@ -26,12 +26,6 @@ use Composer\Semver\VersionParser;
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
|
||||
* @internal
|
||||
*/
|
||||
private static $selfDir = null;
|
||||
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
@@ -317,18 +311,6 @@ class InstalledVersions
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private static function getSelfDir()
|
||||
{
|
||||
if (self::$selfDir === null) {
|
||||
self::$selfDir = strtr(__DIR__, '\\', '/');
|
||||
}
|
||||
|
||||
return self::$selfDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
@@ -340,7 +322,6 @@ class InstalledVersions
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
$copiedLocalDir = false;
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
@@ -349,11 +330,9 @@ class InstalledVersions
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
self::$installedByVendor[$vendorDir] = $required;
|
||||
$installed[] = $required;
|
||||
if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $required;
|
||||
$copiedLocalDir = true;
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -371,7 +350,7 @@ class InstalledVersions
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||
if (self::$installed !== array()) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+4
-4
@@ -3,7 +3,7 @@
|
||||
'name' => 'laravel/laravel',
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '6909e21b677ae5b7bfe8d8ef3f31b61982b5436e',
|
||||
'reference' => '92ba47e99f4839d49d5f002915c30a88bb842c6a',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@@ -427,7 +427,7 @@
|
||||
'laravel/laravel' => array(
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '6909e21b677ae5b7bfe8d8ef3f31b61982b5436e',
|
||||
'reference' => '92ba47e99f4839d49d5f002915c30a88bb842c6a',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@@ -732,8 +732,8 @@
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0 || 2.0 || 3.0',
|
||||
1 => '1.0|2.0|3.0',
|
||||
2 => '3.0.0',
|
||||
1 => '3.0.0',
|
||||
2 => '1.0|2.0|3.0',
|
||||
),
|
||||
),
|
||||
'psr/simple-cache' => array(
|
||||
|
||||
Reference in New Issue
Block a user