@@ -138,7 +138,7 @@ function avviaControllo(controllo) {
138138 }
139139
140140 // Creazione pannello informativo e aggiunta righe
141- let card = initcard(controllo, success);
141+ let card = initcard(controllo, success, records );
142142 for(const record of records) {
143143 addRiga(controllo, card, record);
144144 }
@@ -192,9 +192,10 @@ function setPercentage(percent) {
192192*
193193* @param controllo
194194* @param success
195+ * @param records
195196* @returns {*|jQuery|HTMLElement}
196197*/
197- function initcard(controllo, success) {
198+ function initcard(controllo, success, records ) {
198199 let cssClass = "";
199200 let icon = "minus";
200201 if (success) {
@@ -205,23 +206,41 @@ function initcard(controllo, success) {
205206 let card = `<div class="card ` + cssClass + `" id="controllo-` + controllo["id"] + `">
206207 <div class="card-header with-border">
207208 <h3 class="card-title">` + controllo["name"] + `</h3>
208- <div class="card-tools pull-right">
209+ <div class="card-tools pull-right">`;
210+
211+ // Aggiungi pulsante azione globale se il controllo lo supporta e ci sono record
212+ if (!success && records.length > 0 && hasGlobalActions(controllo)) {
213+ card += `
214+ <button type="button" class="btn btn-success btn-sm" data-controllo-id="` + controllo["id"] + `" data-controllo-class="` + controllo["class"] + `" onclick="eseguiAzioneGlobale(this)">
215+ <i class="fa fa-check-circle"></i> ' .tr ('Risolvi tutti i conflitti ' ).'
216+ </button>`;
217+ }
218+
219+ card += `
209220 <button type="button" class="btn btn-tool" data-widget="collapse">
210221 <i class="fa fa-` + icon + `"></i>
211222 </button>
212223 </div>
213224 </div>`
214225
215226 if (!success) {
227+ // Verifica se ci sono opzioni per le singole righe
228+ let hasRowOptions = records.length > 0 && records[0].options && records[0].options.length > 0;
229+
216230 card += `
217231 <div class="card-body">
218232 <div class="table-responsive">
219233 <table class="table table-striped table-hover table-sm table-bordered">
220234 <thead>
221235 <tr>
222236 <th width="15%"> ' .tr ('Record ' ).'</th>
223- <th> ' .tr ('Descrizione ' ).'</th>
224- <th class="text-center" width="15%"> ' .tr ('Opzioni ' ).'</th>
237+ <th> ' .tr ('Descrizione ' ).'</th>`;
238+
239+ if (hasRowOptions) {
240+ card += `<th class="text-center" width="15%"> ' .tr ('Opzioni ' ).'</th>`;
241+ }
242+
243+ card += `
225244 </tr>
226245 </thead>
227246 <tbody></tbody>
@@ -244,32 +263,201 @@ function initcard(controllo, success) {
244263*/
245264function addRiga(controllo, card, record) {
246265 let body = card.find("tbody");
266+ let hasOptions = record.options && record.options.length > 0;
247267
248268 // Generazione riga
249269 let riga = `<tr class="` + record.type + `" id="controllo-` + controllo["id"] + `-` + record.id + `">
250270 <td>` + record.nome + `</td>
251- <td>` + record.descrizione + `</td>
252- <td></td>
253- </tr>`;
271+ <td>` + record.descrizione + `</td>`;
272+
273+ if (hasOptions) {
274+ riga += `<td></td>`;
275+ }
276+
277+ riga += `</tr>`;
254278 riga = $(riga);
255279
256- // Generazione opzioni
257- const options_columns = riga.find("td").last();
258- record.options.forEach(function (option, id){
259- let button = `<button type="button" class="btn btn-` + option.color + `">
260- <i class="` + option.icon + `"></i> ` + option.name + `
261- </buttton>`;
262- button = $(button);
263-
264- button.on("click", function () {
265- option.params.id = id;
266- eseguiAzione(controllo, record, option.params);
280+ // Generazione opzioni solo se presenti
281+ if (hasOptions) {
282+ const options_columns = riga.find("td").last();
283+ record.options.forEach(function (option, id){
284+ let button = `<button type="button" class="btn btn-` + option.color + `">
285+ <i class="` + option.icon + `"></i> ` + option.name + `
286+ </buttton>`;
287+ button = $(button);
288+
289+ button.on("click", function () {
290+ option.params.id = id;
291+ eseguiAzione(controllo, record, option.params);
292+ });
293+
294+ options_columns.append(button);
267295 });
296+ }
297+
298+ body.append(riga);
299+ }
268300
269- options_columns.append(button);
301+ /**
302+ * Verifica se un controllo supporta azioni globali
303+ * @param controllo
304+ * @returns {boolean}
305+ */
306+ function hasGlobalActions(controllo) {
307+ // Lista dei controlli che supportano azioni globali
308+ const controlliConAzioniGlobali = [
309+ "Modules \\\\Aggiornamenti \\\\Controlli \\\\PianoContiRagioneSociale"
310+ ];
311+
312+ return controlliConAzioniGlobali.includes(controllo["class"]);
313+ }
314+
315+ /**
316+ * Esegue un \'azione globale su tutti i record di un controllo
317+ * @param buttonElement
318+ */
319+ function eseguiAzioneGlobale(buttonElement) {
320+ let button = $(buttonElement);
321+ let controlloId = button.data("controllo-id");
322+ let controlloClass = button.data("controllo-class");
323+
324+ // Crea modal di conferma con lo stile del gestionale
325+ let modalHtml = `
326+ <div class="modal fade" id="modal-conferma-risoluzione" tabindex="-1" role="dialog">
327+ <div class="modal-dialog modal-lg" role="document">
328+ <div class="modal-content">
329+ <div class="modal-header">
330+ <h4 class="modal-title">
331+ <i class="fa fa-exclamation-triangle text-warning"></i>
332+ ' .tr ('Conferma risoluzione conflitti ' ).'
333+ </h4>
334+ <button type="button" class="close" data-dismiss="modal">
335+ <span>×</span>
336+ </button>
337+ </div>
338+ <div class="modal-body">
339+ <p> ' .tr ('Sei sicuro di voler risolvere tutti i conflitti? ' ).'</p>
340+ <div class="alert alert-warning">
341+ <i class="fa fa-info-circle"></i>
342+ ' .tr ('Questa operazione: ' ).'
343+ <ul class="mb-0 mt-2">
344+ <li> ' .tr ('Creerà nuovi conti per le anagrafiche con conflitti multipli ' ).'</li>
345+ <li> ' .tr ('Aggiornerà i movimenti contabili collegati ' ).'</li>
346+ <li> ' .tr ('Eliminerà i conti vuoti non più utilizzati ' ).'</li>
347+ <li> ' .tr ('Non può essere annullata ' ).'</li>
348+ </ul>
349+ </div>
350+ </div>
351+ <div class="modal-footer">
352+ <button type="button" class="btn btn-default" data-dismiss="modal" style="float: left;">
353+ <i class="fa fa-times"></i> ' .tr ('Annulla ' ).'
354+ </button>
355+ <button type="button" class="btn btn-warning" id="conferma-risoluzione" style="float: right;">
356+ <i class="fa fa-check"></i> ' .tr ('Procedi ' ).'
357+ </button>
358+ <div style="clear: both;"></div>
359+ </div>
360+ </div>
361+ </div>
362+ </div>
363+ `;
364+
365+ // Rimuovi modal esistente se presente
366+ $("#modal-conferma-risoluzione").remove();
367+
368+ // Aggiungi modal al DOM
369+ $("body").append(modalHtml);
370+
371+ // Mostra modal con configurazione per evitare chiusura accidentale
372+ $("#modal-conferma-risoluzione").modal({
373+ backdrop: "static",
374+ keyboard: false,
375+ show: true
270376 });
271377
272- body.append(riga);
378+ // Gestisci click su conferma
379+ $("#conferma-risoluzione").on("click", function(e) {
380+ e.preventDefault();
381+ e.stopPropagation();
382+
383+ let confirmButton = $(this);
384+ let restoreConfirm = buttonLoading(confirmButton);
385+
386+ // Disabilita il pulsante di annulla durante l \'operazione
387+ $("#modal-conferma-risoluzione .btn-default").prop("disabled", true);
388+
389+ eseguiRisoluzioneGlobale(button, controlloId, controlloClass, function() {
390+ // Callback di successo: chiudi modal
391+ $("#modal-conferma-risoluzione").modal("hide");
392+ }, function() {
393+ // Callback di errore: ripristina pulsanti
394+ buttonRestore(confirmButton, restoreConfirm);
395+ $("#modal-conferma-risoluzione .btn-default").prop("disabled", false);
396+ });
397+
398+ return false;
399+ });
400+ }
401+
402+ /**
403+ * Esegue effettivamente la risoluzione globale
404+ */
405+ function eseguiRisoluzioneGlobale(button, controlloId, controlloClass, successCallback, errorCallback) {
406+ let restore = buttonLoading(button);
407+
408+ $.ajax({
409+ url: globals.rootdir + "/actions.php",
410+ type: "POST",
411+ dataType: "JSON",
412+ data: {
413+ id_module: globals.id_module,
414+ op: "controlli-action-global",
415+ controllo: controlloClass,
416+ params: {},
417+ },
418+ success: function(results) {
419+ // Rimuovi tutte le righe del controllo
420+ $("#controllo-" + controlloId + " tbody tr").remove();
421+
422+ // Nascondi il pulsante di azione globale
423+ button.hide();
424+
425+ // Mostra messaggio di successo dettagliato
426+ let successMessage = `
427+ <div class="alert alert-success">
428+ <h4><i class="fa fa-check-circle"></i> ' .tr ('Risoluzione completata con successo! ' ).'</h4>
429+ <p> ' .tr ('Tutti i conflitti sono stati risolti. I conti sono stati aggiornati e i movimenti contabili sono stati rigenerati. ' ).'</p>
430+ </div>
431+ `;
432+
433+ $("#controllo-" + controlloId + " .card-body").html(successMessage);
434+
435+ buttonRestore(button, restore);
436+
437+ // Chiama il callback di successo
438+ if (typeof successCallback === "function") {
439+ successCallback();
440+ }
441+ },
442+ error: function(xhr, r, error) {
443+ let errorMessage = xhr.responseJSON && xhr.responseJSON.error ? xhr.responseJSON.error.message : error;
444+
445+ let errorHtml = `
446+ <div class="alert alert-danger">
447+ <h4><i class="fa fa-exclamation-triangle"></i> ' .tr ('Errore durante la risoluzione ' ).'</h4>
448+ <p> ' .tr ('Si è verificato un errore ' ).': ${errorMessage}</p>
449+ </div>
450+ `;
451+
452+ $("#controllo-" + controlloId + " .card-body").prepend(errorHtml);
453+ buttonRestore(button, restore);
454+
455+ // Chiama il callback di errore
456+ if (typeof errorCallback === "function") {
457+ errorCallback();
458+ }
459+ }
460+ });
273461}
274462</script>
275463
0 commit comments