This commit is contained in:
Beppe 2023-01-27 15:17:15 +01:00
commit a00a54c57a
28 changed files with 555 additions and 239 deletions

View File

@ -22,15 +22,15 @@
@font-face {
font-family: 'Source Sans Pro';
src: local('Source Sans Pro'),
url('../fonts/sourcesanspro-regular-webfont.eot') format('embedded-opentype'),
url('../fonts/sourcesanspro-regular-webfont.woff') format('woff'),
url('../fonts/sourcesanspro-regular-webfont.woff2') format('woff2'),
url('../fonts/sourcesanspro-regular-webfont.ttf') format('truetype'),
url('../fonts/sourcesanspro-regular-webfont.svg') format('svg');
src: local('Source Sans Pro'),
url('../fonts/sourcesanspro-regular-webfont.eot') format('embedded-opentype'),
url('../fonts/sourcesanspro-regular-webfont.woff') format('woff'),
url('../fonts/sourcesanspro-regular-webfont.woff2') format('woff2'),
url('../fonts/sourcesanspro-regular-webfont.ttf') format('truetype'),
url('../fonts/sourcesanspro-regular-webfont.svg') format('svg');
}
html{
html {
font-size: 13px;
height: 100%;
}
@ -88,7 +88,8 @@ input[type=file] {
position: fixed;
}
.autocomplete, .ui-autocomplete {
.autocomplete,
.ui-autocomplete {
background: white;
z-index: 10000;
min-width: 160px;
@ -102,12 +103,13 @@ input[type=file] {
border-radius: 5px;
}
.autocomplete .group, .ui-autocomplete-category {
.autocomplete .group,
.ui-autocomplete-category {
font-size: 1.5em;
background: inherit;
}
.autocomplete > div {
.autocomplete>div {
padding: 5px;
}
@ -115,8 +117,8 @@ input[type=file] {
background: #FFFF66;
}
.autocomplete > div:hover:not(.group),
.autocomplete > div.selected {
.autocomplete>div:hover:not(.group),
.autocomplete>div.selected {
background: #F5F5F5;
cursor: pointer;
}
@ -144,8 +146,10 @@ input[type=file] {
.navbar a:hover,
.logo:hover,
.alert a, .alert a:hover,
a:hover, a:focus {
.alert a,
.alert a:hover,
a:hover,
a:focus {
text-decoration: none;
}
@ -191,13 +195,13 @@ a:hover, a:focus {
filter: alpha(opacity=90);
}
#main_loading > div {
#main_loading>div {
position: relative;
top: 50%;
color: #333;
}
#main_loading > div > i {
#main_loading>div>i {
font-size: 300px;
margin-top: -150px;
color: #e24e1e;
@ -213,7 +217,7 @@ a:hover, a:focus {
background: rgba(0, 0, 0, 0.15);
}
#mini-loader > div {
#mini-loader>div {
position: absolute;
bottom: 50%;
left: 50%;
@ -244,9 +248,9 @@ body .header .logo {
border-color: rgba(0, 0, 0, 0.2) !important;
}
.navbar-custom-menu > ul > li > a:hover,
.navbar-custom-menu > ul > li > a:focus,
.navbar-custom-menu > ul > li > a:active {
.navbar-custom-menu>ul>li>a:hover,
.navbar-custom-menu>ul>li>a:focus,
.navbar-custom-menu>ul>li>a:active {
filter: brightness(75%);
}
@ -289,7 +293,7 @@ span.form-control {
padding: 5px 8px;
}
.dropdown.col-md-3 > .dropdown-menu {
.dropdown.col-md-3>.dropdown-menu {
width: 91.5%;
left: 15px;
padding: 5px;
@ -318,6 +322,7 @@ span.form-control {
.widget li {
margin-left: 0;
list-style-type: none;
height: 106px;
}
.widget {
@ -364,18 +369,18 @@ span.form-control {
font-size: 11px;
}
.nav-tabs-custom > .nav-tabs.pull-right > li > a.back-btn {
.nav-tabs-custom>.nav-tabs.pull-right>li>a.back-btn {
font-size: 12px;
color: #FFFFFF;
}
.navbar-nav > .notifications-menu > .dropdown-menu > li .menu > li > a,
.navbar-nav > .messages-menu > .dropdown-menu > li .menu > li > a,
.navbar-nav > .tasks-menu > .dropdown-menu > li .menu > li > a {
.navbar-nav>.notifications-menu>.dropdown-menu>li .menu>li>a,
.navbar-nav>.messages-menu>.dropdown-menu>li .menu>li>a,
.navbar-nav>.tasks-menu>.dropdown-menu>li .menu>li>a {
white-space: normal;
}
.nav-tabs-custom > .nav-tabs.pull-right > li > a.back-btn:hover {
.nav-tabs-custom>.nav-tabs.pull-right>li>a.back-btn:hover {
cursor: pointer;
color: #72AFD2;
}
@ -531,7 +536,7 @@ span.form-control {
border: 0px;
}
.input-group-addon.no-padding > * {
.input-group-addon.no-padding>* {
border-radius: 0px;
}
@ -557,7 +562,7 @@ input.small-width {
}
@media (max-width: 480px) {
#main_loading > div > i {
#main_loading>div>i {
font-size: 160px;
margin-top: -80px;
}
@ -594,12 +599,13 @@ input.small-width {
}
@media screen and (max-width: 992px) {
.table-bordered > thead > tr > th,
.table-bordered > tbody > tr > th,
.table-bordered > tfoot > tr > th,
.table-bordered > thead > tr > td,
.table-bordered > tbody > tr > td,
.table-bordered > tfoot > tr > td {
.table-bordered>thead>tr>th,
.table-bordered>tbody>tr>th,
.table-bordered>tfoot>tr>th,
.table-bordered>thead>tr>td,
.table-bordered>tbody>tr>td,
.table-bordered>tfoot>tr>td {
word-break: break-all;
}
}
@ -656,7 +662,7 @@ input.small-width {
top: -10000px;
}
.box-info ul > li > :last-child {
.box-info ul>li> :last-child {
margin-bottom: 5px;
}
@ -686,7 +692,7 @@ input.small-width {
background: #fff;
}
.component-loader > div {
.component-loader>div {
position: relative;
top: 50%;
color: #333;
@ -715,8 +721,14 @@ input.small-width {
cursor: pointer;
}
.fc-event {
border-top-width: 10px;
.fc-event.fc-h-event,
.fc-event.fc-v-event {
border-top-width: 10px !important;
border-style: solid;
}
.fc-daygrid-dot-event {
padding: 0 !important;
}
.fc-event-primary {
@ -732,21 +744,21 @@ input.small-width {
/* Fix per tabs editor */
.nav-tabs-custom > .nav-tabs > li {
.nav-tabs-custom>.nav-tabs>li {
border-top: 3px solid #ddd;
}
.nav-tabs-custom > .nav-tabs.pull-right > li:first-of-type.active > a {
.nav-tabs-custom>.nav-tabs.pull-right>li:first-of-type.active>a {
border-right-color: #f4f4f4;
border-right-width: 1px;
border-left-width: 0px;
}
.nav-tabs-custom > .nav-tabs > li.header {
.nav-tabs-custom>.nav-tabs>li.header {
padding: 0px;
}
.nav-tabs-custom > .nav-tabs > li {
.nav-tabs-custom>.nav-tabs>li {
margin-bottom: -1px;
margin-right: 0px;
}
@ -787,32 +799,32 @@ input.small-width {
margin-left: -4.5px;
}
.timeline > li {
.timeline>li {
margin-bottom: 20px;
position: relative;
}
.timeline > li:before,
.timeline > li:after {
.timeline>li:before,
.timeline>li:after {
content: " ";
display: table;
}
.timeline > li:after {
.timeline>li:after {
clear: both;
}
.timeline > li:before,
.timeline > li:after {
.timeline>li:before,
.timeline>li:after {
content: " ";
display: table;
}
.timeline > li:after {
.timeline>li:after {
clear: both;
}
.timeline > li > .timeline-panel {
.timeline>li>.timeline-panel {
width: 50%;
float: left;
border: 1px solid #d4d4d4;
@ -823,20 +835,20 @@ input.small-width {
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.175);
}
.timeline > li.timeline-inverted + li:not(.timeline-inverted),
.timeline > li:not(.timeline-inverted) + li.timeline-inverted {
.timeline>li.timeline-inverted+li:not(.timeline-inverted),
.timeline>li:not(.timeline-inverted)+li.timeline-inverted {
margin-top: -60px;
}
.timeline > li:not(.timeline-inverted) {
.timeline>li:not(.timeline-inverted) {
padding-right: 90px;
}
.timeline > li.timeline-inverted {
.timeline>li.timeline-inverted {
padding-left: 90px;
}
.timeline > li > .timeline-panel:before {
.timeline>li>.timeline-panel:before {
position: absolute;
top: 26px;
right: -15px;
@ -848,7 +860,7 @@ input.small-width {
content: " ";
}
.timeline > li > .timeline-panel:after {
.timeline>li>.timeline-panel:after {
position: absolute;
top: 27px;
right: -14px;
@ -860,7 +872,7 @@ input.small-width {
content: " ";
}
.timeline > li > .timeline-badge {
.timeline>li>.timeline-badge {
color: #fff;
width: 50px;
height: 50px;
@ -879,18 +891,18 @@ input.small-width {
border-bottom-left-radius: 50%;
}
.timeline > li.timeline-inverted > .timeline-panel {
.timeline>li.timeline-inverted>.timeline-panel {
float: right;
}
.timeline > li.timeline-inverted > .timeline-panel:before {
.timeline>li.timeline-inverted>.timeline-panel:before {
border-left-width: 0;
border-right-width: 15px;
left: -15px;
right: auto;
}
.timeline > li.timeline-inverted > .timeline-panel:after {
.timeline>li.timeline-inverted>.timeline-panel:after {
border-left-width: 0;
border-right-width: 14px;
left: -14px;
@ -922,12 +934,12 @@ input.small-width {
color: inherit;
}
.timeline-body > p,
.timeline-body > ul {
.timeline-body>p,
.timeline-body>ul {
margin-bottom: 0;
}
.timeline-body > p + p {
.timeline-body>p+p {
margin-top: 5px;
}
@ -1000,33 +1012,33 @@ div.tip {
display: none;
}
.checkbox-group input[type="checkbox"] + .btn-group > label span {
.checkbox-group input[type="checkbox"]+.btn-group>label span {
/*width: 20px;*/
}
.checkbox-group input[type="checkbox"] + .btn-group {
.checkbox-group input[type="checkbox"]+.btn-group {
width: 100%;
display: flex;
overflow: auto;
}
.checkbox-group input[type="checkbox"] + .btn-group label:last-child {
.checkbox-group input[type="checkbox"]+.btn-group label:last-child {
flex-grow: 100;
}
.checkbox-group input[type="checkbox"] + .btn-group > label span:first-child {
.checkbox-group input[type="checkbox"]+.btn-group>label span:first-child {
display: none;
}
.checkbox-group input[type="checkbox"] + .btn-group > label span:last-child {
.checkbox-group input[type="checkbox"]+.btn-group>label span:last-child {
display: inline-block;
}
.checkbox-group input[type="checkbox"]:checked + .btn-group > label span:first-child {
.checkbox-group input[type="checkbox"]:checked+.btn-group>label span:first-child {
display: inline-block;
}
.checkbox-group input[type="checkbox"]:checked + .btn-group > label span:last-child {
.checkbox-group input[type="checkbox"]:checked+.btn-group>label span:last-child {
display: none;
}
@ -1049,7 +1061,7 @@ div.tip {
}
.control-sidebar.control-sidebar-open,
.control-sidebar.control-sidebar-open + .control-sidebar-bg {
.control-sidebar.control-sidebar-open+.control-sidebar-bg {
right: 0;
}
@ -1078,7 +1090,7 @@ div.tip {
height: 0
}
.local-loader > div {
.local-loader>div {
position: absolute;
top: 100px;
z-index: 2;
@ -1091,7 +1103,8 @@ div.tip {
}
/* Stile Fullcalendar per weekend */
.fc-sat, .fc-sun {
.fc-sat,
.fc-sun {
background-color: rgba(255, 99, 71, 0.6) !important;
}
@ -1107,12 +1120,12 @@ div.tip {
user-select: none;
}
.table-extra-condensed > thead > tr > th,
.table-extra-condensed > tbody > tr > th,
.table-extra-condensed > tfoot > tr > th,
.table-extra-condensed > thead > tr > td,
.table-extra-condensed > tbody > tr > td,
.table-extra-condensed > tfoot > tr > td {
.table-extra-condensed>thead>tr>th,
.table-extra-condensed>tbody>tr>th,
.table-extra-condensed>tfoot>tr>th,
.table-extra-condensed>thead>tr>td,
.table-extra-condensed>tbody>tr>td,
.table-extra-condensed>tfoot>tr>td {
padding: 2px;
}
@ -1127,14 +1140,16 @@ div.tip {
@media (min-width: 768px) {
.sidebar-mini:not(.sidebar-mini-expand-feature).sidebar-collapse .sidebar-menu > li:hover > a > span:not(.pull-right),
.sidebar-mini:not(.sidebar-mini-expand-feature).sidebar-collapse .sidebar-menu > li:hover > .treeview-menu {
.sidebar-mini:not(.sidebar-mini-expand-feature).sidebar-collapse .sidebar-menu>li:hover>a>span:not(.pull-right),
.sidebar-mini:not(.sidebar-mini-expand-feature).sidebar-collapse .sidebar-menu>li:hover>.treeview-menu {
width: 220px;
}
.sidebar-mini:not(.sidebar-mini-expand-feature).sidebar-collapse .sidebar-menu > li:hover > a > .pull-right-container {
.sidebar-mini:not(.sidebar-mini-expand-feature).sidebar-collapse .sidebar-menu>li:hover>a>.pull-right-container {
left: 220px !important;
}
html body.sidebar-mini.sidebar-mini.sidebar-collapse i.fa.fa-user-circle-o.fa-3x.pull-left{
html body.sidebar-mini.sidebar-mini.sidebar-collapse i.fa.fa-user-circle-o.fa-3x.pull-left {
font-size: 2.4em;
}
}

View File

@ -98,7 +98,9 @@ const JS = gulp.parallel(() => {
'dropzone/dist/dropzone.js',
'autonumeric/dist/autoNumeric.min.js',
'eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js',
'fullcalendar/dist/fullcalendar.js',
'fullcalendar-scheduler/index.global.js',
'@fullcalendar/moment/index.global.js',
'@fullcalendar/core/locales/it.global.js',
'geocomplete/jquery.geocomplete.js',
'inputmask/dist/min/jquery.inputmask.bundle.min.js',
'jquery-form/src/jquery.form.js',
@ -161,7 +163,6 @@ const CSS = gulp.parallel(() => {
'dropzone/dist/dropzone.css',
'eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css',
'font-awesome/css/font-awesome.min.css',
'fullcalendar/dist/fullcalendar.css',
'parsleyjs/src/parsley.css',
'select2/dist/css/select2.min.css',
'sweetalert2/dist/sweetalert2.css',
@ -208,7 +209,6 @@ function srcCSS() {
const print = gulp.src([
config.development + '/' + config.paths.css + '/print/*.{css,scss,less,styl}',
config.nodeDirectory + '/fullcalendar/fullcalendar.print.css',
], {
allowEmpty: true
})

View File

@ -147,6 +147,28 @@ function discountInfo(Accounting $riga, $mostra_maggiorazione = true)
]);
}
/**
* Visualizza le informazioni relative allo provvigione presente su una riga.
*
* @param bool $mostra_provigione
*
* @return string|null
*/
function provvigioneInfo(Accounting $riga, $mostra_provigione = true)
{
if (empty($riga->provvigione_unitaria) || (!$mostra_provigione && $riga->provvigione_unitaria < 0)) {
return null;
}
$text = $riga->provvigione_unitaria > 0 ? tr('provvigione _TOT_ _TYPE_') : tr('provvigione _TOT__TYPE_');
$totale = !empty($riga->provvigione_percentuale) ? $riga->provvigione_percentuale : $riga->provvigione_unitaria;
return replace($text, [
'_TOT_' => Translator::numberToLocale(abs($totale)),
'_TYPE_' => !empty($riga->provvigione_percentuale) ? '%' : currency(),
]);
}
/**
* Genera i riferimenti ai documenti del gestionale, attraverso l'interfaccia Common\ReferenceInterface.
*

View File

@ -21,6 +21,8 @@ use Carbon\Carbon;
include_once __DIR__.'/../../../core.php';
$filter_agente = Auth::user()['gruppo'] == 'Agenti';
switch ($resource) {
case 'clienti':
$id_azienda = setting('Azienda predefinita');
@ -71,6 +73,10 @@ switch ($resource) {
$where[] = 'an_anagrafiche.deleted_at IS NULL';
}
if (empty(!$filter_agente)) {
$where[] = 'idagente = '.Auth::user()['idanagrafica'];
}
if (!empty($search)) {
$search_fields[] = 'ragione_sociale LIKE '.prepare('%'.$search.'%');
$search_fields[] = 'citta LIKE '.prepare('%'.$search.'%');

View File

@ -427,34 +427,22 @@ if ($is_cliente or $is_fornitore or $is_tecnico) {
<div class="tab-content '.(!$is_cliente && !$is_fornitore && !$is_tecnico ? 'hide' : '').'">
<div class="tab-pane '.(!$is_cliente && !$is_fornitore ? ' hide' : '').'" id="cliente_fornitore">
<!--div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Appoggio bancario').'", "name": "appoggiobancario", "value": "$appoggiobancario$" ]}
</div>
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Filiale banca').'", "name": "filiale", "value": "$filiale$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Codice IBAN').'", "name": "codiceiban", "value": "$codiceiban$" ]}
</div>
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Codice BIC').'", "name": "bic", "value": "$bic$" ]}
</div>
</div-->
<div class="row">
<div class="col-md-3">
{[ "type": "checkbox", "label": "'.tr('Abilitare lo split payment').'", "name": "split_payment", "value": "$split_payment$", "help": "'.tr('Lo split payment è disponibile per le anagrafiche di tipologia \"Ente pubblico\" o \"Azienda\" (iscritta al Dipartimento Finanze - Scissione dei pagamenti) ed <strong>&egrave; obbligatorio</strong> per:<ul><li>Stato;</li><li>organi statali ancorch&eacute; dotati di personalit&agrave; giuridica;</li><li>enti pubblici territoriali e dei consorzi tra essi costituiti;</li><li>Camere di Commercio;</li><li>Istituti universitari;</li><li>ASL e degli enti ospedalieri;</li><li>enti pubblici di ricovero e cura aventi prevalente carattere scientifico;</li><li>enti pubblici di assistenza e beneficienza;</li><li>enti di previdenza;</li><li>consorzi tra questi costituiti.</li></ul>').'", "placeholder": "'.tr('Split payment').'", "extra" : "'.($record['tipo'] == 'Ente pubblico' || $record['tipo'] == 'Azienda' ? '' : 'disabled').'" ]}
</div>
<div class="col-md-3">
{[ "type": "select", "label": "'.tr('Relazione').'", "name": "idrelazione", "ajax-source": "relazioni", "value": "$idrelazione$", "icon-after": "add|'.Modules::get('Relazioni')['id'].'" ]}
</div>
<div class="col-md-9">
{[ "type": "text", "label": "'.tr('Dicitura fissa in fattura').'", "name": "diciturafissafattura", "value": "$diciturafissafattura$" ]}
</div>
</div>
<div class="row">
</div>';
$banche = Banca::where('id_anagrafica', $anagrafica->id)->get();
@ -492,66 +480,61 @@ if ($is_cliente or $is_fornitore or $is_tecnico) {
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Provenienza cliente').'", "name": "id_provenienza", "ajax-source": "provenienze", "value": "$id_provenienza$", "icon-after": "add|'.Modules::get('Provenienze')['id'].'" ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Relazione con il cliente').'", "name": "idrelazione", "ajax-source": "relazioni", "value": "$idrelazione$", "icon-after": "add|'.Modules::get('Relazioni')['id'].'" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Pagamento predefinito').'", "name": "idpagamento_vendite", "values": "query=SELECT id, descrizione FROM co_pagamenti GROUP BY descrizione ORDER BY descrizione ASC", "value": "$idpagamento_vendite$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Banca predefinita per accrediti').'", "name": "idbanca_vendite", "ajax-source": "banche", "select-options": '.json_encode(['id_anagrafica' => $anagrafica_azienda->id]).', "value": "$idbanca_vendite$", "help": "'.tr("Banca predefinita dell'Azienda su cui accreditare i pagamenti").'" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Iva predefinita').'", "name": "idiva_vendite", "ajax-source": "iva", "value": "$idiva_vendite$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr("Ritenuta d'acconto predefinita").'", "name": "id_ritenuta_acconto_vendite", "values": "query=SELECT id, descrizione FROM co_ritenutaacconto ORDER BY descrizione ASC", "value": "$id_ritenuta_acconto_vendite$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Piano di sconto/magg. su articoli').'", "name": "id_piano_sconto_vendite", "values": "query=SELECT id, nome AS descrizione FROM mg_piani_sconto ORDER BY nome ASC", "value": "$id_piano_sconto_vendite$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Indirizzo di fatturazione').'", "name": "idsede_fatturazione", "values": "query=SELECT id, IF(citta = \'\', nomesede, CONCAT_WS(\', \', nomesede, citta)) AS descrizione FROM an_sedi WHERE idanagrafica='.prepare($id_record).' UNION SELECT \'0\' AS id, \'Sede legale\' AS descrizione ORDER BY descrizione", "value": "$idsede_fatturazione$" ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Agente principale').'", "name": "idagente", "values": "query=SELECT an_anagrafiche.idanagrafica AS id, IF(deleted_at IS NOT NULL, CONCAT(ragione_sociale, \' (Eliminato)\'), ragione_sociale ) AS descrizione FROM an_anagrafiche INNER JOIN (an_tipianagrafiche_anagrafiche INNER JOIN an_tipianagrafiche ON an_tipianagrafiche_anagrafiche.idtipoanagrafica=an_tipianagrafiche.idtipoanagrafica) ON an_anagrafiche.idanagrafica=an_tipianagrafiche_anagrafiche.idanagrafica WHERE (descrizione=\'Agente\' AND deleted_at IS NULL)'.(isset($record['idagente']) ? 'OR (an_anagrafiche.idanagrafica = '.prepare($record['idagente']).' AND deleted_at IS NOT NULL) ' : '').'ORDER BY ragione_sociale", "value": "$idagente$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Agente principale').'", "name": "idagente", "values": "query=SELECT an_anagrafiche.idanagrafica AS id, IF(deleted_at IS NOT NULL, CONCAT(ragione_sociale, \' (Eliminato)\'), ragione_sociale ) AS descrizione FROM an_anagrafiche INNER JOIN (an_tipianagrafiche_anagrafiche INNER JOIN an_tipianagrafiche ON an_tipianagrafiche_anagrafiche.idtipoanagrafica=an_tipianagrafiche.idtipoanagrafica) ON an_anagrafiche.idanagrafica=an_tipianagrafiche_anagrafiche.idanagrafica WHERE (descrizione=\'Agente\' AND deleted_at IS NULL)'.(isset($record['idagente']) ? 'OR (an_anagrafiche.idanagrafica = '.prepare($record['idagente']).' AND deleted_at IS NOT NULL) ' : '').'ORDER BY ragione_sociale", "value": "$idagente$" ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Agenti secondari').'", "multiple": "1", "name": "idagenti[]", "values": "query=SELECT an_anagrafiche.idanagrafica AS id, IF(deleted_at IS NOT NULL, CONCAT(ragione_sociale, \' (Eliminato)\'), ragione_sociale ) AS descrizione FROM an_anagrafiche INNER JOIN (an_tipianagrafiche_anagrafiche INNER JOIN an_tipianagrafiche ON an_tipianagrafiche_anagrafiche.idtipoanagrafica=an_tipianagrafiche.idtipoanagrafica) ON an_anagrafiche.idanagrafica=an_tipianagrafiche_anagrafiche.idanagrafica WHERE (descrizione=\'Agente\' AND deleted_at IS NULL AND an_anagrafiche.idanagrafica NOT IN (SELECT idagente FROM an_anagrafiche WHERE idanagrafica = '.prepare($record['idanagrafica']).')) OR (an_anagrafiche.idanagrafica IN (SELECT idagente FROM an_anagrafiche_agenti WHERE idanagrafica = '.prepare($record['idanagrafica']).') ) ORDER BY ragione_sociale", "value": "$idagenti$" ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Listino').'", "name": "id_listino", "ajax-source": "listini", "value": "$id_listino$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Listino').'", "name": "id_listino", "ajax-source": "listini", "value": "$id_listino$" ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Tipo attività predefinita').'", "name": "idtipointervento_default", "values": "query=SELECT idtipointervento AS id, descrizione FROM in_tipiintervento ORDER BY descrizione ASC", "value": "$idtipointervento_default$" ]}
</div>
</div>';
</div>';
// Collegamento con il conto
$conto = $dbo->fetchOne('SELECT co_pianodeiconti3.id, co_pianodeiconti2.numero as numero, co_pianodeiconti3.numero as numero_conto, co_pianodeiconti3.descrizione AS descrizione FROM co_pianodeiconti3 INNER JOIN co_pianodeiconti2 ON co_pianodeiconti3.idpianodeiconti2=co_pianodeiconti2.id WHERE co_pianodeiconti3.id = '.prepare($record['idconto_cliente']));
echo '
<div class="row">
<div class="col-md-6">
<p><b>'.tr('Piano dei conti cliente').'</b></p>';

View File

@ -162,8 +162,10 @@ switch (post('op')) {
Combinazione::sincronizzaVarianti($articolo);
// Leggo la quantità attuale per capire se l'ho modificata
$old_qta = $record['qta'];
$movimento = $qta - $old_qta;
// TODO: gestire la movimentazione manuale per sede
$id_sede = 0;
$old_qta = $articolo->getGiacenze(post('data_movimento'));
$movimento = $qta - $old_qta[$id_sede][0];
$qta_manuale = post('qta_manuale');
if (!empty($qta_manuale)) {

View File

@ -285,20 +285,29 @@ class Articolo extends Model
/**
* Restituisce le giacenze per sede dell'articolo.
*
* @param $data Indica la data fino alla quale calcolare le giacenze totali. Di default tutte
*
* @return array
*/
public function getGiacenze()
public function getGiacenze($data = null)
{
return $this->movimenti()
$movimenti = $this->movimenti()
->select(
'idsede',
database()->raw('SUM(qta) AS qta')
)->groupBy(['idsede'])
->get()
)->groupBy(['idsede']);
if (!empty($data)) {
$movimenti = $movimenti->where('data', '<=', \Carbon\Carbon::parse($data)->format('Y-m-d'));
}
$movimenti = $movimenti->get()
->mapToGroups(function ($item, $key) {
return [$item->idsede => (float) $item->attributes['qta']];
})
->toArray();
return $movimenti;
}
/**

View File

@ -67,6 +67,10 @@ class CSV extends CSVImporter
'field' => 'qta',
'label' => 'Quantità',
],
[
'field' => 'data_qta',
'label' => 'Data inventario',
],
[
'field' => 'um',
'label' => 'Unit&agrave; di misura',
@ -309,7 +313,7 @@ class CSV extends CSVImporter
$articolo->attivo = 1;
// Esportazione della quantità indicata
$qta_registrata = (float) ($record['qta']);
$nuova_qta = (float) ($record['qta']);
$nome_sede = $record['nome_sede'];
// Aggiornamento dettaglio prezzi
@ -406,10 +410,10 @@ class CSV extends CSVImporter
}
if( isset($record['qta']) ) {
$giacenze = $articolo->getGiacenze();
$qta_movimento = $qta_registrata - $giacenze[$id_sede][0];
$giacenze = $articolo->getGiacenze($record['data_qta']);
$qta_movimento = $nuova_qta - $giacenze[$id_sede][0];
$articolo->movimenta($qta_movimento, tr('Movimento da importazione'), new Carbon(), false, [
$articolo->movimenta($qta_movimento, tr('Movimento da importazione'), new Carbon($record['data_qta']), true, [
'idsede' => $id_sede,
]);
}

View File

@ -139,8 +139,16 @@ foreach ($righe as $riga) {
// Importo
echo '
<td class="text-right">
'.moneyFormat($riga->importo).'
</td>';
'.moneyFormat($riga->importo);
//provvigione riga
if (abs($riga->provvigione_unitaria) > 0) {
$text = provvigioneInfo($riga);
echo '
<br><small class="label label-info">'.$text.'</small>';
}
echo '</td>';
}
// Possibilità di rimuovere una riga solo se il preventivo non è stato pagato
@ -276,13 +284,24 @@ if(!empty($contratto->provvigione)) {
echo '
<tr>
<td colspan="6" class="text-right">
'.tr('Provvigioni').':
'.tr('Provvigioni', [], ['upper' => false]).':
</td>
<td class="text-right">
'.moneyFormat($contratto->provvigione).'
</td>
<td></td>
</tr>';
echo '
<tr>
<td colspan="6" class="text-right">
'.tr('Netto da provvigioni', [], ['upper' => false]).':
</td>
<td class="text-right">
'.moneyFormat($netto_a_pagare - $contratto->provvigione, 2).'
</td>
<td></td>
</tr>';
}
echo '

View File

@ -105,12 +105,14 @@ switch (filter('op')) {
$results[] = [
'id' => $sessione['id'],
'idintervento' => $sessione['idintervento'],
'idtecnico' => $sessione['idtecnico'],
'title' => (($sessione['is_completato']) ? '<i class="fa fa-lock" aria-hidden="true"></i>' : '').' '.(($sessione['have_attachments']) ? '<i class="fa fa-paperclip" aria-hidden="true"></i>' : '').($sessione['is_completato'] || $sessione['have_attachments'] ? '<br>' : '').'<b>Int. '.$sessione['codice'].'</b> '.$sessione['cliente'].'<br><b>'.tr('Tecnici').':</b> '.$sessione['nome_tecnico'],
'start' => $sessione['orario_inizio'],
'end' => $sessione['orario_fine'],
'link' => base_path().'/editor.php?id_module='.$modulo_interventi->id.'&id_record='.$sessione['idintervento'],
'extendedProps' => [
'link' => base_path().'/editor.php?id_module='.$modulo_interventi->id.'&id_record='.$sessione['idintervento'],
'idintervento' => $sessione['idintervento'],
'idtecnico' => $sessione['idtecnico'],
],
'backgroundColor' => $backgroundcolor,
'textColor' => color_inverse($backgroundcolor),
'borderColor' => empty($bordercolor) ? '#FFFFFF' : $bordercolor,
@ -190,13 +192,15 @@ switch (filter('op')) {
foreach ($alldays as $evento) {
$results[] = [
'id' => $modulo_eventi->id.'_'.$evento['id'],
'idintervento' => $evento['id'],
'idtecnico' => '',
'title' => '<b>'.tr('Evento').':</b> '.$evento['nome'].'<br>
<b>'.tr('Festività').':</b> '.($evento['is_bank_holiday'] ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>'),
'start' => $evento['data'],
'end' => $evento['data'],
'url' => base_path().'/editor.php?id_module='.$modulo_eventi->id.'&id_record='.$evento['id'],
'extendedProps' => [
'link' => base_path().'/editor.php?id_module='.$modulo_eventi->id.'&id_record='.$evento['id'],
'idintervento' => $evento['id'],
'idtecnico' => '',
],
'backgroundColor' => '#ffebcd',
'textColor' => color_inverse('#ffebcd'),
'borderColor' => '#ffebcd',
@ -435,7 +439,7 @@ switch (filter('op')) {
}
echo '
<div class="fc-event fc-event-'.$class.'" data-id="'.$sessione['id'].'" data-idcontratto="'.$sessione['idcontratto'].'" data-ref="'.$sessione['ref'].'" data-id_tecnico="'.$sessione['id_tecnico'].'">'.($sessione['ref'] == 'intervento' ? Modules::link($modulo_riferimento, $id_riferimento, '<i class="fa fa-wrench"></i>', null, 'title="'.tr('Visualizza scheda').'" class="btn btn-'.$class.' btn-xs pull-right"') : Modules::link($modulo_riferimento, $id_riferimento, '<i class="fa fa-file-text-o"></i>', null, 'title="'.tr('Visualizza scheda').'" class="btn btn-'.$class.' btn-xs pull-right"')).'
<div id="id-'.$sessione['id'].'" class="fc-event fc-event-'.$class.'" data-id="'.$sessione['id'].'" data-idcontratto="'.$sessione['idcontratto'].'" data-ref="'.$sessione['ref'].'" data-id_tecnico="'.$sessione['id_tecnico'].'">'.($sessione['ref'] == 'intervento' ? Modules::link($modulo_riferimento, $id_riferimento, '<i class="fa fa-wrench"></i>', null, 'title="'.tr('Visualizza scheda').'" class="btn btn-'.$class.' btn-xs pull-right"') : Modules::link($modulo_riferimento, $id_riferimento, '<i class="fa fa-file-text-o"></i>', null, 'title="'.tr('Visualizza scheda').'" class="btn btn-'.$class.' btn-xs pull-right"')).'
<b>'.$sessione['ragione_sociale'].'</b>
<br>'.dateFormat($sessione['data_richiesta']).' ('.$sessione['tipo_intervento'].')
<div class="request">'.(!empty($sessione['richiesta']) ? ' - '.$sessione['richiesta'] : '').'</div>

View File

@ -329,11 +329,11 @@ WHERE (SELECT COUNT(*) FROM in_interventi_tecnici WHERE in_interventi_tecnici.id
$vista = setting('Vista dashboard');
if ($vista == 'mese') {
$def = 'month';
$def = 'dayGridMonth';
} elseif ($vista == 'giorno') {
$def = 'agendaDay';
$def = 'resourceTimeGridDay';
} elseif ($vista == 'settimana') {
$def = 'agendaWeek';
$def = 'timeGridWeek';
} else {
$def = 'listWeek';
}
@ -341,8 +341,9 @@ if ($vista == 'mese') {
$modulo_interventi = Modules::get('Interventi');
echo '
<script type="text/javascript">
globals.dashboard = {
<script type="text/javascript">
var Draggable = FullCalendar.Draggable;
globals.dashboard = {
load_url: "'.$structure->fileurl('ajax.php').'?id_module='.$id_module.'",
style: "'.$def.'",
show_sunday: '.intval(setting('Visualizzare la domenica sul calendario')).',
@ -351,11 +352,6 @@ echo '
write_permission: '.intval($modulo_interventi->permission == 'rw').',
tooltip: '.intval(setting('Utilizzare i tooltip sul calendario')).',
calendar: null,
/* timeFormat: {
hour: "2-digit",
minute: "2-digit",
hour12: false
}, */
timeFormat: "H:mm",
select: {
title: "'.tr('Aggiungi intervento').'",
@ -419,15 +415,14 @@ echo '
$("#elenco-promemoria").html(data);
$("#external-events .fc-event").each(function () {
$(this).draggable({
zIndex: 999,
new Draggable( this, {
create: false,
revert: true,
revertDuration: 0,
eventData: {
title: $.trim($(this).text()),
stick: false
}
});
} );
});
});
}
@ -445,7 +440,7 @@ echo '
session_set_array("dashboard,idstatiintervento", id).then(function () {
aggiorna_contatore("#dashboard_stati");
globals.dashboard.calendar.fullCalendar("refetchEvents"); //.refetchEvents()
globals.dashboard.calendar.refetchEvents();
});
});
@ -455,7 +450,7 @@ echo '
session_set_array("dashboard,idtipiintervento", id).then(function () {
aggiorna_contatore("#dashboard_tipi");
globals.dashboard.calendar.fullCalendar("refetchEvents"); //.refetchEvents()
globals.dashboard.calendar.refetchEvents();
});
});
@ -465,7 +460,7 @@ echo '
session_set_array("dashboard,idtecnici", id).then(function () {
aggiorna_contatore("#dashboard_tecnici");
globals.dashboard.calendar.fullCalendar("refetchEvents"); //.refetchEvents()
globals.dashboard.calendar.refetchEvents();
});
});
@ -475,7 +470,7 @@ echo '
session_set_array("dashboard,idzone", id).then(function () {
aggiorna_contatore("#dashboard_zone");
globals.dashboard.calendar.fullCalendar("refetchEvents"); //.refetchEvents()
globals.dashboard.calendar.refetchEvents();
});
});
@ -509,25 +504,26 @@ echo '
var calendarElement = document.getElementById("calendar");
var clickCnt = 0;
var calendar = $(calendarElement).fullCalendar({
/* plugins: [interactionPlugin, dayGridPlugin, timeGridPlugin], */
var calendar = new FullCalendar.Calendar(calendarElement, {
//plugins: [adaptivePlugin, momentPlugin, dayGridPlugin, timeGridPlugin],
/* locales: allLocales, */
locale: globals.locale,
slotEventOverlap: false,
schedulerLicenseKey: "GPL-My-Project-Is-Open-Source",
hiddenDays: globals.dashboard.show_sunday ? [] : [0],
header: {
headerToolbar: {
left: "prev,next today",
center: "title",
right: "month,agendaWeek,agendaDay,listWeek"
right: "dayGridMonth,timeGridWeek,resourceTimeGridDay,listWeek"
},
eventDisplay: "block",
timeFormat: globals.dashboard.timeFormat,
slotLabelFormat: globals.dashboard.timeFormat,
slotDuration: "00:15:00",
snapDuration: globals.snapDuration,
defaultView: globals.dashboard.style,
minTime: globals.dashboard.start_time,
maxTime: globals.dashboard.end_time,
initialView: globals.dashboard.style,
slotMinTime: globals.dashboard.start_time,
slotMaxTime: globals.dashboard.end_time,
lazyFetching: true,
selectMirror: true,
eventLimit: false, // allow "more" link when too many events
@ -535,45 +531,47 @@ echo '
loading: function (isLoading, view) {
if (isLoading) {
$("#tiny-loader").fadeIn();
$("#tiny-loader").show();
} else {
$("#tiny-loader").hide();
}
},
droppable: globals.dashboard.write_permission,
drop: function (date) { // info
// let date = info.date;
drop: function (info) {
let date = info.date;
let data = moment(date).format("YYYY-MM-DD");
let ora_dal = moment(date).format("HH:mm");
let ora_al = moment(date).add(1, "hours").format("HH:mm");
let ref = $(this).data("ref");
let ref = info.draggedEl.dataset.ref;
let name;
if (ref === "promemoria") {
name = "idcontratto_riga";
} else {
name = "id_intervento";
}
openModal(globals.dashboard.drop.title, globals.dashboard.drop.url + "&data=" + data + "&orario_inizio=" + ora_dal + "&orario_fine=" + ora_al + "&ref=dashboard&idcontratto=" + $(this).data("idcontratto") + "&" + name + "=" + $(this).data("id") + "&id_tecnico=" + $(this).data("id_tecnico"));
openModal(globals.dashboard.drop.title, globals.dashboard.drop.url + "&data=" + data + "&orario_inizio=" + ora_dal + "&orario_fine=" + ora_al + "&ref=dashboard&idcontratto=" + info.draggedEl.dataset.idcontratto + "&" + name + "=" + info.draggedEl.dataset.id + "&id_tecnico=" + info.draggedEl.dataset.id_tecnico);
// Ricaricamento dei dati alla chiusura del modal
$(this).remove();
$("#modals > div").on("hidden.bs.modal", function () {
globals.dashboard.calendar.fullCalendar("refetchEvents"); //.refetchEvents()
globals.dashboard.calendar.refetchEvents();
let mese = $("#mese-promemoria").val();
carica_interventi_da_pianificare(mese);
});
},
eventReceive: function(info){
info.revert();
},
selectable: globals.dashboard.write_permission,
select: function (start, end, allDay) { // info
// let start = info.start;
// let end = info.end;
select: function (info) { // info
let start = info.start;
let end = info.end;
let intero_giorno = !start.hasTime() && !end.hasTime();
let intero_giorno = !start.hasTime && !end.hasTime;
if (intero_giorno !== true || globals.dashboard.informazioni_aggiuntive==0) {
let data = moment(start).format("YYYY-MM-DD");
let data_fine = moment(end).format("YYYY-MM-DD");
@ -581,7 +579,7 @@ echo '
let orario_fine = moment(end).format("HH:mm");
// Fix selezione di un giorno avanti per vista mensile
if (globals.dashboard.calendar.fullCalendar("getView").name == "month") {
if (globals.dashboard.calendar.view == "dayGridMonth") {
data_fine = moment(end).subtract(1, "days").format("YYYY-MM-DD");
}
@ -590,8 +588,8 @@ echo '
},
editable: globals.dashboard.write_permission,
eventDrop: function (event, delta, revertFunc) {// info
// let event = info.event;
eventDrop: function (info) {// info
let event = info.event;
if (event.allDay !== true) {
let start = event.start;
@ -599,7 +597,7 @@ echo '
$.post(globals.dashboard.load_url, {
op: "modifica_intervento",
id: event.id,
idintervento: event.idintervento,
idintervento: event.extendedProps.idintervento,
timeStart: moment(start).format("YYYY-MM-DD HH:mm"),
timeEnd: moment(end).format("YYYY-MM-DD HH:mm")
}, function (data, responseType) {
@ -612,22 +610,22 @@ echo '
}
if (data !== "ok") {
revertFunc(); // info.revert();
info.revert();
}
});
} else {
revertFunc();
info.revert();
}
},
eventResize: function (event, delta, revertFunc) { // info
// let event = info.event;
eventResize: function (info) {
let event = info.event;
let start = event.start;
let end = (event.end!=null ? event.end : event.start);
$.post(globals.dashboard.load_url, {
op: "modifica_intervento",
id: event.id,
idintervento: event.idintervento,
idintervento: event.extendedProps.idintervento,
timeStart: moment(start).format("YYYY-MM-DD HH:mm"),
timeEnd: moment(end).format("YYYY-MM-DD HH:mm")
}, function (data, responseType) {
@ -640,7 +638,7 @@ echo '
}
if (data !== "ok") {
revertFunc(); // info.revert();
info.revert();
}
});
@ -649,9 +647,9 @@ echo '
if(isMobile() && setting('Utilizzare i tooltip sul calendario')){
echo '
eventClick: function(info) {
let link = info.link;
let link = info.event.extendedProps.link;
let element = $(this);
clickCnt++;
clickCnt++;
if (clickCnt === 1) {
oneClickTimer = setTimeout(function() {
clickCnt = 0;
@ -666,18 +664,20 @@ if(isMobile() && setting('Utilizzare i tooltip sul calendario')){
}else{
echo '
eventClick: function(info) {
let link = info.link;
location.href = link;
info.jsEvent.preventDefault();
location.href = info.event.extendedProps.link;
},';
}
echo '
// eventPositioned: function (info) {
eventAfterRender: function (event, element) {
// let event = info.event;
// let element = $(info.el);
element.find(".fc-title, .fc-list-item-title").html(event.title);
let id_record = event.idintervento;
eventContent: function (info) {
return { html: info.event.title };
},
eventDidMount: function(info){
let element = $(info.el);
let id_record = info.event.extendedProps.idintervento;
if (globals.dashboard.tooltip == 1) {
element.tooltipster({
@ -700,7 +700,7 @@ echo '
$.post(globals.dashboard.load_url, {
op: "tooltip_info",
id_record: id_record,
allDay: event.allDay,
allDay: info.event.allDay,
}, function (data, response) {
instance.content(data);
@ -711,6 +711,7 @@ echo '
});
}
},
events: {
url: globals.dashboard.load_url + "&op=interventi_periodo",
type: "GET",
@ -720,7 +721,7 @@ echo '
}
});
//calendar.render();
calendar.render();
globals.dashboard.calendar = calendar;
}

View File

@ -177,8 +177,17 @@ foreach ($righe as $riga) {
// Importo
echo '
<td class="text-right">
'.moneyFormat($riga->importo).'
</td>';
'.moneyFormat($riga->importo);
//provvigione riga
if (abs($riga->provvigione_unitaria) > 0) {
$text = provvigioneInfo($riga);
echo '
<br><small class="label label-info">'.$text.'</small>';
}
echo ' </td>';
}
// Possibilità di rimuovere una riga solo se il ddt non è evaso
@ -340,6 +349,18 @@ if(!empty($ddt->provvigione)) {
</td>
<td></td>
</tr>';
echo '
<tr>
<td colspan="6" class="text-right">
'.tr('Netto da provvigioni').':
</td>
<td class="text-right">
'.moneyFormat($ddt->totale_imponibile - $ddt->provvigione).'
</td>
<td></td>
</tr>';
}
echo '

View File

@ -225,8 +225,17 @@ foreach ($righe as $riga) {
// Importo
echo '
<td class="text-right">
'.moneyFormat($riga->importo).'
</td>';
'.moneyFormat($riga->importo);
//provvigione riga
if (abs($riga->provvigione_unitaria) > 0) {
$text = provvigioneInfo($riga);
echo '
<br><small class="label label-info">'.$text.'</small>';
}
echo '</td>';
}
// Possibilità di rimuovere una riga solo se la fattura non è pagata
@ -448,6 +457,18 @@ if(!empty($fattura->provvigione)) {
</td>
<td></td>
</tr>';
echo '
<tr>
<td colspan="6" class="text-right">
'.tr('Netto da provvigioni').':
</td>
<td class="text-right">
'.moneyFormat($fattura->totale_imponibile - $fattura->provvigione).'
</td>
<td></td>
</tr>';
}
echo '

View File

@ -690,8 +690,7 @@ echo '
$("#modals > div").modal("hide");
// Aggiornamento elenco interventi da pianificare
$("#calendar").fullCalendar("refetchEvents");
$("#calendar").fullCalendar("render");
globals.dashboard.calendar.refetchEvents();
}
// Se l\'aggiunta intervento proviene dai contratti, faccio il submit via ajax e ricarico la tabella dei contratti

View File

@ -323,7 +323,7 @@ switch (post('op')) {
$mail->save();
OperationLog::setInfo('id_email', $mail->id);
OperationLog::setInfo('id_module', $id_module);
OperationLog::setInfo('id_record', $id_record);
OperationLog::setInfo('id_record', $mail->id_record);
OperationLog::build('send-email');
array_push($list, $intervento->codice);

View File

@ -156,8 +156,18 @@ echo '
// Prezzo di vendita
echo '
<td class="text-right">
'.moneyFormat($riga->importo).'
</td>';
'.moneyFormat($riga->importo);
//provvigione riga
if (abs($riga->provvigione_unitaria) > 0) {
$text = provvigioneInfo($riga);
echo '
<br><small class="label label-info">'.$text.'</small>';
}
echo '</td>';
}
// Pulsante per riportare nel magazzino centrale.

View File

@ -230,8 +230,15 @@ foreach ($righe as $riga) {
// Importo
echo '
<td class="text-right">
'.moneyFormat($riga->importo).'
</td>';
'.moneyFormat($riga->importo);
//provvigione riga
if (abs($riga->provvigione_unitaria) > 0) {
$text = provvigioneInfo($riga);
echo '
<br><small class="label label-info">'.$text.'</small>';
}
echo '</td>';
}
// Possibilità di rimuovere una riga solo se l'ordine non è evaso
@ -383,6 +390,17 @@ if(!empty($ordine->provvigione)) {
</td>
<td></td>
</tr>';
echo '
<tr>
<td colspan="7" class="text-right">
'.tr('Netto da provvigioni').':
</td>
<td class="text-right">
'.moneyFormat($netto_a_pagare - $ordine->provvigione).'
</td>
<td></td>
</tr>';
}
echo '

View File

@ -180,8 +180,17 @@ foreach ($righe as $riga) {
// Importo
echo '
<td class="text-right">
'.moneyFormat($riga->importo).'
</td>';
'.moneyFormat($riga->importo);
//provvigione riga
if (abs($riga->provvigione_unitaria) > 0) {
$text = provvigioneInfo($riga);
echo '
<br><small class="label label-info">'.$text.'</small>';
}
echo '</td>';
}
// Possibilità di rimuovere una riga solo se il preventivo non è stato pagato

View File

@ -24,6 +24,7 @@ use Models\Cache;
use Models\Module;
use Models\Plugin;
use Util\FileSystem;
use Carbon\Carbon;
$id = post('id');
@ -267,6 +268,20 @@ switch (filter('op')) {
break;
case 'svuota-cache-hooks':
// Svuota cache hooks
$database->table('zz_cache')
->update(['expire_at' => Carbon::now()->subMinutes(1)]);
// Messaggio informativo
flash()->info(tr('Cache hooks svuotata!', []));
echo json_encode([]);
break;
case 'disabilita-hook':
$id = filter('id');

View File

@ -89,14 +89,57 @@ foreach ($gruppi as $modulo => $hooks) {
</tr>';
}
echo '
</tbody>';
}
echo '<tr><td colspan="3"><p>&nbsp;</p><button type="button" class="btn btn-danger btn-xs pull-right" onclick="svuotaCacheHooks(this)">
<i class="fa fa-trash" title="'.tr('Svuota cache degli hooks').'"></i> '.tr('Svuota cache').'</button>
</td></tr>';
echo '
</tbody>';
echo '
</table>
<script>
function svuotaCacheHooks(button){
swal({
title: "'.tr('Svuota la cache degli hooks', []).'",
html: "'.tr('Sei sicuro di voler svuotare la cache degli hooks?', []).'",
type: "warning",
showCancelButton: true,
confirmButtonText: "'.tr('Continua').'"
}).then(function (result) {
let restore = buttonLoading(button);
$.ajax({
url: globals.rootdir + "/actions.php",
type: "POST",
dataType: "JSON",
data: {
id_module: globals.id_module,
op: "svuota-cache-hooks",
},
success: function (response) {
buttonRestore(button, restore);
renderMessages();
},
error: function() {
buttonRestore(button, restore);
swal({
type: "error",
title: globals.translations.ajax.error.title,
text: globals.translations.ajax.error.text,
});
}
});
})
}
function disabilitaHook(button){
const riga = $(button).closest("tr");
const id = riga.data("id");
@ -105,10 +148,10 @@ function disabilitaHook(button){
const nome_tipo = "hook";
swal({
title: "'.tr('Disabilitare il _TYPE_?', [
title: "'.tr('Disabilita _TYPE_', [
'_TYPE_' => '" + nome_tipo + "',
]).'",
html: "'.tr('Sei sicuro di voler disabilitare il _TYPE_ _NAME_?', [
html: "'.tr('Sei sicuro di voler disabilitare l\'_TYPE_ _NAME_?', [
'_TYPE_' => '" + nome_tipo + "',
'_NAME_' => '" + nome + "',
]).'",
@ -152,10 +195,10 @@ function abilitaHook(button) {
const nome_tipo = "hook";
swal({
title: "'.tr('Abilitare il _TYPE_?', [
title: "'.tr('Abilita _TYPE_', [
'_TYPE_' => '" + nome_tipo + "',
]).'",
html: "'.tr('Sei sicuro di voler abilitare il _TYPE_ _NAME_?', [
html: "'.tr('Sei sicuro di voler abilitare l\'_TYPE_ _NAME_?', [
'_TYPE_' => '" + nome_tipo + "',
'_NAME_' => '" + nome + "',
]).'",

View File

@ -73,7 +73,7 @@ foreach ($fields as $key => $field) {
'name' => 'query['.$key.']',
'required' => 1,
'readonly' => ''.(!$editable).'',
'value' => prepareToField($field['query']),
'value' => $field['query'],
'help' => tr("Nome effettivo del campo sulla tabella oppure subquery che permette di ottenere il valore del campo').'.<br>'.tr('ATTENZIONE: utilizza sempre i caratteri < o > seguiti da spazio!"),
]).'
</div>

View File

@ -2,6 +2,7 @@
"private": true,
"main": "gulpfile.js",
"dependencies": {
"@fullcalendar/moment": "^6.0.3",
"admin-lte": "^2.4.18",
"autocompleter": "^6.1.1",
"autonumeric": "^4.6.0",
@ -20,7 +21,7 @@
"dropzone": "^5.7.2",
"eonasdan-bootstrap-datetimepicker": "^4.17.49",
"font-awesome": "^4.7.0",
"fullcalendar": "^3.10.5",
"fullcalendar-scheduler": "^6.0.3",
"geocomplete": "^1.7.0",
"hotkeys-js": "^3.8.5",
"html5sortable": "^0.13.2",

View File

@ -434,6 +434,53 @@ if (!empty($righe)) {
$prezzo_unitario = $riga['PrezzoUnitario'] ?: $riga['Importo'];
$is_descrizione = empty((float)$riga['Quantita']) && empty((float)$prezzo_unitario);
$sconto_unitario = 0;
$sconti = $riga['ScontoMaggiorazione'] ?: 0;
if (!empty($sconti)) {
$tot_sconto_calcolato = 0;
$sconto_unitario = 0;
$sconti = $sconti[0] ? $sconti : [$sconti];
// Determina il tipo di sconto in caso di sconti misti UNT e PRC
foreach ($sconti as $sconto) {
$tipo_sconto = !empty($sconto['Importo']) ? '€' : '%';
if (!empty($tipo) && $tipo_sconto != $tipo) {
$tipo = '€';
} else {
$tipo = $tipo_sconto;
}
}
foreach ($sconti as $sconto) {
$unitario = $sconto['Importo'] ?: $sconto['Percentuale'];
// Sconto o Maggiorazione
$sconto_riga = ($sconto['Tipo'] == 'SC') ? $unitario : -$unitario;
$tipo_sconto = !empty($sconto['Importo']) ? '€' : '%';
if ($tipo_sconto == '%') {
$sconto_calcolato = calcola_sconto([
'sconto' => $sconto_riga,
'prezzo' => $sconto_unitario ? $obj->prezzo_unitario - ($tot_sconto_calcolato / $obj->qta) : $obj->prezzo_unitario,
'tipo' => 'PRC',
'qta' => $obj->qta,
]);
if ($tipo == '%') {
$tot_sconto = $sconto_calcolato * 100 / $obj->imponibile;
} else {
$tot_sconto = $sconto_calcolato;
}
} else {
$tot_sconto = $sconto_riga;
}
$tot_sconto_calcolato += $sconto_calcolato;
$sconto_unitario += $tot_sconto;
}
}
$riferimento_fe = '';
if ($dati_ddt[(int)$riga['NumeroLinea']]) {
@ -466,7 +513,13 @@ if (!empty($righe)) {
</td>
<td class="text-right">
'.moneyFormat($prezzo_unitario).'
'.moneyFormat($prezzo_unitario);
if (abs($sconto_unitario) > 0) {
$text = ($prezzo_unitario >= 0 && $sconto_unitario > 0) || ($prezzo_unitario < 0 && $sconto_unitario < 0) ? tr('sconto _TOT_ _TYPE_', ['_TOT_' => Translator::numberToLocale(abs($sconto_unitario)), '_TYPE_' => $tipo]) : tr('maggiorazione _TOT__TYPE_', ['_TOT_' => Translator::numberToLocale(abs($sconto_unitario)), '_TYPE_' => $tipo]);
echo '
<br><small class="label label-danger">'.$text.'</small>';
}
echo '
<span id="riferimento_'.$key.'_prezzo"></span>
</td>

View File

@ -63,7 +63,7 @@ class App
'i18n/parsleyjs/|lang|.min.js',
'i18n/select2/|lang|.min.js',
'i18n/moment/|lang|.min.js',
'i18n/fullcalendar/|lang|.min.js',
'i18n/@fullcalendar/|lang|.min.js',
],
];

View File

@ -245,11 +245,11 @@ class WidgetManager implements ManagerInterface
// Generazione del codice HTML
if (!empty($widgets)) {
$row_max = count($widgets);
if ($row_max > 4) {
$row_max = 4;
} elseif ($row_max < 2) {
$row_max = 2;
$row_max = setting('Numero massimo Widget per riga');
if ($row_max > 6) {
$row_max = 6;
} elseif ($row_max < 1) {
$row_max = 1;
}
$result = '

View File

@ -226,7 +226,7 @@ class Update
}
/**
* Esegue una precisa sezione dell'aggiornamento fa fare, partendo dalle query e passando poi allo script relativo.
* Esegue una precisa sezione dell'aggiornamento da fare, partendo dalle query e passando poi allo script relativo.
* Prima dell'esecuzione dello script viene inoltre eseguita un'operazione di normalizzazione dei campi delle tabelle del database finalizzata a generalizzare la gestione delle informazioni per l'API: vengono quindi aggiunti i campi <b>created_at</b> e, se permesso dalla versione di MySQL, <b>updated_at</b> ad ogni tabella registrata del software.
*
* @param int $rate Numero di singole query da eseguire dell'aggiornamento corrente

View File

@ -33,7 +33,11 @@ UPDATE `zz_prints` SET `id_module` = (SELECT `id` FROM `zz_modules` WHERE `name`
INSERT INTO `zz_prints` (`id`, `id_module`, `is_record`, `name`, `title`, `filename`, `directory`, `previous`, `options`, `icon`, `version`, `compatibility`, `order`, `predefined`, `default`, `enabled`) VALUES (NULL, (SELECT `id` FROM `zz_modules` WHERE `name`='Stampe contabili'), '1', 'Libro giornale', 'Libro giornale', 'Libro giornale', 'libro_giornale', 'idconto', '', 'fa fa-print', '', '', '0', '0', '1', '1');
-- Aggiunta tabella mansioni
CREATE TABLE IF NOT EXISTS `an_mansioni` ( `id` INT NOT NULL AUTO_INCREMENT , `nome` VARCHAR(100) NOT NULL , PRIMARY KEY (`id`));
CREATE TABLE IF NOT EXISTS `an_mansioni` (
`id` INT NOT NULL AUTO_INCREMENT,
`nome` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `an_mansioni`(
`nome`
@ -56,7 +60,12 @@ INSERT INTO `zz_views` (`id`, `id_module`, `name`, `query`, `order`, `visible`,
UPDATE `zz_plugins` SET `options` = ' { \"main_query\": [ { \"type\": \"table\", \"fields\": \"Nominativo, Mansione, Telefono, Indirizzo email, Sede\", \"query\": \"SELECT an_referenti.id, an_referenti.nome AS Nominativo, an_mansioni.nome AS Mansione, an_referenti.telefono AS Telefono, an_referenti.email AS \'Indirizzo email\', IF(idsede = 0, \'Sede legale\', an_sedi.nomesede) AS Sede FROM an_referenti LEFT OUTER JOIN an_sedi ON idsede = an_sedi.id LEFT OUTER JOIN an_mansioni ON idmansione = an_mansioni.id WHERE 1=1 AND an_referenti.idanagrafica=|id_parent| HAVING 2=2 ORDER BY an_referenti.id DESC\"} ]}' WHERE `zz_plugins`.`name` = 'Referenti';
CREATE TABLE IF NOT EXISTS `em_mansioni_template` ( `id` INT NOT NULL AUTO_INCREMENT , `idmansione` INT NOT NULL , `id_template` INT NOT NULL , PRIMARY KEY (`id`));
CREATE TABLE IF NOT EXISTS `em_mansioni_template` (
`id` INT NOT NULL AUTO_INCREMENT,
`idmansione` INT NOT NULL,
`id_template` INT NOT NULL,
PRIMARY KEY (`id`)
);
-- Aggiunta notifiche ai tecnici assegnati
ALTER TABLE `in_statiintervento` CHANGE `notifica_tecnici` `notifica_tecnico_sessione` TINYINT(4) NOT NULL;

View File

@ -97,4 +97,56 @@ HAVING
ORDER BY
`data` DESC,
CAST(`numero_esterno` AS UNSIGNED) DESC,
`dt_ddt`.created_at DESC" WHERE `name` = 'Ddt di vendita';
`dt_ddt`.created_at DESC" WHERE `name` = 'Ddt di vendita';
-- Fix problemi integrità db se si aggiorna (o si è aggiornato in passato) da una versione precedente alla 2.4.28
ALTER TABLE `an_mansioni` CHANGE `created_at` `created_at` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE `an_mansioni` CHANGE `updated_at` `updated_at` TIMESTAMP on update CURRENT_TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE `em_mansioni_template` CHANGE `created_at` `created_at` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE `em_mansioni_template` CHANGE `updated_at` `updated_at` TIMESTAMP on update CURRENT_TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP;
-- Fix query vista Pagamenti
UPDATE `zz_views` INNER JOIN `zz_modules` ON `zz_views`.`id_module` = `zz_modules`.`id` SET `zz_views`.`query` = '`pagamenti`.`tipo`' WHERE `zz_modules`.`name` = 'Pagamenti' AND `zz_views`.`name` = 'Codice pagamento';
UPDATE `zz_modules` SET `options` = "SELECT
|select|
FROM
`co_pagamenti`
LEFT JOIN(SELECT `fe_modalita_pagamento`.`codice`, CONCAT(`fe_modalita_pagamento`.`codice`, ' - ', `fe_modalita_pagamento`.`descrizione`) AS tipo FROM `fe_modalita_pagamento`) AS pagamenti ON `pagamenti`.`codice` = `co_pagamenti`.`codice_modalita_pagamento_fe`
WHERE
1=1
GROUP BY
`descrizione`
HAVING
2=2" WHERE `name` = 'Pagamenti';
-- Aggiunta impostazione Numero massimo widget per colonna
INSERT INTO zz_settings(nome, valore, tipo, editable, sezione) VALUES ('Numero massimo Widget per riga','6','list[1,2,3,4,6]','1','Generali');
-- Modifica widget Magazzino
UPDATE `zz_widgets` SET `query` = 'SELECT REPLACE(REPLACE(REPLACE(FORMAT(SUM(qta),2), ",", "#"), ".", ","), "#", ".") AS dato FROM mg_articoli WHERE qta>0 AND deleted_at IS NULL AND servizio=0 AND 1=1' WHERE `zz_widgets`.`name` = 'Articoli in magazzino';
UPDATE `zz_widgets` SET `text` = 'Unità' WHERE `zz_widgets`.`name` = 'Articoli in magazzino';
UPDATE `zz_widgets` SET `text` = 'Valore' WHERE `zz_widgets`.`name` = 'Valore magazzino';
-- Aggiunta colonna Banca azienda in Scadenzario
INSERT INTO `zz_views` (`id_module`, `name`, `query`, `order`, `search`, `slow`, `format`, `html_format`, `search_inside`, `order_by`, `visible`, `summable`, `default`) VALUES ('18', 'Banca azienda', '`banca`.`nome`', '18', '1', '0', '0', '0', NULL, NULL, '0', '0', '0');
UPDATE `zz_modules` SET `options` = "
SELECT
|select|
FROM
`co_scadenziario`
LEFT JOIN `co_documenti` ON `co_scadenziario`.`iddocumento` = `co_documenti`.`id`
LEFT JOIN (SELECT `co_banche`.`nome`AS nome, `co_banche`.`id` FROM `co_banche` INNER JOIN `co_documenti` ON `co_documenti`.`id_banca_azienda` = `co_banche`.`id`)AS banca ON `co_scadenziario`.`iddocumento` = `co_documenti`.`id`
LEFT JOIN `an_anagrafiche` ON `co_scadenziario`.`idanagrafica` = `an_anagrafiche`.`idanagrafica`
LEFT JOIN `co_pagamenti` ON `co_documenti`.`idpagamento` = `co_pagamenti`.`id`
LEFT JOIN `co_tipidocumento` ON `co_documenti`.`idtipodocumento` = `co_tipidocumento`.`id`
LEFT JOIN `co_statidocumento` ON `co_documenti`.`idstatodocumento` = `co_statidocumento`.`id`
LEFT JOIN (SELECT `zz_operations`.`id_email`, `zz_operations`.`id_record` FROM `zz_operations` INNER JOIN `em_emails` ON `zz_operations`.`id_email` = `em_emails`.`id` INNER JOIN `em_templates` ON `em_emails`.`id_template` = `em_templates`.`id` INNER JOIN `zz_modules` ON `zz_operations`.`id_module` = `zz_modules`.`id` WHERE `zz_modules`.`name` = 'Scadenzario' AND `zz_operations`.`op` = 'send-email' GROUP BY `zz_operations`.`id_record`) AS `email` ON `email`.`id_record` = `co_scadenziario`.`id`
WHERE
1=1 AND (`co_statidocumento`.`descrizione` IS NULL OR `co_statidocumento`.`descrizione` IN('Emessa','Parzialmente pagato','Pagato'))
HAVING
2=2
ORDER BY
`scadenza` ASC" WHERE `name` = 'Scadenzario';