88 Commits

Author SHA1 Message Date
RMubarakzyanov 9ec5419a86 dlFunction fix 2026-05-24 00:15:09 +03:00
RMubarakzyanov c05091e020 Merge branch 'main' into feature/20260520_scadenziario
# Conflicts:
#	public/userarea/scadenzario/index.php
2026-05-24 00:02:20 +03:00
RMubarakzyanov 0b470f290e fix auto-open 2026-05-23 23:56:43 +03:00
solocla e74870c8d3 added functions 2026-05-22 09:16:46 +02:00
RMubarakzyanov 9001eff317 file repo, cc, auto-open 2026-05-21 23:31:36 +03:00
solocla 650676037a fixed date format 2026-05-20 14:48:45 +02:00
solocla 2fc34c3cf4 fixed redirection 2026-05-18 13:49:22 +02:00
solocla 955a7ed9e9 fixed user setting 2026-05-18 13:31:34 +02:00
solocla e6a805f1f7 fixed permission 2026-05-15 21:10:28 +02:00
solocla fe84d446e7 stop tracking vendor 2026-05-15 20:54:16 +02:00
solocla 2ddf575191 phinx 2026-05-15 20:50:06 +02:00
solocla d73a8bb8d3 add permission to dashboard and navbar 2026-05-15 17:13:29 +02:00
solocla fa2f293835 added roles edit into employees 2026-05-07 14:39:50 +02:00
solocla fc35adc7f9 big modal deadlines 2026-05-07 09:46:25 +02:00
solocla ac942dcdc8 added depart,ments to employee and deadlines 2026-05-07 09:44:38 +02:00
solocla 5728afa788 added departments 2026-04-30 08:22:24 +02:00
solocla 1946648b1b add modifica record 2026-04-28 11:56:31 +02:00
solocla a1bcab3188 fixed color 2026-04-28 11:48:35 +02:00
solocla 2bbeb11726 fixed sql 2026-04-19 17:37:09 +02:00
RMubarakzyanov dd5edab2f3 deadline widget 2026-04-19 09:14:19 +03:00
RMubarakzyanov 1fadc22178 fix login redirect 2026-04-18 20:37:03 +03:00
RMubarakzyanov d3ee9a3790 mobile view 2026-04-18 17:28:49 +03:00
RMubarakzyanov c387b71cae xls converted to sql 2026-04-18 16:44:53 +03:00
RMubarakzyanov b2cfec77df xls converted to sql 2026-04-18 16:44:14 +03:00
RMubarakzyanov 73b9a3d890 dueDate autofill 2026-04-18 16:25:20 +03:00
RMubarakzyanov 0550ffe923 Subject CRUD 2026-04-18 15:26:04 +03:00
RMubarakzyanov d2e5cc8b2b dynamic basepath 2026-04-16 17:35:13 +03:00
RMubarakzyanov d7b6a58407 deadline feature 2026-04-10 15:51:30 +03:00
solocla 174fa73c2c added scadenziario button 2026-04-02 14:42:02 +02:00
solocla 0bd41b8eb0 Ignore matrici attachments 2026-04-02 14:41:52 +02:00
solocla 248ae63875 fixed supplier mescole 2026-04-01 15:03:39 +02:00
solocla d39e997beb fixed update fornitore 2026-04-01 14:57:20 +02:00
solocla 1b23885659 update dashboard 2026-04-01 14:48:03 +02:00
solocla ad16d84b2e added fogloiu di lavoro modals everywhere 2026-03-31 11:39:17 +02:00
solocla 8cf74608b8 move fogli di lavoro 2026-03-24 09:32:55 +01:00
solocla 2642906a9b fixed worksheet modal 2026-03-23 17:49:48 +01:00
solocla d2f2a9089e marici foglio lavoro 2026-03-20 22:09:39 +01:00
solocla 53b990ff40 fixed imballaggi worksheet 2026-03-20 12:24:22 +01:00
solocla f477f393ba prova push gitea gitlab 2026-03-20 08:59:19 +01:00
solocla bc806f37f4 fixed mescole matrici 2026-03-19 16:20:46 +01:00
solocla f043b43791 upgrade matrice with files 2026-03-19 16:16:41 +01:00
solocla 245750f057 mescole update 2026-03-06 08:42:18 +01:00
solocla 22e5b90fe4 loopkup, foglio di lavoro 2026-02-03 16:04:45 +01:00
solocla 31f22b4d92 matrix skills 2026-02-02 17:25:47 +01:00
solocla 340ebdcbce fixed refresh 2026-01-27 10:00:05 +01:00
solocla 1edf7b7239 fixed matrici 2026-01-27 09:57:47 +01:00
solocla 51cca3448a fixed dropdown user 2026-01-27 08:54:55 +01:00
solocla 8732f21af8 fix column matrici 2026-01-21 12:22:23 +01:00
solocla 3043522465 fixed titles 2026-01-21 12:13:05 +01:00
solocla 49435b8e44 fixed table and search 2026-01-21 12:10:05 +01:00
solocla e876cb9775 fix eomployees 2025-12-11 10:48:19 +01:00
solocla 7f78a61808 employees 2025-12-11 10:45:24 +01:00
solocla 50c808e605 update photo button 2025-12-11 09:09:30 +01:00
solocla 978b38c669 fixed modal 2025-12-10 15:07:38 +01:00
solocla 4683c4f40c fixed photo 2025-12-10 14:58:03 +01:00
solocla d9cbaf8df1 fixed line 2025-12-10 14:23:59 +01:00
solocla 9649751ad8 fixed drag lines 2025-12-10 14:14:43 +01:00
solocla 824ae278d1 fixed add instrument 2025-12-05 12:29:33 +01:00
solocla 37909e8175 fixed foto matrice 2025-12-03 14:29:35 +01:00
solocla 86782d26b2 fixed drag with arrows 2025-12-03 14:23:14 +01:00
solocla 329b3ffdeb added params crud lines 2025-12-03 14:07:11 +01:00
solocla 9447f3cf00 added foto matrice everywhere 2025-12-03 12:21:26 +01:00
solocla 5b7a8b57d5 added images 2025-12-03 11:47:00 +01:00
solocla 7a2cac27cd fixed images 2025-12-03 11:35:49 +01:00
solocla f9737fdf73 fixed photo upoload 2025-12-03 10:38:43 +01:00
solocla 77e5820dcc fixed view and multi 2025-12-03 09:55:42 +01:00
solocla dd9d109dee update mescole and photo diagram 2025-12-03 08:35:59 +01:00
solocla a1c9d9f789 dashboard fix 2025-11-26 11:24:29 +01:00
solocla 4c63f16a54 fixed start stop pause 2025-11-24 20:02:40 +01:00
solocla 6f3b933a71 status added 2025-11-22 20:34:51 +01:00
solocla 779821a08b fixed drag 2025-11-22 20:00:40 +01:00
solocla 8edccbdfef added drag and photos 2025-11-22 13:35:12 +01:00
solocla eeb1d0d5de update production line with reference values 2025-11-18 14:25:27 +01:00
solocla 711d3d5f73 fixed dashboard 2025-11-17 17:50:42 +01:00
solocla 85c8ddc985 fixed logo and prod dash 2025-11-03 11:32:45 +01:00
solocla edcedb8f91 added production 2025-10-30 16:40:14 +01:00
solocla a4b1fb9b1f added pages 2025-10-27 10:10:09 +01:00
solocla 92ec026afe new project commit 2025-10-24 21:45:33 +02:00
solocla 29e4b41874 update export to lims 2025-10-11 20:19:43 +02:00
solocla eef9ae8d36 added note to export 2025-10-10 11:31:49 +02:00
solocla 68c867a3f4 change clienti to datadb and fixed column pages 2025-10-09 15:30:44 +02:00
solocla a9827e4e81 added note and date to identification parts 2025-10-08 17:34:21 +02:00
solocla b51936f784 various fixing modal 2025-10-07 20:56:57 +02:00
solocla 15b6f38e8b fixed matrici with db cron 2025-10-07 09:41:29 +02:00
solocla 12c6cc5f95 lazy load modal parts and matrici cron 2025-10-07 09:12:54 +02:00
solocla a0b12463c0 fixed for matrici 2025-10-03 08:52:37 +02:00
solocla 07ddcafd3f fixed nologin 2025-09-27 13:38:26 +02:00
solocla 7843d4b1fc added nologin 2025-09-27 13:37:37 +02:00
12482 changed files with 34384 additions and 1397821 deletions
+2
View File
@@ -31,6 +31,8 @@ MAIL_USERNAME=null
MAIL_PASSWORD=null MAIL_PASSWORD=null
MAIL_ENCRYPTION=null MAIL_ENCRYPTION=null
MANAGER_USER_ID=
PUSHER_APP_ID= PUSHER_APP_ID=
PUSHER_APP_KEY= PUSHER_APP_KEY=
PUSHER_APP_SECRET= PUSHER_APP_SECRET=
+5
View File
@@ -32,6 +32,8 @@ auth.json
# File XLSX temporanei importati # File XLSX temporanei importati
/public/userarea/imported_trf/*.xlsx /public/userarea/imported_trf/*.xlsx
/public/userarea/xlstemplates/*.xlsx /public/userarea/xlstemplates/*.xlsx
/public/userarea/photos/matrici/allegati/
/public/userarea/photos/matrici/allegati/*
# Ignora cartelle di foto generate # Ignora cartelle di foto generate
/public/photostrf/ /public/photostrf/
@@ -64,3 +66,6 @@ public/userarea/logsapi/commessaweb_customfields_763.json
public/userarea/logsapi/commessaweb_invia_762.json public/userarea/logsapi/commessaweb_invia_762.json
public/userarea/logsapi/commessaweb_invia_763.json public/userarea/logsapi/commessaweb_invia_763.json
public/userarea/logsapi/last_auth_url.txt public/userarea/logsapi/last_auth_url.txt
# User uploaded files
/public/userarea/files/
@@ -108,9 +108,17 @@ class LoginController extends Controller
// Reindirizza in base al ruolo // Reindirizza in base al ruolo
if ($user->hasRole('Admin')) { if ($user->hasRole('Admin')) {
return redirect()->to('userarea/import_dashboard.php'); return redirect()->to('userarea/production_dashboard.php');
} elseif ($user->hasRole('User')) { } elseif ($user->hasRole('User')) {
return redirect()->to('userarea/import_dashboard.php'); return redirect()->to('userarea/production_dashboard.php');
} elseif ($user->hasRole('HR')) {
return redirect()->to('userarea/production_dashboard.php');
} elseif ($user->hasRole('SuperUser')) {
return redirect()->to('userarea/production_dashboard.php');
} elseif ($user->hasRole('Management')) {
return redirect()->to('userarea/production_dashboard.php');
} elseif ($user->hasRole('Quality')) {
return redirect()->to('userarea/production_dashboard.php');
} }
// Se il ruolo non è specificato, reindirizza alla home predefinita // Se il ruolo non è specificato, reindirizza alla home predefinita
+1
View File
@@ -44,6 +44,7 @@
"phpmailer/phpmailer": "^6.9", "phpmailer/phpmailer": "^6.9",
"phpoffice/phpspreadsheet": "^4.1", "phpoffice/phpspreadsheet": "^4.1",
"proengsoft/laravel-jsvalidation": "^4.0.0", "proengsoft/laravel-jsvalidation": "^4.0.0",
"robmorgan/phinx": "^0.16.11",
"socialiteproviders/microsoft": "^4.7", "socialiteproviders/microsoft": "^4.7",
"spatie/laravel-query-builder": "^5.0", "spatie/laravel-query-builder": "^5.0",
"vanguardapp/activity-log": "^6.0", "vanguardapp/activity-log": "^6.0",
Generated
+646 -2
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "9c4f1e3bc3ee2180211c055e70635aef", "content-hash": "076e7721d08cfea8b06ce75dd8c6c576",
"packages": [ "packages": [
{ {
"name": "akaunting/laravel-setting", "name": "akaunting/laravel-setting",
@@ -251,6 +251,330 @@
], ],
"time": "2023-11-29T23:19:16+00:00" "time": "2023-11-29T23:19:16+00:00"
}, },
{
"name": "cakephp/chronos",
"version": "3.5.0",
"source": {
"type": "git",
"url": "https://github.com/cakephp/chronos.git",
"reference": "e6e777b534244911566face8a5dbdbd7f7bda5a6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/chronos/zipball/e6e777b534244911566face8a5dbdbd7f7bda5a6",
"reference": "e6e777b534244911566face8a5dbdbd7f7bda5a6",
"shasum": ""
},
"require": {
"php": ">=8.1",
"psr/clock": "^1.0"
},
"provide": {
"psr/clock-implementation": "1.0"
},
"require-dev": {
"cakephp/cakephp-codesniffer": "^5.0",
"phpunit/phpunit": "^10.5.58 || ^11.5.3 || ^12.1.3"
},
"type": "library",
"autoload": {
"psr-4": {
"Cake\\Chronos\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Brian Nesbitt",
"email": "brian@nesbot.com",
"homepage": "http://nesbot.com"
},
{
"name": "The CakePHP Team",
"homepage": "https://cakephp.org"
}
],
"description": "A simple API extension for DateTime.",
"homepage": "https://cakephp.org",
"keywords": [
"date",
"datetime",
"time"
],
"support": {
"issues": "https://github.com/cakephp/chronos/issues",
"source": "https://github.com/cakephp/chronos"
},
"time": "2026-04-10T02:50:39+00:00"
},
{
"name": "cakephp/core",
"version": "5.3.5",
"source": {
"type": "git",
"url": "https://github.com/cakephp/core.git",
"reference": "eb012517900ed288f580aa3487e9a09f28ea85f9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/core/zipball/eb012517900ed288f580aa3487e9a09f28ea85f9",
"reference": "eb012517900ed288f580aa3487e9a09f28ea85f9",
"shasum": ""
},
"require": {
"cakephp/utility": "^5.3.0",
"league/container": "^5.1",
"php": ">=8.2",
"psr/container": "^1.1 || ^2.0"
},
"provide": {
"psr/container-implementation": "^2.0"
},
"suggest": {
"cakephp/cache": "To use Configure::store() and restore().",
"cakephp/event": "To use PluginApplicationInterface or plugin applications.",
"league/container": "To use Container and ServiceProvider classes"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-5.next": "5.4.x-dev"
}
},
"autoload": {
"files": [
"functions.php"
],
"psr-4": {
"Cake\\Core\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/core/graphs/contributors"
}
],
"description": "CakePHP Framework Core classes",
"homepage": "https://cakephp.org",
"keywords": [
"cakephp",
"core",
"framework"
],
"support": {
"forum": "https://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"issues": "https://github.com/cakephp/cakephp/issues",
"source": "https://github.com/cakephp/core"
},
"time": "2026-03-31T06:25:23+00:00"
},
{
"name": "cakephp/database",
"version": "5.3.5",
"source": {
"type": "git",
"url": "https://github.com/cakephp/database.git",
"reference": "cf94dcb57c54a1a308fd866b038cd6995910e36e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/database/zipball/cf94dcb57c54a1a308fd866b038cd6995910e36e",
"reference": "cf94dcb57c54a1a308fd866b038cd6995910e36e",
"shasum": ""
},
"require": {
"cakephp/chronos": "^3.3",
"cakephp/core": "^5.3.0",
"cakephp/datasource": "^5.3.0",
"php": ">=8.2",
"psr/log": "^3.0"
},
"require-dev": {
"cakephp/i18n": "^5.3.0",
"cakephp/log": "^5.3.0"
},
"suggest": {
"cakephp/i18n": "If you are using locale-aware datetime formats.",
"cakephp/log": "If you want to use query logging without providing a logger yourself."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-5.next": "5.4.x-dev"
}
},
"autoload": {
"psr-4": {
"Cake\\Database\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/database/graphs/contributors"
}
],
"description": "Flexible and powerful Database abstraction library with a familiar PDO-like API",
"homepage": "https://cakephp.org",
"keywords": [
"abstraction",
"cakephp",
"database",
"database abstraction",
"pdo"
],
"support": {
"forum": "https://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"issues": "https://github.com/cakephp/cakephp/issues",
"source": "https://github.com/cakephp/database"
},
"time": "2026-03-31T06:25:23+00:00"
},
{
"name": "cakephp/datasource",
"version": "5.3.5",
"source": {
"type": "git",
"url": "https://github.com/cakephp/datasource.git",
"reference": "512464eb27b19316b515ec338089b83822c9ab5a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/datasource/zipball/512464eb27b19316b515ec338089b83822c9ab5a",
"reference": "512464eb27b19316b515ec338089b83822c9ab5a",
"shasum": ""
},
"require": {
"cakephp/core": "^5.3.0",
"php": ">=8.2",
"psr/simple-cache": "^2.0 || ^3.0"
},
"require-dev": {
"cakephp/cache": "^5.3.0",
"cakephp/collection": "^5.3.0",
"cakephp/utility": "^5.3.0"
},
"suggest": {
"cakephp/cache": "If you decide to use Query caching.",
"cakephp/collection": "If you decide to use ResultSetInterface.",
"cakephp/utility": "If you decide to use EntityTrait."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-5.next": "5.4.x-dev"
}
},
"autoload": {
"psr-4": {
"Cake\\Datasource\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/datasource/graphs/contributors"
}
],
"description": "Provides connection managing and traits for Entities and Queries that can be reused for different datastores",
"homepage": "https://cakephp.org",
"keywords": [
"cakephp",
"connection management",
"datasource",
"entity",
"query"
],
"support": {
"forum": "https://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"issues": "https://github.com/cakephp/cakephp/issues",
"source": "https://github.com/cakephp/datasource"
},
"time": "2026-04-04T08:08:42+00:00"
},
{
"name": "cakephp/utility",
"version": "5.3.5",
"source": {
"type": "git",
"url": "https://github.com/cakephp/utility.git",
"reference": "4ac9826fe5faa1505ec5aa3c171d6b58b6ab4e99"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/utility/zipball/4ac9826fe5faa1505ec5aa3c171d6b58b6ab4e99",
"reference": "4ac9826fe5faa1505ec5aa3c171d6b58b6ab4e99",
"shasum": ""
},
"require": {
"cakephp/core": "^5.3.0",
"php": ">=8.2"
},
"suggest": {
"ext-intl": "To use Text::transliterate() or Text::slug()",
"lib-ICU": "To use Text::transliterate() or Text::slug()"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-5.next": "5.4.x-dev"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Cake\\Utility\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/utility/graphs/contributors"
}
],
"description": "CakePHP Utility classes such as Inflector, String, Hash, and Security",
"homepage": "https://cakephp.org",
"keywords": [
"cakephp",
"hash",
"inflector",
"security",
"string",
"utility"
],
"support": {
"forum": "https://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"issues": "https://github.com/cakephp/cakephp/issues",
"source": "https://github.com/cakephp/utility"
},
"time": "2026-03-09T09:38:36+00:00"
},
{ {
"name": "carbonphp/carbon-doctrine-types", "name": "carbonphp/carbon-doctrine-types",
"version": "3.2.0", "version": "3.2.0",
@@ -2627,6 +2951,90 @@
], ],
"time": "2022-12-11T20:36:23+00:00" "time": "2022-12-11T20:36:23+00:00"
}, },
{
"name": "league/container",
"version": "5.2.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/container.git",
"reference": "58accbc032f0090a9bd08326f93062c5a658b2c5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/container/zipball/58accbc032f0090a9bd08326f93062c5a658b2c5",
"reference": "58accbc032f0090a9bd08326f93062c5a658b2c5",
"shasum": ""
},
"require": {
"php": "^8.1",
"psr/container": "^2.0.2",
"psr/event-dispatcher": "^1.0"
},
"provide": {
"psr/container-implementation": "^1.0"
},
"replace": {
"orno/di": "~2.0"
},
"require-dev": {
"nette/php-generator": "^4.1",
"nikic/php-parser": "^5.0",
"phpstan/phpstan": "^2.1.11",
"phpunit/phpunit": "^10.5.45|^11.5.15|^12.0",
"roave/security-advisories": "dev-latest",
"scrutinizer/ocular": "^1.9",
"squizlabs/php_codesniffer": "^3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-1.x": "1.x-dev",
"dev-2.x": "2.x-dev",
"dev-3.x": "3.x-dev",
"dev-4.x": "4.x-dev",
"dev-5.x": "5.x-dev",
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"League\\Container\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Phil Bennett",
"email": "mail@philbennett.co.uk",
"role": "Developer"
}
],
"description": "A fast and intuitive dependency injection container.",
"homepage": "https://github.com/thephpleague/container",
"keywords": [
"container",
"dependency",
"di",
"injection",
"league",
"provider",
"service"
],
"support": {
"issues": "https://github.com/thephpleague/container/issues",
"source": "https://github.com/thephpleague/container/tree/5.2.0"
},
"funding": [
{
"url": "https://github.com/philipobenito",
"type": "github"
}
],
"time": "2026-03-19T18:52:39+00:00"
},
{ {
"name": "league/flysystem", "name": "league/flysystem",
"version": "3.28.0", "version": "3.28.0",
@@ -4980,6 +5388,93 @@
], ],
"time": "2024-04-27T21:32:50+00:00" "time": "2024-04-27T21:32:50+00:00"
}, },
{
"name": "robmorgan/phinx",
"version": "0.16.11",
"source": {
"type": "git",
"url": "https://github.com/cakephp/phinx.git",
"reference": "a03014fea316ba021fc0776982e5bed2d10228d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/phinx/zipball/a03014fea316ba021fc0776982e5bed2d10228d4",
"reference": "a03014fea316ba021fc0776982e5bed2d10228d4",
"shasum": ""
},
"require": {
"cakephp/database": "^5.0.2",
"composer-runtime-api": "^2.0",
"php-64bit": ">=8.1",
"psr/container": "^1.1|^2.0",
"symfony/config": "^4.0|^5.0|^6.0|^7.0|^8.0",
"symfony/console": "^6.0|^7.0|^8.0"
},
"require-dev": {
"cakephp/cakephp-codesniffer": "^5.0",
"cakephp/i18n": "^5.0",
"ext-json": "*",
"ext-pdo": "*",
"phpunit/phpunit": "^10.5",
"symfony/yaml": "^4.0|^5.0|^6.0|^7.0|^8.0"
},
"suggest": {
"ext-json": "Install if using JSON configuration format",
"ext-pdo": "PDO extension is needed",
"symfony/yaml": "Install if using YAML configuration format"
},
"bin": [
"bin/phinx"
],
"type": "library",
"autoload": {
"psr-4": {
"Phinx\\": "src/Phinx/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rob Morgan",
"email": "robbym@gmail.com",
"homepage": "https://robmorgan.id.au",
"role": "Lead Developer"
},
{
"name": "Woody Gilk",
"email": "woody.gilk@gmail.com",
"homepage": "https://shadowhand.me",
"role": "Developer"
},
{
"name": "Richard Quadling",
"email": "rquadling@gmail.com",
"role": "Developer"
},
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/phinx/graphs/contributors",
"role": "Developer"
}
],
"description": "Phinx makes it ridiculously easy to manage the database migrations for your PHP app.",
"homepage": "https://phinx.org",
"keywords": [
"database",
"database migrations",
"db",
"migrations",
"phinx"
],
"support": {
"issues": "https://github.com/cakephp/phinx/issues",
"source": "https://github.com/cakephp/phinx/tree/0.16.11"
},
"time": "2026-03-15T00:04:32+00:00"
},
{ {
"name": "socialiteproviders/manager", "name": "socialiteproviders/manager",
"version": "v4.8.1", "version": "v4.8.1",
@@ -5312,6 +5807,85 @@
], ],
"time": "2024-05-31T14:57:53+00:00" "time": "2024-05-31T14:57:53+00:00"
}, },
{
"name": "symfony/config",
"version": "v7.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "d91b6c7cd2a8c9a9c2b8d26c8f5ed48edf99ef57"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/d91b6c7cd2a8c9a9c2b8d26c8f5ed48edf99ef57",
"reference": "d91b6c7cd2a8c9a9c2b8d26c8f5ed48edf99ef57",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/filesystem": "^7.1|^8.0",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
"symfony/finder": "<6.4",
"symfony/service-contracts": "<2.5"
},
"require-dev": {
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
"symfony/finder": "^6.4|^7.0|^8.0",
"symfony/messenger": "^6.4|^7.0|^8.0",
"symfony/service-contracts": "^2.5|^3",
"symfony/yaml": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Config\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/config/tree/v7.4.10"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-05-03T14:20:49+00:00"
},
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v7.1.3", "version": "v7.1.3",
@@ -5768,6 +6342,76 @@
], ],
"time": "2024-04-18T09:32:20+00:00" "time": "2024-04-18T09:32:20+00:00"
}, },
{
"name": "symfony/filesystem",
"version": "v7.4.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d721ea61b4a5fba8c5b6e7c1feda19efea144b50",
"reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
"require-dev": {
"symfony/process": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v7.4.11"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-05-11T16:38:44+00:00"
},
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v7.1.3", "version": "v7.1.3",
@@ -11355,6 +11999,6 @@
"php": "^8.2.0", "php": "^8.2.0",
"ext-json": "*" "ext-json": "*"
}, },
"platform-dev": [], "platform-dev": {},
"plugin-api-version": "2.6.0" "plugin-api-version": "2.6.0"
} }
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class BaselineExistingDatabase extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
// Baseline migration.
// Existing database structure starts being tracked from this point.
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreatePhinxTestTable extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
$table = $this->table('phinx_test_table');
$table
->addColumn('name', 'string', [
'limit' => 100,
'null' => false,
])
->addColumn('created_at', 'timestamp', [
'default' => 'CURRENT_TIMESTAMP',
'null' => false,
])
->create();
}
}
@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class AddFunctionsToScadDeadlines extends AbstractMigration
{
public function change(): void
{
$this->table('scad_functions', [
'id' => false,
'primary_key' => ['id'],
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
])
->addColumn('id', 'integer', [
'identity' => true,
'signed' => false,
])
->addColumn('name', 'string', [
'limit' => 255,
'null' => false,
])
->addColumn('description', 'text', [
'null' => true,
])
->addColumn('status', 'string', [
'limit' => 20,
'null' => false,
'default' => 'active',
])
->addColumn('created_at', 'timestamp', [
'null' => false,
'default' => 'CURRENT_TIMESTAMP',
])
->addColumn('updated_at', 'timestamp', [
'null' => false,
'default' => 'CURRENT_TIMESTAMP',
'update' => 'CURRENT_TIMESTAMP',
])
->addIndex(['name'], [
'unique' => true,
'name' => 'uniq_scad_functions_name',
])
->create();
$this->table('scad_deadlines')
->addColumn('function_id', 'integer', [
'signed' => false,
'null' => true,
'after' => 'subject_id',
])
->addIndex(['function_id'], [
'name' => 'idx_scad_deadlines_function_id',
])
->addForeignKey('function_id', 'scad_functions', 'id', [
'delete' => 'SET_NULL',
'update' => 'CASCADE',
'constraint' => 'fk_scad_deadlines_function',
])
->update();
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
require_once __DIR__ . '/vendor/autoload.php';
if (file_exists(__DIR__ . '/.env')) {
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->safeLoad();
}
return [
'paths' => [
'migrations' => __DIR__ . '/db/migrations',
'seeds' => __DIR__ . '/db/seeds',
],
'environments' => [
'default_migration_table' => 'phinxlog',
'default_environment' => 'development',
'development' => [
'adapter' => $_ENV['DB_CONNECTION'] ?? 'mysql',
'host' => $_ENV['DB_HOST'] ?? 'localhost',
'name' => $_ENV['DB_DATABASE'] ?? '',
'user' => $_ENV['DB_USERNAME'] ?? '',
'pass' => $_ENV['DB_PASSWORD'] ?? '',
'port' => $_ENV['DB_PORT'] ?? 3306,
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
],
],
'version_order' => 'creation',
];
Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 456 KiB

@@ -0,0 +1,254 @@
<?php
ob_start();
ini_set('display_errors', 1);
error_reporting(E_ALL);
require_once(__DIR__ . '/../../../extra/auth.php');
require_once(__DIR__ . '/../class/db-functions.php');
while (ob_get_level()) {
ob_end_clean();
}
header('Content-Type: application/json; charset=utf-8');
if (!class_exists('Auth')) {
echo json_encode([
'success' => false,
'message' => 'Classe Auth non disponibile'
]);
exit;
}
if (!Auth::check()) {
echo json_encode([
'success' => false,
'message' => 'Sessione non valida o utente non autenticato'
]);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
function formatDateIT($d)
{
if (!$d || $d === '0000-00-00') return '';
return date("d/m/Y", strtotime($d));
}
function formatDateTimeIT($d)
{
if (!$d || $d === '0000-00-00 00:00:00') return '';
return date("d/m/Y H:i", strtotime($d));
}
function worksheetNumberLabel($n)
{
$n = (int)$n;
return $n > 0 ? 'FL' . $n : '—';
}
function revisionLabel($rev)
{
$rev = trim((string)$rev);
return $rev !== '' ? $rev : '0';
}
$action = $_POST['action'] ?? '';
try {
if ($action === 'get_matrice_worksheets') {
$idmatrice = isset($_POST['idmatrice']) ? (int)$_POST['idmatrice'] : 0;
if ($idmatrice <= 0) {
echo json_encode([
'success' => false,
'message' => 'ID matrice non valido'
]);
exit;
}
$stmt = $pdo->prepare("
SELECT
ws.id,
ws.idmatrice,
ws.worksheet_number,
ws.revision_code,
ws.worksheet_status,
ws.worksheet_date,
ws.customer_name,
ws.profile_type_code,
ws.marking,
ws.approved_by,
ws.created_at,
ws.updated_at,
(
SELECT COUNT(*)
FROM work_sheet_mescole wsm
WHERE wsm.worksheet_id = ws.id
) AS mix_count
FROM work_sheets ws
WHERE ws.idmatrice = ?
ORDER BY
ws.worksheet_number DESC,
CASE
WHEN ws.revision_code IS NULL OR ws.revision_code = '' THEN 0
WHEN ws.revision_code REGEXP '^R[0-9]+$' THEN CAST(SUBSTRING(ws.revision_code, 2) AS UNSIGNED)
ELSE 0
END DESC,
ws.id DESC
");
$stmt->execute([$idmatrice]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$data = [];
foreach ($rows as $r) {
$data[] = [
'id' => (int)$r['id'],
'idmatrice' => (int)$r['idmatrice'],
'worksheet_number' => (int)($r['worksheet_number'] ?? 0),
'worksheet_number_label' => worksheetNumberLabel($r['worksheet_number'] ?? 0),
'revision_code' => $r['revision_code'] ?? '',
'revision_label' => revisionLabel($r['revision_code'] ?? ''),
'worksheet_status' => $r['worksheet_status'] ?? 'active',
'worksheet_status_label' => (($r['worksheet_status'] ?? 'active') === 'inactive') ? 'Inattivo' : 'Attivo',
'worksheet_date' => $r['worksheet_date'],
'worksheet_date_it' => formatDateIT($r['worksheet_date']),
'customer_name' => $r['customer_name'] ?? '',
'profile_type_code' => $r['profile_type_code'] ?? '',
'marking' => $r['marking'] ?? '',
'approved_by' => $r['approved_by'] ?? '',
'created_at' => $r['created_at'] ?? '',
'created_at_it' => formatDateTimeIT($r['created_at'] ?? ''),
'updated_at' => $r['updated_at'] ?? '',
'updated_at_it' => formatDateTimeIT($r['updated_at'] ?? ''),
'mix_count' => (int)($r['mix_count'] ?? 0)
];
}
echo json_encode([
'success' => true,
'worksheets' => $data
]);
exit;
}
if ($action === 'get_worksheet_detail') {
$worksheetId = isset($_POST['worksheet_id']) ? (int)$_POST['worksheet_id'] : 0;
if ($worksheetId <= 0) {
echo json_encode([
'success' => false,
'message' => 'ID foglio non valido'
]);
exit;
}
$stmt = $pdo->prepare("
SELECT
ws.*,
m.nome AS matrice_nome,
m.cliente AS matrice_cliente
FROM work_sheets ws
LEFT JOIN matrice m ON m.id = ws.idmatrice
WHERE ws.id = ?
LIMIT 1
");
$stmt->execute([$worksheetId]);
$ws = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$ws) {
echo json_encode([
'success' => false,
'message' => 'Foglio di lavoro non trovato'
]);
exit;
}
$stmtMix = $pdo->prepare("
SELECT
wsm.*,
me.nome AS mescola_nome,
me.nomeuscita AS mescola_uscita
FROM work_sheet_mescole wsm
LEFT JOIN mescole me ON me.id = wsm.idmescola
WHERE wsm.worksheet_id = ?
ORDER BY wsm.mix_position ASC, wsm.id ASC
");
$stmtMix->execute([$worksheetId]);
$mixRows = $stmtMix->fetchAll(PDO::FETCH_ASSOC);
echo json_encode([
'success' => true,
'worksheet' => [
'id' => (int)$ws['id'],
'worksheet_number' => (int)($ws['worksheet_number'] ?? 0),
'worksheet_number_label' => worksheetNumberLabel($ws['worksheet_number'] ?? 0),
'revision_code' => $ws['revision_code'] ?? '',
'revision_label' => revisionLabel($ws['revision_code'] ?? ''),
'worksheet_status' => $ws['worksheet_status'] ?? 'active',
'worksheet_status_label' => (($ws['worksheet_status'] ?? 'active') === 'inactive') ? 'Inattivo' : 'Attivo',
'idmatrice' => (int)$ws['idmatrice'],
'matrice_nome' => $ws['matrice_nome'] ?? '',
'matrice_cliente' => $ws['matrice_cliente'] ?? '',
'worksheet_date' => $ws['worksheet_date'] ?? '',
'worksheet_date_it' => formatDateIT($ws['worksheet_date'] ?? ''),
'customer_name' => $ws['customer_name'] ?? '',
'profile_type_code' => $ws['profile_type_code'] ?? '',
'marking' => $ws['marking'] ?? '',
'prod_control_measure_settings' => $ws['prod_control_measure_settings'] ?? '',
'control_frequency_cut' => $ws['control_frequency_cut'] ?? '',
'control_frequency_drawing' => $ws['control_frequency_drawing'] ?? '',
'control_frequency_jig' => $ws['control_frequency_jig'] ?? '',
'control_mode_jig' => $ws['control_mode_jig'] ?? '',
'requested_package_code' => $ws['requested_package_code'] ?? '',
'meters_per_package' => $ws['meters_per_package'] ?? '',
'meters_per_package_tolerance' => $ws['meters_per_package_tolerance'] ?? '',
'meters_per_package_notes' => $ws['meters_per_package_notes'] ?? '',
'box_type' => $ws['box_type'] ?? '',
'packages_or_pieces_per_box' => $ws['packages_or_pieces_per_box'] ?? '',
'meters_per_box' => $ws['meters_per_box'] ?? '',
'pallet_type' => $ws['pallet_type'] ?? '',
'boxes_or_packages_per_pallet' => $ws['boxes_or_packages_per_pallet'] ?? '',
'speed_expected_kg_h' => $ws['speed_expected_kg_h'] ?? '',
'speed_actual_kg_h' => $ws['speed_actual_kg_h'] ?? '',
'speed_expected_m_h' => $ws['speed_expected_m_h'] ?? '',
'speed_actual_m_h' => $ws['speed_actual_m_h'] ?? '',
'approved_by' => $ws['approved_by'] ?? '',
'notes' => $ws['notes'] ?? '',
'created_at' => $ws['created_at'] ?? '',
'created_at_it' => formatDateTimeIT($ws['created_at'] ?? ''),
'updated_at' => $ws['updated_at'] ?? '',
'updated_at_it' => formatDateTimeIT($ws['updated_at'] ?? '')
],
'mix_rows' => array_map(function ($r) {
return [
'id' => (int)$r['id'],
'mix_position' => (int)$r['mix_position'],
'mescola_nome' => $r['mescola_nome'] ?? '',
'mescola_uscita' => $r['mescola_uscita'] ?? '',
'mix_weight_g_m' => $r['mix_weight_g_m'] ?? '',
'required_density' => $r['required_density'] ?? '',
'required_hardness_shore_a' => $r['required_hardness_shore_a'] ?? '',
'lubrication_type' => $r['lubrication_type'] ?? '',
'lubrication_notes' => $r['lubrication_notes'] ?? ''
];
}, $mixRows)
]);
exit;
}
echo json_encode([
'success' => false,
'message' => 'Azione AJAX sconosciuta'
]);
exit;
} catch (Exception $e) {
echo json_encode([
'success' => false,
'message' => $e->getMessage()
]);
exit;
}
@@ -0,0 +1,136 @@
<?php
require_once(__DIR__ . "/class/db-functions.php");
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$STATUS_PROGRAMMATO = 6;
$STATUS_DA_PROGRAMMARE = 1;
$jsonFile = __DIR__ . "/data/production_priority.json";
/* -------------------------------
JSON HELPERS
---------------------------------*/
function loadPriority()
{
global $jsonFile;
if (!file_exists($jsonFile)) return [];
return json_decode(file_get_contents($jsonFile), true) ?: [];
}
function savePriority($arr)
{
global $jsonFile;
file_put_contents($jsonFile, json_encode($arr, JSON_PRETTY_PRINT));
}
/* -------------------------------
LOAD: PROGRAMMATI
---------------------------------*/
if ($_GET['mode'] === 'planned') {
$priority = loadPriority();
$map = [];
foreach ($priority as $p) $map[$p['id']] = $p['priority'];
$sql = "SELECT p.*, m.nome AS matrice, ms.nome AS mescola,
l.name AS linea, c.nome AS cliente
FROM productiondata p
LEFT JOIN matrice m ON p.idmatrice = m.id
LEFT JOIN mescole ms ON p.idmescola = ms.id
LEFT JOIN production_lines l ON p.id_linea = l.id
LEFT JOIN clients c ON p.id_cliente = c.id
WHERE p.id_status = :s";
$stmt = $pdo->prepare($sql);
$stmt->execute(['s' => $STATUS_PROGRAMMATO]);
$rows = $stmt->fetchAll();
// Ordina per priority
usort($rows, function ($a, $b) use ($map) {
return ($map[$a['id']] ?? 9999) <=> ($map[$b['id']] ?? 9999);
});
ob_start();
foreach ($rows as $r):
$prio = $map[$r['id']] ?? '-';
?>
<tr data-id="<?= $r['id'] ?>">
<td><strong><?= $prio ?></strong></td>
<td><?= date('d/m/Y', strtotime($r['Data'])) ?></td>
<td><?= $r['matrice'] ?></td>
<td><?= $r['mescola'] ?></td>
<td><?= $r['linea'] ?></td>
<td><?= $r['cliente'] ?? '-' ?></td>
</tr>
<?php
endforeach;
echo json_encode(['html' => ob_get_clean()]);
exit;
}
/* -------------------------------
LOAD: DA PROGRAMMARE
---------------------------------*/
if ($_GET['mode'] === 'to_plan') {
$sql = "SELECT p.*, m.nome AS matrice, ms.nome AS mescola,
l.name AS linea, c.nome AS cliente
FROM productiondata p
LEFT JOIN matrice m ON p.idmatrice = m.id
LEFT JOIN mescole ms ON p.idmescola = ms.id
LEFT JOIN production_lines l ON p.id_linea = l.id
LEFT JOIN clients c ON p.id_cliente = c.id
WHERE p.id_status = :s
ORDER BY p.Data ASC";
$stmt = $pdo->prepare($sql);
$stmt->execute(['s' => $STATUS_DA_PROGRAMMARE]);
ob_start();
foreach ($stmt as $r): ?>
<tr data-id="<?= $r['id'] ?>">
<td><?= date('d/m/Y', strtotime($r['Data'])) ?></td>
<td><?= $r['matrice'] ?></td>
<td><?= $r['mescola'] ?></td>
<td><?= $r['linea'] ?></td>
<td><?= $r['cliente'] ?? '-' ?></td>
</tr>
<?php endforeach;
echo json_encode(['html' => ob_get_clean()]);
exit;
}
/* -------------------------------
UPDATE STATUS + PRIORITY
---------------------------------*/
if ($_POST['mode'] === 'save') {
$planned = json_decode($_POST['planned'], true);
$toPlan = json_decode($_POST['toPlan'], true);
$pdo->beginTransaction();
// Aggiorna programmati
foreach ($planned as $i => $row) {
$id = $row['id'];
$stmt = $pdo->prepare("UPDATE productiondata SET id_status = :s WHERE id = :id");
$stmt->execute(['s' => $STATUS_PROGRAMMATO, 'id' => $id]);
$priorityArr[] = ['id' => $id, 'priority' => $i + 1];
}
// Aggiorna da programmare
foreach ($toPlan as $row) {
$id = $row['id'];
$stmt = $pdo->prepare("UPDATE productiondata SET id_status = :s WHERE id = :id");
$stmt->execute(['s' => $STATUS_DA_PROGRAMMARE, 'id' => $id]);
}
$pdo->commit();
savePriority($priorityArr);
echo json_encode(['success' => true]);
exit;
}
+33
View File
@@ -0,0 +1,33 @@
<?php
require_once("include/headscript.php");
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$programmati = json_decode($_POST["programmati"] ?? '[]', true);
$daProgrammare = json_decode($_POST["daProgrammare"] ?? '[]', true);
$pdo->beginTransaction();
foreach ($programmati as $p) {
if (empty($p['id'])) {
continue;
}
$stmt = $pdo->prepare(
"UPDATE productiondata SET id_status=6, priority=? WHERE id=?"
);
$stmt->execute([(int)$p["priority"], (int)$p["id"]]);
}
foreach ($daProgrammare as $p) {
if (empty($p['id'])) {
continue;
}
$stmt = $pdo->prepare(
"UPDATE productiondata SET id_status=1, priority=? WHERE id=?"
);
$stmt->execute([(int)$p["priority"], (int)$p["id"]]);
}
$pdo->commit();
echo json_encode(["success" => true]);
-50
View File
@@ -1,50 +0,0 @@
<?php
ob_start();
session_start();
require_once '../../vendor/autoload.php';
$response = ['error' => '', 'rows' => [], 'columns' => [], 'template_id' => 0, 'filename' => '', 'excel_data' => []];
try {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input = json_decode(file_get_contents('php://input'), true);
$template_id = isset($input['template_id']) ? intval($input['template_id']) : 0;
$filename = $input['routine_data']['filename'] ?? '';
$headerrow = $input['routine_data']['headerrow'] ?? 1;
$excelData = $input['excel_data'] ?? [];
$routineData = $input['routine_data'] ?? [];
if (!$filename || empty($excelData)) {
throw new Exception("Dati della routine mancanti.");
}
$routineFile = __DIR__ . '/routines/' . $filename;
if (file_exists($routineFile)) {
include_once $routineFile;
$routineData['xls_headers'] = $_SESSION['headers'] ?? [];
applyRoutine($excelData, $routineData); // Modifica $excelData in place
error_log("Routine {$routineData['name']} applicata (file: {$filename}) per template {$template_id}, header row: {$headerrow}");
} else {
throw new Exception("File della routine non trovato: $routineFile");
}
// Aggiorna la sessione con i dati modificati
$_SESSION['excel_data'] = $excelData;
$response['excel_data'] = $excelData;
$response['rows'] = array_column($excelData, 'data');
$response['columns'] = $_SESSION['headers'];
$response['template_id'] = $template_id;
$response['filename'] = $input['filename'] ?? '';
} else {
$response['error'] = "Richiesta non valida.";
}
} catch (Exception $e) {
$response['error'] = "Errore durante l'applicazione della routine: " . $e->getMessage();
error_log("Exception in apply_routine.php: " . $e->getMessage());
}
ob_end_clean();
header('Content-Type: application/json');
echo json_encode($response);
exit;
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

+10
View File
@@ -37,6 +37,16 @@ $(function () {
}, },
)); ));
}), }),
// NEW: se la pagina parte già con .wrapper.toggled, abilita subito l'hover
$(".wrapper").hasClass("toggled") &&
$(".sidebar-wrapper").hover(
function () {
$(".wrapper").addClass("sidebar-hovered");
},
function () {
$(".wrapper").removeClass("sidebar-hovered");
},
),
$(document).ready(function () { $(document).ready(function () {
$(window).on("scroll", function () { $(window).on("scroll", function () {
$(this).scrollTop() > 300 $(this).scrollTop() > 300
@@ -0,0 +1,362 @@
(function () {
function escapeHtml(str) {
return String(str || "")
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function valueOrDash(v) {
return v === null || v === undefined || String(v).trim() === ""
? "—"
: escapeHtml(v);
}
function renderReadonlyField(label, value) {
return `
<div class="readonly-label">${escapeHtml(label)}</div>
<div class="readonly-value">${valueOrDash(value)}</div>
`;
}
window.loadMatriceWorksheets = function (idmatrice, matriceNome, endpoint) {
endpoint = endpoint || "ajax/worksheet-linked-data.php";
$("#wl_idmatrice").val(idmatrice);
$("#wl_matrice_name").html(
`<span class="worksheet-chip"><i class="fa-solid fa-layer-group"></i>${escapeHtml(matriceNome || "")}</span>`,
);
$("#worksheetsListContainer").html(
'<div class="text-muted">Caricamento fogli di lavoro...</div>',
);
fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body:
"action=get_matrice_worksheets&idmatrice=" +
encodeURIComponent(idmatrice),
})
.then(async (r) => {
const text = await r.text();
try {
return JSON.parse(text);
} catch (e) {
console.error("Risposta non JSON worksheets:", text);
throw new Error("Risposta non JSON, vedi console");
}
})
.then((data) => {
if (!data.success) {
$("#worksheetsListContainer").html(
'<div class="text-danger">Errore nel caricamento dei fogli</div>',
);
return;
}
const rows = data.worksheets || [];
if (!rows.length) {
$("#worksheetsListContainer").html(
'<div class="text-muted">Nessun foglio di lavoro collegato a questo profilo</div>',
);
return;
}
let html = `
<div class="table-responsive">
<table class="table table-striped align-middle worksheet-list-table">
<thead>
<tr>
<th style="width:110px;">Foglio</th>
<th style="width:100px;">Rev.</th>
<th style="width:110px;">Stato</th>
<th style="width:140px;">Data foglio</th>
<th>Cliente</th>
<th>Codice profilo</th>
<th style="width:110px;">Mescole</th>
<th style="width:230px;">Azioni</th>
</tr>
</thead>
<tbody>
`;
rows.forEach((r) => {
const statusBadge =
r.worksheet_status === "inactive"
? `<span class="worksheet-badge-status-inactive">Inattivo</span>`
: `<span class="worksheet-badge-status-active">Attivo</span>`;
html += `
<tr>
<td><span class="worksheet-badge-fl">${escapeHtml(r.worksheet_number_label || "—")}</span></td>
<td><span class="worksheet-badge-rev">${escapeHtml(r.revision_label || "0")}</span></td>
<td>${statusBadge}</td>
<td>${escapeHtml(r.worksheet_date_it || "—")}</td>
<td title="${escapeHtml(r.customer_name || "")}">${escapeHtml(r.customer_name || "—")}</td>
<td>${escapeHtml(r.profile_type_code || "—")}</td>
<td>${escapeHtml(String(r.mix_count || 0))}</td>
<td class="text-nowrap">
<button type="button"
class="btn btn-view-worksheet open-worksheet-detail"
data-id="${r.id}"
data-endpoint="${escapeHtml(endpoint)}">
<i class="fa-solid fa-eye me-1"></i>Apri dettaglio
</button>
<a class="worksheet-open-link ms-1"
href="manage-worksheet.php?id=${r.id}"
target="_blank">
<i class="fa-solid fa-arrow-up-right-from-square"></i>Apri pagina
</a>
</td>
</tr>
`;
});
html += `
</tbody>
</table>
</div>
`;
$("#worksheetsListContainer").html(html);
})
.catch(() => {
$("#worksheetsListContainer").html(
'<div class="text-danger">Errore nel caricamento dei fogli</div>',
);
});
};
window.loadWorksheetDetail = function (worksheetId, endpoint) {
endpoint = endpoint || "ajax/worksheet-linked-data.php";
$("#worksheetDetailContainer").html(
'<div class="text-muted">Caricamento dettaglio foglio...</div>',
);
fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body:
"action=get_worksheet_detail&worksheet_id=" +
encodeURIComponent(worksheetId),
})
.then(async (r) => {
const text = await r.text();
try {
return JSON.parse(text);
} catch (e) {
console.error("Risposta non JSON worksheet detail:", text);
throw new Error("Risposta non JSON, vedi console");
}
})
.then((data) => {
if (!data.success) {
console.error("Errore worksheets:", data);
$("#worksheetsListContainer").html(
'<div class="text-danger">Errore nel caricamento dei fogli: ' +
escapeHtml(
data.message || "nessun dettaglio restituito",
) +
"</div>",
);
return;
}
const ws = data.worksheet || {};
const mixRows = data.mix_rows || [];
let mixHtml = `<div class="text-muted">Nessuna mescola associata</div>`;
if (mixRows.length) {
mixHtml = `
<div class="table-responsive">
<table class="table table-striped align-middle mix-readonly-table">
<thead>
<tr>
<th style="width:80px;">Pos</th>
<th>Mescola</th>
<th style="width:120px;">Peso g/m</th>
<th style="width:140px;">Densità</th>
<th style="width:150px;">Durezza</th>
<th style="width:130px;">Lubr.</th>
<th>Note lubr.</th>
</tr>
</thead>
<tbody>
`;
mixRows.forEach((r) => {
const nomeMescola = r.mescola_uscita
? `${escapeHtml(r.mescola_nome || "—")} <div class="small text-muted">${escapeHtml(r.mescola_uscita)}</div>`
: escapeHtml(r.mescola_nome || "—");
mixHtml += `
<tr>
<td>${escapeHtml(String(r.mix_position || ""))}</td>
<td>${nomeMescola}</td>
<td>${valueOrDash(r.mix_weight_g_m)}</td>
<td>${valueOrDash(r.required_density)}</td>
<td>${valueOrDash(r.required_hardness_shore_a)}</td>
<td>${valueOrDash(r.lubrication_type)}</td>
<td>${valueOrDash(r.lubrication_notes)}</td>
</tr>
`;
});
mixHtml += `
</tbody>
</table>
</div>
`;
}
const html = `
<div class="worksheet-title-box mb-4">
<div class="d-flex justify-content-between align-items-start gap-3 flex-wrap">
<div>
<h4 class="mb-1">${escapeHtml(ws.worksheet_number_label || "—")} / Rev. ${escapeHtml(ws.revision_label || "0")}</h4>
<small>
Stato: ${escapeHtml(ws.worksheet_status_label || "Attivo")}
${ws.matrice_nome ? " • Profilo: " + escapeHtml(ws.matrice_nome) : ""}
${ws.matrice_cliente ? " • Cliente matrice: " + escapeHtml(ws.matrice_cliente) : ""}
</small>
</div>
<div>
<a href="manage-worksheet.php?id=${escapeHtml(String(ws.id || ""))}"
target="_blank"
class="worksheet-open-link">
<i class="fa-solid fa-arrow-up-right-from-square"></i>
Apri foglio completo
</a>
</div>
</div>
</div>
<div class="row g-3">
<div class="col-lg-6">
<div class="readonly-card">
<div class="readonly-card-header">Dati principali</div>
<div class="readonly-card-body">
<div class="readonly-grid">
${renderReadonlyField("Foglio", ws.worksheet_number_label)}
${renderReadonlyField("Revisione", ws.revision_label)}
${renderReadonlyField("Stato", ws.worksheet_status_label)}
${renderReadonlyField("Data foglio", ws.worksheet_date_it)}
${renderReadonlyField("Cliente override", ws.customer_name)}
${renderReadonlyField("Codice profilo", ws.profile_type_code)}
${renderReadonlyField("Marchiatura", ws.marking)}
${renderReadonlyField("Approvato da", ws.approved_by)}
${renderReadonlyField("Creato il", ws.created_at_it)}
${renderReadonlyField("Ultimo aggiornamento", ws.updated_at_it)}
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="readonly-card">
<div class="readonly-card-header">Controlli produzione</div>
<div class="readonly-card-body">
<div class="readonly-grid">
${renderReadonlyField("Taglio", ws.control_frequency_cut)}
${renderReadonlyField("Disegno", ws.control_frequency_drawing)}
${renderReadonlyField("Dima", ws.control_frequency_jig)}
${renderReadonlyField("Modalità dima", ws.control_mode_jig)}
</div>
<hr>
<div class="readonly-label mb-2">Impostazione misure controllo produzione</div>
<div class="readonly-value" style="white-space:pre-wrap;">${valueOrDash(ws.prod_control_measure_settings)}</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="readonly-card">
<div class="readonly-card-header">Packaging / Confezionamento</div>
<div class="readonly-card-body">
<div class="readonly-grid">
${renderReadonlyField("Codice confezione", ws.requested_package_code)}
${renderReadonlyField("Metri per confezione", ws.meters_per_package)}
${renderReadonlyField("Tolleranza metri/conf.", ws.meters_per_package_tolerance)}
${renderReadonlyField("Scatola tipo", ws.box_type)}
${renderReadonlyField("Conf./pezzi per scatola", ws.packages_or_pieces_per_box)}
${renderReadonlyField("Metri per scatola", ws.meters_per_box)}
${renderReadonlyField("Bancale tipo", ws.pallet_type)}
${renderReadonlyField("Scatole/conf. per bancale", ws.boxes_or_packages_per_pallet)}
</div>
<hr>
<div class="readonly-label mb-2">Note metri / confezione</div>
<div class="readonly-value" style="white-space:pre-wrap;">${valueOrDash(ws.meters_per_package_notes)}</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="readonly-card">
<div class="readonly-card-header">Velocità e note</div>
<div class="readonly-card-body">
<div class="readonly-grid">
${renderReadonlyField("Vel. prevista kg/h", ws.speed_expected_kg_h)}
${renderReadonlyField("Vel. effettiva kg/h", ws.speed_actual_kg_h)}
${renderReadonlyField("Vel. prevista m/h", ws.speed_expected_m_h)}
${renderReadonlyField("Vel. effettiva m/h", ws.speed_actual_m_h)}
</div>
<hr>
<div class="readonly-label mb-2">Note</div>
<div class="readonly-value" style="white-space:pre-wrap;">${valueOrDash(ws.notes)}</div>
</div>
</div>
</div>
<div class="col-12">
<div class="readonly-card">
<div class="readonly-card-header">Mescole associate al foglio</div>
<div class="readonly-card-body">
${mixHtml}
</div>
</div>
</div>
</div>
`;
$("#worksheetDetailContainer").html(html);
})
.catch((err) => {
console.error("Catch loadMatriceWorksheets:", err);
$("#worksheetsListContainer").html(
'<div class="text-danger">Errore nel caricamento dei fogli: ' +
escapeHtml(err.message || "errore JavaScript/fetch") +
"</div>",
);
});
};
$(document).on("click", ".worksheets, .show-worksheets", function () {
const idmatrice = $(this).data("id");
const nome = $(this).data("nome") || "";
const endpoint =
$(this).data("endpoint") || "ajax/worksheet-linked-data.php";
loadMatriceWorksheets(idmatrice, nome, endpoint);
new bootstrap.Modal(
document.getElementById("worksheetsListModal"),
).show();
});
$(document).on("click", ".open-worksheet-detail", function () {
const worksheetId = $(this).data("id");
const endpoint =
$(this).data("endpoint") || "ajax/worksheet-linked-data.php";
loadWorksheetDetail(worksheetId, endpoint);
new bootstrap.Modal(
document.getElementById("worksheetDetailModal"),
).show();
});
})();
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

-58
View File
@@ -1,58 +0,0 @@
<?php
header('Content-Type: application/json');
// URL dell'API e credenziali
$api_url = 'https://93.43.5.102/limsapi/api/authentication/authenticate';
$credentials = [
'Username' => 'WebApiUser',
'Password' => 'webapiuser01'
];
// Inizializza cURL
$ch = curl_init($api_url);
// Configura le opzioni di cURL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($credentials));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Accept: application/json'
]);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Solo per test
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Solo per test
curl_setopt($ch, CURLOPT_VERBOSE, true);
$log = fopen('curl_auth_debug.log', 'w');
curl_setopt($ch, CURLOPT_STDERR, $log);
// Esegui la richiesta
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_error = curl_error($ch);
fclose($log);
// Verifica errori
if ($response === false || $http_code != 200) {
http_response_code($http_code ? $http_code : 500);
echo json_encode([
'error' => 'Errore nella richiesta API',
'http_code' => $http_code,
'curl_error' => $curl_error,
'response' => substr($response, 0, 1000)
]);
} else {
$decoded = json_decode($response);
if (json_last_error() === JSON_ERROR_NONE) {
http_response_code($http_code);
echo $response;
} else {
http_response_code(500);
echo json_encode([
'error' => 'Risposta non JSON valida',
'http_code' => $http_code,
'response' => substr($response, 0, 1000)
]);
}
}
curl_close($ch);
-131
View File
@@ -1,131 +0,0 @@
<?php
require_once "class/VisualLimsApiClient.class.php";
include('include/headscript.php');
$dbHandler = DBHandlerSelect::getInstance();
$pdo = $dbHandler->getConnection();
header("Content-Type: application/json");
// 🔹 Configura directory log (creala se non esiste)
$logDir = __DIR__ . '/logs/api/';
if (!is_dir($logDir)) {
mkdir($logDir, 0755, true);
}
// 🔹 Base URL API
$apiBaseUrl = 'https://93.43.5.102/limsapi/api/odata/';
// 🔹 Hardcoded values
$iddatadb = 846;
$commessaId = 533357;
try {
// 🔹 STEP 4: Fetch Field Values with Labels (usa dati reali per iddatadb=845)
$stmt = $pdo->prepare("
SELECT
idd.field_value,
m.field_label,
m.schema_id,
m.field_id
FROM
import_data_details as idd
JOIN template_mapping m ON idd.mapping_id = m.id
WHERE idd.id = :iddatadb
");
$stmt->execute(['iddatadb' => $iddatadb]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$fieldValues = [];
$valueMap = []; // Mappa per field_id -> valore
foreach ($rows as $row) {
$fieldValues[] = [
"IdCommesseCustomFields" => (int) $row['field_id'],
"Valore" => $row['field_value'],
"FieldLabel" => $row['field_label']
];
$valueMap[(int) $row['field_id']] = $row['field_value']; // Mappa per ID definizione
}
// Logga i fieldValues in error_log
$logFieldValues = "FieldValues dal DB (iddatadb={$iddatadb}):\n" . json_encode($fieldValues, JSON_PRETTY_PRINT);
error_log($logFieldValues);
// 🔹 Initialize API client
$api = VisualLimsApiClient::getInstance();
// 🔹 STEP A: GET iniziale per CommesseCustomFields con espansione CustomField
$expand = "CommesseCustomFields(\$expand=CustomField)"; // Espansione come da istruzioni fornitore
$commessaWithFields = $api->get("CommessaWeb(" . $commessaId . ")?\$expand=" . $expand);
// 🔹 STEP B: Prepara payload PATCH (tutti i campi, sovrascrivi se match su CustomField.IdCustomField == field_id)
$commessaCustomFields = [];
foreach ($commessaWithFields["CommesseCustomFields"] as $customField) {
$definitionId = (int) ($customField["CustomField"]["IdCustomField"] ?? 0); // Usa IdCustomField dal CustomField
$currentValue = $customField["Valore"] ?? '';
$newValue = isset($valueMap[$definitionId]) ? $valueMap[$definitionId] : $currentValue;
$commessaCustomFields[] = [
"IdCommesseCustomFields" => (int) $customField["IdCommesseCustomFields"],
"Valore" => $newValue
];
}
// 🔹 Unico file di log per tutto
$logFile = $logDir . "commessa_{$commessaId}_patch_and_get_" . time() . ".txt";
$logContent = "FieldValues dal DB (iddatadb={$iddatadb}):\n" . json_encode($fieldValues, JSON_PRETTY_PRINT) . "\n\n";
// Log curl-like per GET iniziale
$logContent .= "GET iniziale:\n" .
"curl --location --request GET '{$apiBaseUrl}CommessaWeb({$commessaId})?\$expand=CommesseCustomFields(\$expand=CustomField)' \\\n" .
"--header 'Authorization: Bearer ••••••'\n\n" .
"RESPONSE:\n" . json_encode($commessaWithFields, JSON_PRETTY_PRINT) . "\n\n---\n";
if (!empty($commessaCustomFields)) {
$updatePayload = ["CommesseCustomFields" => $commessaCustomFields];
// Log curl-like per PATCH
$jsonPayload = json_encode($updatePayload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
$logContent .= "PATCH:\n" .
"curl --location --request PATCH '{$apiBaseUrl}CommessaWeb({$commessaId})' \\\n" .
"--header 'Content-Type: application/json' \\\n" .
"--header 'Authorization: Bearer ••••••' \\\n" .
"--data '{$jsonPayload}'\n\n";
$patchResponse = $api->patch("CommessaWeb({$commessaId})", $updatePayload);
$logContent .= "PATCH RESPONSE:\n" . json_encode($patchResponse, JSON_PRETTY_PRINT) . "\n\n---\n";
} else {
$logContent .= "PATCH: Nessun campo custom da aggiornare\n\n---\n";
}
// 🔹 STEP C: GET di controllo post-PATCH
$commessaAfterPatch = $api->get("CommessaWeb(" . $commessaId . ")?\$expand=" . $expand);
// Log curl-like per GET di controllo
$logContent .= "GET di controllo:\n" .
"curl --location --request GET '{$apiBaseUrl}CommessaWeb({$commessaId})?\$expand=CommesseCustomFields(\$expand=CustomField)' \\\n" .
"--header 'Authorization: Bearer ••••••'\n\n" .
"RESPONSE:\n" . json_encode($commessaAfterPatch, JSON_PRETTY_PRINT);
// Salva log unico
file_put_contents($logFile, $logContent);
// 🔹 Output a schermo
echo json_encode([
"success" => true,
"message" => "PATCH eseguito su commessa {$commessaId} con dati da iddatadb {$iddatadb}",
"commessaAfterPatch" => $commessaAfterPatch,
"totalCustomFieldsUpdated" => count($commessaCustomFields),
"fieldValues" => $fieldValues,
"logFile" => $logFile
]);
} catch (Exception $e) {
error_log("Patch Error: " . $e->getMessage() . "\nTrace: " . $e->getTraceAsString());
echo json_encode([
"success" => false,
"message" => "Patch failed: " . $e->getMessage(),
"logFile" => $logFile ?? 'Nessun log generato'
]);
}
@@ -29,7 +29,7 @@ class VisualLimsApiClient
return self::$instance; return self::$instance;
} }
private function authenticate() private function authenticate($retryCount = 0, $maxRetries = 3)
{ {
$ch = curl_init("{$this->baseUrl}/api/authentication/authenticate"); $ch = curl_init("{$this->baseUrl}/api/authentication/authenticate");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@@ -45,16 +45,22 @@ class VisualLimsApiClient
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_VERBOSE, true); curl_setopt($ch, CURLOPT_VERBOSE, true);
$log = fopen(__DIR__ . '/curl_auth_debug.log', 'w') ?: fopen('php://stderr', 'w'); $log = fopen(__DIR__ . '/curl_auth_debug.log', 'a') ?: fopen('php://stderr', 'w');
curl_setopt($ch, CURLOPT_STDERR, $log); curl_setopt($ch, CURLOPT_STDERR, $log);
$response = curl_exec($ch); $response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_error = curl_error($ch); $curl_error = curl_error($ch);
$log_message = date('Y-m-d H:i:s') . " - Auth attempt {$retryCount}: HTTP {$http_code}, Error: {$curl_error}, Response: " . substr($response, 0, 1000) . "\n";
fwrite($log, $log_message);
fclose($log); fclose($log);
curl_close($ch); curl_close($ch);
if ($response === false || $http_code != 200) { if ($response === false || $http_code != 200) {
if ($http_code === 400 && strpos($response, 'Cannot persist the object') !== false && $retryCount < $maxRetries) {
usleep(500000); // Ritardo di 500ms
return $this->authenticate($retryCount + 1, $maxRetries); // Riprova
}
throw new Exception("Autenticazione fallita: HTTP {$http_code}, Errore cURL: {$curl_error}, Risposta: " . substr($response, 0, 1000)); throw new Exception("Autenticazione fallita: HTTP {$http_code}, Errore cURL: {$curl_error}, Risposta: " . substr($response, 0, 1000));
} }
@@ -191,5 +197,4 @@ class VisualLimsApiClient
{ {
return $this->baseUrl; return $this->baseUrl;
} }
} }
+43
View File
@@ -0,0 +1,43 @@
<?php
// Recupero foto esistenti
$photosSlots = [];
$stmt = $pdo->prepare("
SELECT param_position, filename
FROM production_photos
WHERE production_id = ?
AND photo_type = 'parametri_macchina'
");
$stmt->execute([$r['id']]);
foreach ($stmt->fetchAll() as $p) {
$photosSlots[(int)$p['param_position']] = $p['filename'];
}
// Slot dinamici per la linea
$slots = $r['param_slots'] ?? [];
if (empty($slots)) {
echo "<div style='color:#999; padding:8px;'>Nessun parametro configurato per questa linea.</div>";
return;
}
?>
<div class="param-grid" style="grid-template-columns: repeat(<?= count($slots) ?>, 1fr);">
<?php foreach ($slots as $slot): ?>
<?php
$pos = (int)$slot['position'];
$label = htmlspecialchars($slot['short_label']);
$img = $photosSlots[$pos] ?? null;
?>
<div class="param-slot" data-slot="<?= $pos ?>" data-production="<?= $r['id'] ?>">
<div class="thumb">
<?php if ($img): ?>
<img src="photos/<?= htmlspecialchars($img) ?>" class="thumb-img">
<?php else: ?>
<img src="assets/placeholder-photo.png" class="thumb-img">
<?php endif; ?>
</div>
<div class="param-label"><?= $label ?></div>
</div>
<?php endforeach; ?>
</div>
@@ -0,0 +1,32 @@
<div class="photo-actions" style="margin-top:12px; display:flex; gap:12px; width:100%; align-items:center;">
<!-- Lotto mescola -->
<button class="photo-btn"
data-type="lotto_mescola"
data-production="<?= $r['id'] ?>"
title="Foto Lotti Mescola">
<i class="bi bi-box-seam" style="font-size:1.8rem; color:#334155;"></i>
</button>
<!-- Problemi -->
<button class="photo-btn"
data-type="problema"
data-production="<?= $r['id'] ?>"
title="Foto Problemi">
<i class="bi bi-exclamation-triangle" style="font-size:1.8rem; color:#b91c1c;"></i>
</button>
<!-- 🔥 SPAZIO PER PORTARE A DESTRA -->
<div style="flex-grow:1;"></div>
<!-- 🔵 ICONA QUALITÀ -->
<button class="photo-btn qc-btn"
data-production="<?= $r['id'] ?>"
title="Controlli Qualità">
<i class="bi bi-droplet-half"></i>
</button>
</div>
@@ -0,0 +1,67 @@
<div id="photoModal" class="custom-modal">
<div class="modal-content final-wide" style="max-width:800px; position:relative;">
<!-- X per chiudere -->
<button id="photoModalCloseX"
style="position:absolute; top:10px; right:15px; font-size:1.7rem; background:none; border:none; cursor:pointer;">
&times;
</button>
<h3 id="photoModalTitle">Carica Foto</h3>
<p id="photoModalSubtitle"></p>
<div id="photoMessageSuccess"
style="display:none; margin-bottom:10px; padding:8px 12px; border-radius:8px; background:#dcfce7; color:#166534; font-weight:500; text-align:left;">
Foto caricata correttamente.
</div>
<div id="photoMessageError"
style="display:none; margin-bottom:10px; padding:8px 12px; border-radius:8px; background:#fee2e2; color:#b91c1c; font-weight:500; text-align:left;">
⚠️ Errore durante il caricamento.
</div>
<form id="photoForm" enctype="multipart/form-data">
<input type="hidden" name="production_id" id="photoProductionId">
<input type="hidden" name="photo_type" id="photoType">
<input type="hidden" name="param_position" id="photoParamPosition">
<!-- input file DENTRO al form -->
<input type="file" name="photo" id="photoInput"
accept="image/*;capture=camera"
style="display:none;">
<div class="mb-3">
<label><strong>Carica o scatta una foto:</strong></label>
<button type="button" class="modal-btn" id="choosePhotoBtn">Scegli foto</button>
<span id="selectedPhotoName" style="margin-left:8px; font-size:0.85rem; color:#64748b;"></span>
</div>
<!-- 🔥 loader -->
<div id="photoLoading"
style="display:none; margin-top:10px; font-size:0.9rem; color:#64748b;">
Caricamento in corso...
</div>
<div id="singlePhotoInfo"
style="display:none; margin-top:10px; font-size:0.9rem; color:#b91c1c; text-align:left;">
Per questo parametro è già presente una foto.
Se vuoi sostituirla, chiedi all'amministratore di cancellare quella esistente.
</div>
<div class="modal-buttons" style="margin-top:1.5rem;">
<button type="button" id="photoCancel" class="modal-btn modal-cancel">Annulla</button>
<button type="submit" class="modal-btn modal-confirm">Carica</button>
</div>
</form>
<hr style="margin:1.5rem 0;">
<h4 style="font-size:1rem; margin-bottom:0.7rem;">Foto già registrate per questa tipologia</h4>
<div id="photoGallery" class="photo-gallery"
style="display:flex; flex-wrap:wrap; gap:10px; max-height:220px; overflow-y:auto; padding:4px 0;">
<!-- thumbnails caricati via JS -->
</div>
</div>
</div>
-211
View File
@@ -1,211 +0,0 @@
<?php
// Questo file può essere vuoto o contenere logica PHP aggiuntiva se necessario
?>
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Autenticazione VisualLims</title>
<!-- Includi Select2 CSS -->
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 20px auto;
padding: 20px;
}
#authButton {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
#authButton:hover {
background-color: #0056b3;
}
#result {
margin-top: 20px;
padding: 10px;
border: 1px solid #ccc;
word-wrap: break-word;
}
#schemiResult {
margin-top: 20px;
padding: 10px;
border: 1px solid #ccc;
word-wrap: break-word;
}
.select2-container {
width: 100% !important;
}
</style>
</head>
<body>
<h1>Autenticazione VisualLims</h1>
<button id="authButton">Autentica</button>
<div id="result"></div>
<!-- Tendina per i clienti -->
<h3>Seleziona un cliente:</h3>
<select id="clientiSelect" style="width: 100%;">
<option value="">Seleziona un cliente...</option>
</select>
<!-- Area per mostrare gli schemi -->
<div id="schemiResult"></div>
<!-- Includi jQuery (necessario per Select2) -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Includi Select2 JS -->
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script>
// Inizializza Select2 sulla tendina
$(document).ready(function() {
$('#clientiSelect').select2({
placeholder: "Cerca un cliente...",
allowClear: true
});
// Carica i clienti al caricamento della pagina
loadClienti();
});
// Autenticazione
document.getElementById('authButton').addEventListener('click', async () => {
const resultDiv = document.getElementById('result');
resultDiv.textContent = 'Autenticazione in corso...';
try {
const response = await fetch('auth_proxy.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
const data = await response.json();
if (!response.ok) {
throw new Error(`Errore HTTP! Stato: ${response.status}, Dettagli: ${data.error || 'Nessun dettaglio disponibile'}`);
}
if (typeof data === 'string' && data.length > 0) {
resultDiv.textContent = `Token: ${data}`;
} else if (data && data.token) {
resultDiv.textContent = `Token: ${data.token}`;
} else {
resultDiv.textContent = `Autenticazione fallita: Nessun token ricevuto. Dettagli: ${JSON.stringify(data)}`;
}
} catch (error) {
resultDiv.textContent = `Errore: ${error.message}`;
}
});
// Funzione per caricare i clienti nella tendina
async function loadClienti() {
const resultDiv = document.getElementById('result');
resultDiv.textContent = 'Caricamento clienti...';
try {
const response = await fetch('get_clienti.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({})
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `Errore HTTP: ${response.status}, Dettagli: ${JSON.stringify(data)}`);
}
if (data.value && Array.isArray(data.value)) {
const select = document.getElementById('clientiSelect');
data.value.forEach(c => {
const nome = c.Nominativo || 'Nome non disponibile';
const id = c.IdCliente || 'ID non disponibile';
const option = new Option(`${nome.trim()} (ID: ${id})`, id);
select.add(option);
});
resultDiv.textContent = 'Clienti caricati con successo.';
} else {
resultDiv.textContent = 'Nessun cliente trovato o formato dati non valido.';
console.log('Risposta API:', data);
}
} catch (err) {
resultDiv.textContent = 'Errore: ' + err.message;
console.error('Dettagli errore:', err);
}
}
// Evento per gestire la selezione di un cliente e recuperare gli schemi
$('#clientiSelect').on('select2:select', async function(e) {
const clienteId = e.target.value; // Oppure: $(this).val()
const schemiDiv = document.getElementById('schemiResult'); // Correzione del nome variabile
// Log per debug
console.log('Cliente selezionato:', clienteId);
if (!clienteId) {
schemiDiv.textContent = '';
return;
}
schemiDiv.textContent = 'Caricamento schemi...';
try {
const response = await fetch('get_schemi.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
clienteId
})
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `Errore HTTP: ${response.status}, Dettagli: ${JSON.stringify(data)}`);
}
if (data.SchemiAbilitati && Array.isArray(data.SchemiAbilitati)) {
let html = '<h3>Schemi Abilitati:</h3><ul>';
data.SchemiAbilitati.forEach(s => {
const nomeSchema = s.NomeSchema || s.Descrizione || 'Schema non specificato';
html += `<li>${nomeSchema}</li>`;
});
html += '</ul>';
schemiDiv.innerHTML = html;
} else {
schemiDiv.textContent = 'Nessuno schema trovato per questo cliente.';
console.log('Risposta Schemi:', data);
}
} catch (err) {
schemiDiv.textContent = 'Errore: ' + err.message;
console.error('Dettagli errore:', err);
}
});
// Gestisci la deselezione (opzionale)
$('#clientiSelect').on('select2:unselect', function(e) {
const schemiDiv = document.getElementById('schemiResult'); // Correzione del nome variabile
schemiDiv.textContent = '';
});
</script>
</body>
</html>
@@ -0,0 +1,103 @@
<?php
require_once dirname(__DIR__, 3) . '/vendor/autoload.php'; // Risale a root/vendor/
require_once dirname(__FILE__) . '/../class/VisualLimsApiClient.class.php'; // In root/public/userarea/class/
use Dotenv\Dotenv;
// Debug: Log the path where we expect the .env file
$envPath = dirname(__DIR__, 3);
file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . ' - Expected .env path: ' . $envPath . PHP_EOL, FILE_APPEND);
// Carica il file .env dalla root del progetto
try {
$dotenv = Dotenv::createImmutable($envPath);
$dotenv->load();
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore caricamento .env: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
exit(1);
}
// Recupera le variabili d'ambiente
$dbHost = $_ENV['DB_HOST'];
$dbName = $_ENV['DB_DATABASE'];
$dbUser = $_ENV['DB_USERNAME'];
$dbPass = $_ENV['DB_PASSWORD'];
$dbPrefix = $_ENV['DB_PREFIX'];
// Debug: Log database connection details (excluding password)
file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . " - DB Connection: host=$dbHost, dbname=$dbName, user=$dbUser, prefix=$dbPrefix" . PHP_EOL, FILE_APPEND);
// Connessione al database MySQL
try {
$pdo = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4", $dbUser, $dbPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore connessione DB: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
exit(1);
}
try {
$api = VisualLimsApiClient::getInstance();
// Endpoint per recuperare le Matrici
$endpoint = 'Matrice';
// (Opzionale) aggiungi parametri
$options = []; // es. ['$top' => 100]
// Debug: salva URL usato
$base_url = 'https://93.43.5.102/limsapi/api/odata/';
$query = http_build_query($options);
$full_url = $base_url . $endpoint . ($query ? '?' . $query : '');
file_put_contents(__DIR__ . '/last_url.txt', $full_url . PHP_EOL, FILE_APPEND);
// Chiamata API
$data = $api->get($endpoint, $options);
// Debug: Log the API response size
file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . ' - API response received, value count: ' . (isset($data['value']) ? count($data['value']) : 0) . PHP_EOL, FILE_APPEND);
// Salva il JSON in locale (opzionale, per debug)
file_put_contents(__DIR__ . '/matrici_response.json', json_encode($data, JSON_PRETTY_PRINT));
// Svuota la tabella (dump rapido)
$pdo->exec("TRUNCATE TABLE {$dbPrefix}matrici");
// Debug: Log after truncate
file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . ' - Table truncated: ' . $dbPrefix . 'matrici' . PHP_EOL, FILE_APPEND);
// Prepara l'insert
$stmt = $pdo->prepare("
INSERT INTO {$dbPrefix}matrici (
IdMatrice, NomeMatriceTraduzione, DescrizioneTraduzione, MacroMatrice, NomeMatrice, Descrizione
) VALUES (
:IdMatrice, :NomeMatriceTraduzione, :DescrizioneTraduzione, :MacroMatrice, :NomeMatrice, :Descrizione
)
");
// Inserisci i dati
$insertedRows = 0;
if (isset($data['value']) && is_array($data['value'])) {
foreach ($data['value'] as $item) {
$stmt->execute([
':IdMatrice' => $item['IdMatrice'],
':NomeMatriceTraduzione' => $item['NomeMatriceTraduzione'],
':DescrizioneTraduzione' => $item['DescrizioneTraduzione'] ?? null,
':MacroMatrice' => $item['MacroMatrice'] ?? null,
':NomeMatrice' => $item['NomeMatrice'],
':Descrizione' => $item['Descrizione'] ?? null,
]);
$insertedRows++;
// Debug: Log each inserted row
file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . ' - Inserted row with IdMatrice: ' . $item['IdMatrice'] . PHP_EOL, FILE_APPEND);
}
}
// Log successo
file_put_contents(__DIR__ . '/success_log.txt', date('Y-m-d H:i:s') . ' - Aggiornamento completato: ' . $insertedRows . ' record inseriti.' . PHP_EOL, FILE_APPEND);
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
exit(1);
}
exit(0); // Esci con successo per cron
+137 -2
View File
@@ -13,10 +13,145 @@
<link href="assets/css/app.css" rel="stylesheet"> <link href="assets/css/app.css" rel="stylesheet">
<link href="assets/css/icons.css" rel="stylesheet"> <link href="assets/css/icons.css" rel="stylesheet">
<!-- Theme Style CSS --> <!-- Theme Style CSS -->
<link rel="stylesheet" href="assets/css/dark-theme.css" /> <!-- <link rel="stylesheet" href="assets/css/dark-theme.css" />
<link rel="stylesheet" href="assets/css/semi-dark.css" /> <link rel="stylesheet" href="assets/css/semi-dark.css" />
<link rel="stylesheet" href="assets/css/header-colors.css" /> <link rel="stylesheet" href="assets/css/header-colors.css" /> -->
<!-- Font awesome --> <!-- Font awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<!-- SweetAlert2 --> <!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Override temporaneo per tema chiaro pastello -->
<style>
/* ======= HEADER (barra superiore) ======= */
.top-header {
background-color: #a4c4fdff !important;
/* azzurro pastello */
color: #1f2d3d !important;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1) !important;
}
.top-header .nav-link,
.top-header .navbar-brand,
.top-header .navbar-nav .nav-item a,
.top-header .dropdown-item {
color: #1a2a3b !important;
font-weight: 500 !important;
}
.top-header .nav-link:hover,
.top-header .navbar-nav .nav-item a:hover,
.top-header .dropdown-item:hover {
color: #0b5ed7 !important;
}
/* ======= SIDEBAR (menu laterale) ======= */
.sidebar-wrapper {
background-color: #dfebffff !important;
/* grigio chiaro con tono bluastro */
color: #2b3e50 !important;
box-shadow: inset -2px 0 5px rgba(0, 0, 0, 0.05);
}
.sidebar-wrapper .metismenu a {
color: #2b3e50 !important;
font-weight: 500 !important;
border-radius: 6px !important;
padding: 10px 14px !important;
}
.sidebar-wrapper .metismenu a:hover,
.sidebar-wrapper .metismenu .mm-active>a {
background-color: #d6e4ff !important;
/* azzurro più deciso al passaggio */
color: #0d6efd !important;
}
/* ======= CORPO PAGINA ======= */
body {
background-color: #f8fafc !important;
color: #2b3e50 !important;
}
.card,
.form-container,
.table-container {
background-color: #ffffff !important;
border: 1px solid #e2e8f0 !important;
}
/* Pulsanti principali coerenti */
.btn-primary,
.btn-submit {
background-color: #0d6efd !important;
border: none !important;
}
.btn-primary:hover,
.btn-submit:hover {
background-color: #0b5ed7 !important;
}
/* Navbar icone (se presenti) */
.top-header i {
color: #1f2d3d !important;
}
</style>
<style>
/* ======= TOPBAR (barra superiore, con menu e profilo utente) ======= */
.topbar {
background-color: #a4c4fdff !important;
/* azzurro pastello */
color: #1f2d3d !important;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08) !important;
}
.topbar .nav-link,
.topbar .navbar-nav .nav-item a,
.topbar .navbar-brand,
.topbar .dropdown-item {
color: #1f2d3d !important;
font-weight: 500 !important;
}
.topbar .nav-link:hover,
.topbar .navbar-nav .nav-item a:hover,
.topbar .dropdown-item:hover {
color: #0d6efd !important;
background-color: rgba(255, 255, 255, 0.3) !important;
border-radius: 6px;
}
.topbar .user-box .user-info p {
color: #1f2d3d !important;
}
.topbar .dropdown-menu {
border-radius: 8px !important;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1) !important;
}
/* ======= SIDEBAR HEADER (logo + titolo) ======= */
.sidebar-header {
background-color: #a4c4fdff !important;
/* leggermente più scuro per separare dal resto */
color: #1f2d3d !important;
border-bottom: 1px solid #a8c5f9 !important;
}
.sidebar-header .logo-text {
color: #1f2d3d !important;
font-weight: 700;
letter-spacing: 0.5px;
}
.sidebar-header .toggle-icon i {
color: #1f2d3d !important;
}
/* ======= ICONCINE GENERICHE ======= */
.bx,
.fa {
color: #1f2d3d !important;
}
</style>
File diff suppressed because one or more lines are too long
+28
View File
@@ -0,0 +1,28 @@
<?php
include('include/headscript.php');
require_once(__DIR__ . '/class/db-functions.php');
header('Content-Type: application/json');
try {
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
echo json_encode(['success' => false, 'message' => 'ID non valido.']);
exit;
}
$id = (int)$_GET['id'];
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare("DELETE FROM production_lines WHERE id = ?");
$stmt->execute([$id]);
if ($stmt->rowCount() > 0) {
echo json_encode(['success' => true]);
} else {
echo json_encode(['success' => false, 'message' => 'Linea non trovata o già eliminata.']);
}
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => 'Errore: ' . $e->getMessage()]);
}
+26
View File
@@ -0,0 +1,26 @@
<?php
include('../class/db-functions.php');
header('Content-Type: application/json');
try {
if (!isset($_GET['id'])) {
echo json_encode(['success' => false, 'message' => 'ID non fornito.']);
exit;
}
$id = intval($_GET['id']);
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Cancella eventuali associazioni
$pdo->prepare("DELETE FROM matrice_lines WHERE idmatrice = ?")->execute([$id]);
$pdo->prepare("DELETE FROM matrice_mescole WHERE idmatrice = ?")->execute([$id]);
// Cancella la matrice
$pdo->prepare("DELETE FROM matrice WHERE id = ?")->execute([$id]);
echo json_encode(['success' => true, 'message' => 'Matrice eliminata con successo.']);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => 'Errore: ' . $e->getMessage()]);
}
@@ -0,0 +1,61 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json; charset=utf-8');
$response = [
'success' => false,
'message' => ''
];
try {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
throw new Exception('Metodo non consentito');
}
if (!isset($_POST['id']) || !is_numeric($_POST['id'])) {
throw new Exception('ID allegato non valido');
}
$id = (int)$_POST['id'];
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare("SELECT id, file_path FROM matrice_attachments WHERE id = :id LIMIT 1");
$stmt->execute([':id' => $id]);
$attachment = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$attachment) {
throw new Exception('Allegato non trovato');
}
$filePathRelative = ltrim((string)$attachment['file_path'], '/\\');
$filePathAbsolute = __DIR__ . '/' . $filePathRelative;
$pdo->beginTransaction();
$deleteStmt = $pdo->prepare("DELETE FROM matrice_attachments WHERE id = :id");
$deleteStmt->execute([':id' => $id]);
if ($deleteStmt->rowCount() <= 0) {
throw new Exception('Impossibile eliminare il record allegato');
}
if (!empty($filePathRelative) && file_exists($filePathAbsolute) && is_file($filePathAbsolute)) {
@unlink($filePathAbsolute);
}
$pdo->commit();
$response['success'] = true;
$response['message'] = 'Allegato eliminato correttamente';
} catch (Throwable $e) {
if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) {
$pdo->rollBack();
}
$response['message'] = $e->getMessage();
}
echo json_encode($response, JSON_UNESCAPED_UNICODE);
exit;
@@ -0,0 +1,17 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json');
$id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid id']);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare("DELETE FROM mescole_supplier_lots WHERE id = ?");
$ok = $stmt->execute([$id]);
echo json_encode(['success' => (bool)$ok]);
@@ -0,0 +1,20 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json');
$id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid id']);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
try {
$stmt = $pdo->prepare("DELETE FROM packaging_stock_lots WHERE id = ?");
$stmt->execute([$id]);
echo json_encode(['success' => true]);
} catch (PDOException $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
+42
View File
@@ -0,0 +1,42 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
header('Content-Type: application/json');
include('include/headscript.php');
try {
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid parameter id.']);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Check existence
$stmt = $pdo->prepare("SELECT id FROM production_line_params WHERE id = :id");
$stmt->execute([':id' => $id]);
if (!$stmt->fetchColumn()) {
echo json_encode(['success' => false, 'message' => 'Parameter not found.']);
exit;
}
// Delete
$del = $pdo->prepare("DELETE FROM production_line_params WHERE id = :id");
$del->execute([':id' => $id]);
echo json_encode([
'success' => true,
'message' => 'Parameter deleted successfully.'
]);
} catch (Exception $e) {
echo json_encode([
'success' => false,
'message' => 'Server error: ' . $e->getMessage()
]);
}
-29
View File
@@ -1,29 +0,0 @@
<?php
header('Content-Type: application/json');
include('include/headscript.php');
$dbHandler = DBHandlerSelect::getInstance();
$pdo = $dbHandler->getConnection();
$data = json_decode(file_get_contents('php://input'), true);
$partId = $data['part_id'] ?? null;
if (!$partId) {
echo json_encode(['success' => false, 'message' => 'ID parte mancante']);
exit;
}
try {
$stmt = $pdo->prepare("DELETE FROM identification_parts WHERE id = :part_id");
$stmt->execute([':part_id' => $partId]);
$rowCount = $stmt->rowCount();
if ($rowCount > 0) {
echo json_encode(['success' => true, 'message' => 'Parte eliminata con successo']);
} else {
echo json_encode(['success' => false, 'message' => 'Nessuna parte trovata con ID ' . $partId]);
}
} catch (PDOException $e) {
echo json_encode(['success' => false, 'message' => 'Errore nell\'eliminazione: ' . $e->getMessage()]);
}
-28
View File
@@ -1,28 +0,0 @@
<?php
header('Content-Type: application/json');
include('include/headscript.php');
$dbHandler = DBHandlerSelect::getInstance();
$pdo = $dbHandler->getConnection();
$data = json_decode(file_get_contents('php://input'), true);
$partId = $data['part_id'] ?? null;
if (!$partId) {
echo json_encode(['success' => false, 'message' => 'ID parte mancante']);
exit;
}
try {
$stmt = $pdo->prepare("DELETE FROM identification_parts WHERE id = :part_id");
$stmt->execute([':part_id' => $partId]);
$rowCount = $stmt->rowCount();
if ($rowCount > 0) {
echo json_encode(['success' => true, 'message' => 'Parte eliminata con successo']);
} else {
echo json_encode(['success' => false, 'message' => 'Nessuna parte trovata con ID ' . $partId]);
}
} catch (PDOException $e) {
echo json_encode(['success' => false, 'message' => 'Errore nell\'eliminazione: ' . $e->getMessage()]);
}
+35
View File
@@ -0,0 +1,35 @@
<?php
require_once __DIR__ . '/class/db-functions.php';
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$id = (int)($_GET['id'] ?? 0);
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'ID non valido.']);
exit;
}
try {
// Verifica se è usata in production_pauses
$check = $pdo->prepare("SELECT COUNT(*) FROM production_pauses WHERE reason_id = :id");
$check->execute([':id' => $id]);
$used = $check->fetchColumn();
if ($used > 0) {
echo json_encode([
'success' => false,
'message' => 'Impossibile eliminare: la causa è utilizzata in una o più pause.'
]);
exit;
}
// Elimina
$stmt = $pdo->prepare("DELETE FROM pause_reasons WHERE id = :id");
$stmt->execute([':id' => $id]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
-37
View File
@@ -1,37 +0,0 @@
<?php
// delete_photo.php
include('include/headscript.php');
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['photo_id'])) {
echo json_encode(['success' => false, 'message' => 'Richiesta non valida']);
exit;
}
$photoId = intval($_POST['photo_id']);
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Recupera il percorso del file
$stmt = $pdo->prepare("SELECT file_path FROM datadb_photos WHERE id = ?");
$stmt->execute([$photoId]);
$photo = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$photo) {
echo json_encode(['success' => false, 'message' => 'Foto non trovata']);
exit;
}
// Elimina il file dal server
$filePath = '../photostrf/' . $photo['file_path'];
if (file_exists($filePath)) {
unlink($filePath);
}
// Elimina il record dal database
$stmt = $pdo->prepare("DELETE FROM datadb_photos WHERE id = ?");
$stmt->execute([$photoId]);
echo json_encode(['success' => true, 'message' => 'Foto eliminata con successo']);
+18
View File
@@ -0,0 +1,18 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json');
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
if (empty($_POST['id'])) {
echo json_encode(['success' => false, 'msg' => 'ID mancante']);
exit;
}
try {
$stmt = $pdo->prepare("DELETE FROM productiondata WHERE id = :id");
$stmt->execute(['id' => $_POST['id']]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'msg' => $e->getMessage()]);
}
-64
View File
@@ -1,64 +0,0 @@
<?php
// Enable errors for debugging
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/delete_record_debug.log');
// Log iniziale
error_log("Inizio cancellazione record alle " . date('Y-m-d H:i:s'));
// Includi il file di configurazione del database
include('include/headscript.php');
// Ricevi l'ID dalla richiesta POST
$input = json_decode(file_get_contents('php://input'), true);
$iddatadb = isset($input['id']) ? intval($input['id']) : 0;
if ($iddatadb <= 0) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'ID non valido']);
exit;
}
// Connessione al database
try {
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Errore di connessione al database: ' . $e->getMessage()]);
error_log("Errore di connessione al database: " . $e->getMessage());
exit;
}
// Inizia una transazione
$pdo->beginTransaction();
try {
// Elimina i dettagli associati dal tavolo import_data_details
$stmt = $pdo->prepare("DELETE FROM import_data_details WHERE id = ?");
$stmt->execute([$iddatadb]);
// Elimina il record principale dal tavolo datadb
$stmt = $pdo->prepare("DELETE FROM datadb WHERE iddatadb = ?");
$stmt->execute([$iddatadb]);
// Verifica se il record è stato eliminato
if ($stmt->rowCount() > 0) {
$pdo->commit();
echo json_encode(['success' => true, 'message' => 'Record eliminato con successo']);
error_log("Record con iddatadb=$iddatadb eliminato con successo");
} else {
$pdo->rollBack();
http_response_code(404);
echo json_encode(['success' => false, 'message' => 'Record non trovato']);
error_log("Record con iddatadb=$iddatadb non trovato");
}
} catch (Exception $e) {
$pdo->rollBack();
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Errore durante la cancellazione: ' . $e->getMessage()]);
error_log("Errore durante la cancellazione del record con iddatadb=$iddatadb: " . $e->getMessage());
}
+37
View File
@@ -0,0 +1,37 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json');
try {
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$id = intval($_GET['id'] ?? 0);
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'ID non valido']);
exit;
}
// Verifica se status è usato in produzione
$check = $pdo->prepare("SELECT COUNT(*) FROM productiondata WHERE id_status = :id");
$check->execute([':id' => $id]);
$count = $check->fetchColumn();
if ($count > 0) {
echo json_encode([
'success' => false,
'message' => "Impossibile eliminare: lo status è utilizzato in $count record di produzione."
]);
exit;
}
// Eliminazione
$stmt = $pdo->prepare("DELETE FROM production_status WHERE id = :id");
$stmt->execute([':id' => $id]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
-49
View File
@@ -1,49 +0,0 @@
<?php
// Abilita la gestione degli errori
ini_set('display_errors', 1);
error_reporting(E_ALL);
// Includi la connessione al database
require_once 'class/db-functions.php';
try {
// Controlla se è stato passato un ID valido
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
throw new Exception('Invalid ID');
}
$id = intval($_GET['id']); // Sanifica l'ID
// Connessione al database
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
if (!$pdo) {
throw new Exception('Database connection failed');
}
// Verifica se l'ID esiste
$stmtCheck = $pdo->prepare("SELECT id FROM excel_templates WHERE id = ?");
$stmtCheck->execute([$id]);
if ($stmtCheck->rowCount() === 0) {
throw new Exception('Template not found');
}
// Esegui l'eliminazione
$stmt = $pdo->prepare("DELETE FROM excel_templates WHERE id = ?");
$stmt->execute([$id]);
if ($stmt->rowCount() > 0) {
$message = "Template deleted successfully!";
$status = "success";
} else {
throw new Exception('Failed to delete template');
}
} catch (Exception $e) {
$message = $e->getMessage();
$status = "error";
}
// Reindirizza con un messaggio
header("Location: templates_dashboard.php?status=$status&message=" . urlencode($message));
exit;
+47
View File
@@ -0,0 +1,47 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
header('Content-Type: application/json');
require_once 'include/headscript.php';
try {
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$id = (int)($_POST['id'] ?? 0);
$name = trim($_POST['name'] ?? '');
$tool_type = trim($_POST['tool_type'] ?? '');
$description = trim($_POST['description'] ?? '');
$is_active = isset($_POST['is_active']) ? (int)$_POST['is_active'] : 1;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid ID.']);
exit;
}
if ($name === '') {
echo json_encode(['success' => false, 'message' => 'Name is required.']);
exit;
}
$sql = "UPDATE production_tools
SET name = :name,
tool_type = :tool_type,
description = :description,
is_active = :is_active
WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([
'name' => $name,
'tool_type' => $tool_type ?: null,
'description' => $description ?: null,
'is_active' => $is_active,
'id' => $id
]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
+799
View File
@@ -0,0 +1,799 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
include('include/headscript.php');
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
/* ==========================================
AJAX HANDLERS
========================================== */
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax']) && $_POST['ajax'] == '1') {
header('Content-Type: application/json');
$action = $_POST['action'] ?? '';
try {
if ($action === 'add') {
$name = trim($_POST['name'] ?? '');
$code = trim($_POST['code'] ?? '');
$description = trim($_POST['description'] ?? '');
$color = trim($_POST['color'] ?? '#6c757d');
$sort_order = isset($_POST['sort_order']) && $_POST['sort_order'] !== '' ? (int)$_POST['sort_order'] : 999;
$is_active = isset($_POST['is_active']) ? (int)$_POST['is_active'] : 1;
if ($name === '') {
echo json_encode([
'success' => false,
'message' => 'Department name is required.'
]);
exit;
}
if ($code === '') {
$code = strtoupper(str_replace(' ', '_', $name));
$code = preg_replace('/[^A-Z0-9_]/', '', $code);
} else {
$code = strtoupper($code);
$code = preg_replace('/[^A-Z0-9_]/', '', $code);
}
if (!preg_match('/^#[0-9A-Fa-f]{6}$/', $color)) {
$color = '#6c757d';
}
$is_active = $is_active === 1 ? 1 : 0;
$check = $pdo->prepare("
SELECT COUNT(*)
FROM departments
WHERE name = :name OR code = :code
");
$check->execute([
'name' => $name,
'code' => $code
]);
if ((int)$check->fetchColumn() > 0) {
echo json_encode([
'success' => false,
'message' => 'A department with the same name or code already exists.'
]);
exit;
}
$sql = "INSERT INTO departments
(name, code, description, color, sort_order, is_active, created_at, updated_at)
VALUES
(:name, :code, :description, :color, :sort_order, :is_active, NOW(), NOW())";
$stmt = $pdo->prepare($sql);
$stmt->execute([
'name' => $name,
'code' => $code !== '' ? $code : null,
'description' => $description !== '' ? $description : null,
'color' => $color,
'sort_order' => $sort_order,
'is_active' => $is_active
]);
echo json_encode(['success' => true]);
exit;
}
if ($action === 'edit') {
$id = (int)($_POST['id'] ?? 0);
$name = trim($_POST['name'] ?? '');
$code = trim($_POST['code'] ?? '');
$description = trim($_POST['description'] ?? '');
$color = trim($_POST['color'] ?? '#6c757d');
$sort_order = isset($_POST['sort_order']) && $_POST['sort_order'] !== '' ? (int)$_POST['sort_order'] : 999;
$is_active = isset($_POST['is_active']) ? (int)$_POST['is_active'] : 1;
if ($id <= 0) {
echo json_encode([
'success' => false,
'message' => 'Invalid department ID.'
]);
exit;
}
if ($name === '') {
echo json_encode([
'success' => false,
'message' => 'Department name is required.'
]);
exit;
}
if ($code === '') {
$code = strtoupper(str_replace(' ', '_', $name));
$code = preg_replace('/[^A-Z0-9_]/', '', $code);
} else {
$code = strtoupper($code);
$code = preg_replace('/[^A-Z0-9_]/', '', $code);
}
if (!preg_match('/^#[0-9A-Fa-f]{6}$/', $color)) {
$color = '#6c757d';
}
$is_active = $is_active === 1 ? 1 : 0;
$check = $pdo->prepare("
SELECT COUNT(*)
FROM departments
WHERE (name = :name OR code = :code)
AND id <> :id
");
$check->execute([
'name' => $name,
'code' => $code,
'id' => $id
]);
if ((int)$check->fetchColumn() > 0) {
echo json_encode([
'success' => false,
'message' => 'Another department with the same name or code already exists.'
]);
exit;
}
$sql = "UPDATE departments
SET name = :name,
code = :code,
description = :description,
color = :color,
sort_order = :sort_order,
is_active = :is_active,
updated_at = NOW()
WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([
'name' => $name,
'code' => $code !== '' ? $code : null,
'description' => $description !== '' ? $description : null,
'color' => $color,
'sort_order' => $sort_order,
'is_active' => $is_active,
'id' => $id
]);
echo json_encode(['success' => true]);
exit;
}
if ($action === 'delete') {
$id = (int)($_POST['id'] ?? 0);
if ($id <= 0) {
echo json_encode([
'success' => false,
'message' => 'Invalid department ID.'
]);
exit;
}
/*
* Future-proof check:
* If later you add employees.department_id, this prevents deleting
* a department already used by employees.
*/
$columnCheck = $pdo->prepare("
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'employees'
AND COLUMN_NAME = 'department_id'
");
$columnCheck->execute();
$hasDepartmentId = (int)$columnCheck->fetchColumn() > 0;
if ($hasDepartmentId) {
$usageCheck = $pdo->prepare("
SELECT COUNT(*)
FROM employees
WHERE department_id = :id
");
$usageCheck->execute(['id' => $id]);
if ((int)$usageCheck->fetchColumn() > 0) {
echo json_encode([
'success' => false,
'message' => 'This department is linked to one or more employees and cannot be deleted.'
]);
exit;
}
}
$stmt = $pdo->prepare("DELETE FROM departments WHERE id = :id");
$stmt->execute(['id' => $id]);
echo json_encode(['success' => true]);
exit;
}
echo json_encode([
'success' => false,
'message' => 'Unknown action.'
]);
exit;
} catch (Exception $e) {
echo json_encode([
'success' => false,
'message' => $e->getMessage()
]);
exit;
}
}
/* ==========================================
PAGE DATA
========================================== */
$sql = "
SELECT *
FROM departments
ORDER BY sort_order ASC, name ASC
";
$stmtDepartments = $pdo->query($sql);
$departments = $stmtDepartments->fetchAll(PDO::FETCH_ASSOC);
?>
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
<?php include('cssinclude.php'); ?>
<title>Gestione Departments - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
<!-- jQuery and Bootstrap -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- DataTables -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css">
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
<style>
body {
font-size: 1.05rem;
background: #f8fafc;
}
.card {
border-radius: 16px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.back-dashboard {
background-color: #cfe3ff !important;
color: #1f2d3d !important;
border: 1px solid #bcd4f4 !important;
border-radius: 10px;
font-weight: 600;
font-size: 1rem;
padding: 10px 18px;
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease-in-out;
}
.back-dashboard:hover {
background-color: #b9d3ff !important;
transform: translateY(-2px);
}
.btn-add {
background-color: #0d6efd;
color: #fff;
border-radius: 8px;
padding: 10px 20px;
font-weight: 500;
transition: all 0.2s ease-in-out;
}
.btn-add:hover {
background-color: #0b5ed7;
transform: scale(1.02);
}
.table thead {
background-color: #cfe3ff;
color: #1f2d3d;
}
.modal-content {
border-radius: 16px;
}
#tabellaDepartments thead th {
text-align: center;
vertical-align: middle;
}
.badge-status {
padding: 0.25rem 0.6rem;
border-radius: 999px;
font-size: 0.8rem;
font-weight: 600;
}
.badge-status.active {
background-color: #d1fae5;
color: #065f46;
}
.badge-status.inactive {
background-color: #e5e7eb;
color: #374151;
}
.department-color-dot {
display: inline-block;
width: 18px;
height: 18px;
border-radius: 50%;
border: 1px solid rgba(0, 0, 0, 0.2);
vertical-align: middle;
margin-right: 6px;
}
.department-code {
font-family: Consolas, Monaco, monospace;
font-size: 0.9rem;
background: #f1f5f9;
padding: 4px 8px;
border-radius: 8px;
color: #334155;
}
.description-cell {
max-width: 320px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: left;
}
</style>
</head>
<body>
<div class="wrapper toggled">
<?php include('include/navbar.php'); ?>
<?php include('include/topbar.php'); ?>
<div class="page-wrapper">
<div class="page-content">
<div class="card p-3">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Gestione Departments</h5>
<button type="button" class="btn back-dashboard" onclick="location.href='production_dashboard.php'">
↩️ Torna alla Dashboard
</button>
</div>
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="fw-semibold mb-0">Elenco Reparti / Departments</h6>
<button class="btn btn-add" data-bs-toggle="modal" data-bs-target="#addDepartmentModal">
Aggiungi Department
</button>
</div>
<div class="table-responsive">
<table id="tabellaDepartments" class="table table-striped align-middle text-center" style="width:100%;">
<thead>
<tr>
<th>ID</th>
<th>Color</th>
<th>Name</th>
<th>Code</th>
<th>Description</th>
<th>Order</th>
<th>Status</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (!empty($departments)): ?>
<?php foreach ($departments as $row): ?>
<?php
$id = (int)$row['id'];
$name = $row['name'] ?? '';
$code = $row['code'] ?? '';
$description = $row['description'] ?? '';
$color = $row['color'] ?? '#6c757d';
$sortOrder = (int)($row['sort_order'] ?? 999);
$isActive = (int)($row['is_active'] ?? 1);
$statusClass = $isActive === 1 ? 'active' : 'inactive';
$statusLabel = $isActive === 1 ? 'Active' : 'Inactive';
$createdAt = !empty($row['created_at'])
? date('d/m/Y H:i', strtotime($row['created_at']))
: '-';
?>
<tr>
<td><?= $id ?></td>
<td>
<span class="department-color-dot" style="background-color: <?= htmlspecialchars($color, ENT_QUOTES) ?>;"></span>
<?= htmlspecialchars($color) ?>
</td>
<td class="fw-semibold">
<?= htmlspecialchars($name) ?>
</td>
<td>
<?php if ($code !== ''): ?>
<span class="department-code"><?= htmlspecialchars($code) ?></span>
<?php else: ?>
-
<?php endif; ?>
</td>
<td class="description-cell" title="<?= htmlspecialchars($description, ENT_QUOTES) ?>">
<?= $description !== '' ? htmlspecialchars($description) : '-' ?>
</td>
<td><?= $sortOrder ?></td>
<td>
<span class="badge-status <?= $statusClass ?>">
<?= htmlspecialchars($statusLabel) ?>
</span>
</td>
<td><?= $createdAt ?></td>
<td>
<button
class="btn btn-sm btn-outline-secondary edit-department"
data-id="<?= $id ?>"
data-name="<?= htmlspecialchars($name, ENT_QUOTES) ?>"
data-code="<?= htmlspecialchars($code, ENT_QUOTES) ?>"
data-description="<?= htmlspecialchars($description, ENT_QUOTES) ?>"
data-color="<?= htmlspecialchars($color, ENT_QUOTES) ?>"
data-sort_order="<?= $sortOrder ?>"
data-is_active="<?= $isActive ?>">
✏️ Modifica
</button>
<button
class="btn btn-sm btn-outline-danger delete-department"
data-id="<?= $id ?>"
data-name="<?= htmlspecialchars($name, ENT_QUOTES) ?>">
🗑️ Cancella
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<?php include('include/footer.php'); ?>
</div>
<!-- ADD DEPARTMENT MODAL -->
<div class="modal fade" id="addDepartmentModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header" style="background-color:#cfe3ff;">
<h5 class="modal-title">Aggiungi Department</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="addDepartmentForm">
<div class="mb-3">
<label class="form-label fw-semibold">Name</label>
<input type="text" class="form-control" id="addName" name="name" placeholder="e.g. Produzione" required>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Code</label>
<input type="text" class="form-control" id="addCode" name="code" placeholder="Optional, e.g. PRODUZIONE">
<small class="text-muted">If empty, it will be generated automatically from the name.</small>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Description</label>
<textarea class="form-control" id="addDescription" name="description" rows="3" placeholder="Optional notes"></textarea>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label fw-semibold">Color</label>
<input type="color" class="form-control form-control-color" id="addColor" name="color" value="#6c757d">
</div>
<div class="col-md-6 mb-3">
<label class="form-label fw-semibold">Sort Order</label>
<input type="number" class="form-control" id="addSortOrder" name="sort_order" value="999" min="0">
</div>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Status</label>
<select class="form-select" id="addIsActive" name="is_active">
<option value="1" selected>Active</option>
<option value="0">Inactive</option>
</select>
</div>
<div class="text-center">
<button type="submit" class="btn btn-add">💾 Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- EDIT DEPARTMENT MODAL -->
<div class="modal fade" id="editDepartmentModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header" style="background-color:#cfe3ff;">
<h5 class="modal-title">Modifica Department</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="editDepartmentForm">
<input type="hidden" id="editDepartmentId">
<div class="mb-3">
<label class="form-label fw-semibold">Name</label>
<input type="text" class="form-control" id="editName" name="name" required>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Code</label>
<input type="text" class="form-control" id="editCode" name="code">
<small class="text-muted">If empty, it will be generated automatically from the name.</small>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Description</label>
<textarea class="form-control" id="editDescription" name="description" rows="3"></textarea>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label fw-semibold">Color</label>
<input type="color" class="form-control form-control-color" id="editColor" name="color" value="#6c757d">
</div>
<div class="col-md-6 mb-3">
<label class="form-label fw-semibold">Sort Order</label>
<input type="number" class="form-control" id="editSortOrder" name="sort_order" value="999" min="0">
</div>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Status</label>
<select class="form-select" id="editIsActive" name="is_active">
<option value="1">Active</option>
<option value="0">Inactive</option>
</select>
</div>
<div class="text-center">
<button type="submit" class="btn btn-add">💾 Save Changes</button>
</div>
</form>
</div>
</div>
</div>
</div>
<?php include('jsinclude.php'); ?>
<script>
$(document).ready(function() {
$('#tabellaDepartments').DataTable({
order: [
[5, 'asc'],
[2, 'asc']
],
pageLength: 25,
language: {
url: 'https://cdn.datatables.net/plug-ins/1.13.6/i18n/it-IT.json',
emptyTable: 'Nessun department presente'
}
});
/* -------- ADD DEPARTMENT -------- */
$("#addDepartmentForm").on("submit", function(e) {
e.preventDefault();
const payload = new URLSearchParams();
payload.append('ajax', '1');
payload.append('action', 'add');
payload.append('name', $("#addName").val().trim());
payload.append('code', $("#addCode").val().trim());
payload.append('description', $("#addDescription").val().trim());
payload.append('color', $("#addColor").val());
payload.append('sort_order', $("#addSortOrder").val());
payload.append('is_active', $("#addIsActive").val());
fetch("", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: payload.toString()
})
.then(r => r.json())
.then(data => {
if (data.success) {
Swal.fire({
icon: "success",
title: "Saved!",
confirmButtonColor: "#3085d6"
}).then(() => location.reload());
} else {
Swal.fire({
icon: "error",
title: "Error",
text: data.message || "Unable to save department."
});
}
})
.catch(err => {
Swal.fire({
icon: "error",
title: "Error",
text: "Communication error."
});
console.error(err);
});
});
/* -------- OPEN EDIT MODAL -------- */
$(document).on("click", ".edit-department", function() {
const btn = $(this);
$("#editDepartmentId").val(btn.data("id"));
$("#editName").val(btn.data("name"));
$("#editCode").val(btn.data("code"));
$("#editDescription").val(btn.data("description"));
$("#editColor").val(btn.data("color") || '#6c757d');
$("#editSortOrder").val(btn.data("sort_order"));
$("#editIsActive").val(String(btn.data("is_active")));
$("#editDepartmentModal").modal("show");
});
/* -------- SAVE EDIT -------- */
$("#editDepartmentForm").on("submit", function(e) {
e.preventDefault();
const payload = new URLSearchParams();
payload.append('ajax', '1');
payload.append('action', 'edit');
payload.append('id', $("#editDepartmentId").val());
payload.append('name', $("#editName").val().trim());
payload.append('code', $("#editCode").val().trim());
payload.append('description', $("#editDescription").val().trim());
payload.append('color', $("#editColor").val());
payload.append('sort_order', $("#editSortOrder").val());
payload.append('is_active', $("#editIsActive").val());
fetch("", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: payload.toString()
})
.then(r => r.json())
.then(data => {
if (data.success) {
Swal.fire({
icon: "success",
title: "Updated!",
confirmButtonColor: "#3085d6"
}).then(() => location.reload());
} else {
Swal.fire({
icon: "error",
title: "Error",
text: data.message || "Unable to update department."
});
}
})
.catch(err => {
Swal.fire({
icon: "error",
title: "Error",
text: "Communication error."
});
console.error(err);
});
});
/* -------- DELETE DEPARTMENT -------- */
$(document).on("click", ".delete-department", function() {
const id = $(this).data("id");
const name = $(this).data("name");
Swal.fire({
title: "Confermi la cancellazione?",
text: name ? ("Department: " + name) : "This department will be deleted.",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#d33",
cancelButtonColor: "#6c757d",
confirmButtonText: "Sì, cancella",
cancelButtonText: "Annulla"
}).then((result) => {
if (!result.isConfirmed) return;
const payload = new URLSearchParams();
payload.append('ajax', '1');
payload.append('action', 'delete');
payload.append('id', id);
fetch("", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: payload.toString()
})
.then(r => r.json())
.then(data => {
if (data.success) {
Swal.fire({
icon: "success",
title: "Deleted!",
confirmButtonColor: "#3085d6"
}).then(() => location.reload());
} else {
Swal.fire({
icon: "error",
title: "Error",
text: data.message || "Unable to delete department."
});
}
})
.catch(err => {
Swal.fire({
icon: "error",
title: "Error",
text: "Communication error."
});
console.error(err);
});
});
});
});
</script>
</body>
</html>
+171
View File
@@ -0,0 +1,171 @@
<?php include('include/headscript.php'); ?>
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
<?php include('cssinclude.php'); ?>
<title>Modifica Linea di Produzione</title>
<!-- jQuery + Bootstrap -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
body {
background: #f8fafc;
font-size: 1.05rem;
}
.card {
border-radius: 16px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.btn-save {
background-color: #0d6efd;
color: #fff;
border-radius: 8px;
padding: 10px 20px;
font-weight: 500;
}
.btn-save:hover {
background-color: #0b5ed7;
transform: scale(1.02);
}
.back-dashboard {
background-color: #cfe3ff;
color: #1f2d3d;
border: 1px solid #bcd4f4;
border-radius: 10px;
font-weight: 600;
font-size: 1rem;
padding: 10px 18px;
transition: all 0.2s ease-in-out;
}
.back-dashboard:hover {
background-color: #b9d3ff;
transform: translateY(-2px);
}
</style>
</head>
<body>
<div class="wrapper">
<?php include('include/navbar.php'); ?>
<?php include('include/topbar.php'); ?>
<div class="page-wrapper">
<div class="page-content">
<div class="card p-4 mx-auto" style="max-width: 600px;">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0 text-center w-100">Modifica Linea</h5>
<button type="button" class="btn back-dashboard position-absolute end-0 me-3" onclick="location.href='linee.php'">
↩️ Torna all'elenco
</button>
</div>
<div class="card-body">
<?php
require_once(__DIR__ . '/class/db-functions.php');
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
echo "<div class='alert alert-danger'>ID non valido.</div>";
exit;
}
$id = (int)$_GET['id'];
$stmt = $pdo->prepare("SELECT * FROM production_lines WHERE id = ?");
$stmt->execute([$id]);
$line = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$line) {
echo "<div class='alert alert-warning'>Linea non trovata.</div>";
exit;
}
?>
<form id="editLineaForm">
<input type="hidden" name="id" value="<?= htmlspecialchars($line['id']) ?>">
<div class="mb-3">
<label for="lineNumber" class="form-label fw-semibold">Numero Linea</label>
<input type="number" id="lineNumber" name="lineNumber" class="form-control" value="<?= htmlspecialchars($line['line_number']) ?>" required>
</div>
<div class="mb-3">
<label for="lineName" class="form-label fw-semibold">Nome Linea</label>
<input type="text" id="lineName" name="lineName" class="form-control" value="<?= htmlspecialchars($line['name']) ?>" required>
</div>
<div class="mb-3">
<label for="model" class="form-label fw-semibold">Modello</label>
<input type="text" id="model" name="model" class="form-control" value="<?= htmlspecialchars($line['model']) ?>">
</div>
<div class="mb-3">
<label for="brand" class="form-label fw-semibold">Marca</label>
<input type="text" id="brand" name="brand" class="form-control" value="<?= htmlspecialchars($line['brand']) ?>">
</div>
<div class="mb-3">
<label for="color" class="form-label fw-semibold">Colore Linea</label>
<input type="color" id="color" name="color" class="form-control form-control-color"
value="<?= htmlspecialchars($line['color'] ?? '#dc2626') ?>">
</div>
<div class="mb-3">
<label for="status" class="form-label fw-semibold">Stato</label>
<select id="status" name="status" class="form-select">
<option value="active" <?= $line['status'] === 'active' ? 'selected' : '' ?>>Attiva</option>
<option value="inactive" <?= $line['status'] === 'inactive' ? 'selected' : '' ?>>Inattiva</option>
</select>
</div>
<div class="text-center mt-4">
<button type="submit" class="btn btn-save">💾 Salva Modifiche</button>
</div>
</form>
</div>
</div>
</div>
</div>
<?php include('include/footer.php'); ?>
</div>
<script>
document.getElementById("editLineaForm").addEventListener("submit", e => {
e.preventDefault();
const formData = new FormData(e.target);
fetch("update_linea.php", {
method: "POST",
body: formData
})
.then(r => r.json())
.then(data => {
if (data.success) {
Swal.fire({
icon: "success",
title: "Aggiornata!",
text: "La linea è stata modificata correttamente.",
confirmButtonColor: "#3085d6"
}).then(() => location.href = "linee.php");
} else {
Swal.fire("Errore", data.message || "Errore durante l'aggiornamento.", "error");
}
})
.catch(() => Swal.fire("Errore", "Impossibile contattare il server.", "error"));
});
</script>
</body>
</html>
+40
View File
@@ -0,0 +1,40 @@
<?php
require_once __DIR__ . '/class/db-functions.php';
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$id = (int)($_POST['id'] ?? 0);
$name = trim($_POST['name'] ?? '');
$description = trim($_POST['description'] ?? '');
$is_problem = isset($_POST['is_problem']) ? (int)$_POST['is_problem'] : 0;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'ID non valido.']);
exit;
}
if ($name === '') {
echo json_encode(['success' => false, 'message' => 'Il nome è obbligatorio.']);
exit;
}
try {
$stmt = $pdo->prepare("
UPDATE pause_reasons
SET name = :name,
description = :description,
is_problem = :is_problem
WHERE id = :id
");
$stmt->execute([
':name' => $name,
':description' => $description !== '' ? $description : null,
':is_problem' => $is_problem,
':id' => $id
]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
+48
View File
@@ -0,0 +1,48 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json');
try {
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Validazione
$id = intval($_POST['id'] ?? 0);
$nome = trim($_POST['nome'] ?? '');
$ordinamento = intval($_POST['ordinamento'] ?? 0);
$badge = $_POST['badge_color'] ?? '#6c757d';
$line = $_POST['line_color'] ?? '#e9ecef';
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'ID non valido']);
exit;
}
if ($nome === '') {
echo json_encode(['success' => false, 'message' => 'Il nome è obbligatorio']);
exit;
}
// Update
$stmt = $pdo->prepare("
UPDATE production_status
SET nome = :nome,
ordinamento = :ordinamento,
badge_color = :badge,
line_color = :line
WHERE id = :id
");
$stmt->execute([
':nome' => $nome,
':ordinamento' => $ordinamento,
':badge' => $badge,
':line' => $line,
':id' => $id
]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
-434
View File
@@ -1,434 +0,0 @@
<?php include('include/headscript.php');
// Controlla se è stato passato un ID valido
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
header("Location: xlstemplates_grid.php?status=error&message=" . urlencode("Invalid ID"));
exit;
}
$id = intval($_GET['id']); // Sanifica l'ID
// Recupera il template dal database
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare("SELECT * FROM excel_templates WHERE id = ?");
$stmt->execute([$id]);
$template = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$template) {
header("Location: template_dashboard.php?status=error&message=" . urlencode("Template not found"));
exit;
}
// Recupera tutte le routine dal database
$stmt = $pdo->prepare("SELECT * FROM routine");
$stmt->execute();
$routines = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<?php include('cssinclude.php'); ?>
<!-- Include jQuery prima di Select2 -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<title>Edit Template <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
</head>
<body>
<div class="wrapper">
<?php include('include/navbar.php'); ?>
<?php include('include/topbar.php'); ?>
<div class="page-wrapper">
<div class="page-content">
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">Update XLS Template</h5>
</div>
<div class="card-body">
<p class="mb-2">Edit the following form in order to update the selected import XLS template</p>
<p class="mb-2">Mandatory Fields</p>
<ul class="mb-0">
<li>Template Name</li>
<li>Row Header and Column Header: where the title of the excel starts</li>
<li>Schema</li>
</ul>
</div>
</div>
<div class="card radius-10">
<div class="card-header">
<div class="d-flex align-items-center">
<div>
<h6 class="mb-0">Edit Template: <?php echo htmlspecialchars($template['name']); ?></h6>
</div>
</div>
</div>
<div class="card-body">
<div class="col-12">
<form id="editTemplateForm" method="POST">
<input type="hidden" name="id" value="<?php echo $template['id']; ?>">
<div class="mb-3">
<label class="form-label"><?= htmlspecialchars($templatename, ENT_QUOTES, 'UTF-8'); ?> *</label>
<input type="text" name="name" class="form-control" value="<?php echo htmlspecialchars($template['name']); ?>" required>
</div>
<div class="mb-3">
<label class="form-label"><?= htmlspecialchars($rowheader, ENT_QUOTES, 'UTF-8'); ?> *</label>
<input type="number" name="header_row" class="form-control" value="<?php echo $template['header_row']; ?>" required>
</div>
<div class="mb-3">
<label class="form-label"><?= htmlspecialchars($columnheader, ENT_QUOTES, 'UTF-8'); ?>*</label>
<input type="text" name="start_column" class="form-control" value="<?php echo htmlspecialchars($template['start_column']); ?>" required>
</div>
<div class="mb-3">
<label class="form-label"><?= htmlspecialchars($desctemplate, ENT_QUOTES, 'UTF-8'); ?></label>
<textarea name="description" class="form-control"><?php echo htmlspecialchars($template['description']); ?></textarea>
</div>
<div class="mb-3">
<label class="form-label"><?= htmlspecialchars($desttable, ENT_QUOTES, 'UTF-8'); ?>*</label>
<input type="text" name="target_table" class="form-control" value="<?php echo htmlspecialchars($template['target_table']); ?>" readonly required>
</div>
<div class="mb-3">
<label class="form-label">Button Size</label>
<select name="button_size" class="form-control">
<option value="small" <?php echo ($template['button_size'] ?? 'medium') === 'small' ? 'selected' : ''; ?>>Small</option>
<option value="medium" <?php echo ($template['button_size'] ?? 'medium') === 'medium' ? 'selected' : ''; ?>>Medium</option>
<option value="large" <?php echo ($template['button_size'] ?? 'medium') === 'large' ? 'selected' : ''; ?>>Large</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Button Background Color</label>
<input type="color" name="button_bg_color" class="form-control" value="<?php echo htmlspecialchars($template['button_bg_color'] ?? '#007bff'); ?>">
</div>
<div class="mb-3">
<label class="form-label">Button Text Color</label>
<input type="color" name="button_text_color" class="form-control" value="<?php echo htmlspecialchars($template['button_text_color'] ?? '#ffffff'); ?>">
</div>
<div class="mb-3">
<label class="form-label">Button Label</label>
<input type="text" name="button_label" class="form-control" value="<?php echo htmlspecialchars($template['button_label'] ?? 'Click Me'); ?>">
</div>
<div class="mb-3">
<label class="form-label">Select Client *</label>
<select name="client_id" id="clientSelect" class="form-control" required>
<option value="">Select a client...</option>
</select>
<span id="clientLoadingStatus" class="text-muted" style="margin-left: 10px; display: none;">Recupero clienti in corso...</span>
</div>
<div class="mb-3">
<label class="form-label">Select Schema *</label>
<select name="schema_id" id="schemaSelect" class="form-control" required>
<option value="">Select a schema...</option>
</select>
<span id="schemaLoadingStatus" class="text-muted" style="margin-left: 10px; display: none;">Caricamento schemi in corso...</span>
</div>
<div class="mb-3">
<label class="form-label">Select Routine</label>
<select name="idroutine" id="routineSelect" class="form-control">
<option value="">Select a routine...</option>
<?php foreach ($routines as $routine): ?>
<option value="<?php echo $routine['idroutine']; ?>" <?php echo ($template['idroutine'] ?? '') == $routine['idroutine'] ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($routine['name']); ?>
</option>
<?php endforeach; ?>
</select>
<div id="routineDetails" class="mt-2" style="display: none;">
<h6>Routine Details</h6>
<p><strong>Name:</strong> <span id="routineName"></span></p>
<p><strong>Description:</strong> <span id="routineDescription"></span></p>
<p><strong>Action 1:</strong> <span id="routineAction1"></span></p>
<p><strong>Action 2:</strong> <span id="routineAction2"></span></p>
<p><strong>Action 3:</strong> <span id="routineAction3"></span></p>
</div>
</div>
<br>
<button type="submit" class="btn btn-primary"><?= htmlspecialchars($savechanges, ENT_QUOTES, 'UTF-8'); ?></button>
<a href="templates_dashboard.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="overlay toggle-icon"></div>
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
<?php include('include/footer.php'); ?>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
// Verifica che jQuery sia caricato
if (typeof jQuery === 'undefined') {
alert("Errore: jQuery non è caricato. Contatta l'amministratore.");
return;
}
const form = document.getElementById("editTemplateForm");
const clientLoadingStatus = document.getElementById("clientLoadingStatus");
const schemaLoadingStatus = document.getElementById("schemaLoadingStatus");
const routineSelect = document.getElementById("routineSelect");
const routineDetails = document.getElementById("routineDetails");
const routineName = document.getElementById("routineName");
const routineDescription = document.getElementById("routineDescription");
const routineAction1 = document.getElementById("routineAction1");
const routineAction2 = document.getElementById("routineAction2");
const routineAction3 = document.getElementById("routineAction3");
if (!form || !clientLoadingStatus || !schemaLoadingStatus || !routineSelect || !routineDetails) {
alert("Errore: Uno o più elementi della pagina non sono stati trovati. Contatta l'amministratore.");
return;
}
// Inizializza Select2
$('#clientSelect').select2({
placeholder: "Search for a client...",
allowClear: true
});
$('#schemaSelect').select2({
placeholder: "Search for a schema...",
allowClear: true
});
$('#routineSelect').select2({
placeholder: "Select a routine...",
allowClear: true
});
// Carica i clienti
async function loadClients() {
try {
clientLoadingStatus.style.display = 'inline';
clientLoadingStatus.textContent = 'Recupero clienti in corso...';
const response = await fetch("get_clienti.php", {
method: "GET",
headers: {
"Content-Type": "application/json"
}
});
const data = await response.json();
if (!response.ok) throw new Error(data.error || `Errore HTTP: ${response.status}`);
const select = document.getElementById("clientSelect");
select.innerHTML = '<option value="">Select a client...</option>';
data.value.forEach(client => {
const nome = client.Nominativo || "Nome non disponibile";
const id = client.IdCliente || "ID non disponibile";
const option = new Option(`${nome.trim()} (ID: ${id})`, id);
if (parseInt(id) === parseInt(<?php echo json_encode($template['idclient'] ?? 0); ?>)) {
option.selected = true;
}
select.add(option);
});
$(select).trigger('change');
clientLoadingStatus.textContent = "Clienti caricati.";
} catch (error) {
clientLoadingStatus.textContent = "Errore nel caricamento.";
Swal.fire({
title: "Errore!",
text: "Impossibile caricare i clienti: " + error.message,
icon: "error",
confirmButtonText: "OK"
});
} finally {
setTimeout(() => clientLoadingStatus.style.display = 'none', 2000);
}
}
// Carica gli schemi
async function loadSchemas() {
try {
schemaLoadingStatus.style.display = 'inline';
schemaLoadingStatus.textContent = 'Caricamento schemi in corso...';
const response = await fetch("get_schemi.php", {
method: "GET",
headers: {
"Content-Type": "application/json"
}
});
const data = await response.json();
if (!response.ok) throw new Error(data.error || `Errore HTTP: ${response.status}`);
const select = document.getElementById("schemaSelect");
select.innerHTML = '<option value="">Select a schema...</option>';
data.value.forEach(schema => {
const nome = schema.Nome || "Nome non disponibile";
const id = schema.IdSchemaCustomFields || "ID non disponibile";
const option = new Option(`${nome.trim()} (ID: ${id})`, id);
if (parseInt(id) === parseInt(<?php echo json_encode($template['idschema'] ?? 0); ?>)) {
option.selected = true;
}
select.add(option);
});
$(select).trigger('change');
schemaLoadingStatus.textContent = "Schemi caricati.";
} catch (error) {
schemaLoadingStatus.textContent = "Errore nel caricamento.";
Swal.fire({
title: "Errore!",
text: "Impossibile caricare gli schemi: " + error.message,
icon: "error",
confirmButtonText: "OK"
});
} finally {
setTimeout(() => schemaLoadingStatus.style.display = 'none', 2000);
}
}
// Carica i dati
async function loadData() {
try {
await loadClients();
await loadSchemas();
} catch (error) {
Swal.fire({
title: "Errore!",
text: "Errore nel caricamento dei dati: " + error.message,
icon: "error",
confirmButtonText: "OK"
});
}
}
loadData();
// Routine dettagli
const routines = <?php echo json_encode($routines); ?>;
function updateRoutineDetails() {
const selectedId = routineSelect.value;
routineDetails.style.display = selectedId ? 'block' : 'none';
if (selectedId) {
const routine = routines.find(r => r.idroutine == selectedId);
if (routine) {
routineName.textContent = routine.name || 'N/A';
routineDescription.textContent = routine.description || 'N/A';
routineAction1.textContent = routine.action1 || 'N/A';
routineAction2.textContent = routine.action2 || 'N/A';
routineAction3.textContent = routine.action3 || 'N/A';
} else {
routineName.textContent = 'N/A';
routineDescription.textContent = 'N/A';
routineAction1.textContent = 'N/A';
routineAction2.textContent = 'N/A';
routineAction3.textContent = 'N/A';
}
} else {
routineName.textContent = '';
routineDescription.textContent = '';
routineAction1.textContent = '';
routineAction2.textContent = '';
routineAction3.textContent = '';
}
}
routineSelect.addEventListener('change', updateRoutineDetails);
updateRoutineDetails(); // Inizializza dettagli se una routine è preselezionata
// Submit del form
form.addEventListener("submit", function(e) {
e.preventDefault();
let formData = new FormData(this);
const clientSelect = document.getElementById("clientSelect");
const clientId = clientSelect.value;
const selectedClientOption = clientSelect.options[clientSelect.selectedIndex];
if (!clientId) {
Swal.fire({
title: "Errore!",
text: "Per favore seleziona un cliente.",
icon: "error",
confirmButtonText: "OK"
});
return;
}
let clientName = "";
if (selectedClientOption) {
const optionText = selectedClientOption.text.trim();
const nameMatch = optionText.match(/^(.+?)(?:\s*\(ID:\s*\d+\))?$/);
clientName = nameMatch ? nameMatch[1].trim() : optionText;
}
formData.append("client_name", clientName);
const schemaSelect = document.getElementById("schemaSelect");
const schemaId = schemaSelect.value;
const selectedSchemaOption = schemaSelect.options[schemaSelect.selectedIndex];
if (!schemaId) {
Swal.fire({
title: "Errore!",
text: "Per favore seleziona uno schema.",
icon: "error",
confirmButtonText: "OK"
});
return;
}
let schemaName = "";
if (selectedSchemaOption) {
const optionText = selectedSchemaOption.text.trim();
const nameMatch = optionText.match(/^(.+?)(?:\s*\(ID:\s*\d+\))?$/);
schemaName = nameMatch ? nameMatch[1].trim() : optionText;
}
formData.append("idschema", schemaId);
formData.append("schemaname", schemaName);
// Aggiungi idroutine
const routineId = routineSelect.value;
formData.append("idroutine", routineId);
fetch("process_edit_template_xls.php", {
method: "POST",
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
Swal.fire({
title: "Successo!",
text: "Template aggiornato con successo!",
icon: "success",
confirmButtonText: "OK"
}).then(() => {
window.location.href = "templates_dashboard.php";
});
} else {
Swal.fire({
title: "Errore!",
text: data.message,
icon: "error",
confirmButtonText: "OK"
});
}
})
.catch(error => {
Swal.fire({
title: "Errore!",
text: "Si è verificato un errore imprevisto.",
icon: "error",
confirmButtonText: "OK"
});
});
});
});
</script>
</body>
</html>
+57
View File
@@ -0,0 +1,57 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
header('Content-Type: application/json');
require_once 'include/headscript.php';
try {
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$id = (int)($_POST['id'] ?? 0);
$name = trim($_POST['name'] ?? '');
$registrationNumber = trim($_POST['registration_number'] ?? '');
$serialNumber = trim($_POST['serial_number'] ?? '');
$toolType = trim($_POST['tool_type'] ?? '');
$manufacturer = trim($_POST['manufacturer'] ?? '');
$description = trim($_POST['description'] ?? '');
$isActive = isset($_POST['is_active']) ? (int)$_POST['is_active'] : 1;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid ID.']);
exit;
}
if ($name === '') {
echo json_encode(['success' => false, 'message' => 'Name is required.']);
exit;
}
$sql = "UPDATE production_tools
SET name = :name,
registration_number = :registration_number,
serial_number = :serial_number,
tool_type = :tool_type,
manufacturer = :manufacturer,
description = :description,
is_active = :is_active
WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([
'name' => $name,
'registration_number' => $registrationNumber ?: null,
'serial_number' => $serialNumber ?: null,
'tool_type' => $toolType ?: null,
'manufacturer' => $manufacturer ?: null,
'description' => $description ?: null,
'is_active' => $isActive,
'id' => $id
]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
File diff suppressed because it is too large Load Diff
-14
View File
@@ -1,14 +0,0 @@
2025-06-10 12:21:44 - Errore nel recupero dati: HTTP 404, Risposta:
2025-06-16 11:15:30 - Errore nel recupero dati: HTTP 404, Risposta: {"title":"Not Found","status":404,"detail":"Not Found","instance":"GET /api/odata/Rapporto(2523026)","errorCode":"d25cbd678"}
2025-06-16 11:34:59 - Autenticazione fallita: HTTP 0, Errore cURL: Failed to connect to 93.43.5.102 port 443 after 21033 ms: Couldn't connect to server, Risposta:
2025-06-16 11:42:03 - Errore nella richiesta: Recv failure: Connection was reset
2025-07-04 10:42:49 - Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
2025-07-04 10:44:13 - Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
2025-07-04 10:48:07 - Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
2025-08-19 16:29:25 - Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
2025-08-26 16:47:19 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
2025-08-26 16:48:15 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
2025-08-26 16:48:44 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
2025-08-26 16:49:24 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
2025-08-26 16:50:23 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
2025-09-08 08:39:17 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
-6
View File
@@ -1,6 +0,0 @@
<?php
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/import_debug.log');
error_log("TEST: errore manuale");
-239
View File
@@ -1,239 +0,0 @@
document.addEventListener("DOMContentLoaded", () => {
console.log("export_to_lims.js loaded");
// Debug: verifica che i pulsanti siano trovati
const exportButtons = document.querySelectorAll(".export-lims-btn");
console.log(`Found ${exportButtons.length} export-lims-btn buttons`);
if (exportButtons.length === 0) {
console.warn("No .export-lims-btn buttons found in the DOM");
return;
}
exportButtons.forEach((btn) => {
btn.addEventListener("click", (e) => {
e.preventDefault();
const rowIndex = btn.dataset.row;
const iddatadb = btn.dataset.iddatadb;
console.log(
`Export to LIMS clicked for row ${rowIndex}, iddatadb: ${iddatadb}`,
);
// Mostra il modale di conferma
const confirmModalElement =
document.getElementById("exportConfirmModal");
if (!confirmModalElement) {
console.error("exportConfirmModal not found in the DOM");
alert("Errore: Modale di conferma non trovato");
return;
}
const confirmModal = new bootstrap.Modal(confirmModalElement, {
keyboard: false,
});
document.getElementById("exportIddatadb").textContent = iddatadb;
confirmModal.show();
// Gestisci il click su "Conferma"
const confirmBtn = document.getElementById("exportConfirmBtn");
if (!confirmBtn) {
console.error("exportConfirmBtn not found in the DOM");
confirmModal.hide();
alert("Errore: Pulsante di conferma non trovato");
return;
}
const confirmHandler = async () => {
console.log(`Confirmed export for iddatadb: ${iddatadb}`);
confirmModal.hide();
const formData = new FormData();
formData.append("iddatadb", iddatadb);
try {
const response = await fetch("export_to_lims.php", {
method: "POST",
body: formData,
});
if (!response.ok)
throw new Error(
`HTTP error! status: ${response.status}`,
);
const data = await response.json();
console.log("Export response:", data);
// Mostra il modale di risposta
const responseModalElement = document.getElementById(
"exportResponseModal",
);
if (!responseModalElement) {
console.error(
"exportResponseModal not found in the DOM",
);
alert("Errore: Modale di risposta non trovato");
return;
}
const responseModal = new bootstrap.Modal(
responseModalElement,
{
keyboard: false,
},
);
const responseMessage = document.getElementById(
"exportResponseMessage",
);
if (data.success) {
responseMessage.innerHTML = `${data.message.replace(/\n/g, "<br>")}<br>ID CommessaWeb: ${data.idcommessaweb}`;
document.getElementById(
"exportResponseModalLabel",
).textContent = "Esportazione Completata";
responseModal.show();
// Aggiorna la UI per riflettere lo stato 'To LIMS'
const statusCell = btn
.closest(".grid-row")
.querySelector(
'.grid-cell[data-col="status"] .status-badge',
);
if (statusCell) {
statusCell.classList.remove("status-i", "status-P");
statusCell.classList.add("status-l");
statusCell.textContent = "To LIMS";
}
// Gestisci la chiusura del modale di risposta
responseModalElement.addEventListener(
"hidden.bs.modal",
() => {
console.log(
"exportResponseModal closed, cleaning up",
);
// Rimuovi tutti i backdrop residui
document
.querySelectorAll(".modal-backdrop")
.forEach((backdrop) => {
console.log(
"Removing backdrop:",
backdrop,
);
backdrop.remove();
});
// Ripristina il body
document.body.classList.remove("modal-open");
document.body.style.paddingRight = "";
// Nascondi l'overlay
const overlay = document.querySelector(
".overlay.toggle-icon",
);
if (overlay) {
overlay.style.display = "none";
}
},
{ once: true },
);
} else {
responseMessage.textContent = `Errore durante la generazione dei payload: ${data.message}`;
document.getElementById(
"exportResponseModalLabel",
).textContent = "Errore Esportazione";
responseModal.show();
// Gestisci la chiusura del modale di risposta anche in caso di errore
responseModalElement.addEventListener(
"hidden.bs.modal",
() => {
console.log(
"exportResponseModal closed, cleaning up",
);
// Rimuovi tutti i backdrop residui
document
.querySelectorAll(".modal-backdrop")
.forEach((backdrop) => {
console.log(
"Removing backdrop:",
backdrop,
);
backdrop.remove();
});
// Ripristina il body
document.body.classList.remove("modal-open");
document.body.style.paddingRight = "";
// Nascondi l'overlay
const overlay = document.querySelector(
".overlay.toggle-icon",
);
if (overlay) {
overlay.style.display = "none";
}
},
{ once: true },
);
}
} catch (error) {
console.error("Export error:", error);
const responseModalElement = document.getElementById(
"exportResponseModal",
);
if (!responseModalElement) {
console.error(
"exportResponseModal not found in the DOM",
);
alert("Errore: Modale di risposta non trovato");
return;
}
const responseModal = new bootstrap.Modal(
responseModalElement,
{
keyboard: false,
},
);
document.getElementById(
"exportResponseMessage",
).textContent =
`Errore durante la generazione dei payload: ${error.message}`;
document.getElementById(
"exportResponseModalLabel",
).textContent = "Errore Esportazione";
responseModal.show();
// Gestisci la chiusura del modale di risposta in caso di errore
responseModalElement.addEventListener(
"hidden.bs.modal",
() => {
console.log(
"exportResponseModal closed, cleaning up",
);
// Rimuovi tutti i backdrop residui
document
.querySelectorAll(".modal-backdrop")
.forEach((backdrop) => {
console.log("Removing backdrop:", backdrop);
backdrop.remove();
});
// Ripristina il body
document.body.classList.remove("modal-open");
document.body.style.paddingRight = "";
// Nascondi l'overlay
const overlay = document.querySelector(
".overlay.toggle-icon",
);
if (overlay) {
overlay.style.display = "none";
}
},
{ once: true },
);
}
// Rimuovi il listener dopo l'esecuzione
confirmBtn.removeEventListener("click", confirmHandler);
};
// Rimuovi eventuali listener precedenti
confirmBtn.removeEventListener("click", confirmHandler);
confirmBtn.addEventListener("click", confirmHandler);
});
});
});
-291
View File
@@ -1,291 +0,0 @@
<?php
require_once "class/VisualLimsApiClient.class.php";
include('include/headscript.php');
$dbHandler = DBHandlerSelect::getInstance();
$pdo = $dbHandler->getConnection();
header("Content-Type: application/json");
// 🔹 Configura directory log (creala se non esiste)
$logDir = __DIR__ . '/logs/api/';
if (!is_dir($logDir)) {
mkdir($logDir, 0755, true);
}
// 🔹 Base URL API
$apiBaseUrl = 'https://93.43.5.102/limsapi/api/odata/';
// 🔹 Funzione per validare e convertire date
function validateDate($value)
{
// Prova a validare come data (accetta formati comuni)
$date = DateTime::createFromFormat('Y-m-d', $value) ?: DateTime::createFromFormat('Y-m-d H:i:s', $value);
if ($date) {
return $date->format('Y-m-d\TH:i:sP'); // Formato ISO 8601
}
return null; // Imposta null se non è una data valida
}
try {
$iddatadb = $_POST['iddatadb'] ?? null;
if (!$iddatadb) {
throw new Exception("Missing iddatadb");
}
// 🔹 STEP 1+2: Fetch Cliente ID + Schema ID
$stmt = $pdo->prepare("
SELECT et.idclient AS clienteId, et.idschema AS schemaId
FROM datadb as d
INNER JOIN excel_templates as et ON d.templateid = et.id
WHERE d.iddatadb = :iddatadb
LIMIT 1
");
$stmt->execute(['iddatadb' => $iddatadb]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$result) {
throw new Exception("No Cliente/Schema found for iddatadb {$iddatadb}");
}
$clienteId = (int) $result['clienteId'];
$schemaId = (int) $result['schemaId'];
// 🔹 STEP 3: Fetch Parts (including idmatrice)
$stmt = $pdo->prepare("
SELECT part_number, part_description, material, color, mix, idmatrice
FROM identification_parts
WHERE iddatadb = :iddatadb
");
$stmt->execute(['iddatadb' => $iddatadb]);
$parts = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 🔹 STEP 4: Fetch Field Values with Labels
$stmt = $pdo->prepare("
SELECT
idd.field_value,
m.field_label,
m.schema_id,
m.field_id
FROM
import_data_details as idd
JOIN template_mapping m ON idd.mapping_id = m.id
WHERE idd.id = :iddatadb
");
$stmt->execute(['iddatadb' => $iddatadb]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$fieldValues = [];
$valueMap = [];
foreach ($rows as $row) {
$fieldValues[] = [
"IdCommesseCustomFields" => (int) $row['field_id'],
"Valore" => $row['field_value'],
"FieldLabel" => $row['field_label']
];
$valueMap[(int) $row['field_id']] = $row['field_value'];
}
// Logga i fieldValues in error_log
$logFieldValues = "FieldValues dal DB (iddatadb={$iddatadb}):\n" . json_encode($fieldValues, JSON_PRETTY_PRINT);
error_log($logFieldValues);
// 🔹 Initialize API client
$api = VisualLimsApiClient::getInstance();
// 🔹 STEP 5: Create CommessaWeb (NOT WebOrder)
$commessaWebPayload = [
"Cliente" => $clienteId,
"SchemaCustomField" => $schemaId,
"Richiedente" => "Test Web Import",
"Descrizione" => "TEST CommessaWeb",
];
// Costruisci log curl-like per STEP 5
$jsonPayload = json_encode($commessaWebPayload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
$logContentStep5 = "curl --location --request POST '{$apiBaseUrl}CommessaWeb' \\\n" .
"--header 'Content-Type: application/json' \\\n" .
"--header 'Authorization: Bearer ••••••' \\\n" .
"--data '{$jsonPayload}'";
$commessaWeb = $api->post("CommessaWeb", $commessaWebPayload);
$logContentStep5 .= "\n\nRESPONSE:\n" . json_encode($commessaWeb, JSON_PRETTY_PRINT);
// Salva log
$logFileStep5 = $logDir . "commessa_create_step5_" . $iddatadb . "_" . time() . ".txt";
file_put_contents($logFileStep5, $logContentStep5);
$commessaId = $commessaWeb["IdCommessa"];
$commessaWebCode = substr($commessaWeb["CodiceCommessa"] ?? "TEST CommessaWeb", 0, 30); // Limite a 30 caratteri
// 🔹 STEP 6: Create Campioni (Samples) for each part
$campioni = [];
$logContentStep6 = "";
foreach ($parts as $index => $part) {
$matriceId = (int) ($part["idmatrice"] ?? 0);
if ($matriceId <= 0) {
throw new Exception("Invalid or missing idmatrice for part: " . ($part["part_number"] ?? "Unknown"));
}
$campionePayload = [
"Commessa" => $commessaId,
"Matrice" => $matriceId,
"SottoMatrice" => null,
"SchemaCustomField" => $schemaId,
"NoteWeb" => $part["part_description"] ?? ""
];
// Costruisci curl-like per questo campione
$jsonPayload = json_encode($campionePayload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
$logContentStep6 .= "CAMPIONE #{$index}\n" .
"curl --location --request POST '{$apiBaseUrl}Campione' \\\n" .
"--header 'Content-Type: application/json' \\\n" .
"--header 'Authorization: Bearer ••••••' \\\n" .
"--data '{$jsonPayload}'\n\n";
$campione = $api->post("Campione", $campionePayload);
$logContentStep6 .= "RESPONSE:\n" . json_encode($campione, JSON_PRETTY_PRINT) . "\n\n---\n";
$campione["PartNumber"] = $part["part_number"] ?? "";
$campione["Material"] = $part["material"] ?? "";
$campione["Color"] = $part["color"] ?? "";
$campione["Mix"] = $part["mix"] ?? "";
$campioni[] = $campione;
}
// Salva log per STEP 6
$logFileStep6 = $logDir . "commessa_{$commessaId}_campioni_step6_" . time() . ".txt";
file_put_contents($logFileStep6, $logContentStep6);
// 🔹 STEP 7: Update Custom Fields for CommessaWeb
if (!empty($fieldValues)) {
// GET con espansione per CustomField
$expand = "CommesseCustomFields(\$expand=CustomField)";
$commessaWithFields = $api->get("CommessaWeb(" . $commessaId . ")?\$expand=" . $expand);
// Logga il GET
$logContentGet = "curl --location --request GET '{$apiBaseUrl}CommessaWeb({$commessaId})?\$expand=CommesseCustomFields(\$expand=CustomField)' \\\n" .
"--header 'Authorization: Bearer ••••••'\n\n" .
"RESPONSE:\n" . json_encode($commessaWithFields, JSON_PRETTY_PRINT);
$logFileGet = $logDir . "commessa_{$commessaId}_get_step7_" . time() . ".txt";
file_put_contents($logFileGet, $logContentGet);
// Prepara payload PATCH
$commessaCustomFields = [];
foreach ($commessaWithFields["CommesseCustomFields"] as $customField) {
$definitionId = (int) ($customField["CustomField"]["IdCustomField"] ?? 0);
$fieldId = (int) $customField["IdCommesseCustomFields"];
$currentValue = $customField["Valore"] ?? '';
$fieldType = $customField["CustomField"]["Tipo"] ?? '';
$newValue = isset($valueMap[$definitionId]) ? $valueMap[$definitionId] : $currentValue;
// Valida se il campo è di tipo Data
if ($fieldType === 'Data' && $newValue !== $currentValue) {
$newValue = validateDate($newValue);
}
$commessaCustomFields[] = [
"IdCommesseCustomFields" => $fieldId,
"Valore" => $newValue
];
}
if (!empty($commessaCustomFields)) {
$updatePayload = ["CommesseCustomFields" => $commessaCustomFields];
// Logga payload e response
$jsonPayload = json_encode($updatePayload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
$logContentStep7 = "curl --location --request PATCH '{$apiBaseUrl}CommessaWeb({$commessaId})' \\\n" .
"--header 'Content-Type: application/json' \\\n" .
"--header 'Authorization: Bearer ••••••' \\\n" .
"--data '{$jsonPayload}'";
$patchResponse = $api->patch("CommessaWeb({$commessaId})", $updatePayload);
$logContentStep7 .= "\n\nRESPONSE:\n" . json_encode($patchResponse, JSON_PRETTY_PRINT);
$logFileStep7 = $logDir . "commessa_{$commessaId}_update_step7_" . time() . ".txt";
file_put_contents($logFileStep7, $logContentStep7);
}
}
// 🔹 STEP 8: Update datadb with idcommessaweb, commessaweb, and status
$stmt = $pdo->prepare("
UPDATE datadb
SET idcommessaweb = :idcommessaweb, commessaweb = :commessaweb, status = 'l'
WHERE iddatadb = :iddatadb
");
$stmt->execute([
'idcommessaweb' => $commessaId,
'commessaweb' => $commessaWebCode,
'iddatadb' => $iddatadb
]);
// 🔹 STEP 9: Send CommessaWeb to laboratory (commentato come richiesto)
/*
$sendResult = $api->post("CommessaWeb({$commessaId})/InviaCommessa", []);
// Logga il POST
$logContentStep9 = "curl --location --request POST '{$apiBaseUrl}CommessaWeb({$commessaId})/InviaCommessa' \\\n" .
"--header 'Content-Type: application/json' \\\n" .
"--header 'Authorization: Bearer ••••••' \\\n" .
"--data '{}'\n\n" .
"RESPONSE:\n" . json_encode($sendResult, JSON_PRETTY_PRINT);
$logFileStep9 = $logDir . "commessa_{$commessaId}_send_step9_" . time() . ".txt";
file_put_contents($logFileStep9, $logContentStep9);
*/
// 🔹 STEP 10: GET di controllo post-PATCH
$expand = "CommesseCustomFields(\$expand=CustomField)";
$commessaAfterPatch = $api->get("CommessaWeb(" . $commessaId . ")?\$expand=" . $expand);
// Logga il GET di controllo
$logContentStep10 = "curl --location --request GET '{$apiBaseUrl}CommessaWeb({$commessaId})?\$expand=CommesseCustomFields(\$expand=CustomField)' \\\n" .
"--header 'Authorization: Bearer ••••••'\n\n" .
"RESPONSE:\n" . json_encode($commessaAfterPatch, JSON_PRETTY_PRINT);
$logFileStep10 = $logDir . "commessa_{$commessaId}_get_step10_" . time() . ".txt";
file_put_contents($logFileStep10, $logContentStep10);
// 🔹 STEP 11: Prepare final response
$finalCommessa = [
"Cliente" => $clienteId,
"SchemaCustomField" => $schemaId,
"Richiedente" => $commessaWeb["Richiedente"] ?? "Web Import",
"Descrizione" => $commessaWeb["Descrizione"] ?? "",
"CommesseCustomFields" => $commessaAfterPatch["CommesseCustomFields"] ?? [],
"Campioni" => $campioni,
"Inviata" => 0 // Non inviato, come richiesto
];
echo json_encode([
"success" => true,
"commessaWeb" => $finalCommessa,
"commessaWebApiResponse" => $commessaWeb, // Incluso per debug
"totalCampioni" => count($campioni),
"totalCustomFields" => count($commessaAfterPatch["CommesseCustomFields"] ?? []),
"message" => "Export successful",
"logFiles" => [
"step5_create" => $logFileStep5,
"step6_campioni" => $logFileStep6,
"step7_patch" => $logFileStep7,
"step10_get" => $logFileStep10
]
]);
} catch (Exception $e) {
error_log("LIMS Export Error: " . $e->getMessage() . "\nTrace: " . $e->getTraceAsString());
echo json_encode([
"success" => false,
"message" => "Export failed: " . $e->getMessage(),
"logFiles" => [
"step5_create" => $logFileStep5 ?? null,
"step6_campioni" => $logFileStep6 ?? null,
"step7_patch" => $logFileStep7 ?? null,
"step10_get" => $logFileStep10 ?? null
]
]);
}
-150
View File
@@ -1,150 +0,0 @@
<?php
// Abilita il debug degli errori (solo per sviluppo)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Assicurati che non ci sia output prima del JSON
ob_start();
// Imposta l'header per JSON
header('Content-Type: application/json');
// Configura la tua chiave API di TrackingMore
$apiKey = 'u4ssgynn-xuyy-9act-ca29-2glsv2qlzh0w'; // La tua chiave API reale
// Funzione per inviare una risposta JSON e terminare l'esecuzione
function sendResponse($data)
{
ob_end_clean();
echo json_encode($data);
exit;
}
// Verifica che il numero di tracking e il corriere siano stati inviati
if (!isset($_POST['tracking_number']) || empty($_POST['tracking_number']) || !isset($_POST['courier_code']) || empty($_POST['courier_code'])) {
sendResponse(['success' => false, 'message' => 'Numero di tracking o corriere non fornito']);
}
$trackingNumber = $_POST['tracking_number'];
$courierCode = $_POST['courier_code'];
// Lista dei corrieri validi per validazione
$validCarriers = ['tnt-it', 'dhl', 'gls', 'sda', 'ups'];
if (!in_array($courierCode, $validCarriers)) {
sendResponse(['success' => false, 'message' => 'Corriere non valido']);
}
// Imposta il nome del corriere in base al codice
$carrierNames = [
'tnt-it' => 'TNT Italy',
'dhl' => 'DHL',
'gls' => 'GLS',
'sda' => 'SDA',
'ups' => 'UPS'
];
$courierName = $carrierNames[$courierCode];
// Funzione per fare una richiesta cURL a TrackingMore
function makeRequest($url, $data, $apiKey, $method = 'POST')
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Tracking-Api-Key: ' . $apiKey,
'Content-Type: application/json'
]);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
$jsonData = json_encode($data, JSON_PRETTY_PRINT);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
file_put_contents('debug.log', "Encoded JSON Data: $jsonData\n", FILE_APPEND);
}
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
file_put_contents('debug.log', "Request URL: $url\nRequest Data: " . json_encode($data) . "\nResponse: $response\nHTTP Code: $httpCode\nError: $error\n", FILE_APPEND);
if ($response === false) {
return [
'success' => false,
'code' => $httpCode,
'message' => 'Errore nella richiesta API: ' . $error
];
}
$decodedResponse = json_decode($response, true);
if ($decodedResponse === null) {
return [
'success' => false,
'code' => $httpCode,
'message' => 'Risposta API non valida (non è JSON)'
];
}
$decodedResponse['success'] = isset($decodedResponse['meta']['code']) && ($decodedResponse['meta']['code'] === 200 || $decodedResponse['meta']['code'] === 201);
$decodedResponse['http_code'] = $httpCode;
return $decodedResponse;
}
// Step 1: Prova a creare il tracking
$createUrl = 'https://api.trackingmore.com/v4/trackings/create';
$createData = [
'tracking_number' => $trackingNumber,
'courier_code' => $courierCode
];
$createResponse = makeRequest($createUrl, $createData, $apiKey);
file_put_contents('debug.log', "Create Response: " . json_encode($createResponse) . "\n", FILE_APPEND);
$trackingInfo = null;
if ($createResponse['success']) {
// Creazione riuscita, usa i dati restituiti
$trackingInfo = $createResponse['data'];
} else {
// Controlla se l'errore è "Tracking No. already exists" (4101)
if (isset($createResponse['meta']['code']) && $createResponse['meta']['code'] === 4101) {
// Il tracking esiste già, usa /trackings (GET) con tracking_number e courier_code
$getUrl = 'https://api.trackingmore.com/v4/get?tracking_numbers=' . urlencode($trackingNumber);
$getResponse = makeRequest($getUrl, [], $apiKey, 'GET');
file_put_contents('debug.log', "Get Response: " . json_encode($getResponse) . "\n", FILE_APPEND);
if ($getResponse['success'] && !empty($getResponse['data']['items']) && !empty($getResponse['data']['items'][0])) {
$trackingInfo = $getResponse['data']['items'][0];
} else {
$errorMessage = isset($getResponse['meta']['message']) ? $getResponse['meta']['message'] : 'Errore sconosciuto';
sendResponse(['success' => false, 'message' => 'Errore nel recupero del tracking esistente: ' . $errorMessage]);
}
} else {
// Altro errore nella creazione
$errorMessage = isset($createResponse['meta']['message']) ? $createResponse['meta']['message'] : 'Errore sconosciuto';
sendResponse(['success' => false, 'message' => 'Errore nella creazione del tracking: ' . $errorMessage]);
}
}
if (!$trackingInfo) {
sendResponse(['success' => false, 'message' => 'Nessuna informazione di tracking trovata']);
}
// Estrai la data di consegna e il firmatario
$deliveryDate = 'Non disponibile';
$signedBy = 'Non disponibile';
if (isset($trackingInfo['origin_info']['trackinfo']) && is_array($trackingInfo['origin_info']['trackinfo'])) {
foreach ($trackingInfo['origin_info']['trackinfo'] as $checkpoint) {
if (isset($checkpoint['checkpoint_delivery_status']) && $checkpoint['checkpoint_delivery_status'] === 'delivered') {
$deliveryDate = $checkpoint['checkpoint_date'] ?? 'Non disponibile';
$signedBy = $trackingInfo['signed_by'] ?? 'Non disponibile';
break;
}
}
}
// Restituisci i dati al frontend
sendResponse([
'success' => true,
'deliveryDate' => $deliveryDate,
'signedBy' => $signedBy,
'carrierName' => $courierName
]);
@@ -1,166 +0,0 @@
<?php
// Abilita il debug degli errori (solo per sviluppo)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Assicurati che non ci sia output prima del JSON
ob_start();
// Imposta l'header per JSON
header('Content-Type: application/json');
// Configura la tua chiave API di 17Track
$apiKey = '489F6B6DADDE09A5B6CB1C42B5363A3F'; // Sostituisci con la tua chiave API reale
// Funzione per inviare una risposta JSON e terminare l'esecuzione
function sendResponse($data)
{
ob_end_clean();
echo json_encode($data);
exit;
}
// Verifica che il numero di tracking sia stato inviato
if (!isset($_POST['tracking_number']) || empty($_POST['tracking_number'])) {
sendResponse(['success' => false, 'message' => 'Numero di tracking non fornito']);
}
$trackingNumber = $_POST['tracking_number'];
// Funzione per fare una richiesta cURL a 17Track
function makeRequest($url, $data, $apiKey, $method = 'POST')
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'17token: ' . $apiKey,
'Content-Type: application/json'
]);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
file_put_contents('debug.log', "Request URL: $url\nRequest Data: " . json_encode($data) . "\nResponse: $response\nHTTP Code: $httpCode\nError: $error\n", FILE_APPEND);
if ($response === false || $httpCode !== 200) {
return [
'success' => false,
'code' => $httpCode,
'message' => 'Errore nella richiesta API: HTTP ' . $httpCode . ' - ' . $error
];
}
$decodedResponse = json_decode($response, true);
if ($decodedResponse === null) {
return [
'success' => false,
'code' => $httpCode,
'message' => 'Risposta API non valida (non è JSON)'
];
}
return $decodedResponse;
}
// Step 1: Prova con auto-detection
$trackUrl = 'https://api.17track.net/track/v2/register';
$trackData = [
[
'number' => $trackingNumber,
'carrier' => null,
'auto_detection' => true
]
];
$registerResponse = makeRequest($trackUrl, $trackData, $apiKey);
file_put_contents('debug.log', "Register Response (Auto-detect): " . json_encode($registerResponse) . "\n", FILE_APPEND);
if (!isset($registerResponse['data']['accepted']) || empty($registerResponse['data']['accepted'])) {
$errorMessage = $registerResponse['data']['rejected'][0]['error']['message'] ?? 'Errore sconosciuto';
sendResponse(['success' => false, 'message' => 'Errore nella registrazione del tracking: ' . $errorMessage]);
}
// Step 2: Recupera i dettagli con riprova
$getUrl = 'https://api.17track.net/track/v2/gettrackinfo';
$getData = [['number' => $trackingNumber]];
$maxAttempts = 3;
$delaySeconds = 5;
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
$trackResponse = makeRequest($getUrl, $getData, $apiKey);
file_put_contents('debug.log', "Track Response (Attempt $attempt): " . json_encode($trackResponse) . "\n", FILE_APPEND);
if (isset($trackResponse['data']['accepted']) && !empty($trackResponse['data']['accepted'])) {
break;
}
if ($attempt < $maxAttempts) {
sleep($delaySeconds);
}
}
// Se auto-detection ha successo, procedi
if (isset($trackResponse['data']['accepted']) && !empty($trackResponse['data']['accepted'])) {
$trackingInfo = $trackResponse['data']['accepted'][0]['track'] ?? null;
if (!$trackingInfo) {
sendResponse(['success' => false, 'message' => 'Nessuna informazione di tracking trovata']);
}
$deliveryDate = 'Non disponibile';
$signedBy = 'Non disponibile';
$carrierName = $trackingInfo['carrier']['name'] ?? 'Sconosciuto';
if (isset($trackingInfo['z0']['e']) && $trackingInfo['z0']['e'] == 40) {
$deliveryDate = $trackingInfo['z0']['z'] ?? 'Non disponibile';
$signedBy = $trackingInfo['z0']['d'] ?? 'Non disponibile';
}
sendResponse([
'success' => true,
'deliveryDate' => $deliveryDate,
'signedBy' => $signedBy,
'carrierName' => $carrierName
]);
}
// Step 3: Se auto-detection fallisce, prova una lista di corrieri comuni
$commonCarriers = [
['code' => 100003, 'name' => 'TNT'], // TNT
['code' => 100001, 'name' => 'DHL'], // DHL Express
['code' => 100065, 'name' => 'DHL eCommerce'], // DHL eCommerce
['code' => 100002, 'name' => 'UPS'] // UPS
];
$possibleCarriers = [];
foreach ($commonCarriers as $carrier) {
$trackData = [
[
'number' => $trackingNumber,
'carrier' => $carrier['code'],
'auto_detection' => false
]
];
$registerResponse = makeRequest($trackUrl, $trackData, $apiKey);
if (isset($registerResponse['data']['accepted']) && !empty($registerResponse['data']['accepted'])) {
$possibleCarriers[] = $carrier['name'];
}
sleep(1); // Piccolo ritardo per evitare limiti di rate
}
if (!empty($possibleCarriers)) {
sendResponse([
'success' => false,
'message' => 'Auto-detection fallita. Seleziona un corriere tra quelli possibili.',
'possibleCarriers' => $possibleCarriers
]);
} else {
sendResponse(['success' => false, 'message' => 'Nessun corriere identificato per questo numero di tracking']);
}
@@ -1,166 +0,0 @@
<?php
// Abilita il debug degli errori (solo per sviluppo)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Assicurati che non ci sia output prima del JSON
ob_start();
// Imposta l'header per JSON
header('Content-Type: application/json');
// Configura la tua chiave API di TrackingMore
$apiKey = 'u4ssgynn-xuyy-9act-ca29-2glsv2qlzh0w'; // La tua chiave API reale
// Funzione per inviare una risposta JSON e terminare l'esecuzione
function sendResponse($data)
{
ob_end_clean();
echo json_encode($data);
exit;
}
// Verifica che il numero di tracking sia stato inviato
if (!isset($_POST['tracking_number']) || empty($_POST['tracking_number'])) {
sendResponse(['success' => false, 'message' => 'Numero di tracking non fornito']);
}
$trackingNumber = $_POST['tracking_number'];
// Funzione per fare una richiesta cURL a TrackingMore
function makeRequest($url, $data, $apiKey, $method = 'POST')
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Tracking-Api-Key: ' . $apiKey,
'Content-Type: application/json'
]);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
file_put_contents('debug.log', "Request URL: $url\nRequest Data: " . json_encode($data) . "\nResponse: $response\nHTTP Code: $httpCode\nError: $error\n", FILE_APPEND);
if ($response === false || ($httpCode !== 200 && $httpCode !== 201)) {
return [
'success' => false,
'code' => $httpCode,
'message' => 'Errore nella richiesta API: HTTP ' . $httpCode . ' - ' . $error
];
}
$decodedResponse = json_decode($response, true);
if ($decodedResponse === null) {
return [
'success' => false,
'code' => $httpCode,
'message' => 'Risposta API non valida (non è JSON)'
];
}
$decodedResponse['success'] = isset($decodedResponse['meta']['code']) && ($decodedResponse['meta']['code'] === 200 || $decodedResponse['meta']['code'] === 201);
return $decodedResponse;
}
// Step 1: Identifica il corriere
$detectUrl = 'https://api.trackingmore.com/v4/couriers/detect';
$detectData = ['tracking_number' => $trackingNumber];
$detectResponse = makeRequest($detectUrl, $detectData, $apiKey);
file_put_contents('debug.log', "Detect Response: " . json_encode($detectResponse) . "\n", FILE_APPEND);
if (!$detectResponse['success']) {
$errorMessage = isset($detectResponse['meta']['message']) ? $detectResponse['meta']['message'] : 'Errore sconosciuto';
sendResponse(['success' => false, 'message' => 'Errore nella rilevazione del corriere: ' . $errorMessage]);
}
$couriers = $detectResponse['data'] ?? [];
if (empty($couriers)) {
sendResponse(['success' => false, 'message' => 'Corriere non identificato per il numero di tracking']);
}
// Prendi il primo corriere per ora
$courierCode = $couriers[0]['courier_code'] ?? null;
$courierName = $couriers[0]['courier_name'] ?? 'Sconosciuto';
if (!$courierCode) {
sendResponse(['success' => false, 'message' => 'Corriere non identificato']);
}
// Step 2: Crea un tracking
$createUrl = 'https://api.trackingmore.com/v4/trackings/create';
$createData = [
'tracking_number' => $trackingNumber,
'courier_code' => $courierCode
];
$createResponse = makeRequest($createUrl, $createData, $apiKey);
file_put_contents('debug.log', "Create Response: " . json_encode($createResponse) . "\n", FILE_APPEND);
if (!$createResponse['success']) {
$errorMessage = isset($createResponse['meta']['message']) ? $createResponse['meta']['message'] : 'Errore sconosciuto';
sendResponse(['success' => false, 'message' => 'Errore nella creazione del tracking: ' . $errorMessage]);
}
// Step 3: Recupera i dettagli del tracking con riprova
$getUrl = 'https://api.trackingmore.com/v4/trackings/get?tracking_number=' . urlencode($trackingNumber);
$maxAttempts = 3;
$delaySeconds = 5;
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
$trackResponse = makeRequest($getUrl, [], $apiKey, 'GET');
file_put_contents('debug.log', "Track Response (Attempt $attempt): " . json_encode($trackResponse) . "\n", FILE_APPEND);
if ($trackResponse['success'] && !empty($trackResponse['data'])) {
break;
}
if ($attempt < $maxAttempts) {
sleep($delaySeconds);
}
}
if (!$trackResponse['success']) {
$errorMessage = isset($trackResponse['meta']['message']) ? $trackResponse['meta']['message'] : 'Errore sconosciuto';
sendResponse(['success' => false, 'message' => 'Errore nel recupero delle informazioni: ' . $errorMessage]);
}
$trackingInfo = $trackResponse['data'] ?? null;
if (!$trackingInfo) {
// Se ci sono più corrieri rilevati, restituisci una lista per la tendina
if (count($couriers) > 1) {
$possibleCarriers = array_map(function ($courier) {
return ['code' => $courier['courier_code'], 'name' => $courier['courier_name']];
}, $couriers);
sendResponse([
'success' => false,
'message' => 'Dati non trovati. Seleziona un corriere tra quelli rilevati.',
'possibleCarriers' => $possibleCarriers
]);
}
sendResponse(['success' => false, 'message' => 'Nessuna informazione di tracking trovata']);
}
// Estrai la data di consegna e il firmatario
$deliveryDate = 'Non disponibile';
$signedBy = 'Non disponibile';
foreach ($trackingInfo['trackinfo'] as $checkpoint) {
if ($checkpoint['status'] === 'delivered') {
$deliveryDate = $checkpoint['Date'];
$signedBy = $checkpoint['signed_by'] ?? 'Non disponibile';
break;
}
}
// Restituisci i dati al frontend
sendResponse([
'success' => true,
'deliveryDate' => $deliveryDate,
'signedBy' => $signedBy,
'carrierName' => $courierName
]);
-38
View File
@@ -1,38 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once __DIR__ . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
// Disable PHP error display
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
// Parametri OData
$params = [
'$select' => 'IdCliente,Nominativo,CodiceNazioneFatturazione',
'$orderby' => 'Nominativo asc'
];
// Costruisce query string con encoding corretto
$queryString = http_build_query($params);
// Componi endpoint finale
$endpoint = "Cliente?$queryString";
// Richiama API
$data = $api->get($endpoint);
// Salva risposta per debug
file_put_contents(__DIR__ . '/clienti_response.json', json_encode($data, JSON_PRETTY_PRINT));
echo json_encode($data);
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'error' => $e->getMessage()
]);
}
-39
View File
@@ -1,39 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
// ID della CommessaWeb specifica (cambialo di volta in volta)
$id = 529435; // TODO: Cambia questo valore con l'ID desiderato
// Endpoint per recuperare la CommessaWeb specifica con espansione dello schema custom
$endpoint = "CommessaWeb({$id})";
// Opzioni per l'espansione: includi OrderCustomFields per ottenere i campi custom dello schema assegnato all'ordine
$options = ['$expand' => 'OrderCustomFields'];
// Debug: salva URL usato
$base_url = 'https://93.43.5.102/limsapi/api/odata/';
$query = http_build_query($options);
$full_url = $base_url . $endpoint . ($query ? '?' . $query : '');
file_put_contents(__DIR__ . '/last_url.txt', $full_url . PHP_EOL, FILE_APPEND);
// Chiamata API
$data = $api->get($endpoint, $options);
// Salva il JSON in locale
file_put_contents(__DIR__ . '/commessaweb_schema_response.json', json_encode($data, JSON_PRETTY_PRINT));
echo json_encode($data);
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
@@ -1,41 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
// მივიღოთ მრავლობითი field_ids
$fieldIds = [];
if (isset($_GET['field_ids'])) {
$fieldIds = array_filter(array_map('intval', explode(',', $_GET['field_ids'])));
}
// თუ არ გადმოგვცეს -> ერთი default
if (empty($fieldIds)) {
$fieldIds = [156];
}
$results = [];
foreach ($fieldIds as $customFieldId) {
$endpoint = "CustomField($customFieldId)?\$expand=CustomFieldsValues";
$data = $api->get($endpoint);
$results[$customFieldId] = $data['CustomFieldsValues'] ?? [];
}
// Debug ფაილი
file_put_contents(__DIR__ . '/customfield_values_response.json', json_encode($results));
echo json_encode($results);
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'error' => $e->getMessage()
]);
}
+28
View File
@@ -0,0 +1,28 @@
<?php
include('../class/db-functions.php');
header('Content-Type: application/json');
try {
if (!isset($_GET['id'])) {
echo json_encode(['success' => false, 'message' => 'ID matrice non fornito.']);
exit;
}
$idMatrice = intval($_GET['id']);
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Tutte le linee
$stmt = $pdo->query("SELECT id, name, brand FROM production_lines ORDER BY name ASC");
$tutte = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Linee già associate
$stmt = $pdo->prepare("SELECT idlinea FROM matrice_lines WHERE idmatrice = ?");
$stmt->execute([$idMatrice]);
$associate = $stmt->fetchAll(PDO::FETCH_COLUMN);
echo json_encode(['success' => true, 'tutte' => $tutte, 'associate' => $associate]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => 'Errore: ' . $e->getMessage()]);
}
+37
View File
@@ -0,0 +1,37 @@
<?php
require_once(__DIR__ . '/class/db-functions.php');
header('Content-Type: application/json');
try {
if (!isset($_GET['id'])) {
throw new Exception("Parametro ID mancante.");
}
$idMescola = (int) $_GET['id'];
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Recupera TUTTE le linee
$stmt = $pdo->query("SELECT id, name, brand FROM production_lines ORDER BY line_number ASC");
$tutte_linee = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Recupera linee associate a questa mescola
$stmt = $pdo->prepare("SELECT idlinea FROM mescole_lines WHERE idmescola = ?");
$stmt->execute([$idMescola]);
$associate = $stmt->fetchAll(PDO::FETCH_COLUMN);
// Conversione in stringhe (per compatibilità con JS)
$associate = array_map('strval', $associate);
echo json_encode([
"success" => true,
"tutte_linee" => $tutte_linee,
"associate" => $associate
]);
} catch (Exception $e) {
echo json_encode([
"success" => false,
"message" => $e->getMessage()
]);
}
-36
View File
@@ -1,36 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
// Endpoint per recuperare le Matrici
$endpoint = 'Matrice';
// (Opzionale) aggiungi parametri, ad esempio $top per limitare i risultati
$options = []; // oppure ad esempio: ['$top' => 100]
// Debug: salva URL usato
$base_url = 'https://93.43.5.102/limsapi/api/odata/';
$query = http_build_query($options);
$full_url = $base_url . $endpoint . ($query ? '?' . $query : '');
file_put_contents(__DIR__ . '/last_url.txt', $full_url . PHP_EOL, FILE_APPEND);
// Chiamata API
$data = $api->get($endpoint, $options);
// Salva il JSON in locale
file_put_contents(__DIR__ . '/matrici_response.json', json_encode($data, JSON_PRETTY_PRINT));
echo json_encode($data);
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
@@ -0,0 +1,65 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json; charset=utf-8');
$response = [
'success' => false,
'attachments' => [],
'message' => ''
];
try {
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
throw new Exception('ID matrice non valido');
}
$idmatrice = (int)$_GET['id'];
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$sql = "SELECT
id,
matrice_id,
file_name,
file_path,
file_type,
description,
sort_order,
created_at,
updated_at
FROM matrice_attachments
WHERE matrice_id = :matrice_id
ORDER BY sort_order ASC, id DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute([':matrice_id' => $idmatrice]);
$attachments = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$relativePath = ltrim((string)$row['file_path'], '/\\');
$attachments[] = [
'id' => (int)$row['id'],
'matrice_id' => (int)$row['matrice_id'],
'file_name' => $row['file_name'],
'file_path' => $relativePath,
'file_url' => $relativePath,
'file_type' => $row['file_type'],
'description' => $row['description'] ?? '',
'sort_order' => (int)($row['sort_order'] ?? 0),
'created_at' => !empty($row['created_at']) ? date('d/m/Y H:i', strtotime($row['created_at'])) : '',
'updated_at' => !empty($row['updated_at']) ? date('d/m/Y H:i', strtotime($row['updated_at'])) : ''
];
}
$response['success'] = true;
$response['attachments'] = $attachments;
} catch (Throwable $e) {
$response['message'] = $e->getMessage();
}
echo json_encode($response, JSON_UNESCAPED_UNICODE);
exit;
+36
View File
@@ -0,0 +1,36 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json; charset=utf-8');
try {
$idmatrice = (int)($_GET['id'] ?? 0);
if ($idmatrice <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid id']);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// tutte le linee (attive + inattive se vuoi: qui prendo tutte)
$stmt = $pdo->query("
SELECT id, line_number, name
FROM production_lines
ORDER BY line_number ASC
");
$lines = $stmt->fetchAll(PDO::FETCH_ASSOC);
// linee già associate
$stmt = $pdo->prepare("SELECT idlinea FROM matrici_lines WHERE idmatrice = ?");
$stmt->execute([$idmatrice]);
$selected_ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
echo json_encode([
'success' => true,
'lines' => $lines,
'selected_ids' => $selected_ids
]);
} catch (Throwable $e) {
echo json_encode(['success' => false, 'message' => 'Server error']);
}
+35
View File
@@ -0,0 +1,35 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json; charset=utf-8');
try {
$idmatrice = (int)($_GET['id'] ?? 0);
if ($idmatrice <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid id']);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// tutte le mescole
$stmt = $pdo->query("
SELECT id, nome, nomeuscita
FROM mescole
ORDER BY nome ASC
");
$mescole = $stmt->fetchAll(PDO::FETCH_ASSOC);
// mescole già associate
$stmt = $pdo->prepare("SELECT idmescola FROM matrici_mescole WHERE idmatrice = ?");
$stmt->execute([$idmatrice]);
$selected_ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
echo json_encode([
'success' => true,
'mescole' => $mescole,
'selected_ids' => $selected_ids
]);
} catch (Throwable $e) {
echo json_encode(['success' => false, 'message' => 'Server error']);
}
@@ -0,0 +1,31 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json');
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid id']);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$sql = "SELECT
msl.id,
msl.idsupplier AS idsupplier,
s.supplier_name,
msl.supplier_mix_name,
msl.lot_code,
msl.expiry_date,
msl.qty
FROM mescole_supplier_lots msl
INNER JOIN suppliers s ON s.idsupplier = msl.idsupplier
WHERE msl.idmescola = ?
ORDER BY msl.id DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'rows' => $rows]);
+37
View File
@@ -0,0 +1,37 @@
<?php
header('Content-Type: application/json');
// Evita che warning PHP rovinino il json
error_reporting(0);
ini_set('display_errors', 0);
require_once(__DIR__ . '/../class/db-functions.php');
try {
if (!isset($_GET['id'])) {
echo json_encode(['success' => false, 'message' => 'ID matrice non fornito.']);
exit;
}
$idMatrice = intval($_GET['id']);
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// tutte le mescole
$stmt = $pdo->query("SELECT id, nome FROM mescole ORDER BY nome ASC");
$tutte = $stmt->fetchAll(PDO::FETCH_ASSOC);
// mescole associate
$stmt = $pdo->prepare("SELECT idmescola FROM matrice_mescole WHERE idmatrice = ?");
$stmt->execute([$idMatrice]);
$associate = $stmt->fetchAll(PDO::FETCH_COLUMN);
echo json_encode([
'success' => true,
'tutte' => $tutte,
'associate' => $associate
]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
-37
View File
@@ -1,37 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__FILE__) . '/class/VisualLimsApiClientXml.class.php';
header('Content-Type: application/xml; charset=utf-8');
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClientXml::getInstance();
// Endpoint per i metadata
$endpoint = '$metadata';
// Nessun parametro aggiuntivo necessario
$options = [];
// Debug: salva URL usato
$base_url = 'https://93.43.5.102/limsapi/api/odata/';
$query = http_build_query($options);
$full_url = $base_url . $endpoint . ($query ? '?' . $query : '');
file_put_contents(__DIR__ . '/last_url.txt', $full_url . PHP_EOL, FILE_APPEND);
// Chiamata API
$data = $api->get($endpoint, $options);
// Salva il file XML in locale
file_put_contents(__DIR__ . '/metadata_response.xml', $data);
// Restituisci il contenuto XML
echo $data;
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
http_response_code(500);
echo '<?xml version="1.0" encoding="utf-8"?><error>' . htmlspecialchars($e->getMessage()) . '</error>';
}
@@ -0,0 +1,30 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json');
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid id']);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$sql = "SELECT
psl.id,
psl.idsupplier,
s.supplier_name,
psl.lot_code,
psl.expiry_date,
psl.qty
FROM packaging_stock_lots psl
INNER JOIN suppliers s ON s.idsupplier = psl.idsupplier
WHERE psl.idpackaging_item = ?
ORDER BY psl.id DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'rows' => $rows]);
+42
View File
@@ -0,0 +1,42 @@
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
header('Content-Type: application/json');
include('include/headscript.php');
try {
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid parameter id.']);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare("
SELECT id, line_id, position, short_label, label, icon
FROM production_line_params
WHERE id = :id
");
$stmt->execute([':id' => $id]);
$param = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$param) {
echo json_encode(['success' => false, 'message' => 'Parameter not found.']);
exit;
}
echo json_encode([
'success' => true,
'param' => $param
]);
} catch (Exception $e) {
echo json_encode([
'success' => false,
'message' => 'Server error: ' . $e->getMessage()
]);
}
+55
View File
@@ -0,0 +1,55 @@
<?php
header('Content-Type: application/json');
require_once __DIR__ . '/class/db-functions.php';
try {
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$production_id = isset($_GET['production_id']) ? (int)$_GET['production_id'] : 0;
$photo_type = $_GET['photo_type'] ?? '';
$slot = isset($_GET['param_position']) ? (int)$_GET['param_position'] : null;
if ($production_id <= 0 || $photo_type === '') {
throw new Exception("Parametri non validi");
}
// QUERY BASE
$sql = "
SELECT id, filename, photo_type, created_at, elaborato
FROM production_photos
WHERE production_id = :prod
AND photo_type = :ptype
";
// SE È PARAMETRO MACCHINA → FILTRO PER POSIZIONE
if ($photo_type === 'parametri_macchina') {
$sql .= " AND param_position = :slot";
}
$sql .= " ORDER BY created_at DESC, id DESC";
$stmt = $pdo->prepare($sql);
$params = [
':prod' => $production_id,
':ptype' => $photo_type
];
if ($photo_type === 'parametri_macchina') {
$params[':slot'] = $slot;
}
$stmt->execute($params);
$photos = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode([
'success' => true,
'photos' => $photos
]);
} catch (Exception $e) {
echo json_encode([
'success' => false,
'message' => $e->getMessage()
]);
}
-26
View File
@@ -1,26 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
$rapporto_id = 533329;
// Costruzione manuale dell'endpoint con espansione annidata
$endpoint = "Rapporto($rapporto_id)?\$expand=CampioniDatiRapporto(\$expand=AnalisiDatiRapporto,CustomFieldsDatiRapporto)";
// Non passiamo options, già incluso nell'endpoint
$data = $api->get($endpoint);
file_put_contents(__DIR__ . '/rapporto_expanded.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
echo json_encode($data);
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
-30
View File
@@ -1,30 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
// ID dello schema passato via GET o default 45
$schemaId = isset($_GET['id']) && is_numeric($_GET['id']) ? intval($_GET['id']) : 42;
// IMPORTANTE: $expand va dentro la stringa endpoint per entità singola
$endpoint = "SchemaCustomField($schemaId)?\$expand=SchemiCustomFieldsDettagli(\$expand=CustomField)";
// Nessun parametro aggiuntivo
$data = $api->get($endpoint);
// Salva la risposta per debug
file_put_contents(__DIR__ . '/schema_dettagli_response.json', json_encode($data));
echo json_encode($data);
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'error' => $e->getMessage()
]);
}
-36
View File
@@ -1,36 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
// Nessun filtro o espansione: solo la lista degli schemi
$endpoint = 'SchemaCustomField';
// (Opzionale) aggiungi $top se vuoi limitare i risultati
$options = []; // oppure ad esempio: ['$top' => 100]
// Debug: salva URL usato
$base_url = 'https://93.43.5.102/limsapi/api/odata/';
$query = http_build_query($options);
$full_url = $base_url . $endpoint . ($query ? '?' . $query : '');
file_put_contents(__DIR__ . '/last_url.txt', $full_url . PHP_EOL, FILE_APPEND);
// Chiamata API
$data = $api->get($endpoint, $options);
// Salva il JSON in locale
file_put_contents(__DIR__ . '/schemi_base_response.json', json_encode($data, JSON_PRETTY_PRINT));
echo json_encode($data);
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
@@ -1,26 +0,0 @@
```php
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php'; // Torna al livello di public per trovare vendor/
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
// Disabilita la visualizzazione degli errori PHP per evitare output HTML
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
$data = $api->get("SchemaCustomField"); // Recupera la lista degli schemi custom fields
// Salva la risposta in un file per debug
file_put_contents(__DIR__ . '/schemi_custom_fields_response.json', json_encode($data));
echo json_encode($data);
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'error' => $e->getMessage()
]);
}
?>
+11
View File
@@ -0,0 +1,11 @@
<?php
include('include/headscript.php');
header('Content-Type: application/json');
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->query("SELECT idsupplier, supplier_name FROM suppliers ORDER BY supplier_name ASC");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'rows' => $rows]);
File diff suppressed because it is too large Load Diff
-153
View File
@@ -1,153 +0,0 @@
<?php include('include/headscript.php'); ?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
<?php include('cssinclude.php'); ?>
<title>Template Buttons - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
<style>
/* Layout flessibile per gestire dimensioni diverse */
#templateButtons {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: flex-start;
/* Allinea a sinistra */
padding: 20px;
}
/* Definizione delle dimensioni */
/* Definizione delle dimensioni */
.btn-small {
font-size: 12px;
padding: 6px 12px;
min-width: 100px;
min-height: 30px;
display: flex;
/* Aggiunto */
justify-content: center;
/* Aggiunto */
align-items: center;
/* Aggiunto */
}
.btn-medium {
font-size: 16px;
padding: 10px 20px;
min-width: 130px;
min-height: 45px;
display: flex;
/* Aggiunto */
justify-content: center;
/* Aggiunto */
align-items: center;
/* Aggiunto */
}
.btn-large {
font-size: 20px;
padding: 14px 28px;
min-width: 180px;
min-height: 60px;
display: flex;
/* Aggiunto */
justify-content: center;
/* Aggiunto */
align-items: center;
/* Aggiunto */
}
/* Stile della barra di ricerca */
#searchInput {
width: 100%;
padding: 10px;
font-size: 16px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="wrapper">
<?php include('include/navbar.php'); ?>
<?php include('include/topbar.php'); ?>
<div class="page-wrapper">
<div class="page-content">
<?php include('top_stat_widget.php'); ?>
<div class="card radius-10">
<div class="card-header">
<h6 class="mb-0">Active Templates</h6>
</div>
<div class="card-body">
<!-- Barra di ricerca -->
<input type="text" id="searchInput" placeholder="Search template...">
<div id="templateButtons"></div>
</div>
</div>
</div>
</div>
<div class="overlay toggle-icon"></div>
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
<?php include('include/footer.php'); ?>
</div>
<?php include('jsinclude.php'); ?>
<script>
document.addEventListener("DOMContentLoaded", function() {
fetch("load_active_templates.php")
.then(response => response.json())
.then(data => {
if (!data.success) {
console.error("Error loading templates:", data.message);
return;
}
let templateButtons = document.getElementById("templateButtons");
templateButtons.innerHTML = '';
data.data.forEach(template => {
let sizeClass = "btn-medium"; // Default
if (template.button_size === "small") sizeClass = "btn-small";
if (template.button_size === "large") sizeClass = "btn-large";
let btn = document.createElement("a");
btn.href = `import_xls2.php?id=${template.id}`;
btn.className = `btn ${sizeClass}`;
btn.style.backgroundColor = template.button_bg_color;
btn.style.color = template.button_text_color;
btn.textContent = template.button_label;
btn.setAttribute("data-label", template.button_label.toLowerCase()); // Attributo per ricerca
templateButtons.appendChild(btn);
});
})
.catch(error => console.error("Fetch error:", error));
// Funzione per la ricerca live
document.getElementById("searchInput").addEventListener("input", function() {
let searchValue = this.value.toLowerCase();
document.querySelectorAll("#templateButtons a").forEach(btn => {
let label = btn.getAttribute("data-label");
if (label.includes(searchValue)) {
btn.style.display = "inline-block";
} else {
btn.style.display = "none";
}
});
});
});
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-166
View File
@@ -1,166 +0,0 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/import_debug.log');
if (!file_exists(__DIR__ . '/import_debug.log')) {
file_put_contents(__DIR__ . '/import_debug.log', "Inizio importazione alle " . date('Y-m-d H:i:s') . "\n", FILE_APPEND);
}
// Log iniziale
error_log("Inizio importazione alle " . date('Y-m-d H:i:s'));
include('include/headscript.php');
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['template_id']) || !isset($_POST['selected_rows']) || !isset($_POST['filename'])) {
header("Location: xlstemplates_grid.php?status=error&message=" . urlencode("Richiesta non valida"));
exit;
}
$template_id = intval($_POST['template_id']);
$selected_rows = array_map('intval', $_POST['selected_rows']);
$columns = json_decode($_POST['columns'], true);
$rows = json_decode($_POST['rows'], true);
$excelrows = json_decode($_POST['excelrows'], true);
$newFilename = htmlspecialchars($_POST['filename']);
$_SESSION['template_id'] = $template_id;
$_SESSION['selected_rows'] = $selected_rows;
$_SESSION['columns'] = $columns;
$_SESSION['rows'] = $rows;
$_SESSION['excelrows'] = $excelrows;
$_SESSION['filename'] = $newFilename;
error_log("Received Data - Template ID: $template_id, Selected Rows: " . json_encode($selected_rows));
error_log("Columns: " . json_encode($columns));
error_log("Rows: " . json_encode($rows));
error_log("Excelrows: " . json_encode($excelrows));
$user_id = $iduserlogin ?? 1;
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Genera un UUID univoco per importreferencecode
$importReferenceCode = date('YmdHis') . '-' . uniqid();
// Recupera tutti i mapping dal template
$stmt = $pdo->prepare("SELECT id, excel_column, data_type, is_required, manual_default, is_manual, field_label, field_id, main_field FROM template_mapping WHERE template_id = ?");
$stmt->execute([$template_id]);
$allMappings = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($allMappings)) {
header("Location: import_xls.php?id=$template_id&status=error&message=" . urlencode("Nessun mapping trovato per il template"));
exit;
}
// Trova il campo main_field
$mainFieldMapping = null;
foreach ($allMappings as $mapping) {
if ($mapping['main_field'] == 1) {
$mainFieldMapping = $mapping;
break;
}
}
// Inserisci le righe selezionate in datadb
$insertedIds = [];
foreach ($selected_rows as $rowIndex) {
$row = $rows[$rowIndex] ?? null;
$excelrow = $excelrows[$rowIndex] ?? null;
if ($row === null || $excelrow === null) {
error_log("Errore: riga o excelrow mancante per rowIndex $rowIndex");
continue;
}
$values = [
$template_id,
$importReferenceCode,
$newFilename,
'i',
$user_id,
null,
date('Y-m-d'),
$excelrow // Aggiunto excelrow per la colonna excelrow
];
$sql = "INSERT INTO datadb (templateid, importreferencecode, filename_import, status, user_id, limscode, importdate, excelrow) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute($values);
$iddatadb = $pdo->lastInsertId();
$insertedIds[] = $iddatadb;
// Inserisci tutti i campi in import_data_details
foreach ($allMappings as $mapping) {
$fieldValue = null;
if (!$mapping['is_manual']) {
$excelColumn = trim($mapping['excel_column']);
$excelColumnIndex = array_search($excelColumn, array_map('trim', $columns));
if ($excelColumnIndex !== false && isset($row[$excelColumnIndex]) && $row[$excelColumnIndex] !== '') {
$fieldValue = $row[$excelColumnIndex];
error_log("Found Excel column '$excelColumn' at index $excelColumnIndex, value: " . var_export($fieldValue, true));
} else {
$fieldValue = $mapping['manual_default'] ?? '';
error_log("Excel column '$excelColumn' not found or empty, using default: " . var_export($fieldValue, true));
}
switch ($mapping['data_type']) {
case 'INT':
$fieldValue = is_numeric($fieldValue) ? (int)$fieldValue : ($mapping['manual_default'] ?? 0);
break;
case 'DATE':
$fieldValue = !empty($fieldValue) ? date('Y-m-d', strtotime($fieldValue)) : ($mapping['manual_default'] === 'today' ? date('Y-m-d') : ($mapping['manual_default'] ?? ''));
break;
case 'CHAR':
$fieldValue = !empty($fieldValue) ? substr((string)$fieldValue, 0, 1) : ($mapping['manual_default'] ?? '');
break;
case 'Testo':
case 'VARCHAR':
default:
$fieldValue = !empty($fieldValue) ? htmlspecialchars((string)$fieldValue) : ($mapping['manual_default'] ?? '');
break;
}
} else {
$fieldValue = $mapping['manual_default'] ?? '';
if ($mapping['data_type'] === 'DATE' && $mapping['manual_default'] === 'today') {
$fieldValue = date('Y-m-d');
}
}
if ($mapping['is_required'] && (is_null($fieldValue) || $fieldValue === '')) {
error_log("Required field missing for mapping ID: " . $mapping['id'] . ", field: " . $mapping['field_label']);
}
error_log("Inserting into import_data_details - Mapping ID: " . $mapping['id'] . ", Field Value: " . var_export($fieldValue, true) . ", Is Manual: " . $mapping['is_manual'] . ", Excel Column: " . ($mapping['excel_column'] ?? 'N/A') . ", Manual Default: " . ($mapping['manual_default'] ?? 'N/A'));
$stmt = $pdo->prepare("INSERT INTO import_data_details (id, mapping_id, field_value) VALUES (?, ?, ?)");
$stmt->execute([$iddatadb, $mapping['id'], $fieldValue]);
error_log("Inserted into import_data_details for ID $iddatadb, Mapping ID: " . $mapping['id'] . ", Field Value: " . var_export($fieldValue, true));
}
}
$_SESSION['inserted_ids'] = $insertedIds;
$params = [
'template_id' => $template_id,
'filename' => $newFilename,
];
?>
<form id="redirectForm" action="import_edit2.php" method="post">
<input type="hidden" name="template_id" value="<?= htmlspecialchars($template_id) ?>">
<input type="hidden" name="filename" value="<?= htmlspecialchars($newFilename) ?>">
<?php foreach ($selected_rows as $row): ?>
<input type="hidden" name="selected_rows[]" value="<?= htmlspecialchars($row) ?>">
<?php endforeach; ?>
<?php foreach ($insertedIds as $id): ?>
<input type="hidden" name="inserted_ids[]" value="<?= htmlspecialchars($id) ?>">
<?php endforeach; ?>
<input type="hidden" name="columns" value='<?= json_encode($columns) ?>'>
<input type="hidden" name="rows" value='<?= json_encode($rows) ?>'>
<input type="hidden" name="excelrows" value='<?= json_encode($excelrows) ?>'>
</form>
<script>
document.getElementById('redirectForm').submit();
</script>
<?php
exit;
?>
-305
View File
@@ -1,305 +0,0 @@
<?php
include('include/headscript.php');
// Controlla se è stato passato un ID valido
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
header("Location: xlstemplates_grid.php?status=error&message=" . urlencode("Invalid ID"));
exit;
}
$id = intval($_GET['id']); // Sanifica l'ID
// Recupera il template dal database
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare("SELECT * FROM excel_templates WHERE id = ?");
$stmt->execute([$id]);
$template = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$template) {
header("Location: template_dashboard.php?status=error&message=" . urlencode("Template not found"));
exit;
}
// Debug del template
error_log("Loaded template: " . print_r($template, true));
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
<?php include('cssinclude.php'); ?>
<style>
.table-container {
overflow-x: auto;
max-width: 100%;
margin-bottom: 20px;
}
.table {
width: 100%;
border-collapse: collapse;
}
.table th,
.table td {
padding: 10px;
text-align: left;
border: 1px solid #dee2e6;
min-width: 100px;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.table th:first-child,
.table td:first-child {
min-width: 50px;
max-width: 50px;
}
.table th {
background-color: #f8f9fa;
position: relative;
cursor: col-resize;
user-select: none;
}
.table th .resize-handle {
position: absolute;
top: 0;
right: 0;
width: 5px;
height: 100%;
cursor: col-resize;
background: transparent;
}
.table th .resize-handle:hover {
background: #007bff;
}
.search-container {
margin-bottom: 20px;
}
.search-container input {
width: 300px;
padding: 8px;
border: 1px solid #ced4da;
border-radius: 5px;
}
.loader {
display: none;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 10px auto;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<title><?= htmlspecialchars($template['name']) ?> - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
</head>
<body>
<div class="wrapper">
<?php include('include/navbar.php'); ?>
<?php include('include/topbar.php'); ?>
<div class="page-wrapper">
<div class="page-content">
<?php include('top_stat_widget.php'); ?>
<div class="card radius-10">
<div class="card-header">
<div class="d-flex align-items-center">
<div>
<h6 class="mb-0"><?= htmlspecialchars($template['name']) ?></h6>
<small>Template ID: <?= $id ?>, Start Row: <?= $template['header_row'] ?>, Start Column: <?= $template['start_column'] ?></small>
</div>
</div>
</div>
<div class="card-body">
<!-- Form per caricare il file -->
<form id="uploadForm" enctype="multipart/form-data" class="mb-4">
<div class="mb-3">
<label for="excel_file" class="form-label">Upload XLS File</label>
<input type="file" class="form-control" id="excel_file" name="excel_file" accept=".xls,.xlsx" required>
</div>
<button type="submit" class="btn btn-primary">Upload</button>
<div class="loader" id="loader"></div>
</form>
<!-- Contenitore per messaggi di errore -->
<div id="errorContainer" class="alert alert-danger mt-3" style="display: none;"></div>
<!-- Contenitore per la tabella -->
<div id="tableContainer"></div>
</div>
</div>
</div>
</div>
<!--end page wrapper -->
<div class="overlay toggle-icon"></div>
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
<?php include('include/footer.php'); ?>
</div>
<!--end wrapper-->
<!-- search modal -->
<?php //include('include/searchmodal.php');
?>
<!-- end search modal -->
<!--start switcher-->
<?php //include('include/themeswitcher.php');
?>
<!--end switcher-->
<?php include('jsinclude.php'); ?>
<script>
document.addEventListener("DOMContentLoaded", function() {
const form = document.getElementById('uploadForm');
const loader = document.getElementById('loader');
const errorContainer = document.getElementById('errorContainer');
const tableContainer = document.getElementById('tableContainer');
form.addEventListener('submit', function(e) {
e.preventDefault();
loader.style.display = 'block';
errorContainer.style.display = 'none';
tableContainer.innerHTML = '';
const formData = new FormData(this);
formData.append('template_id', <?= $id ?>);
formData.append('header_row', <?= $template['header_row'] ?>);
formData.append('start_column', <?= $template['start_column'] ?>);
fetch('process_import_xls.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
loader.style.display = 'none';
if (data.error) {
errorContainer.textContent = data.error;
errorContainer.style.display = 'block';
} else {
let html = `
<form id="selectRowsForm" action="import_edit.php" method="POST">
<input type="hidden" name="template_id" value="${data.template_id}">
<input type="hidden" name="columns" value='${JSON.stringify(data.columns)}'>
<input type="hidden" name="rows" value='${JSON.stringify(data.rows)}'>
<input type="hidden" name="filename" value="${data.filename}">
<div class="search-container">
<input type="text" id="searchInput" class="form-control" placeholder="Cerca nelle righe...">
</div>
<div class="table-container">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Seleziona</th>
${data.columns.map(col => `<th>${col || 'Colonna senza nome'}<div class="resize-handle"></div></th>`).join('')}
</tr>
</thead>
<tbody>
${data.rows.map((row, index) => `
<tr>
<td><input type="checkbox" class="row-checkbox" name="selected_rows[]" value="${index}"></td>
${row.map(cell => `<td>${cell}</td>`).join('')}
</tr>
`).join('')}
</tbody>
</table>
</div>
<button type="submit" class="btn btn-primary mt-3" id="proceedButton" disabled>Prosegui</button>
</form>
`;
tableContainer.innerHTML = html;
// Aggiungi logica per il ridimensionamento delle colonne
const thElements = document.querySelectorAll('.table th');
thElements.forEach((th, index) => {
if (index === 0) return; // Escludi la colonna "Seleziona" dal ridimensionamento
const resizeHandle = th.querySelector('.resize-handle');
if (resizeHandle) {
resizeHandle.addEventListener('mousedown', (e) => {
e.preventDefault();
const startX = e.clientX;
const startWidth = th.offsetWidth;
const onMouseMove = (e) => {
const newWidth = Math.max(50, startWidth + (e.clientX - startX));
th.style.width = `${newWidth}px`;
th.style.minWidth = `${newWidth}px`;
th.style.maxWidth = `${newWidth}px`;
const cells = document.querySelectorAll(`.table td:nth-child(${index + 1})`);
cells.forEach(cell => {
cell.style.width = `${newWidth}px`;
cell.style.minWidth = `${newWidth}px`;
cell.style.maxWidth = `${newWidth}px`;
});
};
const onMouseUp = () => {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
}
});
// Aggiungi event listener per la ricerca
const searchInput = document.getElementById('searchInput');
const rows = document.querySelectorAll('.table tbody tr');
const checkboxes = document.querySelectorAll('.row-checkbox');
const proceedButton = document.getElementById('proceedButton');
searchInput.addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
rows.forEach(row => {
const text = Array.from(row.cells).slice(1).map(cell => cell.textContent.toLowerCase()).join(' ');
row.style.display = text.includes(searchTerm) ? '' : 'none';
});
});
// Aggiungi event listener per i checkbox
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
proceedButton.disabled = !Array.from(checkboxes).some(cb => cb.checked);
});
});
}
})
.catch(error => {
loader.style.display = 'none';
errorContainer.textContent = 'Errore durante il caricamento del file: ' + error.message;
errorContainer.style.display = 'block';
});
});
});
</script>
</body>
</html>
-413
View File
@@ -1,413 +0,0 @@
<?php
include('include/headscript.php');
// Controlla se è stato passato un ID valido
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
header("Location: xlstemplates_grid.php?status=error&message=" . urlencode("Invalid ID"));
exit;
}
$id = intval($_GET['id']); // Sanifica l'ID
// Recupera il template dal database
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare("SELECT * FROM excel_templates WHERE id = ?");
$stmt->execute([$id]);
$template = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$template) {
header("Location: template_dashboard.php?status=error&message=" . urlencode("Template not found"));
exit;
}
// Verifica i mapping
$stmt = $pdo->prepare("SELECT id FROM template_mapping WHERE template_id = ?");
$stmt->execute([$id]);
$hasMappings = $stmt->fetch(PDO::FETCH_ASSOC);
// Debug del template
error_log("Loaded template: " . print_r($template, true));
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
<?php include('cssinclude.php'); ?>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.table-container {
overflow-x: auto;
max-width: 100%;
margin-bottom: 20px;
}
.table {
width: 100%;
border-collapse: collapse;
}
.table th,
.table td {
padding: 10px;
text-align: left;
border: 1px solid #dee2e6;
min-width: 100px;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.table th:first-child,
.table td:first-child {
min-width: 50px;
max-width: 50px;
}
.table th {
background-color: #f8f9fa;
position: relative;
cursor: col-resize;
user-select: none;
}
.table th .resize-handle {
position: absolute;
top: 0;
right: 0;
width: 5px;
height: 100%;
cursor: col-resize;
background: transparent;
}
.table th .resize-handle:hover {
background: #007bff;
}
.search-container {
margin-bottom: 20px;
}
.search-container input {
width: 300px;
padding: 8px;
border: 1px solid #ced4da;
border-radius: 5px;
}
.loader {
display: none;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 10px auto;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<title><?= htmlspecialchars($template['name']) ?> - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
</head>
<body>
<div class="wrapper">
<?php include('include/navbar.php'); ?>
<?php include('include/topbar.php'); ?>
<div class="page-wrapper">
<div class="page-content">
<?php include('top_stat_widget.php'); ?>
<div class="mb-3 text">
<a href="historical_trf.php?id=<?= $id ?>&status=i" class="btn btn-warning me-2">Imported (i)</a>
<a href="historical_trf.php?id=<?= $id ?>&status=P" class="btn btn-primary me-2">In Progress (P)</a>
<a href="historical_trf.php?id=<?= $id ?>&status=l" class="btn btn-success">To LIMS (l)</a>
</div>
<div class="card radius-10">
<div class="card-header">
<div class="d-flex align-items-center">
<div>
<h6 class="mb-0"><?= htmlspecialchars($template['name']) ?></h6>
<small>Template ID: <?= $id ?>, Start Row: <?= $template['header_row'] ?>, Start Column: <?= $template['start_column'] ?></small>
</div>
</div>
</div>
<div class="card-body">
<?php if (!$hasMappings): ?>
<div class="alert alert-warning" role="alert">
Nessun mapping trovato per questo template. Configura i mapping prima di procedere.
</div>
<?php endif; ?>
<form id="uploadForm" enctype="multipart/form-data" class="mb-4">
<div class="mb-3">
<label for="excel_file" class="form-label">Upload XLS File</label>
<input type="file" class="form-control" id="excel_file" name="excel_file" accept=".xls,.xlsx" required>
</div>
<button type="submit" class="btn btn-primary" <?= !$hasMappings ? 'disabled' : '' ?>>Upload</button>
<div class="loader" id="loader"></div>
</form>
<div id="errorContainer" class="alert alert-danger mt-3" style="display: none;"></div>
<div id="tableContainer"></div>
<div class="modal fade" id="routineConfirmModal" tabindex="-1" aria-labelledby="routineConfirmModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="routineConfirmModalLabel">Conferma Applicazione Routine</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p><strong>Routine:</strong> <span id="routineName"></span></p>
<p><strong>Descrizione:</strong> <span id="routineDescription"></span></p>
<p>Vuoi applicare questa routine al file caricato?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="cancelRoutineBtn">Annulla</button>
<button type="button" class="btn btn-primary" id="confirmRoutineBtn">Applica</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="overlay toggle-icon"></div>
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
<?php include('include/footer.php'); ?>
</div>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.min.js"></script>
<?php include('jsinclude.php'); ?>
<script>
document.addEventListener("DOMContentLoaded", function() {
const form = document.getElementById('uploadForm');
const loader = document.getElementById('loader');
const errorContainer = document.getElementById('errorContainer');
const tableContainer = document.getElementById('tableContainer');
const routineModal = new bootstrap.Modal(document.getElementById('routineConfirmModal'));
const confirmRoutineBtn = document.getElementById('confirmRoutineBtn');
const cancelRoutineBtn = document.getElementById('cancelRoutineBtn');
let routineData = null;
let excelData = null;
let responseData = null;
form.addEventListener('submit', function(e) {
e.preventDefault();
loader.style.display = 'block';
errorContainer.style.display = 'none';
tableContainer.innerHTML = '';
const formData = new FormData(this);
const templateId = <?= $id ?>;
console.log('Template ID passed to formData:', templateId);
formData.append('template_id', templateId);
formData.append('header_row', <?= $template['header_row'] ?>);
formData.append('start_column', <?= $template['start_column'] ?>);
fetch('process_import_xls2.php', {
method: 'POST',
body: formData
})
.then(response => {
console.log('Stato risposta:', response.status);
return response.json();
})
.then(data => {
console.log('Risposta JSON:', data);
loader.style.display = 'none';
if (data.error) {
errorContainer.textContent = data.error;
errorContainer.style.display = 'block';
} else if (data.apply_routine) {
console.log('Routine rilevata:', data.routine_data);
routineData = data.routine_data;
excelData = data.excel_data;
responseData = data;
document.getElementById('routineName').textContent = routineData.name || 'Sconosciuta';
document.getElementById('routineDescription').textContent = routineData.instruction || 'Nessuna descrizione';
routineModal.show();
} else {
console.log('Nessuna routine, procedo con tabella');
showTable(data);
}
})
.catch(error => {
console.log('Errore fetch:', error);
loader.style.display = 'none';
errorContainer.textContent = 'Errore durante il caricamento del file: ' + error.message;
errorContainer.style.display = 'block';
});
});
confirmRoutineBtn.addEventListener('click', function() {
console.log('Conferma routine:', routineData);
routineModal.hide();
fetch('apply_routine.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
template_id: <?= $id ?>,
filename: routineData.filename,
headerrow: routineData.headerrow,
excel_data: excelData,
routine_data: routineData
})
})
.then(response => {
console.log('Stato apply_routine:', response.status);
return response.json();
})
.then(data => {
console.log('Risposta apply_routine:', data);
if (data.error) {
errorContainer.textContent = data.error;
errorContainer.style.display = 'block';
} else {
showTable(data);
}
})
.catch(error => {
console.log('Errore apply_routine:', error);
errorContainer.textContent = 'Errore durante l\'applicazione della routine: ' + error.message;
errorContainer.style.display = 'block';
});
});
cancelRoutineBtn.addEventListener('click', function() {
console.log('Routine annullata, procedo con tabella');
routineModal.hide();
showTable(responseData);
});
function showTable(data) {
console.log('Mostro tabella con dati:', data);
let html = `
<form id="selectRowsForm" action="import_insert.php" method="POST">
<input type="hidden" name="template_id" value="${data.template_id}">
<input type="hidden" name="columns" value='${JSON.stringify(data.columns)}'>
<input type="hidden" name="rows" value='${JSON.stringify(data.rows)}'>
<input type="hidden" name="excelrows" value='${JSON.stringify(data.excel_data.map(row => row.excelrow))}'>
<input type="hidden" name="filename" value="${data.filename}">
<div class="search-container">
<input type="text" id="searchInput" class="form-control" placeholder="Cerca nelle righe...">
</div>
<div class="table-container">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th><input type="checkbox" id="selectAll"> Seleziona</th>
${data.columns.map(col => `<th>${col || 'Colonna senza nome'}<div class="resize-handle"></div></th>`).join('')}
</tr>
</thead>
<tbody>
${data.excel_data.map((row, index) => `
<tr>
<td><input type="checkbox" class="row-checkbox" name="selected_rows[]" value="${index}" data-excelrow="${row.excelrow}"></td>
${row.data.map(cell => `<td>${cell}</td>`).join('')}
</tr>
`).join('')}
</tbody>
</table>
</div>
<button type="submit" class="btn btn-primary mt-3" id="proceedButton" disabled>Prosegui</button>
</form>
`;
tableContainer.innerHTML = html;
const proceedButton = document.getElementById('proceedButton');
const selectAllCheckbox = document.getElementById('selectAll');
const checkboxes = document.querySelectorAll('.row-checkbox');
function updateProceedButton() {
proceedButton.disabled = !Array.from(checkboxes).some(cb => cb.checked);
}
selectAllCheckbox.addEventListener('change', function() {
checkboxes.forEach(checkbox => {
checkbox.checked = this.checked;
});
updateProceedButton();
});
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
console.log('Checkbox changed, checked:', this.checked, 'excelrow:', this.dataset.excelrow);
selectAllCheckbox.checked = Array.from(checkboxes).every(cb => cb.checked);
updateProceedButton();
});
});
const thElements = document.querySelectorAll('.table th');
thElements.forEach((th, index) => {
if (index === 0) return;
const resizeHandle = th.querySelector('.resize-handle');
if (resizeHandle) {
resizeHandle.addEventListener('mousedown', (e) => {
e.preventDefault();
const startX = e.clientX;
const startWidth = th.offsetWidth;
const onMouseMove = (e) => {
const newWidth = Math.max(50, startWidth + (e.clientX - startX));
th.style.width = `${newWidth}px`;
th.style.minWidth = `${newWidth}px`;
th.style.maxWidth = `${newWidth}px`;
const cells = document.querySelectorAll(`.table td:nth-child(${index + 1})`);
cells.forEach(cell => {
cell.style.width = `${newWidth}px`;
cell.style.minWidth = `${newWidth}px`;
cell.style.maxWidth = `${newWidth}px`;
});
};
const onMouseUp = () => {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
}
});
const searchInput = document.getElementById('searchInput');
const rows = document.querySelectorAll('.table tbody tr');
searchInput.addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
rows.forEach(row => {
const text = Array.from(row.cells).slice(1).map(cell => cell.textContent.toLowerCase()).join(' ');
row.style.display = text.includes(searchTerm) ? '' : 'none';
});
});
updateProceedButton();
}
});
</script>
</body>
</html>

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