++ gruppi di servizio: sorvegliante con utenza limitata, pacchetto di territori, assegnazione ai membri
Il gruppo ha un sorvegliante (proclamatore con utenza: email e password temporanea, senza conferma dell'email) e dei membri; l'amministratore mette in blocco dei territori nel pacchetto del gruppo. Il pacchetto non e' un'assegnazione e non tocca le statistiche; quando il sorvegliante da' un territorio a un membro nasce un'assegnazione normale con gruppo_servizio_id. Al rientro il territorio torna in reparto. Sciogliere il gruppo libera pacchetto e membri e disattiva l'utenza. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,7 +34,10 @@ class UsersIndex extends Component
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
// "sorvegliante" si dà solo creando un gruppo di servizio, con
|
||||
// l'utenza collegata al proclamatore: da qui non si assegna.
|
||||
$this->availableRoles = Role::query()
|
||||
->where('name', '!=', 'sorvegliante')
|
||||
->orderBy('name')
|
||||
->pluck('name')
|
||||
->all();
|
||||
@@ -111,9 +114,28 @@ class UsersIndex extends Component
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Le utenze dei sorveglianti di gruppo (attive o disattivate) si gestiscono
|
||||
* da Gruppi di servizio: cambiarle o cancellarle da qui lascerebbe un
|
||||
* gruppo senza sorvegliante, o un sorvegliante con un ruolo diverso.
|
||||
*/
|
||||
private function gestitaDaiGruppi(User $user): bool
|
||||
{
|
||||
if ($user->proclamatore_id === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->avvisaErrore("L'utenza di {$user->name} è di un sorvegliante di gruppo: si gestisce da Gruppi di servizio.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function startEdit(int $userId): void
|
||||
{
|
||||
$user = User::query()->with('roles')->findOrFail($userId);
|
||||
if ($this->gestitaDaiGruppi($user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->editingUserId = $user->id;
|
||||
$this->editName = $user->name;
|
||||
@@ -143,6 +165,9 @@ class UsersIndex extends Component
|
||||
|
||||
$validated = $this->validate($this->editRules());
|
||||
$user = User::query()->findOrFail($this->editingUserId);
|
||||
if ($this->gestitaDaiGruppi($user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Togliere il ruolo di amministratore a sé stessi, o all'ultimo
|
||||
// rimasto, lascia l'installazione senza nessuno che possa gestire
|
||||
@@ -193,6 +218,9 @@ class UsersIndex extends Component
|
||||
{
|
||||
$currentUser = auth()->user();
|
||||
$user = User::query()->with('roles')->findOrFail($userId);
|
||||
if ($this->gestitaDaiGruppi($user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $currentUser || $currentUser->id === $user->id) {
|
||||
$this->avvisaErrore('Non puoi cancellare il tuo utente.');
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Jobs\ImportTerritoryPdfFolder;
|
||||
use App\Models\AnnoTeocratico;
|
||||
use App\Models\Assegnazione;
|
||||
use App\Models\Campagna;
|
||||
use App\Models\GruppoServizio;
|
||||
use App\Models\Proclamatore;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Territorio;
|
||||
@@ -469,6 +470,7 @@ class XmlExchange extends Component
|
||||
try {
|
||||
DB::transaction(function () use ($xml, $actorId, $attore, $attoreEraAmministratore, &$stats) {
|
||||
Assegnazione::query()->delete();
|
||||
GruppoServizio::query()->delete();
|
||||
Campagna::query()->delete();
|
||||
Territorio::query()->withTrashed()->forceDelete();
|
||||
Proclamatore::query()->withTrashed()->forceDelete();
|
||||
@@ -520,6 +522,7 @@ class XmlExchange extends Component
|
||||
// accounts in the file are (re)created. $userMap remaps the
|
||||
// created_by/returned_by FKs on the assignments below.
|
||||
$userMap = [];
|
||||
$utentiDaCollegare = [];
|
||||
foreach (($xml->users->user ?? []) as $userNode) {
|
||||
$email = trim((string) ($userNode->email ?? ''));
|
||||
$legacyId = (string) ($userNode['legacy_id'] ?? '');
|
||||
@@ -589,6 +592,13 @@ class XmlExchange extends Component
|
||||
|
||||
DB::table('users')->where('id', $user->id)->update($meta);
|
||||
|
||||
// Utenza di un sorvegliante: si collega al proclamatore dopo che
|
||||
// i proclamatori sono stati importati (vedi i gruppi di servizio).
|
||||
$utentiDaCollegare[$user->id] = [
|
||||
'proclamatore' => (string) ($userNode->legacy_proclamatore_id ?? ''),
|
||||
'disattivato_at' => $this->normalizeDateTimeForDb((string) ($userNode->disattivato_at ?? '')),
|
||||
];
|
||||
|
||||
$stats['utenti_importati']++;
|
||||
if ($legacyId !== '') {
|
||||
$userMap[$legacyId] = $user->id;
|
||||
@@ -624,6 +634,7 @@ class XmlExchange extends Component
|
||||
}
|
||||
|
||||
$proclamatoreMap = [];
|
||||
$gruppiDeiProclamatori = [];
|
||||
foreach (($xml->proclamatori->proclamatore ?? []) as $proclamatoreNode) {
|
||||
$p = Proclamatore::create([
|
||||
'nome' => (string) $proclamatoreNode->nome,
|
||||
@@ -634,14 +645,42 @@ class XmlExchange extends Component
|
||||
]);
|
||||
$this->applyRowMeta('proclamatori', $p->id, $proclamatoreNode, true);
|
||||
$stats['proclamatori_importati']++;
|
||||
$gruppiDeiProclamatori[$p->id] = (string) ($proclamatoreNode->legacy_gruppo_id ?? '');
|
||||
$legacyId = (string) ($proclamatoreNode['legacy_id'] ?? '');
|
||||
if ($legacyId !== '') {
|
||||
$proclamatoreMap[$legacyId] = $p->id;
|
||||
}
|
||||
}
|
||||
|
||||
$annoMap = [];
|
||||
foreach (($xml->anni_teocratici->anno ?? []) as $annoNode) {
|
||||
// Gruppi di servizio, dopo i proclamatori: il sorvegliante è uno di
|
||||
// loro. Poi i collegamenti che li aspettavano (membri, utenze).
|
||||
$gruppoMap = [];
|
||||
foreach (($xml->gruppi_servizio->gruppo ?? []) as $gruppoNode) {
|
||||
$legacySorvegliante = (string) ($gruppoNode->legacy_sorvegliante_id ?? '');
|
||||
$g = GruppoServizio::create([
|
||||
'nome' => (string) $gruppoNode->nome,
|
||||
'sorvegliante_id' => $proclamatoreMap[$legacySorvegliante] ?? null,
|
||||
'sciolto_at' => $this->normalizeDateTimeForDb((string) ($gruppoNode->sciolto_at ?? '')),
|
||||
]);
|
||||
$this->applyRowMeta('gruppi_servizio', $g->id, $gruppoNode);
|
||||
$legacyId = (string) ($gruppoNode['legacy_id'] ?? '');
|
||||
if ($legacyId !== '') {
|
||||
$gruppoMap[$legacyId] = $g->id;
|
||||
}
|
||||
}
|
||||
foreach ($gruppiDeiProclamatori as $idProclamatore => $legacyGruppo) {
|
||||
if (isset($gruppoMap[$legacyGruppo])) {
|
||||
DB::table('proclamatori')->where('id', $idProclamatore)->update(['gruppo_servizio_id' => $gruppoMap[$legacyGruppo]]);
|
||||
}
|
||||
}
|
||||
foreach ($utentiDaCollegare as $idUtente => $collegamento) {
|
||||
DB::table('users')->where('id', $idUtente)->update([
|
||||
'proclamatore_id' => $proclamatoreMap[$collegamento['proclamatore']] ?? null,
|
||||
'disattivato_at' => $collegamento['disattivato_at'],
|
||||
]);
|
||||
}
|
||||
|
||||
$annoMap = []; foreach (($xml->anni_teocratici->anno ?? []) as $annoNode) {
|
||||
$label = (string) $annoNode->label;
|
||||
$anno = AnnoTeocratico::create([
|
||||
'label' => $label,
|
||||
@@ -706,6 +745,7 @@ class XmlExchange extends Component
|
||||
'note' => (string) ($territorioNode->note ?? ''),
|
||||
'attivo' => ((int) ($territorioNode->attivo ?? 1)) === 1,
|
||||
'prioritario' => ((int) ($territorioNode->prioritario ?? 0)) === 1,
|
||||
'gruppo_servizio_id' => $gruppoMap[(string) ($territorioNode->legacy_gruppo_id ?? '')] ?? null,
|
||||
'pdf_path' => $pdfPath !== '' ? $pdfPath : null,
|
||||
'thumbnail_path' => $thumbnailPath !== '' ? $thumbnailPath : null,
|
||||
]);
|
||||
@@ -768,6 +808,7 @@ class XmlExchange extends Component
|
||||
'campaign_id' => $legacyCampagna !== '' && isset($campagnaMap[$legacyCampagna]) ? $campagnaMap[$legacyCampagna] : null,
|
||||
'link_sent' => ((int) ($assegnazioneNode->link_sent ?? 0)) === 1,
|
||||
'link_da_inviare' => ((int) ($assegnazioneNode->link_da_inviare ?? 0)) === 1,
|
||||
'gruppo_servizio_id' => $gruppoMap[(string) ($assegnazioneNode->legacy_gruppo_id ?? '')] ?? null,
|
||||
'link_canale' => in_array((string) ($assegnazioneNode->link_canale ?? ''), array_keys(Assegnazione::CANALI_LINK), true) ? (string) $assegnazioneNode->link_canale : null,
|
||||
'pdf_access_code' => $pdfAccessCode !== '' ? $pdfAccessCode : null,
|
||||
'note' => (string) ($assegnazioneNode->note ?? ''),
|
||||
@@ -824,16 +865,20 @@ class XmlExchange extends Component
|
||||
// remember_token no: all'import si azzera comunque, e nel file
|
||||
// sarebbe solo una credenziale in più per chi lo tiene.
|
||||
'roles' => $u->roles->pluck('name')->all(),
|
||||
// Sorvegliante di gruppo: il proclamatore collegato e se l'utenza è disattivata.
|
||||
'proclamatore_id' => $u->proclamatore_id ? (string) $u->proclamatore_id : '',
|
||||
'disattivato_at' => optional($u->disattivato_at)->toIso8601String() ?? '',
|
||||
'created_at' => optional($u->created_at)->toIso8601String() ?? '',
|
||||
'updated_at' => optional($u->updated_at)->toIso8601String() ?? '',
|
||||
])->all(),
|
||||
'zones' => $this->righeEsportate(Zona::query()->orderBy('id'), ['id', 'nome', 'attivo', 'created_at', 'updated_at']),
|
||||
'tipologie' => $this->righeEsportate(Tipologia::query()->orderBy('id'), ['id', 'nome', 'attivo', 'created_at', 'updated_at']),
|
||||
'proclamatori' => $this->righeEsportate(Proclamatore::query()->withTrashed()->orderBy('id'), ['id', 'nome', 'cognome', 'attivo', 'deleted_at', 'created_at', 'updated_at']),
|
||||
'territori' => $this->righeEsportate(Territorio::query()->withTrashed()->orderBy('id'), ['id', 'numero', 'zona_id', 'tipologia_id', 'confini', 'note', 'attivo', 'prioritario', 'pdf_path', 'thumbnail_path', 'deleted_at', 'created_at', 'updated_at']),
|
||||
'proclamatori' => $this->righeEsportate(Proclamatore::query()->withTrashed()->orderBy('id'), ['id', 'nome', 'cognome', 'attivo', 'gruppo_servizio_id', 'deleted_at', 'created_at', 'updated_at']),
|
||||
'gruppi_servizio' => $this->righeEsportate(GruppoServizio::query()->orderBy('id'), ['id', 'nome', 'sorvegliante_id', 'sciolto_at', 'created_at', 'updated_at']),
|
||||
'territori' => $this->righeEsportate(Territorio::query()->withTrashed()->orderBy('id'), ['id', 'numero', 'zona_id', 'tipologia_id', 'confini', 'note', 'attivo', 'prioritario', 'gruppo_servizio_id', 'pdf_path', 'thumbnail_path', 'deleted_at', 'created_at', 'updated_at']),
|
||||
'anni_teocratici' => $this->righeEsportate(AnnoTeocratico::query()->orderBy('id'), ['id', 'label', 'start_date', 'end_date', 'created_at', 'updated_at']),
|
||||
'campagne' => $this->righeEsportate(Campagna::query()->orderBy('id'), ['id', 'descrizione', 'start_date', 'end_date', 'created_at', 'updated_at']),
|
||||
'assegnazioni' => $this->righeEsportate(Assegnazione::query()->orderBy('id'), ['id', 'territorio_id', 'proclamatore_id', 'anno_teocratico_id', 'campaign_id', 'assigned_at', 'returned_at', 'counted_in_campaign', 'note', 'created_by', 'returned_by', 'link_sent', 'link_da_inviare', 'link_canale', 'pdf_access_code', 'created_at', 'updated_at']),
|
||||
'assegnazioni' => $this->righeEsportate(Assegnazione::query()->orderBy('id'), ['id', 'territorio_id', 'proclamatore_id', 'anno_teocratico_id', 'campaign_id', 'assigned_at', 'returned_at', 'counted_in_campaign', 'note', 'created_by', 'returned_by', 'link_sent', 'link_da_inviare', 'link_canale', 'gruppo_servizio_id', 'pdf_access_code', 'created_at', 'updated_at']),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1232,6 +1277,8 @@ class XmlExchange extends Component
|
||||
$this->addXmlText($node, 'email', (string) ($user['email'] ?? ''));
|
||||
$this->addXmlText($node, 'password', (string) ($user['password'] ?? ''));
|
||||
$node->addChild('email_verified_at', (string) ($user['email_verified_at'] ?? ''));
|
||||
$node->addChild('legacy_proclamatore_id', (string) ($user['proclamatore_id'] ?? ''));
|
||||
$node->addChild('disattivato_at', (string) ($user['disattivato_at'] ?? ''));
|
||||
$node->addChild('created_at', (string) ($user['created_at'] ?? ''));
|
||||
$node->addChild('updated_at', (string) ($user['updated_at'] ?? ''));
|
||||
$rolesNode = $node->addChild('roles');
|
||||
@@ -1265,6 +1312,7 @@ class XmlExchange extends Component
|
||||
$this->addXmlText($node, 'nome', (string) ($proclamatore['nome'] ?? ''));
|
||||
$this->addXmlText($node, 'cognome', (string) ($proclamatore['cognome'] ?? ''));
|
||||
$node->addChild('attivo', (string) ((int) ($proclamatore['attivo'] ?? 1)));
|
||||
$node->addChild('legacy_gruppo_id', (string) ($proclamatore['gruppo_servizio_id'] ?? ''));
|
||||
$node->addChild('deleted_at', (string) ($proclamatore['deleted_at'] ?? ''));
|
||||
$this->addTimestampNodes($node, $proclamatore);
|
||||
}
|
||||
@@ -1280,6 +1328,7 @@ class XmlExchange extends Component
|
||||
$this->addXmlText($node, 'note', (string) ($territorio['note'] ?? ''));
|
||||
$node->addChild('attivo', (string) ((int) ($territorio['attivo'] ?? 1)));
|
||||
$node->addChild('prioritario', (string) ((int) ($territorio['prioritario'] ?? 0)));
|
||||
$node->addChild('legacy_gruppo_id', (string) ($territorio['gruppo_servizio_id'] ?? ''));
|
||||
$this->addXmlText($node, 'pdf_path', (string) ($territorio['pdf_path'] ?? ''));
|
||||
$this->addXmlText($node, 'thumbnail_path', (string) ($territorio['thumbnail_path'] ?? ''));
|
||||
$node->addChild('deleted_at', (string) ($territorio['deleted_at'] ?? ''));
|
||||
@@ -1296,6 +1345,17 @@ class XmlExchange extends Component
|
||||
$this->addTimestampNodes($node, $anno);
|
||||
}
|
||||
|
||||
// Gruppi di servizio: il sorvegliante è un proclamatore (legacy id).
|
||||
$gruppiNode = $xml->addChild('gruppi_servizio');
|
||||
foreach (($dataset['gruppi_servizio'] ?? []) as $gruppo) {
|
||||
$node = $gruppiNode->addChild('gruppo');
|
||||
$this->addLegacyIdAttribute($node, $gruppo);
|
||||
$this->addXmlText($node, 'nome', (string) ($gruppo['nome'] ?? ''));
|
||||
$node->addChild('legacy_sorvegliante_id', (string) ($gruppo['sorvegliante_id'] ?? ''));
|
||||
$node->addChild('sciolto_at', (string) ($gruppo['sciolto_at'] ?? ''));
|
||||
$this->addTimestampNodes($node, $gruppo);
|
||||
}
|
||||
|
||||
$campagneNode = $xml->addChild('campagne');
|
||||
foreach ($dataset['campagne'] as $campagna) {
|
||||
$node = $campagneNode->addChild('campagna');
|
||||
@@ -1321,6 +1381,7 @@ class XmlExchange extends Component
|
||||
$node->addChild('counted_in_campaign', (string) ((int) ($assegnazione['counted_in_campaign'] ?? 0)));
|
||||
$node->addChild('link_sent', (string) ((int) ($assegnazione['link_sent'] ?? 0)));
|
||||
$node->addChild('link_da_inviare', (string) ((int) ($assegnazione['link_da_inviare'] ?? 0)));
|
||||
$node->addChild('legacy_gruppo_id', (string) ($assegnazione['gruppo_servizio_id'] ?? ''));
|
||||
$this->addXmlText($node, 'link_canale', (string) ($assegnazione['link_canale'] ?? ''));
|
||||
$this->addXmlText($node, 'pdf_access_code', (string) ($assegnazione['pdf_access_code'] ?? ''));
|
||||
$this->addXmlText($node, 'note', (string) ($assegnazione['note'] ?? ''));
|
||||
|
||||
Reference in New Issue
Block a user