Compare commits

...

913 Commits

Author SHA1 Message Date
FabioL bb43544c59 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-05-17 17:53:52 +02:00
FabioL 5140dc5b78 Fix per AdminLTE3 2024-05-17 17:53:49 +02:00
Pek5892 909d535b5f Aggiunta rientri menu sidebar 2024-05-17 17:29:55 +02:00
FabioL 2179e9f30f Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-05-17 17:27:14 +02:00
FabioL 697685e268 Migliorie grafiche login e preloader 2024-05-17 17:27:12 +02:00
Pek5892 90d9a80f4f Fix line_chart.js 2024-05-17 16:49:14 +02:00
Pek5892 123582b730 Fix modulo statistiche 2024-05-17 16:42:59 +02:00
FabioL ed2c9abba5 Fix sidebar 2024-05-17 13:23:34 +02:00
Pek5892 63f42c130c Fix minore 2024-05-17 12:54:03 +02:00
Pek5892 dcee9a7dc7 Avanzamento grafica AdminLTE3 2024-05-17 12:11:00 +02:00
Matteo ca3a074e77 Fix esportazione bancaria vuota 2024-05-17 11:49:42 +02:00
loviuz eee3f4382a Fix loader 2024-05-17 00:33:47 +02:00
loviuz 448a47b5a3 Avanzamento grafica AdminLTE3 2024-05-17 00:32:46 +02:00
Pek5892 648fb32987 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-05-16 18:08:33 +02:00
Pek5892 e6fa02d41a Migrazione parziale ad AdminLTE 3 2024-05-16 18:02:50 +02:00
Luca 00e7364950 Fix Legenda scadenzario 2024-05-14 18:16:13 +02:00
FabioL c2a740920c Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-05-14 17:16:32 +02:00
FabioL e2873c30f0 Fix ricerca globale su automezzi 2024-05-14 17:16:30 +02:00
FabioL abda0b2265 Fix ricerca globale su ddt 2024-05-14 17:16:25 +02:00
Luca 18adb9e379 Aggiornamento stampa del contratto 2024-05-14 17:09:49 +02:00
Luca 9b745228c6 Aggiunte opzioni possibli stampa Contratto 2024-05-14 16:51:20 +02:00
Luca 967b57999d Opzioni possibili per stampa "Contratto" 2024-05-14 16:41:45 +02:00
Luca bf3a0a22ea Rimossa variabile inutilizzata $is_last_page 2024-05-14 16:36:45 +02:00
Luca 3c013380df Migliorie minori 2024-05-14 16:29:55 +02:00
Pek5892 22960059f2 Fix template ddt 2024-05-14 14:30:16 +02:00
Pek5892 0036e53a1d Fix minori attività 2024-05-14 12:25:26 +02:00
Pek5892 b3c4fff620 Fix minori 2024-05-14 11:56:24 +02:00
Pek5892 1d2d06b60d Aggiunta legenda in Scadenzario 2024-05-14 11:56:16 +02:00
Pek5892 4985df2ebc Fix compatibilità 2024-05-13 17:26:12 +02:00
Pek5892 b8e19be76f Fix minori 2024-05-13 16:29:57 +02:00
Pek5892 5d0e3102ee Aggiunta colonne Marca e Modello in Impianti 2024-05-13 16:24:38 +02:00
Pek5892 50e02eaa16 Fix minore 2024-05-13 14:39:25 +02:00
Pek5892 c35e24d08b Fix viste 2024-05-13 12:59:39 +02:00
Pek5892 869a7fddab Fix minore 2024-05-13 12:59:04 +02:00
Pek5892 8865fec6d9 Fix footer template fattura 2024-05-13 12:37:45 +02:00
Pek5892 aa831bd8fc Fix minore 2024-05-13 12:23:31 +02:00
Pek5892 47b2df170c Ottimizzati i background in scadenzario 2024-05-13 12:12:29 +02:00
Pek5892 c85540c888 Miglioria gestione rate in scadenzario 2024-05-13 11:35:51 +02:00
Pek5892 635ad11534 Fix ricerca metodo pagamento 2024-05-13 10:42:59 +02:00
Pek5892 968ace04b4 Fix minore 2024-05-13 10:40:05 +02:00
Pek5892 f41b025dce Fix minore 2024-05-13 10:33:08 +02:00
Pek5892 0662ba11d7 Fix grafico minore 2024-05-10 16:53:35 +02:00
FabioL bbd0825f6a Aggiornamento stylesheet FE 2024-05-10 16:10:19 +02:00
Pek5892 bee21f02da Fix stampa riepilogo intervento 2024-05-10 15:49:40 +02:00
Pek5892 058c76fb45 Fix aggiunta al volo tags 2024-05-10 15:35:33 +02:00
Pek5892 c808e25967 Fix modulo tags 2024-05-10 14:50:23 +02:00
Pek5892 4661a184b0 Fix minore 2024-05-10 12:13:58 +02:00
Pek5892 6e846483f2 Fix versione php 2024-05-10 10:24:35 +02:00
Pek5892 4eeeed12d8 Aggiunto avviso in caso di permessi assenti sui segmenti 2024-05-10 09:28:12 +02:00
Pek5892 50e3d73400 Aggiornamento rector.php 2024-05-10 09:27:42 +02:00
Pek5892 527b0c82e5 Fix minore 2024-05-10 09:27:25 +02:00
Pek5892 857a8694f9 Aggiunta gestione marca e modello su Impianti 2024-05-09 16:57:11 +02:00
FabioL 540fe7b4d2 Aggiunta gestione calcolo media su colonne 2024-05-09 16:51:13 +02:00
Pek5892 44a9355477 Fix minori 2024-05-09 10:29:53 +02:00
Pek5892 8da9743c29 Fix per php8.3 2024-05-08 12:16:57 +02:00
Pek5892 585c47bb18 Fix minore scadenzario 2024-05-07 18:01:57 +02:00
Luca 58aa7675ce Semplificata apertura attività da calendario su nuova scheda 2024-05-07 15:25:45 +02:00
FabioL 7defba3e5a Apertura attività da calendario su nuova scheda 2024-05-07 15:15:15 +02:00
Pek5892 63a002cdf0 Fix minore 2024-05-07 14:35:53 +02:00
FabioL 1dc8343e0b Fix immagine header 2024-05-07 10:09:34 +02:00
FabioL b969957394 Fix per retrocompatibilità PHP 7.4 2024-05-07 09:50:27 +02:00
Beppe 786f638706 Fix query 2024-05-06 15:23:33 +02:00
Pek5892 97c1817c65 Fix query vista Attività 2024-05-06 13:11:57 +02:00
Pek5892 4c83fe7c73 Fix salvataggio tecnici assegnati in attività 2024-05-06 13:11:48 +02:00
Pek5892 450494f279 Miglioria header.php 2024-05-06 12:56:08 +02:00
Pek5892 a7bf474c84 Fix invio sollecito di pagamento 2024-05-06 11:25:51 +02:00
Pek5892 06d0b87cee Fix minori 2024-05-06 11:25:41 +02:00
Pek5892 57a389fc6a Fix invio sollecito scadenzario 2024-05-06 10:59:20 +02:00
Pek5892 4b8a12e164 Fix minore 2024-05-03 17:31:29 +02:00
Pek5892 137a5e6ffe Miglioria conteggio caratteri 2024-05-03 17:23:20 +02:00
Pek5892 8c20974e5b Fix template fatture 2024-05-03 16:53:48 +02:00
Pek5892 01cf1379d0 Fix riferimento banca in FE 2024-05-03 15:41:14 +02:00
Pek5892 158d463232 Fix minore 2024-05-03 15:34:38 +02:00
Pek5892 d2bdd6cc19 Fix banca controparte 2024-05-03 15:28:18 +02:00
Pek5892 432d781ce2 Fix update campi in viste 2024-05-03 14:51:07 +02:00
Pek5892 063337f9cb Fix stato intervento 2024-05-03 14:45:21 +02:00
Pek5892 dac7d5f5cd Fix query vista Attività 2024-05-03 14:42:56 +02:00
Pek5892 bcf6c7a142 Fix caricamento allegati in interventi 2024-05-03 14:42:39 +02:00
Pek5892 8fc4ccc7be Fix ddt 2024-05-03 12:15:09 +02:00
Pek5892 cf917bd94f Aggiunta Tags in Attività 2024-05-03 11:06:25 +02:00
Pek5892 07e326bd9f Fix attività 2024-05-03 09:50:33 +02:00
Pek5892 d8829ac8f8 Migliorie grafiche Attività 2024-05-02 17:34:31 +02:00
Pek5892 16f9bf4032 Aggiunta header.php in interventi 2024-05-02 17:00:11 +02:00
Pek5892 d497d6ae92 aggiunta gestione header.php 2024-05-02 16:59:40 +02:00
Pek5892 e8cf2a53e2 Fix modifica nome allegati 2024-05-02 16:58:52 +02:00
Pek5892 4fdb6a6c94 Fix controllo numerazione attività 2024-04-30 18:03:45 +02:00
FabioL b14fced154 Fix utf-8 in esportazione RiBa 2024-04-30 10:20:47 +02:00
Pek5892 9333c2c119 Fix caricamento immagine in articoli 2024-04-29 08:59:10 +02:00
Pek5892 894e3aea5a Retrofix aggiornamento 2024-04-29 08:50:14 +02:00
Luca 6501672ac6 Update README.md 2024-04-26 13:22:27 +02:00
Luca 408b88457b Update README.md 2024-04-26 13:21:55 +02:00
Luca 5cb07c8b08 Update README.md 2024-04-26 13:18:46 +02:00
Luca b1a815dce2 Fix my_impianti_marche 2024-04-25 19:51:50 +02:00
Pek5892 03b1cf0ded Fix minore 2024-04-24 17:25:35 +02:00
Pek5892 3b6ff36a9c Fix minori 2024-04-24 12:26:51 +02:00
MatteoPistorello 7de3170635 Plugin Asssicurazione crediti 2024-04-24 12:18:53 +02:00
Pek5892 246f0e8295 Fix plugin dichiarazioni d'intento 2024-04-24 11:56:32 +02:00
Pek5892 eb68e8f92d Fix minore 2024-04-24 10:16:49 +02:00
Pek5892 2d91614f43 Aggiornamento CHANGELOG 2024-04-24 09:49:19 +02:00
Pek5892 143272993e Fix import fe 2024-04-23 17:26:29 +02:00
MatteoPistorello f4a85c583e Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-04-23 17:15:03 +02:00
MatteoPistorello 818ce3cc1e Caricamento checklist plugin Impianti 2024-04-23 17:14:56 +02:00
Pek5892 4c23e1cf95 Fix import fe per sconto unitario 2024-04-23 16:55:41 +02:00
Pek5892 e0f02d302d Fix import fatture 2024-04-23 15:54:02 +02:00
Pek5892 ed5d524fff Fix widget 2024-04-23 15:29:50 +02:00
Pek5892 672c9ce34e Fix minori 2024-04-23 15:25:32 +02:00
Pek5892 f57ee2ab7e Fix categorie 2024-04-23 15:05:18 +02:00
Pek5892 fbc4b3d718 Fix minori 2024-04-23 14:43:42 +02:00
Pek5892 eadeb43b8a Fix tipi scadenze 2024-04-23 14:15:24 +02:00
Pek5892 146a36ab9e Fix ddt 2024-04-23 12:01:59 +02:00
Pek5892 1cc40b76e2 Formattazione codice 2024-04-23 09:56:36 +02:00
Pek5892 cccd2b3c39 Fix ddt 2024-04-22 16:51:27 +02:00
Pek5892 f25ea17ba7 Fix minori 2024-04-22 16:15:55 +02:00
Pek5892 1bc6e5d3fe Modifica forzatura aggiornamento 2024-04-22 14:39:25 +02:00
Pek5892 5871b8e608 Fix minore 2024-04-22 14:28:03 +02:00
Pek5892 00ca74ee24 Fix backup 2024-04-22 12:35:30 +02:00
Pek5892 a569100444 Fix minore 2024-04-22 12:32:48 +02:00
Pek5892 6096968262 Fix modulo adattatori di archiviazione 2024-04-22 12:25:52 +02:00
Pek5892 1bae45821a Fix per php8.1 2024-04-22 10:11:10 +02:00
Pek5892 5d55ad191d Fix minore statistiche 2024-04-22 09:44:07 +02:00
Pek5892 e62d206c14 Fix per ottimizzazione database 2024-04-19 16:44:08 +02:00
Pek5892 2f8fb8077a Fix creazione files 2024-04-19 15:31:32 +02:00
Pek5892 dbf6846653 Fix campi tabelle 2024-04-19 08:57:08 +02:00
Pek5892 aa93371e2b Miglioria gestione traduzioni 2024-04-18 17:44:05 +02:00
Pek5892 b3d8779005 Fix per php8.1 2024-04-17 11:44:13 +02:00
Pek5892 4152b51b83 Aggiunta campi marca e modello in import Impianti 2024-04-17 11:43:58 +02:00
Beppe 9df84eb7fb Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-04-17 11:30:19 +02:00
Beppe ec326c35f5 Fix eliminazione destinatari collegati ad anagrafiche rimosse 2024-04-17 11:30:17 +02:00
Pek5892 f9c5b4aa35 Aggiunti i campi marca e modello in Impianti 2024-04-17 11:21:05 +02:00
Pek5892 6b7fa73bc3 Fix per php8.1 2024-04-17 10:39:25 +02:00
FabioL 9b1e2e82e0 Fix per lettura file XML fuori dalla root 2024-04-17 09:34:07 +02:00
Pek5892 961186c3d1 #1384 Aggiunta colonna Gruppi abilitati in Categorie documenti 2024-04-16 11:06:25 +02:00
Pek5892 edde4a50ce Fix impostazione stampa per anteprima e firma 2024-04-15 17:28:16 +02:00
Pek5892 927f1abf6a Fix minore 2024-04-15 14:59:09 +02:00
Pek5892 1710ec1720 Fix per php8.1 2024-04-15 08:57:53 +02:00
Pek5892 03eb6a166b Fix configurazione per php8.1 2024-04-15 08:54:08 +02:00
Luca c41ca167eb Fix minori 2024-04-13 20:28:48 +02:00
Luca 901c79edb2 Update edit.php 2024-04-12 18:10:45 +02:00
Luca f144877ee1 Update edit.php 2024-04-12 18:05:07 +02:00
Luca 5e66283d09 Update edit.php 2024-04-12 18:04:10 +02:00
Luca d23788ca8b Se non è installato il modulo distinta base elimino il plugin 2024-04-12 18:03:03 +02:00
Pek5892 1e68240070 Aggiornamento CHANGELOG 2024-04-12 17:27:29 +02:00
Pek5892 e0f0fcdd27 Fix per php8.1 2024-04-12 17:12:05 +02:00
Pek5892 c65bbd3f39 Fix php8.1 2024-04-12 16:59:19 +02:00
Pek5892 9f0e319a03 Fix php8.1 2024-04-12 16:47:34 +02:00
Pek5892 8ffe852c19 Fix per php8.1 2024-04-12 16:25:04 +02:00
Pek5892 fc495377d6 Fix minori 2024-04-12 15:53:58 +02:00
Pek5892 c4e3c2f484 Fix riferimenti 2024-04-12 13:22:14 +02:00
Pek5892 c9f007db16 Fix per php8.1 2024-04-12 10:54:05 +02:00
Pek5892 9858c371c6 Fix minore 2024-04-12 10:22:56 +02:00
Pek5892 ec940b82f2 Fix stampa con php8.1 2024-04-12 10:17:30 +02:00
Pek5892 c8c5f59abf Formattazione codice 2024-04-12 09:53:02 +02:00
Pek5892 2ebb059b3e Fix stampa pdf per php8.1 2024-04-12 09:35:30 +02:00
Pek5892 f98ae71340 Fix per emissione fatture con php8.1 2024-04-12 09:12:45 +02:00
Pek5892 7b8018c68a Fix per php8.1 2024-04-11 17:55:49 +02:00
Pek5892 95f7840a44 Fix verifica numero ddt 2024-04-11 16:24:29 +02:00
Pek5892 8a018f8606 Fix minore 2024-04-11 16:16:35 +02:00
Pek5892 519c7219cd Fix minore 2024-04-11 14:53:46 +02:00
Pek5892 9b9744b134 Fix redirect per php8.1 2024-04-11 12:26:12 +02:00
Pek5892 072c2e615a Fix minori 2024-04-11 12:21:13 +02:00
Pek5892 95b0fc5b1a Fix contratti 2024-04-11 11:46:38 +02:00
Pek5892 6809ca0ce3 Fix per php8.1 2024-04-11 11:17:03 +02:00
Pek5892 97a3c0ef47 Fix per php8.1 2024-04-11 11:16:47 +02:00
Pek5892 b4d2fec82b Fix minore 2024-04-10 17:43:54 +02:00
Matteo edda7c38e2 Fix per api cleanup checklist 2024-04-10 17:15:20 +02:00
Pek5892 c1f86dace3 Fix #1463 2024-04-10 16:12:02 +02:00
Pek5892 b975cbc24e Fix caricamento promemoria da pianificare in dashboard 2024-04-10 14:53:26 +02:00
Pek5892 6172a7c89b Fix aggiunta attività con php8.1 2024-04-10 12:43:32 +02:00
Pek5892 ce8ac0f846 Fix redirect 2024-04-10 10:32:23 +02:00
Pek5892 eb15f24ac9 Fix per php8.1 2024-04-10 10:28:30 +02:00
Pek5892 c20ba3eeee Fix backup 2024-04-10 10:09:24 +02:00
Pek5892 f373036f15 Ottimizzazione 2024-04-10 09:49:42 +02:00
Pek5892 025dc5dcd3 Fix reindirizzamento 2024-04-09 17:08:35 +02:00
Pek5892 2700b0c0f8 Miglioria aggiornamento 2.5 2024-04-09 14:56:20 +02:00
Pek5892 4da98e49d0 Fix minore 2024-04-09 14:53:15 +02:00
Pek5892 5ac04f4a01 Aggiornamento versione mysql 2024-04-09 14:45:37 +02:00
Pek5892 982f029f43 Fix minore 2024-04-09 14:26:58 +02:00
Pek5892 bc43765546 Fix controllo database 2024-04-09 14:21:57 +02:00
Pek5892 fedf455b1f Aggiornamento dipendenza php-cs-fixer 2024-04-09 12:18:08 +02:00
Pek5892 6c6fb4fd24 Fix minori 2024-04-09 11:53:02 +02:00
Pek5892 6bf644e45d Aggiunta chiavi esterne con zz_langs 2024-04-09 11:11:26 +02:00
Pek5892 e4b2fceda2 Fix per php8.1 2024-04-09 10:55:08 +02:00
Pek5892 3419d5fcaa Fix minore 2024-04-09 09:10:45 +02:00
Luca 1bb6311339 Rinomino plugin Sedi in Anagrafica 2024-04-08 18:33:05 +02:00
Pek5892 6873ec686a Fix minore 2024-04-08 16:29:13 +02:00
Pek5892 477a56e953 Ottimizzazione file con php8.1 2024-04-08 15:57:28 +02:00
Pek5892 de4759fd5b Fix minore 2024-04-08 15:49:53 +02:00
Pek5892 6369cb466e Ottimizzazione file con php8.1 2024-04-08 15:44:33 +02:00
Pek5892 00baaa0788 Fix upload template 2024-04-05 16:07:27 +02:00
Pek5892 cd80a18bca Fix upload plugins 2024-04-05 15:46:33 +02:00
Pek5892 783fd1a9c6 Fix upload moduli 2024-04-05 14:32:29 +02:00
Pek5892 60282b2007 Fix upload allegati 2024-04-05 09:47:28 +02:00
Pek5892 2d03b1b173 Fix #1457 2024-04-05 09:01:55 +02:00
Pek5892 62137f0da7 Fix stampe contabili 2024-04-04 17:29:26 +02:00
Luca e4a7fa2cf0 Sposto impostazione sotto sezione Aggiornamenti 2024-04-04 16:00:01 +02:00
Pek5892 df3ce50315 Fix vari 2024-04-04 11:47:36 +02:00
Pek5892 76fde27116 Fix selezione anagrafiche clienti-fornitori 2024-04-03 17:32:56 +02:00
Pek5892 1eb711d873 Fix vari 2024-04-03 17:28:18 +02:00
MatteoPistorello 247ad030ca Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-04-03 17:21:35 +02:00
MatteoPistorello 9f57920975 Visualizzazione checklist impianti in stampa Attività 2024-04-03 17:21:32 +02:00
Pek5892 9b4cccf2fe Fix minore 2024-04-03 16:21:14 +02:00
Matteo 982829ca88 Fix azione di gruppo allegati download file zip 2024-04-03 16:18:09 +02:00
Pek5892 d7822c33bf Fix minori 2024-04-02 17:33:12 +02:00
Pek5892 728c30d5a2 Fix minore 2024-04-02 16:53:36 +02:00
Pek5892 d853766ff7 Fix 2024-04-02 16:28:55 +02:00
Pek5892 37517ce0b9 Fix vari 2024-04-02 16:12:14 +02:00
Pek5892 4a7db72004 Aggiunta classe PagamentoLang 2024-04-02 15:07:03 +02:00
Pek5892 2f56ddcfb2 Fix add scadenze in scadenzario 2024-04-02 14:38:02 +02:00
Pek5892 8c02c99132 Fix vista scadenzario e plugin 2024-04-02 14:37:43 +02:00
Pek5892 6d0f6ba3ac Fix vari query 2024-04-02 12:32:38 +02:00
FabioL 7b9811bd69 Fix visualizzazione info dispositivo 2024-04-02 11:11:59 +02:00
Pek5892 450633b863 Miglioria procedura di aggiornamento 2024-04-02 10:26:49 +02:00
loviuz 317884b8ea Aggiunta user-agent nei log di accesso 2024-04-01 23:09:37 +02:00
loviuz 3d85b76a93 Ripristinata la verifica query della vista 2024-03-31 01:35:10 +01:00
loviuz b72dce21dc Fix classe per salvataggio vista 2024-03-31 01:17:33 +01:00
loviuz 62d372df0a Fix salvataggio nome vista e migliorie minori 2024-03-31 01:06:03 +01:00
loviuz 22edea5520 Riordino css e miglioria sfondo login 2024-03-31 00:37:00 +01:00
Luca 0ace49cec3 Update tables.php 2024-03-29 10:56:48 +01:00
Pek5892 ab2f83fbf0 Aggiornamento CHANGELOG 2024-03-28 16:55:49 +01:00
Pek5892 cd1cb11198 Fix lingua inglese 2024-03-28 16:38:03 +01:00
Pek5892 41f75cf19f Fix per fatture di vendita lingua inglese 2024-03-28 13:03:21 +01:00
Pek5892 847177a0ec Fix modulo ddt lingua inglese 2024-03-28 12:10:13 +01:00
Pek5892 a6faefaa99 Fix per lingua inglese 2024-03-28 11:39:26 +01:00
Pek5892 0459dd2e4a Fix configurazione per lingua inglese 2024-03-28 10:42:22 +01:00
Pek5892 1535abf4a6 Fix vista Segmenti inglese 2024-03-28 10:27:13 +01:00
Pek5892 e506e4b18a Fix getTipo() anagrafica in inglese 2024-03-28 09:50:31 +01:00
Pek5892 ed056e060d Fix viste tradotte in inglese 2024-03-28 09:50:12 +01:00
Pek5892 9ff3022deb Ottmizzazione con funzione getPredefined() 2024-03-28 09:26:26 +01:00
Pek5892 71cacecf75 Fix per aggiunta anagrafica da aggiunta attività da dashboard in inglese 2024-03-28 09:16:13 +01:00
loviuz 126949a16c Fix traduzione 2024-03-28 00:55:13 +01:00
loviuz 6f4ca17fb7 Aggiornamenti minori delle traduzioni 2024-03-28 00:19:31 +01:00
loviuz 0f9c5e71dd Aggiornamento parziale traduzioni inglese 2024-03-27 23:50:59 +01:00
Luca 365bdf5551 Update 2_5.php 2024-03-27 19:40:57 +01:00
Luca 22cec86092 Fix minori 2024-03-27 19:14:26 +01:00
Pek5892 8072aaf537 Formattazione codice 2024-03-27 16:59:46 +01:00
Pek5892 72f569659a Miglioria 2024-03-27 16:43:30 +01:00
Pek5892 9fda45c411 Allineamento 2024-03-27 16:30:53 +01:00
Pek5892 da0999dd84 Aggiornamento traduzioni 2024-03-27 16:01:22 +01:00
Pek5892 cd12fb6e4d Fix minore 2024-03-27 15:38:39 +01:00
Pek5892 4e2f399a59 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-27 15:34:03 +01:00
Pek5892 f3126950c4 Ottimizzazione lingue 2024-03-27 15:34:01 +01:00
Beppe caa2b4bd44 Esclusioni default in preventivi 2024-03-27 15:18:09 +01:00
Pek5892 d4866e4ce4 Fix import preventivi 2024-03-27 11:47:35 +01:00
Pek5892 529cf6f5c5 Fix import impianti 2024-03-27 11:38:10 +01:00
Pek5892 88ba7311b3 Aggiunta tabella my_impianti_categorie_lang 2024-03-27 11:07:15 +01:00
Pek5892 c3338c78a9 Fix importazione articoli 2024-03-27 10:37:57 +01:00
Pek5892 a864b251b2 Fix upload csv 2024-03-27 10:17:27 +01:00
Pek5892 dfedb4b512 Fix upload allegati 2024-03-27 10:03:36 +01:00
FabioL 700b67a3d2 Fix larghezza automatica colonne datatables 2024-03-26 19:25:27 +01:00
Pek5892 e1c7781c8b Fix download fe 2024-03-26 18:43:55 +01:00
Pek5892 5ecaf54c12 Fix varie 2024-03-26 18:05:18 +01:00
Pek5892 1b8c632d69 Fix spostamento tra sedi 2024-03-26 17:22:40 +01:00
Luca 9fce000535 Update 2_5.sql 2024-03-26 16:42:34 +01:00
Pek5892 e71ede0641 Fix newsletter 2024-03-26 16:06:18 +01:00
Pek5892 d451464911 Fix per traduzione in oggetti vuoti 2024-03-26 15:43:52 +01:00
FabioL 54b45f1656 Ottimizzazione azzeramento checklist 2024-03-25 18:24:38 +01:00
Pek5892 99ec335ee5 Fix vista campi in viste 2024-03-25 17:34:39 +01:00
Pek5892 db698f114d Fix query vista Movimenti 2024-03-25 17:25:54 +01:00
Pek5892 83c400f693 Fix minore 2024-03-25 17:20:23 +01:00
Pek5892 ab061d6f7e Fix problema precedenza uso dei traits 2024-03-25 17:12:26 +01:00
Pek5892 dd8c2ef464 Fix minore 2024-03-25 16:13:43 +01:00
Pek5892 4d49a52296 Fix minore 2024-03-25 15:29:25 +01:00
Pek5892 0091fca368 Fix minore 2024-03-25 14:42:00 +01:00
FabioL 11e4482d0a Fix lettura lingue da tradurre 2024-03-25 12:32:22 +01:00
Pek5892 935738af86 Fix vari 2024-03-25 12:27:34 +01:00
Matteo 15d55d140b Fix query inserimento adattatore file locali 2024-03-25 11:43:12 +01:00
Pek5892 68fac4c12a Fix minore 2024-03-25 11:38:43 +01:00
Pek5892 5fff793da2 Fix minori 2024-03-25 11:09:20 +01:00
Pek5892 4592e7de5b Fix minori 2024-03-25 09:23:58 +01:00
Luca 7cd57dd12a Fix minore 2024-03-24 00:08:43 +01:00
FabioL 160947e49a Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-22 18:41:58 +01:00
FabioL 5cbc4125a7 Correzione per struttura stampe e traduzioni 2024-03-22 18:41:55 +01:00
FabioL 203606855e Fix versione di pdfjs viewer 2024-03-22 18:41:37 +01:00
Pek5892 96120c4b4a Fix minore 2024-03-22 18:00:36 +01:00
Pek5892 ffcedce0ed Fix minore 2024-03-22 17:43:28 +01:00
FabioL d2c79a9cb5 Fix nome mancante del plugin 2024-03-22 17:11:33 +01:00
FabioL e58f728c6f Fix problema lettura modulo da plugin 2024-03-22 17:11:27 +01:00
FabioL 0b03fb8d1e Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-22 16:37:25 +01:00
FabioL 2d4846ceb1 Fix nome plugin principale 2024-03-22 16:37:23 +01:00
Pek5892 d2381c453e Fix anagrafiche 2024-03-22 16:33:17 +01:00
Pek5892 24c316594f Fix minori 2024-03-22 16:12:30 +01:00
FabioL 715b715248 Fix minore 2024-03-22 16:11:17 +01:00
Pek5892 fbea29d7fd Fix minore 2024-03-22 15:55:58 +01:00
Pek5892 092e9880e8 Formattazione codice 2024-03-22 15:52:24 +01:00
Pek5892 bf34ae7051 Fix 2024-03-22 15:49:51 +01:00
Pek5892 2df908b11c Fix vari 2024-03-22 15:30:25 +01:00
Pek5892 a6363ca6c5 Aggiornamento changelog 2024-03-22 15:30:18 +01:00
Pek5892 639eda7eac Fix minore 2024-03-22 15:15:06 +01:00
Pek5892 ee2320338e Fix 2024-03-22 15:02:16 +01:00
Pek5892 649673eb1c Aggiunta traduzioni 2024-03-22 14:51:11 +01:00
Pek5892 e0ce1b3bfc Aggiunta traduzione impostazioni 2024-03-21 17:20:31 +01:00
Pek5892 5dd1302a1e Aggiunta traduzioni views 2024-03-21 16:34:35 +01:00
Pek5892 f093ba4382 Aggiunte le traduzioni dei plugins 2024-03-21 15:29:01 +01:00
Pek5892 1c1072d4ed Fix vari 2024-03-21 15:06:51 +01:00
Pek5892 6e16df9669 Traduzione moduli e widgets 2024-03-21 12:49:20 +01:00
Pek5892 780c67102f Fix per vista menu 2024-03-21 11:32:43 +01:00
Pek5892 ca88797519 Allineamento query 2024-03-21 10:56:35 +01:00
Pek5892 87b23d8ae7 Allineamento query 2024-03-21 10:53:02 +01:00
Pek5892 af7cf059a0 Aggiunti record per lingua inglese 2024-03-21 10:36:23 +01:00
Pek5892 add94f9bd0 Fix minore 2024-03-21 09:46:26 +01:00
Pek5892 08b6bb5556 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-20 16:17:14 +01:00
Pek5892 2560328be8 Ristrutturazione gestione lingue 2024-03-20 16:15:37 +01:00
Luca 6c7a47700a Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-20 15:42:09 +01:00
Luca a22597e29d Messaggi di avviso per ripristino db 2024-03-20 15:42:07 +01:00
Matteo cf6d7c9b01 Fix minori su api per app 2024-03-20 13:03:44 +01:00
Pek5892 c349125f4f Allineamento standardizzazione lingue 2024-03-20 11:13:28 +01:00
FabioL e5a2e75b2d
Fix query di aggiornamento 2024-03-20 10:22:49 +01:00
Matteo ceea29fb80 Sincronizzazione pagamento attività su app 2024-03-20 10:14:55 +01:00
Pek5892 6f117d5fbf Fix query vista Netto a pagare 2024-03-20 09:06:14 +01:00
Matteo 54330664f3 Aggiunta riferimento pagamento in attività 2024-03-19 18:40:27 +01:00
Pek5892 cc34b665f7 Modifica gestione lingue 2024-03-19 18:18:11 +01:00
Pek5892 c459ebe812 Fix minore 2024-03-19 17:17:07 +01:00
MatteoPistorello 366da4d89e Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-19 17:11:57 +01:00
MatteoPistorello c9a3731378 Aggiunto nuovo periodo calendario 2024-03-19 17:11:54 +01:00
Pek5892 e32bdec38f Aggiunta gestione stato fattura Non valida 2024-03-19 16:41:11 +01:00
FabioL 1ba9f45549 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-19 15:50:44 +01:00
FabioL 8c2a3023a4 Ulteriore standardizzazione della gestione lingue 2024-03-19 15:50:41 +01:00
Matteo b6cf28aa7c Fix api login app 2024-03-19 15:35:03 +01:00
Matteo 837bcae1b2 Blocco campo tipo archiviazione e blocco eliminazione per adattatori archiviazione 2024-03-19 15:27:22 +01:00
Pek5892 2ea249275a Fix minore 2024-03-19 15:27:17 +01:00
Pek5892 646fc7390a Fix iva su marca da bollo 2024-03-19 15:17:01 +01:00
Matteo c86aa025dd Fix minore 2024-03-19 13:30:58 +01:00
Matteo 98ef40d45d Query per introduzione connettori per il caricamento dei file 2024-03-19 13:24:31 +01:00
Matteo f53559eef1 Introduzione connettori per il caricamento dei file 2024-03-19 13:23:23 +01:00
Pek5892 d818d2e393 Fix ordinamento promemoria in Dashboard 2024-03-19 12:44:01 +01:00
Pek5892 aa14944c92 Fix minore 2024-03-18 16:49:05 +01:00
Pek5892 d60890734e Aggiunta impostazione Raggruppa attività per tipologia in fattura 2024-03-18 16:04:01 +01:00
Pek5892 395aeae7b6 Fix minore 2024-03-18 15:11:18 +01:00
Pek5892 21c08cbcdb Fix toggle password 2024-03-18 12:59:09 +01:00
Pek5892 55c386e7b4 Aggiornamento known-issues 2024-03-18 08:48:16 +01:00
Pek5892 d9148f2622 fix 2024-03-15 16:20:30 +01:00
Pek5892 8dd7577557 Aggiornamento CHANGELOG 2024-03-15 16:19:55 +01:00
Pek5892 82204f66dc Fix ricerca per articoli eliminati 2024-03-15 14:58:14 +01:00
Pek5892 897b29e60a Fix minore 2024-03-15 14:47:53 +01:00
Pek5892 ffc81244e6 Fix minori 2024-03-15 13:17:23 +01:00
MatteoPistorello 44021dfa8b Gestione visualizzazione articoli distinta inline nei documenti 2024-03-15 12:33:20 +01:00
Pek5892 d321458d25 Fix installazione 2024-03-15 10:47:24 +01:00
FabioL 8cc3137ba2 Fix per caratteri accentati su file RiBa 2024-03-15 10:06:21 +01:00
MatteoPistorello 8a48347649 Fix plugin impianti 2024-03-14 17:35:15 +01:00
MatteoPistorello b042c567ef Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-14 17:35:02 +01:00
MatteoPistorello 56f144604b Spostamento panel dettagli cliente 2024-03-14 17:34:57 +01:00
Pek5892 180422cb6f Fix minore 2024-03-14 14:45:29 +01:00
Pek5892 286ad99d2a Fix filtro per data attività 2024-03-14 14:30:39 +01:00
MatteoPistorello ba90d10567 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-14 10:50:50 +01:00
MatteoPistorello 2cbf758edd Fix visualizzazione dashboard 2024-03-14 10:50:47 +01:00
Pek5892 604fad69f6 Fix minore 2024-03-14 09:27:53 +01:00
Pek5892 a96fa70eb3 Fix varie 2024-03-13 17:32:07 +01:00
MatteoPistorello 69d05523bd Merge 2024-03-13 17:06:18 +01:00
MatteoPistorello 615f1b92ca Fix visualizzazione modal programmazione interventi 2024-03-13 17:01:54 +01:00
MatteoPistorello 8622ad9da0 Fix set serial 2024-03-13 17:00:21 +01:00
Pek5892 38cd6a4145 Fix minore 2024-03-13 12:24:26 +01:00
Pek5892 df54653961 Fix minore 2024-03-13 12:23:58 +01:00
Pek5892 f2ede64b1a Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-13 11:38:40 +01:00
Pek5892 3fbe9bbe50 Ottimizzazione funzione lingue 2024-03-13 11:38:29 +01:00
Matteo 47e1a4a1d0 Filtro tariffe contratti per api APP 2024-03-13 11:17:37 +01:00
Pek5892 8aaecb8218 Fix minore 2024-03-13 10:41:05 +01:00
Pek5892 3adc516ed2 Allineamento API 2024-03-13 10:14:41 +01:00
Pek5892 0af35e0a64 Fix minori 2024-03-13 09:47:05 +01:00
Pek5892 05a6bb9123 Aggiunta tabella zz_cache_lang 2024-03-12 17:40:43 +01:00
Pek5892 ee25709e46 Fix minori 2024-03-12 17:27:26 +01:00
Pek5892 7fb94fde8f Aggiunta tabella zz_group_module_lang 2024-03-12 17:16:07 +01:00
Pek5892 032a60f653 Fix dipendenze pdf.js 2024-03-12 17:12:56 +01:00
Pek5892 5ff6d4c427 Aggiunta tabella zz_groups_lang 2024-03-12 16:39:34 +01:00
Pek5892 c7720101b9 Aggiunta tabella zz_hooks_lang 2024-03-12 15:33:57 +01:00
Pek5892 138030d5c0 Aggiunta tabella zz_imports_lang 2024-03-12 15:14:30 +01:00
Pek5892 5624f9ea07 Aggiunta tabella zz_prints_lang 2024-03-12 12:31:49 +01:00
Pek5892 0d005c1a97 Aggiunta tabella zz_tasks_lang 2024-03-12 11:32:08 +01:00
Pek5892 1016296697 Fix minore 2024-03-12 10:54:31 +01:00
Luca 8aaabb3f88 Update actions.php 2024-03-12 00:45:32 +01:00
Pek5892 c7cdee2a67 Fix minore 2024-03-11 17:23:42 +01:00
Pek5892 169df3fc07 Fix minore 2024-03-11 16:15:49 +01:00
Pek5892 407e04ee17 Aggiunta tabella zz_settings_lang 2024-03-11 15:22:37 +01:00
Pek5892 1e41d3f33d Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-11 14:23:15 +01:00
Pek5892 1a3da53ba9 Fix minore 2024-03-11 14:23:14 +01:00
MatteoPistorello afa646c36a Fix add serial 2024-03-11 13:36:59 +01:00
MatteoPistorello fe9e082f66 Gestione inserimento seriali su documenti bloccati 2024-03-11 13:36:41 +01:00
Pek5892 dd211750d3 Fix minore 2024-03-11 11:29:38 +01:00
Pek5892 a5994a5eb4 Aggiunta tabella zz_views_lang 2024-03-11 11:21:05 +01:00
Pek5892 cf68c56b3a Aggiunta tabella zz_segments_lang 2024-03-11 10:40:42 +01:00
Pek5892 5cc4a2884f Fix #1427 2024-03-08 17:20:47 +01:00
Pek5892 eff9ad1783 Aggiunta tabella zz_currencies_lang 2024-03-08 17:13:27 +01:00
Pek5892 ba8d30ecb0 Fix minore 2024-03-08 16:32:50 +01:00
Pek5892 a615bea36e Fix minori 2024-03-08 16:29:53 +01:00
Pek5892 502dcd326a Fix numero versione 2024-03-08 14:32:49 +01:00
Pek5892 d9bf9b57e7 Fix minore 2024-03-08 13:20:01 +01:00
Pek5892 9278651f00 Fix minori 2024-03-08 13:10:32 +01:00
Pek5892 e682aba173 Fix minori 2024-03-08 11:54:00 +01:00
Pek5892 4f90f52bba Aggiunta tabella co_tipi_scadenze_lang 2024-03-07 17:51:41 +01:00
Matteo aef2266684 Fix minori 2024-03-07 17:15:43 +01:00
Pek5892 cb7d6d425d Allineamento add stati ordine 2024-03-07 16:46:41 +01:00
Matteo 54e1e961bf Fix minori 2024-03-07 16:34:23 +01:00
Pek5892 ba2109c042 Allineamento add combinazioni 2024-03-07 16:20:32 +01:00
Matteo 344e116b90 Fix minori 2024-03-07 16:13:54 +01:00
Matteo 08dd078a71 Fix minori 2024-03-07 16:11:45 +01:00
Matteo a3d1313469 Introduzione campi personalizzati su applicazione + fix minori api 2024-03-07 16:08:28 +01:00
Pek5892 61199687d3 Allineamento add categorie articoli 2024-03-07 16:04:52 +01:00
Pek5892 2d3465ce4f Allineamento add attributi 2024-03-07 15:38:03 +01:00
Pek5892 659ea9f97a Allineamento add tipi intervento 2024-03-07 15:20:23 +01:00
Pek5892 91ddc0c77b Allineamento add stati intervento 2024-03-07 15:08:26 +01:00
Pek5892 675d1f11da Allineamento add template email 2024-03-07 14:52:41 +01:00
Pek5892 877379134b Allineamento add liste 2024-03-07 14:33:31 +01:00
Pek5892 88e5623a9e Allineamento add categorie documenti 2024-03-07 12:53:02 +01:00
Pek5892 00e8fb9be1 Allineamento add tipi documento 2024-03-07 10:10:42 +01:00
Pek5892 5d2d4ca620 Allineamento add stati preventivo 2024-03-07 09:50:47 +01:00
Pek5892 49083abc6a Allineamento add stati documento 2024-03-07 09:37:01 +01:00
FabioL 0294d0aa87 Fix di forma 2024-03-07 09:27:22 +01:00
Luca a5c8bdf718 Update firma_tavoletta.php 2024-03-06 19:10:13 +01:00
Luca 4aad89de9b Fix firma con tavoletta wacom 2024-03-06 19:08:20 +01:00
Luca cb1e69f6ec Fix minori 2024-03-06 18:57:19 +01:00
Pek5892 5f79a6ee71 Allineamento add stati contratti 2024-03-06 17:38:12 +01:00
Pek5892 7a904d5450 Allineamento add tipi anagrafiche e pagamenti 2024-03-06 17:26:58 +01:00
Pek5892 3c190fdcb9 Fix aggiunta articoli 2024-03-06 14:54:16 +01:00
Pek5892 2f78d4f555 Rimozione modulo Voci di servizio 2024-03-06 14:54:03 +01:00
Pek5892 cafb43878d Fix minore 2024-03-06 12:58:20 +01:00
Pek5892 77bf9dd235 Revert "Fix minore"
This reverts commit acb0a5da1d.
2024-03-06 12:48:51 +01:00
Pek5892 acb0a5da1d Fix minore 2024-03-06 12:45:19 +01:00
MatteoPistorello 4c4c4080dc Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-06 12:23:31 +01:00
MatteoPistorello 6d33274dbb Fix duplicazione interventi 2024-03-06 12:23:28 +01:00
Pek5892 5d77defea7 Fix minore 2024-03-06 12:19:37 +01:00
MatteoPistorello ef16c663eb Fix allineamento orari sessioni in line 2024-03-06 11:57:36 +01:00
MatteoPistorello aa1abce671 Fix select sede in preventivi 2024-03-06 11:23:52 +01:00
MatteoPistorello 762463d01a Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-06 11:23:16 +01:00
MatteoPistorello 7e2b19ee45 Fix plugin impianti 2024-03-06 11:23:14 +01:00
Pek5892 9f53db57db Fix minore 2024-03-06 11:02:37 +01:00
Pek5892 9d9bd9e4bc Fix minori 2024-03-06 10:56:09 +01:00
Pek5892 8f279df90a Fix minori 2024-03-06 09:23:43 +01:00
Luca d63a9f300c Fix minori 2024-03-05 17:39:32 +01:00
MatteoPistorello ff5e68e5ec Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-05 17:31:39 +01:00
MatteoPistorello c05cb17fb0 Migliorie plugin Impianti 2024-03-05 17:31:36 +01:00
Luca eca64a10d4 Revert "Merge branch 'master' of https://github.com/devcode-it/openstamanager"
This reverts commit 0ade18167a, reversing
changes made to 72171f24b9.
2024-03-05 17:03:25 +01:00
Pek5892 791d1431f4 Fix minore 2024-03-05 16:46:22 +01:00
Pek5892 f43d67e20d Fix minore 2024-03-05 16:36:14 +01:00
Pek5892 0ade18167a Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-03-05 16:04:34 +01:00
Pek5892 72171f24b9 Aggiunta tabella zz_modules_lang 2024-03-05 16:01:45 +01:00
Luca 8e42483c7e Controlla che l'utente che voglio eliminare non presenti logs associati 2024-03-05 15:12:39 +01:00
Pek5892 6318f722bd Fix minore 2024-03-04 14:41:36 +01:00
Pek5892 1985015aeb Aggiunta tabella zz_plugins_lang 2024-03-04 13:17:54 +01:00
Pek5892 cd92b6b58f Aggiunta tabella zz_widgets_lang 2024-03-04 12:28:16 +01:00
Luca 04f0d8a20c Aggiunto backup del solo database 2024-03-04 02:07:58 +01:00
Luca fd7a021605 Fix minori 2024-03-03 18:42:16 +01:00
Luca 9d8f884e18 Aggiunta esclusioni da backup del db 2024-03-03 17:52:50 +01:00
Luca 7c3e8a63d4 Fix minori 2024-03-03 12:55:26 +01:00
Luca 641d1aee80 Rinomino i file zip all'interno della cartella di backup, aggiungendo "COMPLETO" alla fine del nome 2024-03-03 12:29:42 +01:00
Luca ca0cc77b86 Aggiunta informazione tipologia backup creato 2024-03-03 10:25:39 +01:00
Luca cc834940d2 Aggiunta possibilità di creazione backup escludendo la cartella files 2024-03-02 23:04:03 +01:00
Luca 20a4c9dc2e Migliorato Pulsante Precedente e Successivo all'interno della scheda attività 2024-03-02 17:16:51 +01:00
Luca 6406135540 Fix duplicazione attività da scheda attività 2024-03-02 14:22:02 +01:00
Luca 752d4feceb Aggiunta verifica integrità db per MariaDB 10.x 2024-03-02 02:52:30 +01:00
Luca ccc80f5408 Retrofix 2.4.14 per compatibilità MariaDB 10.6.x 2024-03-02 01:51:46 +01:00
Luca 67eac60e8b Retrofix 2.4.14 per compatibilità MariaDB 10.6.x 2024-03-02 01:37:38 +01:00
Pek5892 a69f016a29 Fix vari 2024-03-01 17:32:31 +01:00
Pek5892 cd801efce9 Fix minore 2024-03-01 16:17:00 +01:00
Pek5892 da00337c6c Fix minore 2024-03-01 15:48:43 +01:00
Pek5892 c6da8e890a Fix minore 2024-03-01 15:47:24 +01:00
Luca 1fbb02fbaa Fix per tasto command su MAC 2024-03-01 15:34:47 +01:00
Matteo 0d85aba8f6 Fix minori 2024-03-01 15:29:28 +01:00
Pek5892 87529dd442 Fix minori 2024-03-01 15:07:42 +01:00
Matteo 132579719c Introduzione stampa cespiti 2024-03-01 14:49:13 +01:00
Pek5892 2cbbea902b Fix minore 2024-03-01 13:16:58 +01:00
Pek5892 685a1b7dcb Fix minori 2024-03-01 12:10:39 +01:00
Pek5892 c894c20c12 Fix minori 2024-03-01 11:53:07 +01:00
Pek5892 58dcb1e099 Aggiunta tabella or_tipiordine_lang 2024-03-01 11:49:21 +01:00
Pek5892 98259586f1 Aggiunta tabella or_statiordine_lang 2024-03-01 11:32:13 +01:00
Pek5892 6168165bcb Aggiunta tabella mg_combinazioni_lang 2024-03-01 09:54:39 +01:00
Pek5892 331fb5094e Aggiunta tabella mg_causali_movimenti_lang 2024-03-01 09:27:21 +01:00
Pek5892 9073633705 Aggiunta tabella mg_categorie_lang 2024-03-01 09:08:08 +01:00
Pek5892 026127d7b3 Aggiunta tabella mg_attributi_lang 2024-02-29 17:42:08 +01:00
Pek5892 8cecb9c4eb Fix minore 2024-02-29 16:23:02 +01:00
Pek5892 5b8f1e9834 Aggiunta tabella mg_articoli_lang 2024-02-29 15:10:55 +01:00
Pek5892 e1fb9d763c Fix minori 2024-02-29 11:56:21 +01:00
Pek5892 d5285a36b4 Fix minore 2024-02-29 09:55:44 +01:00
Pek5892 36998c07a2 Aggiunta tabella in_tipiintervento_lang 2024-02-28 16:28:53 +01:00
Pek5892 cced7ac246 Fix query widgets attività 2024-02-28 15:32:40 +01:00
Pek5892 e113edaacb Aggiunta tabella in_statiintervento_lang 2024-02-28 15:28:39 +01:00
Pek5892 088f520374 Aggiunta tabella in_fasceorarie_lang 2024-02-28 11:39:12 +01:00
Pek5892 b1fbc4ce21 Aggiunta tabella fe_tipi_documento_lang 2024-02-28 11:17:46 +01:00
Pek5892 3774755825 Aggiunta tabella fe_stati_documento_lang 2024-02-28 10:50:39 +01:00
Pek5892 bf399db100 Aggiunta tabella fe_regime_fiscale_lang 2024-02-28 10:28:23 +01:00
Pek5892 61facdfc3d Aggiunta tabella fe_natura_lang 2024-02-28 10:21:46 +01:00
Pek5892 a058f89f9a Aggiunta tabella fe_modalita_pagamento_lang 2024-02-28 10:16:03 +01:00
Pek5892 0f8b68e7d6 Aggiunta tabella em_templates_lang 2024-02-28 09:38:04 +01:00
Luca 6490ca640d Pulsante Precedente e Successivo all'interno della scheda attività 2024-02-28 01:46:48 +01:00
Pek5892 39b6c16345 Aggiunta tabella em_lists_lang 2024-02-27 16:34:12 +01:00
Pek5892 9e0abc0d8a Aggiunta tabella dt_tipiddt_lang 2024-02-27 15:51:13 +01:00
Pek5892 fce1ce09c9 Fix minore 2024-02-27 14:54:33 +01:00
Pek5892 c39cc5412d Aggiunta tabella `dt_statiddt_lang` 2024-02-27 12:55:27 +01:00
Pek5892 7fdf81dafa Aggiunta tabella dt_spedizione_lang 2024-02-27 11:57:42 +01:00
Pek5892 2bde2db940 Aggiunta tabella dt_porto_lang 2024-02-27 11:29:48 +01:00
Pek5892 1b3ba587e4 Aggiunta tabella dt_causalet_lang 2024-02-27 11:10:40 +01:00
Pek5892 760b594e70 Aggiunta tabella dt_aspettobeni_lang 2024-02-27 09:59:44 +01:00
Pek5892 74930d424f Aggiunta tabella do_categorie_lang 2024-02-27 09:39:20 +01:00
Pek5892 12a3a760e3 Fix minore 2024-02-26 16:49:38 +01:00
Pek5892 b7f2fa13b6 Aggiunta tabella co_tipidocumento_lang 2024-02-26 15:53:39 +01:00
Pek5892 70d48973bd Fix minore 2024-02-26 11:16:21 +01:00
Luca 09b2f3d236 Controllo per "Data inizio verifica contatore fattura di vendita" valorizzata 2024-02-26 11:14:09 +01:00
Pek5892 fe6677e760 Aggiunta tabella co_statipreventivi_lang 2024-02-26 10:50:43 +01:00
Pek5892 17e004f0f7 Aggiunta Controparte in plugin Movimenti 2024-02-26 08:52:46 +01:00
loviuz 1bb7878a06 Fix query di aggiornamento 2024-02-25 22:54:16 +01:00
loviuz fa42d44bb2 Spostata posizione dell'accettazione licenza 2024-02-25 22:50:08 +01:00
Luca 6552a1bba3 Update validation.php 2024-02-25 17:26:59 +01:00
Luca 0d81129756 Update validation.php 2024-02-25 17:24:06 +01:00
Luca 04e541ff6a Update edit.php 2024-02-25 17:19:34 +01:00
Luca ed1e233eee Auto-completamento codice intermediario per anagrafiche con tipologia Azienda 2024-02-25 16:30:47 +01:00
Luca 93adf5b23e Validazione indirizzo email in aggiunta utente 2024-02-25 16:08:22 +01:00
Luca 99eb832786 Introduco tabella an_sdi per censire tutti i codici degli intermediari di fatturazione elettronica italiani 2024-02-25 13:52:32 +01:00
Luca 01c8675215 Aggiunto controllo per validare codice intermediario in anagrafica 2024-02-25 13:31:59 +01:00
Luca a5e39bf800 Fix minori 2024-02-25 13:22:06 +01:00
Luca 3a5a942051 Migliorie minori 2024-02-25 11:24:18 +01:00
Luca bb4fb17b4d Anticipa di 2 giorni l'avviso se la scadenza per invio della fattura elettronica di vendita cade di sabato o domenica 2024-02-24 01:19:15 +01:00
Luca e684fe1e12 Anticipa la data di 2 giorni l'avviso se la scadenza per invio della fattura elettronica di vendita cade di sabato o domenica 2024-02-24 01:08:41 +01:00
Luca 7fdad47f3b Migliorati messaggi ricevute hooks 2024-02-24 00:47:43 +01:00
Luca 8e2049270b Impostazione per data inizio verifica contatore fattura di vendita 2024-02-24 00:47:01 +01:00
Luca f54ec72fc7 Update edit.php 2024-02-23 19:44:52 +01:00
Luca 03dd006979 Fix #1440 2024-02-23 19:44:46 +01:00
Luca 963e214308 Se la fattura presenta già una ricevuta principale con un codice che non di scarto e il codice delle ricevuta da importare è 00404 (Fattura duplicata), non aggiorno la ricevuta. 2024-02-23 18:50:02 +01:00
Luca 1525a72efe Aggiunta informazione "suggerimento" per ricevute fatture elettroniche 2024-02-23 18:28:45 +01:00
Luca 84c3e061ee Migliorie minori 2024-02-23 18:18:50 +01:00
Luca bcb8cb0ac3 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-02-23 16:42:50 +01:00
Luca 0925445981 Corretto avviso codice anagrafica già presente
Uniformato stili avvisi warning e danger
2024-02-23 16:42:43 +01:00
Pek5892 a490a5746b Miglioria plugin Regole pagamenti 2024-02-23 16:40:25 +01:00
Pek5892 8227b32fda Fix impostazione segmento predefinito limitata ai sezionali 2024-02-23 16:22:17 +01:00
Luca 7efb51f0bb In fase di emissione documento ciclo attivo
Controllo p.iva valorizzata in caso l'anagrafica Azienda sia di tipologia 'Azienda' o codice fiscale in caso sia tipologia 'Ente pubblico'
2024-02-23 16:08:17 +01:00
Pek5892 5c7f5cc712 Fix ricerca in piano dei conti 2024-02-23 15:14:00 +01:00
Pek5892 4633113022 Aggiunto avviso nel caso di righe con quantità a 0. 2024-02-23 14:40:08 +01:00
Luca f1f3e553a7 Fix minore 2024-02-23 13:14:38 +01:00
Pek5892 8789a839ad Fix minore 2024-02-23 12:37:46 +01:00
Luca 657a9b47e6 Aggiunta funzione per richiesta AJAX hooks completata con successo
Altre migliorie minori
2024-02-23 12:08:25 +01:00
Beppe ad29334cc0 Correzione stampa carico automezzi 2024-02-23 09:48:01 +01:00
Pek5892 98b79a3052 fix minore 2024-02-22 18:00:40 +01:00
Luca cdbda8eaed Update requirements.php 2024-02-22 17:17:42 +01:00
Luca 31d11bdee0 Update requirements.php 2024-02-22 17:12:35 +01:00
Luca c3107c1969 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-02-22 17:11:29 +01:00
Luca 6a24c96952 Fix minori 2024-02-22 17:11:22 +01:00
Pek5892 ae2cfdde4f Fix minori 2024-02-22 17:03:48 +01:00
Pek5892 39374285e0 Fix minori 2024-02-22 17:03:37 +01:00
Pek5892 8373970656 Aggiunta navigazione attività con codice precedente e successivo 2024-02-22 17:03:32 +01:00
Luca 5334747609 Aggiunta visualizzazione sessioni attive in stato dei servizi. 2024-02-22 15:58:03 +01:00
Luca 6da04b302e In aggiornamenti visualizzo il tipo di interfaccia di PHP 2024-02-22 01:09:14 +01:00
Luca 6f7d9f1dc3 Aggiunto flag "Fatture Elettroniche" in segmenti 2024-02-22 00:00:38 +01:00
Luca 67856a523a Aggiunta informazione di creazione per campi delle viste 2024-02-21 23:37:02 +01:00
Luca 263e9b100f Fix per errore creazione tabella an_sedi_tecnici v. 2.4.52 2024-02-20 18:08:05 +01:00
Pek5892 3fffd5f1d9 Fix minore 2024-02-20 16:35:40 +01:00
Pek5892 8b6ebe4be1 Fix per invio sms whatsapp 2024-02-20 16:33:44 +01:00
Pek5892 c6fced8ff2 Fix minore 2024-02-20 16:24:14 +01:00
Pek5892 ecb234178d Esclusione autofatture dalla stampa fatturato 2024-02-20 14:37:53 +01:00
loviuz 4b380fbff5 Miglioramento grafico riquadro plugin 2024-02-20 14:11:01 +01:00
loviuz eedada707b Fix su aggiunta attività per utenti senza permessi specifici 2024-02-20 13:53:41 +01:00
Pek5892 886ae8fe14 Fix vista utenti e permessi 2024-02-20 13:03:44 +01:00
loviuz 52400fac42 Aggiornamento chiave di licenza per Wacom v2 2024-02-19 19:03:55 +01:00
Pek5892 2720e99581 Fix pagamenti 2024-02-16 16:32:19 +01:00
Pek5892 0e1afcff37 Fix minori 2024-02-16 14:49:10 +01:00
Pek5892 fafab7221f Aggiunta creazione automatica banca in import CSV anagrafiche 2024-02-16 14:49:00 +01:00
Pek5892 435edd153a Fix modifica stati dei contratti 2024-02-16 12:46:17 +01:00
Pek5892 e41618dc7d Fix minore 2024-02-16 12:35:42 +01:00
Pek5892 45f0edf0ab Fix minore 2024-02-16 12:24:12 +01:00
Pek5892 8d0bcbc1d0 Allineamento vista Tecnici e tariffe 2024-02-16 11:20:17 +01:00
Pek5892 5d11a63c18 Fix minore 2024-02-16 10:10:17 +01:00
Luca b2b39cbff4 Update init.php 2024-02-15 18:33:39 +01:00
Pek5892 7385be6218 Fix aggiunta conto in partitario 2024-02-15 17:47:17 +01:00
Pek5892 a711877c19 Fix minore 2024-02-15 17:03:44 +01:00
Pek5892 ca82ceb175 Fix minore 2024-02-15 16:52:46 +01:00
Pek5892 7d928242cb Fix minore 2024-02-15 15:09:43 +01:00
Luca fc25f24713 Aggiunto blocco Aggiorna informazioni di acquisto in fase di import fe 2024-02-14 19:18:03 +01:00
Luca ed2408b3ca Update generate.php 2024-02-14 17:48:40 +01:00
Luca a6692b34bb Update generate.php 2024-02-14 17:28:56 +01:00
Pek5892 c86b027955 Fix minore 2024-02-14 17:23:06 +01:00
Pek5892 7e16c40d24 Fix minore 2024-02-14 16:46:45 +01:00
loviuz 66b5e663ee Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-02-14 16:15:10 +01:00
loviuz 04c89f8596 Spostamento fix aggiustamenti contabili su penultimo conto 2024-02-14 16:15:07 +01:00
Pek5892 be1200fb7b Fix per iva indetraibile 2024-02-14 15:05:53 +01:00
Pek5892 88bd9c993d Aggiunta riferimento attività collegate ai ddt 2024-02-14 13:06:44 +01:00
Pek5892 17a6174f9f Fix RegimeFiscale in generazione XML fattura 2024-02-14 10:55:28 +01:00
Pek5892 ad96b9e30c Fix minore 2024-02-13 18:05:37 +01:00
Pek5892 9c91c51042 Fix minore 2024-02-13 17:52:08 +01:00
Pek5892 c3861da79e Fix minore 2024-02-13 17:29:06 +01:00
Pek5892 0b402f12d1 Fix generazione scadenze 2024-02-13 17:16:47 +01:00
Pek5892 9e4ced1fea Fix minori 2024-02-13 17:01:18 +01:00
MatteoPistorello c3bebe640f Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-02-13 16:55:36 +01:00
MatteoPistorello 82cdbeb723 Fix validazione campo in fase di duplicazione 2024-02-13 16:55:32 +01:00
Pek5892 06991f8b79 Fix minore 2024-02-13 16:38:15 +01:00
Pek5892 a9c4abfef6 Fix 2024-02-13 15:56:56 +01:00
Pek5892 5beba88c4b Formattazione codice 2024-02-13 15:50:26 +01:00
Pek5892 2f42eb061e Aggiunta tabella co_statidocumento_lang 2024-02-13 15:49:40 +01:00
Luca 331e525ee9 Aggiunta colonna N. utenti abilitati e N. API abilitate
Migliorato messaggio informativo per interventi non fatturati.
2024-02-12 19:17:33 +01:00
Luca 571b5d2f85 Aggiunte skin light per tema 2024-02-12 18:13:39 +01:00
loviuz 74ad2bd1e3 Fix arrotondamento movimenti contabili 2024-02-12 10:32:39 +01:00
loviuz 801ed47ef8 Correzione problemi di sbilanciamento contabile 2024-02-09 17:12:47 +01:00
Pek5892 94c630b8de Aggiunta tabella co_staticontratti_lang 2024-02-09 12:08:55 +01:00
Pek5892 17fa885d33 Allineamento widget anagrafiche 2024-02-08 16:57:35 +01:00
Pek5892 09934d7f7a Fix minore 2024-02-08 16:26:31 +01:00
Pek5892 d6359306be Fix minore 2024-02-08 15:58:34 +01:00
Pek5892 c8c3afbc83 Aggiunta tabella co_pagamenti_lang 2024-02-08 13:10:46 +01:00
Luca 7782769922 Fix per file sql di update aggiornato dopo rilascio 2.4.35 2024-02-08 11:34:56 +01:00
Luca 58bab546d8 Fix per file sql di update aggiornato dopo rilascio 2.4.35 2024-02-08 11:24:43 +01:00
Luca 107eb6fb4d Update KNOWN-ISSUES.md 2024-02-08 11:13:31 +01:00
Luca cf0ff2c4ae Introduzione del file KNOWN-ISSUES.md 2024-02-08 11:12:12 +01:00
loviuz 068e0cd102 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-02-08 09:31:08 +01:00
loviuz 4e573c53df Aggiunta log rimozione sessioni per velocizzare sincronizzazione app 2024-02-08 09:31:07 +01:00
Pek5892 0f60108464 Fix per avviso ckeditor 2024-02-07 17:11:04 +01:00
Beppe 305c772f80
Fix lettura valori da campi personalizzati 2024-02-07 15:57:40 +01:00
MatteoPistorello 5c38f26f48 Fix data inizio e fine intervento 2024-02-07 14:18:13 +01:00
MatteoPistorello b56416712f Fix creazione banca in fase di importFE 2024-02-07 09:52:14 +01:00
MatteoPistorello b23315f2b2 Fix minore importFE 2024-02-07 09:42:16 +01:00
Luca 67e3e8db9f
Merge pull request #1433 from lepool/master 2024-02-07 08:02:42 +01:00
Pek5892 bb4ba12185 Aggiunta tabella co_iva_lang 2024-02-06 17:36:05 +01:00
Pek5892 66305b3657 Fix minori 2024-02-06 17:25:50 +01:00
Pek5892 6722e59de4 Fix creazione config 2024-02-06 16:27:00 +01:00
Pek5892 e13ad96b65 Fix minore 2024-02-06 14:38:30 +01:00
Pek5892 9e07fb442f Fix importazione fatture 2024-02-06 12:07:51 +01:00
Pek5892 92b4746585 Fix minori 2024-02-06 11:36:09 +01:00
Pek5892 bf275837e0 Fix per importazione fattura di acquisto con rivalsa non specificata nelle righe 2024-02-06 10:23:55 +01:00
Pek5892 ff89f281e2 Prima aggiunta tabelle traduzioni 2024-02-05 17:07:33 +01:00
MatteoPistorello c6107b0121 Fix flag fatturazione 2024-02-05 16:23:30 +01:00
Luca 4e9169f227 Rendo il flag is_fatturabile condizione sufficiente per poter fatturare l'attività che si trova in uno stato relativo 2024-02-05 12:39:39 +01:00
Luca 71eea29909 Ripristino versione dipendenza symfony/translation 2024-02-03 18:48:46 +01:00
lepool b36a5f7d91 risolto problema errore notifica lettura email mancante 2024-02-02 16:21:55 +01:00
Luca 7cd3b7180e Abilito il ritorno al punto precedente anche per i dispositivi mobili 2024-02-02 14:15:50 +01:00
loviuz 2bafa32b19 Anticipazione miglioria su API impianti eliminati 2024-02-02 09:12:42 +01:00
Pek5892 033fff9b00 Aggiornamento CHANGELOG 2024-02-01 15:26:59 +01:00
Pek5892 0c6293bac3 Fix minore 2024-01-31 16:23:19 +01:00
Pek5892 8fd3170fdd Fix minore 2024-01-31 14:32:05 +01:00
Pek5892 71b1f91005 Formattazione codice 2024-01-31 14:23:46 +01:00
Pek5892 47801bf4f8 Aggiunta impostazione per timeout tavoletta grafica 2024-01-31 12:21:32 +01:00
Pek5892 9e6d1ba37e Fix minore 2024-01-31 11:46:26 +01:00
Pek5892 1c2202a51b Fix minore 2024-01-31 11:02:49 +01:00
Beppe 8966998511 Fix valorizzazione campi personalizzati 2024-01-31 09:12:25 +01:00
loviuz 992d0bc57e Fix per installazione iniziale 2024-01-31 00:13:46 +01:00
MatteoPistorello 14f3ef9556 Fix fatturazione promemoria 2024-01-30 14:59:44 +01:00
MatteoPistorello abea14a12e Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-01-30 10:29:10 +01:00
MatteoPistorello b2c05c8701 Fix autenticazione oauth2 2024-01-30 10:29:08 +01:00
Pek5892 620a3317e1 Fix minore 2024-01-30 09:16:17 +01:00
MatteoPistorello 9f01ead36b Migliorie pianificazione promemoria 2024-01-29 16:00:59 +01:00
MatteoPistorello d29cc8d55e Fix minore 2024-01-29 09:49:42 +01:00
MatteoPistorello 4162871c10 Fix minore eventi in dashboard 2024-01-26 17:08:00 +01:00
MatteoPistorello 6b80a88343 Merge 2024-01-26 17:00:37 +01:00
MatteoPistorello 9e2b76ffdf Gestione login tramite Microsoft 2024-01-26 17:00:02 +01:00
Pek5892 2541aaec3a Correzione vista fatture di vendita 2024-01-26 16:05:04 +01:00
Pek5892 725a0870d5 Aggiunta sede di partenza merce in stampa ddt 2024-01-26 14:48:13 +01:00
Luca fbdd4f4587 Aggiunta variabile random per evitare la cache del browser
in fase di link pdf o anteprima stampa
2024-01-26 12:34:14 +01:00
Pek5892 921fc0ad98 Fix selezione automatica sezionale documento 2024-01-25 17:41:19 +01:00
Luca 328f03b473 Fix minori 2024-01-24 19:23:52 +01:00
Pek5892 039054a300 Aggiunta metodo getValue per la lettura dei valori dei campi personalizzati 2024-01-24 17:50:16 +01:00
loviuz 9c1d3a0ed7 Fix per campi personalizzati 2024-01-24 15:52:26 +01:00
Luca 6bb0bad1dd Update 2_4_23.sql 2024-01-23 18:24:25 +01:00
Luca ac78f3d589 Retrofix query update 2.4.23 2024-01-23 18:23:04 +01:00
MatteoPistorello f527f7cfe9 Fix add serial 2024-01-23 15:17:06 +01:00
MatteoPistorello e18c2e2da6 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-01-23 15:09:03 +01:00
MatteoPistorello 7ee0b0ff50 Fix minore 2024-01-23 15:09:00 +01:00
Luca 1f8cd4edd0 Update ajax_tecnici.php 2024-01-22 15:04:41 +01:00
Luca 775903561c Fix per controllo File di servizio 2024-01-19 18:04:08 +01:00
Luca ae996c22a2 Migliorato esempio import Attività 2024-01-19 18:01:33 +01:00
MatteoPistorello 754d5d22bf Fix pianificazione intervento 2024-01-19 15:26:12 +01:00
MatteoPistorello f96cc83379 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2024-01-19 15:25:39 +01:00
MatteoPistorello c8ceb36dc8 Aggiunta gestione fatturazione in bulk raggruppata per sede 2024-01-19 15:25:36 +01:00
Pek5892 f693fbfe7b Fix minore 2024-01-19 15:19:27 +01:00
Luca 87f91d4ab2 Update DefaultHandler.php 2024-01-19 11:55:56 +01:00
Luca 4d2a5bf0ea Aggiunta colonna tema in utenti e permessi 2024-01-19 11:18:36 +01:00
Luca 59aabaf705 Fix minori 2024-01-19 10:32:20 +01:00
Pek5892 13dbb3d80a Fix per firma da mobile 2024-01-19 09:06:25 +01:00
Pek5892 764ffb7639 Fix minore 2024-01-19 09:06:13 +01:00
Luca c26cc608f4 Aggiunta possibilità di impostare un tema diverso per ogni gruppo di utenti 2024-01-18 22:39:15 +01:00
Luca 02ffb6d811 Aggiunto controllo file settings.json
Fix varie
2024-01-18 20:40:52 +01:00
Pek5892 0bd7cb533b Fix minore 2024-01-17 18:06:37 +01:00
Pek5892 3b35d3ff42 Fix minore 2024-01-17 11:10:52 +01:00
Matteo 3e3d70e87e Fix api login app 2024-01-17 10:45:36 +01:00
Matteo 17423f2131 Fix api checklist per impianto 2024-01-17 10:45:12 +01:00
Pek5892 f0aba5bd4b Fix selezione fornitore predefinito in articoli 2024-01-16 15:43:29 +01:00
Pek5892 92fb4f9bd0 Miglioria controllo su impostazioni 2024-01-16 10:23:22 +01:00
Pek5892 0462c0acc0 Fix minore 2024-01-15 15:51:24 +01:00
Pek5892 5b4abf66f1 Fix minore 2024-01-15 15:34:29 +01:00
Pek5892 b3c6cb7110 Formattazione codice 2024-01-15 15:30:45 +01:00
Pek5892 453b3603cc Aggiunta controllo su impostazioni 2024-01-15 14:52:26 +01:00
loviuz 0dace8b900 Aggiornamento versione dipendenze 2024-01-13 01:07:23 +01:00
loviuz f01affbf55 Rimozione file di test codeception 2024-01-13 01:04:42 +01:00
loviuz 2636a71ef7 Adattamento form di login a AdmitLTE 2024-01-13 00:21:37 +01:00
loviuz c0b632b4e6 Cambio icona di aggiornamento completato 2024-01-12 23:25:59 +01:00
Pek5892 2dae8961a3 Fix aggiunta scadenza 2024-01-12 11:05:16 +01:00
Luca 02b9f581e3 Fix commit campi ckeditor in modifica attività 2024-01-11 18:55:24 +01:00
Pek5892 702ddd712d Fix campi ckeditor in modifica attività 2024-01-11 17:55:15 +01:00
Pek5892 58736564be Aggiunta carattere non supportato 2024-01-11 09:30:37 +01:00
Pek5892 6e31818c53 Fix modifica orario inline sessione tecnici 2024-01-10 16:34:51 +01:00
Pek5892 f380044c60 Fix minori 2024-01-10 15:08:26 +01:00
Pek5892 322e7483f5 Fix stampa ordini con immagine 2024-01-10 15:08:09 +01:00
Pek5892 3edf623da0 Fix #1421 e ottimizzazioni 2024-01-08 16:54:27 +01:00
Pek5892 f463e0cab7 Fix minore 2024-01-08 14:34:17 +01:00
Luca 54bb955759 Update requirements.php 2024-01-06 19:37:05 +01:00
Luca 34a0edd2d0 Aggiunto try catch per funzione exec sconosciuta 2024-01-06 19:34:00 +01:00
Pek5892 f40d3ee4f3 Fix minore 2024-01-04 16:58:44 +01:00
Pek5892 98a7a6ed79 Aggiornamento CHANGELOG 2024-01-04 16:23:05 +01:00
Pek5892 7cdfbbff18 Formattazione codice 2024-01-04 14:47:06 +01:00
Pek5892 96f1a62e0f Fix php8.0 2024-01-02 16:14:18 +01:00
Pek5892 7aa8e90d24 Fix quantità righe per servizi 2024-01-02 16:05:41 +01:00
MatteoPistorello 421f4129a7 Modifica visualizzazione plugin movimenti in Anagrafiche 2024-01-02 15:52:43 +01:00
MatteoPistorello 07f3f139a6 Merge 2023-12-29 16:16:15 +01:00
MatteoPistorello 9976403e41 Aggiunta icona nelle righe dei documenti per segnalare incogruenza importi 2023-12-29 16:15:38 +01:00
MatteoPistorello 9996dc6df8 Aggiunte azioni di gruppo per associare i listini ad anagrafiche e articoli 2023-12-28 17:14:26 +01:00
MatteoPistorello 9ec77ca597 Gestione import listini cliente 2023-12-28 16:18:26 +01:00
MatteoPistorello 2d2bf85710 Migliorie listini cliente e impostazione listino predefinito 2023-12-28 16:18:02 +01:00
Pek5892 cb984db073 Miglioria stampe automezzi 2023-12-28 14:24:49 +01:00
Pek5892 29f35ff91e Aggiunta impostazione per importazione seriali in import fe 2023-12-28 09:56:34 +01:00
Luca 513e17e33d Campo descrizione attività incolonnato su schermi piccoli 2023-12-27 14:43:49 +01:00
Luca 5539326a58 Fix per controllo esistenza cartella backup 2023-12-27 14:43:10 +01:00
Pek5892 0e14bf0923 Fix minore 2023-12-27 12:24:55 +01:00
Pek5892 14f55a1998 Fix minore 2023-12-21 13:03:49 +01:00
Pek5892 307570f0cb Modifica valore decimali quantità in stampa di default a 2 2023-12-21 11:25:05 +01:00
Pek5892 c1fe86c222 Aggiunta colonna email in vista Anagrafiche 2023-12-21 09:20:21 +01:00
Pek5892 b4b4a67abf Fix minore 2023-12-20 15:42:24 +01:00
Pek5892 af97d0d310 Corretta l'applicazione della rivalsa sulla marca da bollo 2023-12-20 15:08:21 +01:00
Pek5892 02c35f1d41 Aggiunto mod_mime ai requisiti server 2023-12-20 13:03:44 +01:00
Pek5892 ec48dffbcd Aggiornamento vista Fatture di vendita 2023-12-20 09:51:42 +01:00
Beppe 566e0e0e38 Correzione vista riferimenti DDT in ordini cliente 2023-12-19 15:39:32 +01:00
Pek5892 f15b28fcb3 Aggiunta gestione inline sessioni 2023-12-19 12:11:18 +01:00
Pek5892 70c9e02126 Fix calcolo ritenuta in import fe 2023-12-18 16:10:45 +01:00
loviuz 6dffe7b481 Aggiornamento ricerce OSM in italiano 2023-12-18 15:01:50 +01:00
Beppe 3501e0ffee Fix iva acquisto articoli 2023-12-18 12:42:23 +01:00
Pek5892 bf5fcd87fe Fix maggiorazione in importo fe 2023-12-18 12:26:44 +01:00
Pek5892 768b5fd5a7 Fix arrotondamenti 2023-12-15 17:29:06 +01:00
MatteoPistorello f16395151a Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-12-15 13:18:20 +01:00
MatteoPistorello 17f64af531 Fix serial in documenti di acquisto 2023-12-15 13:17:35 +01:00
Matteo 66d6912c92
Fix ricerca coordinate con google maps 2023-12-15 12:11:24 +01:00
Pek5892 90c31c9d23 Aggiunta ricerca articolo per barcode in importazione fattura 2023-12-14 14:53:25 +01:00
Luca 8b2bd668a8 Aggiornamento file catalog.pot 2023-12-14 10:27:24 +01:00
Beppe 4ccbcc7cab Fix versione 2023-12-14 09:37:54 +01:00
Beppe 96df096a68 Fix filtro sede in selettore articoli modulo automezzi 2023-12-14 09:27:48 +01:00
Beppe 9736ec97aa Aggiunti dettagli aggiuntivi in sedi per dettagli automezzi 2023-12-14 09:27:15 +01:00
Pek5892 3fad8c53a1 Fix immagine in stampa ordini 2023-12-13 17:51:09 +01:00
Pek5892 ea49c110d4 Aggiunta impostazione per raggruppare i riferimenti riga in fase di stampa 2023-12-13 17:33:24 +01:00
Pek5892 e6e8ed58da Fix minore 2023-12-13 17:33:01 +01:00
Pek5892 1edc3189ff Fix minore 2023-12-13 11:44:45 +01:00
Pek5892 fd8869d400 Fix per visualizzazione plugin sede anagrafica Azienda 2023-12-13 11:41:59 +01:00
loviuz 47c65d4802 Fix minore 2023-12-12 17:18:51 +01:00
loviuz 90a8a6527c Pre-caricamento prezzo di vendita all'aggiunta articolo in listino cliente 2023-12-12 17:05:55 +01:00
Pek5892 e04785d530 Fix plugin consuntivo 2023-12-11 11:57:17 +01:00
loviuz 02c988db3f Aggiunta ottimizzazione per dipendenze di composer 2023-12-08 23:03:12 +01:00
loviuz fa68a95c58 Miglioramento ricerche con OpenStreetMap 2023-12-08 13:47:56 +01:00
Luca 93527d7c7c Update tables.php 2023-12-08 11:08:26 +01:00
Luca 69bb242570 Update CHANGELOG.md 2023-12-08 11:01:52 +01:00
Luca 4ea3cc130c Update edit.php 2023-12-08 10:52:40 +01:00
Pek5892 52150c17d7 Fix per php8.0 2023-12-07 18:12:20 +01:00
Pek5892 c2744876c6 Fix minore 2023-12-07 16:52:27 +01:00
Pek5892 a8ad5f3f5a fix changelog 2023-12-07 16:39:33 +01:00
Pek5892 224e1eca85 fix 2023-12-07 16:36:18 +01:00
Pek5892 1ea3829ae1 Aggiornamento CHANGELOG 2023-12-07 16:35:40 +01:00
Beppe 968fd7f1dc Migliorie query modulo interventi 2023-12-07 10:50:33 +01:00
Pek5892 bf19f15f52 Formattazione codice 2023-12-06 17:24:23 +01:00
Pek5892 0c41dc9bb8 Modifica modutil per permettere aggiunta custom 2023-12-06 16:48:54 +01:00
Pek5892 09fe13d5d9 Formattazione codice 2023-12-06 15:06:49 +01:00
Pek5892 eed67da504 Fix creazione attività da documenti 2023-12-06 13:20:55 +01:00
Pek5892 154b2a80f4 Fix campo icon_Inviata in vista fatture di vendita 2023-12-06 12:33:23 +01:00
Pek5892 0a606fece8 Fix righe per quantità = 0 2023-12-06 12:27:34 +01:00
Pek5892 1dea0135da Modifica vista ricarico nd 2023-12-06 12:27:22 +01:00
Beppe 34c3b6242b Fix campi personalizzati con valori multipli 2023-12-06 11:20:28 +01:00
Pek5892 d7316f73ee Retrofix impostazione cifre decimali 2023-12-06 10:33:31 +01:00
Pek5892 c28adb3d79 Aggiunta impostazione decimali per totali in stampa 2023-12-06 10:06:36 +01:00
Pek5892 d8d3855052 Aggiunta variabile nome preventivo ai preventivi 2023-12-06 09:21:34 +01:00
Luca 741130f30b Rimosso codice di debug 2023-12-05 19:36:13 +01:00
Luca 0aebed89cf Fix per permettere valore 0 su impostazioni decimali per quantità e importi in stampa 2023-12-05 19:35:01 +01:00
loviuz 7faaf50888 Fix per funzionamento campi personalizzati 2023-12-05 18:04:50 +01:00
Pek5892 bff0ddf748 Aggiunte impostazioni decimali per quantità e importi in stampa 2023-12-05 17:43:35 +01:00
Pek5892 70f8a79d91 Fix minore 2023-12-05 16:41:33 +01:00
Pek5892 fe1ea7e935 Fix per aggiunta banca da fattura di vendita 2023-12-05 13:01:20 +01:00
Pek5892 2b9f735f98 Fix aliquota in stampa ordini 2023-12-05 11:42:22 +01:00
Pek5892 967c6a28d6 Fix righe ordini con quantità a 0 2023-12-05 11:36:46 +01:00
MatteoPistorello 1f4fca3c6e Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-12-05 10:48:10 +01:00
MatteoPistorello 5352e4ab24 Fix creazione conto 2023-12-05 10:48:07 +01:00
Pek5892 7ec7a26505 fix minore 2023-12-05 10:39:26 +01:00
Pek5892 d57ee7edaa fix minore 2023-12-05 10:33:53 +01:00
Pek5892 e752db93c0 Fix movimentazione articoli 2023-12-04 17:40:24 +01:00
Pek5892 8d7740b271 Fix minore 2023-12-04 15:04:15 +01:00
Pek5892 dc0b739c7e Fix minore 2023-12-04 12:31:55 +01:00
Pek5892 d0a8011ce6 Aggiunta gestione RappresentanteFiscale in XML 2023-12-04 11:59:42 +01:00
Pek5892 b1080c129b Fix minore 2023-12-01 17:34:36 +01:00
Pek5892 68ae1bd206 Formattazione codice 2023-12-01 17:21:47 +01:00
Pek5892 fc0d100d7b Fix avviso eliminazione righe 2023-12-01 17:21:34 +01:00
loviuz 341e85869c Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-12-01 17:14:56 +01:00
loviuz d0a6957f5a Cambio grafica messaggi di conferma salvataggio con toastr 2023-12-01 17:14:54 +01:00
Pek5892 6aa15f0da3 Modifica posizione avvisi in basso a destra 2023-12-01 13:28:39 +01:00
Pek5892 925f7da15f Fix avviso 2023-12-01 09:20:11 +01:00
Pek5892 72c4f0d0f8 Fix minore 2023-11-30 15:35:53 +01:00
Beppe 848c2bf22c Aggiunta gestione Automezzi 2023-11-30 12:57:03 +01:00
Beppe ce2da169ff Miglioria movimentazione articoli 2023-11-30 12:54:50 +01:00
Beppe dcfa03b2b9 Aggiunta una limitazione sulle quantità scaricabili nei documenti di vendita 2023-11-30 11:59:08 +01:00
Beppe e4ace9b192 Fix movimentazione sedi 2023-11-30 11:19:43 +01:00
Pek5892 818d0a6b02 Fix per mimetype su file con estensione mjs 2023-11-29 16:45:46 +01:00
Pek5892 5b4208d007 Risolto il problema di visualizzazione dei PDF negli allegati 2023-11-29 16:34:22 +01:00
Pek5892 de5ebf5eda Fix minori 2023-11-29 10:15:59 +01:00
Pek5892 2f5518303e fix minore 2023-11-28 17:17:08 +01:00
Pek5892 6f7563345e Spostati gli avvisi Toast in posizione top-center 2023-11-28 16:06:26 +01:00
Pek5892 7522a67263 Fix minore 2023-11-28 15:21:47 +01:00
Pek5892 88d400b132 Fix #1396 2023-11-28 15:09:01 +01:00
Pek5892 405c2f01e5 Fix #1393 2023-11-28 14:53:59 +01:00
Pek5892 4e67b8efb3 Fix minore 2023-11-28 14:45:19 +01:00
Luca f715c8a77b Update actions.php 2023-11-28 13:52:30 +01:00
Luca 02930cfe8a Permetto sempre la modifica delle note aggiuntive e/o della data di competenza della fattura di vendita 2023-11-28 13:45:04 +01:00
Pek5892 3613eb18dc Aggiunta generazione stato in import attività 2023-11-28 12:44:32 +01:00
Pek5892 c96d66cbf9 Fix file esempio import articoli 2023-11-28 11:05:56 +01:00
MatteoPistorello ed7ae630b9 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-11-27 17:12:50 +01:00
MatteoPistorello 678029eeea Fix select qta articoli 2023-11-27 17:12:45 +01:00
Pek5892 211a74f7f6 Fix marca da bollo automatica 2023-11-27 16:30:49 +01:00
MatteoPistorello 2bed6d7da2 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-11-27 15:49:06 +01:00
MatteoPistorello d8ef71b3f1 Fix stampa consuntivo 2023-11-27 15:49:01 +01:00
Pek5892 0c79ebb073 Fix minori 2023-11-27 11:18:54 +01:00
Pek5892 3eb359d25c Migliorie minori 2023-11-27 10:06:30 +01:00
Pek5892 b0ddbc5e7a Fix formattazione 2023-11-24 18:24:20 +01:00
Pek5892 618164dbbd Fix minore 2023-11-24 18:24:13 +01:00
Pek5892 2e7f11d2c5 Aggiunta tipo di pagamento e banca accredito e addebito in scadenza 2023-11-24 13:20:00 +01:00
Pek5892 d58052df2e Fix minore 2023-11-23 14:49:09 +01:00
MatteoPistorello 39035f459e Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-11-23 09:50:41 +01:00
MatteoPistorello d2a0d25ab5 Fix calcolo totale consuntivi 2023-11-23 09:50:38 +01:00
Luca eac54f9c98 Update functions.js 2023-11-17 18:07:05 +01:00
loviuz 3e0028db06 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-11-17 17:47:19 +01:00
loviuz 09f3407579 Fix velocità caricamento lista allegati 2023-11-17 17:47:17 +01:00
MatteoPistorello 41cdce5f1b Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-11-17 17:27:33 +01:00
MatteoPistorello 590104dabc Salvataggio row-edit e row-serial via ajax nei documenti 2023-11-17 17:27:31 +01:00
Pek5892 0d0f986f1d Formattazione codice 2023-11-17 17:08:32 +01:00
Pek5892 ee5a693652 aggiornamento data movimento alla modifica della data_competenza in fattura 2023-11-17 16:42:28 +01:00
Pek5892 31c5199be6 Fix password con carattere & 2023-11-17 16:41:52 +01:00
MatteoPistorello 6d924749e2 Fix import serial contratti 2023-11-17 15:14:48 +01:00
MatteoPistorello d2c666ce18 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-11-17 15:14:27 +01:00
MatteoPistorello d3c82137f4 Aggiunta creazione al volo referente in edit attività 2023-11-17 15:14:24 +01:00
Pek5892 2fcff3c80c Fix stampa scadenza 2023-11-17 10:15:02 +01:00
Pek5892 7572affced Fix stampa consuntivo ordine 2023-11-17 09:43:35 +01:00
Pek5892 d640e806eb Fix per aliquote duplicate in xml 2023-11-16 11:42:07 +01:00
Pek5892 e4a4b3a7c4 Fix import anagrafiche 2023-11-16 11:08:15 +01:00
Pek5892 3bf253587e Fix calcolo rivalsa 2023-11-15 15:53:13 +01:00
Pek5892 3808e0612d Fix calcolo ritenuta 2023-11-15 15:35:22 +01:00
loviuz 5409b5af7e Aggiunta requisiti hardware 2023-11-15 15:09:54 +01:00
Pek5892 02dc04e937 Ripristino background data odierna fullcalendar 2023-11-15 14:48:51 +01:00
Pek5892 6c93ce4ad1 Fix minori 2023-11-15 14:10:33 +01:00
Pek5892 b181d26af8 Aggiunta selezione sottocategoria in add impianto 2023-11-15 13:26:59 +01:00
Pek5892 ad5e8c174b Fix fatture di vendita per schermi a bassa risoluzione 2023-11-15 12:03:36 +01:00
Pek5892 1d0efdf6d3 Aggiunta stampa preventivo (solo totale imponibile) 2023-11-14 10:48:04 +01:00
MatteoPistorello c762f8fa55 Gestione seriali contratti 2023-11-13 15:38:27 +01:00
MatteoPistorello 6b9776e0a9 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-11-10 16:39:18 +01:00
MatteoPistorello 99213c1127 Associazione serial da riferimento documento in import FE 2023-11-10 16:38:48 +01:00
Pek5892 a2ef25ef13 Fix import impianti 2023-11-09 14:56:03 +01:00
Pek5892 f899c57ed2 Fix minore 2023-11-09 12:32:01 +01:00
Pek5892 c70de5ceb5 #1392 Ripristino funzionalità duplica ordine 2023-11-08 17:23:13 +01:00
Matteo 9236b8ec1f Aggiunta seconda ricerca coordinate anagrafica in bulk con google maps 2023-11-08 17:09:08 +01:00
Matteo c4b6c1fcb0 Aggiunta seconda ricerca coordinate anagrafica in bulk con google maps 2023-11-08 16:51:53 +01:00
Pek5892 195edf22b4 Fix rimozione referente in sede 2023-11-08 16:43:04 +01:00
Pek5892 d674dfb2aa Aggiunta calcolo provvigione in pianificazione fatturazione 2023-11-08 16:22:03 +01:00
Pek5892 b65ca03e52 Fix selezione impianti in pianificazione ciclica attività 2023-11-08 14:56:01 +01:00
Pek5892 2bd2b33509 Aggiunti i ddt alla lista documenti collegati in preventivi 2023-11-08 12:33:43 +01:00
Pek5892 053200de9d Aggiunta colonna sottocategoria in vista Impianti 2023-11-08 11:29:13 +01:00
Pek5892 652917b137 Formattazione codice 2023-11-08 11:08:47 +01:00
Pek5892 d92f1b980e Fix minore 2023-11-08 11:06:14 +01:00
Pek5892 dfcd04755e Aggiunte sottocategorie in impianti 2023-11-08 10:58:11 +01:00
Pek5892 5bfa7e71f4 Aggiunti import Attività e Impianti 2023-11-08 10:31:52 +01:00
MatteoPistorello 0ccfaa0fff Fix plugin Impianti 2023-11-07 16:30:49 +01:00
Pek5892 5ae664af99 Aggiunta carattere in validator.php 2023-11-06 12:45:36 +01:00
Pek5892 905a20051c Fix minore 2023-11-06 12:34:32 +01:00
Pek5892 22bfae0c0f Miglioria controllo su chiavi esterne 2023-11-03 15:38:11 +01:00
Pek5892 8fe7b769c8 Fix creazione anagrafica in importazione articoli 2023-11-03 14:46:17 +01:00
Pek5892 3dcb5b0c3a Aggiunta creazione anagrafica in import articoli 2023-11-03 11:55:27 +01:00
Pek5892 8061481ddf Fix minori 2023-11-02 17:11:07 +01:00
Pek5892 d68feee4c3 Utilizzo funzione sanitizeXML2 2023-11-02 16:44:55 +01:00
Pek5892 c3bbde2395 Aggiunta costi e margine in ordini cliente 2023-11-02 15:31:47 +01:00
Pek5892 ad1ea0f933 Fix selettori con la virgola 2023-10-30 15:38:33 +01:00
Pek5892 1c7fa5a5b5 Aggiunta info gestione task 2023-10-30 15:38:05 +01:00
Pek5892 cf65bf5bcc Fix aggiunta categoria impianto già esistente 2023-10-30 14:18:26 +01:00
Pek5892 2c4768438a Revert "Fix minore"
This reverts commit 7dc118b075.
2023-10-30 13:14:40 +01:00
MatteoPistorello dba329953f Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-10-30 13:12:26 +01:00
MatteoPistorello 2b0c5f886e Fix checks impianti parent 2023-10-30 13:12:24 +01:00
Pek5892 7dc118b075 Fix minore 2023-10-30 13:02:55 +01:00
Pek5892 072a240d4d fix minore 2023-10-30 09:23:34 +01:00
Pek5892 c400eb7614 Rinominato il widget Notifiche interne in Note interne 2023-10-30 09:22:18 +01:00
Pek5892 11b3fb7664 Aggiornamento CHANGELOG 2023-10-27 17:32:47 +02:00
MatteoPistorello 54f9c58c63 Merge 2023-10-27 17:18:28 +02:00
MatteoPistorello 352b97d71a Fix minore 2023-10-27 17:17:48 +02:00
Pek5892 51ee3c48db fix minore 2023-10-27 17:15:08 +02:00
Pek5892 e651812528 fix minore 2023-10-27 17:10:17 +02:00
MatteoPistorello 88c4651f8e Fix minori 2023-10-27 15:35:40 +02:00
MatteoPistorello 8669c5ef7c Fix minori 2023-10-27 15:23:06 +02:00
MatteoPistorello 2f7ddad013 Merge 2023-10-27 15:10:17 +02:00
MatteoPistorello 9b0e6947b0 Gestione checklist plugin Impianti 2023-10-27 15:09:49 +02:00
Pek5892 5ced7116bb Fix minore 2023-10-27 14:49:14 +02:00
Pek5892 04a8989ae8 fix grafico minore 2023-10-27 12:34:05 +02:00
Pek5892 63f00a80b5 Fix stampa liquidazione iva 2023-10-27 12:24:13 +02:00
Pek5892 6f83f01e47 Fix minore invio stampe 2023-10-27 11:07:12 +02:00
Pek5892 d5b232743b Formattazione codice 2023-10-27 10:35:05 +02:00
Pek5892 78d03c8260 fix minore 2023-10-27 10:33:29 +02:00
Pek5892 8dba03e2bb Aggiunta modulo Gestione task 2023-10-27 10:23:52 +02:00
Pek5892 543e39d6cc Aggiunte notifiche interne per anagrafiche 2023-10-25 10:23:48 +02:00
MatteoPistorello f2f1d5528c Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-10-25 09:20:24 +02:00
MatteoPistorello 85e8f861b0 Fix select sedi azienda 2023-10-25 09:20:19 +02:00
Pek5892 6cc4607892 #1387 Aggiunta variabile email in anagrafiche 2023-10-24 15:39:52 +02:00
Pek5892 ce924f434b Fix minore 2023-10-24 11:15:42 +02:00
Pek5892 53792e1acd Aggiunte impostazioni Crea contratto rinnovabile di default e Giorni di preavviso di default 2023-10-24 11:08:16 +02:00
Pek5892 328a41915c Fix minore 2023-10-24 10:48:10 +02:00
Pek5892 8a47d54026 Fix minore 2023-10-24 10:20:51 +02:00
Pek5892 369ffb9edb Aggiunta colonna Allegati in Interventi 2023-10-24 10:17:43 +02:00
Pek5892 2394855b57 Ottimizzazione installazione aggiornamenti 2023-10-24 09:30:22 +02:00
MatteoPistorello 6db962f068 Merge 2023-10-23 16:40:27 +02:00
MatteoPistorello 262e8016a7 Gestione verifica movimenti contabili 2023-10-23 16:39:27 +02:00
Luca ec971fec1f Controllo a db per impostazioni e username doppi 2023-10-23 14:36:52 +02:00
MatteoPistorello 4832ac44f4 Fix footer fatture 2023-10-23 14:33:51 +02:00
Pek5892 b1c2f56537 Fix minore 2023-10-19 15:37:19 +02:00
Pek5892 fda99fd92b Fix autofattura natura IVA N2 2023-10-19 09:23:16 +02:00
Pek5892 8ac662a6ff Fix query invio sollecito di pagamento da bulk per note di credito 2023-10-18 12:34:17 +02:00
Pek5892 f14b151c32 Fix invio scadenze per anagrafica da bulk 2023-10-18 12:00:34 +02:00
loviuz 9a29164d48 Miglioramento pulsanti mappa 2023-10-13 14:57:59 +02:00
Pek5892 af7e0b5e34 Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-10-13 11:51:21 +02:00
Pek5892 fb8e67ec10 Fix autofattura con aliquota N6 2023-10-13 11:51:20 +02:00
loviuz 4c66be78a4 Aggiunta gestione apertura mappe con applicazione dispositivo mobile 2023-10-13 10:41:31 +02:00
Pek5892 1f6ea9ef45 Aggiunta modulo Stati fatture 2023-10-12 16:27:20 +02:00
Pek5892 8754b1c750 esclusione fatture stornate da sollecito pagamento 2023-10-12 15:48:10 +02:00
Pek5892 20a15f2494 Aggiunta controllo integrità db su relazioni chiavi esterne 2023-10-11 18:14:48 +02:00
MatteoPistorello 3dd9d654bc Merge branch 'master' of https://github.com/devcode-it/openstamanager 2023-10-11 17:24:58 +02:00
MatteoPistorello 057120b338 Fix tooltip dashboard 2023-10-11 17:24:54 +02:00
Luca cb22d644ba Corretto codice destinatario per fe verso san marino 2023-10-10 09:27:31 +02:00
Pek5892 bcf1273903 Aggiunta gestione filtro =data su tabelle 2023-10-09 12:46:36 +02:00
Luca f6aa14fba8 Update gulpfile.js 2023-10-06 19:32:01 +02:00
992 changed files with 48557 additions and 26018 deletions

6
.gitignore vendored
View File

@ -91,8 +91,10 @@ REVISION
.php_cs.cache
manifest.json
checksum.json
database.json
database_5_7.json
mysql.json
mysql_5_7.json
mariadb_10_x.json
settings.json
/tests/_log/*
/tests/_temp/*

View File

@ -90,3 +90,7 @@ ServerSignature Off
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>
<IfModule mod_mime.c>
AddType text/javascript mjs
</IfModule>

View File

@ -4,6 +4,12 @@ Tutti i maggiori cambiamenti di questo progetto saranno documentati in questo fi
Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://keepachangelog.com/), e il progetto segue il [Semantic Versioning](http://semver.org/) per definire le versioni delle release.
- [2.5.1 (2024-04-24)](#251-2024-04-24)
- [2.5 (2024-03-28)](#25-2024-03-28)
- [2.4.54 (2024-02-02)](#2454-2024-02-02)
- [2.4.53 (2024-01-05)](#2453-2024-01-05)
- [2.4.52 (2023-12-08)](#2452-2023-12-08)
- [2.4.51 (2023-10-30)](#2451-2023-10-30)
- [2.4.50 (2023-10-06)](#2450-2023-10-06)
- [2.4.49 (2023-09-22)](#2449-2023-09-25)
- [2.4.48 (2023-08-01)](#2448-2023-08-01)
@ -61,6 +67,243 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k
- [2.2 (2016-11-10)](#22-2016-11-10)
- [2.1 (2015-04-02)](#21-2015-04-02)
## 2.5.1 (2024-04-24)
### Aggiunto (Added)
- Aggiunto user-agent nei log di accesso
- Aggiunta la visualizzazione delle checklist impianti in stampa Attività
- Aggiunta colonna Gruppi abilitati in **Categorie documenti**
### Modificato (Changed)
- Ottimizzato il codice per renderlo compatibile con php8.1
- Migliorata la procedura di aggiornamento
- Rinominato il plugin **Sedi** in **Sedi aggiuntive**
- Modificata la forzatura aggiornamento in ?force=1
### Fixed
- Corretto il salvataggio nome in **Viste**
- Ripristinata la verifica query in **Viste**
- Corretta la gestione degli allegati
- Corretta l'azione di gruppo per il download degli allegati
- Corretta la selezione anagrafiche clienti-fornitori
- Corrette le stampe contabili
- Corretti gli upload di moduli, plugins e template
- Corretta l'aggiunta attività
- Corretta la gestione degli automezzi per tecnico
- Corretto il caricamento dei promemoria da pianificare in dashboard
- Corretta l'emissione di fatture
## 2.5 (2024-03-28)
### Aggiunto (Added)
- Aggiunte le tabelle '_lang' per la gestione delle traduzioni dei dati presenti a database
- Aggiunta log rimozione sessioni per velocizzare la sincronizzazione dell'app
- Introduzione del file Known-issue.md
- Aggiunle le skin light per i temi
- Aggiunta colonna N. utenti abilitati e N. api abilitate nel modulo **Utenti e permessi**
- Aggiunto il riferimento alle attività collegate nei moduli **DDT**
- Aggiunto il blocco **Aggiorna informazioni di acquisto** in fase di importazione fattura elettronica
- Aggiunta creazione automatica della banca in fase di importazione CSV anagrafiche
- Aggiunta informazioni di creazione per campi delle viste
- Aggiunto il flag 'Fatture elettroniche' in segmenti
- Aggiunta la visualizzazione delle sessioni attive in **Stato dei servizi**
- Aggiunta la navigazione tra **Attività** con codice precedente e successivo
- Aggiunto un avviso nel caso di righe con quantità a 0 nelle **Fatture di vendita**
- Aggiunto un controllo sulla partita IVA per **Fatture** emesse verso anagrafiche cliente di tipo Azienda o codice fiscale se Ente pubblico
- Aggiunto controllo per validare il codice dell'intermediario in **Anagrafica**
- Aggiunta la validazione dell'indirizzo email in aggiunta **Utente**
- Aggiunta la controparte in plugin **Movimenti**
- Aggiunta la **stampa cespiti**
- Aggiunta la verifica di integrità database per MariaDB
- Aggiunta la possibilità di creare **Backup** escludendo la cartella files e il database
- Aggiunta la gestione dei campi personalizzati su applicazione
- Aggiunta la gestione della visualizzazione articoli distinta inline nei documenti
- Aggiunta impostazione Raggruppa attività per tipologia in fattura
- Introduzione connettori per il caricamento dei file
- Aggiunta gestione stato fattura Non valida
- Aggiunta gestione pagamento in **Attività**
### Modificato (Changed)
- Abilitato il ritorno al punto precedente anche per i dispositivi mobili
- Aggiornata la chiave di licenza per Wacom v2
- Migliorato graficamente il riquadro **Plugin**
- Migliorata la **Stampa fatturato** escludendo le autofatture
- Migliorato il plugin **Regole pagamenti**
- Migliorata l'impostazione della ricevuta della fattura elettronica nel caso di ricevuta di scarto per fattura duplicata
- Migliorato l'avviso della scadenza per l'invio della fattura elettronica nel caso in cui corrisponda a giorni non lavorativi
- Migliorata l'eliminazione degli utente con un controllo sui logs associati
- Rimosso il modulo **Voci di servizio**
- Corretta la firma con tavoletta grafica
- Migliorata la gestione dei seriali su documenti bloccati
- Spostato il panel Dettagli cliente in fase di aggiunta intervento
### Fixed
- Corretto errore notifica di lettura email mancante
- Corretto il flag per la fatturazione negli stati attività
- Corretta l'importazione delle **Fatture di acquisto** con rivalsa non specificata nelle righe
- Corretta la creazione del file config
- Corretta la creazione della banca in fase di importazione fatture di acquisto
- Corretta la lettura dei valori dai campi personalizzati
- Corretto l'avviso di ckeditor
- Corretto l'arrotondamento dei movimenti contabili che creavano incongruenze nel piano dei conti
- Corretta la generazione delle scadenze
- Corretta la valorizzazione del campo RegimeFiscale in generazione XML fattura
- Corretta la gestione dell'IVA indetraibile
- Corretta l'aggiunta di un conto in **Partitario**
- Corretta l'aggiunta attività per utenti senza permessi specifici
- Corretta la stampa **Carico automezzi**
- Corretta la ricerca nel **Piano dei conti**
- Corretta l'impostazione del segmento predefinito per tipo di documento limitandola ai sezionali
- Corretto l'avviso del codice anagrafica già presente
- Corretta la duplicazione dell'**Attività** dalla scheda attività
- Corretto l'allineamento degli orari delle sessioni in line in **Attività**
- Corrette le api dell'app
- Corretta la gestione dei caratteri accentati sul file di esportazione delle ricevute bancarie
- Corretta la ricerca articoli escludendo gli articoli eliminati
- Corretta la visualizzazione della password in impostazione
- Corretto l'ordinamento dei promemoria in **Dashboard**
- Corretta la versione di pdfjs viewer
- Corretta la larghezza automatica delle colonne nelle tabelle
## 2.4.54 (2024-02-02)
### Aggiunto (Added)
- Aggiunto un controllo sulle impostazioni presenti a gestionale
- Aggiunta la possibilità di impostare un tema diverso per ogni gruppo di utenti
- Aggiunta la gestione della fatturazione da azione di gruppo raggruppata per sede
- Aggiunto il metodo getValue per la lettura dei valori dei campi personalizzati
- Aggiunta variabile random per evitare la cache del browser in fase di link pdf o anteprima di stampa
- Aggiunta sede di partenza merce in stampa ddt
- Aggiunta la gestione del login tramite Microsoft
- Aggiunta impostazione per timeout tavoletta grafica
### Modificato (Changed)
- Migliorato il form di login AdminLTE
- Migliorato l'esempio di importazione Attività
- Migliorata la pianificazione dei promemoria
- Corretta la visualizzazione dei referenti in fase di aggiunta nuova sede
- Corretta la stampa di ordini con immagini
- Corretta la modifica inline dell'orario della sessione dei tecnici
- Corretti i campi richiesta e descrizione in fase di aggiunta attività
- Corretta l'aggiunta delle scadenze
- Corretta la selezione del fornitore predefinito in articoli
- Corrette le API delle checklist per gli impianti
- Corrette le api per login da app
- Corretta la firma da dispositivo mobile
- Corretta la pianificazione degli interventi
- Corretto l'avviso di sessioni tecnici senza ore in attività
- Corretta l'aggiunta dei seriali
- Corretta la gestione de campi personalizzati
## 2.4.53 (2024-01-05)
### Aggiunto (Added)
- Aggiunta sezione **dettagli aggiuntivi** nel plugin sedi per compilare i dettagli dell'automezzo (nome, descrizione, targa)
- Aggiunta impostazione per definire il **listino cliente** predefinito in fase di aggiunta anagrafica cliente
- Aggiunta azione di gruppo in **Anagrafiche** e **Articoli** per impostare il listino cliente massivamente ad Anagrafiche e Articoli
- Aggiunto import listini cliente
- Aggiunta icona nel campo input prezzo e sconto nelle righe dei documenti per segnalare incongruenza tra prezzo di listino e prezzo inserito
- Aggiunta impostazione per scegliere di non importare i seriali in fase di importazione delle fatture elettroniche
- Aggiunta colonna email in vista **Anagrafiche**
- Aggiunto mod_mime ai requisiti server
- Aggiunta la ricerca articolo per barcode in fase di importazione fattura elettronica
- Aggiunta impostazione per raggruppare i riferimenti riga in fase di stampa
### Modificato (Changed)
- Migliorata la visualizzazione del plugin movimenti in **Anagrafiche**
- Migliorata la stampa **Automezzi** per automezzi senza magazzino registrato
- Modificato il valore di decimali per le quantità in stampa di default a 2
- Migliorate le ricerche indirizzo in italiano
### Fixed
- Corretto filtro articoli negli **Automezzi** per visualizzare correttamente la giacenza della sede centrale
- Corretta selezione automatica iva all'aggiunta degli articoli nei documenti di vendita. Il sistema da priorità all'iva del fornitore se presente, altrimenti passa all'iva dell'articolo se presente, altrimenti assegna l'iva di default definita in impostazioni.
- Corretta la vista riferimenti negli **Ordini cliente** aggiungendo il numero esterno del DDT al posto dell'id come veniva erroneamente visualizzato prima
- Corretta l'applicazione della rivalsa sulla marca da bollo
- Corretto l'automatismo che aggiorna la quantità degli articoli nelle righe quando sono servizi
- Corretto il controllo che verifica la presenza della cartella backup/
- Corretta l'IVA di acquisto degli articoli
- Corretti gli arrotondamenti in fase di importazione fattura elettronica
- Corretti i seriali in fase di importazione fattura elettronica
- Corretta la ricerca coordinate con google maps
## 2.4.52 (2023-12-08)
### Aggiunto (Added)
- Aggiunta la gestione delle sedi definite come automezzi con pratico modulo per il carico/scarico degli articoli nell'automezzo, l'assegnazione di tecnici/autisti con date di validità e stampe di carico filtrabili
- Aggiunta una limitazione sulle quantità scaricabili nei documenti di vendita in modo da non poter vendere più articoli di quelli presenti fisicamente nel magazzino selezionato. Questa limitazione è legata all'impostazione **Permetti selezione articoli con quantità minore o uguale a zero in Documenti di Vendita**
- Aggiunti costi e margine negli ordini cliente
- Aggiunta la possibilità di importare tramite CSV Impianti e Attività
- Aggiunte le sottocategorie in Impianti
- Aggiunti i DDT alla lista dei documenti collegati nel modulo Preventivi
- Aggiunto il calcolo della provvigione in pianificazione fatturazione
- Aggiunta una seconda ricerca delle coordinate anagrafica da azione di gruppo con Google Maps
- Aggiunta la gestione dei seriali da riferimento documento in fase di importazione di una fattura elettronica
- Aggiunta la gestione dei seriali nei contratti
- Aggiunta la stampa preventivo (solo totale imponibile)
- Aggiunta la selezione delle sottocategorie in fase di aggiunta impianto
- Aggiunta la creazione al volo dei referenti in attività
- Aggiunto colore in base allo stato in modifica stato da azioni di gruppo in Preventivi, Contratti e Ordini
- Aggiunta la gestione del rappresentante fiscale negli XML
- Aggiunte le impostazioni per definire il numero di decimali per gli importi, per le quantità e per i totali nelle stampe
- Aggiunta la variabile Nome preventivo nei Preventivi
- Aggiunto il tipo di pagamento e banca di accredito e addebito nelle scadenze
### Modificato (Changed)
- Migliorata l'importazione degli articoli tramite CSV, le anagrafiche relative a clienti e fornitori vengono ora create se non presenti a gestionale
- Migliorato il controllo sulle chiavi esterne nel controllo del database
- Ripristinata la funzionalità di duplicazione degli ordini
- La modifica della data competenza di una fattura aggiorna ora la data del movimento relativo
- Migliorato il caricamento della lista allegati
- L'aggiunta di note aggiuntive e la modifica della data competenza è ora sempre possibile nelle fatture
- Spostati tutti gli avvisi in basso a destra
- Modificate le funzioni nei file modutil.php per permettere l'aggiunta di file custom
### Fixed
- Corretto il problema di visualizzazione dei PDF negli allegati
- Corretto un problema di movimentazione magazzino: gli articoli nelle attività venivano sempre movimentati da sede legale anche se specificata diversa sede di partenza nel documento (solo da popup di modifica articolo)
- Corretta la selezione degli impianti in pianificazione ciclica delle attività
- Corretta la rimozione del referente nelle sedi
- Corretta la visualizzazione del modulo fatture di vendita per schermi a bassa risoluzione
- Corretti i calcoli della ritenuta e rivalsa in fattura
- Corretta l'importazione delle anagrafiche da CSV
- Corretta l'importazione di fatture elettroniche con aliquote IVA multiple
- Corretta la stampa del consuntivo ordine, della scadenza e del consuntivo
- Corretta la validazione di password contenenti il carattere '&'
- Corretto il calcolo del totale nei consuntivi
- Corretta l'applicazione della marca da bollo in fattura
- Corretta la visualizzazione della quantità articoli in fase di selezione
- Corretta la visualizzazione delle righe nei documenti in presenza di articoli con quantità 0
- Corretta la movimentazione degli articoli
- Corretta la creazione del conto del piano dei conti per le anagrafiche
- Corretto il funzionamento dei campi personalizzati
- Corretta la vista Fatture di vendita per l'icona email
- Corretta la crezione di attività da documenti, viene ora mantenuto il collegamento
## 2.4.51 (2023-10-30)
### Aggiunto (Added)
- Aggiunta la gestione checklist nel plugin impianti
- Aggiunto il modulo **Gestione task**
- Aggiunte Note interne per anagrafiche
- Aggiunta la variabile email nei template delle anagrafiche
- Aggiunta impostazioni **Crea contratto rinnovabile di default** e **Giorni di preavviso di default**
- Aggiunta colonna Allegati in Attività
- Aggiunta la gestione di verifica dei movimenti contabili
- Aggiunta gestione apertura mappe con applicazione dispositivo mobile
- Aggiunto il modulo **Stati fatture**
- Aggiunto il controllo di integrità del database su relazioni chiavi esterne
- Aggiunta gestione filtro =data su tabelle
### Modificato (Changed)
- Miglioria pulsanti mappa
- Rinominato il widget Notifiche interne in Note interne
### Fixed
- Corretta la stampa liquidazione iva per aliquote con natura iva non specificata
- Corretta la selezione delle sedi azienda
- Corretto il footer delle fatture
- Corretta la generazione di autofatture per righe con natura iva N2 e N6
- Corretta la query Invio sollecito di pagamento da azioni di gruppo per escludere le note di credito
- Corretto l'invio scadenze per anagrafica da azioni di gruppo
- Corretti i tooltip in dashboard
## 2.4.50 (2023-10-06)
### Aggiunto (Added)

35
KNOWN-ISSUES.md Normal file
View File

@ -0,0 +1,35 @@
In questo file verranno riassunte le problematiche del gestionale che sono già note alla community.
Le problematiche saranno raggruppate per release e le relative correzioni (se applicabili) saranno riportate sotto la sezione **Soluzione**.
#### 2.4.54 - 03/02/2024
##### Problemi noti
- In fase di installazione non viene compilato il file config se assente
##### Soluzione
Modificare il file index.php sostituendo il blocco di codice che inizia alla riga 30 con
```php
if ($dbo->isConnected()) {
try {
$microsoft = $dbo->selectOne('zz_oauth2', '*', ['nome' => 'Microsoft', 'enabled' => 1, 'is_login' => 1]);
} catch (QueryException $e) {
}
}
```
oppure aggiornare alla **v.2.5** di OpenSTAManager.
#### 2.4.35 - 12/08/2022
##### Problemi noti
- Colonna **id_module_start** mancante per tabella **zz_groups**
- Icona non aggiornata per il modulo **Causali movimenti**
##### Soluzione
Eseguire a database le seguenti query di allineamento:
```bash
UPDATE `zz_modules` SET `icon` = 'fa fa-exchange' WHERE `title` = 'Causali movimenti';
ALTER TABLE `zz_groups` ADD `id_module_start` INT NULL AFTER `editable`;
```
oppure aggiornare alla **v.2.5** di OpenSTAManager.

View File

@ -21,7 +21,6 @@
[![Downloads](https://img.shields.io/github/downloads/devcode-it/openstamanager/total.svg)](https://github.com/devcode-it/openstamanager/releases)
[![SourceForge](https://img.shields.io/sourceforge/dt/openstamanager.svg?label=SourceForge)](https://sourceforge.net/projects/openstamanager/)
[![license](https://img.shields.io/github/license/devcode-it/openstamanager.svg)](https://github.com/devcode-it/openstamanager/blob/master/LICENSE)
[![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
Il gestionale OpenSTAManager è un software open-source e web based, sviluppato dall'azienda informatica [DevCode](https://www.devcode.it/) di Este per gestire ed archiviare il servizio di assistenza tecnica e la relativa fatturazione.
Il nome del progetto deriva dalla parziale traduzione in inglese degli elementi principali che lo compongono: la natura open-source e il suo obiettivo quale Gestore del Servizio Tecnico di Assistenza.
@ -53,7 +52,7 @@ La documentazione ufficiale è disponibile all'indirizzo <https://docs.openstama
<!-- /TOC -->
## Requisiti
## Requisiti software
L'installazione del gestionale richiede la presenza di un server web con abilitato il [DBMS MySQL](https://www.mysql.com) e il linguaggio di programmazione [PHP](https://php.net).
@ -63,18 +62,22 @@ L'installazione del gestionale richiede la presenza di un server web con abilita
| PHP | EOL | Supportato |
|-----|-----|:----------:|
| 8.1 | 25/11/2024 | ❌ |
| 8.0 | 26/11/2023 | ✔️ |
| 7.4 | 28/11/2022 | ✔️ |
| 7.3 | 06/12/2021 | ✔️ |
| 7.2 | 30/11/2020 | ❌ |
| 8.3 | 23/11/2026 | ✔️ |
| 8.2 | 08/12/2025 | ✔️ |
| 8.1 | 25/11/2024 | ✔️ |
| 8.0 | 26/11/2023 | ❗ |
| 7.4 | 28/11/2022 | ❗ |
| 7.3 | 06/12/2021 | ❌ |
</td>
<td valign="top">
| MYSQL | EOL | Supportato |
|-----|-----|:----------:|
| 8.0 | 01/04/2026 | ✔️ |
| 8.3 | 30/04/2024 | ✔️ |
| 8.2 | 31/01/2024 | ✔️ |
| 8.1 | 25/10/2023 | ✔️ |
| 8.0 | 30/04/2026 | ✔️ |
| 5.7 | 21/10/2023 | ✔️ |
| 5.6 | 05/02/2021 | ❌ |
@ -83,8 +86,26 @@ L'installazione del gestionale richiede la presenza di un server web con abilita
</tr>
</table>
❗Alcune dipendenze presenti dalla versione 2.5 non sono più compatibili con PHP 7.4 e PHP 8.0. Per continuare a utilizzare tali versioni di PHP, sarà necessario ricompilare utilizzando il file composer_74.json.
Per semplificarne l'installazione, la versione 2.5.2 sarà disponibile in un doppio zip con entrambe le versioni (compatibile con php < 8.1 e compatibile con php >= 8.1).
Dalla versione 2.5.3 sarà richiesta una versione di php >= 8.1, non sarà quindi disponibile al download il secondo file zip.
Per ulteriori informazioni sui pacchetti che forniscono questi elementi di default, visitare la sezione [Installazione](https://docs.openstamanager.com/configurazione/installazione) della documentazione.
### Requisiti hardware
Minimi:
- 1 CPU
- 2GB di ram
- 200MB di spazio per il gestionale
Consigliati:
- 2 CPU
- 4GB di ram
- 2GB di spazio per il gestionale
## Installazione rapida
```bash
git clone https://github.com/devcode-it/openstamanager.git
@ -158,7 +179,7 @@ In questo modo è possibile ottenere un'ulteriore garanzia sul funzionamento del
La community è una componente importante in un progetto open-source, perché mette in contatto utenti e programmatori tra di loro e permette pertanto l'individuazione di soluzioni innovative e migliori.
Siamo presenti su [Facebook](https://www.facebook.com/openstamanager), [Twitter](https://twitter.com/openstamanager/), [YouTube](https://www.youtube.com/channel/UCoToaK4dhDXmcQXi1AnqQ4Q) e [Mastodon](https://mastodon.uno/@openstamanager) e il nostro forum ufficiale è disponibile all'indirizzo <https://forum.openstamanager.com>, dove potete segnalare i vostri problemi e soddisfare le vostre curiosità nelle sezioni più adeguate.
Siamo presenti su [Facebook](https://www.facebook.com/openstamanager), [Instagram](https://www.instagram.com/openstamanager/), [Twitter](https://twitter.com/openstamanager/), [YouTube](https://www.youtube.com/@openstamanager2900), [Telegram](https://t.me/openstamanager_official) e [Mastodon](https://mastodon.uno/@openstamanager) e il nostro forum ufficiale è disponibile all'indirizzo <https://forum.openstamanager.com>, dove potete segnalare i vostri problemi e soddisfare le vostre curiosità nelle sezioni più adeguate.
## Contribuire

View File

@ -19,6 +19,7 @@
include_once __DIR__.'/core.php';
use Models\Module;
use Models\Note;
use Models\OperationLog;
use Models\Upload;
@ -41,20 +42,13 @@ if (filter('op') == 'aggiungi-allegato' || filter('op') == 'rimuovi-allegato') {
// Controllo sui permessi di scrittura per il modulo
if (Modules::getPermission($id_module) != 'rw') {
flash()->error(tr('Non hai permessi di scrittura per il modulo _MODULE_', [
'_MODULE_' => '"'.Modules::get($id_module)['name'].'"',
]));
}
// Controllo sui permessi di scrittura per il file system
elseif (!directory($upload_dir)) {
flash()->error(tr('Non hai i permessi di scrittura nella cartella _DIR_!', [
'_DIR_' => '"files"',
'_MODULE_' => '"'.Module::find($id_module)->getTranslation('title').'"',
]));
}
// Gestione delle operazioni
else {
//UPLOAD PER CKEDITOR
// UPLOAD PER CKEDITOR
if (filter('op') == 'aggiungi-allegato' && !empty($_FILES) && !empty($_FILES['upload']['name'])) {
$CKEditor = get('CKEditor');
$funcNum = get('CKEditorFuncNum');
@ -63,8 +57,8 @@ if (filter('op') == 'aggiungi-allegato' || filter('op') == 'rimuovi-allegato') {
'png', 'jpg', 'jpeg',
];
//Maximum file limit (unit: byte)
$max_size = '2097152'; //2MB
// Maximum file limit (unit: byte)
$max_size = '2097152'; // 2MB
// Get image file extension
$file_extension = pathinfo($_FILES['upload']['name'], PATHINFO_EXTENSION);
@ -73,7 +67,7 @@ if (filter('op') == 'aggiungi-allegato' || filter('op') == 'rimuovi-allegato') {
$upload = Uploads::upload($_FILES['upload'], [
'name' => filter('nome_allegato'),
'category' => filter('categoria'),
'id_module' => Modules::get('Gestione documentale')['id'],
'id_module' => (new Module())->getByField('title', 'Gestione documentale', Models\Locale::getPredefined()->id),
'id_record' => $id_record,
]);
@ -86,7 +80,7 @@ if (filter('op') == 'aggiungi-allegato' || filter('op') == 'rimuovi-allegato') {
// Creazione file fisico
if (!empty($upload)) {
//flash()->info(tr('File caricato correttamente!'));
// flash()->info(tr('File caricato correttamente!'));
$id_allegato = $dbo->lastInsertedID();
$upload = Upload::find($id_allegato);
@ -113,15 +107,15 @@ if (filter('op') == 'aggiungi-allegato' || filter('op') == 'rimuovi-allegato') {
echo json_encode($response);
}
} else {
//flash()->error(tr('Errore durante il caricamento del file!'));
// flash()->error(tr('Errore durante il caricamento del file!'));
echo '<script type="text/javascript"> window.parent.toastr.error("'.tr('Errore durante il caricamento del file!').'"); </script>';
}
} else {
//flash()->error(tr('Estensione non permessa!'));
// flash()->error(tr('Estensione non permessa!'));
echo '<script type="text/javascript"> window.parent.toastr.error("'.tr('Estensione non permessa').'"); </script>';
}
exit();
exit;
}
// UPLOAD
@ -167,7 +161,17 @@ if (filter('op') == 'aggiungi-allegato' || filter('op') == 'rimuovi-allegato') {
elseif (filter('op') == 'download-allegato') {
$rs = $dbo->fetchArray('SELECT * FROM zz_files WHERE id_module='.prepare($id_module).' AND id='.prepare(filter('id')).' AND filename='.prepare(filter('filename')));
download($upload_dir.'/'.$rs[0]['filename'], $rs[0]['original']);
// download($upload_dir.'/'.$rs[0]['filename'], $rs[0]['original']);
$file = Upload::find($rs[0]['id']);
if (!empty($file)) {
$content = $file->get_contents();
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: Binary');
header('Content-disposition: attachment; filename="'.basename($file->original_name).'"');
echo $content;
}
} elseif (filter('op') == 'visualizza-modifica-allegato') {
include_once base_dir().'/include/modifica_allegato.php';
}
@ -193,10 +197,10 @@ elseif (filter('op') == 'download-zip-allegati') {
$src = basename($allegato->filepath);
$dst = basename($allegato->original_name);
$file = slashes($module->upload_directory.'/'.$src);
$dest = slashes($dir.'tmp/'.$dst);
$file_content = $allegato->get_contents();
$result = copy($file, $dest);
$dest = slashes($dir.'tmp/'.$dst);
file_put_contents($dest, $file_content);
}
// Creazione zip
@ -359,7 +363,7 @@ elseif (filter('op') == 'ordina-checks') {
elseif (post('op') == 'send-email') {
$template = Template::find(post('template'));
$mail = \Modules\Emails\Mail::build($user, $template, $id_record);
$mail = Modules\Emails\Mail::build($user, $template, $id_record);
// Rimozione allegati predefiniti
$mail->resetPrints();
@ -410,12 +414,12 @@ elseif (post('op') == 'send-email') {
$visible = filter('visible');
$id_riga = filter('id_vista');
$dbo->query('UPDATE `zz_views` SET `visible` = '.prepare($visible).' WHERE id = '.prepare($id_riga));
$dbo->query('UPDATE `zz_views` SET `visible` = '.prepare($visible).' WHERE `id` = '.prepare($id_riga));
} elseif (filter('op') == 'ordina_colonne') {
$order = explode(',', post('order', true));
foreach ($order as $i => $id_riga) {
$dbo->query('UPDATE `zz_views` SET `order` = '.prepare($i).' WHERE id='.prepare($id_riga));
$dbo->query('UPDATE `zz_views` SET `order` = '.prepare($i).' WHERE `id`='.prepare($id_riga));
}
} elseif (filter('op') == 'visualizza_righe_riferimenti') {
include_once base_dir().'/include/riferimenti/riferimenti.php';
@ -485,22 +489,24 @@ if ($structure->permission == 'rw') {
($include_file = $structure->filepath('actions.php')) ? include $include_file : null;
// Operazioni generiche per i campi personalizzati
if (post('op') != null) {
if (!empty(post('op'))) {
$custom_where = !empty($id_plugin) ? '`id_plugin` = '.prepare($id_plugin) : '`id_module` = '.prepare($id_module);
$query = 'SELECT `id`, `html_name` AS `name` FROM `zz_fields` WHERE '.$custom_where;
$query = 'SELECT `id`, `html_name` AS `title` FROM `zz_fields` WHERE '.$custom_where;
$customs = $dbo->fetchArray($query);
if (!string_starts_with(post('op'), 'delete')) {
if (post('op') != 'delete') {
$values = [];
foreach ($customs as $custom) {
if (post($custom['name']) !== null) {
$values[$custom['id']] = post($custom['name']);
} else {
$values[$custom['id']] = '';
}
}
// Inserimento iniziale
if (string_starts_with(post('op'), 'add')) {
if (post('op') == 'add') {
// Informazioni di log
Filter::set('get', 'id_record', $id_record);
@ -514,12 +520,13 @@ if ($structure->permission == 'rw') {
}
// Aggiornamento
elseif (string_starts_with(post('op'), 'update')) {
if (post('op') == 'update') {
$query = 'SELECT `zz_field_record`.`id_field` FROM `zz_field_record` JOIN `zz_fields` ON `zz_fields`.`id` = `zz_field_record`.`id_field` WHERE id_record = '.prepare($id_record).' AND '.$custom_where;
$customs_present = $dbo->fetchArray($query);
$customs_present = array_column($customs_present, 'id_field');
foreach ($values as $key => $value) {
$value = (!is_array($value) ? $value : json_encode($value));
if (in_array($key, $customs_present)) {
$dbo->update('zz_field_record', [
'value' => $value,

14
add.php
View File

@ -40,20 +40,20 @@ echo '
// Campi personalizzati
echo '
<div class="hide" id="custom_fields_top-add">
<div class="hide" id="custom_fields_top-add_'.$id_module.'-'.$id_plugin.'">
<input type="hidden" name="id_module" value="'.$id_module.'">
<input type="hidden" name="id_plugin" value="'.$id_plugin.'">
{( "name": "custom_fields", "id_module": "'.$id_module.'", "id_plugin": "'.$id_plugin.'", "position": "top", "place": "add" )}
</div>
<div class="hide" id="custom_fields_bottom-add">
<div class="hide" id="custom_fields_bottom-add_'.$id_module.'-'.$id_plugin.'">
{( "name": "custom_fields", "id_module": "'.$id_module.'", "id_plugin": "'.$id_plugin.'", "position": "bottom", "place": "add" )}
</div>
<script>
$(document).ready(function(){
let form = $("#custom_fields_top-add").parent().find("form").first();
let form = $("#custom_fields_top-add_'.$id_module.'-'.$id_plugin.'").parent().find("form").first();
// Ultima sezione/campo del form
let last = form.find(".panel").last();
@ -62,15 +62,19 @@ $(document).ready(function(){
last = form.find(".box").last();
}
if (!last.length) {
last = form.find(".card").last();
}
if (!last.length) {
last = form.find(".row").eq(-2);
}
// Campi a inizio form
aggiungiContenuto(form, "#custom_fields_top-add", {}, true);
aggiungiContenuto(form, "#custom_fields_top-add_'.$id_module.'-'.$id_plugin.'", {}, true);
// Campi a fine form
aggiungiContenuto(last, "#custom_fields_bottom-add", {});
aggiungiContenuto(last, "#custom_fields_bottom-add_'.$id_module.'-'.$id_plugin.'", {});
});
</script>';

View File

@ -52,7 +52,7 @@ switch (filter('op')) {
break;
// Imposta un valore ad una sessione
// Imposta un valore ad una sessione
case 'session_set':
$array = explode(',', get('session'));
$value = get('value', true);
@ -78,12 +78,12 @@ switch (filter('op')) {
case 'active_users':
$posizione = get('id_module');
if (isset($id_record)) {
if (!empty($id_record)) {
$posizione .= ', '.get('id_record');
}
$user = Auth::user();
$interval = setting('Timeout notifica di presenza (minuti)') * 60 * 2;
$interval = setting('Timeout notifica di presenza (minuti)') * 60;
$dbo->query('UPDATE zz_semaphores SET updated = NOW() WHERE id_utente = :user_id AND posizione = :position', [
':user_id' => $user['id'],
@ -112,7 +112,7 @@ switch (filter('op')) {
if ($hook->permission != '-') {
$results[] = [
'id' => $hook->id,
'name' => $hook->name,
'name' => $hook->getTranslation('title'),
];
}
}
@ -167,5 +167,15 @@ switch (filter('op')) {
echo json_encode($results);
break;
case 'avg-results':
$ids = post('ids') ?: [];
$results = Util\Query::getAverages($structure, [
'id' => $ids,
]);
echo json_encode($results);
break;
}

View File

@ -31,7 +31,7 @@ if (!empty(filter('order'))) {
}
array_shift($columns);
$total = Util\Query::readQuery($structure);
$total = Query::readQuery($structure);
// Ricerca
$search = [];
@ -52,6 +52,7 @@ $results = [
'recordsTotal' => 0,
'recordsFiltered' => 0,
'summable' => [],
'avg' => [],
'draw' => $draw_numer,
];
@ -74,7 +75,10 @@ if (!empty($query)) {
$results['recordsFiltered'] = $data['count'];
// SOMME
$results['summable'] = Util\Query::getSums($structure, $search);
$results['summable'] = Query::getSums($structure, $search);
// MEDIE
$results['avg'] = Query::getAverages($structure, $search);
// Allineamento delle righe
$align = [];
@ -113,7 +117,11 @@ if (!empty($query)) {
$column = [];
if (!empty($r['_bg_'])) {
$column['data-background'] = $r['_bg_'];
if (preg_match('/-light$/', $r['_bg_'])) {
$column['data-background'] = substr($r['_bg_'], 0, -6); // Remove the "-light" suffix from the word
} else {
$column['data-background'] = $r['_bg_'];
}
}
// Allineamento
@ -160,7 +168,7 @@ if (!empty($query)) {
// Icona
elseif (preg_match('/^icon_(.+?)$/', trim($field), $m)) {
$value = '<span class=\'label text-black\' style=\'font-weight:normal;\' ><i class="'.$r[$field].'" title="'.$r['icon_title_'.$m[1]].'" ></i> <span>'.$r['icon_title_'.$m[1]].'</span></span>';
$value = '<span class=\'badge text-black\' style=\'font-weight:normal;\' ><i class="'.$r[$field].'" title="'.$r['icon_title_'.$m[1]].'" ></i> <span>'.$r['icon_title_'.$m[1]].'</span></span>';
}
// Colore del testo

View File

@ -43,7 +43,7 @@ try {
} catch (Exception $e) {
// Log dell'errore
$logger = logger();
$logger->addRecord(\Monolog\Logger::ERROR, $e);
$logger->addRecord(Monolog\Logger::ERROR, $e);
$response = Response::error('serverError');
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -18,12 +18,7 @@
// Aggiunta dell'ingranaggio all'unload della pagina
$(window).on("beforeunload", function () {
$("#main_loading").show();
});
// Rimozione dell'ingranaggio al caricamento completo della pagina
$(window).on("load", function () {
$("#main_loading").fadeOut();
$("#main_loading").css('height', '100vh').find('img').show().removeClass('animation__shake').addClass('animation__shake');
});
// Fix multi-modal
@ -39,7 +34,7 @@ $(document).ready(function () {
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-right",
"positionClass": "toast-bottom-right",
//"preventDuplicates": true,
"onclick": null,
"showDuration": "300",
@ -117,6 +112,14 @@ $(document).on('select2:open', () => {
//Send a WhatsApp message using JavaScript
function sendWhatsAppMessage(phoneNumber, message) {
// Rimuove eventuali spazi bianchi dal numero di telefono
phoneNumber = phoneNumber.replace(/\s/g, '');
// Rimuove il simbolo "+" all'inizio del numero, se presente
if (phoneNumber.startsWith('+')) {
phoneNumber = phoneNumber.slice(1);
}
var text = message ? "&text=" + encodeURIComponent(message) : "";
var url = "https://api.whatsapp.com/send?phone=" + phoneNumber + text;
window.open(url);

View File

@ -35,7 +35,8 @@ $(document).ready(function () {
});
// Nel caso la navigazione sia da mobile, disabilito il ritorno al punto precedente
if (!globals.is_mobile) {
// 2024-01-30 disabilito controllo in quanto non è chiaro il proposito
//if (!globals.is_mobile) {
// Salvo lo scroll per riportare qui l'utente al reload
$(window).on('scroll', function () {
if (sessionStorage != undefined) {
@ -49,7 +50,7 @@ $(document).ready(function () {
scrollToOffset(sessionStorage['scrollTop_' + globals.id_module + '_' + globals.id_record]);
}, 1);
}
}
//}
$('.nav-tabs a').click(function (e) {
$(this).tab('show');
@ -61,7 +62,7 @@ $(document).ready(function () {
});
// Fix per la visualizzazione di Datatables all'interno dei tab Bootstrap
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
$('a[data-widget="tab"]').on('shown.bs.tab', function (e) {
$($.fn.dataTable.tables(true)).DataTable().columns.adjust();
$($.fn.dataTable.tables(true)).DataTable().scroller.measure();
});

View File

@ -17,31 +17,9 @@
*/
$(document).ready(function () {
// Fix per il menu principale
$('.sidebar-menu').tree({
followLink: true,
});
$('.sidebar-menu > li.treeview i.fa-angle-left').click(function (e) {
e.preventDefault();
$(this).find('ul').stop().slideDown();
});
$('.sidebar-menu > li.treeview i.fa-angle-down').click(function (e) {
e.preventDefault();
$(this).find('ul').stop().slideUp();
});
const elenco_menu = $('.treeview-menu > li.active');
for (i = 0; i < elenco_menu.length; i++) {
const elemento = $(elenco_menu[i]);
elemento.parent().show().parent().addClass('active');
elemento.parent().parent().find('i.fa-angle-left').removeClass('fa-angle-left').addClass('fa-angle-down');
}
// Menu ordinabile
if (!globals.is_mobile) {
const menu = sortable(".sidebar-menu", {
const menu = sortable(".nav-sidebar", {
axis: "y",
cursor: "move",
dropOnEmpty: true,
@ -50,7 +28,7 @@ $(document).ready(function () {
if (menu) {
menu.addEventListener("sortupdate", function (e) {
let order = $(".sidebar-menu > .treeview[data-id]").toArray().map(a => $(a).data("id"))
let order = $(".nav-sidebar > .nav-item[data-id]").toArray().map(a => $(a).data("id"))
$.post(globals.rootdir + "/actions.php", {
id_module: globals.order_manager_id,
@ -80,7 +58,7 @@ $(document).ready(function () {
// Gestione click sul pulsante per il toggle
pluginToggle.on("click", function () {
$("aside.content-wrapper, .main-footer").toggleClass("with-control-sidebar");
$("aside.content-sidebar, section.content, .main-footer").toggleClass("with-control-sidebar");
toggleControlSidebar();
});

View File

@ -52,7 +52,7 @@ $(document).ready(function () {
// Trasformazione risultati in formato leggibile
const results = data.map(function (result) {
return {
label: result.label ? result.label : '<h4>' + result.title + '</h4>' + result.labels
label: result.badge ? result.badge : '<h4>' + result.title + '</h4>' + result.badges
.join('').split('<br/>,').join('<br/>'),
group: result.category,
link: result.link,
@ -87,8 +87,8 @@ $(document).ready(function () {
},
render: function(item, currentValue){
const itemElement = document.createElement("div");
itemElement.innerHTML = item.label;
// <a href='" + item.link + "' title='Clicca per aprire'><b>" + item.value + "</b><br/>" + item.label + "</a>
itemElement.innerHTML = item.badge;
// <a href='" + item.link + "' title='Clicca per aprire'><b>" + item.value + "</b><br/>" + item.badge + "</a>
return itemElement;
}
});

View File

@ -322,7 +322,7 @@ function impostaCategorieAllegatiDisponibili(gestione, categorie) {
update(results);
},
onSelect: function (item) {
input.value = item.label;
input.value = item.badge;
},
});
}

View File

@ -291,7 +291,7 @@ function initComplete(settings) {
forceSearch = true;
}
$('<br><input type="text" style="width:100%" class="form-control' + (value ? ' input-searching' : '') + '" placeholder="' + globals.translations.filter + '..." value="' + value.replace(/"/g, '&quot;') + '"><i class="deleteicon fa fa-times fa-2x' + (value ? '' : ' hide') + '"></i>')
$('<br><input type="text" style="width:100%" class="form-control' + (value ? ' input-searching' : '') + '" placeholder="' + globals.translations.filter + '..." value="' + value.replace(/"/g, '&quot;') + '"><i class="deleteicon fa fa-times ' + (value ? '' : ' hide') + '"></i>')
.appendTo(column.header())
.on('keyup', function (e) {
clearInterval(tempo);
@ -410,6 +410,11 @@ function drawCallback(settings) {
}).select();
}
});
// Fix larghezza colonne datatables
setTimeout( function(){
datatable.columns.adjust()
}, 100);
}
function footerCallback(row, data, start, end, display) {
@ -418,11 +423,17 @@ function footerCallback(row, data, start, end, display) {
this.api().columns().every(function () {
if (json.summable[i] !== undefined) {
$(this.footer()).addClass("text-right")
$(this.footer()).css("text-align", "right")
.attr("id", "summable")
.html(json.summable[i]);
}
if (json.avg[i] !== undefined) {
$(this.footer()).css("text-align", "right")
.attr("id", "avg")
.html(json.avg[i]);
}
i++;
});
}
@ -527,7 +538,11 @@ function getTable(selector) {
getSelectedRowsFooter: function () {
let ids = this.getSelectedRows();
return $.ajax({
let summable_results = [];
let avg_results = [];
let results = [];
summable_results = $.ajax({
url: globals.rootdir + "/ajax.php",
type: "POST",
dataType: "json",
@ -538,10 +553,25 @@ function getTable(selector) {
ids: ids,
}
});
avg_results = $.ajax({
url: globals.rootdir + "/ajax.php",
type: "POST",
dataType: "json",
data: {
id_module: this.id_module,
id_plugin: this.id_plugin,
op: "avg-results",
ids: ids,
}
});
results = $.when(summable_results, avg_results);
return results;
},
/**
* Aggiornamento dei campi summable
* Aggiornamento dei campi summable e avg
*/
updateFooterForSelectedRows: function () {
let datatable = this.datatable;
@ -550,9 +580,12 @@ function getTable(selector) {
for (let [column, value] of Object.entries(response)) {
let index = parseInt(column) + 1;
let sel = datatable.column(index).footer();
$(sel).addClass("text-right")
$(sel).css("text-align", "right")
.attr("id", "summable")
.html(value);
$(sel).css("text-align", "right")
.attr("id", "avg")
.html(value);
}
});
},

View File

@ -129,6 +129,7 @@ function start_complete_calendar(id, callback) {
ranges[globals.translations.nextMonth] = [moment().add(1, 'month').startOf('month'), moment().add(1, 'month').endOf('month')];
ranges[globals.translations.thisYear] = [moment().startOf('year'), moment().endOf('year')];
ranges[globals.translations.lastYear] = [moment().subtract(1, 'year').startOf('year'), moment().subtract(1, 'year').endOf('year')];
ranges[globals.translations.lastYear_thisYear] = [moment().subtract(1, 'year').startOf('year'), moment().endOf('year')];
var format = dateFormatMoment(globals.date_format);
$(id).daterangepicker({

View File

@ -58,13 +58,13 @@ function openModal(title, href) {
const content = '<div class="modal-dialog modal-lg">\
<div class="modal-content">\
<div class="modal-header bg-light-blue">\
<button type="button" class="close" data-dismiss="modal">\
<span aria-hidden="true">&times;</span><span class="sr-only">' + globals.translations.close + '</span>\
</button>\
<div class="modal-header">\
<h4 class="modal-title">\
<i class="fa fa-pencil"></i> ' + title + '\
</h4>\
<button type="button" class="close" data-dismiss="modal">\
<span aria-hidden="true">&times;</span><span class="sr-only">' + globals.translations.close + '</span>\
</button>\
</div>\
<div class="modal-body">|data|</div>\
</div>\
@ -94,7 +94,7 @@ function openModal(title, href) {
* @param link
*/
function openLink(event, link) {
if (event.ctrlKey) {
if (event.ctrlKey || event.metaKey) {
window.open(link);
} else {
location.href = link;
@ -451,17 +451,17 @@ function alertPush() {
$('.alert-success.push').each(function () {
i++;
tops = 60 * i + 95;
bottoms = 60 * i;
$(this).css({
'position': 'fixed',
'z-index': 3000,
'right': '10px',
'top': -100,
'z-index': 300000,
'right': '10px',
'bottom': -100,
}).delay(1000).animate({
'top': tops,
'bottom': bottoms,
}).delay(3000).animate({
'top': -100,
'bottom': -100,
});
});
}
@ -469,7 +469,7 @@ function alertPush() {
// Nascondo la notifica se passo sopra col mouse
$('.alert-success.push').on('mouseover', function () {
$(this).stop().animate({
'top': -100,
'bottom': -100,
'opacity': 0
});
});

View File

@ -19,6 +19,41 @@
/**
*
*/
// Funzione per richiesta AJAX hooks completata con successo
function handleHooksSuccess(hooks) {
completedRequests = 0;
$("#hooks-header").text(globals.translations.hooksExecuting);
$("#hooks-number").text(hooks.length);
if (hooks.length == 0) {
$("#hooks-loading").hide();
$("#hooks-number").text(0);
$("#hooks-header").text(globals.translations.hookNone);
}
hooks.forEach(function (item, index) {
renderHook(item, {
show: true,
message: globals.translations.hookExecuting.replace('_NAME_', item.name)
});
startHook(item, true);
completedRequests++;
});
totalRequests = hooks.length;
if (completedRequests === totalRequests) {
// Verifica se tutte le richieste sono state completate con successo
//console.log("Tutte le richieste AJAX sono state eseguite con successo.");
}else{
console.log("Alcune richieste AJAX non sono state eseguite.");
}
}
function startHooks() {
$.ajax({
url: globals.rootdir + "/ajax.php",
@ -28,25 +63,11 @@ function startHooks() {
},
success: function (data) {
hooks = JSON.parse(data);
$("#hooks-header").text(globals.translations.hooksExecuting);
$("#hooks-number").text(hooks.length);
if (hooks.length == 0) {
$("#hooks-loading").hide();
$("#hooks-number").text(0);
$("#hooks-header").text(globals.translations.hookNone);
}
hooks.forEach(function (item, index) {
renderHook(item, {
show: true,
message: globals.translations.hookExecuting.replace('_NAME_', item.name)
});
startHook(item, true);
});
},
handleHooksSuccess(hooks);
},
error: function (xhr, status, error) {
console.error("Errore durante la richiesta AJAX relativa agli Hooks");
}
});
}
@ -76,6 +97,7 @@ function startHook(hook, init) {
if (token) {
executeHook(hook, token);
} else {
//Rallentamento esecuzione hooks
var timeout = 30;
setTimeout(function () {
@ -151,11 +173,11 @@ function updateHook(hook) {
if (number == 0) {
$("#hooks-notified").html('<i class="fa fa-check" aria-hidden="true"></i>');
$("#hooks-label").removeClass();
$("#hooks-label").addClass('label').addClass('label-success');
$("#hooks-label").addClass('badge').addClass('badge-success');
} else {
$("#hooks-notified").text(number);
$("#hooks-label").removeClass();
$("#hooks-label").addClass('label').addClass('label-danger');
$("#hooks-label").addClass('badge').addClass('badge-danger');
}
if (counter == $("#hooks-number").text()) {
@ -206,7 +228,7 @@ function renderHook(hook, result) {
// Inizializzazione
var element = $("#" + element_id);
if (element.length == 0) {
$("#hooks").append('<li class="hook-element" id="' + element_id + '"></li>');
$("#hooks").append('<div class="dropdown-item hook-element" id="' + element_id + '"></div>');
element = $("#" + element_id);
}
@ -219,7 +241,16 @@ function renderHook(hook, result) {
}
// Contenuto
var content = '<a href="' + (result.link ? result.link : "#") + '"><i class="' + result.icon + '"></i><span class="small"> ' + result.message + '</span>';
var content = '';
if (result.link) {
content += '<a href="' + result.link + '">';
} else {
content += '<div class="hooks-header">';
}
content += '<i class="' + result.icon + '"></i> <span class="small"> ' + result.message + '</span>';
if (result.progress) {
var current = result.progress.current;
@ -232,7 +263,11 @@ function renderHook(hook, result) {
content += '<div class="progress" style="margin-bottom: 0px;"><div class="progress-bar" role="progressbar" aria-valuenow="' + percentage + '" aria-valuemin="0" aria-valuemax="100" style="width:' + percentage + '%">' + percentage + '% (' + current + '/' + total + ')</div></div>';
}
content += '</a>';
if (result.link) {
content += '</a>';
} else {
content += '</div>';
}
element.html(content);
}

View File

@ -17,9 +17,6 @@
*/
function init() {
// Inizializzazzione dei box AdminLTE
$('.box').boxWidget();
// Modal di default
$('[data-href]').not('.ask, .bound').click(function () {
launch_modal($(this).data('title'), $(this).data('href'), 1);

View File

@ -119,6 +119,7 @@ function initCKEditor(input) {
filebrowserUploadMethod: 'form',
fullPage: (input.hasAttribute('use_full_ckeditor')) ? true : false,
allowedContent: (input.hasAttribute('use_full_ckeditor')) ? true : false,
versionCheck: false,
extraPlugins: 'scayt,textwatcher,autocomplete,textmatch,emoji',
skin: 'moono-lisa',
});

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,8 @@
/**
* Copyright (C) 2023 Wacom.
* Use of this source code is governed by the MIT License that can be found in the LICENSE file.
*/
function integrityStatusDesc(status) {
switch (status) {
case Module.IntegrityStatus.OK: return "Integrity correct";

View File

@ -1,12 +0,0 @@
{
"name": "STU-SDK",
"productName": "STU-SDK",
"version": "1.0.0",
"description": "STU SDK for Javascript",
"dependencies": {
"blueimp-md5": "^2.19.0",
"sjcl": "^1.0.8"
},
"author": "Juan Garrido",
"license": "Wacom"
}

View File

@ -1,826 +0,0 @@
//
// stu_capture.js
//
// Displays a form with 3 buttons on the STU pad and on the browser allowing user to input a signature.
// The final signature is then reproduced on a second window on the PC screen
//
// Copyright (c) 2021 Wacom GmbH. All rights reserved.
//
//
var signatureForm;
function captureFromSTU(sigObj, integrityType, hash, extraData) {
if (!signatureForm) {
signatureForm = new SignatureForm(sigObj, integrityType, hash, extraData);
}
signatureForm.connect();
}
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
// In order to simulate buttons, we have our own Button class that stores the bounds and event handler.
// Using an array of these makes it easy to add or remove buttons as desired.
// delegate void ButtonClick();
function Button() {
this.Bounds; // in Screen coordinates
this.Text;
this.Click;
}
function Rectangle(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.Contains = function (pt) {
if (((pt.x >= this.x) && (pt.x <= (this.x + this.width))) &&
((pt.y >= this.y) && (pt.y <= (this.y + this.height)))) {
return true;
} else {
return false;
}
}
}
class SignatureForm {
constructor(sigObj, integrityType, hash, extraData) {
this.sigObj = sigObj;
this.integrityType = integrityType;
this.hash = hash;
this.extraData = extraData;
// The mIsDown flag is used like this:
// 0 = up
// +ve = down, pressed on button number
// -1 = down, inking
// -2 = down, ignoring
this.mIsDown = 0;
this.mPenData = new Array(); // Array of data being stored. This can be subsequently used as desired.
this.currentDevice = null;
this.onClick = false;
}
// Connect to the first device
async connect() {
if (!this.currentDevice) {
let devices = await com.WacomGSS.STU.UsbDevice.requestDevices();
if (devices.length > 0) {
this.currentDevice = devices[0];
} else {
return;
}
}
this.mTablet = new com.WacomGSS.STU.Tablet();
this.mTablet.setEncryptionHandler(new MyEncryptionHandler());
this.mTablet.setEncryptionHandler2(new MyEncryptionHandler2());
try {
await this.mTablet.usbConnect(this.currentDevice);
this.mCapability = await this.mTablet.getCapability();
this.mInformation = await this.mTablet.getInformation();
this.mInkThreshold = await this.mTablet.getInkThreshold();
try {
await this.mTablet.setPenDataOptionMode(com.WacomGSS.STU.Protocol.PenDataOptionMode.TimeCountSequence);
} catch (e) {
}
this.mTablet.addTabletHandler(this);
//if (this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.OperationMode_$LI$())) {
//this.mSignatureMode = true;
//}
this.mSignatureMode = false;
const pixelWidth = (96*this.mCapability.tabletMaxX*0.01)/25.4;
const pixelHeight = (96*this.mCapability.tabletMaxY*0.01)/25.4;
//this.createModalWindow(this.mCapability.screenWidth, this.mCapability.screenHeight);
this.createModalWindow(pixelWidth, pixelHeight);
this.mScaleX = this.canvas.width / this.mCapability.tabletMaxX;
this.mScaleY = this.canvas.height / this.mCapability.tabletMaxY;
this.mBtns = new Array(3);
this.mBtns[0] = new Button();
this.mBtns[1] = new Button();
this.mBtns[2] = new Button();
if (this.mSignatureMode) {
// LCD is 800x480; Button positions and sizes are fixed
this.mBtns[0].Bounds = new Rectangle( 0, 431, 265, 48);
this.mBtns[1].Bounds = new Rectangle(266, 431, 265, 48);
this.mBtns[2].Bounds = new Rectangle(532, 431, 265, 48);
} else if (this.mInformation.modelName != "STU-300") {
// Place the buttons across the bottom of the screen.
const w2 = this.canvas.width / 3;
const w3 = this.canvas.width / 3;
const w1 = this.canvas.width - w2 - w3;
const y = this.canvas.height * 6 / 7;
const h = this.canvas.height - y;
this.mBtns[0].Bounds = new Rectangle(0, y, w1, h);
this.mBtns[1].Bounds = new Rectangle(w1, y, w2, h);
this.mBtns[2].Bounds = new Rectangle(w1 + w2, y, w3, h);
} else {
// The STU-300 is very shallow, so it is better to utilise
// the buttons to the side of the display instead.
const x = this.mCapability.screenWidth * 3 / 4;
const w = this.mCapability.screenWidth - x;
const h2 = this.mCapability.screenHeight / 3;
const h3 = this.mCapability.screenHeight / 3;
const h1 = this.mCapability.screenHeight - h2 - h3;
this.mBtns[0].Bounds = new Rectangle(x, 0, w, h1);
this.mBtns[1].Bounds = new Rectangle(x, h1, w, h2);
this.mBtns[2].Bounds = new Rectangle(x, h1 + h2, w, h3);
}
this.mBtns[0].Text = "Clear";
this.mBtns[0].Click = this.btnClearClick.bind(this);
this.mBtns[1].Text = "Cancel";
this.mBtns[1].Click = this.btnCancelClick.bind(this);
this.mBtns[2].Text = "OK";
this.mBtns[2].Click = this.btnOkClick.bind(this);
// This application uses the same bitmap for both the screen and client (window).
this.ctx.lineWidth = 1;
this.ctx.strokeStyle = 'black';
this.ctx.font = "30px Arial";
this.ctx.fillStyle = "white";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
let encodingFlag = com.WacomGSS.STU.Protocol.ProtocolHelper.simulateEncodingFlag(this.mTablet.getProductId(), this.mCapability.ecodingFlag);
// Disable color if the bulk driver isn't installed (supportsWrite())
if ((encodingFlag & com.WacomGSS.STU.Protocol.EncodingFlag.EncodingFlag_24bit) != 0) {
this.mEncodingMode = this.mTablet.supportsWrite() ? com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_24bit_Bulk : com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_24bit;
} else if ((encodingFlag & com.WacomGSS.STU.Protocol.EncodingFlag.EncodingFlag_16bit) != 0) {
this.mEncodingMode = this.mTablet.supportsWrite() ? com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_16bit_Bulk : com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_16bit;
} else {
// assumes 1bit is available
this.mEncodingMode = com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_1bit;
}
if (this.mSignatureMode && !await this.initializeSigMode()) {
alert("Exception initializing Signature Mode, reverting to normal operation");
this.mSignatureMode = false;
}
if (!this.mSignatureMode) {
let btnsColors = ["white", "white", "white"];
if((this.mEncodingMode & (com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_16bit_Bulk | com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_24bit_Bulk)) != 0)
btnsColors = ["lightgrey", "lightgrey", "lightgrey"];
let newCanvas = this.createScreenImage(btnsColors, "black", null);
//store the background image in order to be reuse it when clear the screen
this.mCanvasBackgroundImage = newCanvas.toDataURL("image/jpeg");
this.mDeviceBackgroundImage = com.WacomGSS.STU.Protocol.ProtocolHelper.resizeAndFlatten(newCanvas, 0, 0, newCanvas.width, newCanvas.height,
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode,0, "white", false, 0);
// If you wish to further optimize image transfer, you can compress the image using
// the Zlib algorithm.
const useZlibCompression = false;
if (this.mEncodingMode == com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_1bit && useZlibCompression) {
this.mDeviceBackgroundImage = compress_using_zlib(this.mDeviceBackgroundImage); // insert compression here!
this.mEncodingMode = com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_1bit_ZLib;
}
// Initialize the screen
await this.clearScreen();
}
if ((this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.EncryptionStatus)) ||
(await com.WacomGSS.STU.Protocol.ProtocolHelper.supportsEncryption(this.mTablet.getProtocol()))) {
await this.mTablet.startCapture(0xc0ffee);
this.mIsEncrypted = true;
}
// Enable the pen data on the screen (if not already)
await this.mTablet.setInkingMode(com.WacomGSS.STU.Protocol.InkingMode.On);
this.willCanvas = document.createElement("canvas");
this.willCanvas.id = "willCanvas";
this.willCanvas.style.position = "absolute";
this.willCanvas.style.top = this.canvas.style.top;
this.willCanvas.style.left = this.canvas.style.left;
this.willCanvas.height = this.canvas.height;
this.willCanvas.width = this.canvas.width;
this.mFormDiv.appendChild(this.willCanvas);
if (this.willCanvas.addEventListener) {
this.willCanvas.addEventListener("click", this.onCanvasClick.bind(this), false);
}
await this.initInkController(this.willCanvas);
} catch (e) {
alert(e);
}
}
async disconnect() {
// Ensure that you correctly disconnect from the tablet, otherwise you are
// likely to get errors when wanting to connect a second time.
if (this.mTablet != null) {
if (this.mIsEncrypted) {
await this.mTablet.endCapture();
this.mIsEncrypted = false;
}
await this.mTablet.setInkingMode(com.WacomGSS.STU.Protocol.InkingMode.Off);
await this.mTablet.setClearScreen();
await this.mTablet.disconnect();
}
this.closeModalWindow();
}
showLoadingScreen(value) {
if (value) {
//this.canvas.style.display = "none";
this.mLoadingImageDiv.style.display = "block";
} else {
//this.canvas.style.display = "block";
this.mLoadingImageDiv.style.display = "none";
}
}
createModalWindow(width, height) {
this.mModalBackground = document.createElement('div');
this.mModalBackground.id = "modal-background";
this.mModalBackground.className = "active";
this.mModalBackground.style.width = window.innerWidth;
this.mModalBackground.style.height = window.innerHeight;
document.getElementsByTagName('body')[0].appendChild(this.mModalBackground);
let titleBarHeight = 25;
let margin = 2;
this.mSignatureWindow = document.createElement('div');
this.mSignatureWindow.id = "signatureWindow";
this.mSignatureWindow.style.position = "absolute";
this.mSignatureWindow.style.backgroundColor = "#0097d4";
this.mSignatureWindow.style.top = (window.innerHeight / 2) - (height / 2) + "px";
this.mSignatureWindow.style.left = (window.innerWidth / 2) - (width / 2) + "px";
this.mSignatureWindow.style.width = (width + margin + margin) + "px";
this.mSignatureWindow.style.height = (height+titleBarHeight + margin + margin) + "px";
document.getElementsByTagName('body')[0].appendChild(this.mSignatureWindow);
this.mTitleBar = document.createElement("div");
this.mTitleBar.id = "titleBar";
this.mTitleBar.style.width = "100%";
this.mTitleBar.style.height = (titleBarHeight-5)+"px";
this.mTitleBar.innerHTML = this.mInformation.modelName;
this.mSignatureWindow.appendChild(this.mTitleBar);
this.mFormDiv = document.createElement('div');
//this.mFormDiv.id = "signatureWindow";
//this.mFormDiv.className = "active";
this.mFormDiv.style.position = "absolute";
this.mFormDiv.style.margin = "2px 2px 2px 2px";
this.mFormDiv.style.top = titleBarHeight;//(window.innerHeight / 2) - (height / 2) + "px";
//this.mFormDiv.style.left = "10px";//(window.innerWidth / 2) - (width / 2) + "px";
this.mFormDiv.style.width = width + "px";
this.mFormDiv.style.height = height + "px";
this.mSignatureWindow.appendChild(this.mFormDiv);
//document.getElementsByTagName('body')[0].appendChild(this.mFormDiv);
this.canvas = document.createElement("canvas");
this.canvas.id = "myCanvas";
this.canvas.style.position = "absolute";
this.canvas.height = this.mFormDiv.offsetHeight;
this.canvas.width = this.mFormDiv.offsetWidth;
this.ctx = this.canvas.getContext("2d");
this.mFormDiv.appendChild(this.canvas);
//this.canvas.style.display = "none";
//if (this.canvas.addEventListener) {
//this.canvas.addEventListener("click", this.onCanvasClick.bind(this), false);
//}
this.mLoadingImageDiv = document.createElement('div');
this.mLoadingImageDiv.style.position = "absolute";
this.mLoadingImageDiv.style.backgroundColor="white";
this.mLoadingImageDiv.style.width = "100%";
this.mLoadingImageDiv.style.height = "100%";
this.mLoadingImageDiv.innerHTML = '<div id="loadingDiv"><table><tr><td><img src="../common/stu_capture/loading.gif"></td><td>Loading the image, this could take a few seconds...</td></tr></div>';
this.mFormDiv.appendChild(this.mLoadingImageDiv);
$("#signatureWindow").draggable({handle:"#titleBar"});
}
// Initialize Signature Mode (STU-540 only)
async initializeSigMode() {
// Buttons on bitmaps sent to the tablet must be in the order Cancel / OK / Clear. The tablet will then
// reorder button images displayed according to parameters passed to it in OperationMode_Signature
// This application uses Clear / Cancel / OK
const btnOrder = [2, 0, 1];
const btnsUpColors = ["blue", "red", "green"];
const btnsDownColors = ["darkblue", "darkred", "darkgreen"];
let canvas = this.createScreenImage(btnsUpColors, "black", btnOrder);
let bitmapData = com.WacomGSS.STU.Protocol.ProtocolHelper.resizeAndFlatten(canvas, 0, 0, canvas.width, canvas.height,
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode,
com.WacomGSS.STU.Protocol.ProtocolHelper.Scale.Strech, "white", false, 0);
await this.checkSigModeImage(false, bitmapData);
canvas = this.createScreenImage(btnsDownColors, "white", btnOrder);
bitmapData = com.WacomGSS.STU.Protocol.ProtocolHelper.resizeAndFlatten(canvas, 0, 0, canvas.width, canvas.height,
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode,
com.WacomGSS.STU.Protocol.ProtocolHelper.Scale.Strech, "white", false, 0);
await this.checkSigModeImage(true, bitmapData);
let sigMode = new com.WacomGSS.STU.Protocol.OperationMode_Signature(2, btnOrder, 0, 0);
await this.mTablet.setOperationMode(new com.WacomGSS.STU.Protocol.OperationMode(sigMode));
canvas = this.createScreenImage(btnsUpColors, "black", null);
this.mCanvasBackgroundImage = canvas.toDataURL("image/jpeg");
this.clearScreen();
return true;
}
createScreenImage(btnColors, txtColor, btnOrder) {
let canvas = document.createElement("canvas");
canvas.width = this.canvas.width;
canvas.height = this.canvas.height;
let ctx = canvas.getContext("2d");
ctx.lineWidth = 1;
ctx.strokeStyle = 'black';
ctx.font = "30px Arial";
ctx.fillStyle = "white";
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
// Draw the buttons
for (let i = 0; i < this.mBtns.length; ++i) {
// Button objects are created in the order, left-to-right, Clear / Cancel / OK
// If reordering for Signature Mode (btnOrder != null), use bounds of another button when drawing
// for image to be sent to tablet.
let btn = this.mBtns[i];
let bounds = btnOrder != null ? this.mBtns[btnOrder[i]].Bounds : this.mBtns[i].Bounds;
if (this.mEncodingMode != com.WacomGSS.STU.Protocol.EncodingMode.EncodingMode_1bit) {
ctx.fillStyle = btnColors[i];
ctx.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
}
ctx.fillStyle = txtColor;
ctx.rect(bounds.x, bounds.y, bounds.width, bounds.height);
let xPos = bounds.x + ((bounds.width / 2) - (ctx.measureText(btn.Text).width / 2));
let metrics = ctx.measureText(btn.Text);
let fontHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
let actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
let yOffset = bounds.height - ((bounds.height / 2) - (actualHeight / 2));
/*if (m_information.idProduct == enumProductId.STU_300)
yOffset = 28;
else if (m_information.idProduct == enumProductId.STU_430)
yOffset = 26;
else
yOffset = 40;*/
ctx.fillText(btn.Text, xPos, bounds.y + yOffset);
}
ctx.stroke();
/*if ((this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.EncryptionStatus)) ||
(await com.WacomGSS.STU.Protocol.ProtocolHelper.supportsEncryption(this.mTablet.getProtocol()))) {
ctx.fillStyle = "black";
ctx.fillText("\uD83D\uDD12", 20, 50);
}*/
return canvas;
}
// Check if a Signature Mode screen image is already stored on the tablet. Download it if not.
async checkSigModeImage(pushed, imageData) {
let sigScreenImageNum = 2;
let romStartImageData = com.WacomGSS.STU.Protocol.RomStartImageData.initializeSignature(this.mEncodingMode, pushed, sigScreenImageNum, [true, true, true]);
await this.mTablet.setRomImageHash(com.WacomGSS.STU.Protocol.OperationModeType.Signature_$LI$(), pushed, sigScreenImageNum);
let romImgHash = await this.mTablet.getRomImageHash();
let writeImage = true;
if (romImgHash.getResult() == 0) {
// There is already an image stored on the tablet corresponding to this image number and pushed state:
// compare image hashes to determine if we need to overwrite it.
if (arrayEquals(md5.array(imageData), romImgHash.getHash())) {
// Image hashes match: no need to write image again
writeImage = false;
}
}
// else - no image on pad, writeImage = true;
if (writeImage) {
// no image on pad
await this.mTablet.writeRomImage(romStartImageData, imageData);
}
}
async clearScreen() {
if (window.WILL) {
window.WILL.clear();
} else {
// repaint the background image on the screen.
const outer = this;
const image = new Image();
image.onload = function () {
outer.ctx.drawImage(image, 0, 0);
}
image.src = this.mCanvasBackgroundImage;
}
this.showLoadingScreen(true);
if (!this.mSignatureMode) {
// note: There is no need to clear the tablet screen prior to writing an image.
await this.mTablet.writeImage(this.mEncodingMode, this.mDeviceBackgroundImage);
}
this.mPenData = new Array();
this.mIsDown = 0;
this.showLoadingScreen(false);
}
closeModalWindow() {
this.deleteInkCanvas();
document.getElementsByTagName('body')[0].removeChild(this.mSignatureWindow);
const modalBackground = document.getElementById("modal-background");
if (modalBackground) {
document.getElementsByTagName('body')[0].removeChild(modalBackground);
}
}
tabletToScreen(penData) {
// Screen means LCD screen of the tablet.
return new Point(penData.x * this.mScaleX, penData.y * this.mScaleY);
}
async onSignatureEvent(keyValue) {
switch (keyValue) {
case 0:
await this.btnCancelClick()
break;
case 1:
await this.btnOkClick();
break;
case 2:
await this.btnClearClick();
break;
}
}
onCanvasClick(event) {
// Enable the mouse to click on the simulated buttons that we have displayed.
// Note that this can add some tricky logic into processing pen data
// if the pen was down at the time of this click, especially if the pen was logically
// also 'pressing' a button! This demo however ignores any that.
const posX = event.pageX - $("#willCanvas").offset().left;
const posY = event.pageY - $("#willCanvas").offset().top;
for (let i = 0; i < this.mBtns.length; i++) {
if (this.mBtns[i].Bounds.Contains(new Point(posX, posY))) {
this.mBtns[i].Click();
break;
}
}
}
async btnOkClick() {
if (this.mPenData.length > 0) {
await this.getCaptureData();
await this.btnCancelClick();
this.renderSignature = true;
}
this.onClick = false;
}
async btnClearClick() {
if (this.mPenData.length > 0) {
await this.clearScreen();
}
this.onClick = false;
}
async btnCancelClick() {
await this.disconnect();
this.onClick = false;
}
// Generate the signature image
async getCaptureData() {
//Create Stroke Data
var strokeVector = new Module.StrokeVector();
var currentStroke = new Module.PointVector();
var currentStrokeID = 0;
var isDown = true;
var hasDown = false;
for (let index = 0; index < this.mPenData.length; index++) {
if (this.mPenData[index].sw == 0 && !hasDown) {
continue;
}
hasDown = true;
if (isDown && this.mPenData[index].sw == 0 || !isDown && this.mPenData[index].sw == 1) {
isDown = (this.mPenData[index].sw == 1);
//Move the current stroke data into the strokes array
strokeVector.push_back({'points': currentStroke});
currentStroke.delete();
currentStroke = new Module.PointVector();
currentStrokeID++;
}
var point = {
'x': this.mPenData[index].x,
'y': this.mPenData[index].y,
'p': this.mPenData[index].pressure,
't': this.mPenData[index].timeCount,
'tilt': 0,
'twist': 0,
'is_down': this.mPenData[index].sw,
'stroke_id': currentStrokeID
};
currentStroke.push_back(point);
}
//Create capture area character
var device = {
'device_max_X': this.mCapability.tabletMaxX,
'device_max_Y': this.mCapability.tabletMaxY,
'device_max_P': this.mCapability.tabletMaxPressure,
'device_pixels_per_m_x': 100000,
'device_pixels_per_m_y': 100000,
'device_origin_X': 0,
'device_origin_Y': 1,
'has_tilt': false,
'has_twist': false
}
var uid2;
try {
// getUid2 will throw if pad doesn't support Uid2
uid2 = mTablet.getUid2();
}
catch (e) {
}
if (!uid2) {
uid2 = 0;
}
var digitizerInfo = "STU;'"+this.mInformation.modelName+"';"+this.mInformation.firmwareMajorVersion+"."+((parseInt(this.mInformation.firmwareMinorVersion) >> 4) & 0x0f)+"."+(parseInt(this.mInformation.firmwareMinorVersion) & 0x0f)+";"+uid2;
var nicInfo = "";
var timeResolution = 1000;
var who = "Test user";
var why = "test signature";
var where = "";
await this.sigObj.generateSignature(who, why, where, this.integrityType, this.hash, strokeVector, device, digitizerInfo, nicInfo, timeResolution, new Date());
// put the extra data
for (const [key, value] of this.extraData) {
this.sigObj.setExtraData(key, value);
}
//this.hash.delete();
strokeVector.delete();
currentStroke.delete();
}
onPenDataOption(penData, time) {
this.onPenData(penData, time);
}
onPenDataTimeCountSequence(penData, time) {
this.onPenData(penData, time);
}
onPenDataTimeCountSequenceEncrypted(penData, time) {
this.onPenDataTimeCountSequence(penData, time);
}
onPenDataEncryptedOption(penData, time) { // Process incoming pen data
this.onPenData(penData.penData1, time);
this.onPenData(penData.penData2, time);
}
onPenDataEncrypted(penData, time) { // Process incoming pen data
this.onPenData(penData.penData1, time);
this.onPenData(penData.penData2, time);
}
onPenData(penData, time) { // Process incoming pen data
// console.log(JSON.stringify(penData));
if (this.onClick) {
return;
}
if (!penData.timeCount) {
penData.timeCount = Math.trunc(time)%1000000;
}
// when the pen goes behind borders there is a bug that onalsy return 0
let pt = this.tabletToScreen(penData);
let btn = 0; // will be +ve if the pen is over a button.
for (var i = 0; i < this.mBtns.length; ++i) {
if (this.mBtns[i].Bounds.Contains(pt)) {
btn = i + 1;
break;
}
}
if (this.mIsDown == 0)
{
const isDown = (penData.pressure > this.mInkThreshold.onPressureMark);
if (isDown)
{
// transition to down
if (btn > 0)
{
// We have put the pen down on a button.
// Track the pen without inking on the client.
this.mIsDown = btn;
}
else
{
// We have put the pen down somewhere else.
// Treat it as part of the signature.
this.mIsDown = -1;
this.mPenData.push(penData);
this.mPainting = true;
var downEvent = new PointerEvent("pointerdown", {
pointerId: 1,
bubbles: true,
cancelable: true,
pointerType: "pen",
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
time: penData.timeCount
});
window.WILL.begin(InkBuilder.createPoint(downEvent));
}
} else {
// hover point
this.mPenData.push(penData);
}
}
else
{
const isDown = !(penData.pressure <= this.mInkThreshold.offPressureMark);
if (!isDown)
{
// transition to up
if (btn > 0) {
// The pen is over a button
if (btn == this.mIsDown) {
// The pen was pressed down over the same button as is was lifted now.
// Consider that as a clicki!
this.onClick = true; //
this.mBtns[btn-1].Click();
}
}
this.mIsDown = 0;
if (this.mPainting) {
this.mPainting = false;
this.mPenData.push(penData);
if ((penData.x == 0) && (penData.y == 0) && (penData.pressure == 0)) {
penData.x = this.lastPenData.x;
penData.y = this.lastPenData.y;
pt = this.tabletToScreen(penData);
}
var upEvent = new PointerEvent("pointerup", {
pointerId: 1,
bubbles: true,
cancelable: true,
pointerType: "pen",
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
time: penData.timeCount
});
window.WILL.end(InkBuilder.createPoint(upEvent));
}
} else {
if (this.mPainting) {
this.mPenData.push(penData);
var moveEvent = new PointerEvent("pointermove", {
pointerId: 1,
bubbles: true,
cancelable: true,
pointerType: "pen",
width: 10,
height: 10,
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
time: penData.timeCount
});
window.WILL.move(InkBuilder.createPoint(moveEvent));
}
}
}
this.lastPenData = penData;
}
onEventDataSignature(eventData) {
this.onSignatureEvent(eventData.getKeyValue());
}
onEventDataSignatureEncrypted(eventData) {
this.onSignatureEvent(eventData.getKeyValue());
}
// Capture any report exception.
onGetReportException(exception) {
try {
exception.getException();
} catch (e) {
alert(e);
}
}
async initInkController(canvas) {
const inkColor = "#0000ff";
let inkCanvas = await new InkCanvasRaster(canvas, canvas.width, canvas.height);
await BrushPalette.configure(inkCanvas.canvas.ctx);
window.WILL = inkCanvas;
WILL.setColor(Color.fromHex(inkColor));
WILL.type = "raster";
await WILL.setTool("pen");
}
async deleteInkCanvas() {
await BrushPalette.delete();
await window.WILL.delete();
window.WILL = null;
if (this.renderSignature) {
this.renderSignature = false;
renderSignature(true);
}
}
onDisconnect(device) {
if (device == this.currentDevice) {
if (document.getElementById("modal-background")) {
this.closeModalWindow();
}
alert(device.productName+" has been disconnected, please connect it again.");
this.currentDevice = null;
signatureForm = null;
}
}
}

View File

@ -1,289 +0,0 @@
/**
* Classes for encryption on STU devices
**/
function toHex(value, padding) {
var hex = value.toString(16);
return "0000000000000000".substr(0,padding-hex.length)+hex;
}
function toHex2(value) { return toHex(value,2); }
function toHex4(value) { return toHex(value,4); }
function toHex8(value) { return toHex(value,8); }
function arrayToHex(v) {
var s="";
for (var i = 0; i < v.length; ++i)
s = s + toHex2(v[i]);
return s;
}
function hexToArray(s) {
var a = new Array();
for (var i = 0; i < s.length;i+=2)
a.push(parseInt("0x"+ s.substr(i,2),16));
return a;
}
function padLeft(str, len, pad) {
if (typeof(pad) == "undefined") pad = ' ';
str = str.toString();
if (len > str.length)
str = Array(len+1-str.length).join(pad) + str;
return str;
}
function base64UrlDecode(str) {
str = atob(str.replace(/-/g, '+').replace(/_/g, '/'));
var buffer = new Array(str.length);
for(var i = 0; i < str.length; ++i) {
buffer[i] = str.charCodeAt(i);
}
return buffer;
}
function arrayEquals(a, b) {
return Array.isArray(a) &&
Array.isArray(b) &&
a.length === b.length &&
a.every((val, index) => val === b[index]);
}
function generateHexString(length) {
var ret = "";
while (ret.length < length) {
ret += Math.random().toString(16).substring(2);
}
return ret.substring(0,length);
}
function powMod(a, b, prime) {
if (b <= BigInt(0)) {
return (BigInt(1));
} else if (b === BigInt(1)) {
return a % prime;
} else if (b % BigInt(2) === BigInt(0)) {
return powMod((a * a) % prime, b / BigInt(2) | BigInt(0), prime) % prime;
} else {
return (powMod((a * a) % prime, b / BigInt(2) | BigInt(0), prime) * a) % prime;
}
}
class MyEncryptionHandler {
constructor() {
this.clearKeys();
}
/**
* Reset the encryption handler
*/
reset() {
this.clearKeys();
}
/**
* Reset all encryption key values
*/
clearKeys() {
this.bigint_p = null;
this.bigint_g = null;
this.sjcl_keyAES = null;
}
/**
* Checks if Diffie-Hellman key exchange is required
* @return true if key exchange is required
*/
requireDH() {
return this.bigint_p == null || this.bigint_g == null;
}
/**
* Initializes parameters for Diffie-Hellman key exchange
* @param dhPrime Diffie-Hellman prime number
* @param dhBase Diffie-Hellman base number
*/
setDH(dhPrime, dhBase) {
var p = dhPrime;
var g = dhBase;
this.bigint_p = BigInt("0x"+arrayToHex(p));
this.bigint_g = BigInt("0x"+arrayToHex(g));
}
/**
* Generate a public key
* @return 128-bit key, as array of bytes
*/
generateHostPublicKey() {
// secret key
let randomValues = new Uint8Array(64);
window.crypto.getRandomValues(randomValues);
this.bigint_a = BigInt("0x"+arrayToHex(randomValues));
// public key
var bigint_A = powMod(this.bigint_g, this.bigint_a, this.bigint_p);
var hex_A = padLeft(bigint_A.toString(16), 32, '0');
var A = hexToArray(hex_A);
return A;
}
/**
* Calculate a shared key, given the tablet's public key
* @param devicePublicKey the tablet's public key
*/
computeSharedKey(devicePublicKey) {
var B = devicePublicKey;
var bigint_B = BigInt("0x"+arrayToHex(B));
var bigint_shared = powMod(bigint_B, this.bigint_a, this.bigint_p);
var str_shared = padLeft(bigint_shared.toString(16), 32, '0');
this.sjcl_keyAES = new sjcl.cipher.aes( sjcl.codec.hex.toBits(str_shared) );
}
/**
* Decrypts a block of encrypted data
* @param data an array of bytes to decrypt
* @return decrypted data
*/
decrypt(data) {
var arr_cipherText = data;
var hex_cipherText = arrayToHex(arr_cipherText);
var sjcl_cipherText = sjcl.codec.hex.toBits(hex_cipherText);
var sjcl_plainText = this.sjcl_keyAES.decrypt(sjcl_cipherText);
var hex_plainText = sjcl.codec.hex.fromBits(sjcl_plainText);
var arr_plainText = hexToArray(hex_plainText);
return arr_plainText;
}
}
class MyEncryptionHandler2 {
constructor() {
this.clearKeys();
}
/**
* Reset the encryption handler
*/
reset() {
this.clearKeys();
}
/**
* Reset all encryption key values
*/
clearKeys() {
this.privateKey = null;
this.keyAES = null;
this.exponent = null;
this.modulus = null;
}
/**
* Returns the symmetric key type
* @return a Protocol.SymmetricKeyType value
*/
getSymmetricKeyType() {
return com.WacomGSS.STU.Protocol.SymmetricKeyType.AES256;
}
/**
* Returns the asymmetric padding type
* @return a Protocol.AsymmetricPaddingType value
*/
getAsymmetricPaddingType() {
return com.WacomGSS.STU.Protocol.AsymmetricPaddingType.OAEP;
}
/**
* Returns the asymmetric key type
* @return a Protocol.AsymmetricKeyType value
*/
getAsymmetricKeyType() {
return com.WacomGSS.STU.Protocol.AsymmetricKeyType.RSA2048;
}
/**
* Returns the public key exponent
* @return RSA public key exponent as a byte array
*/
async getPublicExponent() {
const keyPair = await window.crypto.subtle.generateKey({
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {
name: "SHA-1"
},
},
true, //wheter the key is extractable or not
["encrypt", "decrypt"]);
this.privateKey = keyPair.privateKey;
const publicKey = await window.crypto.subtle.exportKey("jwk", keyPair.publicKey);
// base64url-decode modulus
this.modulus = base64UrlDecode(publicKey.n);
// base64url-decode exponent
this.exponent = base64UrlDecode(publicKey.e);
return this.exponent;
}
/**
* Generates a public key
* @return generated key as a byte array
*/
async generatePublicKey() {
return this.modulus
}
/**
* Uses private key and padding type to decrypt an encrypted AES (symmetric) key to use in
* subsequent calls to #decrypt.
* @param data Encrypted AES key
*/
async computeSessionKey(data) {
const key = await window.crypto.subtle.decrypt({
name: "RSA-OAEP"
},
this.privateKey,
Uint8Array.from(data)
);
// replace additional left zeros
const decryptKey = BigInt("0x"+arrayToHex(new Uint8Array(key)));
const hexKey = padLeft(decryptKey.toString(16), 64, '0');
// SubtleCrypto only supports AES-CBC with PKCS#7 padding.
// so we need to use another library as STU devices uses no padding.
this.keyAES = new sjcl.cipher.aes(sjcl.codec.hex.toBits(hexKey));
}
/**
* Decrypts a block of encrypted data
* @param data an array of bytes to decrypt
* @return decrypted data
*/
decrypt(data) {
var hex_cipherText = arrayToHex(data);
var sjcl_cipherText = sjcl.codec.hex.toBits(hex_cipherText);
var sjcl_plainText = this.keyAES.decrypt(sjcl_cipherText);
var hex_plainText = sjcl.codec.hex.fromBits(sjcl_plainText);
var arr_plainText = hexToArray(hex_plainText);
return arr_plainText;
}
}

View File

@ -1,22 +0,0 @@
# js-ext ChangeLog
## 1.0.2
_2021-10-01_
### Updates
- TypedArray extened with createSharedIntsance - instance with SharedArrayBuffer, various updates across TypedArray related with shared memory
## 1.0.1
_2021-06-01_
### Updates
- Function Set, Location extension implemented
- Number MAX_$Type constatnts implemented
## 1.0.0
_2020-07-01_
- First release

View File

@ -1,7 +0,0 @@
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,26 +0,0 @@
# js-ext
## Description
The Javascript extension. Provides additional functionality to classes when they are available and when particular functionality is missing.
* Object
* String
* Number
* Function
* Array
* ArrayBuffer
* TypedArray
* Set
* Screen
* Location
* HTMLElement
* HTMLImageElement
* Image
* Canvas (Adds support for OffscreenCanvas when is not available)
* DOMPoint
* DOMRect
* DOMMatrix
Functionallity extensions through not existant classes:
* DOMSize

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,16 +0,0 @@
{
"name": "js-ext",
"productName": "JavaScript Extensions",
"version": "1.0.2",
"description": "Additional functionality provider",
"main": "js-ext-min.cjs",
"module": "js-ext-min.js",
"unpkg": "js-ext-min.js",
"repository": "https://github.com/js-ext.git",
"author": "Tzvetelin Vassilev",
"homepage": "https://github.com/js-ext",
"bugs": {
"url": "https://github.com/js-ext/issues"
},
"license": "ISC"
}

View File

@ -1,155 +0,0 @@
# digital-ink ChangeLog
## 1.5.0 (3.0.7)
_2022-07-01_
### Updates
- _BrushApplier_ optimizations - simplify transform - mat4 to mat2d
- _RIFFEncoder_ and _RIFFDecoder_ LIST chunk support added
- _InkBuilderSettings_ extended - keepAllData, keepSplineParameters options added
- _InkPathProducer_ build method optional settings added, additional pipeline data could be achieved from the worker
- _InkModel_ clear method implemented
_ _SplineInterpolator_ is capable to process and SplineFragments as input
- _InkBuilderAsync_ open / close methods added, open workers is a prerequisite for proper usage
### Breaking Changes
- Long dependency update - ECMA 6 compatible version integrated
- Manipulation module refactoring based on C# implementation
- SpatialContext createInstance method is removed, clone method is provided
- InkModel createCopyInstance method is removed, clone method is provided
- ArrayPath / SharedPath primitives replaced from Path implementation
- View name validation - for non valid names error is throwing
- Interval type deprecated, SplineFragment replace it
- _Stroke_ subStroke method is removed, because Interval dependency, slice replace it, based on SplineFragment
## 1.4.2 (3.0.6)
_2021-11-01_
### Updates
- _ConvexHullChainProducerAsync_ worker _ConvexHullProvider_ as external resource
- _Selector_ selection algorythm improvments
- _InkModel_ version support added, reffers UIM version
- _SplineParameter_ implementation and integration
## 1.4.1 (3.0.5)
_2021-10-01_
### Updates
- _View_ tree property is deprecated, use root instead
- _Stroke_ Stroke.onPipeline abstract static could be implemented to provide custom settings for pipeline
- _Stroke_ target property is deprected, Target enum is obsolete, onPipeline should be implemented when specific behaiour is needed.
- Pipeline refactoring, prediction control increased, POLYGON_SIMPLIFIER stage is deprecated, lastPipelineStage defaults to POLYGON_MERGER
- _InkBuilderSettings_ concatSegments option added, mergePrediction is deprecated
- ArrayPath / SharedPath primitives implemented
- Polygon primitive implemented - shape and holes paths, vertices property provides access to triangulated geometry
- InkPath2D refactored - list of polygons, vertices property provides access to triangulated geometry of all underlying polygons, representing the shape
- Pipeline output update for some of stages - Polygon / InkPath2D
### Bugfixes
- _Scalar_ refactoring, DIP fixed (pixel representation), DP and DPI included
- _SensorChannel_ default resolution fix
- _OffscreenCanvasGL_ height property fix
## 1.4.0 (3.0.4)
_2021-09-01_
### Breaking Changes
- _StrokeRendererGL_ streamUpdatedArea is replaced with blendStroke2D for better integration between GL and 2D contexts
- _InkCodec_ decodeInkModel is async
### Updates
- _InputListener_ resize reason listeners added - for orientation, window resolution, screen resolution, InkController resize method argument reason provided, ResizeReason enum provided
- _InputListener_ suppressKeys properly introduced, it configures ctrlKey, altKey, shiftKey and metaKey and by default if any of them is pressed ink is suppressed
- _InputListener_ provides prediction to _InkController_ move method when is browser supported
- _OffscreenLayer2D_ draws with alpha
- _InkBuilderSettings_ excludedPipelineStages, lastPipelineStage option added
- Stroke renderMode defaults to SOURCE_OVER, required
- StrokeRenderers can batch strokes list, blendStrokes implemented
- Brush2D shape frame based on 1 diameter provides thiner strokes generation
- Selector functionallity bug-fixes
- SpatialContext createInstance method provided - could be based on another context (RTree clone)
- Ink data format update to v.3.1.0
- InkOperation protocol is created
- PrecisionDetection compression serialisation functionality introduced, InkCodec precisionCalculator optional property controlls it
- TripleStore refactoring, extends Array
## 1.3.0 (3.0.3)
_2021-01-15_
### Breaking Changes
- _InkBuilder_ configure method should be called only once before starting new path building
- InkBuilderSettings onBuildComplete property is deprecated, InkBuilder onComplete property should be used instead
### Updates
- _InputListener_ - affects ink input when surface transform is available
- _Stroke_ style support implemented
- _Color_ - hex property provides color as hex
- _Matrix_
- properties setters impl
- is2D property impl
- matrix3d support added
- fromPoints static method impl
- distribution file name updated
- PipelineStage enum available
- InkBuilderSettings updated, pipeline options added:
- lastPipelineStep - controls where pipeline to complete
- excludedPipelineStages - excludes stages from pipeline
### Bugfixes
- _InputDevice_ - fix senosor input validation when pointer is not available
- loading BrushGL assets in Safari
## 1.2.0 (3.0.2)
_2020-09-01_
### Breaking Changes
- _InkController_ - interface is updated, registerTouches(changedTouches) method is replaced with registerInputProvider(pointerID, isPrimary), getInkBuilder(changedTouches) with getInkBuilder(pointerID), implementation update is required
- _InkBuilderAbstract_ - property touchID is renamed to pointerID
### Updates
- _InputListener_ - based on PointerEvent only, fallback class is provided when PointerEvent is not available which implementation is based on MouseEvent and TouchEvent
- _SensorPoint_ - PointerEvent based InputListener extends SensorPoint with coalesced and predicted points, when available
- _Matrix_ - provides access to additional properties like scaleX, translateX, etc.
- _InkPath2D_ - 2D ink path type implemented and integrated
- Layer and StrokeRender implementations extended with setTransform method
### Bugfixes
- _PathPoint_ - transform properly applied rotation when available
## 1.1.0 (3.0.1)
_2020-08-11_
### Updates
- _Spline_ - transfrom functionallity provided
- _Stroke_ - transform functionality updated - transform underlying spline and path if available
- _Intersector_ - intersect2 method renamed to intersectSegmentation, doc update
- _InkContext_ - drawSprite is replaced from drawSpritesBatch (batching points sprites)
- _InputDevice_ - decouple sensor point building from ink builder, InputDevice handles building, validation and provides sensor layout as string array
- _InkCanvas2D_ - context attributes support (Layers inherits canvas attributes)
### Bugfixes
- _InkModel_ - provide proper strokes order after manipulations
- _StrokeDrawContext_ - randomSeed fix (int number instead long)
- _StrokeRendererGL_ - renderer configuration color update, overrides path color
- _InkGLContext_ - blend mode MIN fixed, blendMode as property instead method
- _Matrix_ - fromMatrix method do not recreates Matrix when data is Matrix instance
- _PathPointContext_ - improved attributes values analyse, added suppot for tocuh devices with radius range (0, 1)
- _CurvatureBasedInterpolator_ - rotation bug-fix, ts and tf aplyed
## 1.0.0 (3.0.0)
_2020-07-01_
- First release

View File

@ -1,9 +0,0 @@
The MIT License (MIT)
Copyright (c) 2020 Wacom Co LTD (https://www.wacom.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,140 +0,0 @@
# WILL SDK for ink
**Wacom Ink Layer Language (WILL™)** is a cross-platform digital ink technology.
It is based on the needs of the end-user and Wacom's experience with different domains.
WILL allows you to include premium digital inking features in your applications.
It uses a modularized pipeline allowing each module to be configured, replaced, or omitted as required by the specific application, providing you with superior flexibility.
The newly introduced **Universal Ink Model** is a data model describing ink related data structures and meta-data concept to describe the semantic content of ink.
You can also use the file encoding of the Universal Ink Model to exchange ink content between applications and cross-platform.
The WILL 3 Framework includes:
* Software libraries for multiple platforms (Windows, Android, iOS, Web)
* Code samples illustrating particular functionality
* A web-based **Ink Designer** to configure and test the pipeline
* Comprehensive documentation, including step-by-step guides
## Design Concepts
The following is an introduction to the Design Concepts for our WILL technology.
## Interoperability
WILL 3.0 technology and its **Universal Ink Model** is platform and device agnostic, thus the specification does not focus on specific hardware platforms.
Ink Markup Language **[InkML]** and Ink Serialized Format **[ISF]** are the most well-known formats for storing digital ink besides Wacom Ink Layer Language **[WILL]**.
The previous version of WILL did not support the storage of sensor data samples for digital ink (e.g., timestamps, (x,y)-coordinates, or pressure values).
WILL 3.0 gives the ability to store ink sensor samples along with the visual representation of digital ink as well as semantic metadata.
As a result it is now possible to make a loss-less conversion of the Universal Ink Data format to other existing formats.
### Natural
Digital ink has to look natural and similar to real ink.
To ensure that the visual appearance of the digital ink can be shared across platforms, WILL 3.0 contains all relevant data to present ink in a consistent way across all platforms.
By using WILL particle ink rasterization, natural brushes can be configured to create artwork, as illustrated in *Figure 1*.
![Artwork created with raster / particle ink.](media/overview_artwork.png)
*Figure 1: Artwork created with raster / particle ink.*
### Active
Mobile apps, Cloud application, or Cloud services have become a part of modern IT infrastructures.
Thus, modern data formats need to address issues including:
* Unique identifiable IDs for devices
* Streaming capability for partial updates of ink data
* Document size reduction
* Support for commonly used Web Standards such as JSON
![Active.](media/overview_active.png)
*Figure 2: Active Ink.*
### Meta Data and Semantics
There are three types of metadata:
- Descriptive
- Structural
- Administrative
*Descriptive metadata* are typically used for discovery and identification, as information used to search and locate an object such as title, author, subject, keyword, and publisher.
WILL offers metadata for the description of Document and Author in the ink document.
*Structural metadata* give a description of how the components of an object are organised.
The metadata for ink can be used to describe the structure of ink documents.
Finally, *administrative metadata* give information to help manage the source.
They refer to the technical information including file type or when and how the file was created.
Two sub-types of administrative metadata are *rights management metadata* and *preservation metadata*.
Rights management metadata explain intellectual property rights, while preservation metadata contain information that is needed to preserve and save a resource.
*Semantic metadata* is slowly becoming the differentiator in the vocabulary of many vendors.
Semantics is the study of meaning.
As it applies to technology and unstructured content, it represents the ability to extract meaning from words, phrases, sentences, and larger units of text that provide the context within content, and is manually applied or automatically generated as semantic metadata to describe the object.
Semantic metadata is typically leveraged to improve search, but any application that uses metadata can achieve significant benefits through the generation or application of semantic metadata.
Thus, WILL metadata is based on established metadata for document and author descriptions and defines its own semantic metadata for ink.
### Sensor Data and Biometrics
Another important objective in the design of the Universal Ink Model is to support the capture of sensor data from ink devices.
For example, sensor data is used in the context of handwriting analysis, as well as signature capture and verification.
Some ink devices provide additional information *(see Figure 3)* that in most use cases is considered less important and may not be supported by all makes or types of devices.
This includes:
* **Pressure** - the force applied to the nib of the pen
* **Inclination** - the angle between the pen barrel and vertical
* **Orientation** - the plain-direction of the pen from the nib
* **Rotation** - the rotation of the barrel during signing
![Overview ink sensor channels.](media/overview_ink_device_sensor_channels.png)
*Figure 3: Overview ink sensor channels.*
The forensic character of the data is of paramount importance, and means that the data-collection philosophy differs in many respects from competing signature technologies.
A key principle is that during the collection of the signature, the software stores the data exactly as it is supplied by the device.
Each type of data (e.g. position, time, pressure, etc.) is collected with metric information which describes the units being used by the device, and this is stored with the raw point data to allow the conversion to true units when required.
The advantage of this is that the accuracy of the information is determined by the device and cannot be compromised by the conversion process.
In addition to the pen-data, contextual data is collected and stored with the signature.
This includes:
* The name of the signatory
* The date and time at which the signature was given
* The reason for signing
* The make and type of digitizer being used
* The type and version of the digitizer driver being used
* The type and version of the operating system of the client PC being used
* The Network Interface Card address of the PC
The objective is to store sensor data and the characteristics of the ink device alongside the visual representation of the digital ink.
## Technology
The WILL technology is designed to be a platform-independent inking engine, providing the most relevant capabilities:
- **Ink Geometry Pipeline and Rendering** - Converts sensor data from an input device into a geometry which is rendered by a platform-specific rendering engine
- **Ink Serialization** - Exchanges the rendering results, the collected sensor data, and relevant metadata; the Universal Ink Format is used to serialize and de-serialize the information
- **Ink Manipulation** - Manipulates the generated geometry; the ink manipulation operations will be able to scale, move, rotate, and erase ink strokes (including exact split)
---
# Additional resources
## Sample Code
For further samples check Wacom's Developer additional samples, see [https://github.com/Wacom-Developer](https://github.com/Wacom-Developer)
## Documentation
For further details on using the SDK see [WILL SDK for ink documentation](http://developer-docs.wacom.com/sdk-for-ink/)
The API Reference is available directly in the downloaded SDK.
## Support
If you experience issues with the technology components, please see related [FAQs](http://developer-docs.wacom.com/faqs)
For further support file a ticket in our **Developer Support Portal** described here: [Request Support](http://developer-docs.wacom.com/faqs/docs/q-support/support)
## Developer Community
Join our developer community:
- [LinkedIn - Wacom for Developers](https://www.linkedin.com/company/wacom-for-developers/)
- [Twitter - Wacom for Developers](https://twitter.com/Wacomdevelopers)
## License
This sample code is licensed under the [MIT License](https://choosealicense.com/licenses/mit/)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,64 +0,0 @@
{
"name": "digital-ink",
"version": "1.5.0",
"productName": "WILL SDK for ink",
"productVersion": "3.0.5",
"description": "WILL™ SDK for ink supports a variety of input technologies and generates the highest quality, most attractive digital ink outputs via these modules: Path generation and smoothing, Rasterizer, Manipulation and Serialization",
"main": "digital-ink-min.cjs",
"module": "./digital-ink-min.js",
"exports": {
".": {
"node": {
"import": "./digital-ink-min.cjs.mjs",
"require": "./digital-ink-min.cjs"
},
"browser": {
"import": "./digital-ink-min.mjs"
},
"default": "./digital-ink-min.js"
},
"./web-integrator": {
"node": {
"import": "./web-integrator/web-integrator.mjs",
"require": "./web-integrator/web-integrator.cjs"
},
"default": "./web-integrator/web-integrator.js"
}
},
"dependencies": {
"canvas": "^2.9.1",
"clipper-lib": "^6.4.2",
"gl": "^5.0.0",
"gl-matrix": "^3.4.3",
"js-ext": "../../wacom/js-ext",
"js-md5": "^0.7.3",
"jszip": "^3.9.1",
"long": "^5.2.0",
"poly2tri": "^1.5.0",
"protobufjs": "^6.11.2",
"rbush": "^3.0.1",
"systeminformation": "^5.11.9"
},
"engines": {
"node": ">=10.0.0"
},
"files": [
"*.*",
"web-integrator/**",
"workers/**"
],
"keywords": [
"wacom",
"ink",
"canvas",
"rasterization",
"universal-ink-model"
],
"repository": "https://github.com/orgs/Wacom-Developer",
"author": "Wacom Co., Ltd",
"homepage": "https://developer.wacom.com",
"bugs": {
"url": "https://developer.wacom.com/developer-dashboard/support"
},
"license": "Wacom INK SDK Evaluation Agreement"
}

View File

@ -1 +0,0 @@
"use strict";class e{static DEPENDENCIES_SRC="/node_modules";get dependenciesESM(){return{quickselect:`${this.src}/quickselect/index.js`,rbush:`${this.src}/rbush/index.js`,long:`${this.src}/long/index.js`,"gl-matrix":`${this.src}/gl-matrix/esm/index.js`,"js-ext":`${this.src}/js-ext/js-ext-min.mjs`,"digital-ink":`${this.src}/digital-ink/digital-ink-min.mjs`}}get devDependenciesESM(){return Object.assign({},this.dependenciesESM,{"js-ext":`${this.src}/js-ext/js-ext.mjs`,"digital-ink":`${this.src}/digital-ink/digital-ink.mjs`})}get dependenciesUMD(){return{"clipper-lib":`${this.src}/clipper-lib/clipper.js`,poly2tri:`${this.src}/poly2tri/dist/poly2tri.min.js`,protobufjs:`${this.src}/protobufjs/dist/protobuf.min.js`,"js-md5":`${this.src}/js-md5/build/md5.min.js`,jszip:`${this.src}/jszip/dist/jszip.min.js`,rbush:`${this.src}/rbush/rbush.js`,long:`${this.src}/long/umd/index.js`,"gl-matrix":`${this.src}/gl-matrix/gl-matrix.js`,"js-ext":`${this.src}/js-ext/js-ext-min.js`,"digital-ink":`${this.src}/digital-ink/digital-ink-min.js`}}get devDependenciesUMD(){return Object.assign({},this.dependenciesUMD,{poly2tri:`${this.src}/poly2tri/dist/poly2tri.js`,protobufjs:`${this.src}/protobufjs/dist/protobuf.js`,"js-md5":`${this.src}/js-md5/src/md5.js`,jszip:`${this.src}/jszip/dist/jszip.js`,"js-ext":`${this.src}/js-ext/js-ext.js`,"digital-ink":`${this.src}/digital-ink/digital-ink.js`})}constructor(t=!0,i=""){this.cdn=t||"function"==typeof DedicatedWorkerGlobalScope,this.src=i+e.DEPENDENCIES_SRC}build(){return this.dependencies||(e.dev?this.cdn?this.dependencies=Object.assign({},this.devDependenciesUMD):this.dependencies=Object.assign({},this.devDependenciesUMD,this.devDependenciesESM):this.cdn?this.dependencies=Object.assign({},this.dependenciesUMD):this.dependencies=Object.assign({},this.dependenciesUMD,this.dependenciesESM)),this.dependencies}include(e={}){this.dependencies=Object.assign(this.build(),e)}integrate(){if(this.build(),this.cdn)if("function"==typeof DedicatedWorkerGlobalScope)Object.values(this.dependencies).forEach((e=>self.importScripts(e)));else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main or worker thread!");Object.values(this.dependencies).forEach((e=>document.write(`<script type="text/javascript" src="${e}"><\/script>`)))}else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main thread!");{let e={imports:this.dependencies},t=document.createElement("script");t.setAttribute("type","importmap"),t.textContent=JSON.stringify(e,0,4),document.currentScript?document.currentScript.after(t):document.head.appendChild(t)}}}static linkWorkers(...e){for(let t of e){let e=t.buildWorkerURL().split(location.host).last,i=document.createElement("link");i.setAttribute("rel","modulepreload"),i.setAttribute("href",e),document.head.appendChild(i)}}static integrate(t){new e(!0,t).integrate()}static integrateECMA6(t,i){let s=new e(!1,i);s.include(t),s.integrate()}static getCDNImports(t){return new e(!0,t).build()}}module.exports=e;

View File

@ -1 +0,0 @@
var DigitalInkWebIntegrator=function(){"use strict";function e(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function t(e,t){for(var i=0;i<t.length;i++){var n=t[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}var i,n,s,c=function(){function i(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";e(this,i),this.cdn=t||"function"==typeof DedicatedWorkerGlobalScope,this.src=n+i.DEPENDENCIES_SRC}var n,s,c;return n=i,s=[{key:"dependenciesESM",get:function(){return{quickselect:"".concat(this.src,"/quickselect/index.js"),rbush:"".concat(this.src,"/rbush/index.js"),long:"".concat(this.src,"/long/index.js"),"gl-matrix":"".concat(this.src,"/gl-matrix/esm/index.js"),"js-ext":"".concat(this.src,"/js-ext/js-ext-min.mjs"),"digital-ink":"".concat(this.src,"/digital-ink/digital-ink-min.mjs")}}},{key:"devDependenciesESM",get:function(){return Object.assign({},this.dependenciesESM,{"js-ext":"".concat(this.src,"/js-ext/js-ext.mjs"),"digital-ink":"".concat(this.src,"/digital-ink/digital-ink.mjs")})}},{key:"dependenciesUMD",get:function(){return{"clipper-lib":"".concat(this.src,"/clipper-lib/clipper.js"),poly2tri:"".concat(this.src,"/poly2tri/dist/poly2tri.min.js"),protobufjs:"".concat(this.src,"/protobufjs/dist/protobuf.min.js"),"js-md5":"".concat(this.src,"/js-md5/build/md5.min.js"),jszip:"".concat(this.src,"/jszip/dist/jszip.min.js"),rbush:"".concat(this.src,"/rbush/rbush.js"),long:"".concat(this.src,"/long/umd/index.js"),"gl-matrix":"".concat(this.src,"/gl-matrix/gl-matrix.js"),"js-ext":"".concat(this.src,"/js-ext/js-ext-min.js"),"digital-ink":"".concat(this.src,"/digital-ink/digital-ink-min.js")}}},{key:"devDependenciesUMD",get:function(){return Object.assign({},this.dependenciesUMD,{poly2tri:"".concat(this.src,"/poly2tri/dist/poly2tri.js"),protobufjs:"".concat(this.src,"/protobufjs/dist/protobuf.js"),"js-md5":"".concat(this.src,"/js-md5/src/md5.js"),jszip:"".concat(this.src,"/jszip/dist/jszip.js"),"js-ext":"".concat(this.src,"/js-ext/js-ext.js"),"digital-ink":"".concat(this.src,"/digital-ink/digital-ink.js")})}},{key:"build",value:function(){return this.dependencies||(i.dev?this.cdn?this.dependencies=Object.assign({},this.devDependenciesUMD):this.dependencies=Object.assign({},this.devDependenciesUMD,this.devDependenciesESM):this.cdn?this.dependencies=Object.assign({},this.dependenciesUMD):this.dependencies=Object.assign({},this.dependenciesUMD,this.dependenciesESM)),this.dependencies}},{key:"include",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.dependencies=Object.assign(this.build(),e)}},{key:"integrate",value:function(){if(this.build(),this.cdn)if("function"==typeof DedicatedWorkerGlobalScope)Object.values(this.dependencies).forEach((function(e){return self.importScripts(e)}));else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main or worker thread!");Object.values(this.dependencies).forEach((function(e){return document.write('<script type="text/javascript" src="'.concat(e,'"><\/script>'))}))}else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main thread!");var e={imports:this.dependencies},t=document.createElement("script");t.setAttribute("type","importmap"),t.textContent=JSON.stringify(e,0,4),document.currentScript?document.currentScript.after(t):document.head.appendChild(t)}}}],c=[{key:"linkWorkers",value:function(){for(var e=arguments.length,t=new Array(e),i=0;i<e;i++)t[i]=arguments[i];for(var n=0,s=t;n<s.length;n++){var c=s[n],r=c.buildWorkerURL().split(location.host).last,o=document.createElement("link");o.setAttribute("rel","modulepreload"),o.setAttribute("href",r),document.head.appendChild(o)}}},{key:"integrate",value:function(e){new i(!0,e).integrate()}},{key:"integrateECMA6",value:function(e,t){var n=new i(!1,t);n.include(e),n.integrate()}},{key:"getCDNImports",value:function(e){return new i(!0,e).build()}}],s&&t(n.prototype,s),c&&t(n,c),Object.defineProperty(n,"prototype",{writable:!1}),i}();return s="/node_modules",(n="DEPENDENCIES_SRC")in(i=c)?Object.defineProperty(i,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):i[n]=s,c}();

View File

@ -1 +0,0 @@
class e{static DEPENDENCIES_SRC="/node_modules";get dependenciesESM(){return{quickselect:`${this.src}/quickselect/index.js`,rbush:`${this.src}/rbush/index.js`,long:`${this.src}/long/index.js`,"gl-matrix":`${this.src}/gl-matrix/esm/index.js`,"js-ext":`${this.src}/js-ext/js-ext-min.mjs`,"digital-ink":`${this.src}/digital-ink/digital-ink-min.mjs`}}get devDependenciesESM(){return Object.assign({},this.dependenciesESM,{"js-ext":`${this.src}/js-ext/js-ext.mjs`,"digital-ink":`${this.src}/digital-ink/digital-ink.mjs`})}get dependenciesUMD(){return{"clipper-lib":`${this.src}/clipper-lib/clipper.js`,poly2tri:`${this.src}/poly2tri/dist/poly2tri.min.js`,protobufjs:`${this.src}/protobufjs/dist/protobuf.min.js`,"js-md5":`${this.src}/js-md5/build/md5.min.js`,jszip:`${this.src}/jszip/dist/jszip.min.js`,rbush:`${this.src}/rbush/rbush.js`,long:`${this.src}/long/umd/index.js`,"gl-matrix":`${this.src}/gl-matrix/gl-matrix.js`,"js-ext":`${this.src}/js-ext/js-ext-min.js`,"digital-ink":`${this.src}/digital-ink/digital-ink-min.js`}}get devDependenciesUMD(){return Object.assign({},this.dependenciesUMD,{poly2tri:`${this.src}/poly2tri/dist/poly2tri.js`,protobufjs:`${this.src}/protobufjs/dist/protobuf.js`,"js-md5":`${this.src}/js-md5/src/md5.js`,jszip:`${this.src}/jszip/dist/jszip.js`,"js-ext":`${this.src}/js-ext/js-ext.js`,"digital-ink":`${this.src}/digital-ink/digital-ink.js`})}constructor(t=!0,i=""){this.cdn=t||"function"==typeof DedicatedWorkerGlobalScope,this.src=i+e.DEPENDENCIES_SRC}build(){return this.dependencies||(e.dev?this.cdn?this.dependencies=Object.assign({},this.devDependenciesUMD):this.dependencies=Object.assign({},this.devDependenciesUMD,this.devDependenciesESM):this.cdn?this.dependencies=Object.assign({},this.dependenciesUMD):this.dependencies=Object.assign({},this.dependenciesUMD,this.dependenciesESM)),this.dependencies}include(e={}){this.dependencies=Object.assign(this.build(),e)}integrate(){if(this.build(),this.cdn)if("function"==typeof DedicatedWorkerGlobalScope)Object.values(this.dependencies).forEach((e=>self.importScripts(e)));else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main or worker thread!");Object.values(this.dependencies).forEach((e=>document.write(`<script type="text/javascript" src="${e}"><\/script>`)))}else{if("undefined"==typeof document)throw new Error("Integration failed. Supported env is browser - main thread!");{let e={imports:this.dependencies},t=document.createElement("script");t.setAttribute("type","importmap"),t.textContent=JSON.stringify(e,0,4),document.currentScript?document.currentScript.after(t):document.head.appendChild(t)}}}static linkWorkers(...e){for(let t of e){let e=t.buildWorkerURL().split(location.host).last,i=document.createElement("link");i.setAttribute("rel","modulepreload"),i.setAttribute("href",e),document.head.appendChild(i)}}static integrate(t){new e(!0,t).integrate()}static integrateECMA6(t,i){let s=new e(!1,i);s.include(t),s.integrate()}static getCDNImports(t){return new e(!0,t).build()}}export{e as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -17,10 +17,14 @@ class StuCaptDialog {
this.config.sizeMode = "stu";
}
this.config.strokeColor = config.strokeColor ?? "#0202FE";
this.config.strokeSize = config.strokeSize ?? 6;
this.config.showWait = config.showWait ?? true;
this.config.stuDevice = config.stuDevice;
} else {
this.config = {showWait:true, sizeMode:"stu"};
this.config = {showWait:true, sizeMode:"stu", strokeColor:"#0202FE", strokeSize:6 };
}
this.mPenData = Array();
@ -36,40 +40,14 @@ class StuCaptDialog {
* @param {string} - Reason for signing.
* @param {IntegrityType} - Hash method to maintain the signature integrity. None by default.
* @param {Hash} - Hash of an attached document. None by default.
* @param {string} - osInfo, string indicating the OS.
* @param {string} - nicInfo.
**/
async open(sigObj, who, why, extraData, integrityType, documentHash) {
this.sigObj = sigObj;
if (who) {
this.who = who;
} else {
this.who = 'Customer';
}
if (why) {
this.why = why;
} else {
this.why = 'Confirmed';
}
this.extraData = extraData;
if (integrityType) {
this.integrityType = integrityType;
} else {
this.integrityType = Module.KeyType.None;
}
if (documentHash) {
this.documentHash = documentHash;
} else {
this.documentHash = new Module.Hash(Module.HashType.None);
}
if (!this.currentDevice) {
async open(sigObj, who, why, where, extraData, integrityType, documentHash, osInfo, nicInfo) {
if (!this.config.stuDevice) {
let devices = await com.WacomGSS.STU.UsbDevice.requestDevices();
if (devices.length > 0) {
this.currentDevice = devices[0];
this.config.stuDevice = devices[0];
} else {
throw "No STU devices found";
}
@ -86,8 +64,12 @@ class StuCaptDialog {
this.mTablet.setEncryptionHandler2(this.config.encryption.encryptionHandler2);
}
}
await this.mTablet.usbConnect(this.currentDevice);
try {
await this.mTablet.usbConnect(this.config.stuDevice);
} catch (e) {
alert("STU Device not found");
}
this.mCapability = await this.mTablet.getCapability();
this.mInformation = await this.mTablet.getInformation();
this.mInkThreshold = await this.mTablet.getInkThreshold();
@ -156,25 +138,23 @@ class StuCaptDialog {
//this.config.borderColor = "#cccccc";
this.config.source = {mouse:false, touch:false, pen:false, stu:true},
this.sigCaptDialog = new SigCaptDialog(this.config);
this.config.will = this.sigCaptDialog.config.will;
this.sigCaptDialog.getCaptureData = this.getCaptureData.bind(this);
this.sigCaptDialog.addEventListener("clear", this.onClearBtn.bind(this));
this.sigCaptDialog.addEventListener("cancel", this.onCancelBtn.bind(this));
this.sigCaptDialog.addEventListener("ok", this.onOkBtn.bind(this));
await this.sigCaptDialog.open(this.sigObj, this.who, this.why, this.extraData, this.integrityType, this.documentHash);
await this.sigCaptDialog.open(sigObj, who, why, where, extraData, integrityType, documentHash, osInfo, "", nicInfo);
//store the background image in order to be reuse it when clear the screen
//store the background image in order for it to be reused when the screen is cleared
let canvas = await this.drawImageToCanvas(this.sigCaptDialog.createScreenImage(useColor));
let ctx = canvas.getContext("2d");
this.mDeviceBackgroundImage = com.WacomGSS.STU.Protocol.ProtocolHelper.resizeAndFlatten(canvas, 0, 0, canvasWidth, canvasHeight,
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode, com.WacomGSS.STU.Protocol.ProtocolHelper.Scale.Stretch, "white", false, false);
// Initialize the screen
await this.clearScreen();
this.mCapability.screenWidth, this.mCapability.screenHeight, this.mEncodingMode, com.WacomGSS.STU.Protocol.ProtocolHelper.Scale.Stretch, "white", false, false);
if (this.config.encryption) {
if ((this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.EncryptionStatus)) ||
(await com.WacomGSS.STU.Protocol.ProtocolHelper.supportsEncryption(this.mTablet.getProtocol()))) {
await this.mTablet.startCapture(this.config.encryption.sessionID);
(await com.WacomGSS.STU.Protocol.ProtocolHelper.supportsEncryption(this.mTablet.getProtocol()))) {
await this.mTablet.startCapture(this.config.encryption.sessionID);
this.mIsEncrypted = true;
}
}
@ -183,14 +163,22 @@ class StuCaptDialog {
if (useColor) {
let htc = await this.mTablet.getHandwritingThicknessColor();
let components = this.hexToRgb(this.config.will.color);
let components = this.hexToRgb(this.config.strokeColor);
htc.penColor = this.rgb3216(components.r, components.g, components.b);
htc.penThickness = this.config.strokeSize;
await this.mTablet.setHandwritingThicknessColor(htc);
}
const reportCountLengths = this.mTablet.getReportCountLengths();
if (reportCountLengths[com.WacomGSS.STU.Protocol.ReportId.RenderingMode_$LI$()] !== undefined) {
await this.mTablet.setRenderingMode(com.WacomGSS.STU.Protocol.RenderingMode.WILL);
}
// Enable the pen data on the screen (if not already)
await this.mTablet.setInkingMode(com.WacomGSS.STU.Protocol.InkingMode.On);
// Initialize the screen
await this.clearScreen();
}
rgb3216(r, g, b) {
@ -261,6 +249,7 @@ class StuCaptDialog {
async clearScreen() {
this.sigCaptDialog.stopCapture();
await this.mTablet.setClearScreen();
if ((this.config.showWait) &&
(this.mTablet.isSupported(com.WacomGSS.STU.Protocol.ReportId.StartImageDataArea_$LI$()))) {
@ -321,7 +310,6 @@ class StuCaptDialog {
}
async onOkBtn() {
await this.getCaptureData();
await this.disconnect();
this.onOkListeners.forEach(listener => listener());
}
@ -363,24 +351,22 @@ class StuCaptDialog {
// transition to down we save the button pressed
this.mBtnIndex = btnIndex;
if (this.mBtnIndex == -1) {
// We have put the pen down outside a buttom.
// We have put the pen down outside a button.
// Treat it as part of the signature.
this.mPenData.push(penData);
var downEvent = new PointerEvent("pointerdown", {
pointerId: 1,
pointerType: "pen",
pointerType: "stu",
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
pressure: penData.pressure/this.mCapability.tabletMaxPressure
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
buttons: 1
});
const point = window.DigitalInk.InkBuilder.createPoint(downEvent);
point.timestamp = penData.timeCount;
this.sigCaptDialog.draw("begin", point);
this.sigCaptDialog.stopTimeOut();
this.startDown = Date.now();
//downEvent.timeStamp = penData.timeCount;
this.sigCaptDialog.onDown(downEvent);
}
} else {
// hover point
@ -397,35 +383,35 @@ class StuCaptDialog {
} else {
var upEvent = new PointerEvent("pointerup", {
pointerId: 1,
pointerType: "pen",
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
pressure: penData.pressure/this.mCapability.tabletMaxPressure
});
const point = window.DigitalInk.InkBuilder.createPoint(upEvent);
point.timestamp = penData.timeCount;
this.sigCaptDialog.draw("end", point);
this.mPenData.push(penData);
this.sigCaptDialog.startTimeOut();
this.sigCaptDialog.addTimeOnSurface(Date.now() - this.startDown);
}
} else {
// continue inking
var moveEvent = new PointerEvent("pointermove", {
pointerId: 1,
pointerType: "pen",
pointerType: "stu",
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
buttons: 1
});
//upEvent.timeStamp = penData.timeCount;
this.sigCaptDialog.onUp(upEvent);
this.mPenData.push(penData);
}
} else {
// continue inking
if (this.mBtnIndex == -1) {
var moveEvent = new PointerEvent("pointermove", {
pointerId: 1,
pointerType: "stu",
isPrimary: true,
clientX: pt.x,
clientY: pt.y,
pressure: penData.pressure/this.mCapability.tabletMaxPressure,
buttons: 1
});
const point = window.DigitalInk.InkBuilder.createPoint(moveEvent);
point.timestamp = penData.timeCount;
this.sigCaptDialog.draw("move", point);
this.mPenData.push(penData);
//moveEvent.timeStamp = penData.timeCount;
this.sigCaptDialog.onMove(moveEvent);
this.mPenData.push(penData);
}
}
}
this.mIsDown = isDown;
@ -434,7 +420,7 @@ class StuCaptDialog {
/**
* Generate the signature from the raw data.
**/
async getCaptureData() {
getCaptureData() {
//Create Stroke Data
let strokeVector = new Module.StrokeVector();
let currentStroke = new Module.PointVector();
@ -485,7 +471,8 @@ class StuCaptDialog {
'device_pixels_per_m_x': 100000,
'device_pixels_per_m_y': 100000,
'device_origin_X': 0,
'device_origin_Y': 1
'device_origin_Y': 1,
'device_unit_pixels': false
}
var uid2;
@ -500,24 +487,39 @@ class StuCaptDialog {
uid2 = 0;
}
var digitizerInfo = "STU;'"+this.mInformation.modelName+"';"+this.mInformation.firmwareMajorVersion+"."+((parseInt(this.mInformation.firmwareMinorVersion) >> 4) & 0x0f)+"."+(parseInt(this.mInformation.firmwareMinorVersion) & 0x0f)+";"+uid2;
var nicInfo = "";
var timeResolution = 1000;
var who = this.who;
var why = this.why;
var where = "";
const digitizerInfo = "STU;'"+this.mInformation.modelName+"';"+this.mInformation.firmwareMajorVersion+"."+((parseInt(this.mInformation.firmwareMinorVersion) >> 4) & 0x0f)+"."+(parseInt(this.mInformation.firmwareMinorVersion) & 0x0f)+";"+uid2;
const timeResolution = 1000;
await this.sigObj.generateSignature(who, why, where, this.integrityType, this.documentHash, strokeVector, device, digitizerInfo, nicInfo, timeResolution);
// put the extra data
if (this.extraData) {
for (const data of this.extraData) {
this.sigObj.setExtraData(data.name, data.value);
}
}
strokeVector.delete();
currentStroke.delete();
const myPromise = new Promise((resolve, reject) => {
try {
const promise = this.sigCaptDialog.sigObj.generateSignature(this.sigCaptDialog.signatory, this.sigCaptDialog.reason, this.sigCaptDialog.where, this.sigCaptDialog.integrityType, this.sigCaptDialog.documentHash, strokeVector, device, this.sigCaptDialog.osInfo, digitizerInfo, this.sigCaptDialog.nicInfo, timeResolution);
promise.then((value) => {
if (value) {
// put the extra data
if (this.extraData) {
for (const data of this.extraData) {
this.sigObj.setExtraData(data.name, data.value);
}
}
}
strokeVector.delete();
currentStroke.delete();
resolve(value);
});
promise.catch(error => {
strokeVector.delete();
currentStroke.delete();
reject(error);
});
} catch (exception) {
strokeVector.delete();
currentStroke.delete();
reject(exception);
}
});
return myPromise;
}
drawImageToCanvas(src){

View File

@ -1,5 +1,13 @@
/* touch-action: none; is required to make pen works fine with WILL */
/*#signatureWindow {touch-action: none;}*/
body {
-webkit-user-select: none;
-webkit-touch-callout: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/*touch-action: none;*/
}
#modal-background {
position: absolute;
@ -27,4 +35,4 @@
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
}

View File

@ -1,14 +0,0 @@
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
settings:
bootstrap: _bootstrap.php
error_level: E_ALL & ~E_WARNING & ~E_NOTICE & ~E_USER_DEPRECATED
actor_suffix: Tester
extensions:
enabled:
- Codeception\Extension\RunFailed
#- Codeception\Extension\Recorder

View File

@ -15,7 +15,7 @@
}],
"type": "project",
"require": {
"php": "^7.3|^8.0",
"php": "^8.1|^8.3",
"ext-curl": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
@ -28,45 +28,47 @@
"ext-simplexml": "*",
"ext-xsl": "*",
"ext-zip": "*",
"davidepastore/codice-fiscale": "^0.6.0",
"davidepastore/codice-fiscale": "^0.9.1",
"devcode-it/ical-easy-reader": "dev-main",
"digitick/sepa-xml": "^2.1",
"dragonmantank/cron-expression": "^1.0",
"ezyang/htmlpurifier": "^4.8",
"filp/whoops": "^2.1",
"filp/whoops": "^2.15.0",
"greenlion/php-sql-parser": "^4.5",
"guzzlehttp/guzzle": "^7.0.1",
"ifsnop/mysqldump-php": "^2.3",
"illuminate/database": "^8.0",
"intervention/image": "^2.3",
"jurosh/pdf-merge": "^2.1",
"league/csv": "9.7.0",
"league/csv": "^9.7.0",
"league/oauth2-client": "^2.6",
"league/oauth2-google": "^3.0",
"league/oauth2-google": "^4.0",
"league/flysystem": "^3.0",
"league/flysystem-ftp": "^3.0",
"maximebf/debugbar": "^1.15",
"monolog/monolog": "^1.22",
"mpdf/mpdf": "^v8.0.10",
"mpociot/vat-calculator": "^2.3",
"owasp/csrf-protector-php": "^1.0",
"phpmailer/phpmailer": "^6.0",
"respect/validation": "^1.1",
"servo/fluidxml": "^1.21",
"respect/validation": "^2.0",
"servo/fluidxml": "^2.0",
"slim/flash": "^0.4.0",
"spipu/html2pdf": "^5.0",
"symfony/filesystem": "^4.0",
"symfony/finder": "^4.0",
"spipu/html2pdf": "^5.0.0",
"symfony/filesystem": "^5.0",
"symfony/finder": "^5.0",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-php70": "^1.8",
"symfony/translation": "^4.0",
"symfony/var-dumper": "^4.0",
"symfony/var-dumper": "^5.0",
"thenetworg/oauth2-azure": "^2.0",
"voku/stringy": "~6.0",
"voku/stringy": "^6.0.0",
"wdog/sdd_ita": "dev-master",
"willdurand/geocoder": "^4.2"
},
"require-dev": {
"codeception/codeception": "^4.0",
"friendsofphp/php-cs-fixer": "^3.4"
"friendsofphp/php-cs-fixer": "^3.53",
"rector/rector": "^1.0"
},
"autoload": {
"psr-4": {
@ -111,6 +113,8 @@
"Modules\\Impostazioni\\": ["modules/impostazioni/custom/src/", "modules/impostazioni/src/"],
"Modules\\Partitario\\": ["modules/partitario/custom/src/", "modules/partitario/src/"],
"Modules\\StatoEmail\\": ["modules/stato_email/custom/src/", "modules/stato_email/src/"],
"Modules\\FileAdapters\\": ["modules/adattatori_archiviazione/custom/src/", "modules/adattatori_archiviazione/src/"],
"Plugins\\AssicurazioneCrediti\\": ["plugins/assicurazione_crediti/custom/src/", "plugins/assicurazione_crediti/src/"],
"Plugins\\ExportFE\\": ["plugins/exportFE/custom/src/", "plugins/exportFE/src/"],
"Plugins\\ImportFE\\": ["plugins/importFE/custom/src/", "plugins/importFE/src/"],
"Plugins\\ReceiptFE\\": ["plugins/receiptFE/custom/src/", "plugins/receiptFE/src/"],
@ -139,13 +143,13 @@
],
"config": {
"sort-packages": true,
"optimize-autoloader": false,
"optimize-autoloader": true,
"apcu-autoloader": true,
"minimum-stability": "dev",
"prefer-stable": true,
"platform-check": false,
"platform": {
"php": "8.0.17"
"php": "8.3.7"
},
"allow-plugins": {
"kylekatarnls/update-helper": true

158
composer_74.json Normal file
View File

@ -0,0 +1,158 @@
{
"name": "devcode-it/openstamanager",
"description": "Gestionale open-source per assistenza tecnica e fatturazione elettronica",
"license": "GPL-3.0",
"keywords": [
"gestionale",
"assistenza tecnica",
"fatturazione elettronica",
"open-source"
],
"homepage": "https://www.openstamanager.com/",
"authors": [{
"name": "DevCode s.r.l.",
"email": "info@openstamanager.com"
}],
"type": "project",
"require": {
"php": "^7.4|^8.0",
"ext-curl": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-intl": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-pdo": "*",
"ext-simplexml": "*",
"ext-xsl": "*",
"ext-zip": "*",
"davidepastore/codice-fiscale": "^0.9.1",
"devcode-it/ical-easy-reader": "dev-main",
"digitick/sepa-xml": "^2.1",
"dragonmantank/cron-expression": "^1.0",
"ezyang/htmlpurifier": "^4.8",
"filp/whoops": "^2.15.0",
"greenlion/php-sql-parser": "^4.5",
"guzzlehttp/guzzle": "^7.0.1",
"ifsnop/mysqldump-php": "^2.3",
"illuminate/database": "^8.0",
"intervention/image": "^2.3",
"jurosh/pdf-merge": "^2.1",
"league/csv": "^9.7.0",
"league/oauth2-client": "^2.6",
"league/oauth2-google": "^4.0",
"league/flysystem": "^3.0",
"league/flysystem-ftp": "^3.0",
"maximebf/debugbar": "^1.15",
"monolog/monolog": "^1.22",
"mpdf/mpdf": "^v8.0.10",
"mpociot/vat-calculator": "^2.3",
"owasp/csrf-protector-php": "^1.0",
"phpmailer/phpmailer": "^6.0",
"respect/validation": "^2.0",
"servo/fluidxml": "^1.21",
"slim/flash": "^0.4.0",
"spipu/html2pdf": "^5.0.0",
"symfony/filesystem": "^5.0",
"symfony/finder": "^5.0",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-php70": "^1.8",
"symfony/translation": "^4.0",
"symfony/var-dumper": "^5.0",
"thenetworg/oauth2-azure": "^2.0",
"voku/stringy": "^6.0.0",
"wdog/sdd_ita": "dev-master",
"willdurand/geocoder": "^4.2"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.53",
"rector/rector": "^1.0"
},
"autoload": {
"psr-4": {
"": "src/",
"Update\\": "update/",
"Modules\\Aggiornamenti\\": ["modules/aggiornamenti/custom/src/", "modules/aggiornamenti/src/"],
"Modules\\Anagrafiche\\": ["modules/anagrafiche/custom/src/", "modules/anagrafiche/src/"],
"Modules\\AttributiCombinazioni\\": ["modules/attributi_combinazioni/custom/src/", "modules/attributi_combinazioni/src/"],
"Modules\\Backups\\": ["modules/backups/custom/src/", "modules/backups/src/"],
"Modules\\CombinazioniArticoli\\": ["modules/combinazioni_articoli/custom/src/", "modules/combinazioni_articoli/src/"],
"Modules\\Emails\\": ["modules/emails/custom/src/", "modules/emails/src/"],
"Modules\\Articoli\\": ["modules/articoli/custom/src/", "modules/articoli/src/"],
"Modules\\Checklists\\": ["modules/checklists/custom/src/", "modules/checklists/src/"],
"Modules\\Ritenute\\": ["modules/ritenute/custom/src/", "modules/ritenute/src/"],
"Modules\\RitenuteContributi\\": ["modules/ritenute_contributi/custom/src/", "modules/ritenute_contributi/src/"],
"Modules\\Rivalse\\": ["modules/rivalse/custom/src/", "modules/rivalse/src/"],
"Modules\\Newsletter\\": ["modules/newsletter/custom/src/", "modules/newsletter/src/"],
"Modules\\ListeNewsletter\\": ["modules/liste_newsletter/custom/src/", "modules/liste_newsletter/src/"],
"Modules\\Iva\\": ["modules/iva/custom/src/", "modules/iva/src/"],
"Modules\\DDT\\": ["modules/ddt/custom/src/", "modules/ddt/src/"],
"Modules\\Fatture\\": ["modules/fatture/custom/src/", "modules/fatture/src/"],
"Modules\\ListiniCliente\\": ["modules/listini_cliente/custom/src/", "modules/listini_cliente/src/"],
"Modules\\Ordini\\": ["modules/ordini/custom/src/", "modules/ordini/src/"],
"Modules\\Preventivi\\": ["modules/preventivi/custom/src/", "modules/preventivi/src/"],
"Modules\\Contratti\\": ["modules/contratti/custom/src/", "modules/contratti/src/"],
"Modules\\Interventi\\": ["modules/interventi/custom/src/", "modules/interventi/src/"],
"Modules\\Pagamenti\\": ["modules/pagamenti/custom/src/", "modules/pagamenti/src/"],
"Modules\\Statistiche\\": ["modules/statistiche/custom/src/", "modules/statistiche/src/"],
"Modules\\Scadenzario\\": ["modules/scadenzario/custom/src/", "modules/scadenzario/src/"],
"Modules\\PrimaNota\\": ["modules/primanota/custom/src/", "modules/primanota/src/"],
"Modules\\Utenti\\": ["modules/utenti/custom/src/", "modules/utenti/src/"],
"Modules\\StatoServizi\\": ["modules/stato_servizi/custom/src/", "modules/stato_servizi/src/"],
"Modules\\StatiIntervento\\": ["modules/stati_intervento/custom/src/", "modules/stati_intervento/src/"],
"Modules\\StatiPreventivo\\": ["modules/stati_preventivo/custom/src/", "modules/stati_preventivo/src/"],
"Modules\\StatiContratto\\": ["modules/stati_contratto/custom/src/", "modules/stati_contratto/src/"],
"Modules\\StatiOrdine\\": ["modules/stati_ordine/custom/src/", "modules/stati_ordine/src/"],
"Modules\\TipiIntervento\\": ["modules/tipi_intervento/custom/src/", "modules/tipi_intervento/src/"],
"Modules\\CategorieDocumentali\\": ["modules/categorie_documenti/custom/src/", "modules/categorie_documenti/src/"],
"Modules\\PianiSconto\\": ["modules/piano_sconto/custom/src/", "modules/piano_sconto/src/"],
"Modules\\Impianti\\": ["modules/impianti/custom/src/", "modules/impianti/src/"],
"Modules\\Importazione\\": ["modules/import/custom/src/", "modules/import/src/"],
"Modules\\Impostazioni\\": ["modules/impostazioni/custom/src/", "modules/impostazioni/src/"],
"Modules\\Partitario\\": ["modules/partitario/custom/src/", "modules/partitario/src/"],
"Modules\\StatoEmail\\": ["modules/stato_email/custom/src/", "modules/stato_email/src/"],
"Modules\\FileAdapters\\": ["modules/adattatori_archiviazione/custom/src/", "modules/adattatori_archiviazione/src/"],
"Plugins\\AssicurazioneCrediti\\": ["plugins/assicurazione_crediti/custom/src/", "plugins/assicurazione_crediti/src/"],
"Plugins\\ExportFE\\": ["plugins/exportFE/custom/src/", "plugins/exportFE/src/"],
"Plugins\\ImportFE\\": ["plugins/importFE/custom/src/", "plugins/importFE/src/"],
"Plugins\\ReceiptFE\\": ["plugins/receiptFE/custom/src/", "plugins/receiptFE/src/"],
"Plugins\\DichiarazioniIntento\\": ["plugins/dichiarazioni_intento/custom/src/", "plugins/dichiarazioni_intento/src/"],
"Plugins\\PianificazioneInterventi\\": ["plugins/pianificazione_interventi/custom/src/", "plugins/pianificazione_interventi/src/"],
"Plugins\\PianificazioneFatturazione\\": ["plugins/pianificazione_fatturazione/custom/src/", "plugins/pianificazione_fatturazione/src/"],
"Plugins\\StatisticheArticoli\\": ["plugins/statistiche_articoli/custom/src/", "plugins/statistiche_articoli/src/"],
"Plugins\\ListinoClienti\\": ["plugins/listino_clienti/custom/src/", "plugins/listino_clienti/src/"],
"Plugins\\ListinoFornitori\\": ["plugins/listino_fornitori/custom/src/", "plugins/listino_fornitori/src/"],
"Plugins\\ComponentiImpianti\\": ["plugins/componenti/custom/src/", "plugins/componenti/src/"],
"Plugins\\PresentazioniBancarie\\": ["plugins/presentazioni_bancarie/custom/src/", "plugins/presentazioni_bancarie/src/"]
},
"files": [
"lib/functions.php",
"lib/common.php",
"lib/helpers.php",
"lib/util.php",
"lib/deprecated.php"
]
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/wdog/sdd_ita"
}
],
"config": {
"sort-packages": true,
"optimize-autoloader": true,
"apcu-autoloader": true,
"minimum-stability": "dev",
"prefer-stable": true,
"platform-check": false,
"platform": {
"php": "8.0.29"
},
"allow-plugins": {
"kylekatarnls/update-helper": true
}
}
}

View File

@ -22,9 +22,9 @@ $db_host = '|host|';
$db_username = '|username|';
$db_password = '|password|';
$db_name = '|database|';
//$port = '|port|';
// $port = '|port|';
$db_options = [
//'sort_buffer_size' => '2M',
// 'sort_buffer_size' => '2M',
];
// Percorso della cartella di backup

View File

@ -17,6 +17,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use Models\Plugin;
include_once __DIR__.'/core.php';
if (!empty($id_record) && !empty($id_module)) {
@ -33,43 +35,55 @@ include_once base_dir().'/actions.php';
// Widget in alto
echo '{( "name": "widgets", "id_module": "'.$id_module.'", "position": "top", "place": "controller" )}';
$segmenti = $dbo->FetchArray('SELECT `id` FROM `zz_segments` WHERE `id_module` = '.prepare($id_module));
if ($segmenti) {
$segmenti = Modules::getSegments($id_module);
if (empty($segmenti)) {
echo '
<div class="alert alert-warning">
<i class="fa fa-warning-circle"></i> '.tr("Questo gruppo di utenti non ha i permessi per visualizzare nessun segmento di questo modulo").'.
</div>';
}
}
// Lettura eventuali plugins modulo da inserire come tab
echo '
<div class="nav-tabs-custom">
<ul class="nav nav-tabs pull-right" id="tabs" role="tablist">
<li class="pull-left active header">
<a data-toggle="tab" href="#tab_0">
<i class="'.$structure['icon'].'"></i> '.$structure['title'];
<div class="nav-tabs-custom">
<ul class="nav nav-tabs" id="tabs" role="tablist">
<li class="pull-left active nav-item header">
<a data-widget="tab" href="#tab_0" class="nav-link">
<i class="'.$structure['icon'].'"></i> '.$structure->getTranslation('title');
// Pulsante "Aggiungi" solo se il modulo è di tipo "table" e se esiste il template per la popup
if ($structure->hasAddFile() && $structure->permission == 'rw') {
echo '
<button type="button" class="btn btn-primary" data-toggle="modal" data-title="'.tr('Aggiungi').'..." data-href="add.php?id_module='.$id_module.'&id_plugin='.$id_plugin.'"><i class="fa fa-plus"></i></button>';
<button type="button" class="btn btn-primary" data-widget="modal" data-title="'.tr('Aggiungi').'..." data-href="add.php?id_module='.$id_module.'&id_plugin='.$id_plugin.'"><i class="fa fa-plus"></i></button>';
}
echo '
</a>
</li>';
</a>
</li>';
$plugins = $dbo->fetchArray('SELECT id, title FROM zz_plugins WHERE idmodule_to='.prepare($id_module)." AND position='tab_main' AND enabled = 1");
$plugins = Plugin::where('idmodule_to', $id_module)->where('position', 'tab_main')->where('enabled', 1)->get();
// Tab dei plugin
foreach ($plugins as $plugin) {
echo '
<li>
<a data-toggle="tab" href="#tab_'.$plugin['id'].'" id="link-tab_'.$plugin['id'].'">'.$plugin['title'].'</a>
</li>';
<li class="nav-item">
<a class="nav-link" data-widget="tab" href="#tab_'.$plugin->id.'" id="link-tab_'.$plugin->id.'">'.$plugin->getTranslation('title').'</a>
</li>';
}
echo '
</ul>
<div class="tab-content">
<div id="tab_0" class="tab-pane active">';
</ul>
<div class="tab-content">
<div id="tab_0" class="tab-pane active">';
include base_dir().'/include/manager.php';
echo '
</div>';
</div>';
// Plugin
$module_record = $record;
@ -77,34 +91,34 @@ foreach ($plugins as $plugin) {
$record = $module_record;
echo '
<div id="tab_'.$plugin['id'].'" class="tab-pane">';
<div id="tab_'.$plugin->id.'" class="tab-pane">';
$id_plugin = $plugin['id'];
$id_plugin = $plugin->id;
include base_dir().'/include/manager.php';
include base_dir().'/include/manager.php';
echo '
</div>';
echo '
</div>';
}
$record = $module_record;
echo '
</div>
</div>';
</div>
</div>';
redirectOperation($id_module, isset($id_parent) ? $id_parent : $id_record);
redirectOperation($id_module, !empty($id_parent) ? $id_parent : $id_record);
// Interfaccia per la modifica dell'ordine e della visibilità delle colonne (Amministratore)
if ($user->is_admin && string_contains($module['option'], '|select|')) {
echo '
<a class="btn btn-xs btn-default pull-right" style="margin-top: -1.25rem;" onclick="modificaColonne(this)">
<i class="fa fa-th-list"></i> '.tr('Modifica colonne').'
<a class="btn btn-xs btn-default justify-content-end" style="margin-top: -1.25rem;" onclick="modificaColonne(this)">
<i class="fa fa-th-list"></i> '.tr('Modifica colonne').'
</a><div class="clearfix" >&nbsp;</div>
<script>
function modificaColonne(button) {
openModal("'.tr('Modifica colonne').'", globals.rootdir + "/actions.php?id_module=" + globals.id_module + "&op=aggiorna_colonne")
openModal("'.tr('Modifica colonne').'", globals.rootdir + "/actions.php?id_module=" + globals.id_module + "&op=aggiorna_colonne")
}
</script>';
}

View File

@ -18,7 +18,7 @@
*/
// Rimozione header X-Powered-By
header_remove('X-Powered-By');
// header_remove('X-Powered-By');
// Impostazioni di configurazione PHP
date_default_timezone_set('Europe/Rome');
@ -30,7 +30,7 @@ if (version_compare(phpversion(), $minimum) < 0) {
<p>Stai utilizzando la versione PHP '.phpversion().', non compatibile con OpenSTAManager.</p>
<p>Aggiorna PHP alla versione >= '.$minimum.'.</p>';
exit();
exit;
}
// Caricamento delle impostazioni personalizzabili
@ -54,13 +54,16 @@ $docroot = DOCROOT;
$rootdir = ROOTDIR;
$baseurl = BASEURL;
// Sicurezza della sessioni
ini_set('session.cookie_samesite', 'lax');
ini_set('session.use_trans_sid', '0');
ini_set('session.use_only_cookies', '1');
// Controllo che le intestazioni non siano già state inviate.
if (!headers_sent()) {
// Sicurezza della sessioni
ini_set('session.cookie_samesite', 'lax');
ini_set('session.use_trans_sid', '0');
ini_set('session.use_only_cookies', '1');
session_set_cookie_params(0, base_path(), null, isHTTPS(true));
session_start();
session_set_cookie_params(0, base_path(), null, isHTTPS(true));
session_start();
}
// Lettura della configurazione
$config = App::getConfig();
@ -69,7 +72,7 @@ $config = App::getConfig();
if (!empty($config['redirectHTTPS']) && !isHTTPS(true)) {
header('HTTP/1.1 301 Moved Permanently');
header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
exit();
exit;
}
/* GESTIONE DEGLI ERRORI */
@ -161,7 +164,6 @@ $formatter = !empty($config['formatter']) ? $config['formatter'] : [];
$translator = trans();
$translator->addLocalePath(base_dir().'/locale');
$translator->addLocalePath(base_dir().'/modules/*/locale');
$translator->setLocale($lang, $formatter);
// Individuazione di versione e revisione del progetto
$version = Update::getVersion();
@ -181,7 +183,7 @@ if (!$continue && getURLPath() != slashes(base_path().'/index.php') && !Permissi
}
redirect(base_path().'/index.php');
exit();
exit;
}
/* INIZIALIZZAZIONE GENERALE */
@ -246,8 +248,8 @@ if (!API\Response::isAPIRequest()) {
$plugin = Plugins::getCurrent();
$structure = isset($plugin) ? $plugin : $module;
$id_module = $module ? $module['id'] : null;
$id_plugin = $plugin ? $plugin['id'] : null;
$id_module = $module ? $module->id : null;
$id_plugin = $plugin ? $plugin->id : null;
$user = Auth::user();
@ -300,3 +302,13 @@ $list = array_merge($files, $custom_files);
foreach ($list as $file) {
include_once $file;
}
// Inizializzazione traduzioni
if (database()->tableExists('zz_settings') && database()->tableExists('zz_langs')) {
$id_lang = setting('Lingua');
Models\Locale::setDefault($id_lang);
Models\Locale::setPredefined();
$lang = Models\Locale::find($id_lang)->language_code;
$translator->setLocale($lang, $formatter);
}

View File

@ -61,13 +61,13 @@ $handler->setFormatter($formatter);
$logger->pushHandler($handler);
// Lettura della cache
$ultima_esecuzione = Cache::pool('Ultima esecuzione del cron');
$ultima_esecuzione = Cache::find((new Cache())->getByField('title', 'Ultima esecuzione del cron', Models\Locale::getPredefined()->id));
$data = $ultima_esecuzione->content;
$in_esecuzione = Cache::pool('Cron in esecuzione');
$cron_id = Cache::pool('ID del cron');
$in_esecuzione = Cache::find((new Cache())->getByField('title', 'Cron in esecuzione', Models\Locale::getPredefined()->id));
$cron_id = Cache::find((new Cache())->getByField('title', 'ID del cron', Models\Locale::getPredefined()->id));
$disattiva = Cache::pool('Disabilita cron');
$disattiva = Cache::find((new Cache())->getByField('title', 'Disabilita cron', Models\Locale::getPredefined()->id));
if ($disattiva->content || (in_array($_SERVER['HTTP_HOST'], ['localhost', '127.0.0.1']) && !$forza_cron_localhost)) {
return;
}
@ -107,7 +107,7 @@ while (true) {
}
// Rimozione dei log più vecchi
$database->query('DELETE FROM zz_tasks_logs WHERE DATE_ADD(created_at, INTERVAL :interval DAY) <= NOW()', [
$database->query('DELETE FROM `zz_tasks_logs` WHERE DATE_ADD(`created_at`, INTERVAL :interval DAY) <= NOW()', [
':interval' => 7,
]);
@ -139,7 +139,7 @@ while (true) {
$task->registerNextExecution($inizio_iterazione);
$task->save();
$logger->info($task->name.': data mancante', [
$logger->info($task->getTranslation('title').': data mancante', [
'timestamp' => $task->next_execution_at->toDateTimeString(),
]);
}
@ -147,7 +147,7 @@ while (true) {
// Esecuzione diretta solo nel caso in cui sia prevista
if ($task->next_execution_at->copy()->addSeconds(20)->greaterThanOrEqualTo($inizio_iterazione) && $task->next_execution_at->lessThanOrEqualTo($adesso->copy()->addseconds(20))) {
// Registrazione dell'esecuzione nei log
$logger->info($task->name.': '.$task->expression);
$logger->info($task->getTranslation('title').': '.$task->expression);
try {
$task->execute();
} catch (Exception $e) {
@ -158,12 +158,12 @@ while (true) {
'trace' => $e->getTraceAsString(),
]);
$logger->error($task->name.': errore');
$logger->error($task->getTranslation('title').': errore');
}
}
// Esecuzione mancata
elseif ($task->next_execution_at->lessThan($inizio_iterazione)) {
$logger->warning($task->name.': mancata', [
$logger->warning($task->getTranslation('title').': mancata', [
'timestamp' => $task->next_execution_at->toDateTimeString(),
]);

View File

@ -20,6 +20,7 @@
include_once __DIR__.'/core.php';
use Carbon\Carbon;
use Models\Module;
// Disabilitazione dei campi
$read_only = $structure->permission == 'r';
@ -41,19 +42,21 @@ if (!empty($id_record)) {
}
// Rimozione della condizione deleted_at IS NULL per visualizzare anche i record eliminati
if (!empty($query)) {
if (preg_match('/[`]*([a-z0-9_]*)[`]*[\.]*([`]*deleted_at[`]* IS NULL)/i', $query, $m)) {
if (preg_match('/[`]*([a-z0-9_]*)[`]*[\.]*([`]*deleted_at[`]* IS NULL)/si', $query, $m)) {
$query = str_replace(["\n", "\t"], ' ', $query);
$conditions_to_remove = [];
$condition = trim($m[0]);
if (!empty($table_name)) {
$condition = $table_name.'.'.$condition;
}
$conditions_to_remove[] = ' AND '.$condition;
$conditions_to_remove[] = $condition.' AND ';
$conditions_to_remove[] = ' AND\s*'.$condition;
$conditions_to_remove[] = $condition.'\s*AND ';
$query = str_replace($conditions_to_remove, '', $query);
foreach ($conditions_to_remove as $condition_to_remove) {
$query = preg_replace('/'.$condition_to_remove.'/si', '', $query);
}
$query = str_replace($condition, '', $query);
}
}
@ -95,41 +98,42 @@ if (empty($record) || !$has_access) {
<h3 class="box-title"><i class="fa fa-warning"></i> '.tr('Attenzione!').'</h3>
</div>
<div class="box-body">
<p>'.tr('I seguenti utenti stanno visualizzando questa pagina').':</p>
<p>'.tr('I seguenti utenti stanno consultando questa scheda').':</p>
<ul class="list">
</ul>
<p>'.tr('Prestare attenzione prima di effettuare modifiche, poichè queste potrebbero essere perse a causa di multipli salvataggi contemporanei').'.</p>
<p>'.tr('Prestare attenzione prima di effettuare modifiche, poiché queste potrebbero essere perse a causa di una sovrascrittura delle informazioni').'.</p>
</div>
</div>';
}
echo '
<div class="nav-tabs-custom">
<ul class="nav nav-tabs pull-right" id="tabs" role="tablist">
<li class="pull-left active header">
<a data-toggle="tab" href="#tab_0">
<i class="'.$structure['icon'].'"></i> '.$structure['title'];
<nav class="navbar navbar-expand navbar-light">
<ul class="navbar-nav" id="tabs">
<li class="nav-item">
<a data-widget="tab" href="#tab_0" class="nav-link">
<i class="'.$structure['icon'].'"></i> '.$structure->getTranslation('title');
// Pulsante "Aggiungi" solo se il modulo è di tipo "table" e se esiste il template per la popup
if ($structure->hasAddFile() && $structure->permission == 'rw') {
echo '
<button type="button" class="btn btn-primary" data-toggle="modal" data-title="'.tr('Aggiungi').'..." data-href="add.php?id_module='.$id_module.'&id_plugin='.$id_plugin.'"><i class="fa fa-plus"></i></button>';
<button type="button" class="btn btn-primary" data-widget="modal" data-title="'.tr('Aggiungi').'..." data-href="add.php?id_module='.$id_module.'&id_plugin='.$id_plugin.'"><i class="fa fa-plus"></i></button>';
}
echo '
</a>
</li>';
</li>
</ul>
echo '
<li class="control-sidebar-toggle">
<a style="cursor: pointer">'.tr('Plugin').'</a>
<ul class="navbar-nav ml-auto">
<li class="nav-item control-sidebar-toggle">
<a class="nav-link" style="cursor: pointer">'.tr('Plugin').'</a>
</li>
</ul>
</nav>
<div class="tab-content">
<div id="tab_0" class="tab-pane active">';
<div id="tab_0" class="tab-pane active nav-item">';
if (!empty($record['deleted_at'])) {
$operation = $dbo->fetchOne("SELECT zz_operations.created_at, username FROM zz_operations INNER JOIN zz_users ON zz_operations.id_utente = zz_users.id WHERE op='delete' AND id_module=".prepare($id_module).' AND id_record='.prepare($id_record).' ORDER BY zz_operations.created_at DESC');
@ -159,88 +163,65 @@ if (empty($record) || !$has_access) {
}
// Pulsanti di default
echo '
<div id="pulsanti">
<a class="btn btn-warning" id="back" href="'.base_path().'/controller.php?id_module='.$id_module.'">
<i class="fa fa-chevron-left"></i> '.tr("Torna all'elenco").'
</a>
echo '
<div class="pull-right">
{( "name": "button", "type": "print", "id_module": "'.$id_module.'", "id_plugin": "'.$id_plugin.'", "id_record": "'.$id_record.'" )}
<div id="pulsanti">
<a class="btn btn-default" id="back" href="'.base_path().'/controller.php?id_module='.$id_module.'">
<i class="fa fa-chevron-left"></i> '.tr("Torna all'elenco").'
</a>
{( "name": "button", "type": "email", "id_module": "'.$id_module.'", "id_plugin": "'.$id_plugin.'", "id_record": "'.$id_record.'" )}';
<div class="float-right d-none d-sm-inline">
{( "name": "button", "type": "print", "id_module": "'.$id_module.'", "id_plugin": "'.$id_plugin.'", "id_record": "'.$id_record.'" )}
if (Modules::get('Account SMS')) {
echo '
{( "name": "button", "type": "sms", "id_module": "'.$id_module.'", "id_plugin": "'.$id_plugin.'", "id_record": "'.$id_record.'" )}';
{( "name": "button", "type": "email", "id_module": "'.$id_module.'", "id_plugin": "'.$id_plugin.'", "id_record": "'.$id_record.'" )}';
if (Module::find((new Module())->getByField('title', 'Account SMS', Models\Locale::getPredefined()->id))) {
echo '
{( "name": "button", "type": "sms", "id_module": "'.$id_module.'", "id_plugin": "'.$id_plugin.'", "id_record": "'.$id_record.'" )}';
}
echo '
<div class="btn-group" id="save-buttons">
<a class="btn btn-success" id="'.(!empty($record['deleted_at']) ? 'restore' : 'save').'">
<i class="fa fa-'.(!empty($record['deleted_at']) ? 'undo' : 'check').'"></i> '.(!empty($record['deleted_at']) ? tr('Salva e ripristina') : tr('Salva')).'
<div class="btn-group" id="save-buttons">
<button type="button" class="btn btn-success" id="'.(!empty($record['deleted_at']) ? 'restore' : 'save').'">
<i class="fa fa-'.(!empty($record['deleted_at']) ? 'undo' : 'check').'"></i> '.(!empty($record['deleted_at']) ? tr('Salva e ripristina') : tr('Salva')).'
</button>
<button type="button" class="btn btn-success dropdown-toggle dropdown-icon" data-toggle="dropdown" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu" role="menu">
<a class="dropdown-item" href="#" id="'.(!empty($record['deleted_at']) ? 'restore' : 'save').'-close">
<i class="fa fa-'.(!empty($record['deleted_at']) ? 'undo' : 'check-square-o').'"></i>
'.(!empty($record['deleted_at']) ? tr('Ripristina e chiudi') : tr('Salva e chiudi')).'
</a>
<a type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</a>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="#" id="'.(!empty($record['deleted_at']) ? 'restore' : 'save').'-close">
<i class="fa fa-'.(!empty($record['deleted_at']) ? 'undo' : 'check-square-o').'"></i>
'.(!empty($record['deleted_at']) ? tr('Ripristina e chiudi') : tr('Salva e chiudi')).'
</a></li>
</ul>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
var form = $("#module-edit").find("form").first();
<script>
$(document).ready(function(){
var form = $("#module-edit").find("form").first();
// Aggiunta del submit
form.prepend(\'<button type="submit" id="submit" class="hide"></button>\');
// Aggiunta del submit
form.prepend(\'<button type="submit" id="submit" class="hide"></button>\');
$("#save").click(function(){
//submitAjax(form);
$("#save").click(function(){
//submitAjax(form);
$("#submit").trigger("click");
});
$("#save-close").on("click", function (){
form.find("[name=backto]").val("record-list");
$("#submit").trigger("click");
});';
// Pulsanti dinamici
if (!isMobile()) {
echo '
$("#pulsanti").affix({
offset: {
top: 200
}
});
if ($("#pulsanti").hasClass("affix")) {
$("#pulsanti").css("width", $("#tab_0").css("width"));
}
$("#pulsanti").on("affix.bs.affix", function(){
$("#pulsanti").css("width", $("#tab_0").css("width"));
});
$("#pulsanti").on("affix-top.bs.affix", function(){
$("#pulsanti").css("width", "100%");
});';
}
echo '
$("#submit").trigger("click");
});
</script>
<div class="clearfix"></div>
<br>';
$("#save-close").on("click", function (){
form.find("[name=backto]").val("record-list");
$("#submit").trigger("click");
});
});
</script>
<div class="clearfix"></div>
<br>';
// Pulsanti personalizzati
$buttons = $structure->filepath('buttons.php');
@ -250,18 +231,23 @@ if (empty($record) || !$has_access) {
$buttons = ob_get_clean();
echo '
<div class="pull-right" id="pulsanti-modulo">
'.$buttons.'
</div>
<div class="float-right d-none d-sm-inline" id="pulsanti-modulo">
'.$buttons.'
</div>
<div class="clearfix"></div>
<br>';
<div class="clearfix"></div>
<br>';
// Eventuale header personalizzato
$header = $structure->filepath('header.php');
if ($header) {
include_once $header;
}
}
// Contenuti del modulo
echo '
<div id="module-edit">';
<div id="module-edit">';
$path = $structure->getEditFile();
if (!empty($path)) {
@ -269,73 +255,73 @@ if (empty($record) || !$has_access) {
}
echo '
</div>
</div>';
</div>
</div>';
// Campi personalizzati
echo '
<div class="hide" id="custom_fields_top-edit">
{( "name": "custom_fields", "id_module": "'.$id_module.'", "id_record": "'.$id_record.'", "position": "top" )}
</div>
<div class="hide" id="custom_fields_top-edit_'.$id_module.'-'.$id_plugin.'">
{( "name": "custom_fields", "id_module": "'.$id_module.'", "id_record": "'.$id_record.'", "position": "top" )}
</div>
<div class="hide" id="custom_fields_bottom-edit">
{( "name": "custom_fields", "id_module": "'.$id_module.'", "id_record": "'.$id_record.'" )}
</div>
<div class="hide" id="custom_fields_bottom-edit_'.$id_module.'-'.$id_plugin.'">
{( "name": "custom_fields", "id_module": "'.$id_module.'", "id_record": "'.$id_record.'" )}
</div>
<script>
$(document).ready(function(){
let form = $("#edit-form").first();
<script>
$(document).ready(function(){
let form = $("#edit-form").first();
// Ultima sezione/campo del form
let last = form.find(".panel").last();
// Ultima sezione/campo del form
let last = form.find(".panel").last();
if (!last.length) {
last = form.find(".box").last();
}
if (!last.length) {
last = form.find(".box").last();
}
if (!last.length) {
last = form.find(".row").eq(-2);
}
if (!last.length) {
last = form.find(".row").eq(-2);
}
// Campi a inizio form
aggiungiContenuto(form, "#custom_fields_top-edit", {}, true);
// Campi a inizio form
aggiungiContenuto(form, "#custom_fields_top-edit_'.$id_module.'-'.$id_plugin.'", {}, true);
// Campi a fine form
aggiungiContenuto(last, "#custom_fields_bottom-edit", {});
});
</script>';
// Campi a fine form
aggiungiContenuto(last, "#custom_fields_bottom-edit_'.$id_module.'-'.$id_plugin.'", {});
});
</script>';
if ($structure->permission != '-' && $structure->use_notes && $user->gruppo != 'Clienti') {
echo '
<div id="tab_note" class="tab-pane">';
<div id="tab_note" class="tab-pane">';
include base_dir().'/plugins/notes.php';
echo '
</div>';
</div>';
}
if ($structure->permission != '-' && $structure->use_checklists) {
echo '
<div id="tab_checks" class="tab-pane">';
<div id="tab_checks" class="tab-pane">';
include base_dir().'/plugins/checks.php';
echo '
</div>';
</div>';
}
// Informazioni sulle operazioni
if (Auth::admin()) {
echo '
<div id="tab_info" class="tab-pane">';
<div id="tab_info" class="tab-pane">';
$operations = $dbo->fetchArray('SELECT `zz_operations`.*, `zz_users`.`username` FROM `zz_operations` JOIN `zz_users` ON `zz_operations`.`id_utente` = `zz_users`.`id` WHERE id_module = '.prepare($id_module).' AND id_record = '.prepare($id_record).' ORDER BY `created_at` DESC LIMIT 200');
$operations = $dbo->fetchArray('SELECT `zz_operations`.*, `zz_users`.`username` FROM `zz_operations` LEFT JOIN `zz_users` ON `zz_operations`.`id_utente` = `zz_users`.`id` WHERE id_module = '.prepare($id_module).' AND id_record = '.prepare($id_record).' ORDER BY `created_at` DESC LIMIT 200');
if (!empty($operations)) {
echo '
<ul class="timeline">';
<ul class="timeline">';
foreach ($operations as $operation) {
$description = $operation['op'];
@ -374,42 +360,42 @@ if (empty($record) || !$has_access) {
}
echo '
<li '.$timeline_class.'>
<div class="timeline-badge '.$color.'"><i class="fa fa-'.$icon.'"></i></div>
<div class="timeline-panel">
<div class="timeline-heading">
<div class="row">
<div class="col-md-8">
<h4 class="timeline-title">'.$description.'</h4>
</div>
<div class="col-md-4 text-right">
<p><small class="label label-default tip" title="'.Translator::timestampToLocale($operation['created_at']).'"><i class="fa fa-clock-o"></i> '.Carbon::parse($operation['created_at'])->diffForHumans().'</small></p>
<p><small class="label label-default"><i class="fa fa-user"></i> '.$operation['username'].'</small></p>
</div>
<li '.$timeline_class.'>
<div class="timeline-badge '.$color.'"><i class="fa fa-'.$icon.'"></i></div>
<div class="timeline-panel">
<div class="timeline-heading">
<div class="row">
<div class="col-md-8">
<h4 class="timeline-title">'.$description.'</h4>
</div>
<div class="col-md-4 text-right">
<p><span class="right badge badge-default tip" title="'.Translator::timestampToLocale($operation['created_at']).'"><i class="fa fa-clock-o"></i> '.Carbon::parse($operation['created_at'])->diffForHumans().'</small></p>
<p><span class="right badge badge-default"><i class="fa fa-user"></i> '.$operation['username'].'</small></p>
</div>
</div>
<div class="timeline-body">
</div>
<div class="timeline-footer">
</div>
</div>
</li>';
<div class="timeline-body">
</div>
<div class="timeline-footer">
</div>
</div>
</li>';
}
echo '
</ul>';
</ul>';
} else {
echo '
<div class="alert alert-info">
<i class="fa fa-info-circle"></i>
<b>'.tr('Informazione:').'</b> '.tr('Nessun log disponibile per questa scheda').'.
</div>';
<div class="alert alert-info">
<i class="fa fa-info-circle"></i>
<b>'.tr('Informazione:').'</b> '.tr('Nessun log disponibile per questa scheda').'.
</div>';
}
echo '
</div>';
</div>';
}
// Plugin
@ -418,34 +404,34 @@ if (empty($record) || !$has_access) {
$record = $module_record;
echo '
<div id="tab_'.$plugin['id'].'" class="tab-pane">';
<div id="tab_'.$plugin['id'].'" class="tab-pane">';
$id_plugin = $plugin['id'];
include base_dir().'/include/manager.php';
echo '
</div>';
</div>';
}
$record = $module_record;
echo '
</div>
</div>';
</div>
</div>';
}
redirectOperation($id_module, isset($id_parent) ? $id_parent : $id_record);
redirectOperation($id_module, !empty($id_parent) ? $id_parent : $id_record);
// Widget in basso
echo '{( "name": "widgets", "id_module": "'.$id_module.'", "id_record": "'.$id_record.'", "position": "right", "place": "editor" )}';
if (!empty($record)) {
echo '
<hr>
<a class="btn btn-default" href="'.base_path().'/controller.php?id_module='.$id_module.'">
<i class="fa fa-chevron-left"></i> '.tr('Indietro').'
</a>';
<hr>
<a class="btn btn-default" href="'.base_path().'/controller.php?id_module='.$id_module.'">
<i class="fa fa-chevron-left"></i> '.tr('Indietro').'
</a>';
}
echo '
@ -459,7 +445,7 @@ if ($read_only || !empty($block_edit)) {
$(document).ready(function(){
$("input, textarea, select", "section.content")'.$not.'.attr("readonly", "true");
$("select, input[type=checkbox]", "section.content")'.$not.'.prop("disabled", true);
$(".checkbox-buttons label", "section.content")'.$not.'.addClass("disabled");
$(".checkbox-buttons badge", "section.content")'.$not.'.addClass("disabled");
';
// Nascondo il plugin Note interne ai clienti
@ -506,15 +492,10 @@ if ($read_only || !empty($block_edit)) {
if(content_was_modified) {
var dialogText = "Uscire senza salvare?";
e.returnValue = dialogText;
$("#main_loading").fadeOut();
return dialogText;
}
});
window.addEventListener("unload", function(e) {
$("#main_loading").show();
});
<?php
if (!empty($advanced_sessions)) {

View File

@ -122,6 +122,9 @@ const JS = gulp.parallel(() => {
'bootstrap-maxlength/dist/bootstrap-maxlength.js',
'leaflet/dist/leaflet.js',
'leaflet-gesture-handling/dist/leaflet-gesture-handling.min.js',
'ismobilejs/dist/isMobile.min.js',
'ua-parser-js/dist/ua-parser.min.js',
'popper.js/dist/umd/popper.js',
];
for (const i in vendor) {
@ -223,15 +226,15 @@ function srcCSS() {
.pipe(gulp.dest(config.production + '/' + config.paths.css));
const themes = gulp.src([
config.development + '/' + config.paths.css + '/themes/*.{css,scss,less,styl}',
config.nodeDirectory + '/admin-lte/dist/css/skins/_all-skins.min.css',
])
.pipe(gulpIf('*.scss', sass(), gulpIf('*.less', less(), gulpIf('*.styl', stylus()))))
.pipe(autoprefixer())
.pipe(gulpIf(!config.debug, minifyCSS(config.minifiers.css)))
.pipe(concat('themes.min.css'))
.pipe(flatten())
.pipe(gulp.dest(config.production + '/' + config.paths.css));
config.development + '/' + config.paths.css + '/themes/*.{css,scss,less,styl}',
config.nodeDirectory + '/admin-lte/dist/css/adminlte.min.css',
])
.pipe(gulpIf('*.scss', sass(), gulpIf('*.less', less(), gulpIf('*.styl', stylus()))))
.pipe(autoprefixer())
.pipe(gulpIf(!config.debug, minifyCSS(config.minifiers.css)))
.pipe(concat('themes.min.css'))
.pipe(flatten())
.pipe(gulp.dest(config.production + '/' + config.paths.css));
return merge(css, print, themes);
}
@ -269,11 +272,10 @@ function wacom(){
'modules/digital-ink/digital-ink-min.js',
'common/will/tools.js',
'modules/sjcl/sjcl.js',
'sigCaptDialog/libs/stu_capture/stu-sdk.min.js',
'sigCaptDialog/libs/stu_capture/stu_capture_encryption.js',
'common/libs/signature_sdk.js',
'common/libs/signature_sdk_helper.js',
'modules/node-forge/dist/forge.min.js',
'common/libs/signature_sdk_helper.js',
'common/libs/stu-sdk.min.js',
'modules/node-forge/dist/forge.min.js',
'sigCaptDialog/sigCaptDialog.js',
'sigCaptDialog/stuCaptDialog.js'
];
@ -306,11 +308,11 @@ const fonts = gulp.parallel(() => {
'font-awesome/fonts/fontawesome-webfont.woff',
'font-awesome/fonts/fontawesome-webfont.woff2',
'font-awesome/fonts/FontAwesome.otf',
'bootstrap/dist/fonts/glyphicons-halflings-regular.eot',
'bootstrap/dist/fonts/glyphicons-halflings-regular.svg',
'bootstrap/dist/fonts/glyphicons-halflings-regular.ttf',
'bootstrap/dist/fonts/glyphicons-halflings-regular.woff',
'bootstrap/dist/fonts/glyphicons-halflings-regular.woff2',
'select2-bootstrap-theme/docs/fonts/glyphicons-halflings-regular.eot',
'select2-bootstrap-theme/docs/fonts/glyphicons-halflings-regular.svg',
'select2-bootstrap-theme/docs/fonts/glyphicons-halflings-regular.ttf',
'select2-bootstrap-theme/docs/fonts/glyphicons-halflings-regular.woff',
'select2-bootstrap-theme/docs/fonts/glyphicons-halflings-regular.woff2',
'../assets/src/css/fonts/sourcesanspro-regular-webfont.eot',
'../assets/src/css/fonts/sourcesanspro-regular-webfont.svg',
'../assets/src/css/fonts/sourcesanspro-regular-webfont.ttf',
@ -396,16 +398,16 @@ function csrf() {
function pdfjs() {
const web = gulp.src([
config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/web/**/*',
'!' + config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/web/cmaps/*',
'!' + config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/web/*.map',
'!' + config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/web/*.pdf',
config.nodeDirectory + '/pdfjs-viewer-element/dist/pdfjs-4.0.379-dist/web/**/*',
'!' + config.nodeDirectory + '/pdfjs-viewer-element/dist/pdfjs-4.0.379-dist/web/cmaps/*',
'!' + config.nodeDirectory + '/pdfjs-viewer-element/dist/pdfjs-4.0.379-dist/web/*.map',
'!' + config.nodeDirectory + '/pdfjs-viewer-element/dist/pdfjs-4.0.379-dist/web/*.pdf',
])
.pipe(gulp.dest(config.production + '/pdfjs/web'));
const build = gulp.src([
config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/build/*',
'!' + config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/build/*.map',
config.nodeDirectory + '/pdfjs-viewer-element/dist/pdfjs-4.0.379-dist/build/*',
'!' + config.nodeDirectory + '/pdfjs-viewer-element/dist/pdfjs-4.0.379-dist/build/*.map',
])
.pipe(gulp.dest(config.production + '/pdfjs/build'));
@ -463,8 +465,11 @@ function release(done) {
glob([
'**/*',
'!checksum.json',
'!database.json',
'!database_5_7.json',
'!mysql.json',
'!mysql_5_7.json',
'!mariadb_10_x.json',
'!settings.json',
'!manifest.json',
'!.idea/**',
'!.git/**',
'!.github/**',
@ -478,6 +483,7 @@ function release(done) {
'!config.inc.php',
'!psalm.xml',
'!update/structure.php',
'!update/settings.php',
'!**/*.(lock|phar|log|zip|bak|jar|txt)',
'!**/~*',
'!vendor/tecnickcom/tcpdf/examples/**',
@ -523,7 +529,14 @@ function release(done) {
archive.append(shell.exec('php update/structure.php', {
silent: true
}).stdout, {
name: 'database.json'
name: 'mysql.json'
});
// Aggiunta del file per il controllo delle impostazioni
archive.append(shell.exec('php update/settings.php', {
silent: true
}).stdout, {
name: 'settings.json'
});
// Aggiunta del commit corrente nel file REVISION

View File

@ -21,10 +21,8 @@ include_once __DIR__.'/../core.php';
if (Auth::check()) {
echo '
</div>
</div><!-- /.row -->
</section><!-- /.content -->
</aside><!-- /.content-wrapper -->
</div><!-- /.content-wrapper -->
<footer class="main-footer">
<a class="hidden-xs" href="'.tr('https://www.openstamanager.com').'" title="'.tr("Il gestionale open source per l'assistenza tecnica e la fatturazione").'." target="_blank"><strong>'.tr('OpenSTAManager').'</strong></a>
@ -78,7 +76,7 @@ if (Auth::check()) {
// Hooks
if (!$config['disable_hooks']) {
echo '
setTimeout("startHooks();", 1000);';
startHooks();';
}
// Abilitazione del cron autonoma

View File

@ -18,19 +18,20 @@
*/
include_once __DIR__.'/../core.php';
use Models\Module;
// Compatibilità per controller ed editor
$structure = Modules::get($id_module);
$structure = Module::find($id_module);
echo '
<p>'.tr('Trascina le colonne per ordinare la struttura della tabella principale, seleziona e deseleziona le colonne per renderle visibili o meno').'.</p>
<div class="sortable">';
$fields = $dbo->fetchArray('SELECT *, (SELECT GROUP_CONCAT(zz_groups.nome) FROM zz_group_view INNER JOIN zz_groups ON zz_group_view.id_gruppo = zz_groups.id WHERE zz_group_view.id_vista = zz_views.id) AS gruppi_con_accesso FROM zz_views WHERE id_module='.prepare($id_module).' ORDER BY `order` ASC');
$fields = $dbo->fetchArray('SELECT `zz_views`.*, (SELECT GROUP_CONCAT(`zz_groups_lang`.`title`) FROM `zz_group_view` INNER JOIN `zz_groups` ON `zz_group_view`.`id_gruppo` = `zz_groups`.`id` LEFT JOIN `zz_groups_lang` ON (`zz_groups`.`id` = `zz_groups_lang`.`id_record` AND `zz_groups_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `zz_group_view`.`id_vista` = `zz_views`.`id`) AS gruppi_con_accesso FROM `zz_views` LEFT JOIN `zz_views_lang` ON (`zz_views`.`id` = `zz_views_lang`.`id_record` AND `zz_views_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `id_module`='.prepare($id_module).' ORDER BY `order` ASC');
foreach ($fields as $field) {
echo '
<div class="panel panel-default clickable col-md-4" data-id="'.$field['id'].'">
<div class="panel-body no-selection">
<div class="card card-default clickable col-md-4" data-id="'.$field['id'].'">
<div class="card-body no-selection">
<input type="checkbox" name="visibile" '.($field['visible'] ? 'checked' : '').'>
<span class="text-'.($field['visible'] ? 'success' : 'danger').'">'.$field['name'].'<br><small>( '.$field['gruppi_con_accesso'].')</small></span>
@ -47,8 +48,8 @@ echo '
<script>
// Abilitazione dinamica delle colonne
$("input[name=visibile]").change(function() {
let panel = $(this).closest(".panel[data-id]");
let id = panel.data("id");
let card = $(this).closest(".card[data-id]");
let id = card.data("id");
// Aggiornamento effettivo
$.post(globals.rootdir + "/actions.php", {
@ -59,7 +60,7 @@ echo '
});
// Aggiornamento grafico
let text = panel.find("span");
let text = card.find("span");
if ($(this).is(":checked")) {
text.removeClass("text-danger")
.addClass("text-success");
@ -82,7 +83,7 @@ echo '
dropOnEmpty: true,
scroll: true,
})[0].addEventListener("sortupdate", function(e) {
let order = $(".panel[data-id]").toArray().map(a => $(a).data("id"))
let order = $(".card[data-id]").toArray().map(a => $(a).data("id"))
console.log(order);
$.post(globals.rootdir + "/actions.php", {

View File

@ -17,24 +17,27 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
$result['idarticolo'] = isset($result['idarticolo']) ? $result['idarticolo'] : null;
$result['idarticolo'] ??= null;
$qta_minima = 0;
$id_listino = $dbo->selectOne('an_anagrafiche', 'id_listino', ['idanagrafica' => $options['idanagrafica']])['id_listino'];
// Articolo
$database = database();
$articolo = $database->fetchOne('SELECT mg_articoli.id,
mg_fornitore_articolo.id AS id_dettaglio_fornitore,
IFNULL(mg_fornitore_articolo.codice_fornitore, mg_articoli.codice) AS codice,
IFNULL(mg_fornitore_articolo.descrizione, mg_articoli.descrizione) AS descrizione,
IFNULL(mg_fornitore_articolo.qta_minima, 0) AS qta_minima
FROM mg_articoli
LEFT JOIN mg_fornitore_articolo ON mg_fornitore_articolo.id_articolo = mg_articoli.id AND mg_fornitore_articolo.id = '.prepare($result['id_dettaglio_fornitore']).'
WHERE mg_articoli.id = '.prepare($result['idarticolo']));
$articolo = $database->fetchOne('SELECT
`mg_articoli`.`id`,
`mg_fornitore_articolo`.`id` AS id_dettaglio_fornitore,
IFNULL(`mg_fornitore_articolo`.`codice_fornitore`, `mg_articoli`.`codice`) AS codice,
IFNULL(`mg_fornitore_articolo`.`descrizione`, `mg_articoli_lang`.`title`) AS descrizione,
IFNULL(`mg_fornitore_articolo`.`qta_minima`, 0) AS qta_minima
FROM `mg_articoli`
LEFT JOIN `mg_articoli_lang` ON (`mg_articoli_lang`.`id_record` = `mg_articoli`.`id` AND `mg_articoli_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).')
LEFT JOIN `mg_fornitore_articolo` ON `mg_fornitore_articolo`.`id_articolo` = `mg_articoli`.`id` AND `mg_fornitore_articolo`.`id` = '.prepare($result['id_dettaglio_fornitore']).'
WHERE
`mg_articoli`.`id` = '.prepare($result['idarticolo']));
$qta_minima = $articolo['qta_minima'];
echo '
echo '
{[ "type": "select", "disabled":"1", "label": "'.tr('Articolo').'", "name": "idarticolo", "value": "'.$result['idarticolo'].'", "ajax-source": "articoli", "select-options": '.json_encode($options['select-options']['articoli']).' ]}
<script>
@ -53,7 +56,7 @@ $qta_minima = $articolo['qta_minima'];
<input type="hidden" name="blocca_minimo_vendita" value="'.setting('Bloccare i prezzi inferiori al minimo di vendita').'">';
// Selezione impianto per gli Interventi
if ($module['name'] == 'Interventi') {
if ($module->getTranslation('title') == 'Attività') {
echo '
<div class="row">
<div class="col-md-12">
@ -180,12 +183,6 @@ $("#idarticolo").on("change", function() {
});
});
$("#idsede").on("change", function() {
updateSelectOption("idsede_partenza", $(this).val());
session_set("superselect,idsede_partenza", $(this).val(), 0);
$("#idarticolo").selectReset();
});
$(document).on("change", "input[name^=qta], input[name^=prezzo_unitario], input[name^=sconto]", function() {
verificaPrezzoArticolo();
verificaScontoArticolo();
@ -388,7 +385,7 @@ function verificaPrezzoArticolo() {
let table = $(".table-prezzi");
if (prezzo_anagrafica) {
table.append(`<tr><td class="pr_anagrafica"><small>'.($options['dir'] == 'uscita' ? tr('Prezzo listino') : tr('Netto cliente')).': '.Plugins::link(($options['dir'] == 'uscita' ? 'Listino Fornitori' : 'Netto Clienti'), $result['idarticolo'], tr('Visualizza'), null, '').'</small></td><td align="right" class="pr_anagrafica"><small>` + prezzo_anagrafica.toLocale() + ` ` + globals.currency + `</small></td>`);
table.append(`<tr><td class="pr_anagrafica"><small>'.($options['dir'] == 'uscita' ? tr('Prezzo listino') : tr('Netto cliente')).': '.Plugins::link($options['dir'] == 'uscita' ? 'Listino Fornitori' : 'Netto Clienti', $result['idarticolo'], tr('Visualizza'), null, '').'</small></td><td align="right" class="pr_anagrafica"><small>` + prezzo_anagrafica.toLocale() + ` ` + globals.currency + `</small></td>`);
let tr = $(".pr_anagrafica").parent();
if (prezzo_unitario == prezzo_anagrafica.toFixed(2)) {
@ -504,7 +501,7 @@ function verificaScontoArticolo() {
}
div.css("margin-top", "-13px");
div.html(`<small class="label label-info">'.tr('Sconto suggerito').': ` + sconto_previsto.toLocale() + `%<button type="button" class="btn btn-xs btn-info pull-right" onclick="aggiornaScontoArticolo()"><i class="fa fa-refresh"></i> '.tr('Aggiorna').'</button></small>`);
div.html(` <span class="right badge badge-info">'.tr('Sconto suggerito').': ` + sconto_previsto.toLocale() + `%<button type="button" class="btn btn-xs btn-info pull-right" onclick="aggiornaScontoArticolo()"><i class="fa fa-refresh"></i> '.tr('Aggiorna').'</button></small>`);
}
/**
@ -612,7 +609,7 @@ function verificaMinimoVendita() {
div.css("margin-top", "-13px");
if (prezzo_unitario < minimo_vendita) {
if (input("blocca_minimo_vendita").get() == "0") {
div.html(`<p class="label-warning">'.tr('Attenzione:<br>valore inferiore al prezzo minimo di vendita ').'` + minimo_vendita.toLocale() + ` ` + globals.currency + `</p>`);
div.html(`<p class="badge-warning">'.tr('Attenzione:<br>valore inferiore al prezzo minimo di vendita ').'` + minimo_vendita.toLocale() + ` ` + globals.currency + `</p>`);
}
} else {
div.html("");
@ -620,7 +617,7 @@ function verificaMinimoVendita() {
if (prezzo_unitario <= minimo_vendita) {
if (input("blocca_minimo_vendita").get() == "1") {
prezzo_unitario_input.val(minimo_vendita);
div.html(`<p class="label-warning">'.tr('Attenzione:<br>non è possibile inserire un prezzo inferiore al prezzo minimo di vendita ').'` + minimo_vendita.toLocale() + ` ` + globals.currency + `</p>`);
div.html(`<p class="badge-warning">'.tr('Attenzione:<br>non è possibile inserire un prezzo inferiore al prezzo minimo di vendita ').'` + minimo_vendita.toLocale() + ` ` + globals.currency + `</p>`);
}
}
}

View File

@ -18,7 +18,7 @@
*/
// Informazioni aggiuntive per Fatture
if ($module['name'] != 'Fatture di acquisto' && $module['name'] != 'Fatture di vendita') {
if ($module->getTranslation('title') != 'Fatture di acquisto' && $module->getTranslation('title') != 'Fatture di vendita') {
return;
}
@ -48,25 +48,25 @@ $calcolo_ritenuta_acconto = $calcolo_ritenuta_acconto ?: setting("Metodologia ca
echo '
<div class="row">';
// Cassa previdenziale
echo '
// Cassa previdenziale
echo '
<div class="col-md-4">
{[ "type": "select", "label": "'.tr('Cassa previdenziale').'", "name": "id_rivalsa_inps", "value": "'.$id_rivalsa_inps.'", "values": "query=SELECT * FROM co_rivalse", "help": "'.(($options['dir'] == 'entrata') ? setting('Tipo Cassa Previdenziale') : null).'" ]}
</div>';
// Ritenuta d'acconto
echo '
// Ritenuta d'acconto
echo '
<div class="col-md-4">
{[ "type": "select", "label": "'.tr("Ritenuta d'acconto").'", "name": "id_ritenuta_acconto", "value": "'.$id_ritenuta_acconto.'", "values": "query=SELECT * FROM co_ritenutaacconto" ]}
</div>';
// Calcola ritenuta d'acconto su
echo '
// Calcola ritenuta d'acconto su
echo '
<div class="col-md-4">
{[ "type": "select", "label": "'.tr("Calcola ritenuta d'acconto su").'", "name": "calcolo_ritenuta_acconto", "value": "'.$calcolo_ritenuta_acconto.'", "values": "list=\"IMP\":\"Imponibile\", \"IMP+RIV\":\"Imponibile + rivalsa\""]}
</div>';
echo '
echo '
</div>';
if (!empty($options['show-ritenuta-contributi']) || empty($options['hide_conto'])) {

View File

@ -32,11 +32,11 @@ echo '
</div>
</div>';
if ($module['name'] == 'Preventivi' && $options['op'] == 'manage_descrizione') {
if ($module->getTranslation('title') == 'Preventivi' && $options['op'] == 'manage_descrizione') {
echo '
<div class="row">
<div class="col-md-6">
{[ "type": "checkbox", "label": "'.tr('Utilizza come titolo del gruppo').'", "name": "is_titolo", "value": '.json_encode($result['is_titolo']).', "help": "'.tr('').'" ]}
{[ "type": "checkbox", "label": "'.tr('Utilizza come titolo del gruppo').'", "name": "is_titolo", "value": '.json_encode($result['is_titolo']).', "help": "'.tr(' ').'" ]}
</div>
</div>';
}

View File

@ -17,11 +17,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
$result['id'] = isset($result['id']) ? $result['id'] : null;
// Form di inserimento riga documento
echo '
<form action="'.base_path().'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'" method="post">
<form action="'.base_path().'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'" method="post" id="submit-form">
<input type="hidden" name="id_plugin" value="'.$id_plugin.'">
<input type="hidden" name="hash" value="tab_'.$id_plugin.'">
<input type="hidden" name="backto" value="record-edit">
@ -41,10 +39,26 @@ echo '
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary pull-right"><i class="fa '.$icon.'"></i> '.$button.'</button>
<button type="button" class="btn btn-primary pull-right" onclick="submitForm()"><i class="fa '.$icon.'"></i> '.$button.'</button>
</div>
</div>
</form>';
echo '
<script>$(document).ready(init)</script>';
echo '
<script>
function submitForm() {
var form = input("#submit-form");
salvaForm("#submit-form", {
id_module: "'.$id_module.'",
id_record: "'.$id_record.'",
}).then(function(response) {
form.getElement().closest("div[id^=bs-popup").modal("hide");
caricaRighe(null);
});
return false;
}
</script>';

View File

@ -17,6 +17,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use Models\Module;
use Modules\Contratti\Stato as StatoContratto;
use Modules\DDT\Stato;
use Modules\Fatture\Stato as StatoFattura;
use Modules\Fatture\Tipo as Tipofattura;
use Modules\Ordini\Stato as StatoOrdine;
use Plugins\ListinoFornitori\DettaglioFornitore;
// Inizializzazione
@ -28,22 +34,25 @@ if (empty($documento)) {
// Informazioni utili
$dir = $documento->direzione;
$original_module = Modules::get($documento->module);
$original_module = Module::find((new Module())->getByField('title', $documento->module, Models\Locale::getPredefined()->id));
$name = !empty($documento_finale) ? $documento_finale->module : $options['module'];
$final_module = Modules::get($name);
$id_segment = $_SESSION['module_'.$final_module['id']]['id_segment'];
$final_module = Module::find((new Module())->getByField('title', $name, Models\Locale::getPredefined()->id));
$id_segment = $_SESSION['module_'.$final_module->id]['id_segment'];
// IVA predefinita
$id_iva = $id_iva ?: setting('Iva predefinita');
$righe_totali = $documento->getRighe();
if ($final_module['name'] == 'Interventi') {
$id_module_interventi = (new Module())->getByField('title', 'Attività', Models\Locale::getPredefined()->id);
$id_module_ordini_f = (new Module())->getByField('title', 'Ordini fornitore', Models\Locale::getPredefined()->id);
if ($final_module->id == $id_module_interventi) {
$righe = $righe_totali->where('is_descrizione', '=', 0)
->where('qta_rimanente', '>', 0);
$righe_evase = $righe_totali->where('is_descrizione', '=', 0)
->where('qta_rimanente', '=', 0);
} elseif ($final_module['name'] == 'Ordini fornitore') {
} elseif ($final_module->id == $id_module_ordini_f) {
$righe = $righe_totali;
$righe_evase = collect();
} else {
@ -58,7 +67,7 @@ if ($righe->isEmpty()) {
return;
}
$link = !empty($documento_finale) ? base_path().'/editor.php?id_module='.$final_module['id'].'&id_record='.$documento_finale->id : base_path().'/controller.php?id_module='.$final_module['id'];
$link = !empty($documento_finale) ? base_path().'/editor.php?id_module='.$final_module->id.'&id_record='.$documento_finale->id : base_path().'/controller.php?id_module='.$final_module->id;
echo '
<form action="'.$link.'" method="post">
@ -73,11 +82,11 @@ echo '
// Creazione fattura dal documento
if (!empty($options['create_document'])) {
echo '
<div class="box box-warning">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Nuovo documento').'</h3>
<div class="card card-warning">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Nuovo documento').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<div class="row">
<input type="hidden" name="create_document" value="on" />
@ -87,33 +96,32 @@ if (!empty($options['create_document'])) {
</div>';
// Opzioni aggiuntive per le Fatture
if (in_array($final_module['name'], ['Fatture di vendita', 'Fatture di acquisto'])) {
$stato_predefinito = $database->fetchOne("SELECT id FROM co_statidocumento WHERE descrizione = 'Bozza'");
$id_module_fatt_vendita = (new Module())->getByField('title', 'Fatture di vendita', Models\Locale::getPredefined()->id);
$id_module_fatt_acquisto = (new Module())->getByField('title', 'Fatture di acquisto', Models\Locale::getPredefined()->id);
$id_module_ddt_vendita = (new Module())->getByField('title', 'Ddt in uscita', Models\Locale::getPredefined()->id);
$id_module_ddt_acquisto = (new Module())->getByField('title', 'Ddt in entrata', Models\Locale::getPredefined()->id);
if (in_array($final_module->id, [$id_module_fatt_vendita, $id_module_fatt_acquisto])) {
$stato_predefinito = (new StatoFattura())->getByField('title', 'Bozza', Models\Locale::getPredefined()->id);
$fatt_differita_acquisto = (new Tipofattura())->getByField('title', 'Fattura differita di acquisto', Models\Locale::getPredefined()->id);
$fatt_differita_vendita = (new Tipofattura())->getByField('title', 'Fattura differita di vendita', Models\Locale::getPredefined()->id);
if (!empty($options['reversed'])) {
$idtipodocumento = $dbo->selectOne('co_tipidocumento', ['id'], [
'dir' => $dir,
'descrizione' => 'Nota di credito',
])['id'];
} elseif (in_array($original_module['name'], ['Ddt di vendita', 'Ddt di acquisto'])) {
$idtipodocumento = $dbo->selectOne('co_tipidocumento', ['id'], [
'dir' => $dir,
'descrizione' => ($dir == 'uscita' ? 'Fattura differita di acquisto' : 'Fattura differita di vendita'),
])['id'];
$idtipodocumento = database()->fetchOne('SELECT `co_tipidocumento`.`id` FROM `co_tipidocumento` LEFT JOIN `co_tipidocumento_lang` ON (`co_tipidocumento_lang`.`id_record` = `co_tipidocumento`.`id` AND `co_tipidocumento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `title` = "Nota di credito" AND `dir` = \''.$dir.'\'')['id'];
} elseif (in_array($original_module->id, [$id_module_ddt_vendita, $id_module_ddt_acquisto])) {
$idtipodocumento = database()->fetchOne('SELECT `co_tipidocumento`.`id` FROM `co_tipidocumento` LEFT JOIN `co_tipidocumento_lang` ON (`co_tipidocumento_lang`.`id_record` = `co_tipidocumento`.`id` AND `co_tipidocumento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `co_tipidocumento`.`id` = '.($dir == 'uscita' ? $fatt_differita_acquisto : $fatt_differita_vendita).' AND `dir` = \''.$dir.'\'')['id'];
} else {
$idtipodocumento = $dbo->selectOne('co_tipidocumento', ['id'], [
'predefined' => 1,
'dir' => $dir,
])['id'];
$idtipodocumento = database()->fetchOne('SELECT `co_tipidocumento`.`id` FROM `co_tipidocumento` LEFT JOIN `co_tipidocumento_lang` ON (`co_tipidocumento_lang`.`id_record` = `co_tipidocumento`.`id` AND `co_tipidocumento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `dir` = \''.$dir.'\' AND `predefined` = 1')['id'];
}
$id_bozza = (new StatoFattura())->getByField('title', 'Bozza', Models\Locale::getPredefined()->id);
$id_emessa = (new StatoFattura())->getByField('title', 'Emessa', Models\Locale::getPredefined()->id);
echo '
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT * FROM co_statidocumento WHERE descrizione IN (\'Emessa\', \'Bozza\')", "value": "'.$stato_predefinito['id'].'"]}
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT `co_statidocumento`.`id` as id, `co_statidocumento_lang`.`title` as descrizione FROM `co_statidocumento` LEFT JOIN `co_statidocumento_lang` ON (`co_statidocumento`.`id` = `co_statidocumento_lang`.`id_record` AND `co_statidocumento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `co_statidocumento`.`id` IN ('.$id_bozza.', '.$id_emessa.')", "value": "'.$stato_predefinito.'"]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Tipo documento').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT id, CONCAT(codice_tipo_documento_fe, \' - \', descrizione) AS descrizione FROM co_tipidocumento WHERE enabled = 1 AND dir = '.prepare($dir).' ORDER BY codice_tipo_documento_fe", "value": "'.$idtipodocumento.'" ]}
{[ "type": "select", "label": "'.tr('Tipo documento').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT `co_tipidocumento`.`id`, CONCAT(`codice_tipo_documento_fe`, \' - \', `title`) AS descrizione FROM `co_tipidocumento` LEFT JOIN `co_tipidocumento_lang` ON (`co_tipidocumento`.`id` = `co_tipidocumento_lang`.`id_record` AND `co_tipidocumento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `enabled` = 1 AND `dir` = '.prepare($dir).' ORDER BY `codice_tipo_documento_fe`", "value": "'.$idtipodocumento.'" ]}
</div>
<div class="col-md-6">
@ -122,10 +130,10 @@ if (!empty($options['create_document'])) {
}
// Opzioni aggiuntive per gli Interventi
elseif ($final_module['name'] == 'Interventi') {
elseif ($final_module->getTranslation('title') == 'Attività') {
echo '
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato_intervento", "required": 1, "values": "query=SELECT idstatointervento AS id, descrizione, colore AS _bgcolor_ FROM in_statiintervento WHERE deleted_at IS NULL AND is_completato = 0 ORDER BY descrizione" ]}
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato_intervento", "required": 1, "values": "query=SELECT `in_statiintervento`.`id`, `in_statiintervento_lang`.`title` as `descrizione`, `colore` AS _bgcolor_ FROM `in_statiintervento` LEFT JOIN `in_statiintervento_lang` ON (`in_statiintervento`.`id` = `in_statiintervento_lang`.`id_record` AND `in_statiintervento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `deleted_at` IS NULL AND `is_completato` = 0 ORDER BY `title`" ]}
</div>
<div class="col-md-6">
@ -134,36 +142,36 @@ if (!empty($options['create_document'])) {
}
// Opzioni aggiuntive per i Contratti
elseif ($final_module['name'] == 'Contratti') {
$stato_predefinito = $database->fetchOne("SELECT * FROM co_staticontratti WHERE descrizione = 'Bozza'");
elseif ($final_module->getTranslation('title') == 'Contratti') {
$stato_predefinito = (new StatoContratto())->getByField('title', 'Bozza', Models\Locale::getPredefined()->id);
echo '
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT id, descrizione FROM co_staticontratti", "value": "'.$stato_predefinito['id'].'" ]}
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT `co_staticontratti`.`id`, `co_staticontratti_lang`.`title` AS descrizione FROM `co_staticontratti` LEFT JOIN `co_staticontratti_lang` ON (`co_staticontratti`.`id` = `co_staticontratti_lang`.`id_record` AND `co_staticontratti_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).')", "value": "'.$stato_predefinito.'" ]}
</div>';
}
// Opzioni aggiuntive per i DDT
elseif (in_array($final_module['name'], ['Ddt di vendita', 'Ddt di acquisto'])) {
$stato_predefinito = $database->fetchOne("SELECT * FROM dt_statiddt WHERE descrizione = 'Bozza'");
elseif (in_array($final_module->getTranslation('title'), ['Ddt in uscita', 'Ddt in entrata'])) {
$stato_predefinito = (new Stato())->getByField('title', 'Bozza', Models\Locale::getPredefined()->id);
echo '
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT * FROM dt_statiddt", "value": "'.$stato_predefinito['id'].'" ]}
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT `dt_statiddt`.*, `dt_statiddt_lang`.`title` AS descrizione FROM `dt_statiddt` LEFT JOIN `dt_statiddt_lang` ON (`dt_statiddt`.`id` = `dt_statiddt_lang`.`id_record` AND `dt_statiddt_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).')", "value": "'.$stato_predefinito.'" ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Causale trasporto').'", "name": "id_causale_trasporto", "required": 1, "ajax-source": "causali", "icon-after": "add|'.Modules::get('Causali')['id'].'", "help": "'.tr('Definisce la causale del trasporto').'" ]}
{[ "type": "select", "label": "'.tr('Causale trasporto').'", "name": "id_causale_trasporto", "required": 1, "ajax-source": "causali", "icon-after": "add|'.(new Module())->getByField('title', 'Causali', Models\Locale::getPredefined()->id).'", "help": "'.tr('Definisce la causale del trasporto').'" ]}
</div>';
}
// Opzioni aggiuntive per gli Ordini
elseif (in_array($final_module['name'], ['Ordini cliente', 'Ordini fornitore'])) {
$stato_predefinito = $database->fetchOne("SELECT * FROM or_statiordine WHERE descrizione = 'Bozza'");
elseif (in_array($final_module->getTranslation('title'), ['Ordini cliente', 'Ordini fornitore'])) {
$stato_predefinito = (new StatoOrdine())->getByField('title', 'Bozza', Models\Locale::getPredefined()->id);
echo '
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT * FROM or_statiordine WHERE descrizione IN(\'Bozza\', \'Accettato\', \'In attesa di conferma\', \'Annullato\')", "value": "'.$stato_predefinito['id'].'" ]}
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT * ,`or_statiordine`.`id`, `or_statiordine_lang`.`title` AS descrizione FROM `or_statiordine` LEFT JOIN `or_statiordine_lang` ON (`or_statiordine`.`id` = `or_statiordine_lang`.`id_record` AND `or_statiordine_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `title` IN(\'Bozza\', \'Accettato\', \'In attesa di conferma\', \'Annullato\')", "value": "'.$stato_predefinito.'" ]}
</div>';
}
@ -174,13 +182,13 @@ if (!empty($options['create_document'])) {
echo '
<div class="col-md-6">
{[ "type": "select", "label": "'.$tipo_anagrafica.'", "name": "idanagrafica", "required": 1, "ajax-source": "'.$ajax.'", "icon-after": "add|'.Modules::get('Anagrafiche')['id'].'|tipoanagrafica='.$tipo_anagrafica.'" ]}
{[ "type": "select", "label": "'.$tipo_anagrafica.'", "name": "idanagrafica", "required": 1, "ajax-source": "'.$ajax.'", "icon-after": "add|'.(new Module())->getByField('title', 'Anagrafiche', Models\Locale::getPredefined()->id).'|tipoanagrafica='.$tipo_anagrafica.'" ]}
</div>';
}
echo '
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "ajax-source": "segmenti", "select-options": '.json_encode(['id_module' => $final_module['id'], 'is_sezionale' => 1]).', "value": "'.$id_segment.'" ]}
{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "ajax-source": "segmenti", "select-options": '.json_encode(['id_module' => $final_module->id, 'is_sezionale' => 1]).', "value": "'.$database->selectOne('co_tipidocumento', 'id_segment', ['id' => $idtipodocumento])['id_segment'].'" ]}
</div>
</div>
</div>
@ -188,7 +196,7 @@ if (!empty($options['create_document'])) {
}
// Conto, rivalsa INPS, ritenuta d'acconto e ritenuta previdenziale
if (in_array($final_module['name'], ['Fatture di vendita', 'Fatture di acquisto']) && !in_array($original_module['name'], ['Fatture di vendita', 'Fatture di acquisto'])) {
if (in_array($final_module->getTranslation('title'), ['Fatture di vendita', 'Fatture di acquisto']) && !in_array($original_module->getTranslation('title'), ['Fatture di vendita', 'Fatture di acquisto'])) {
$id_rivalsa_inps = setting('Cassa previdenziale predefinita');
if ($dir == 'uscita') {
$id_ritenuta_acconto = $documento->anagrafica->id_ritenuta_acconto_acquisti;
@ -205,11 +213,11 @@ if (in_array($final_module['name'], ['Fatture di vendita', 'Fatture di acquisto'
}
echo '
<div class="box box-info">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Opzioni generali delle righe').'</h3>
<div class="card card-info">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Opzioni generali delle righe').'</h3>
</div>
<div class="box-body">';
<div class="card-body">';
echo '
<div class="row">';
@ -273,12 +281,12 @@ if (!empty($options['serials'])) {
// Righe del documento
echo '
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Righe da importare').'</h3>
<div class="card card-success">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Righe da importare').'</h3>
</div>
<table class="box-body table table-striped table-hover table-condensed">
<table class="card-body table table-striped table-hover table-condensed">
<thead>
<tr>
<th width="2%"><input id="import_all" type="checkbox" checked/></th>
@ -298,14 +306,14 @@ echo '
<tbody id="righe_documento_importato">';
foreach ($righe as $i => $riga) {
if ($final_module['name'] == 'Ordini fornitore') {
if ($final_module->getTranslation('title') == 'Ordini fornitore') {
$qta_rimanente = $riga['qta'];
} else {
$qta_rimanente = $riga['qta_rimanente'];
}
$attr = 'checked="checked"';
if ($original_module['name'] == 'Preventivi') {
if ($original_module->getTranslation('title') == 'Preventivi') {
if (empty($riga['confermato']) && $riga['is_descrizione'] == 0) {
$attr = '';
}
@ -347,8 +355,8 @@ foreach ($righe as $i => $riga) {
if (!empty($mancanti)) {
echo '
<br><b><small class="text-danger">'.tr('_NUM_ serial mancanti', [
'_NUM_' => $mancanti,
]).'</small></b>';
'_NUM_' => $mancanti,
]).'</small></b>';
}
}
@ -420,15 +428,15 @@ echo '
// Elenco righe evase completametne
if (!$righe_evase->isEmpty()) {
echo '
<div class="box box-info collapsable collapsed-box">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Righe evase completamente').'</h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
<div class="card card-info collapsable collapsed-card">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Righe evase completamente').'</h3>
<div class="card-tools pull-right">
<button type="button" class="btn btn-card-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
</div>
</div>
<table class="box-body table table-striped table-hover table-condensed">
<table class="card-body table table-striped table-hover table-condensed">
<thead>
<tr>
<th>'.tr('Descrizione').'</th>
@ -490,7 +498,7 @@ foreach ($articoli as $elenco) {
$qta = $elenco->sum('qta');
$articolo = $elenco->first()->articolo;
$descrizione_riga = $articolo->codice.' - '.$articolo->descrizione;
$descrizione_riga = $articolo->codice.' - '.$articolo->getTranslation('title');
$text = $articolo ? Modules::link('Articoli', $articolo->id, $descrizione_riga) : $descrizione_riga;
$scorte[$articolo->id] = [

View File

@ -17,8 +17,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
$articolo = $database->selectOne('mg_articoli', '*', ['id' => $result['idarticolo']]);
$width = $options['dir'] == 'uscita' && $articolo['fattore_um_secondaria'] ? 3 : 4;
use Models\Module;
use Modules\Articoli\Articolo;
$articolo = Articolo::find($result['idarticolo']);
$width = $options['dir'] == 'uscita' && $articolo->fattore_um_secondaria ? 3 : 4;
// Descrizione
echo App::internalLoad('descrizione.php', $result, $options);
@ -42,14 +45,14 @@ echo '
// Unità di misura
echo '
<div class="col-md-'.$width.'">
{[ "type": "select", "label": "'.tr('Unità di misura').'", "icon-after": "add|'.Modules::get('Unità di misura')['id'].'", "name": "um", "value": "'.$result['um'].'", "ajax-source": "misure" ]}
{[ "type": "select", "label": "'.tr('Unità di misura').'", "icon-after": "add|'.(new Module())->getByField('title', 'Unità di misura', Models\Locale::getPredefined()->id).'", "name": "um", "value": "'.$result['um'].'", "ajax-source": "misure" ]}
</div>';
// Unità di misura
if ($options['dir'] == 'uscita' && $articolo['fattore_um_secondaria']) {
if ($options['dir'] == 'uscita' && $articolo->fattore_um_secondaria) {
echo '
<div class="col-md-3">
{[ "type": "number", "label": "'.tr('Q.tà secondaria').'", "name": "fattore_um_secondaria", "value": "'.abs((float) $articolo['fattore_um_secondaria'] * $result['qta']).'", "icon-after": "'.$articolo['um_secondaria'].'" ]}
{[ "type": "number", "label": "'.tr('Q.tà secondaria').'", "name": "fattore_um_secondaria", "value": "'.abs((float) $articolo->fattore_um_secondaria * $result['qta']).'", "icon-after": "'.$articolo->um_secondaria.'" ]}
</div>
<script>
@ -178,10 +181,10 @@ if ($options['dir'] == 'entrata') {
if (guadagno < 0) {
parent.addClass("has-error");
$(".table-margine").addClass("label-danger").removeClass("label-success");
$(".table-margine").addClass("badge-danger").removeClass("badge-success");
} else {
parent.removeClass("has-error");
$(".table-margine").removeClass("label-danger").addClass("label-success");
$(".table-margine").removeClass("badge-danger").addClass("badge-success");
}
}
@ -225,7 +228,7 @@ if ($options['dir'] == 'entrata') {
</div>
</div>
<div class="row">
<div class="col-md-offset-4 col-md-4 minimo_vendita text-center"></div>
<div class="offset-md-4 col-md-4 minimo_vendita text-center"></div>
</div>';
} else {
echo '
@ -238,11 +241,11 @@ if ($options['dir'] == 'entrata') {
// Data prevista evasione (per ordini)
if (in_array($module['name'], ['Ordini cliente', 'Ordini fornitore', 'Preventivi'])) {
if (in_array($module->getTranslation('title'), ['Ordini cliente', 'Ordini fornitore', 'Preventivi'])) {
if ($options['action'] == 'add') {
if ($module['name'] == 'Ordini cliente') {
if ($module->getTranslation('title') == 'Ordini cliente') {
$confermato = setting('Conferma automaticamente le quantità negli ordini cliente');
} elseif ($module['name'] == 'Ordini fornitore') {
} elseif ($module->getTranslation('title') == 'Ordini fornitore') {
$confermato = setting('Conferma automaticamente le quantità negli ordini fornitore');
} else {
$confermato = setting('Conferma automaticamente le quantità nei preventivi');
@ -251,15 +254,15 @@ if (in_array($module['name'], ['Ordini cliente', 'Ordini fornitore', 'Preventivi
$confermato = $result['confermato'];
}
echo '
<div class="box box-info collapsable collapsed-box">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Informazioni aggiuntive').'</h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
<div class="card card-info collapsable collapsed-card">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Informazioni aggiuntive').'</h3>
<div class="card-tools pull-right">
<button type="button" class="btn btn-card-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
</div>
</div>
<div class="box-body">
<div class="card-body">
<div class="row">
<div class="col-md-4">
{[ "type": "date", "label": "'.tr('Data prevista evasione').'", "name": "data_evasione", "value": "'.$result['data_evasione'].'" ]}
@ -276,7 +279,7 @@ if (in_array($module['name'], ['Ordini cliente', 'Ordini fornitore', 'Preventivi
</div>
<div class="col-md-4">
{[ "type": "checkbox", "label": "'.tr('Articolo confermato').'", "name": "confermato", "value": "'.$confermato.'", "help": "'.tr('Articolo confermato dal _ANA_ e che è possibile evadere', ['_ANA_' => $module['name'] == 'Ordini fornitore' ? tr('fornitore') : tr('cliente')]).'" ]}
{[ "type": "checkbox", "label": "'.tr('Articolo confermato').'", "name": "confermato", "value": "'.$confermato.'", "help": "'.tr('Articolo confermato dal _ANA_ e che è possibile evadere', ['_ANA_' => $module->getTranslation('title') == 'Ordini fornitore' ? tr('fornitore') : tr('cliente')]).'" ]}
</div>
<div class="col-md-4">
{[ "type": "checkbox", "label": "'.tr('Cambia stato a tutte le righe').'", "name": "confermato_all", "value": "" ]}
@ -303,7 +306,7 @@ if (in_array($module['name'], ['Ordini cliente', 'Ordini fornitore', 'Preventivi
</script>';
}
if (in_array($module['name'], ['Fatture di vendita', 'Fatture di acquisto'])) {
if (in_array($module->getTranslation('title'), ['Fatture di vendita', 'Fatture di acquisto'])) {
echo '
<script>
$(document).ready(function() {
@ -338,15 +341,15 @@ if (in_array($module['name'], ['Fatture di vendita', 'Fatture di acquisto'])) {
if (prezzo_unitario < 0) {
if (input("is_nota").get() == true) {
if (input("dir").get() == "entrata") {
div.html(`<small class="label label-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Importo a credito').'</small>`);
div.html(`<span class="right badge badge-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Importo a credito').'</small>`);
} else {
div.html(`<small class="label label-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Importo a debito').'</small>`);
div.html(`<span class="right badge badge-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Importo a debito').'</small>`);
}
} else {
if (input("dir").get() == "entrata") {
div.html(`<small class="label label-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Importo a debito').'</small>`);
div.html(`<span class="right badge badge-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Importo a debito').'</small>`);
} else {
div.html(`<small class="label label-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Importo a credito').'</small>`);
div.html(`<span class="right badge badge-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Importo a credito').'</small>`);
}
}
} else {
@ -365,12 +368,12 @@ if (in_array($module['name'], ['Fatture di vendita', 'Fatture di acquisto'])) {
div_margine.css("margin-top", "-20px");
div_prezzi.css("margin-top", "-20px");
div_prezzi.css("margin-bottom", "20px");
div.html(`<small class="label label-default" >'.tr('Sconto').'</small>`);
div.html(`<span class="right badge badge-default" >'.tr('Sconto').'</small>`);
} else if (sconto < 0) {
div_margine.css("margin-top", "-20px");
div_prezzi.css("margin-top", "-20px");
div_prezzi.css("margin-bottom", "20px");
div.html(`<small class="label label-default" >'.tr('Maggiorazione').'</small>`);
div.html(`<span class="right badge badge-default" >'.tr('Maggiorazione').'</small>`);
} else {
div_margine.css("margin-top", "0px");
div_prezzi.css("margin-top", "0px");

View File

@ -74,9 +74,9 @@ echo '
}
if (sconto > 0) {
div.html(`<small class="label label-default" >'.tr('Sconto').'</small>`);
div.html(`<span class="right badge badge-default" >'.tr('Sconto').'</small>`);
} else if (sconto < 0) {
div.html(`<small class="label label-default" >'.tr('Maggiorazione').'</small>`);
div.html(`<span class="right badge badge-default" >'.tr('Maggiorazione').'</small>`);
} else {
div.html("");
}
@ -94,9 +94,9 @@ echo '
}
if (sconto > 0) {
div.html(`<small class="label label-default" >'.tr('Sconto').'</small>`);
div.html(`<span class="right badge badge-default" >'.tr('Sconto').'</small>`);
} else if (sconto < 0) {
div.html(`<small class="label label-default" >'.tr('Maggiorazione').'</small>`);
div.html(`<span class="right badge badge-default" >'.tr('Maggiorazione').'</small>`);
} else {
div.html("");
}

View File

@ -31,7 +31,7 @@ $pageTitle = tr('Configurazione');
include_once App::filepath('include|custom|', 'top.php');
// Controllo sull'esistenza di nuovi parametri di configurazione
if (post('db_host') !== null) {
if (!empty(post('db_host'))) {
$db_host = $_POST['db_host']; // Fix per evitare la conversione in numero
$db_name = post('db_name');
$db_username = post('db_username');
@ -51,7 +51,7 @@ if (post('db_host') !== null) {
}
// Test della configurazione
if (post('test') !== null) {
if (!empty(post('test'))) {
ob_end_clean();
if ($dbo->isConnected()) {
@ -73,8 +73,8 @@ if (post('db_host') !== null) {
$privileges = current($result);
if (
string_contains($privileges, ' ON `'.$db_name.'`.*') ||
string_contains($privileges, ' ON *.*')
string_contains($privileges, ' ON `'.$db_name.'`.*')
|| string_contains($privileges, ' ON *.*')
) {
$pieces = explode(', ', explode(' ON ', str_replace('GRANT ', '', $privileges))[0]);
@ -110,7 +110,7 @@ if (post('db_host') !== null) {
}
echo $state;
exit();
exit;
}
// Creazione della configurazione
@ -141,14 +141,14 @@ if (post('db_host') !== null) {
$creation = file_put_contents('config.inc.php', $new_config);
if (!$creation) {
echo '
<div class="box box-center box-danger box-solid text-center">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Permessi di scrittura mancanti').'</h3>
<div class="card card-center card-danger card-solid text-center">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Permessi di scrittura mancanti').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr('Sembra che non ci siano i permessi di scrittura sul file _FILE_', [
'_FILE_' => '<b>config.inc.php</b>',
]).'</p>
'_FILE_' => '<b>config.inc.php</b>',
]).'</p>
<form action="'.base_path().'/index.php?action=updateconfig&firstuse=true" method="post">
<div class="hide">
<input type="hidden" name="db_name" value="'.$db_name.'">
@ -160,17 +160,17 @@ if (post('db_host') !== null) {
<button class="btn btn-info"><i class="fa fa-repeat"></i> '.tr('Riprova').'</button>
</form>
<hr>
<div class="box box-default collapsed-box">
<div class="box-header with-border">
<h4 class="box-title"><a class="clickable" data-widget="collapse">'.tr('Creazione manuale').'...</a></h4>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
<div class="card card-default collapsed-card">
<div class="card-header with-border">
<h4 class="card-title"><a class="clickable" data-widget="collapse">'.tr('Creazione manuale').'...</a></h4>
<div class="card-tools pull-right">
<button type="button" class="btn btn-card-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
</div>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr('Inserire il seguente testo nel file _FILE_', [
'_FILE_' => '<b>config.inc.php</b>',
]).'</p>
'_FILE_' => '<b>config.inc.php</b>',
]).'</p>
<pre class="text-left">'.htmlentities($new_config).'</pre>
</div>
</div>
@ -182,7 +182,7 @@ if (post('db_host') !== null) {
// Creazione manifest.json
include_once App::filepath('include/init', 'manifest.php');
redirect(base_path().'/index.php');
exit();
exit;
}
}
}
@ -190,11 +190,11 @@ if (post('db_host') !== null) {
// Controlla che i parametri di configurazione permettano l'accesso al database
if ((file_exists('config.inc.php') || $valid_config) && !$dbo->isConnected()) {
echo '
<div class="box box-center box-danger box-solid text-center">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Impossibile connettersi al database').'</h3>
<div class="card card-center card-danger card-solid text-center">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Impossibile connettersi al database').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr('Si è verificato un errore durante la connessione al database').'.</p>
<p>'.tr('Controllare di aver inserito correttamente i dati di accesso, e che il database atto ad ospitare i dati del gestionale sia esistente').'.</p>
<a class="btn btn-info" href="'.base_path().'/index.php"><i class="fa fa-repeat"></i> '.tr('Riprova').'</a>
@ -208,15 +208,15 @@ $img = App::getPaths()['img'];
if (empty($creation) && (!file_exists('config.inc.php') || !$valid_config)) {
if (file_exists('config.inc.php')) {
echo '
<div class="box box-center box-danger box-solid text-center">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Parametri non sufficienti!').'</h3>
<div class="card card-center card-danger card-solid text-center">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Parametri non sufficienti!').'</h3>
</div>
<div class="box-body">
<p>'.tr("L'avvio del software è fallito a causa dell'assenza di alcuni paramentri nella configurazione di base").'.</p>
<div class="card-body">
<p>'.tr("L'avvio del software è fallito a causa dell'assenza di alcuni parametri nella configurazione di base").'.</p>
<p>'.tr("Si prega di controllare che il file _FILE_ contenga tutti i dati inseriti durante la configurazione iniziale (con l'eccezione di password e indirizzo email amministrativi)", [
'_FILE_' => '<b>config.inc.php</b>',
]).'.</p>
'_FILE_' => '<b>config.inc.php</b>',
]).'.</p>
<p>'.tr("Nel caso il problema persista, rivolgersi all'assistenza ufficiale").'.</p>
<a class="btn btn-info" href="'.base_path().'/index.php"><i class="fa fa-repeat"></i> '.tr('Riprova').'</a>
</div>
@ -305,12 +305,12 @@ if (empty($creation) && (!file_exists('config.inc.php') || !$valid_config)) {
</script>';
echo '
<div class="box box-center-large box-warning">
<div class="box-header with-border text-center">
<div class="card card-center-large card-warning">
<div class="card-header with-border text-center">
<img src="'.$img.'/logo_completo.png" width="300" alt="'.tr('OSM Logo').'">
</div>
<div class="box-body" id="smartwizard">
<div class="card-body" id="smartwizard">
<span class="pull-right col-md-4">
<select class="form-control hide" id="language" required="1">';
@ -431,9 +431,12 @@ if (empty($creation) && (!file_exists('config.inc.php') || !$valid_config)) {
// LICENZA
echo '
<div id="step-2">
<p>'.tr('OpenSTAManager è tutelato dalla licenza _LICENSE_!', [
'_LICENSE_' => 'GPL 3.0',
]).'</p>
<p>'.tr('OpenSTAManager è tutelato dalla licenza _LICENSE_', [
'_LICENSE_' => 'GPL 3.0',
]).':</p>
<textarea class="form-control autosize" rows="15" readonly>'.file_get_contents('LICENSE').'</textarea><br>
<a class="pull-left" href="https://www.gnu.org/licenses/translations.en.html#GPL" target="_blank">[ '.tr('Versioni tradotte').' ]</a><hr>
<div class="row">
<div class="col-md-8">
@ -445,10 +448,6 @@ if (empty($creation) && (!file_exists('config.inc.php') || !$valid_config)) {
<label for="agree">'.tr('Ho visionato e accetto').'.</label>
</form>
</div>
<hr>
<textarea class="form-control autosize" rows="15" readonly>'.file_get_contents('LICENSE').'</textarea><br>
<a class="pull-left" href="https://www.gnu.org/licenses/translations.en.html#GPL" target="_blank">[ '.tr('Versioni tradotte').' ]</a><br><br>
</div>';
$host = !empty($db_host) ? $db_host : '';
@ -463,8 +462,8 @@ if (empty($creation) && (!file_exists('config.inc.php') || !$valid_config)) {
<p>'.tr('Non hai ancora configurato OpenSTAManager').'.</p>
<p><small class="help-block">'.tr('Configura correttamente il software con i seguenti parametri (modificabili successivamente dal file _FILE_)', [
'_FILE_' => '<b>config.inc.php</b>',
]).'</small></p>
'_FILE_' => '<b>config.inc.php</b>',
]).'</small></p>
<hr>';
@ -489,8 +488,8 @@ if (empty($creation) && (!file_exists('config.inc.php') || !$valid_config)) {
</div>
<small>'.tr('I formati sono impostabili attraverso lo standard previsto da PHP: _LINK_', [
'_LINK_' => '<a href="https://www.php.net/manual/en/function.date.php#refsect1-function.date-parameters">https://www.php.net/manual/en/function.date.php#refsect1-function.date-parameters</a>',
]).'.</small>
'_LINK_' => '<a href="https://www.php.net/manual/en/function.date.php#refsect1-function.date-parameters">https://www.php.net/manual/en/function.date.php#refsect1-function.date-parameters</a>',
]).'.</small>
<hr>';
@ -520,8 +519,8 @@ if (empty($creation) && (!file_exists('config.inc.php') || !$valid_config)) {
</div>
<small>'.tr("Si consiglia l'abilitazione dell'estensione _EXT_ di PHP", [
'_EXT_' => 'intl',
]).'.</small>
'_EXT_' => 'intl',
]).'.</small>
<hr>';
}
@ -587,4 +586,4 @@ if (empty($creation) && (!file_exists('config.inc.php') || !$valid_config)) {
include_once App::filepath('include|custom|', 'bottom.php');
exit();
exit;

View File

@ -19,14 +19,22 @@
include_once __DIR__.'/../../core.php';
use Models\Group;
use Models\Module;
use Models\Setting;
use Modules\Anagrafiche\Tipo;
if (Update::isUpdateAvailable() || !$dbo->isInstalled()) {
return;
}
$has_azienda = $dbo->fetchNum("SELECT `an_anagrafiche`.`idanagrafica` FROM `an_anagrafiche`
$id_tipo_azienda = Tipo::find((new Tipo())->getByField('title', 'Azienda', Models\Locale::getPredefined()->id))->id;
$has_azienda = $dbo->fetchNum('SELECT `an_anagrafiche`.`idanagrafica` FROM `an_anagrafiche`
LEFT JOIN `an_tipianagrafiche_anagrafiche` ON `an_anagrafiche`.`idanagrafica`=`an_tipianagrafiche_anagrafiche`.`idanagrafica`
LEFT JOIN `an_tipianagrafiche` ON `an_tipianagrafiche`.`idtipoanagrafica`=`an_tipianagrafiche_anagrafiche`.`idtipoanagrafica`
WHERE `an_tipianagrafiche`.`descrizione` = 'Azienda' AND `an_anagrafiche`.`deleted_at` IS NULL") != 0;
LEFT JOIN `an_tipianagrafiche` ON `an_tipianagrafiche`.`id`=`an_tipianagrafiche_anagrafiche`.`idtipoanagrafica`
LEFT JOIN `an_tipianagrafiche_lang` ON (`an_tipianagrafiche`.`id`=`an_tipianagrafiche_lang`.`id_record` AND `an_tipianagrafiche_lang`.`id_lang`='.prepare(Models\Locale::getDefault()->id).')
WHERE `an_tipianagrafiche`.`id` = '.$id_tipo_azienda.' AND `an_anagrafiche`.`deleted_at` IS NULL') != 0;
$has_user = $dbo->fetchNum('SELECT `id` FROM `zz_users`') != 0;
$settings = [
@ -66,7 +74,7 @@ if (post('action') == 'init') {
// Azienda predefinita
if (!$has_azienda) {
Filter::set('post', 'op', 'add');
$id_module = Modules::get('Anagrafiche')['id'];
$id_module = (new Module())->getByField('title', 'Anagrafiche', Models\Locale::getPredefined()->id);
include base_dir().'/modules/anagrafiche/actions.php';
// Logo stampe
@ -83,9 +91,7 @@ if (post('action') == 'init') {
// Utente amministratore
if (!$has_user) {
$admin = $dbo->selectOne('zz_groups', ['id'], [
'nome' => 'Amministratori',
]);
$admin = Group::where('nome', '=', 'Amministratori')->first();
// Creazione utente Amministratore
$dbo->insert('zz_users', [
@ -93,7 +99,7 @@ if (post('action') == 'init') {
'password' => Auth::hashPassword(post('admin_password')),
'email' => post('admin_email'),
'idgruppo' => $admin['id'],
'idanagrafica' => isset($id_record) ? $id_record : 0,
'idanagrafica' => $id_record ?? 0,
'enabled' => 1,
]);
@ -106,44 +112,46 @@ if (post('action') == 'init') {
if (!$has_settings) {
foreach ($settings as $setting => $required) {
$setting = Settings::get($setting);
$setting = Setting::where('nome', '=', $setting)->first();
$value = post('setting')[$setting['id']];
$value = post('setting')[$setting->id];
if (!empty($value)) {
Settings::setValue($setting['nome'], $value);
Settings::setValue($setting->id, $value);
}
}
}
redirect(base_path(), 'js');
exit();
exit;
}
$img = App::getPaths()['img'];
// Visualizzazione dell'interfaccia di impostazione iniziale, nel caso il file di configurazione sia mancante oppure i paramentri non siano sufficienti
echo '
<div class="box box-center-large box-warning">
<div class="box-header with-border text-center">
<div class="card card-center-large card-warning">
<div class="card-header text-center">
<img src="'.$img.'/logo_completo.png" class="logo-image" alt="'.tr('OSM Logo').'">
</div>
<div class="box-body">
<div class="card-body">
<form action="" method="post" id="init-form" enctype="multipart/form-data">
<input type="hidden" name="action" value="init">';
if (!$has_user) {
echo '
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">'.tr('Amministrazione').'</h3>
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">'.tr('Amministrazione').'</h3>
</div>
<div class="panel-body">
<div class="card-body">
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Username').'", "name": "admin_username", "value": "", "placeholder": "'.tr("Imposta l'username dell'amministratore").'", "required": 1 ]}
<div class="form-group">
<label for="admin_username">'.tr('Username').'</label>
<input type="text" class="form-control" id="admin_username" name="admin_username" placeholder="'.tr("Imposta l'username dell'amministratore").'" required>
</div>
</div>
<div class="col-md-6">
@ -151,7 +159,10 @@ if (!$has_user) {
</div>
<div class="col-md-6">
{[ "type": "email", "label": "'.tr('Email').'", "name": "admin_email", "value": "", "placeholder": "'.tr("Imposta l'indirizzo email dell'amministratore").'", "required": 1 ]}
<div class="form-group">
<label for="admin_email">'.tr('Email').'</label>
<input type="email" class="form-control" id="admin_email" name="admin_email" placeholder="'.tr("Imposta l'indirizzo email dell'amministratore").'" required>
</div>
</div>
</div>
</div>
@ -160,15 +171,14 @@ if (!$has_user) {
if (!$has_azienda) {
echo '
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">'.tr('Azienda predefinita').'</h3>
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">'.tr('Azienda predefinita').'</h3>
</div>
<div class="panel-body" id="bs-popup">';
<div class="card-body" id="bs-popup">';
$idtipoanagrafica = $dbo->fetchArray("SELECT idtipoanagrafica FROM an_tipianagrafiche WHERE descrizione='Azienda'")[0]['idtipoanagrafica'];
$idtipoanagrafica = (new Tipo())->getByField('title', 'Azienda', Models\Locale::getPredefined()->id);
$readonly_tipo = true;
ob_start();
@ -178,23 +188,26 @@ if (!$has_azienda) {
echo str_replace('</form>', '', $anagrafica);
echo '
<div class="box box-success collapsed-box">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Logo stampe').'</h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<div class="card card-success collapsed-card">
<div class="card-header">
<h3 class="card-title">'.tr('Logo stampe').'</h3>
<div class="card-tools">
<button type="button" class="btn btn-tool" data-card-widget="collapse">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<div class="box-body collapse">
<div class="card-body collapse">
<div class="col-md-12">
{[ "type": "file", "placeholder": "'.tr('File').'", "name": "blob" ]}
<div class="form-group">
<label>'.tr('File').'</label>
<input type="file" class="form-control" name="blob">
</div>
</div>
<p>&nbsp;</p><div class="col-md-12 alert alert-info text-center">'.tr('Per impostare il logo delle stampe, caricare un file ".jpg". Risoluzione consigliata 302x111 pixel').'.</div>
<p>&nbsp;</p>
<div class="col-md-12 alert alert-info text-center">'.tr('Per impostare il logo delle stampe, caricare un file ".jpg". Risoluzione consigliata 302x111 pixel').'.</div>
</div>
</div>';
@ -206,13 +219,12 @@ if (!$has_azienda) {
if (!$has_settings) {
echo '
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">'.tr('Impostazioni di base').'</h3>
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">'.tr('Impostazioni di base').'</h3>
</div>
<div class="panel-body">';
<div class="card-body">';
$i = 0;
foreach ($settings as $setting => $required) {
if (empty(setting($setting))) {
@ -234,19 +246,18 @@ if (!$has_settings) {
echo ' </div>
</div>';
}
echo '
<!-- PULSANTI -->
<div class="row">
<div class="col-md-4">
<span>*<small><small>'.tr('Campi obbligatori').'</small></small></span>
</div>
<div class="col-md-4 text-right">
<button type="submit" id="config" class="btn btn-success btn-block">
<i class="fa fa-cog"></i> '.tr('Configura').'
</button>
</div>
<!-- PULSANTI -->
<div class="row">
<div class="col-md-4">
<span>*<small><small>'.tr('Campi obbligatori').'</small></small></span>
</div>
<div class="col-md-4 text-right">
<button type="submit" id="config" class="btn btn-success btn-block">
<i class="fa fa-cog"></i> '.tr('Configura').'
</button>
</div>
</div>
</form>
</div>
@ -263,4 +274,4 @@ echo '
include_once App::filepath('include|custom|', 'bottom.php');
exit();
exit;

View File

@ -24,17 +24,17 @@ if ($config['maintenance_ip'] != $_SERVER['REMOTE_ADDR']) {
$img = App::getPaths()['img'];
echo '
<div class="box box-center-large box-danger">
<div class="box-header with-border text-center">
<div class="card card-center-large card-danger">
<div class="card-header with-border text-center">
<img src="'.$img.'/logo_completo.png" width="300" alt="'.tr('OSM Logo').'">
</div>
<div class="box-body">
<div class="box box-center box-danger box-solid text-center">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Manutenzione in corso!').'</h3>
<div class="card-body">
<div class="card card-center card-danger card-solid text-center">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Manutenzione in corso!').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr('Il software si trova attualmente in modalità manutenzione, siete pregati di attendere sino alla conclusione dell\'intervento').'.</p>
</div>
</div>
@ -43,5 +43,5 @@ if ($config['maintenance_ip'] != $_SERVER['REMOTE_ADDR']) {
include_once App::filepath('include|custom|', 'bottom.php');
exit();
exit;
}

View File

@ -46,14 +46,14 @@ if (!$creation) {
file_put_contents('manifest.json', $manifest);
} else {
echo '
<div class="box box-center box-danger box-solid text-center">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Permessi di scrittura mancanti').'</h3>
<div class="card card-center card-danger card-solid text-center">
<div class="card-header with-border">
<h3 class="card-title">'.tr('Permessi di scrittura mancanti').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr('Sembra che non ci siano i permessi di scrittura sul file _FILE_', [
'_FILE_' => '<b>manifest.json</b>',
]).'</p>
'_FILE_' => '<b>manifest.json</b>',
]).'</p>
</div>
</div>';
}

View File

@ -23,8 +23,56 @@ $modules = [
'server' => 'HTTP_MOD_REWRITE',
'description' => tr('Fornisce un sistema di riscrittura URL basato su regole predefinite'),
],
'mod_mime' => [
'server' => 'text/javascript mjs',
'description' => tr('Consente di associare i tipi di file ai tipi di contenuto corretti.'),
],
];
$sapi_name = php_sapi_name();
$php_interface = '';
switch (true) {
case strpos($sapi_name, 'apache') !== false:
// PHP è in esecuzione come modulo Apache (4)
$php_interface = 'apache';
break;
case strpos($sapi_name, 'fpm-fcgi') !== false:
// PHP è in esecuzione come PHP-FPM FastCGI (3)
$php_interface = 'fpm-fcgi';
break;
case strpos($sapi_name, 'fpm') !== false:
// PHP è in esecuzione come PHP-FPM (9)
$php_interface = 'fpm';
break;
case strpos($sapi_name, 'cgi-fcgi') !== false:
// PHP è in esecuzione come FastCGI (8)
$php_interface = 'cgi-fcgi';
break;
case strpos($sapi_name, 'cgi') !== false:
// PHP è in esecuzione come modulo CGI (2)
$php_interface = 'cgi';
break;
case strpos($sapi_name, 'cli') !== false:
// PHP è in esecuzione dalla riga di comando (command line interface) (1)
$php_interface = 'cli';
break;
case strpos($sapi_name, 'embed') !== false:
// PHP è incorporato in un'applicazione (5)
$php_interface = 'embed';
break;
case strpos($sapi_name, 'litespeed') !== false:
// PHP è in esecuzione come modulo LiteSpeed (6)
$php_interface = 'litespeed';
break;
case strpos($sapi_name, 'isapi') !== false:
// PHP è in esecuzione come modulo ISAPI in IIS (7)
$php_interface = 'isapi';
break;
default:
// Non è possibile determinare il tipo di interfaccia di PHP (0)
$php_interface = 'n.d.';
}
if (function_exists('apache_get_modules')) {
$available_modules = apache_get_modules();
}
@ -35,6 +83,15 @@ foreach ($modules as $name => $values) {
$status = isset($available_modules) ? in_array($name, $available_modules) : $_SERVER[$values['server']] == 'On';
if ($name == 'mod_mime' && $php_interface != 'apache') {
$headers = get_headers((!empty($config['redirectHTTPS']) && !isHTTPS(true)) ? 'https://' : 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true);
if (isset($headers['Content-Type'])) {
$status = 1;
} else {
$status = 0;
}
}
$apache[] = [
'name' => $name,
'description' => $description,
@ -43,13 +100,13 @@ foreach ($modules as $name => $values) {
];
}
//PHP
// PHP
$settings = [
'php_version' => [
'type' => 'version',
'description' => '7.3.x - 8.0.x, consigliato almeno 7.4.x',
'minimum' => '7.3.0',
'maximum' => '8.0.99',
'description' => '8.0.x - 8.3.x',
'minimum' => '8.0.0',
'maximum' => '8.3.99',
],
'zip' => [
@ -97,10 +154,10 @@ $settings = [
'description' => tr('Permette la creazione dell\'immagine della firma per il rapportino d\'intervento (facoltativo)'),
],
//'display_errors' => [
// 'display_errors' => [
// 'type' => 'value',
// 'description' => true,
//],
// ],
'allow_url_fopen' => [
'type' => 'value',
@ -121,6 +178,11 @@ $settings = [
'type' => 'value',
'description' => '>5000',
],
'exec' => [
'type' => 'function',
'description' => tr('Permette di importare file con estensione .p7m'),
],
];
$php = [];
@ -136,6 +198,8 @@ foreach ($settings as $name => $values) {
$status = ((version_compare(phpversion(), $values['minimum'], '>=') && version_compare(phpversion(), $values['maximum'], '<=')) ? 1 : 0);
} elseif ($values['type'] == 'ext') {
$status = extension_loaded($name);
} elseif ($values['type'] == 'function') {
$status = ((function_exists($name) && is_callable($name)) ? 1 : 0);
} else {
$ini = str_replace(['k', 'M'], ['000', '000000'], ini_get($name));
$real = str_replace(['k', 'M'], ['000', '000000'], $description);
@ -155,17 +219,17 @@ foreach ($settings as $name => $values) {
}
$description = tr('Valore consigliato: _VALUE_ (Valore attuale: _INI_)', [
'_VALUE_' => $description,
'_INI_' => ini_get($name),
'_VALUE_' => $description,
'_INI_' => ini_get($name),
]);
}
$type = ($values['type'] == 'ext') ? tr('Estensione') : tr('Impostazione');
if ($values['type'] == 'ext') {
$type = tr('Estensione');
} elseif ($values['type'] == 'version') {
$type = tr('Versione');
} elseif ($values['type'] == 'function') {
$type = tr('Funzione');
} else {
$type = tr('Impostazione');
}
@ -180,19 +244,29 @@ foreach ($settings as $name => $values) {
// MySQL
if ($database->isInstalled()) {
$db = [
'mysql_version' => [
'type' => 'version',
'description' => '5.7.x - 8.0.x',
'minimum' => '5.7.0',
'maximum' => '8.0.99',
],
if (method_exists($database, 'isMySQL')) {
$db = [
'mysql_version' => [
'type' => 'version',
'warning' => $database->isMySQL() ? false : true,
'description' => $database->isMySQL() ? '5.7.x - 8.0.x' : '10.x',
'minimum' => $database->isMySQL() ? '5.7.0' : '10.1.0',
'maximum' => $database->isMySQL() ? '8.3.99' : '10.6.99',
],
'sort_buffer_size' => [
'type' => 'value',
'description' => '>2M',
],
];
'sort_buffer_size' => [
'type' => 'value',
'description' => '>2M',
],
];
} else {
$db = [
'sort_buffer_size' => [
'type' => 'value',
'description' => '>2M',
],
];
}
/*foreach (App::getConfig()['db_options'] as $n => $v){
@ -208,6 +282,8 @@ if ($database->isInstalled()) {
}*/
}
$mysql = [];
foreach ($db as $name => $values) {
$description = $values['description'];
@ -219,10 +295,15 @@ foreach ($db as $name => $values) {
]);
$status = ((version_compare($database->getMySQLVersion(), $values['minimum'], '>=') && version_compare($database->getMySQLVersion(), $values['maximum'], '<=')) ? 1 : 0);
if ($values['warning'] && $status == 1) {
$status = 0;
$description .= '. <i class="fa fa-exclamation-triangle text-danger" ></i><b> '.tr('Al momento MariaDB _MYSQL_VERSION_ non è completamente supportato, si consiglia di passare a MySQL.', ['_MYSQL_VERSION_' => $database->getMySQLVersion()]).'</b>';
}
} else {
$type = tr('Impostazione');
//Vedo se riesco a recuperare l'impostazione dalle variabili di sessione o globali di mysql
// Vedo se riesco a recuperare l'impostazione dalle variabili di sessione o globali di mysql
$rs_session_variabile = $dbo->fetchArray('SHOW SESSION VARIABLES LIKE '.prepare($name));
$rs_global_variabile = $dbo->fetchArray('SHOW GLOBAL VARIABLES LIKE '.prepare($name));
@ -251,8 +332,8 @@ foreach ($db as $name => $values) {
}
$description = tr('Valore consigliato: _VALUE_ (Valore attuale: _INC_)', [
'_VALUE_' => $description,
'_INC_' => \Util\FileSystem::formatBytes($inc),
'_VALUE_' => $description,
'_INC_' => Util\FileSystem::formatBytes($inc),
]);
}
@ -266,7 +347,7 @@ foreach ($db as $name => $values) {
// Percorsi di servizio
$dirs_to_check = [
'backup' => tr('Necessario per il salvataggio dei backup'),
$backup_dir => tr('Necessario per il salvataggio dei backup'),
'files' => tr('Necessario per il salvataggio di file inseriti dagli utenti'),
'files/temp' => tr('Necessario per la generazione delle stampe'),
'logs' => tr('Necessario per la gestione dei file di log'),
@ -274,7 +355,11 @@ $dirs_to_check = [
$directories = [];
foreach ($dirs_to_check as $name => $description) {
$status = is_writable(base_dir().DIRECTORY_SEPARATOR.$name);
if ($name == $backup_dir) {
$status = is_writable($name);
} else {
$status = is_writable(base_dir().DIRECTORY_SEPARATOR.$name);
}
$directories[] = [
'name' => $name,
@ -287,14 +372,16 @@ foreach ($dirs_to_check as $name => $description) {
// File di servizio
$files_to_check = [
'manifest.json' => tr('Necessario per l\'aggiunta a schermata home da terminale (creato al termine della configurazione)'),
'database_5_7.json' => tr('Necessario per il controllo integrità con database MySQL 5.7.x'),
'database.json' => tr('Necessario per il controllo integrità con database MySQL 8.0.x'),
'mariadb_10_x.json' => tr('Necessario per il controllo integrità con database MariaDB 10.x'),
'mysql_5_7.json' => tr('Necessario per il controllo integrità con database MySQL 5.7.x'),
'mysql.json' => tr('Necessario per il controllo integrità con database MySQL 8.0.x'),
'checksum.json' => tr('Necessario per il controllo integrità dei files del gestionale'),
'settings.json' => tr('Necessario per il controllo delle impostazioni del gestionale'),
];
$files = [];
foreach ($files_to_check as $name => $description) {
$status = is_writable(base_dir().DIRECTORY_SEPARATOR.$name);
$status = is_readable(base_dir().DIRECTORY_SEPARATOR.$name);
$files[] = [
'name' => $name,
@ -344,11 +431,11 @@ foreach ($config_to_check as $name => $values) {
if ($type == 'value') {
$description = tr('Valore consigliato: _SUGGESTED_ (Valore attuale: _ACTUAL_)', [
'_SUGGESTED_' => $values['suggested_value'],
'_ACTUAL_' => (!empty($values['section']) ? ${$values['section']}[$name] : $$name),
'_ACTUAL_' => (!empty($values['section']) ? ${$values['section']}[$name] : ${$name}),
]);
}
$status = ($values['operator']((!empty($values['section']) ? ${$values['section']}[$name] : $$name), $values['value_to_check']) ? 1 : 0);
$status = ($values['operator'](!empty($values['section']) ? ${$values['section']}[$name] : ${$name}, $values['value_to_check']) ? 1 : 0);
$config[] = [
'name' => $name,
@ -359,19 +446,25 @@ foreach ($config_to_check as $name => $values) {
}
$requirements = [
tr('Apache') => $apache,
tr('Apache (_INTERFACE_)', [
'_INTERFACE_' => $php_interface,
]) => $apache,
tr('PHP (_VERSION_ _SUPPORTED_)', [
'_VERSION_' => phpversion(),
'_SUPPORTED_' => ((version_compare(phpversion(), $settings['php_version']['minimum'], '>=') && version_compare(phpversion(), $settings['php_version']['maximum'], '<=')) ? '' : '<small><small class="label label-danger" ><i class="fa fa-warning"></i> '.tr('versioni supportate:').' '.$settings['php_version']['description'].'</small></small>'),
'_SUPPORTED_' => ((version_compare(phpversion(), $settings['php_version']['minimum'], '>=') && version_compare(phpversion(), $settings['php_version']['maximum'], '<=')) ? '' : '<small> <span class="right badge badge-danger" ><i class="fa fa-warning"></i> '.tr('versioni supportate:').' '.$settings['php_version']['description'].'</small></small>'),
]) => $php,
tr('MySQL') => $mysql,
tr('DBMS (_TYPE_)', [
'_TYPE_' => method_exists($database, 'getType') ? $database->getType() : '',
]) => $mysql,
tr('Percorsi di servizio') => $directories,
tr('File di servizio') => $files,
tr('Configurazioni') => $config,
];
if (!$database->isInstalled() || empty($mysql)) {
unset($requirements['MySQL']);
unset($requirements[tr('DBMS (_TYPE_)', [
'_TYPE_' => $database->getType(),
])]);
}
// Tabelle di riepilogo
@ -383,14 +476,14 @@ foreach ($requirements as $key => $values) {
}
echo '
<div class="box box-'.($general_status ? 'success collapsed-box' : 'danger').'">
<div class="box-header with-border">
<h3 class="box-title">'.$key.'</h3>';
<div class="card card-'.($general_status ? 'success collapsed-card' : 'danger').'">
<div class="card-header with-border">
<h3 class="card-title">'.$key.'</h3>';
if ($general_status) {
echo '
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<div class="card-tools pull-right">
<button type="button" class="btn btn-card-tool" data-widget="collapse">
<i class="fa fa-plus"></i>
</button>
</div>';
@ -398,7 +491,7 @@ foreach ($requirements as $key => $values) {
echo '
</div>
<div class="box-body no-padding">
<div class="card-body no-padding">
<table class="table">';
foreach ($values as $value) {
@ -406,7 +499,7 @@ foreach ($requirements as $key => $values) {
<tr class="'.($value['status'] ? 'success' : 'danger').'">
<td style="width: 10px"><i class="fa fa-'.($value['status'] ? 'check' : 'times').'"></i></td>
<td style="width: 120px" >'.$value['type'].'</td>
<td style="width: 200px" >'.$value['name'].'</td>
<td style="width: 300px" >'.$value['name'].'</td>
<td>'.$value['description'].'</td>
</tr>';
}

View File

@ -33,105 +33,105 @@ if (filter('action') == 'do_update') {
$result = Update::doUpdate($updateRate);
if (!empty($result)) {
// Aggiunta del messaggio generico riguardante l'aggiornamento
// Adding a generic message regarding the update
echo '
<script>
addVersion("'.$update['name'].'");
</script>';
<script>
addVersion("'.$update['name'].'");
</script>';
if (is_array($result)) {
// Aggiunta del messaggio riguardante la conclusione dell'aggiornamento del database
// Adding a message about the completion of the database update
if (!empty($update['sql']) && $result[1] == $result[2]) {
echo '
<script>
$("#progress .info").html($("#progress .info").html() + "<p>&nbsp;&nbsp;&nbsp;&nbsp;<i class=\"fa fa-check\"></i> '.tr('Aggiornamento del database (_FILENAME_)', [
'_FILENAME_' => '<i>'.$update['filename'].'.sql</i>',
]).'</p>");
</script>';
<script>
$("#progress .info").html($("#progress .info").html() + "<p><i class=\"fa fa-check\"></i> '.tr('Aggiornamento del database (_FILENAME_)', [
'_FILENAME_' => '<i>'.$update['filename'].'.sql</i>',
]).'</p>");
</script>';
}
$rate = $result[1] - $result[0];
} elseif (!empty($update['script'])) {
// Aggiunta del messaggio riguardante la conclusione dello script
// Adding a message about the completion of the script
echo '
<script>
$("#progress .info").html($("#progress .info").html() + "<p>&nbsp;&nbsp;&nbsp;&nbsp;<i class=\"fa fa-check\"></i> '.tr('Esecuzione dello script di aggiornamento (_FILENAME_)', [
'_FILENAME_' => '<i>'.$update['filename'].'.php</i>',
]).'</p>");
</script>';
<script>
$("#progress .info").html($("#progress .info").html() + "<p><i class=\"fa fa-check\"></i> '.tr('Esecuzione dello script di aggiornamento (_FILENAME_)', [
'_FILENAME_' => '<i>'.$update['filename'].'.php</i>',
]).'</p>");
</script>';
$rate = $scriptValue;
}
// Aumento della percentuale di completamento totale
// Increasing the total completion percentage
if (!empty($rate)) {
echo '
<script>
addProgress('.$rate.');
</script>';
<script>
addProgress('.$rate.');
</script>';
}
echo '
<script>
$("#result").load("index.php?action=do_update&firstuse='.$_GET['firstuse'].'");
</script>';
<script>
$("#result").load("index.php?action=do_update&firstuse='.$_GET['firstuse'].'");
</script>';
} else {
// Fallimento
// Failure
echo '
<div class="alert alert-danger">
<i class="fa fa-times"></i> '.tr("Errore durante l'esecuzione dell'aggiornamento alla versione _VERSION_", [
'_VERSION_' => $update['version'],
]).'
</div>';
<div class="alert alert-danger">
<i class="fa fa-times"></i> '.tr("Errore durante l'esecuzione dell'aggiornamento alla versione _VERSION_", [
'_VERSION_' => $update['version'],
]).'
</div>';
}
}
// Aggiornamento completato
// Update completed
elseif (Update::isUpdateCompleted()) {
Update::updateCleanup();
echo '
<p><strong>'.tr('Aggiornamento completato').'</strong> <i class="fa fa-smile-o"></i></p>
<script>
setPercent(100);
</script>';
// Istruzioni per la prima installazione
<p><strong>'.tr('Aggiornamento completato').'</strong> 😃</p>
<script>
setPercent(100);
</script>';
// Instructions for the first installation
if ($_GET['firstuse'] == 'true') {
echo '
<p class="text-danger">'.tr("E' fortemente consigliato rimuovere i permessi di scrittura dal file _FILE_", [
'_FILE_' => '<b>config.inc.php</b>',
]).'.</p>';
<p class="text-danger">'.tr('Si consiglia di rimuovere i permessi di scrittura dal file _FILE_', [
'_FILE_' => '<b>config.inc.php</b>',
]).'.</p>';
}
echo '
<a class="btn btn-success btn-block" href="'.base_path().'">
<i class="fa fa-check"></i> '.tr('Continua').'
</a>';
<a class="btn btn-success btn-block" href="'.base_path().'">
<i class="fa fa-check"></i> '.tr('Continua').'
</a>';
}
exit();
exit;
} elseif (Update::isUpdateAvailable()) {
// Controllo se l'aggiornamento è in esecuzione
if (Update::isUpdateLocked() && filter('force') === null) {
// Check if the update is in progress
if (Update::isUpdateLocked() && filter('force') != '1') {
$pageTitle = tr('Aggiornamento in corso!');
include_once App::filepath('include|custom|', 'top.php');
echo '
<div class="box box-center box-danger box-solid text-center">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Aggiornamento in corso!').'</h3>
<div class="card card-danger card-outline text-center">
<div class="card-header">
<h3 class="card-title">'.tr('Aggiornamento in corso!').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr('Il software si trova attualmente nella fase di aggiornamento, potrebbero volerci fino a 10 minuti, siete pregati di attendere sino alla sua conclusione').'.</p>
<p>'.tr("In caso di problemi rivolgersi all'amministratore di sistema o all'assistenza del gestionale").'.</p>
<a class="btn btn-info" href="'.base_path().'/index.php"><i class="fa fa-repeat"></i> '.tr('Riprova').'</a>
<a class="btn btn-info" href="'.base_path().'/index.php"><i class="fa fa-redo"></i> '.tr('Riprova').'</a>
</div>
</div>';
include_once App::filepath('include|custom|', 'bottom.php');
exit();
exit;
}
$firstuse = !$dbo->isInstalled() ? 'true' : 'false';
@ -142,11 +142,11 @@ if (filter('action') == 'do_update') {
include_once App::filepath('include|custom|', 'top.php');
echo '
<div class="box box-center-large box-warning text-center">
<div class="box-header with-border">
<h3 class="box-title">'.(!$dbo->isInstalled() ? tr('Installazione') : tr('Aggiornamento')).'</h3>
<div class="card card-warning card-center-large text-center">
<div class="card-header">
<h3 class="card-title"><i class="fa fa-refresh"></i> '.(!$dbo->isInstalled() ? tr('Installazione') : tr('Aggiornamento')).'</h3>
</div>
<div class="box-body">';
<div class="card-body">';
if (!$dbo->isInstalled()) {
echo '
<p><strong>'.tr("E' la prima volta che avvii OpenSTAManager e non hai ancora installato il database").'.</strong></p>';
@ -156,9 +156,9 @@ if (filter('action') == 'do_update') {
}
echo '
<p>'.tr("Premi il tasto _BUTTON_ per procedere con l'".(!$dbo->isInstalled() ? tr('installazione') : tr('aggiornamento')).'!', [
'_BUTTON_' => '<b>"'.$button.'"</b>',
]).'</p>
<input type="button" class="btn btn-primary" value="'.$button.'" onclick="continue_update()" id="contine_button">
'_BUTTON_' => '<b>"'.$button.'"</b>',
]).'</p>
<input type="button" class="btn btn-primary" value="'.$button.'" onclick="continue_update()" id="continue_button">
<script>
function continue_update(){
@ -173,7 +173,7 @@ if (filter('action') == 'do_update') {
function(){
$("#progress").show();
$("#result").load("index.php?action=do_update&firstuse='.$firstuse.'");
$("#contine_button").remove();
$("#continue_button").remove();
}, function(){});
}
</script>
@ -185,21 +185,20 @@ if (filter('action') == 'do_update') {
</div>
</div>
<hr>
<div class="box box-info text-center collapsed-box">
<div class="box-header with-border">
<h3 class="box-title"><a class="clickable" data-widget="collapse">'.tr('Log').'</a></h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
<div class="card card-info text-center collapsed-card">
<div class="card-header with-border">
<h3 class="card-title"><a class="clickable" data-card-widget="collapse">'.tr('Log').'</a></h3>
<div class="card-tools pull-right">
<button type="button" class="btn btn-card-tool" data-card-widget="collapse"><i class="fa fa-plus"></i></button>
</div>
</div>
<div class="box-body info text-left"></div>
<div class="card-body info text-left"></div>
</div>
</div>
<div id="result"></div>';
$total = 0;
$updates = Update::getTodoUpdates();
foreach ($updates as $update) {
if ($update['sql'] && (!empty($update['done']) || is_null($update['done']))) {
$queries = readSQLFile(base_dir().'/'.$update['directory'].$update['filename'].'.sql', ';');
@ -216,45 +215,46 @@ if (filter('action') == 'do_update') {
}
echo '
<script>
$(document).ready(function(){
$(".login-box").fadeOut();
<script>
$(document).ready(function(){
$(".login-box").fadeOut();
count = '.count($updates).';
current = 0;
versions = [];
count = '.count($updates).';
current = 0;
versions = [];
progress = 0;
total = '.$total.';
});
progress = 0;
total = '.$total.';
});
function addProgress(rate){
progress += rate;
percent = progress / total * 100;
percent = Math.round(percent);
percent = percent > 100 ? 100 : percent;
function addProgress(rate){
progress += rate;
percent = progress / total * 100;
percent = Math.round(percent);
percent = percent > 100 ? 100 : percent;
setPercent(percent);
}
setPercent(percent);
}
function setPercent(percent){
$("#progress .progress-bar").width(percent + "%");
$("#progress .progress-bar span").text(percent + "%");
}
function setPercent(percent){
$("#progress .progress-bar").width(percent + "%");
$("#progress .progress-bar span").text(percent + "%");
}
function addVersion(version){
if(versions.indexOf(version) === -1){
versions.push(version);
current += 1;
function addVersion(version){
if(versions.indexOf(version) === -1){
versions.push(version);
current += 1;
$("#progress .info").html($("#progress .info").html() + "<p><strong>'.tr('Aggiornamento _DONE_ di _TODO_ (_VERSION_)', [
'_DONE_' => '" + current + "',
'_TODO_' => '" + count + "',
'_VERSION_' => '" + version.trim() + "',
]).'</strong></p>");
}
}
</script>
</div>
</div>';
}
$("#progress .info").html($("#progress .info").html() + "<p><strong>'.tr('Aggiornamento _DONE_ di _TODO_ (_VERSION_)', [
'_DONE_' => '" + current + "',
'_TODO_' => '" + count + "',
'_VERSION_' => '" + version.trim() + "',
]).'</strong></p>");
}
}
</script>
</div>
</div>';
}

View File

@ -18,14 +18,16 @@
*/
use HTMLBuilder\HTMLBuilder;
use Models\Module;
use Models\Plugin;
include_once __DIR__.'/../core.php';
// Compatibilità per controller ed editor
if (!empty($id_plugin)) {
$structure = Plugins::get($id_plugin);
$structure = Plugin::find($id_plugin);
} else {
$structure = Modules::get($id_module);
$structure = Module::find($id_module);
}
if (!empty($id_plugin)) {
@ -42,7 +44,7 @@ if (!empty($id_plugin)) {
echo '
<h4>
<span class="'.(!empty($structure['help']) ? ' tip' : '').'"'.(!empty($structure['help']) ? ' title="'.prepareToField($structure['help']).'" data-position="bottom"' : '').' >
'.$structure['title'].(!empty($structure['help']) ? ' <i class="fa fa-question-circle-o"></i>' : '').'</span>';
'.$structure->getTranslation('title').(!empty($structure['help']) ? ' <i class="fa fa-question-circle-o"></i>' : '').'</span>';
if ($structure->hasAddFile()) {
echo '
@ -72,12 +74,13 @@ if (!empty($type) && $type != 'menu' && $type != 'custom') {
if (empty($id_plugin) && count(Modules::getSegments($id_module)) > 1) {
echo '
<div class="row">
<div class="col-md-4 pull-right">
{[ "type": "select", "name": "id_segment_", "required": 0, "ajax-source": "segmenti", "select-options": '.json_encode(['id_module' => $id_module]).', "value": "'.$_SESSION['module_'.$id_module]['id_segment'].'" ]}
</div>
</div>
<br>';
<div class="container">
<div class="row justify-content-end">
<div class="col-md-4">
{[ "type": "select", "name": "id_segment_", "required": 0, "ajax-source": "segmenti", "select-options": '.json_encode(['id_module' => $id_module]).', "value": "'.$_SESSION['module_'.$id_module]['id_segment'].'" ]}
</div>
</div>
</div>';
echo '
<script>
@ -97,13 +100,13 @@ if (!empty($type) && $type != 'menu' && $type != 'custom') {
$_SESSION['module_'.$id_module]['selected'] = [];
$selezione = array_keys($_SESSION['module_'.$id_module]['selected']);
$table_id = 'main_'.rand(0, 99);
$table_id = 'main_'.random_int(0, 99);
echo '
<table data-idmodule="'.$id_module.'" data-idplugin="'.$id_plugin.'" data-idparent="'.$id_record.'" data-selected="'.implode(';', $selezione).'" id="'.$table_id.'" width="100%" class="main-records'.(!empty($id_plugin) ? '-plugins' : '').' table table-condensed table-bordered">
<thead>
<tr>
<th id="th_selector"></th>';
<table data-idmodule="'.$id_module.'" data-idplugin="'.$id_plugin.'" data-idparent="'.$id_record.'" data-selected="'.implode(';', $selezione).'" id="'.$table_id.'" width="100%" class="table main-records table-hover table-striped '.(!empty($id_plugin) ? '-plugins' : '').'">
<thead>
<tr>
<th id="th_selector"></th>';
foreach ($total['fields'] as $key => $field) {
$attr_td = '';
$name = trim($field);

View File

@ -29,23 +29,23 @@ echo '
<input type="hidden" name="op" value="modifica-allegato">
<div class="row">';
if (sizeof($id_allegati) == 1) {
$allegato = Upload::find($id_allegati[0]);
echo '
if (sizeof($id_allegati) == 1) {
$allegato = Upload::find($id_allegati[0]);
echo '
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Nome').'", "name": "nome_allegato", "value": "'.$allegato->name.'" ]}
</div>
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Categoria').'", "name": "categoria_allegato", "value": "'.$allegato->category.'", "disabled": "'.intval(in_array($allegato->category, ['Fattura Elettronica'])).'" ]}
</div>';
} else {
$allegato = Upload::find($id_allegati[0]);
echo '
} else {
$allegato = Upload::find($id_allegati[0]);
echo '
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Categoria').'", "name": "categoria_allegato", "value": "" ]}
</div>';
}
echo '
}
echo '
</div>
<!-- PULSANTI -->
@ -90,7 +90,7 @@ $(document).ready(function () {
update(results);
},
onSelect: function (item) {
input.value = item.label;
input.value = item.badge;
},
});
});

View File

@ -20,7 +20,9 @@
include_once __DIR__.'/../../core.php';
use Modules\DDT\DDT;
use Modules\DDT\Stato as StatoDDT;
use Modules\Ordini\Ordine;
use Modules\Ordini\Stato as StatoOrdine;
// Informazioni generali sulla riga
$source_type = filter('riga_type');
@ -43,7 +45,7 @@ include_once __DIR__.'/righe_riferimenti.php';
echo '
</div>
<div class="alert alert-info" id="box-loading-riferimenti">
<div class="alert alert-info" id="card-loading-riferimenti">
<i class="fa fa-spinner fa-spin"></i> '.tr('Caricamento in corso').'...
</div>';
@ -52,7 +54,8 @@ $direzione_richiesta = $source->getDocument()->direzione == 'entrata' ? 'uscita'
// Individuazione DDT disponibili
$ddt = DDT::whereHas('stato', function ($query) {
$query->where('descrizione', '!=', 'Bozza');
$id_stato = (new StatoDDT())->getByField('title', 'Bozza', Models\Locale::getPredefined()->id);
$query->where('id', '!=', $id_stato);
})->whereHas('tipo', function ($query) use ($direzione_richiesta) {
$query->where('dir', '=', $direzione_richiesta);
})->get();
@ -67,7 +70,8 @@ foreach ($ddt as $elemento) {
// Individuazione ordini disponibili
$tipo_ordini = $direzione_richiesta == 'entrata' ? 'cliente' : 'fornitore';
$ordini = Ordine::whereHas('stato', function ($query) {
$query->where('descrizione', '!=', 'Bozza');
$id_stato = (new StatoOrdine())->getByField('title', 'Bozza', Models\Locale::getPredefined()->id);
$query->where('id', '!=', $id_stato);
})->whereHas('tipo', function ($query) use ($direzione_richiesta) {
$query->where('dir', '=', $direzione_richiesta);
})->get();
@ -80,12 +84,12 @@ foreach ($ordini as $elemento) {
}
echo '
<div class="box">
<div class="box-header">
<h3 class="box-title">'.tr('Nuovo riferimento').'</h3>
<div class="card">
<div class="card-header">
<h3 class="card-title">'.tr('Nuovo riferimento').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<div class="row">
<div class="col-md-12">
{[ "type": "select", "label": "'.tr('Documento').'", "name": "documento_riferimento", "required": 1, "values": '.$documenti_disponibili->toJson().' ]}
@ -94,7 +98,7 @@ echo '
<div id="righe_documento"></div>
<div class="alert alert-info" id="box-loading">
<div class="alert alert-info" id="card-loading">
<i class="fa fa-spinner fa-spin"></i> '.tr('Caricamento in corso').'...
</div>
</div>
@ -106,8 +110,8 @@ echo '
<script>
$(document).ready(function(){
$("#box-loading").hide();
$("#box-loading-riferimenti").hide();
$("#card-loading").hide();
$("#card-loading-riferimenti").hide();
});
var riferimenti = JSON.parse(\''.json_encode($elenco_riferimenti).'\');
@ -126,7 +130,7 @@ echo '
});
function caricaRiferimenti() {
let loader = $("#box-loading-riferimenti");
let loader = $("#card-loading-riferimenti");
let content = $("#righe_riferimenti");
loader.show();
@ -154,7 +158,7 @@ echo '
function caricaRighe(tipo_documento, id_documento){
let content = $("#righe_documento");
let loader = $("#box-loading");
let loader = $("#card-loading");
loader.show();
content.html("");

View File

@ -42,14 +42,14 @@ echo '
<tbody>';
$righe = $documento->getRighe();
foreach ($righe as $riga) {
$riga_class = get_class($riga);
$righe = $documento->getRighe();
foreach ($righe as $riga) {
$riga_class = get_class($riga);
$riferimento_locale = $riga_class.'|'.$riga->id;
$presente = in_array($riferimento_locale, $riferimenti);
$riferimento_locale = $riga_class.'|'.$riga->id;
$presente = in_array($riferimento_locale, $riferimenti);
echo '
echo '
<tr data-id="'.$riga->id.'" data-type="'.$riga_class.'">
<td>'.$riga->descrizione.'</td>
<td>'.numberFormat($riga->qta_rimanente, 'qta').' / '.numberFormat($riga->qta, 'qta').'</td>
@ -59,8 +59,8 @@ echo '
</button>
</td>
</tr>';
}
}
echo '
echo '
</tbody>
</table>';

View File

@ -17,14 +17,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use Models\Module;
use Util\FileSystem;
include_once __DIR__.'/../core.php';
include_once __DIR__ . '/../core.php';
$paths = App::getPaths();
$user = Auth::user();
$pageTitle = !empty($pageTitle) ? $pageTitle : $structure->title;
$pageTitle = !empty($pageTitle) ? $pageTitle : $structure->getTranslation('title');
$lang = (empty($lang) || $lang == '|lang|') ? 'it_IT' : $lang;
@ -34,31 +35,31 @@ echo '<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>'.$pageTitle.' - '.tr('OpenSTAManager').'</title>
<title>' . $pageTitle . ' - ' . tr('OpenSTAManager') . '</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<meta name="robots" content="noindex,nofollow">
<meta name="description" content="'.tr('OpenSTAManager, il software gestionale open source per assistenza tecnica e fatturazione elettronica.').'">
<meta name="description" content="' . tr('OpenSTAManager, il software gestionale open source per assistenza tecnica e fatturazione elettronica.') . '">
<meta name="author" content="DevCode s.r.l.">
<link href="'.$paths['img'].'/favicon.png" rel="icon" type="image/x-icon" />';
<link href="' . $paths['img'] . '/favicon.png" rel="icon" type="image/x-icon" />';
if (file_exists(base_dir().'/manifest.json')) {
if (file_exists(base_dir() . '/manifest.json')) {
echo '
<link rel="manifest" href="'.base_path().'/manifest.json?r='.rand().'">';
<link rel="manifest" href="' . base_path() . '/manifest.json?r=' . random_int(0, mt_getrandmax()) . '">';
}
// CSS
foreach (App::getAssets()['css'] as $style) {
echo '
<link rel="stylesheet" type="text/css" media="all" href="'.$style.'"/>';
<link rel="stylesheet" type="text/css" media="all" href="' . $style . '"/>';
}
// Print CSS
foreach (App::getAssets()['print'] as $style) {
echo '
<link rel="stylesheet" type="text/css" media="print" href="'.$style.'"/>';
<link rel="stylesheet" type="text/css" media="print" href="' . $style . '"/>';
}
if (Auth::check()) {
@ -66,15 +67,15 @@ if (Auth::check()) {
<script>
search = []';
$array = $_SESSION['module_'.$id_module];
$array = $_SESSION['module_' . $id_module];
if (!empty($array)) {
foreach ($array as $field => $value) {
if (!empty($value) && string_starts_with($field, 'search_')) {
$field_name = str_replace('search_', '', $field);
echo '
search.push("search_'.$field_name.'");
search["search_'.$field_name.'"] = "'.addslashes($value).'";';
search.push("search_' . $field_name . '");
search["search_' . $field_name . '"] = "' . addslashes($value) . '";';
}
}
}
@ -97,6 +98,7 @@ if (Auth::check()) {
'nextMonth' => tr('Mese prossimo'),
'thisYear' => tr("Quest'anno"),
'lastYear' => tr('Anno scorso'),
'lastYear_thisYear' => tr("Quest'anno + prec."),
'apply' => tr('Applica'),
'cancel' => tr('Annulla'),
'from' => tr('Da'),
@ -125,95 +127,95 @@ if (Auth::check()) {
];
foreach ($translations as $key => $value) {
echo '
'.$key.': "'.addslashes($value).'",';
' . $key . ': "' . addslashes($value) . '",';
}
echo '
allegati: {
messaggio: "'.tr('Clicca o trascina qui per caricare uno o più file').'",
maxFilesize: "'.tr('Dimensione massima: _SIZE_ MB').'",
errore: "'.tr('Errore').'",
modifica: "'.tr('Modifica allegato').'",
elimina: "'.tr('Vuoi eliminare questo file?').'",
procedi: "'.tr('Procedi').'",
messaggio: "' . tr('Clicca o trascina qui per caricare uno o più file') . '",
maxFilesize: "' . tr('Dimensione massima: _SIZE_ MB') . '",
errore: "' . tr('Errore') . '",
modifica: "' . tr('Modifica allegato') . '",
elimina: "' . tr('Vuoi eliminare questo file?') . '",
procedi: "' . tr('Procedi') . '",
},
ajax: {
"missing": {
"title": "'.tr('Errore').'",
"text": "'.tr('Alcuni campi obbligatori non sono stati compilati correttamente').'",
"title": "' . tr('Errore') . '",
"text": "' . tr('Alcuni campi obbligatori non sono stati compilati correttamente') . '",
},
"error": {
"title": "'.tr('Errore').'",
"text": "'.tr('Errore durante il salvataggio del record').'",
"title": "' . tr('Errore') . '",
"text": "' . tr('Errore durante il salvataggio del record') . '",
}
},
password: {
"wordMinLength": "'.tr('La password è troppo corta').'",
"wordMaxLength": "'.tr('La password è troppo lunga').'",
"wordInvalidChar": "'.tr('La password contiene un carattere non valido').'",
"wordNotEmail": "'.tr('Non usare la tua e-mail come password').'",
"wordSimilarToUsername": "'.tr('La password non può contenere il tuo nome').'",
"wordTwoCharacterClasses": "'.tr('Usa classi di caratteri diversi').'",
"wordRepetitions": "'.tr('La password contiene ripetizioni').'",
"wordSequences": "'.tr('La password contiene sequenze').'",
"errorList": "'.tr('Attenzione').':",
"veryWeak": "'.tr('Molto debole').'",
"weak": "'.tr('Debole').'",
"normal": "'.tr('Normale').'",
"medium": "'.tr('Media').'",
"strong": "'.tr('Forte').'",
"veryStrong": "'.tr('Molto forte').'",
"wordMinLength": "' . tr('La password è troppo corta') . '",
"wordMaxLength": "' . tr('La password è troppo lunga') . '",
"wordInvalidChar": "' . tr('La password contiene un carattere non valido') . '",
"wordNotEmail": "' . tr('Non usare la tua e-mail come password') . '",
"wordSimilarToUsername": "' . tr('La password non può contenere il tuo nome') . '",
"wordTwoCharacterClasses": "' . tr('Usa classi di caratteri diversi') . '",
"wordRepetitions": "' . tr('La password contiene ripetizioni') . '",
"wordSequences": "' . tr('La password contiene sequenze') . '",
"errorList": "' . tr('Attenzione') . ':",
"veryWeak": "' . tr('Molto debole') . '",
"weak": "' . tr('Debole') . '",
"normal": "' . tr('Normale') . '",
"medium": "' . tr('Media') . '",
"strong": "' . tr('Forte') . '",
"veryStrong": "' . tr('Molto forte') . '",
},
datatables: {
"emptyTable": "'.tr('Nessun dato presente nella tabella').'",
"info": "'.tr('Vista da _START_ a _END_ di _TOTAL_ elementi').'",
"infoEmpty": "'.tr('Vista da 0 a 0 di 0 elementi').'",
"infoFiltered": "('.tr('filtrati da _MAX_ elementi totali').')",
"emptyTable": "' . tr('Nessun dato presente nella tabella') . '",
"info": "' . tr('Vista da _START_ a _END_ di _TOTAL_ elementi') . '",
"infoEmpty": "' . tr('Vista da 0 a 0 di 0 elementi') . '",
"infoFiltered": "(' . tr('filtrati da _MAX_ elementi totali') . ')",
"infoPostFix": "",
"lengthMenu": "'.tr('Visualizza _MENU_ elementi').'",
"lengthMenu": "' . tr('Visualizza _MENU_ elementi') . '",
"loadingRecords": " ",
"processing": "'.tr('Elaborazione').'...",
"search": "'.tr('Cerca').':",
"zeroRecords": "'.tr('La ricerca non ha portato alcun risultato').'.",
"processing": "' . tr('Elaborazione') . '...",
"search": "' . tr('Cerca') . ':",
"zeroRecords": "' . tr('La ricerca non ha portato alcun risultato') . '.",
"paginate": {
"first": "'.tr('Inizio').'",
"previous": "'.tr('Precedente').'",
"next": "'.tr('Successivo').'",
"last": "'.tr('Fine').'"
"first": "' . tr('Inizio') . '",
"previous": "' . tr('Precedente') . '",
"next": "' . tr('Successivo') . '",
"last": "' . tr('Fine') . '"
},
},
};
globals = {
rootdir: "'.base_path().'",
js: "'.$paths['js'].'",
css: "'.$paths['css'].'",
img: "'.$paths['img'].'",
rootdir: "' . base_path() . '",
js: "' . $paths['js'] . '",
css: "' . $paths['css'] . '",
img: "' . $paths['img'] . '",
id_module: "'.$id_module.'",
id_record: "'.$id_record.'",
id_module: "' . $id_module . '",
id_record: "' . $id_record . '",
is_mobile: '.isMobile().',
is_mobile: ' . isMobile() . ',
cifre_decimali: '.setting('Cifre decimali per importi').',
cifre_decimali: ' . setting('Cifre decimali per importi') . ',
timestamp_format: "'.formatter()->getTimestampPattern().'",
date_format: "'.formatter()->getDatePattern().'",
time_format: "'.formatter()->getTimePattern().'",
decimals: "'.formatter()->getNumberSeparators()['decimals'].'",
thousands: "'.formatter()->getNumberSeparators()['thousands'].'",
currency: "'.currency().'",
timestamp_format: "' . formatter()->getTimestampPattern() . '",
date_format: "' . formatter()->getDatePattern() . '",
time_format: "' . formatter()->getTimePattern() . '",
decimals: "' . formatter()->getNumberSeparators()['decimals'] . '",
thousands: "' . formatter()->getNumberSeparators()['thousands'] . '",
currency: "' . currency() . '",
search: search,
translations: translations,
locale: "'.(explode('_', $lang)[0]).'",
full_locale: "'.$lang.'",
locale: "' . explode('_', $lang)[0] . '",
full_locale: "' . $lang . '",
start_date: "'.$_SESSION['period_start'].'",
start_date_formatted: "'.Translator::dateToLocale($_SESSION['period_start']).'",
end_date: "'.$_SESSION['period_end'].'",
end_date_formatted: "'.Translator::dateToLocale($_SESSION['period_end']).'",
minute_stepping: '.setting('Numero di minuti di avanzamento delle sessioni delle attività').',
start_date: "' . $_SESSION['period_start'] . '",
start_date_formatted: "' . Translator::dateToLocale($_SESSION['period_start']) . '",
end_date: "' . $_SESSION['period_end'] . '",
end_date_formatted: "' . Translator::dateToLocale($_SESSION['period_end']) . '",
minute_stepping: ' . setting('Numero di minuti di avanzamento delle sessioni delle attività') . ',
collapse_plugin_sidebar: '.intval(setting('Nascondere la barra dei plugin di default')).',
collapse_plugin_sidebar: ' . intval(setting('Nascondere la barra dei plugin di default')) . ',
ckeditorToolbar: [
["Undo","Redo","-","Cut","Copy","Paste","PasteText","PasteFromWord","-","SpellChecker", "Scayt", "-","Link","Unlink","-","Bold","Italic","Underline","Superscript","SpecialChar","HorizontalRule","-","JustifyLeft","JustifyCenter","JustifyRight","JustifyBlock","-","NumberedList","BulletedList","Outdent","Indent","Blockquote","-","Styles","Format","Image","Table", "TextColor", "BGColor", "EmojiPanel" ],
@ -236,46 +238,46 @@ if (Auth::check()) {
{ name: "tools", items : [ "Maximize", "ShowBlocks" ] },
{ name: "about", items: [ "About" ] }
],
order_manager_id: "'.($dbo->isInstalled() ? Modules::get('Stato dei servizi')['id'] : '').'",
dataload_page_buffer: '.setting('Lunghezza in pagine del buffer Datatables').',
tempo_attesa_ricerche: '.setting('Tempo di attesa ricerche in secondi').',
restrict_summables_to_selected: '.setting('Totali delle tabelle ristretti alla selezione').',
snapDuration: "'.setting('Tempo predefinito di snap attività sul calendario').'"
order_manager_id: "' . ($dbo->isInstalled() ? (new Module())->getByField('title', 'Stato dei servizi', Models\Locale::getPredefined()->id) : '') . '",
dataload_page_buffer: ' . setting('Lunghezza in pagine del buffer Datatables') . ',
tempo_attesa_ricerche: ' . setting('Tempo di attesa ricerche in secondi') . ',
restrict_summables_to_selected: ' . setting('Totali delle tabelle ristretti alla selezione') . ',
snapDuration: "' . setting('Tempo predefinito di snap attività sul calendario') . '"
};
</script>';
} else {
echo '
<script>
globals = {
rootdir: "'.base_path().'",
rootdir: "' . base_path() . '",
search: {},
translations: {
password: {
"wordMinLength": "'.tr('La tua password è troppo corta').'",
"wordMaxLength": "'.tr('La tua password è troppo lunga').'",
"wordInvalidChar": "'.tr('La tua password contiene un carattere non valido').'",
"wordNotEmail": "'.tr('Non usare la tua e-mail come password').'",
"wordSimilarToUsername": "'.tr('La tua password non può contenere il tuo nome').'",
"wordTwoCharacterClasses": "'.tr('Usa classi di caratteri diversi').'",
"wordRepetitions": "'.tr('Troppe ripetizioni').'",
"wordSequences": "'.tr('La tua password contiene sequenze').'",
"errorList": "'.tr('Errori').':",
"veryWeak": "'.tr('Molto debole').'",
"weak": "'.tr('Debole').'",
"normal": "'.tr('Normale').'",
"medium": "'.tr('Media').'",
"strong": "'.tr('Forte').'",
"veryStrong": "'.tr('Molto forte').'",
"wordMinLength": "' . tr('La tua password è troppo corta') . '",
"wordMaxLength": "' . tr('La tua password è troppo lunga') . '",
"wordInvalidChar": "' . tr('La tua password contiene un carattere non valido') . '",
"wordNotEmail": "' . tr('Non usare la tua e-mail come password') . '",
"wordSimilarToUsername": "' . tr('La tua password non può contenere il tuo nome') . '",
"wordTwoCharacterClasses": "' . tr('Usa classi di caratteri diversi') . '",
"wordRepetitions": "' . tr('Troppe ripetizioni') . '",
"wordSequences": "' . tr('La tua password contiene sequenze') . '",
"errorList": "' . tr('Errori') . ':",
"veryWeak": "' . tr('Molto debole') . '",
"weak": "' . tr('Debole') . '",
"normal": "' . tr('Normale') . '",
"medium": "' . tr('Media') . '",
"strong": "' . tr('Forte') . '",
"veryStrong": "' . tr('Molto forte') . '",
},
},
timestamp_format: "'.formatter()->getTimestampPattern().'",
date_format: "'.formatter()->getDatePattern().'",
time_format: "'.formatter()->getTimePattern().'",
timestamp_format: "' . formatter()->getTimestampPattern() . '",
date_format: "' . formatter()->getDatePattern() . '",
time_format: "' . formatter()->getTimePattern() . '",
locale: "'.(explode('_', $lang)[0]).'",
full_locale: "'.$lang.'",
locale: "' . explode('_', $lang)[0] . '",
full_locale: "' . $lang . '",
};
</script>';
}
@ -283,7 +285,7 @@ if (Auth::check()) {
// JS
foreach (App::getAssets()['js'] as $js) {
echo '
<script type="text/javascript" charset="utf-8" src="'.$js.'"></script>';
<script type="text/javascript" charset="utf-8" src="' . $js . '"></script>';
}
// Impostazioni di default per gli alert
@ -293,20 +295,20 @@ echo '
buttonsStyling: false,
confirmButtonClass: "btn btn-lg btn-primary",
cancelButtonClass: "btn btn-lg",
cancelButtonText: "'.tr('Annulla').'",
cancelButtonText: "' . tr('Annulla') . '",
});
</script>';
if (Auth::check()) {
if (setting('Abilita esportazione Excel e PDF')) {
echo '
<script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js"></script>
<script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js"></script>';
<script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/pdfmake.min.js"></script>
<script type="text/javascript" charset="utf-8" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/vfs_fonts.min.js"></script>';
}
if (setting('Attiva scorciatoie da tastiera')) {
echo '<script type="text/javascript" charset="utf-8" src="'.App::getPaths()['js'].'/hotkeys-js/hotkeys.min.js"></script>';
echo '<script type="text/javascript" charset="utf-8" src="' . App::getPaths()['js'] . '/hotkeys-js/hotkeys.min.js?v=' . $version . '"></script>';
echo '
<script>
@ -336,24 +338,36 @@ if (Auth::check()) {
}
}
// Set the group theme
if (isset($user)) {
if ($user->getThemeAttribute()) {
$theme = $user->getThemeAttribute();
}
}
if ($theme == 'default') {
$theme = 'sidebar-dark-secondary';
} else {
$theme = 'bg-'.$theme;
}
$settings_collapse = session_get('settings.sidebar-collapse') ? 1 : 0;
$hide_sidebar = Auth::check() && (setting('Nascondere la barra sinistra di default') || $settings_collapse);
echo '
</head>
<body class="sidebar-mini skin-'.$theme.(!empty($hide_sidebar) ? ' sidebar-collapse' : '').(!Auth::check() ? ' hold-transition login-page' : '').'">
<div class="'.(!Auth::check() ? '' : 'wrapper').'">';
<body class="sidebar-mini layout-fixed '. (!empty($hide_sidebar) ? ' sidebar-collapse' : '') . (!Auth::check() ? ' hold-transition login-page' : '') . '">
<div class="' . (!Auth::check() ? '' : 'wrapper') . '">';
if (Auth::check()) {
$calendar_color_label = ($_SESSION['period_start'] != date('Y').'-01-01' || $_SESSION['period_end'] != date('Y').'-12-31') ? 'danger' : 'default';
$calendar_color_label = ($_SESSION['period_start'] != date('Y') . '-01-01' || $_SESSION['period_end'] != date('Y') . '-12-31') ? 'danger' : 'secondary';
echo '
<!-- Loader principale -->
<div id="main_loading">
<div>
<i class="fa fa-cog fa-spin text-danger"></i>
</div>
</div>
<!-- Preloader -->
<div id="main_loading" class="preloader flex-column justify-content-center align-items-center">
<img class="animation__shake" src="'.$rootdir.'/assets/dist/img/logo.png" alt="OSM" height="60" width="60">
</div>
<!-- Loader secondario -->
<div id="mini-loader" style="display:none;">
@ -363,138 +377,132 @@ if (Auth::check()) {
<!-- Loader senza overlay -->
<div id="tiny-loader" style="display:none;"></div>
<header class="main-header">
<a href="'.tr('https://www.openstamanager.com').'" class="logo" title="'.tr("Il gestionale open source per l'assistenza tecnica e la fatturazione").'" target="_blank">
<!-- mini logo for sidebar mini 50x50 pixels -->
<span class="logo-mini">'.tr('OSM').'</span>
<!-- logo for regular state and mobile devices -->
<span class="logo-lg">'.tr('OpenSTAManager').'</span>
</a>
<!-- Header Navbar: style can be found in header.less -->
<nav class="navbar navbar-static-top" role="navigation">
<!-- Navbar -->
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fa fa-bars"></i></a>
</li>
<!-- Sidebar toggle button-->
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
<span class="sr-only">'.tr('Mostra/nascondi menu').'</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<li class="nav-item">
<a href="#" id="daterange" class="nav-link" role="button">
<i class="fa fa-calendar"></i> <i class="fa fa-caret-down"></i>
</a>
</li>
<li class="nav-item d-none d-sm-inline-block">
<a class="nav-link text-' . $calendar_color_label . '">
' . Translator::dateToLocale($_SESSION['period_start']) . ' - ' . Translator::dateToLocale($_SESSION['period_end']) . '
</a>
</li>
</ul>
<!-- Navbar Left Menu -->
<div class="navbar-left">
<ul class="nav navbar-nav">
<li><a href="#" id="daterange" role="button" >
<i class="fa fa-calendar" style="color:inherit"></i> <i class="fa fa-caret-down" style="color:inherit"></i>
</a></li>
<li><a style="cursor:default;padding:0px;padding-right:5px;padding-left:5px;margin-top:15px;" class="label label-'.$calendar_color_label.'">
'.Translator::dateToLocale($_SESSION['period_start']).' - '.Translator::dateToLocale($_SESSION['period_end']).'
</a></li>
</ul>
</div>
<!-- Navbar Right Menu -->
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="nav-button hide"><a href="'.base_path().'/bug.php" class="tip nav-button" title="'.tr('Segnalazione bug').'">
<i class="fa fa-bug"></i>
</a></li>
<li class="nav-button" >
<p style="padding:10px 15px;">&nbsp;</p>
</li>';
if ($user->gruppo == 'Amministratori') {
<!-- Navbar Right Menu -->
<ul class="navbar-nav ml-auto">';
// Visualizzo gli hooks solo se non sono stati disabilitati
if (!$config['disable_hooks']) {
echo '
<li class="dropdown notifications-menu nav-button">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-bell-o"></i>
<span id="hooks-label" class="label label-warning">
<span id="hooks-loading"><i class="fa fa-spinner fa-spin"></i></span>
<span id="hooks-notified"></span>
<span id="hooks-counter" class="hide">0</span>
<span id="hooks-number" class="hide">0</span>
</span>
<div class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-bell-o"></i>
<span id="hooks-badge" class="badge badge-warning">
<span id="hooks-loading"><i class="fa fa-spinner fa-spin"></i></span>
<span id="hooks-notified"></span>
<span id="hooks-counter" class="d-none">0</span>
<span id="hooks-number" class="d-none">0</span>
</span>
</a>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
<a href="#" class="dropdown-item">
<span class="small" id="hooks-header"></span>
</a>
<ul class="dropdown-menu">
<li class="header"><span class="small" id="hooks-header"></span></li>
<li><ul class="menu" id="hooks">
</ul></li>
</ul>
</li>
<li class="nav-button"><a href="#" onclick="window.print()" class="tip nav-button" title="'.tr('Stampa').'">
<i class="fa fa-print"></i>
</a></li>
<li class="nav-button"><a href="'.base_path().'/log.php" class="tip nav-button" title="'.tr('Log accessi').'">
<i class="fa fa-book"></i>
</a></li>';
<div id="hooks"></div>
</div>
</div>';
}
echo '
<li class="nav-button"><a data-href="'.base_path().'/shortcuts.php" data-title="'.tr('Scorciatoie da tastiera').'" class="tip nav-button" title="'.tr('Scorciatoie').'">
<i class="fa fa-keyboard-o"></i>
</a></li>
<li class="nav-item">
<a href="#" onclick="window.print()" class="nav-link" title="' . tr('Stampa') . '">
<i class="fa fa-print nav-icon"></i>
</a>
</li>
<li class="nav-button"><a href="'.base_path().'/info.php" class="tip nav-button" title="'.tr('Informazioni').'">
<i class="fa fa-info"></i>
</a></li>
<li class="nav-item">
<a href="' . base_path() . '/log.php" class="nav-link" title="' . tr('Log accessi') . '">
<i class="fa fa-book nav-icon"></i>
</a>
</li>
<li class="nav-button"><a href="'.base_path().'/index.php?op=logout" onclick="sessionStorage.clear()" class="bg-red tip" title="'.tr('Esci').'">
<i class="fa fa-power-off"></i>
</a></li>
</ul>
</div>
<li class="nav-item">
<a href="' . base_path() . '/shortcuts.php" class="nav-link" title="' . tr('Scorciatoie') . '">
<i class="fa fa-keyboard-o nav-icon"></i>
</a>
</li>
</nav>
</header>
<li class="nav-item">
<a href="' . base_path() . '/info.php" class="nav-link" title="' . tr('Informazioni') . '">
<i class="fa fa-info nav-icon"></i>
</a>
</li>
<aside class="main-sidebar">
<section class="sidebar">
<li class="nav-item">
<a href="' . base_path() . '/index.php?op=logout" onclick="sessionStorage.clear()" class="nav-link bg-danger" title="' . tr('Esci') . '">
<i class="fa fa-power-off nav-icon"></i>
</a>
</li>
</ul>
</nav>
<!-- /.navbar -->
<!-- Sidebar user panel -->
<div class="user-panel text-center info" style="height: 60px">
<div class="info">
<p><a href="'.base_path().'/modules/utenti/info.php">
'.$user['username'].'
</a></p>
<p id="datetime"></p>
</div>
<!-- Main Sidebar Container -->
<aside class="main-sidebar ' . $theme .' elevation-4">
<a href="' . tr('https://www.openstamanager.com') . '" class="brand-link" title="' . tr("Il gestionale open source per l'assistenza tecnica e la fatturazione") . '" target="_blank">
<img src="' . $rootdir . '/assets/dist/img/logo_completo.png" alt="' . tr("Il gestionale open source per l'assistenza tecnica e la fatturazione") . '" class="img-fluid">
<span class="brand-text font-weight-light">&nbsp;</span>
</a>
<a class="image" href="'.base_path().'/modules/utenti/info.php">';
<!-- Sidebar -->
<div class="sidebar">
<!-- Sidebar user panel (optional) -->
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
<div class="image">';
$user_photo = $user->photo;
if ($user_photo) {
echo '
<img src="'.$user_photo.'" class="img-circle pull-left" alt="'.$user['username'].'" />';
<img src="' . $user_photo . '" class="img-circle elevation-2" alt="' . $user['username'] . '" />';
} else {
echo '
<i class="fa fa-user-circle-o fa-3x pull-left" alt="'.tr('OpenSTAManager').'"></i>';
<i class="fa fa-user-circle-o fa-2x" alt="' . tr('Utente') . '"></i>';
}
echo '
</a>
</div>
<!-- search form -->
<div class="sidebar-form">
<div class="input-group">
<input type="text" name="q" class="form-control" id="supersearch" placeholder="'.tr('Cerca').'..."/>
<span class="input-group-btn">
<button class="btn btn-flat" id="search-btn" name="search" type="submit">
<i class="fa fa-search"></i>
</button>
</span>
</div>
<div class="info">
<a href="' . base_path() . '/modules/utenti/info.php" class="d-block">
' . $user['username'] . '
</a>
</div>
</div>
<!-- /.search form -->
<ul class="sidebar-menu">';
<!-- SidebarSearch Form -->
<div class="form-inline">
<div class="input-group" data-widget="sidebar-search">
<input class="form-control form-control-sidebar" id="supersearch" type="search" placeholder="' . tr('Cerca') . '" aria-label="' . tr('Cerca') . '">
<div class="input-group-append">
<button class="btn btn-sidebar">
<i class="fa fa-search fa-fw"></i>
</button>
</div>
</div>
</div>
<!-- Sidebar Menu -->
<nav class="mt-2">
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu">';
echo Modules::getMainMenu();
echo '
</ul>
@ -506,19 +514,19 @@ if (Auth::check()) {
// Menu laterale per la visualizzazione dei plugin
echo '
<aside class="control-sidebar control-sidebar-light">
<h4 class="text-center">'.tr('Plugin disponibili').'</h4>
<h4><i class="fa fa-plug"></i> ' . tr('Plugin') . '</h4>
<ul class="nav nav-tabs nav-pills nav-stacked">
<li data-toggle="control-sidebar" class="active btn-default">
<a data-toggle="tab" href="#tab_0">
<i class="'.$structure['icon'].'"></i> '.$structure['title'].'
<li data-toggle="control-sidebar" class="active btn-default nav-item">
<a class="nav-link" data-toggle="tab" href="#tab_0">
' . $structure->getTranslation('title') . '
</a>
</li>';
// Tab dei plugin
if (!empty($id_record)) {
$plugins = $dbo->fetchArray('SELECT id, title, options, options2 FROM zz_plugins WHERE idmodule_to='.prepare($id_module)." AND position='tab' AND enabled = 1 ORDER BY zz_plugins.order DESC");
$plugins = $dbo->fetchArray('SELECT `zz_plugins`.`id`, `title`, `options`, `options2` FROM `zz_plugins` LEFT JOIN `zz_plugins_lang` ON (`zz_plugins`.`id` = `zz_plugins_lang`.`id_record` AND `zz_plugins_lang`.`id_lang` = ' . prepare(Models\Locale::getDefault()->id) . ') WHERE `idmodule_to`=' . prepare($id_module) . " AND `position`='tab' AND `enabled` = 1 ORDER BY `zz_plugins`.`order` DESC");
foreach ($plugins as $plugin) {
//Badge count per record plugin
// Badge count per record plugin
$count = 0;
$opt = '';
if (!empty($plugin['options2'])) {
@ -533,12 +541,12 @@ if (Auth::check()) {
}
echo '
<li data-toggle="control-sidebar" class="btn-default" >
<a data-toggle="tab" href="#tab_'.$plugin['id'].'" id="link-tab_'.$plugin['id'].'">
'.$plugin['title'].'
<span class="badge pull-right">'.($count > 0 ? $count : '').'</span>
</a>
</li>';
<li data-widget="control-sidebar" class="btn-default nav-item" >
<a class="nav-link" data-widget="tab" href="#tab_' . $plugin['id'] . '" id="link-tab_' . $plugin['id'] . '">
' . $plugin['title'] . '
<span class="right badge badge-danger">' . ($count > 0 ? $count : '') . '</span>
</a>
</li>';
}
}
@ -547,12 +555,12 @@ if (Auth::check()) {
$notes = $structure->recordNotes($id_record);
echo '
<li data-toggle="control-sidebar" class="btn-default">
<a class="bg-info" data-toggle="tab" href="#tab_note" id="link-tab_note">
'.tr('Note interne').'
<span class="badge pull-right">'.($notes->count() ?: '').'</span>
</a>
</li>';
<li data-widget="control-sidebar" class="btn-default">
<a class="bg-info" data-widget="tab" href="#tab_note" id="link-tab_note">
<' . tr('Note interne') . '
<span class="badge pull-right">' . ($notes->count() ?: '') . '</span>
</a>
</li>';
}
// Tab per le checklist
@ -561,25 +569,23 @@ if (Auth::check()) {
$checklists_total = $structure->recordChecks($id_record);
echo '
<li data-toggle="control-sidebar" class="btn-default">
<a class="bg-info" data-toggle="tab" href="#tab_checks" id="link-tab_checks">
'.tr('Checklist').'
'.(($checklists_total->count() > 0) ?
'<span class="badge pull-right">'.$checklists_unchecked->count().tr(' / ').($checklists_total->count()).'</span>' : '').'
</a>
</li>';
<li data-widget="control-sidebar" class="btn-default">
<a class="bg-info" data-widget="tab" href="#tab_checks" id="link-tab_checks">
<' . tr('Checklist') . '
<' . ($checklists_total->count() > 0) ? '<span class="badge pull-right">' . $checklists_unchecked->count() . tr(' / ') . $checklists_total->count() . '</span>' : '' . '
</a>
</li>';
}
// Tab per le informazioni sulle operazioni
if (Auth::admin()) {
echo '
<li data-toggle="control-sidebar" class="btn-default">
<a class="bg-info" data-toggle="tab" href="#tab_info" id="link-tab_info">
'.tr('Info').'
</a>
</li>';
<li data-widget="control-sidebar" class="btn-default">
<a class="bg-info" data-widget="tab" href="#tab_info" id="link-tab_info">
<' . tr('Info') . '
</a>
</li>';
}
echo '
</ul>
</aside>
@ -588,12 +594,9 @@ if (Auth::check()) {
}
echo '
<!-- Right side column. Contains the navbar and content of the page -->
<aside class="content-wrapper">
<!-- Main content -->
<section class="content">
<div class="row">';
<!-- Main content -->
<div class="content-wrapper">
<section class="content">';
if (string_contains($_SERVER['SCRIPT_FILENAME'], 'editor.php')) {
$location = 'editor_right';
@ -601,9 +604,6 @@ if (Auth::check()) {
$location = 'controller_right';
}
echo '
<div class="col-md-12">';
// Eventuale messaggio personalizzato per l'installazione corrente
$extra_file = App::filepath('include/custom/extra', 'extra.php');
if ($extra_file) {
@ -616,24 +616,26 @@ if (Auth::check()) {
include_once $extra_file;
}
if (!empty($messages['info']) || !empty($messages['warning']) || !empty($messages['error'])) {
if (!empty($messages['warning']) || !empty($messages['error'])) {
echo '
<div class="box box-warning box-center">
<div class="box-header with-border text-center">
<h3 class="box-title">'.tr('Informazioni').'</h3>
<div class="card card-warning card-center">
<div class="card-header with-border text-center">
<h3 class="card-title">' . tr('Informazioni') . '</h3>
</div>
<div class="box-body">';
<div class="card-body">';
}
}
// Infomazioni
if (!empty($messages['info'])) {
foreach ($messages['info'] as $value) {
echo '
<div class="alert alert-success push">
<i class="fa fa-check"></i> '.$value.'
</div>';
echo '
<script>
$(document).ready( function(){
window.parent.toastr.success("' . $value . '", toastr.options);
});
</script>';
}
}
@ -642,7 +644,8 @@ if (!empty($messages['error'])) {
foreach ($messages['error'] as $value) {
echo '
<div class="alert alert-danger push">
<i class="fa fa-times"></i> '.$value.'
<h4><i class="fa fa fa-ban"></i> ' . tr('Errore') . '</h4>
' . $value . '
</div>';
}
}
@ -652,8 +655,8 @@ if (!empty($messages['warning'])) {
foreach ($messages['warning'] as $value) {
echo '
<div class="alert alert-warning push">
<i class="fa fa-warning"></i>
'.$value.'
<h4><i class="fa fa-warning"></i> ' . tr('Attenzione') . '</h4>
' . $value . '
</div>';
}
}
@ -671,12 +674,12 @@ if ($free_space < ($space_limit * (1024 ** 3))) {
echo '
<div class="callout callout-warning">
<h4>
<i class="fa fa-warning"></i> '.tr('Spazio in esaurimento').'
<i class="fa fa-warning"></i> ' . tr('Spazio in esaurimento') . '
</h4>
<p>'.tr('Lo spazio a disposizione del gestionale è in esaurimento: sono al momento disponibili _TOT_', [
'_TOT_' => FileSystem::formatBytes($free_space),
]).'.</p>
<p>'.tr('Questo può risultare un serio problema per la continuità di funzionamento del software, poiché le operazioni più espansive che richiedono spazio di archiviazione possono causare malfunzionamenti imprevisti').'. '.tr('Ad esempio, le attività di backup, caricamento di allegati o anche l\'utilizzo normale del gestionale potrebbero rendere i dati inaffidabili, provocando pertanto una perdita delle informazioni salvate').'.</p>
<p>'.tr('Contatta gli amministratori di sistema per risolvere al più presto il problema').'.</p>
<p>' . tr('Lo spazio a disposizione del gestionale è in esaurimento: sono al momento disponibili _TOT_', [
'_TOT_' => FileSystem::formatBytes($free_space),
]) . '.</p>
<p>' . tr('Questo può risultare un serio problema per la continuità di funzionamento del software, poiché le operazioni più espansive che richiedono spazio di archiviazione possono causare malfunzionamenti imprevisti') . '. ' . tr('Ad esempio, le attività di backup, caricamento di allegati o anche l\'utilizzo normale del gestionale potrebbero rendere i dati inaffidabili, provocando pertanto una perdita delle informazioni salvate') . '.</p>
<p>' . tr('Contatta gli amministratori di sistema per risolvere al più presto il problema') . '.</p>
</div>';
}

138
index.php
View File

@ -21,14 +21,24 @@ $skip_permissions = true;
include_once __DIR__.'/core.php';
use Carbon\Carbon;
use Illuminate\Database\QueryException;
$op = filter('op');
$microsoft = null;
if ($dbo->isConnected()) {
try {
$microsoft = $dbo->selectOne('zz_oauth2', '*', ['nome' => 'Microsoft', 'enabled' => 1, 'is_login' => 1]);
} catch (QueryException $e) {
}
}
// LOGIN
switch ($op) {
case 'login':
$username = post('username');
$password = post('password');
$password = $_POST['password'];
if ($dbo->isConnected() && $dbo->isInstalled() && auth()->attempt($username, $password)) {
$_SESSION['keep_alive'] = true;
@ -45,15 +55,15 @@ switch ($op) {
$_SESSION['period_end'] = date('Y').'-12-31';
}
// Rimozione log vecchi
//$dbo->query('DELETE FROM `zz_operations` WHERE DATE_ADD(`created_at`, INTERVAL 30*24*60*60 SECOND) <= NOW()');
// Rimozione log vecchi
// $dbo->query('DELETE FROM `zz_operations` WHERE DATE_ADD(`created_at`, INTERVAL 30*24*60*60 SECOND) <= NOW()');
} else {
$status = auth()->getCurrentStatus();
flash()->error(Auth::getStatus()[$status]['message']);
redirect(base_path().'/index.php');
exit();
exit;
}
break;
@ -62,7 +72,7 @@ switch ($op) {
Auth::logout();
redirect(base_path().'/index.php');
exit();
exit;
}
if (Auth::check() && isset($dbo) && $dbo->isConnected() && $dbo->isInstalled()) {
@ -73,7 +83,7 @@ if (Auth::check() && isset($dbo) && $dbo->isConnected() && $dbo->isInstalled())
} else {
redirect(base_path().'/index.php?op=logout');
}
exit();
exit;
}
// Modalità manutenzione
@ -97,84 +107,96 @@ include_once App::filepath('include|custom|', 'top.php');
// Controllo se è una beta e in caso mostro un warning
if (Update::isBeta()) {
echo '
<div class="clearfix">&nbsp;</div>
<div class="alert alert-warning alert-dismissable col-md-6 col-md-push-3 text-center fade in">
<i class="fa fa-warning"></i> <b>'.tr('Attenzione!').'</b> '.tr('Stai utilizzando una versione <b>non stabile</b> di OSM.').'
<div class="clearfix"></div>
<div class="alert alert-warning alert-dismissible col-md-6 offset-md-3 text-center show">
<i class="fa fa-exclamation-triangle"></i> <strong>'.tr('Attenzione!').'</strong> '.tr('Stai utilizzando una versione <b>non stabile</b> di OSM.').'
<button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
</div>';
</div>';
}
// Controllo se è una beta e in caso mostro un warning
if (Auth::isBrute()) {
echo '
<div class="box box-danger box-center" id="brute">
<div class="box-header with-border text-center">
<h3 class="box-title">'.tr('Attenzione').'</h3>
</div>
echo'
<div class="box box-danger" id="brute">
<div class="box-header with-border text-center">
<h3 class="box-title">'.tr('Attenzione').'</h3>
</div>
<div class="box-body text-center">
<p>'.tr('Sono stati effettuati troppi tentativi di accesso consecutivi!').'</p>
<p>'. tr('Tempo rimanente (in secondi)').': <span id="brute-timeout">'.(Auth::getBruteTimeout() + 1).'</span></p>
</div>
</div>
<div class="box-body text-center">
<p>'.tr('Sono stati effettuati troppi tentativi di accesso consecutivi!').'</p>
<p>'.tr('Tempo rimanente (in secondi)').': <span id="brute-timeout">'.(Auth::getBruteTimeout() + 1).'</span></p>
</div>
</div>
<script>
$(document).ready(function(){
$(".login-box").fadeOut();
brute();
});
<script>
$(document).ready(function(){
$(".login-box").hide();
brute();
});
function brute() {
var value = parseFloat($("#brute-timeout").html()) - 1;
$("#brute-timeout").html(value);
function brute() {
var value = parseFloat($("#brute-timeout").text()) - 1;
$("#brute-timeout").text(value);
if(value > 0){
setTimeout("brute()", 1000);
} else{
$("#brute").fadeOut();
$(".login-box").fadeIn();
}
}
</script>';
if(value > 0){
setTimeout(brute, 1000);
} else {
$("#brute").fadeOut();
$(".login-box").fadeIn();
}
}
</script>';
}
if (!empty(flash()->getMessage('error'))) {
echo '
<script>
$(document).ready(function(){
$(".login-box").effect("shake");
$(document).ready(function(){
$(".login-box").addClass("animated shake");
});
</script>';
}
echo '
<form action="?op=login" method="post" class="login-box box" autocomplete="off" >
<div class="box-header with-border text-center">
<img src="'.App::getPaths()['img'].'/logo_completo.png" class="img-responsive" alt="'.tr('OpenSTAManager, il software gestionale open source per assistenza tecnica e fatturazione elettronica').'">
</div>
<form action="?op=login" method="post" autocomplete="off">
<div class="login-box">
<div class="card card-outline card-orange">
<div class="card-header text-center">
<img src="'.App::getPaths()['img'].'/logo_completo.png" alt="'.tr('OpenSTAManager, il software gestionale open source per assistenza tecnica e fatturazione elettronica').'" class="img-fluid">
</div>
<div class="login-box-body box-body">
<div class="form-group input-group">
<span class="input-group-addon before"><i class="fa fa-user"></i> </span>
<input type="text" name="username" autocomplete="username" class="form-control" placeholder="'.tr('Nome utente').'"';
<div class="card-body">
<p class="login-box-msg">'.tr('Accedi con le tue credenziali').'</p>
<div class="input-group mb-3">
<input type="text" name="username" autocomplete="username" class="form-control" placeholder="'.tr('Nome utente').'"';
if (isset($username)) {
echo ' value="'.$username.'"';
}
echo ' required>
</div>
<div class="input-group-append">
<div class="input-group-text">
<i class="fa fa-user"></i>
</div>
</div>
</div>
{[ "type": "password", "name": "password", "autocomplete": "current-password", "placeholder": "'.tr('Password').'", "icon-before": "<i class=\"fa fa-lock\"></i>"]}
<div class="input-group mb-3">
{[ "type": "password", "name": "password", "autocomplete": "current-password", "placeholder": "'.tr('Password').'" ]}
</div>
<div class="text-right">
<small><a href="'.base_path().'/reset.php">'.tr('Password dimenticata?').'</a></small>
<button type="submit" class="btn btn-danger btn-block btn-flat">'.tr('Accedi').'</button>
<br>
<p><a href="'.base_path().'/reset.php">'.tr('Password dimenticata?').'</a></p>';
if ($microsoft) {
echo '
<div class="social-auth-links text-center">
<p>- oppure -</p>
<a href="'.base_path().'/oauth2_login.php?id='.$microsoft['id'].'" class="btn btn-block btn-social btn-primary btn-flat"><i class="fa fa-windows"></i>'.tr('Accedi con Microsoft').'</a>
</div>';
}
echo '
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" id="login" class="btn btn-danger btn-block">'.tr('Accedi').'</button>
</div>
<!-- box-footer -->
</form>
<!-- /.box -->

View File

@ -26,15 +26,15 @@ $paths = App::getPaths();
include_once App::filepath('include|custom|', 'top.php');
echo '
<div class="box">
<div class="box-header">
<div class="card">
<div class="card-header">
<img src="'.$paths['img'].'/logo_completo.png" class="pull-left img-responsive" width="300" alt="'.tr('OSM Logo').'">
<div class="pull-right">
<div class="float-right d-none d-sm-inline">
<i class="fa fa-info"></i> '.tr('Informazioni').'
</div>
</div>
<div class="box-body">';
<div class="card-body">';
if (file_exists(base_dir().'/assistenza.php')) {
include base_dir().'/assistenza.php';
@ -60,12 +60,12 @@ if (file_exists(base_dir().'/assistenza.php')) {
<div class="row">
<div class="col-md-6">
<div class="box box-primary">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-globe"></i> '.tr('Perchè software libero').'</h3>
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title text-uppercase"><i class="fa fa-globe"></i> '.tr('Perchè software libero').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr("Il progetto è software libero perchè permette a tutti di conoscere come funziona avendo il codice sorgente del programma e fornisce così la possibilità di studiare come funziona, modificarlo, adattarlo alle proprie esigenze e, in ambito commerciale, non obbliga l'utilizzatore ad essere legato allo stesso fornitore di assistenza").'.</p>
<p>'.tr("E' altrettanto importante sapere come funziona per conoscere come vengono trattati i VOSTRI dati, proteggendo così la vostra <b>privacy</b>").'.</p>
@ -83,23 +83,23 @@ if (file_exists(base_dir().'/assistenza.php')) {
</div>
<div class="col-md-6">
<div class="box box-warning">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-download"></i> '.tr('Aggiornamenti e nuove versioni').'</h3>
<div class="card card-warning">
<div class="card-header">
<h3 class="card-title text-uppercase"><i class="fa fa-download"></i> '.tr('Aggiornamenti e nuove versioni').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr("Tutti gli aggiornamenti e le nuove versioni sono disponibili all'indirizzo").':</p>
<a href="https://www.openstamanager.com/downloads/" target="_blank"><i class="fa fa-external-link"></i> www.openstamanager.com/downloads/</a>
</div>
</div>
<div class="box box-default">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-book"></i> '.tr('Guida e documentazione tecnica').'</h3>
<div class="card card-default">
<div class="card-header">
<h3 class="card-title text-uppercase"><i class="fa fa-book"></i> '.tr('Guida e documentazione tecnica').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr("La guida all'utilizzo di <strong>OpenSTAManager</strong> e la documentazione tecnica sono consultabili all'indirizzo").':</p>
<a href="https://docs.openstamanager.com/" target="_blank"><i class="fa fa-external-link"></i> docs.openstamanager.com/</a>
</div>
@ -109,12 +109,12 @@ if (file_exists(base_dir().'/assistenza.php')) {
<div class="row">
<div class="col-md-6">
<div class="box box-danger">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-group"></i> '.tr('Community').'</h3>
<div class="card card-danger">
<div class="card-header">
<h3 class="card-title text-uppercase"><i class="fa fa-group"></i> '.tr('Community').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr('La community è un componente importante in un progetto open-source perchè mette in contatto le persone tra di loro, utenti e programmatori').'.</p>
<p>'.tr('Con OpenSTAManager siamo presenti su').':</p>
@ -164,12 +164,12 @@ if (file_exists(base_dir().'/assistenza.php')) {
</div>
<div class="col-md-6">
<div class="box box-success">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-euro"></i> '.tr('Servizi a pagamento').'</h3>
<div class="card card-success">
<div class="card-header">
<h3 class="card-title text-uppercase"><i class="fa fa-euro"></i> '.tr('Servizi a pagamento').'</h3>
</div>
<div class="box-body">
<div class="card-body">
<p>'.tr('Per le aziende che hanno necessità di essere seguite da <b>supporto professionale</b> è disponibile un servizio di assistenza e supporto a pagamento').'.</p>
<p>'.tr("E' disponibile anche un <b>servizio cloud</b> su cui poter installare OpenSTAManager, in modo da non doverti più preoccupare di backup, aggiornamenti e gestione dei dati").'.</p>

View File

@ -95,12 +95,6 @@ function calcola_sconto($data)
/**
* Individua il valore della colonna order per i nuovi elementi di una tabella.
*
* @param $table
* @param $field
* @param $id
*
* @return mixed
*/
function orderValue($table, $field, $id)
{
@ -109,10 +103,6 @@ function orderValue($table, $field, $id)
/**
* Ricalcola il riordinamento righe di una tabella.
*
* @param $table
*
* @return mixed
*/
function reorderRows($table, $field, $id)
{
@ -172,14 +162,13 @@ function provvigioneInfo(Accounting $riga, $mostra_provigione = true)
/**
* Genera i riferimenti ai documenti del gestionale, attraverso l'interfaccia Common\ReferenceInterface.
*
* @param $document
* @param string $text Formato "Contenuto descrittivo _DOCUMENT_"
*
* @return string
*/
function reference($document, $text = null)
{
if (!empty($document) && !($document instanceof \Common\ReferenceInterface)) {
if (!empty($document) && !($document instanceof Common\ReferenceInterface)) {
return null;
}
@ -208,8 +197,6 @@ function reference($document, $text = null)
* Funzione che gestisce il parsing di uno sconto combinato e la relativa trasformazione in sconto fisso.
* Esempio: (40 + 10) % = 44 %.
*
* @param $combinato
*
* @return float|int
*/
function parseScontoCombinato($combinato)
@ -232,10 +219,7 @@ function parseScontoCombinato($combinato)
}
/**
* Funzione che gestisce il parsing di uno sconto combinato e la relativa trasformazione in sconto fisso.
* Esempio: (40 + 10) % = 44 %.
*
* @param $combinato
* Visualizza le informazioni del segmento.
*
* @return float|int
*/
@ -245,3 +229,157 @@ function getSegmentPredefined($id_module)
return $id_segment;
}
/**
* Funzione che visualizza i prezzi degli articoli nei listini.
*
* @return array
*/
function getPrezzoConsigliato($id_anagrafica, $direzione, $id_articolo, $riga = null)
{
if ($riga) {
$qta = $riga->qta;
$prezzo_unitario_corrente = $riga->prezzo_unitario_corrente;
$sconto_percentuale_corrente = $riga->sconto_percentuale;
} else {
$qta = 1;
}
$prezzi_ivati = setting('Utilizza prezzi di vendita comprensivi di IVA');
$show_notifica_prezzo = null;
$show_notifica_sconto = null;
$prezzo_unitario = 0;
$sconto = 0;
// Prezzi netti clienti / listino fornitore
$query = 'SELECT minimo, massimo,
sconto_percentuale,
'.($prezzi_ivati ? 'prezzo_unitario_ivato' : 'prezzo_unitario').' AS prezzo_unitario
FROM mg_prezzi_articoli
WHERE id_articolo = '.prepare($id_articolo).' AND dir = '.prepare($direzione).' AND id_anagrafica = '.prepare($id_anagrafica).'
ORDER BY minimo ASC, massimo DESC';
$prezzi = database()->fetchArray($query);
// Prezzi listini clienti
$query = 'SELECT sconto_percentuale AS sconto_percentuale_listino,
'.($prezzi_ivati ? 'prezzo_unitario_ivato' : 'prezzo_unitario').' AS prezzo_unitario_listino
FROM mg_listini
LEFT JOIN mg_listini_articoli ON mg_listini.id=mg_listini_articoli.id_listino
LEFT JOIN an_anagrafiche ON mg_listini.id=an_anagrafiche.id_listino
WHERE mg_listini.data_attivazione<=NOW()
AND (mg_listini_articoli.data_scadenza>=NOW() OR (mg_listini_articoli.data_scadenza IS NULL AND mg_listini.data_scadenza_predefinita>=NOW()))
AND mg_listini.attivo=1
AND id_articolo = '.prepare($id_articolo).'
AND dir = '.prepare($direzione).'
AND idanagrafica = '.prepare($id_anagrafica);
$listino = database()->fetchOne($query);
// Prezzi listini clienti sempre visibili
$query = 'SELECT mg_listini.nome, sconto_percentuale AS sconto_percentuale_listino_visibile,
'.($prezzi_ivati ? 'prezzo_unitario_ivato' : 'prezzo_unitario').' AS prezzo_unitario_listino_visibile
FROM mg_listini
LEFT JOIN mg_listini_articoli ON mg_listini.id=mg_listini_articoli.id_listino
WHERE mg_listini.data_attivazione<=NOW()
AND (mg_listini_articoli.data_scadenza>=NOW() OR (mg_listini_articoli.data_scadenza IS NULL AND mg_listini.data_scadenza_predefinita>=NOW()))
AND mg_listini.attivo=1 AND mg_listini.is_sempre_visibile=1 AND id_articolo = '.prepare($id_articolo).' AND dir = '.prepare($direzione);
$listini_sempre_visibili = database()->fetchArray($query);
if ($prezzi) {
foreach ($prezzi as $prezzo) {
if ($qta >= $prezzo['minimo'] && $qta <= $prezzo['massimo']) {
$show_notifica_prezzo = $prezzo['prezzo_unitario'] != $prezzo_unitario_corrente ? true : $show_notifica_prezzo;
$show_notifica_sconto = $prezzo['sconto_percentuale'] != $sconto_percentuale_corrente ? true : $show_notifica_sconto;
$prezzo_unitario = $prezzo['prezzo_unitario'];
$sconto = $prezzo['sconto_percentuale'];
continue;
}
if ($prezzo['minimo'] == null && $prezzo['massimo'] == null && $prezzo['prezzo_unitario'] != null) {
$show_notifica_prezzo = $prezzo['prezzo_unitario'] != $prezzo_unitario_corrente ? true : $show_notifica_prezzo;
$show_notifica_sconto = $prezzo['sconto_percentuale'] != $sconto_percentuale_corrente ? true : $show_notifica_sconto;
$prezzo_unitario = $prezzo['prezzo_unitario'];
$sconto = $prezzo['sconto_percentuale'];
continue;
}
}
}
if ($listino) {
$show_notifica_prezzo = $listino['prezzo_unitario_listino'] != $prezzo_unitario_corrente ? true : $show_notifica_prezzo;
$show_notifica_sconto = $listino['sconto_percentuale_listino'] != $sconto_percentuale_corrente ? true : $show_notifica_sconto;
$prezzo_unitario = $listino['prezzo_unitario_listino'];
$sconto = $listino['sconto_percentuale_listino'];
}
if ($listini_sempre_visibili) {
foreach ($listini_sempre_visibili as $listino_sempre_visibile) {
$show_notifica_prezzo = $listino_sempre_visibile['prezzo_unitario_listino_visibile'] != $prezzo_unitario_corrente ? true : $show_notifica_prezzo;
$show_notifica_sconto = $listino_sempre_visibile['sconto_percentuale_listino_visibile'] != $sconto_percentuale_corrente ? true : $show_notifica_sconto;
}
}
$result = [];
$result['show_notifica_prezzo'] = $show_notifica_prezzo;
$result['show_notifica_sconto'] = $show_notifica_sconto;
$result['prezzo_unitario'] = $prezzo_unitario;
$result['sconto'] = $sconto;
return $result;
}
/**
* Funzione PHP che controlla se un campo "cellulare" contiene già un prefisso telefonico:
*
* @return bool
*/
function checkPrefix($cellulare)
{
// Array di prefissi telefonici da controllare
$internationalPrefixes = ['+1', '+44', '+49', '+33', '+39']; // Esempi di prefissi
// Controlla se il campo "cellulare" inizia con uno dei prefissi
foreach ($internationalPrefixes as $prefix) {
if (strpos($cellulare, $prefix) === 0) {
return true; // Un prefisso è già presente
}
}
return false; // Nessun prefisso trovato
}
/**
* Funzione PHP che dato id_modulo restituisce un array contenente tutti i valori di "search_" per quel modulo.
*
* @param int $id_module
*
* @return array
*/
function getSearchValues($id_module)
{
$result = [];
if (isset($_SESSION['module_'.$id_module])) {
// Itera su tutti i valori
foreach ($_SESSION['module_'.$id_module] as $key => $value) {
// Controlla se la chiave inizia con "search_"
if (!empty($value) && string_starts_with($key, 'search_')) {
$result[str_replace(['search_', '-'], ['', ' '], $key)] = $value;
}
}
}
return $result;
}
/**
* Funzione PHP che controlla se l'articolo ha una distinta.
*
* @param int $id_articolo
*
* @return bool
*/
function hasArticoliFiglio($id_articolo)
{
if (function_exists('renderDistinta')) {
return database()->fetchOne('SELECT qta FROM mg_articoli_distinte WHERE id_articolo='.prepare($id_articolo));
} else {
return false;
}
}

View File

@ -40,13 +40,9 @@ function get_next_code($str, $qty = 1, $mask = '')
* Se descrizione = 1 e il tipo è 'query=' mi restituisce il valore del campo descrizione della query.
*
* @deprecated 2.4.2
*
* @param string $name
* @param string $sezione
* @param string $descrizione
*
* @return mixed
*/
function get_var($nome, $sezione = null, $descrizione = false, $again = false)
{
@ -163,7 +159,7 @@ function datediff($interval, $datefrom, $dateto, $using_timestamps = false)
break;
case 'm': // Number of full months
$months_difference = floor($difference / 2678400);
while (mktime(date('H', $datefrom), date('i', $datefrom), date('s', $datefrom), date('n', $datefrom) + ($months_difference), date('j', $dateto), date('Y', $datefrom)) < $dateto) {
while (mktime(date('H', $datefrom), date('i', $datefrom), date('s', $datefrom), date('n', $datefrom) + $months_difference, date('j', $dateto), date('Y', $datefrom)) < $dateto) {
++$months_difference;
}
--$months_difference;
@ -207,12 +203,6 @@ function datediff($interval, $datefrom, $dateto, $using_timestamps = false)
}
/**
* @param $field
* @param $id_riga
* @param $old_qta
* @param $new_qta
* @param $dir
*
* @throws Exception
*
* @return bool
@ -274,8 +264,6 @@ function seriali_non_rimuovibili($field, $id_riga, $dir)
/**
* Restistuisce le informazioni sull'eventuale riferimento ai documenti.
*
* @param $info
* @param $dir
* @param array $ignore
*
* @deprecated

View File

@ -54,8 +54,6 @@ function redirect($url, $type = 'php')
* Verifica e corregge il nome di un file.
*
* @param string $filename
*
* @return mixed
*/
function sanitizeFilename($filename)
{
@ -96,14 +94,13 @@ function delete($files)
*/
function directory($path)
{
return Util\FileSystem::directory($path);
return FileSystem::directory($path);
}
/**
* Copy a file, or recursively copy a folder and its contents.
*
* @param array|string $source Source path
* @param string $dest Destination path
* @param array|string $ignores Paths to ingore
*
* @return bool Returns TRUE on success, FALSE on failure
@ -239,12 +236,12 @@ function translateTemplate()
];
$template = replace($template, $replaces);
$template = HTMLBuilder::replace($template);
$template = $template ? HTMLBuilder::replace($template) : $template;
$template = replace($template, $replaces);
// Informazioni estese sulle azioni dell'utente
$op = post('op');
if (!empty($op) && $op != 'summable-results') {
if (!empty($op) && $op != 'summable-results' && $op != 'avg-results') {
OperationLog::setInfo('id_module', $id_module);
OperationLog::setInfo('id_plugin', $id_plugin);
OperationLog::setInfo('id_record', $id_record);
@ -271,7 +268,7 @@ function translateTemplate()
// Annullo le notifiche (AJAX)
if (isAjaxRequest()) {
//flash()->clearMessage('info');
// flash()->clearMessage('info');
}
echo $template;
@ -300,7 +297,7 @@ function slashes($string)
*/
function isAjaxRequest()
{
return \Whoops\Util\Misc::isAjaxRequest() && filter('ajax') !== null;
return Whoops\Util\Misc::isAjaxRequest() && filter('ajax') !== null && filter('ajax') !== '';
}
/**
@ -327,7 +324,7 @@ function redirectOperation($id_module, $id_record)
redirect(base_path().'/controller.php?id_module='.$id_module.$hash);
}
exit();
exit;
}
}
@ -342,7 +339,7 @@ function redirectOperation($id_module, $id_record)
*/
function prepareToField($string)
{
return str_replace('"', '&quot;', $string);
return $string ? str_replace('"', '&quot;', $string) : $string;
}
/**
@ -445,7 +442,7 @@ function session_get($name, $default = null)
$session = &$session[$piece];
}
return isset($session) ? $session : $default;
return $session ?? $default;
}
/**

View File

@ -23,15 +23,16 @@
* @since 2.4.2
*/
use HTMLBuilder\HTMLBuilder;
use Models\Setting;
/**
* Restituisce l'oggetto dedicato alla gestione della connessione con il database.
*
* @return \Database
* @return Database
*/
function database()
{
return \Database::getConnection();
return Database::getConnection();
}
/**
@ -41,8 +42,6 @@ function database()
* @param string $parameter
*
* @since 2.3
*
* @return mixed
*/
function prepare($parameter)
{
@ -62,7 +61,7 @@ function prepare($parameter)
*/
function filter($param, $method = null, $raw = false)
{
return \Filter::getValue($param, $method, $raw);
return Filter::getValue($param, $method, $raw);
}
/**
@ -77,7 +76,7 @@ function filter($param, $method = null, $raw = false)
*/
function post($param, $raw = false)
{
return \Filter::getValue($param, 'post', $raw);
return Filter::getValue($param, 'post', $raw);
}
/**
@ -92,7 +91,7 @@ function post($param, $raw = false)
*/
function get($param, $raw = false)
{
return \Filter::getValue($param, 'get', $raw);
return Filter::getValue($param, 'get', $raw);
}
/**
@ -107,7 +106,7 @@ function get($param, $raw = false)
*/
function setting($name, $again = false)
{
return \Settings::getValue($name);
return Setting::where('nome', '=', $name)->first()->valore;
}
/**
@ -115,7 +114,7 @@ function setting($name, $again = false)
*
* @since 2.4.2
*
* @return \Util\Messages
* @return Util\Messages
*/
function flash()
{
@ -127,11 +126,11 @@ function flash()
*
* @since 2.4.2
*
* @return \Auth
* @return Auth
*/
function auth()
{
return \Auth::getInstance();
return Auth::getInstance();
}
/**
@ -139,11 +138,11 @@ function auth()
*
* @since 2.4.2
*
* @return \Translator
* @return Translator
*/
function trans()
{
return \Translator::getInstance();
return Translator::getInstance();
}
/**
@ -151,11 +150,11 @@ function trans()
*
* @since 2.4.2
*
* @return \Intl\Formatter
* @return Intl\Formatter
*/
function formatter()
{
return \Translator::getFormatter();
return Translator::getFormatter();
}
/**
@ -171,7 +170,7 @@ function formatter()
*/
function tr($string, $parameters = [], $operations = [])
{
return \Translator::translate($string, $parameters, $operations);
return Translator::translate($string, $parameters, $operations);
}
// Retrocompatibilità (con la funzione gettext)
@ -187,7 +186,7 @@ if (!function_exists('_')) {
*
* @since 2.4.2
*
* @return \Monolog\Logger
* @return Monolog\Logger
*/
function logger()
{
@ -213,7 +212,8 @@ function numberFormat($number, $decimals = null)
* Restituisce il timestamp indicato formattato secondo la configurazione del sistema.
*
* @param string $timestamp
+ *
* + *
*
* @return string
*
* @since 2.4.8
@ -260,14 +260,12 @@ function timeFormat($time)
*/
function currency()
{
return \Translator::getCurrency();
return Translator::getCurrency();
}
/**
* Restituisce il numero indicato formattato come una valuta secondo la configurazione del sistema.
*
* @param string $time
*
* @return string
*
* @since 2.4.9

View File

@ -38,9 +38,7 @@ if (!function_exists('array_column')) {
*/
function array_column($array, $key)
{
return array_map(function ($v) use ($key) {
return is_object($v) ? $v->$key : $v[$key];
}, $array);
return array_map(fn ($v) => is_object($v) ? $v->$key : $v[$key], $array);
}
}
@ -48,8 +46,6 @@ if (!function_exists('array_clean')) {
/**
* Pulisce i contenuti vuoti di un array.
*
* @param $array
*
* @since 2.3.2
*
* @return array
@ -57,9 +53,7 @@ if (!function_exists('array_clean')) {
function array_clean($array)
{
if (!empty($array)) {
return array_unique(array_values(array_filter($array, function ($value) {
return !empty($value);
})));
return array_unique(array_values(array_filter($array, fn ($value) => !empty($value))));
}
}
}
@ -68,8 +62,6 @@ if (!function_exists('array_deep_clean')) {
/**
* Pulisce i contenuti vuoti di un array.
*
* @param $array
*
* @since 2.4.11
*
* @return array
@ -111,7 +103,7 @@ if (!function_exists('string_starts_with')) {
*/
function string_starts_with($string, $starts_with)
{
//return strpos($string, $string_starts_with) === 0;
// return strpos($string, $string_starts_with) === 0;
return S::create($string)->startsWith($starts_with);
}
}
@ -127,7 +119,7 @@ if (!function_exists('string_ends_with')) {
*/
function string_ends_with($string, $ends_with)
{
//return substr($string, -strlen($string_ends_with)) === $string_ends_with;
// return substr($string, -strlen($string_ends_with)) === $string_ends_with;
return S::create($string)->endsWith($ends_with);
}
}
@ -143,7 +135,7 @@ if (!function_exists('string_contains')) {
*/
function string_contains($string, $contains)
{
//return strpos($string, $contains) !== false;
// return strpos($string, $contains) !== false;
return S::create($string)->contains($contains);
}
}
@ -240,7 +232,7 @@ if (!function_exists('random_string')) {
// Don't allow duplicate letters to be disabled if the length is
// longer than the available characters
if ($no_duplicate_chars && strlen($pool) < $length) {
throw new \LengthException('$length exceeds the size of the pool and $no_duplicate_chars is enabled');
throw new LengthException('$length exceeds the size of the pool and $no_duplicate_chars is enabled');
}
// Convert the pool of characters into an array of characters and
@ -286,7 +278,7 @@ if (!function_exists('secure_random_string')) {
$bytes = openssl_random_pseudo_bytes($length * 2);
if ($bytes === false) {
throw new \LengthException('$length is not accurate, unable to generate random string');
throw new LengthException('$length is not accurate, unable to generate random string');
}
return substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $length);
@ -304,9 +296,6 @@ if (!function_exists('download')) {
*
* @param string $filename The name of the filename to display to
* browsers
* @param string $content The content to output for the download.
* If you don't specify this, just the
* headers will be sent
*
* @since 2.3
*
@ -427,7 +416,7 @@ if (!function_exists('color_darken')) {
}
$rgb = '';
for ($x = 0; $x < 3; ++$x) {
$c = hexdec(substr($color, (2 * $x), 2)) - $dif;
$c = hexdec(substr($color, 2 * $x, 2)) - $dif;
$c = ($c < 0) ? 0 : dechex($c);
$rgb .= (strlen($c) < 2) ? '0'.$c : $c;
}
@ -448,15 +437,15 @@ if (!function_exists('color_inverse')) {
*/
function color_inverse($start_colour)
{
if (preg_match('/^#[a-f0-9]{6}$/i', $start_colour)) { //hex color is valid
if (preg_match('/^#[a-f0-9]{6}$/i', $start_colour)) { // hex color is valid
$R1 = hexdec(substr($start_colour, 1, 2));
$G1 = hexdec(substr($start_colour, 3, 2));
$B1 = hexdec(substr($start_colour, 5, 2));
$R2 = 255;
$G2 = 255;
$B2 = 255;
$L1 = 0.2126 * pow($R1 / 255, 2.2) + 0.7152 * pow($G1 / 255, 2.2) + 0.0722 * pow($B1 / 255, 2.2);
$L2 = 0.2126 * pow($R2 / 255, 2.2) + 0.7152 * pow($G2 / 255, 2.2) + 0.0722 * pow($B2 / 255, 2.2);
$L1 = 0.2126 * ($R1 / 255) ** 2.2 + 0.7152 * ($G1 / 255) ** 2.2 + 0.0722 * ($B1 / 255) ** 2.2;
$L2 = 0.2126 * ($R2 / 255) ** 2.2 + 0.7152 * ($G2 / 255) ** 2.2 + 0.0722 * ($B2 / 255) ** 2.2;
if ($L1 > $L2) {
$lum = ($L1 + 0.05) / ($L2 + 0.05);
} else {
@ -468,7 +457,17 @@ if (!function_exists('color_inverse')) {
return '#000';
}
} else {
return '#000';
switch ($start_colour) {
case 'black':
return 'white';
case 'blue':
return 'white';
case 'purple':
return 'white';
// Aggiungere altri casi per colori specifici
default:
return '#000'; // Se il colore non è specificato, restituisce il colore originale
}
}
}
}
@ -543,9 +542,6 @@ if (!function_exists('temp_file')) {
/**
* Crea un file temporaneo e lo imposta per la rimozione alla fine dell'esecuzione.
*
* @param $name
* @param $content
*
* @return string
*/
function temp_file($name = null, $content = null)
@ -602,6 +598,6 @@ if (!function_exists('adjustBrightness')) {
$color = str_pad(dechex($color + $adjustAmount), 2, '0', STR_PAD_LEFT);
}
return '#'.implode($hexCode);
return '#'.implode('', $hexCode);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -9796,7 +9796,7 @@ msgstr ""
#: plugins/receiptFE/edit.php:25
msgid ""
"Le ricevute delle Fatture Elettroniche permettono di individuare se una "
"determinata fattura tramessa è stata accettata dal Sistema Di Interscambio"
"determinata fattura trasmessa è stata accettata dal Sistema Di Interscambio"
msgstr ""
#: plugins/receiptFE/edit.php:29 plugins/receiptFE/edit.php:87

Binary file not shown.

File diff suppressed because it is too large Load Diff

74
log.php
View File

@ -17,6 +17,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use Carbon\Carbon;
include_once __DIR__.'/core.php';
$pageTitle = tr('Log');
@ -24,20 +26,21 @@ $pageTitle = tr('Log');
include_once App::filepath('include|custom|', 'top.php');
echo '
<div class="box">
<div class="box-header">
<h3 class="box-title"><i class="fa fa-book"></i> '.tr('Ultimi 100 accessi').'</h3>
<div class="card">
<div class="card-header">
<h3 class="card-title"><i class="fa fa-book"></i> '.tr('Ultimi 100 accessi').'</h3>
</div>
<!-- /.box-header -->
<div class="box-body table-responsive no-padding">
<!-- /.card-header -->
<div class="card-body table-responsive no-padding">
<table class="datatables table table-hover">
<thead>
<tr>
<th>'.tr('Username').'</th>
<th>'.tr('Data').'</th>
<th>'.tr('Stato').'</th>
<th>'.tr('Indirizzo IP').'</th>
<th width="200">'.tr('Username').'</th>
<th width="150">'.tr('Data').'</th>
<th width="100">'.tr('Indirizzo IP').'</th>
<th>'.tr('Dispositivo').'</th>
<th width="180">'.tr('Stato').'</th>
</tr>
</thead>
<tbody>';
@ -50,25 +53,19 @@ if (Auth::admin()) {
} else {
$q = 'SELECT * FROM `zz_logs` WHERE `id_utente`='.prepare(Auth::user()['id']).' ORDER BY `created_at` DESC LIMIT 0, 100';
}
$rs = $dbo->fetchArray($q);
$n = sizeof($rs);
$logs = $dbo->fetchArray($q);
for ($i = 0; $i < $n; ++$i) {
$id = $rs[$i]['id'];
$id_utente = $rs[$i]['id_utente'];
$username = $rs[$i]['username'];
$ip = $rs[$i]['ip'];
$timestamp = Translator::timestampToLocale($rs[$i]['created_at']);
foreach ($logs as $log) {
$timestamp = Translator::timestampToLocale($log['created_at']);
$status = Auth::getStatus();
if ($rs[$i]['stato'] == $status['success']['code']) {
if ($log['stato'] == $status['success']['code']) {
$type = 'success';
$stato = $status['success']['message'];
} elseif ($rs[$i]['stato'] == $status['disabled']['code']) {
} elseif ($log['stato'] == $status['disabled']['code']) {
$type = 'warning';
$stato = $status['disabled']['message'];
} elseif ($rs[$i]['stato'] == $status['unauthorized']['code']) {
} elseif ($log['stato'] == $status['unauthorized']['code']) {
$type = 'warning';
$stato = $status['unauthorized']['message'];
} else {
@ -76,12 +73,15 @@ for ($i = 0; $i < $n; ++$i) {
$stato = $status['failed']['message'];
}
$created_at = new Carbon($log['created_at']);
echo '
<tr class="'.$type.'">
<td>'.$username.'</td>
<td>'.$timestamp.'</td>
<td><span class="label label-'.$type.'">'.$stato.'</span></td>
<td>'.$ip.'</td>
<td>'.$log['username'].'</td>
<td class="tip" title="'.$created_at->format('d/m/Y H:i:s').'">'.$created_at->diffForHumans().'</td>
<td>'.$log['ip'].'</td>
<td class="user-agent tip" title="'.strip_tags($log['user_agent']).'">'.$log['user_agent'].'</td>
<td><span class="badge badge-'.$type.'">'.$stato.'</span></td>
</tr>';
}
@ -90,8 +90,28 @@ echo '
</tbody>
</table>
</div>
<!-- /.box-body -->
<!-- /.card-body -->
</div>
<!-- /.box -->';
<!-- /.card -->';
?>
<script>
$(document).ready(function() {
var parser = new UAParser();
$('tr').each(function(){
user_agent_cell = $(this).find('.user-agent');
user_agent = user_agent_cell.text();
if (user_agent !== '') {
parser.setUA(user_agent);
device = parser.getResult();
user_agent_cell.html('<strong>' + (device.browser.name || '') + '</strong> ' + (device.browser.version || '') + ' | <strong>' + (device.os.name || '') + '</strong> ' + (device.os.version || ''));
}
})
})
</script>
<?php
include_once App::filepath('include|custom|', 'bottom.php');

View File

@ -17,6 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use Models\Module;
use Modules\Emails\Template;
include_once __DIR__.'/core.php';
@ -51,7 +52,7 @@ foreach ($mansioni as $mansione) {
}
// Aggiungo email tecnici assegnati quando sono sul template Notifica intervento
if ($template->name == 'Notifica intervento') {
if ($template->getTranslation('title') == 'Notifica intervento') {
$tecnici = $dbo->select('in_interventi_tecnici_assegnati', 'id_tecnico', [], ['id_intervento' => $id_record]);
foreach ($tecnici as $tecnico) {
$anagrafica = $dbo->table('an_anagrafiche')->where('idanagrafica', $tecnico['id_tecnico'])->where('email', '!=', '')->first();
@ -78,7 +79,7 @@ if (sizeof($campi_mancanti) > 0) {
echo '
<div class="alert alert-warning">
<i class="fa fa-warning"></i> '.tr("Prima di procedere all'invio completa: _VALUES_", [
'_VALUES_' => '<b>'.implode(', ', $campi_mancanti).'</b>',
'_VALUES_' => '<b>'.implode(', ', $campi_mancanti).'</b>',
]).'<br/>
'.Modules::link('Account email', $smtp['id'], tr('Vai alla scheda account email'), null).'
</div>';
@ -112,21 +113,21 @@ echo '
<b>'.tr('Destinatari').' <span class="tip" title="'.tr('Email delle sedi, dei referenti o agente collegato all\'anagrafica.').'"><i class="fa fa-question-circle-o"></i></span></b>
<div class="row" id="lista-destinatari">';
$idx = 0;
$idx = 0;
foreach ($emails as $email) {
echo '
foreach ($emails as $email) {
echo '
<div class="col-md-12">
{[ "type": "email", "name": "destinatari['.$idx++.']", "value": "'.$email.'", "icon-before": "choice|email", "extra": "onkeyup=\'aggiungiDestinatario();\'", "class": "destinatari", "required": 0 ]}
</div>';
}
}
if (empty($emails)) {
echo '
if (empty($emails)) {
echo '
<div class="col-md-12">
{[ "type": "email", "name": "destinatari['.$idx++.']", "value": "", "icon-before": "choice|email", "extra": "onkeyup=\'aggiungiDestinatario();\'", "class": "destinatari", "required": 0 ]}
</div>';
}
}
echo '
</div>
@ -150,11 +151,11 @@ echo '
<div class="row">
<div class="col-md-6">
{[ "type": "select", "multiple": "1", "label": "'.tr('Stampe').'", "name": "prints[]", "value": "'.implode(',', $selected).'", "values": "query=SELECT id, title AS text FROM zz_prints WHERE id_module = '.prepare($id_module).' AND enabled=1 AND is_record=1", "link": "stampa" ]}
{[ "type": "select", "multiple": "1", "label": "'.tr('Stampe').'", "name": "prints[]", "value": "'.implode(',', $selected).'", "values": "query=SELECT `zz_prints`.`id`, `title` AS text FROM `zz_prints` LEFT JOIN `zz_prints_lang` ON (`zz_prints`.`id` = `zz_prints_lang`.`id_record` AND `zz_prints_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') WHERE `id_module` = '.prepare($id_module).' AND `enabled`=1 AND `is_record`=1", "link": "stampa" ]}
</div>';
$uploads = [];
if ($smtp['pec'] == 1 && $module['name'] == 'Fatture di vendita') {
if ($smtp['pec'] == 1 && $module->getTranslation('title') == 'Fatture di vendita') {
$uploads = $dbo->fetchArray('SELECT id FROM zz_files WHERE id_module = '.prepare($module['id']).' AND id_record = '.prepare($id_record).' AND category = \'Fattura Elettronica\'');
$uploads = array_column($uploads, 'id');
}
@ -163,7 +164,7 @@ if ($smtp['pec'] == 1 && $module['name'] == 'Fatture di vendita') {
echo '
<div class="col-md-6">
{[ "type": "select", "multiple": "1", "label": "'.tr('Allegati').'", "name": "uploads[]", "value": "'.implode(',', $uploads).'", "help": "'.tr('Allegati del documento o caricati nell\'anagrafica dell\'azienda.').'", "values": "query=SELECT id, name AS text FROM zz_files WHERE id_module = '.prepare($id_module).' AND id_record = '.prepare($id_record).' UNION SELECT id, CONCAT(name, \' (Azienda)\') AS text FROM zz_files WHERE id_module = '.prepare(Modules::get('Anagrafiche')['id']).' AND id_record = (SELECT valore FROM zz_settings WHERE nome = \'Azienda predefinita\')", "link": "allegato" ]}
{[ "type": "select", "multiple": "1", "label": "'.tr('Allegati').'", "name": "uploads[]", "value": "'.implode(',', $uploads).'", "help": "'.tr('Allegati del documento o caricati nell\'anagrafica dell\'azienda.').'", "values": "query=SELECT `id`, `title` AS text FROM `zz_files` WHERE `id_module` = '.prepare($id_module).' AND `id_record` = '.prepare($id_record).' UNION SELECT `id`, CONCAT(`title`, \' (Azienda)\') AS text FROM `zz_files` WHERE `id_module` = '.(new Module())->getByField('title', 'Anagrafiche', Models\Locale::getPredefined()->id).' AND `id_record` = (SELECT `valore` FROM `zz_settings` WHERE `title` = \'Azienda predefinita\')", "link": "allegato" ]}
</div>
</div>';
@ -171,16 +172,16 @@ echo '
<div class="row">
<div class="col-md-12">';
echo input([
'type' => 'ckeditor',
'use_full_ckeditor' => 1,
'label' => tr('Contenuto'),
'name' => 'body',
'id' => 'body_'.rand(0, 999),
'value' => $body,
]);
echo input([
'type' => 'ckeditor',
'use_full_ckeditor' => 1,
'label' => tr('Contenuto'),
'name' => 'body',
'id' => 'body_'.rand(0, 999),
'value' => $body,
]);
echo '
echo '
</div>
</div>';

View File

@ -0,0 +1,59 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
include_once __DIR__.'/../../core.php';
use Modules\FileAdapters\FileAdapter;
switch (filter('op')) {
case 'add':
$adapter = new FileAdapter();
$adapter->name = post('name');
$adapter->class = '\\Modules\\FileAdapters\\Adapters\\'.post('class');
$adapter->save();
$id_record = $adapter->id;
flash()->info(tr('Nuoovo adattatore aggiunto!'));
break;
case 'update':
$adapter->name = post('name');
$adapter->class = '\\Modules\\FileAdapters\\Adapters\\'.post('class');
$adapter->options = post('options');
if (post('is_default') == 1) {
$dbo->query('UPDATE `zz_storage_adapters` SET `is_default` = 0');
$adapter->is_default = post('is_default');
}
$adapter->save();
flash()->info(tr('Adattatore modificato correttamente!'));
break;
case 'delete':
$adapter->delete();
break;
}

View File

@ -19,22 +19,25 @@
include_once __DIR__.'/../../core.php';
?><form action="" method="post" id="edit-form">
<input type="hidden" name="op" value="update">
?><form action="" method="post" id="add-form">
<input type="hidden" name="op" value="add">
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="id_record" value="<?php echo $id_record; ?>">
<input type="hidden" name="dir" value="<?php echo $dir; ?>">
<div class="row">
<div class="col-md-4">
{[ "type": "text", "label": "<?php echo tr('Categoria'); ?>", "name": "categoria", "required": 1, "value": "$categoria$" ]}
<div class="col-md-6">
{[ "type": "text", "label": "<?php echo tr('Nome'); ?>", "name": "name", "required": 1 ]}
</div>
<div class="col-md-8">
{[ "type": "text", "label": "<?php echo tr('Descrizione'); ?>", "name": "descrizione", "required": 1, "value": "$descrizione$" ]}
<div class="col-md-6">
{[ "type": "select", "label": "<?php echo tr('Tipo archiviazione'); ?>", "name": "class", "values": "list=\"LocalAdapter\":\"<?php echo tr('Archiviazione locale'); ?>\",\"FTPAdapter\":\"<?php echo tr('Archiviazione FTP'); ?>\"", "required": 1 ]}
</div>
</div>
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary"><i class="fa fa-plus"></i> <?php echo tr('Aggiungi'); ?></button>
</div>
</div>
</form>
<a class="btn btn-danger ask" data-backto="record-list">
<i class="fa fa-trash"></i> <?php echo tr('Elimina'); ?>
</a>
</form>

Some files were not shown because too many files have changed in this diff Show More