Aggiunta Checklist

This commit is contained in:
Thomas Zilio 2019-07-26 16:24:20 +02:00
parent 94e2049ad2
commit 4d6b15a217
21 changed files with 679 additions and 42 deletions

View File

@ -3,6 +3,8 @@
include_once __DIR__.'/core.php';
use Models\Note;
use Models\Checklist;
use Models\User;
if (empty($structure) || empty($structure['enabled'])) {
die(tr('Accesso negato'));
@ -105,8 +107,8 @@ elseif (filter('op') == 'add_nota') {
flash()->info(tr('Nota interna aggiunta correttamente!'));
}
// Aggiunta nota interna
elseif (filter('op') == 'remove_nota') {
// Rimozione nota interna
elseif (filter('op') == 'delete_nota') {
$id_nota = post('id_nota');
$nota = Note::find($id_nota);
@ -115,6 +117,39 @@ elseif (filter('op') == 'remove_nota') {
flash()->info(tr('Nota interna aggiunta correttamente!'));
}
// Rimozione checklist
elseif (filter('op') == 'add_check') {
$content = post('content');
$parent_id = post('parent') ?: null;
$assigned_user = User::find(post('assigned_user'));
$check = Checklist::build($user, $assigned_user, $structure, $id_record, $content, $parent_id);
}
// Rimozione checklist
elseif (filter('op') == 'delete_check') {
$check_id = post('check_id');
$check = Checklist::find($check_id);
$check->delete();
}
// Gestione check per le checklist
elseif (filter('op') == 'toggle_check') {
$check_id = post('check_id');
$check = Checklist::find($check_id);
if (!empty($check)) {
$check->checked_at = $check->checked_at ? null : date('Y-m-d H:i:s');
$check->save();
echo json_encode([
'checked_at' => timestampFormat($check->checked_at) ?: null,
]);
}
}
// Invio email
elseif (post('op') == 'send-email') {
$id_template = post('template');

View File

@ -54,6 +54,11 @@ switch (get('op')) {
break;
case 'checklists':
echo '{( "name": "checklists", "id_module": "'.$id_module.'", "id_record": "'.$id_record.'", "id_plugin": "'.$id_plugin.'" )}';
break;
case 'active_users':
$posizione = get('id_module');
if (isset($id_record)) {

View File

@ -826,7 +826,7 @@ input.small-width {
margin-bottom: 5px;
}
.skin-default .nav.navbar-nav li a{
.skin-default .nav.navbar-nav li a{
color: #FFFFFF;
}
.skin-default .nav.navbar-nav li a:hover{
@ -845,8 +845,48 @@ input.small-width {
hyphens: auto;
}
.request .morelink{
color: #fff;
font-weight: bold;
}
/* Checklist */
ul.checklist {
list-style-type: none;
margin: 0;
padding: 0;
}
ul.checklist li {
cursor: pointer;
position: relative;
padding: 12px 8px 12px 10px;
font-size: 18px;
transition: 0.2s;
/* make the list items unselectable */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
ul.checklist li:hover {
background: #ddd;
}
ul.checklist li.checked {
background: #eee;
}
ul.checklist li.checked > .check-text {
text-decoration: line-through;
}
ul.checklist li > .check-icon {
display: none;
}
ul.checklist li.checked > .check-icon {
display: inline-block;
}

View File

@ -0,0 +1,86 @@
$(document).ready(function () {
$('#supersearch').keyup(function () {
$(document).ajaxStop();
if ($(this).val() == '') {
$(this).removeClass('wait');
} else {
$(this).addClass('wait');
}
});
$.widget("custom.supersearch", $.ui.autocomplete, {
_create: function () {
this._super();
this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)");
},
_renderMenu: function (ul, items) {
if (items[0].value == undefined) {
$('#supersearch').removeClass('wait');
ul.html('');
} else {
var that = this,
currentCategory = "";
ul.addClass('ui-autocomplete-scrollable');
ul.css('z-index', '999');
$.each(items, function (index, item) {
if (item.category != currentCategory) {
ul.append("<li class='ui-autocomplete-category'>" + item.category + "</li>");
currentCategory = item.category;
}
that._renderItemData(ul, item);
});
}
},
_renderItem: function (ul, item) {
return $("<li>")
.append("<a href='" + item.link + "' title='Clicca per aprire'><b>" + item.value + "</b><br/>" + item.label + "</a>")
.appendTo(ul);
}
});
// Configurazione supersearch
var $super = $('#supersearch').supersearch({
minLength: 3,
select: function (event, ui) {
location.href = ui.item.link;
},
source: function (request, response) {
$.ajax({
url: globals.rootdir + '/ajax_search.php',
dataType: "json",
data: {
term: request.term
},
complete: function (jqXHR) {
$('#supersearch').removeClass('wait');
},
success: function (data) {
if (data == null) {
response($.map(['a'], function (item) {
return false;
}));
} else {
response($.map(data, function (item) {
labels = (item.labels).toString();
labels = labels.replace('<br/>,', '<br/>');
return {
label: labels,
category: item.category,
link: item.link,
value: item.title
}
}));
}
}
});
}
});
});

View File

@ -333,7 +333,7 @@ if (empty($record) || !$has_access) {
if ($user->is_admin || $utente->id == $user->id) {
echo '
<button type="button" class="btn btn-danger btn-xs ask" data-op="remove_nota" data-id_nota="'.$nota->id.'" data-msg="'.tr('Rimuovere questa nota?').'" data-backto="record-edit">
<button type="button" class="btn btn-danger btn-xs ask" data-op="delete_nota" data-id_nota="'.$nota->id.'" data-msg="'.tr('Rimuovere questa nota?').'" data-backto="record-edit">
<i class="fa fa-trash-o"></i>
</button>';
}

View File

@ -280,7 +280,7 @@ $(document).ready(function () {
removeHash();
}
});
// Nel caso la navigazione sia da mobile, disabilito il ritorno al punto precedente
if (!isMobile.any()) {
// Salvo lo scroll per riportare qui l'utente al reload
@ -1034,6 +1034,7 @@ function start_datepickers() {
});
});
}
// Select
function start_superselect() {
// Statico
@ -1790,3 +1791,14 @@ function removeHash() {
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find, "g"), replace);
}
function restart_input() {
start_datepickers();
start_inputmask();
$('.superselect, .superselectajax').select2().select2("destroy");
start_superselect();
// Autosize per le textarea
autosize($('.autosize'));
}

View File

@ -23,9 +23,6 @@ $(document).ready(function () {
});
});
// Autosize per le textarea
autosize($('.autosize'));
if ($('form').length) {
$('form').not('.no-check').parsley();
}
@ -34,8 +31,6 @@ $(document).ready(function () {
this.$element.removeClass('parsley-success');
});
start_datepickers();
// Aggiunta nell'URL del nome tab su cui tornare dopo il submit
// Blocco del pulsante di submit dopo il primo submit
$("form").submit(function () {
@ -65,6 +60,5 @@ $(document).ready(function () {
return false;
});
start_superselect();
start_inputmask();
restart_input();
});

View File

@ -94,7 +94,7 @@ $_SESSION['superselect']['idsede_destinazione'] = $record['idsede_destinazione']
<div class="col-md-3">
{[ "type": "timestamp", "label": "<?php echo tr('Data/ora richiesta'); ?>", "name": "data_richiesta", "required": 1, "value": "$data_richiesta$", "readonly": "<?php echo $record['flag_completato']; ?>" ]}
</div>
<div class="col-md-3">
{[ "type": "timestamp", "label": "<?php echo tr('Data/ora scadenza'); ?>", "name": "data_scadenza", "required": 0, "value": "$data_scadenza$", "readonly": "<?php echo $record['flag_completato']; ?>" ]}
</div>
@ -286,6 +286,8 @@ include $structure->filepath('ajax_righe.php');
</div>
</form>
{( "name": "checklists", "id_module": "$id_module$", "id_record": "$id_record$" )}
{( "name": "filelist_and_upload", "id_module": "$id_module$", "id_record": "$id_record$", <?php echo ($record['flag_completato']) ? '"readonly": 1' : '"readonly": 0'; ?> )}
<!-- EVENTUALE FIRMA GIA' EFFETTUATA -->
@ -355,15 +357,15 @@ include $structure->filepath('ajax_righe.php');
//session_set('superselect,idzona', $(this).selectData().idzona, 0);
}
});
$('#codice_cig, #codice_cup').bind("keyup change", function(e) {
if ($('#codice_cig').val() == '' && $('#codice_cup').val() == '' ){
$('#id_documento_fe').prop('required', false);
}else{
$('#id_documento_fe').prop('required', true);
}
});
</script>

View File

@ -4,7 +4,7 @@ include_once __DIR__.'/../../../core.php';
switch ($resource) {
case 'anagrafiche_utenti':
$query = 'SELECT `an_anagrafiche`.`idanagrafica` AS id, `an_anagrafiche`.`ragione_sociale` AS "descrizione", `an_tipianagrafiche`.`descrizione` AS optgroup FROM `an_tipianagrafiche` INNER JOIN `an_tipianagrafiche_anagrafiche` ON `an_tipianagrafiche`.`idtipoanagrafica`=`an_tipianagrafiche_anagrafiche`.`idtipoanagrafica` INNER JOIN `an_anagrafiche` ON `an_anagrafiche`.`idanagrafica`=`an_tipianagrafiche_anagrafiche`.`idanagrafica` |where| ORDER BY `optgroup` ASC';
$query = 'SELECT `an_anagrafiche`.`idanagrafica` AS id, `an_anagrafiche`.`ragione_sociale` AS descrizione, `an_tipianagrafiche`.`descrizione` AS optgroup FROM `an_tipianagrafiche` INNER JOIN `an_tipianagrafiche_anagrafiche` ON `an_tipianagrafiche`.`idtipoanagrafica`=`an_tipianagrafiche_anagrafiche`.`idtipoanagrafica` INNER JOIN `an_anagrafiche` ON `an_anagrafiche`.`idanagrafica`=`an_tipianagrafiche_anagrafiche`.`idanagrafica` |where| ORDER BY `optgroup` ASC';
$where[] = 'an_anagrafiche.deleted_at IS NULL';
@ -44,5 +44,54 @@ switch ($resource) {
];
}
break;
case 'utenti':
$query = "SELECT zz_users.id AS id, if(`an_anagrafiche`.`idanagrafica` IS NOT NULL, CONCAT(`an_anagrafiche`.`ragione_sociale`, ' (', zz_users.username, ')'), zz_users.username) AS descrizione, `an_tipianagrafiche`.`descrizione` AS optgroup
FROM zz_users
LEFT JOIN `an_anagrafiche` ON `an_anagrafiche`.`idanagrafica` = `zz_users`.`idanagrafica`
INNER JOIN `an_tipianagrafiche_anagrafiche` ON `an_anagrafiche`.`idanagrafica`=`an_tipianagrafiche_anagrafiche`.`idanagrafica`
INNER JOIN `an_tipianagrafiche` ON `an_tipianagrafiche`.`idtipoanagrafica`=`an_tipianagrafiche_anagrafiche`.`idtipoanagrafica`
|where| ORDER BY `optgroup` ASC";
$where[] = 'an_anagrafiche.deleted_at IS NULL';
foreach ($elements as $element) {
$filter[] = 'zz_users.id='.prepare($element);
}
if (!empty($search)) {
$search_fields[] = 'an_anagrafiche.ragione_sociale LIKE '.prepare('%'.$search.'%');
$search_fields[] = 'zz_users.username LIKE '.prepare('%'.$search.'%');
}
if (!empty($search_fields)) {
$where[] = '('.implode(' OR ', $search_fields).')';
}
if (!empty($filter)) {
$where[] = '('.implode(' OR ', $filter).')';
}
$wh = '';
if (count($where) != 0) {
$wh = 'WHERE '.implode(' AND ', $where);
}
$query = str_replace('|where|', $wh, $query);
$rs = $dbo->fetchArray($query);
foreach ($rs as $r) {
if ($prev != $r['optgroup']) {
$results[] = ['text' => $r['optgroup'], 'children' => []];
$prev = $r['optgroup'];
}
$results[count($results) - 1]['children'][] = [
'id' => $r['id'],
'text' => $r['descrizione'],
'descrizione' => $r['descrizione'],
];
}
break;
}

View File

@ -75,6 +75,7 @@ class HTMLBuilder
protected static $managers = [
'list' => [
'filelist_and_upload' => Manager\FileManager::class,
'checklists' => Manager\ChecklistManager::class,
'button' => Manager\ButtonManager::class,
'csrf' => Manager\CSRFManager::class,
'custom_fields' => Manager\FieldManager::class,

View File

@ -0,0 +1,263 @@
<?php
namespace HTMLBuilder\Manager;
use Models\Checklist;
use Modules;
use Plugins;
/**
* Gestione delle checklist.
*
* @since 2.4.11
*/
class ChecklistManager implements ManagerInterface
{
/**
* Gestione "checklists".
* Esempio: {( "name": "checklists", "id_module": "2", "id_record": "1", "readonly": "false" )}.
*
* @param array $options
*
* @return string
*/
public function manage($options)
{
$module = Modules::get($options['id_module']);
$plugin = Plugins::get($options['id_plugin']);
$structure = isset($plugin) ? $plugin : $module;
// ID del form
$manager_id = 'checklist_'.$options['id_module'].'_'.$options['id_plugin'];
$checklists = $structure->checklists($options['id_record']);
$list = [];
foreach ($checklists as $checklist) {
$list [] = [
'id' => $checklist->id,
'text' => $checklist->content,
];
}
$result = '
<div class="panel panel-primary" id="'.$manager_id.'">
<div class="panel-heading">
<h3 class="panel-title">'.tr('Checklist').'</h3>
</div>
<div class="panel-body">
<div id="loading_'.$manager_id.'" class="text-center hide" style="position:relative;top:100px;z-index:2;opacity:0.5;">
<i class="fa fa-refresh fa-spin fa-3x fa-fw"></i><span class="sr-only">'.tr('Caricamento...').'</span>
</div>';
// Form per la creazione di una nuova checklist
if (!$options['readonly']) {
$result .= '
<div id="checklist-form" class="row">
<div class="col-md-6">
{[ "type": "text", "placeholder": "'.tr('Contenuto').'", "name": "content", "class": "unblockable", "required": 1 ]}
</div>
<div class="col-md-3">
{[ "type": "select", "placeholder": "'.tr('Genitore').'", "name": "parent", "class": "unblockable", "values": '.json_encode($list).' ]}
</div>
<div class="col-md-2">
{[ "type": "select", "placeholder": "'.tr('Utente').'", "name": "assigned_user", "class": "unblockable", "ajax-source": "utenti", "required": 1 ]}
</div>
<div class="col-md-1 text-right">
<button type="button" class="btn btn-success" onclick="addCheck(this)">
<i class="fa fa-upload"></i> '.tr('Crea').'
</button>
</div>
</div>
<hr>';
}
$result .= '
<ul class="checklist">';
foreach ($checklists as $checklist) {
$result .= $this->renderChecklist($checklist);
}
$result .= '
</ul>
</div>
</div>';
$result .= '
<script src="'.ROOTDIR.'/lib/init.js"></script>
<script>
$(document).ready(function() {
$(".check-item").click(function(event){
var id = $(this).attr("id").replace("check_", "");
toggleCheck(id);
});
$(".check-delete").click(function(event){
var li = $(this).closest("li");
var id = li.attr("id").replace("check_", "");
console.log(id);
deleteCheck(id);
event.stopPropagation();
});
});
var data = {
id_module: "'.$options['id_module'].'",
id_plugin: "'.$options['id_plugin'].'",
id_record: "'.$options['id_record'].'",
};
function addCheck(btn) {
$form = $(btn).closest("#checklist-form");
var continua = true;
$form.find(":input:not(:button)").each(function (index, value) {
continua &= $(this).parsley().validate();
});
if (!continua) {
swal({
type: "error",
title: "'.tr('Errore').'",
text: "'.tr('Alcuni campi obbligatori non sono stati compilati correttamente.').'",
});
return;
}
show_loader_'.$manager_id.'()
var info = JSON.parse(JSON.stringify(data));
info.op = "add_check";
$form.ajaxSubmit({
url: globals.rootdir + "/actions.php",
data: info,
type: "post",
success: function(data){
reload_'.$manager_id.'();
},
error: function(data) {
alert("'.tr('Errore').': " + data);
}
});
}
function deleteCheck(id) {
swal({
title: "'.tr("Rimuovere l'elemento della checklist?").'",
html: "'.tr('Tutti gli elementi figli saranno rimossi di conseguenza. Continuare?').'",
showCancelButton: true,
confirmButtonText: "'.tr('Procedi').'",
type: "error",
}).then(function (result) {
var check = findCheck(id);
check.icon.removeClass("fa-check").addClass("fa-refresh fa-spin bg-danger").show();
var info = JSON.parse(JSON.stringify(data));
info.op = "delete_check";
info.check_id = id;
show_loader_'.$manager_id.'();
$.ajax({
url: globals.rootdir + "/actions.php",
cache: false,
type: "POST",
data: info,
success: function(data) {
reload_'.$manager_id.'()
}
});
});
}
function toggleCheck(id) {
var check = findCheck(id);
check.icon.removeClass("fa-check").addClass("fa-refresh fa-spin").show();
var info = JSON.parse(JSON.stringify(data));
info.op = "toggle_check";
info.check_id = id;
$.ajax({
url: globals.rootdir + "/actions.php",
cache: false,
type: "POST",
data: info,
success: function(data) {
if(!data) return;
data = JSON.parse(data);
check.icon.removeClass("fa-refresh fa-spin")
check.date.text(data.checked_at);
if (data.checked_at){
check.item.addClass("checked");
check.icon.addClass("fa-check")
} else {
check.item.removeClass("checked");
}
}
});
}
function findCheck(id) {
var li = $("#check_" + id);
return {
item: li,
icon: li.find(".check-icon"),
date: li.find(".check-date"),
text: li.find(".check-text"),
children: li.find(".check-children"),
};
}
function show_loader_'.$manager_id.'() {
$("#loading_'.$manager_id.'").removeClass("hide");
}
function reload_'.$manager_id.'() {
$("#'.$manager_id.'").load(globals.rootdir + "/ajax.php?op=checklists&id_module='.$options['id_module'].'&id_record='.$options['id_record'].'&id_plugin='.$options['id_plugin'].'", function() {
$("#loading_'.$manager_id.'").addClass("hide");
});
}
</script>';
return $result;
}
protected function renderChecklist(Checklist $checklist, $level = 0)
{
$result = '
<li id="check_'.$checklist->id.'" class="check-item'.(!empty($checklist->checked_at) ? ' checked' : '').'">
'.str_repeat('&nbsp;', $level * 8).'
<i class="check-icon fa fa-check"></i>
<span class="check-text">'.$checklist->content.'</span>
<div class="pull-right">
<span class="badge check-date">'.timestampFormat($checklist->checked_at).'</span>
<i class="fa fa-close check-delete"></i>
</div>
</li>
<ul class="checklist" class="check-children">';
$children = $checklist->children;
foreach ($children as $child) {
$result .= $this->renderChecklist($child, $level + 1);
}
$result .= '
</ul>';
return $result;
}
}

View File

@ -241,7 +241,6 @@ function show_'.$attachment_id.'() {
}
function reload_'.$attachment_id.'() {
$("#'.$attachment_id.'").load(globals.rootdir + "/ajax.php?op=list_attachments&id_module='.$options['id_module'].'&id_record='.$options['id_record'].'&id_plugin='.$options['id_plugin'].'", function() {
$("#loading_'.$attachment_id.'").addClass("hide");
});

71
src/Models/Checklist.php Normal file
View File

@ -0,0 +1,71 @@
<?php
namespace Models;
use Common\Model;
use Traits\HierarchyTrait;
use Traits\NoteTrait;
class Checklist extends Model
{
use HierarchyTrait;
protected static $parent_identifier = 'id_parent';
protected $table = 'zz_checklists';
/**
* Crea un nuovo elemento della checklist.
*
* @param User $user
* @param User $assigned_user
* @param NoteTrait $structure
* @param int $id_record
* @param string $contenuto
* @param int $id_parent
*
* @return self
*/
public static function build(User $user, User $assigned_user, $structure, $id_record, $contenuto, $id_parent = null)
{
$model = parent::build();
$model->user()->associate($user);
$model->assignedUser()->associate($assigned_user);
if ($structure instanceof Module) {
$model->module()->associate($structure);
} elseif ($structure instanceof Plugin) {
$model->plugin()->associate($structure);
}
$model->id_record = $id_record;
$model->id_parent = $id_parent;
$model->content = $contenuto;
$model->save();
return $model;
}
/* Relazioni Eloquent */
public function user()
{
return $this->belongsTo(User::class, 'id_utente');
}
public function assignedUser()
{
return $this->belongsTo(User::class, 'id_utente_assegnato');
}
public function plugin()
{
return $this->belongsTo(Plugin::class, 'id_plugin');
}
public function module()
{
return $this->belongsTo(Module::class, 'id_module');
}
}

View File

@ -5,10 +5,11 @@ namespace Models;
use Auth;
use Common\Model;
use Illuminate\Database\Eloquent\Builder;
use Traits\Components\ChecklistTrait;
use Traits\Components\NoteTrait;
use Traits\Components\UploadTrait;
use Traits\ManagerTrait;
use Traits\NoteTrait;
use Traits\StoreTrait;
use Traits\UploadTrait;
class Module extends Model
{
@ -16,11 +17,11 @@ class Module extends Model
use UploadTrait;
use StoreTrait;
use NoteTrait;
use ChecklistTrait;
protected $table = 'zz_modules';
protected $main_folder = 'modules';
protected $upload_identifier = 'id_module';
protected $note_identifier = 'id_module';
protected $component_identifier = 'id_module';
protected $variables = [];

View File

@ -5,10 +5,11 @@ namespace Models;
use App;
use Common\Model;
use Illuminate\Database\Eloquent\Builder;
use Traits\Components\ChecklistTrait;
use Traits\Components\NoteTrait;
use Traits\Components\UploadTrait;
use Traits\ManagerTrait;
use Traits\NoteTrait;
use Traits\StoreTrait;
use Traits\UploadTrait;
class Plugin extends Model
{
@ -18,11 +19,11 @@ class Plugin extends Model
getUploadDirectoryAttribute as protected defaultUploadDirectory;
}
use NoteTrait;
use ChecklistTrait;
protected $table = 'zz_plugins';
protected $main_folder = 'plugins';
protected $upload_identifier = 'id_plugin';
protected $note_identifier = 'id_plugin';
protected $component_identifier = 'id_plugin';
protected $appends = [
'permission',

View File

@ -0,0 +1,13 @@
<?php
namespace Traits\Components;
use Models\Checklist;
trait ChecklistTrait
{
public function checklists($id_record)
{
return $this->hasMany(Checklist::class, $this->component_identifier)->where('id_record', $id_record)->whereNull('id_parent')->orderBy('created_at')->get();
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Traits\Components;
use Models\Note;
trait NoteTrait
{
public function notes($id_record)
{
return $this->hasMany(Note::class, $this->component_identifier)->where('id_record', $id_record)->orderBy('created_at')->get();
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Traits;
namespace Traits\Components;
use Models\Upload;
@ -25,6 +25,6 @@ trait UploadTrait
public function uploads($id_record)
{
return $this->hasMany(Upload::class, $this->upload_identifier)->where('id_record', $id_record)->get();
return $this->hasMany(Upload::class, $this->component_identifier)->where('id_record', $id_record)->get();
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Traits;
trait HierarchyTrait
{
public function children()
{
return $this->hasMany(self::class, self::$parent_identifier);
}
public function parent()
{
return $this->belongsTo(self::class, self::$parent_identifier);
}
public function allParents()
{
return $this->parent()->with('allParents');
}
public function allChildren()
{
return $this->children()->with('allChildren');
}
public static function getHierarchy()
{
return self::with('allChildren')
->whereNull(self::$parent_identifier)
->get();
}
}

View File

@ -1,13 +0,0 @@
<?php
namespace Traits;
use Models\Note;
trait NoteTrait
{
public function notes($id_record)
{
return $this->hasMany(Note::class, $this->note_identifier)->where('id_record', $id_record)->orderBy('created_at')->get();
}
}

View File

@ -203,3 +203,35 @@ CREATE TABLE IF NOT EXISTS `zz_notes` (
FOREIGN KEY (`id_plugin`) REFERENCES `zz_plugins`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_utente`) REFERENCES `zz_users`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
-- Sistema di checklists
CREATE TABLE IF NOT EXISTS `zz_checklists` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_module` int(11),
`id_plugin` int(11),
`id_record` int(11) NOT NULL,
`id_utente` int(11) NOT NULL,
`id_utente_assegnato` int(11) NOT NULL,
`checked_at` TIMESTAMP,
`content` TEXT,
`id_parent` int(11),
PRIMARY KEY (`id`),
FOREIGN KEY (`id_module`) REFERENCES `zz_modules`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_plugin`) REFERENCES `zz_plugins`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_utente`) REFERENCES `zz_users`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_utente_assegnato`) REFERENCES `zz_users`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_parent`) REFERENCES `zz_checklists`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `zz_checklist_templates` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_module` int(11),
`id_plugin` int(11),
`id_record` int(11) NOT NULL,
`content` TEXT,
`id_parent` int(11),
PRIMARY KEY (`id`),
FOREIGN KEY (`id_module`) REFERENCES `zz_modules`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_plugin`) REFERENCES `zz_plugins`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_parent`) REFERENCES `zz_checklist_templates`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;