From 8806d598eb3d1d2e560c578bf82e5edf1f16602a Mon Sep 17 00:00:00 2001 From: allebonvi Date: Mon, 27 Oct 2025 17:18:09 +0100 Subject: [PATCH] chore: initial commit --- .idea/.gitignore | 8 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 10 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/warehouse.iml | 12 + .../async_loop_singleton.cpython-313.pyc | Bin 0 -> 2479 bytes .../async_msssql_query.cpython-313.pyc | Bin 0 -> 7686 bytes __pycache__/async_runner.cpython-313.pyc | Bin 0 -> 2126 bytes .../db_async_singleton.cpython-313.pyc | Bin 0 -> 2441 bytes .../gestione_aree_frame_async.cpython-313.pyc | Bin 0 -> 9672 bytes .../gestione_pickinglist.cpython-313.pyc | Bin 0 -> 39576 bytes __pycache__/layout_window.cpython-313.pyc | Bin 0 -> 41659 bytes .../prenota_sprenota_sql.cpython-313.pyc | Bin 0 -> 8505 bytes __pycache__/reset_corsie.cpython-313.pyc | Bin 0 -> 16364 bytes __pycache__/search_pallets.cpython-313.pyc | Bin 0 -> 22680 bytes .../view_celle_multiple.cpython-313.pyc | Bin 0 -> 26565 bytes .../Font Awesome 7 Brands-Regular-400.otf | Bin 0 -> 199352 bytes .../fonts/Font Awesome 7 Free-Regular-400.otf | Bin 0 -> 87332 bytes .../fonts/Font Awesome 7 Free-Solid-900.otf | Bin 0 -> 410580 bytes assets/icons/home.png | Bin 0 -> 3699 bytes async_loop_singleton.py | 35 + async_msssql_query.py | 93 + async_runner.py | 25 + backups/autosave.tcl.bak1 | 148 + backups/autosave.tcl.bak2 | 148 + baseline_Mediseawall.json | 4 + db_async_singleton.py | 33 + fix_layout_window.py | 40 + fix_query.py | 87 + gestione_aree_frame_async.py | 170 + gestione_pickinglist.py | 668 ++++ layout_window.py | 670 ++++ layout_window.py.bak_fix_bc_transparent | 633 ++++ layout_window.py.bak_perf | 632 ++++ main.py | 156 + pickinglist.sql | 62 + prenota_sprenota_sql.py | 189 + pyproject.toml | 16 + readme.txt | 50 + reset_corsie.py | 245 ++ riassunto_ricerca_udc_20251005.pdf | 68 + script.sql | Bin 0 -> 274924 bytes search_pallets.py | 453 +++ sql.txt | 21 + view_celle_multiple.py | 346 ++ warehouse_sp_python.py | 1712 +++++++++ warehouse_sql.log | 3270 +++++++++++++++++ 48 files changed, 10024 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/warehouse.iml create mode 100644 __pycache__/async_loop_singleton.cpython-313.pyc create mode 100644 __pycache__/async_msssql_query.cpython-313.pyc create mode 100644 __pycache__/async_runner.cpython-313.pyc create mode 100644 __pycache__/db_async_singleton.cpython-313.pyc create mode 100644 __pycache__/gestione_aree_frame_async.cpython-313.pyc create mode 100644 __pycache__/gestione_pickinglist.cpython-313.pyc create mode 100644 __pycache__/layout_window.cpython-313.pyc create mode 100644 __pycache__/prenota_sprenota_sql.cpython-313.pyc create mode 100644 __pycache__/reset_corsie.cpython-313.pyc create mode 100644 __pycache__/search_pallets.cpython-313.pyc create mode 100644 __pycache__/view_celle_multiple.cpython-313.pyc create mode 100644 assets/fonts/Font Awesome 7 Brands-Regular-400.otf create mode 100644 assets/fonts/Font Awesome 7 Free-Regular-400.otf create mode 100644 assets/fonts/Font Awesome 7 Free-Solid-900.otf create mode 100644 assets/icons/home.png create mode 100644 async_loop_singleton.py create mode 100644 async_msssql_query.py create mode 100644 async_runner.py create mode 100644 backups/autosave.tcl.bak1 create mode 100644 backups/autosave.tcl.bak2 create mode 100644 baseline_Mediseawall.json create mode 100644 db_async_singleton.py create mode 100644 fix_layout_window.py create mode 100644 fix_query.py create mode 100644 gestione_aree_frame_async.py create mode 100644 gestione_pickinglist.py create mode 100644 layout_window.py create mode 100644 layout_window.py.bak_fix_bc_transparent create mode 100644 layout_window.py.bak_perf create mode 100644 main.py create mode 100644 pickinglist.sql create mode 100644 prenota_sprenota_sql.py create mode 100644 pyproject.toml create mode 100644 readme.txt create mode 100644 reset_corsie.py create mode 100644 riassunto_ricerca_udc_20251005.pdf create mode 100644 script.sql create mode 100644 search_pallets.py create mode 100644 sql.txt create mode 100644 view_celle_multiple.py create mode 100644 warehouse_sp_python.py create mode 100644 warehouse_sql.log diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..2a6eac1 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..d6a57ee --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/warehouse.iml b/.idea/warehouse.iml new file mode 100644 index 0000000..460d402 --- /dev/null +++ b/.idea/warehouse.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/__pycache__/async_loop_singleton.cpython-313.pyc b/__pycache__/async_loop_singleton.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c366516ff43a5c7c5c9a919e86c141916f5e4d7a GIT binary patch literal 2479 zcma)8-A~(A6u*w0*dZaXt&l)g=CQV$J3ds}PV0)$SXFgvQ7XlBduX&PCzxPrYuk&8Tu6=dlX-!Os@PAMROA$C59Jw!^Q23fX=-^>FSKY7 zuFll@Ve^3G2>QZ8D#v&=1U3YfXW^otguNJ@vhBssZF5Fvdtta;Xy~E|^b}$yH5mxT zcY~O)3zp9v+%A$$F0&c(1QYCe5qFO1+6*`-IJ!CO;5FGhd+C$hjQ*`|<`$RTIorxD z<(4$2&)FqM&uPxGRiLO%9m6V`x@%h_i_4xwsbLu|rQWd?Uq>3J5wPrZ16d(E$5Qu% z_2^D-|2^S;tcG5)D3FX2K`WNFpo5hTN*C;zl8O5`rQeh^vo7hPbk<;wYZ{hr*_5&b zD0@AWI?Q}Q$>Htf@RQ`|y0{+SmAb0Zz_v8- zXz6kJVfm>vv?FzHMAxG0F%WIU*Wy)4u1NB4(xBgdx4Y`m4Cjl(h=pl|hxw#2@W2zW z^}Wc9rZ3o*BC)sOok4KX03k4myzphrfESteXBxu-cwv|c4D^>Y!&O4;UDT6-IEYU9 z(;(EYwjkMuAjApp)&605 zz3)_ePHy*{{CRro<1e<)wa1huQ z;^`Ow-K36fTQmTfqs{8@p>*xV09?YnZCI=q%r!qUUN_2HTZWy53j^?TG$7C@0hk_% zkK+&H)zoMuHCj!bsie*vw1rZUlwaQeb!c;_dirAJ^u?#rILZ=hiK>*YNa>#@0fH6j z)J`&uown0=d|kYs*pHIFv6Zs#iV|h`F9kaV1e$1h5#nJ8sNfrj?c=>MnRi^K6U{^<9e zE6GAQ?Bm$_?svcQKIePiCk}^=K>5p4Pp1C3hLHcjmr^n72>0aYfLtOHk+@+p#8J+J zxMA2p4eZHNfjy1X$et!@f+s(09OL3UW-KZpi?DR>{VmcE70wTD|;Fs+C0Sd(1$WHIdasa;zYdv&*3G zhc-?cR*~^~Gl__V6!+4=X0+%twvyn^39^fCB@>*l?knu(<1~9jQIe@hDxOr-ppV!1 zUgfkV1me+@X4yZ3ax=a9MH3^Y1p+u3m?S|3fRh4M?lnhuxnqU7^VBdxywL@PYPaW`}P6WW_ zgw_GjH%Hz0j>}{KYgHG3spb1 zV@IRm<0qpqA1fAsWft+mom?V^ek;U&) zA^tgPw`62g({t1*$;7DUG8N7$WErhw*W#=pbBV=3ip-}i-khL_5lXMz@0c=5yKP;=7A(#YyHw8xbzCAFi znWTYHd|Cp%2YUN@r2%c(0lXXi4*M%^h7auxX#AT81DbiDct_mM=a>`)u@glXnY4{~ z;BG?1O$LG2(r_y?t`O%0trjxCiujY{lF>u<)e>TdmXq8z9yE+W<8}pa0F!D4|0az) zu5l+-JWG$q!chNj>};XHjuTLs`z^n$!H{@?)I0PyaGK{1YZFQ zXWU&kH~g^k+U5%(xj+iA=X+_1QF&&f}T| z`bCaL;H?qnqfH2wBUpi;83C?TGaNsu2{^5a)(G}pEc*7H&+nP;fHq8ie;1H5WWh!n zns0d@b`1P*;FGP7c+U0~cc$;Z%=Rnw7mVi)KQz}|Idoy*;_`=P=QZ<%?H3&n&Gi?K zUXEXkUvu1F<}cWt=ey5!XWd=bSAXQa;r(z!&fS%>cirN%_MK+}1xNdbZ+|p?V?5sx z$aVyNav;|+lxZK%*hezL2-65iq@*CjH2PFDkb$83lUN= zGl+I|SzT6fiVzY;(cV;*ivDPbstT;UY|BeK@O;xsQP8SNNLcK3Xj7uRze)59Xb-fW zZ5~_eO`w5SfIWQb5zkuhw5+O;NqF%&Gy!!Dcnj?6%tfb06N^X~`A9Rvje@T;saYrG z)Ck~U1IK3trupZ*ITW+@9$e$~6z)7e@+W?fH>&BYCkcE4E$h zy)UjSG`DkI&iJ( z6KOwoH8XEEp44iAi^DXnD8SN;!71*M_9Ey*fX7Dz2=*b^13(kv%0yB##A7}K4I=db z02QyNWXheu$|`8lk_@%J$ePbJ*n|V90MMEj>^0|m&h=#NZ3WTwpk`UVX8paI^|>0~ zobaG=1M=72b9)PQ4VPD3T=C_ymck0pwKZ2-9@$MzHssm`Ct0})7#fDj+neFP%#kaz z;>t|R_J7!NEB5!@pNfG6o`|nJQ&C5r?Q`_ia4&c~j6MJAm#`=H`qkMJShB2?Vd7#L zA(1x5G$lgCbJSY#QbbGMIjxl4S|C=w6ZKUg6sORzbHRZ9uk%Vt@6%_SC9 zKwL&K@Te*hiV%m9XQddyST8X%5pa~C#S+4`ltGdBMU{_YVj;n^MN#<**%5+Jb1FV9 zC)26fnxas|;_3|8>zL2RM1dZJcJvSe!Zw1c(((cOJ+wR%ha`v^? z>+`-HS>KL(_8kS+vdirk+w-nrnpo12OE>U=(l;(QVun$5RjO7%YV%^_dH5SM-jJ3G_a&!v)K$1)S zU}W1E#zn0Bs`nZaIzWp_TnG3);2;)P2Jt_?2IPGY7j%Qve-6LDf#18UNITh!Cjq>o z>qHCWWy-e%oHt?ckXG1nLH#H(pPiXm$XuOBXeNk6BhxCCaR5VVlP2KU8V^c| z#@QlZnX1M?Y6h1X2K}XC3W2$dI?x?Qh-D#(rKiT4Ur2I)hH|>{&Q)3G zs+_YeZ)wX|+8#LS@{X2!j+UImGiNBc8!z`=XWi@bZr^>k@A`p4(<>i{?~8wN z;CkDiAO6_%WAWDNT+^<+YZs^__cCn%N4w_&58RDc_zx`aTYg~6x!dLfPtBx$0}Szh zaDz>sZSBrAZvX4R^%GZxtJ1alYbSm%{;y3NeiWD+%rtJF8~mBCBiHD^S%0nfs&M74 zKQrH`#|nR;x%GO}-G+Y=@`H!(4Ia)7j%CKbl^y(6=G(FCo>*pLGS@qmt%+wW@y89s zy5?tY-)F8}PkDV}m^5+3YlH#5A&+qa#+ZQ}a6Ot;NV zh_{N+=Ju;x-!{|jb`#>A;Hhx8yEv@f#_;W?{#x_x*SUU!c!!99-x1Bw29C5BCe&jd z7U}fkE4qX%=7IYCh_kFZi@t=T5Ph+roc;mS_`nmgPa5$EXhQstN91iUlb5$v(8!2cKqBVrW zDt-xyh9Pf3<43`6snC7{HbBpT*%6jmVW1UA>HvW6l1B#KXj!n3OLHK zIKVw_u^Trptgsu8ahZwZPYEImI$R+b*Jge@{FK1+2?BivOxySbilH<`_m6Fx-Ga|W zUqb>r?QLZYL+P&_<#UH4KcXjO&tntxKJ*?eHOmf?MOWrlJy~eHM;uwneJ08B9rvU%2$IKbTt6tOKW_GW%Kw`E0DhY_fh;&tIQr z>CqWxH+>(PfbAgaKLS|bIga~JviiTtt9kP3zms)YvhH*8+UI1==cIW-Fmi8j|0b+> zAcPh~(%q8@9WK;v%)EI34DKhwBeTfu;|evd1)d=-tBQ#4wIZ_TfR6lBtXVK(o1YHv z*O3JiaW*fo0RY`R$Q5x5F}TUcs8R7OPNAT&YRND7n`ED|Ao*qPNLn;m9nXLqNa&eS`z zE%m8S#wMCBk)}NOfG-L@k@%udihn^-NXtZtktgCywGfH=;JLH2?FKo?oO|v)_nvdl zIlp^mGnGmL((jLdt$xM%@sY530EJ~xKw-`Tp(A^id7CAy1U;|^6s`{xeu!=C zCR~M)g@<%9E;E66O1EvjXq!eu-QZ$0*}RCtGUS0U3J_Ld2&b@wSGc^8ZIAY}41=t~ z_rWAj;!3*`%Zo}JKQW(BgoAN_!I+Yu+DV2am1G}~Hl>ZUR|Gi~w2gZ6j*+c7j!7O0 zXz_z{W1d;5nNrP>^f}$~=@lifW=po~&PWy8E$X;nO2jg%mOiaZmSkWgMctT^EJsqO zq*+Us2K2ITl7WDyrwq*B7SU|b`R4P;mSLjP-cn6SHq)F`;07};vjOW*5exxjF5o@W zE(dXcN+Yi8hpQg7BuP^6+Nt4u$(%Lq{LH*xb)EcNeoiN5)vbAEUZ*i?Bn)z3WdvD{UV!x-y&uQdGd-UqHgOK)f#5otI~BxmFbN6b)28R?71M}O zbwpGSBm4@5WytZbMhd+TaF*SQFAl>0^^LXu;njV^ce;-LoZhvT z9{4dmaDDze`CIv?^qU`X>tg#-axqyye0BD&cz|@`VS@s_N%X~q)sisZ1t>5Dw!jtm zWl))CRca_Y*Q}O)2teJgFq&8SEVcI(HP1=#BDLIlgJ@@Sha;%$9z?`;{VSkCmfrIz z%F=W^MGBMSb4-rQu{jtN6c*pT*hB)Y@=I`G3oCKZu@+8D<7ja4-#XS40Fb}T!+vh3sE!HErpoBa26th8KtLckHaIE9Wnt zzj9%N)gH0U3KG1aw7(*ofO&e#rRTcF;y?F^_^brJAGGt>&c@y zWM0?=Ce?qhv%5}KlJ(?z`;LD$1YG&sdk(#Q-7|U!ZXHUVOmVl4iYG#iv}w0gv#H#!Y46u`JJNJ$TG=9=Z(}ELTvW$3t>hY-M!IR* zx<-qhPjtf{n>8K(9R3bS8rKPZBLRmhLVpB}4DHf1&)0p+&~)D?RLzH#B0KR;tRmGFWMcZaD@TB|1h8kra&^vTjL9cFcdV;JTEq7fK6rS1t#Ewbg1W*EaNok1F5NI1fB!HR_T0&Z@%HpC?e(BFUkHhDxK$yU-q zG@*@X;(o5Yl8G9fmNY3P_i>usMotS%(UcS!Yp%LjZ*i7ZmlFFVtv;ApuZ7wO3*~4$ z{1m4p?ovN$Ff;9$dfJ_}4c)YJdE1OrU+~Pcp0RF=5I9Oer5VX}BcC){ff`wk+@-if zsj?}~7hKcIvM`LfxK365H;?tFGUkkFr3$m&q+_Sfq|T(7Iq4K#GnJXBoXXAHIm`4M zySFgwE4rSy^PaBzjg?*XRy8tOMs}X8Zr=7~s01SMd3W0Kr9zser(6T~S|yx$5x&wp zl#thm3j0rzvFhlCc5LISihh5krDO!|aS~?C&^bOKhKbE5`7v?B@`^Z){sKzU{ooNP z$yI?d0>F96ijWkd!0bWUIA9Xo^ zA^d9Ap}*0(N_G*2BtC}kfXk`i!4|WqiR>gjWCUjeUdks@NSJh0+-6|kS(qOKZz@Fi z2p=O^dXUf3IG6AR=A3ckVh~|pHXPeF4bPX&v!+q>Oon&ji(au{nQ@slK#w8nSrqjG zPWL5dx<$+LDPygm4T7nbiNOUBzka%CvRVDK>)3vCHU8^5%v{$2_7pJ?-Ew{4>cC30 zb1B-n676~r?Yc9(+8+D<@OOuQ67Fa}*3BPSZtq`d?Z5Qy!_J=N=$_lzn@!h_-`M%> ziCfuA!;8^9t1WFehOZobE|ZoxSXhpBJ#6iN;Yas87t0z@E=IflaVNp&h1k#zdW#Mo zl5X=L{SX@x_yvIu4oC~4f^tLa;1Ow|LqvIZ7^W<|O@}yXp-)12fTI2gj^5`eXzmNr zP`iA;o(?sH?}x%DZ;?UILf|YBuftTZ(^Dp-LcOj}Ihmq`a#+`=i)pJevPsvodFFZ+ z)CJqob+!o>Lr!?i7czOnW81Lbs_U+o_VR|F_B@uKfN;6GewVN&7!7WoA$kLbHNb5H z_67NqqvG~8Nf0}39$O>O%(pzpro0SS_zK1qj57nEQzNu-5x$ZNtekq|weciWRrqm- z_+2D`7N0m3=lq6(<5+runR)^0fiGo?UXhs$GLOV5>x9Nd6KWYK&H7aOQ?pVK%XNfx z!!RPwZ2^V|c@)}lLO25T({h{w!V!GfFI7B5G5Rch1#FIt z122=YkC5?NZ5%^WuTTg1&l*t6QkzS1W3>!lUtFy<(_|b&AJDqrY8}`G*Kls+7(556 zwYyw%)nsB&opCHL-J@nq+hdNJw^TfunzNjVv}N|FrV2Ud<-KCwHB1~ftUOHZjZ40) zA5XkDk~r?m!RwND{H?5L>xRReq6c`=y-Dzvano5dxLby(2rv@o*&8ThRD2#H<>Hk= zBA0_BYmN{@J5Q>q?~e*GTV!y@U6uZFrF2Ywz0jq$kHaHQ3DAjuZSJ_{!$oRBR zL(R)!om3E*49iWNW4+M$awhK<9M@#8LvKBA{Dz9Yfrr!a1obs)oZ@S6rFAUV^9cYFq-{ysn>hzi4fzIqhpaJk4F zWrtuClg%9iw#HLRpODC7a^Nv(e=aDr;|~ICt%Za(otM`HN>9?8?lXeznk3O}SGKG) abuTq_uMz0X8$t7P?iuz~?dab6OCjFs*v?Bf>AhcHUORffTR-i%24e1c8=Ye`&t6m+;tAaeA zl~rq9+sM19h|4lP)mDe^WKgFy&5 zDczA9p^7}DyNoZ)R<|F10j8$gF@NH1P8T#KGpu2s5&b~-6Q_oh7nIDYv5DM>nmu(s z(jMtn$I|kt^Do(%Ez_ktI%QQ)iPBO~VD)`W9Bt9Uqr~}*2VuuOc zok)zTL*p5YdlQN0$K_11#GgnEr>U09q_av^O(ZDpfgVaEG!&L(LeAxAdT>0aXo5F&4*#TNTXHi7m$cs|q1mDo+vWg^Z}EJK4Ub zRo$0W&L==HvbhA4E1#z1%G1uo(VnLccJ-8YOy_|`_t5cdVpye6l}0&MYKR(JaNU)_ za%_>dL5~~YU+V&LiQMwk6g(|AJS{gpt(Okn5#>cbR)nQ6iN>SoU3PAV65EDl8hEzTR<(uGN(|~|fI(@HReDPx5*?h}i zH*<0N;=H&XG*=3rx6h-VDNGxlPvAcXTmctL2e#I-Ij)Xi%1 z0(@Jo2G`&6HO#L+eA9PiUOWQAKeKmw@4QgIR*q3$FggDFuOY`xFwNB z4Wy<D1JslZuDAL6ORvmlk#%@nmR z8sbum6;JEeJaOh4Mo0<_TC6DXZIma6bHS zA-p3W-f>Ix&v>W31u>czqrcqp&i1#r7q;!mZ`-pV?nQC^?yKKL7T>h5Ag<4g>*u=R z5ah+JMXkITT4zc>Q_l5yq5eZ*-C98|DiCgY7mQ~Wo)QsJ0dNFN1<1-Sxg-J79Cb)` zNINA56;sZrTlX9s*Cw6<+mewdZa)F-B+Jzj#@SIh#(H=ra4($2P?uGcrJ$Y>SPBmv z3#Mtb>y9zdOMs(<1T3`9C&mULniE;Y^bEKRAsEFC9qHl@d=ynA*LF@%tOZN zU>=$w;7K7Au;yLjyq_}2a{XMq!Z9xiI+Wu`Rt2*hO2NFW4rb}tqfmYy@B*dxfi7cx zmFHZ^6!r@~xES@@f!g|QjPgFR(^*nJ?7-^W1)X~c4(dJ_GTTbscRrmRR&m=i2$l7~ z_}Gw~Q((t4N>0|!X}ZVYpsJd?P@b4D6X(-Ixe?uKu#G6`)JRSjQ;IsOj@1Rb z@~yjWwmt?0qIbqM?J9^3d9h(uo|Wdfxt6)wxvn{RPP)cjYq?fCzrOuLvBQwta;dYR z**}8xo&jCZcVEesA0o(6-U7@GgDKncx_fa{lI(s?;?NMJuvH6cvj!QtpEPG}1D3go zBWPX~0Lt4;iOTZ*d|%mJub;0Z%aX+(Ax#8$D#18j63pvzk*k9Fmh6%P=XH-ZK*yHa zD4Rui)f6BJv*1AoyE|=Jp6PoP%0|bX)+H$GBpX}nKFxWa#S|>HIv4>2)6loy?HD)S~H`Y}FTqaPB@gDWzj3P&jn&r{;F>sy;IpspGZ_?2&XU0b4RP@x$ z_0PBd?#W4K>mw`xi#VK0B-M-xH$mMtn3@#ZL5Gg2TJE+8gM-Yfq)M|2O;C9#J+2k8 z(kD;qjwD!GxIprt6P3&bMkjQKoK22EWBjBjDJfNn^dG;CrbQP9!Sw>xS7M1_HJgJ3 zs*BqwnK;%laDC`iV5Svlb~K#@^_><#7^5~_0H=bY+nI)D$`|>E)0xa&&)#k|JDg69 zQ)T}ej}ELVx4a3O-_L>m;^NTQ>R?L8rsDOQqfY}1bjc}9;Tss?lA+key%~9Qa7f;- zZ!Fj9+K76-V{b+Ue5mb*h{1Cf+R+dfetC)fYFA;;$^4#^3wwH*rlp6l6He#lp`mD< zVaA?>EZvnfXT!`IJ&c)rGIvh*boZU>v#gs6@QS9vm8A@&sglg;?vnpRw*kA@m&~x+ zl6&M{A$ZXe6YN$|!&MvpuQ_7YY4DX&b`rR>mtk9A zjTSxrna-I`(-;PVS6!D~g+OaQ(0Z+Y9=|&(TF6_z>KXMlb#~~cuXT!F4AwI^CVC2D zV_s~W?OPBxF4=fj^`h556Pu3BK0epC;N7<5;9XlWt9QD0u5+q4?`>al5SJGr^c$0N zyB5T)fAZJNTzu`~Z1=V2^Zp&o6wkP)-Lw2$>$Q<7cV7I~tziAto*(qg1?QiL=Yx{b zF|)YX%i#!wX`=Vz}`w*PE`n_Jtk2^U}9xUGw2TN6h)ED^;i!xJ#uq%Yng2~2hcvqGsDuBlokQw!AFbnm8{&YjIC`M&49GhVJ9`D;EM%+> z7Aye61tzs3PaM?R>R=vNyd#!7X`zJ*FkwwE6?pCkC5pXRO@I>F@2#s#d-rlzm=!A+JTBZ)Y-n-->-gRHz36bCiI8;@kj{-qBNmZe*?s(T` z`BrD$)lhJM*l_T1^1h>?TO`+O8@t2g`s40yJO6>eAr;--A^w9PhcxW&ZsR}L!~q3e zdjRTEG!Vv`Ti2c#tS8=N?>ckmI(pMuGRlo3;O)xg6tJUI`R_}=fQ>@*NY^33XA+7~ zk-6WQR;L#+`67}=B;dCx^S;qeOd`RXyoN2kLhjh?_6?u;oc4$B)HK_l;XXge)!JJO z%Z98;__spw>~PB`AZwLN!3NF*5#0&kR{J6iddD?k@;W70<;pZP}3gD?dd zHn0FLw(_xLxo*QajE!6V1w_t}GqyAQ8R3lM zj1z#6VCf!ctxu=~i~8;61qndCHJ`YpS)kEk08q~XurBYrSYm3aQD?uSU+8!C^Zhn} z(hiA3C_U=vbCh0Rm?zE_TOl~8))<2OXD}oC9XRkxLp2xPniS}kKHf?NFm-=J0=EgF z(jC-nIZOJSl_prpaDev$ZVUYmxG|u&Ogzh(%fRlkU%wrDU)fENsddZnfLf0clI8mB z)+{0NjmF5q80|1dJbEj}*bHVh%XM)nGGKXpBw@hv@APw~V3g)ns$bW(GV%#iF6SL37A}^YlcW?p!}!sZ}$4@ zt?%vlmxoxdlT8C<<3Ang&yIj*$|yq-*47iZQM<#NpD+XuSsFU(9%PyV5{elZxndi?V7ADvvXiPcBA z#fA-UZF_UukGH?kz2pOXeD&nzlZ9YgKG-%VzuWrz=%EjThd%++4i>l&K*K$^aZdR# zu>H$B)g;`uOoZwa+#l+j5eR$U^c2F;d^mco<=w&Gw;wKqkL1Hg{uJIY-?abVg!kef zh=uU+eE9fROD?Q+S3|S*PT(K_T;lEy^Vi+mx@-CCogttf)Y>5@Dj1d!-5YusW(n6~ z3U6QVUR~zzH#alKAk{tjCXtg-^H(ARC8iZ3ZnB@IxZIN=i@)rKd7AA4JbCA6WelV{6Nw=;S^O;m z{TWW+=SUintinMrV;+*1;9olihJhOF8o>0$u)ctKFo0~ zpAw{B^w~CZRi6j;{6O{q3;_lqP*f^Sg*-=suQZ^@#b6sfmJ$t+TqBgrsGf)p$WpbMZLwBjhq zj65w=-=r@fp(-?+G)VnaFXvqfF0C6M_`L6~*I8d-|+;dv_>Hjvv!! zX1@OxssMsT$;$NEJ!f~X#EVe;VBG~!o(Pp-@c&BCUGIR~7g^FXec%bv{#^A6;T`7CTX=sHj!7P7GJV3Am~lxnpe zEIv>omK-P*OYtU4Tq0zP<-#^0r<8lfATAZQ3r-eVChQP)3V9TMh8Nu@vWvM&PRK9i z1lI=ihujAFhZ8GKRN!5%P#_cvMH>uqG>a=1iiMJlxKg21D9eajA}kTgGvbyCONC{E zdtP}JLZwiZ5mznLEQqTW>QLVNy!Apo+M>p-vWk^L!-*FHLP#A?=xHPi}Wtysgxc^$@iy)w>XEsNWLxQ!=_ zogK+xPy5-RmmkD>mU0tPKBnewU~!uf*Zh#&%LN_&ZE4a8Ey7kd^Ez?GfUbf&QD)}6 zxg3WTV=Lvv5>}!eB|6kvN|$ka`HqHuZkv7?*UvZXxGyP5DE<<%0y9pJ;=B; zJm@*U`@HXnxA(L^I6$==K^=JQr9vc&aHP{09tuQy)5eygvAx1^{5>}URTzVpx#PT& zK;Snd!#;kK9{tvJ3?F%LHSS<2==Pr(42cnMk3ZmRcB3o)et)mmJt+EUtUO^g@NA%I z@B%vFKo2ASGrrxT7!uJHgI62~OQzH3=r>Fo((RVkwKkvV^PTktP7Gd%oC*a`oI8Q{ zzEh#0u`W{>IBN-h7N#xz zHAgl-Z(Nd4fWNmCZ(rt4a3U{oqE6re)r^83>xUN&0$|&KuE8Waso)}b9lc2afiTBW zAsAr(UOfUYbH|(kie>JYJD?8pvDJZObsRUqO<|$wC7swSnUjl2vikcxBAdGggJcN% z0{vnsN)gM*TLO>u!3`%;KP8LD;}7~H9*>l(OnQ?NRZPigST1pi!s2i3ohT^d3MMfNWRJOc>4WfI1=y&u?##Okp@;O@OZ+seR@6KNJRAa3`Kllk7tS# z-FVA7!^W0*G`?XAycf7nbiB14fSVH0*n9sC2GAz#KD4{F%SPkSdbqoztG;c&(6zs# zwaYDUga&#;u0=@3G-@S26pBPbYFbLnVl>mXh-iB#pd?3HB}OxOn=jle`iE(yQUyq! z79-~ny4&j?k9bq{vlc5Ja^R($vMtm*bjBBqgpyT-`Z~O8a8n)(Q1xDt(LS%PcyXg^iIf*#|0G zs~K`yBxNs?#qRH@KP>k7X+fda3mcyHGS!g%Z36W@BQ=$e(vvT3dpZxdyZd@VO~=p` z&r!ecTpAR$?d?3=eZ;-%Nq1_*-L0w7b}J+8W;NLkced^Bq~z@x4Q@;?V1A}8w&5=& z*ROlI+?b!HCcH#J=5~yHh2(x4E0ucBSf08;dQrUKP|}uQ>3>fD#8#^)lDZ z^~-vBLRs2 zklr9)w@%L2&2^e-jOIH*ubiUWc(pbFS2spMGrd70J$mFu`+|D>8M-kN``*Vm7`ydK ziQX@#k3+XHHG{`3N_*Dp7R*HtT5ssY7-qWTSxU@tIxUzxP6sG+-D;oG;*3hWm0FbN zeD0_ztXqxIMY{p_gQjj%T0XU`<~*z~jOVe9H0Fm5g0b6_&8^cNJ4(+UUAvp(>==iz zE@)E9c606D_(OWmR>JqcK<`t1PW3Oj-sbfSV;D3oXfZ}nqs1S{vE2rF-B60up7LT! zkLRPq%n7DaS|@a_XE=pI$yaF=WlYpHfqmZ1t>WdqMs?B1^|MtjhZ@YobGFt{5J+0Y z=k^EOgWd~)khjk*`XeDR2*By?^SYlM@`)Eb&x8rJ3%Uun^1A!{_}?38vI#?j4BKnQ zS-R23L16uX}b{XT6V`xN@%@a*(u75t>DgbFB`F@>*N(Oz!Bap zmLLaOZ1acxK{^I{eUgEuK{B$gq7#@3AkMm`)e?U;i80H#pmpnjFX%fzC~lW3Jk(=P zB;=vw;ij#DP_H)--rl4pc^dVEtKkurJX_fH^NZIizS}(EeWUtqVoV-MS!N~sG_JYyg@rtqj@Ak#* zRZ)9YBEN9tKt}o-<|Vg_w~g#eFI>AAJ*-WFzDKYH><%cYdb^coT+TQEW z{wi{#R(P-J;9Zvb_Z(kxn7?o0mek7gI$0hs+Y~F?lvuLt)dQ~__=WKoz1J(=?f*qq ztnTp7vu4&zu9m^6-W^tuU=d!utvKMW4E4Y&FzpvyR zIp0|qE$q4${^jsH!@sx~E9{ErcSZBN60V}r4I_s>uxDM`|Jg_R)aK7VvT*fB_%Il!b#;wyZvZa|b@aQ#5wZSkLz6@#ydDn?ytt9p4Z-!~+R}N#;(k2(D4wA2 zCGLaVys?szwX=rW@9QU8{?vqkOoHsi>t1TD;?$P!LJV5Y12%y03hIxoR`C|_){g1v zTod>$sF$5bE+sDQT+mU^I`ChlYD54A0tI}ZWWYuNpz8DWdqLGp{OJrT&?FOF;$h_Q z<1b7=<`VattlSYkVRw9cWJH`vjWe^51r)Qj!6unoLjhsX*L!CWdBlD20L%Q5 z06+w~CF%V^0Jn4gzQ`$nkYMkrkjQ!tYEz`uAXbrAO&(w_CxN<5-!Qcqw8wLYDwFtgl2ygF z@0_P7a}txkGe=KGMg!alvNuWc;?5D4)i-Rel4&c+B>&#&!;4{4715V|$;imeVQW>A zg!D@mg_xA|p!z<~BA(9i^wcVdM} zw(cJAVHk-hS=x4YvD|lvf1o|l2k>V8L<>4FJ@jDc+64n+q?!bWU}Pb)kR@ajvcg!Z z7QqZwnpLpCw+U9!K45Fek+Qo&p+JvU6bAjo(YiB+3WkQ^+1mZRVrZo|=szR3&mHg$ z41jSI4kN}r=o5i>;LrlU#|=h-|Exdq?nJZgObC0|>mCYv-QcD90`6X5DE%Vn!)EvI zu8!jGCH#%y??rc0Q6ODxs*_ot-&xv3md7Ezb_?!$CAG<5_zOLI=Ydb zzeh`GK1U~Y)OQ-x^lG3IKtSNZfYfi+cXI)%lR3eFCpA6LM=n4xL4F71EubO`16+eC z2?L(RYhsf{eCH$LQ9Lk|W)F^0(;$WjTSwm;ISn3T*XctvE;w;}0+P<-m&_h-FNP23 zgXfu0&y-Fqr`+e@r6Ub8Z>DJeY^fZitCV^*JmMfN`Ih~5e&N-vFK(SMO?FO;(fsBS z!?!GnynOta6Gcn#<4CxQM-1P#$}ojstl}ulhLdVLXcj4QBBoe%Q!LR&1Ys|G<#wlT3R$TiSOE;&XT@8L`X!gObq$ zUf1b{1&2kdBuq2%9sQe`x+${;9(BzIajt`*_v?VC5p<};;=ZbST0-QmeQ!D zbYlJMTVC5T8F};E)VXNYrrFBJX84)vnZjB3&bWI|)V(L>-Zx7r_a~6ecG>oA$HG-b z+lkF(0)dym&^-05D~v#sDFkR+h26oVJ3nIvs~!CEuL00d9-RKca_ zcE~5tA2+v*>sYDEAPgOQWQ^bi6syc5m;my2mK@&xh)?wN60s1Fth>+m`j{|+O||$9 zO7~TG>HEkKj)VrK`~?#j8l0q*Ps79fCAT!Dar5QPQM-Fir_U-#I9*rmWA?bSKI*KW zbiG+JRdUn04!A@~`AFNh*kq;VSce(BVX6A`zL|5C-{bhKg7=)RIX!+qXDs?Zu4!4q zy|cvD(x88*o`*jVD^zFqFR=?Bwp06%W`O2ZV{ZyPCY?L3?og!C*q6$juEe{HIn~&& zT02zGDP;tCK_AqmI4htJv(W_RGAThXaKW^;sgfAM(EJ^6NziH>Ci@q0GX}lz>FZdB8{#>dzctlDXp!CW>Pq zi7o0oluo3TEuMtekR^jD0!QLD@T>1Sj0k0nan6S)(4<7FU39|9RmXB@Nc-3%P=!4Z4);Ml>qt0wBIndqHd z|7P=4bIi3-J$D<7X+ub(Ap-&$C=eG61sJwQPB%Tl&Qf3(V2MPA#Ne<4s6>;3N#NMn ziyX*6@ShEMgF_P|H+wvNpzymO>eLdYIzK8^d3iUcSKH z)#;6vISZG){L-HLI-{}Vel~9`{=La)EchtfVyynyWixJKM*+*(i%hDcsfFY3(Rz9c zFk_xHPeEz*q6zXmvyjuxt>+n1Yk|&yg-}``vV_js7&>bgtOz@ptT;=6oLI~j9Po3N z;sg<#~9k>iMxU6;O#JIR280&IW`=(@O+WbwFJNh|QBT$koiw~&>H z64WCRc?gfna5%CEtJS%wObz4%Kq~n@1?)PV8HM1n68Vp-;03wB{@rXq{p!(qTm>kd zB*n~dl)n=|Gt&vCRH;ZoqnP0YGpk2!yLLI91UoXEU_n~KT{E0u)vhVk62Z3F$VN<~ z#huGCio+ut54+<aoz{A4irtYctkFKpp8XFnVr{db72ABIK~r)guO}G;%LGW|bN> zEiz_;lg*C0G8U;xYs_>Qhuj5YMj$7{(b^I67Ad(tBQYL@eAav7DlnHeBa4;pLg|f4 z`qXc-q#`8-sg^6@)UW1>pnX>$_YS#;S(@QAa}{DtlIv)Z{?bvJ;TCDt+Kgm)M9TFG zV}+t5e9&6$+VyGmN25NWm=F`xs<8_@H)*t_gn{=`0A-7UjIjI~EAj#P%NFF{ys$2X zG-G7fl8$*;tPaW75ioxYfhx|;Fj;U3v0X#CoeRrS=sXlQP zymY!uq(PAC(heJykk=3Z{EBj;4p{(Dy7>o(CZ2tD)Au(0;82p?UtG$IFX8}-r|)xfRsTBrH>H;>{R19|Rlw7G9Yrb4 zry*g5NxI-UusA{12m3Ahvrn>|B8nLiBIE562W=1W6D9L0s8oSxDP{FSvnArgpwr@% z3{T5hDlk}iosHJ$k@TSF`C|XLKn%hOC(bCP6ZEqg>!J$~`=2+2Yiv7Uih+CFM zElbCroy?u3&-Cebot$~{cH^2E*Uy&xWC?^-C42c~`B$d5QA^dt?&<0uH@?+)Es|K? z^k(B!<4=bm`Lb5u<#_8J9!-&x5-W+CGrgWsM~|h|KC|XpZnU^{VcjPaD^|U^b!scs zEO)GI*{j=L*%mL`7%kg4J#?+>mnYsik=VZLdi7s7{;CnxF4;84@k@@Ol{YQL3+vv< z>TX8e1w~g6y?AKCHTlf7wqLft(;jboB8va6V`zo-wyQAtHgK&i-gY#K|E?$K4bgwr z%hoH|m$S#$Ogugr8Oe@X)@#Rt)nd((JHISySq2W;g{cc~etGK4*Sq5Fz0vmGSqtL( zC^H+(`H9%eZE_io%b2{9sHJ3l<;{jeH!bayXF(*JbsFYdmL&@z1EK7UR4IhN7>}kC z?=qbN>TnVQFb4TuPimpda8 zk3u#PMeRT(2s1*Og-N*1s)dnAsWIbeBbviThU=u$Im2m{CpZP?!^&I_f`kxO@VxRm z#2=tkk(fyme}2yt1UmhGQi_1K29ORJ%`&Di7a9F=^gusFIrJsv2}fHRQR5I`2OFu>bFT4&f2l@rhUT(qFC1XqCxsB1>#$V?) zjkF{jSy%R7-v7TqiGs^p1(2STcO~%6!1(%Cx4yD2Lm<3}f}Mh-?DP2f1j9TibW#YD|bNBxI+1y>ti zY#cxP=KiVuGriHgT_ddtN6wXfm-mg=P8!~{PuZuteti6`7iSL_J}& zJs8MG0sPoFgr;OT#L_HgIDt=Y%#3(??4%ZCxO4`5x2l5a1?7eEGt$zdCYMVu=+hYY zn(ZQnJTc7`x)RSudd8+V$(#Ps>RY7u`c!#foQr>o8pQ47(UxVT$sJ4qC*Fkzxlj~8 zQkFmBJELO0VvOF)yR!#ZRgx&@8Si<30NPiQE-a=KksvsR2B9eDld*P2a7at%ZKVb8 zO;`cpQ51&#q+lHkg=>pfua8!*pK1Hqp`RR@CA4mTA}jaG$;&6>S<9kX%O;GmtlAOX z`}VAa!+E9sa(moS6?IfiS4_9O-8)nLv&Nq^Ue{e;^DAR)W5?`~&RL-=dZc@H&Cyv$ z)eXlJA7tj4?)!1zt-!T4vuk#<6dJ3R29B-THU!wJMcXr73hBVS&;Vz+)cb*?z#5!o zlq3FYB+QhxiSHsZV+0q_MA-hgfqM9Kh3UW832SwbA_ASbqIw%ZO23a+Og_<-~?tmIm#i0#ls7cj`ey zMT;ZDkut|dj^P?wgY2x|u{;GhrY{y+Afk=NB0-_| z;3ZdxXh$sY8W6VgmxzQkQu#axq>PI~E0@yPR3ly5*vPBlrlo<#hG;7gL!-W1%E%yx z>eP+&0-_#eWR#8cs5A^lQ5Dgstx$El)5q%uUW@n0yH6fL8D#+xvX{PqBwKI5=M|Zv ztW=mjUa9z{G*C^*h=Flx}-Wo4;e3HIh=P#x$8-eVxhNzS{4o-h{{rME$A zw^gftjFAT6hgc2HJ0sOJ2s>yCLMjDf4U|vXIBF1k)FS8;f&|lQ3rHJ@(aZ6D{d(n~=9zQ{jpcdH?ex0SS^D*O}VEuTPS#Rr8w4 z9u!c*2u4?j_#?zJf>HcW2<;JnN6#;j_n*o8-^nBPt@wB3JxLyQ7{K(uPc64z-;+mlP(xlCDaW9VO3#TOQ=;F)ldQfVE+C5Y$T{&7dfi3dr{sM` z-sj|9Adgkf;FVn_;C3KZvVvI)wrQX5ykwS@eZ!KI>D>Z3m06u2>ZYlHHuC-}dH+B; zb-g{TOs3!`6MHF&4~6wHMzEBh4)~IhRRr}8!MnuW&z?`ut$Z|k?!&@m6Nc9vuQ}p{ zD=+UEX-OmN&iuh--3OpB&s{z@z9N=W^L~ESdnFB%wXu>lqq`E|7w#R~J5l}miq}?v z>U?hMx!H;>*Q$Tn@J_>Q*At_AW3FQ#x@3-H;bc$LwI=S`7d3US0qNcg!AR*`DqYYMu(}-;0#AvPq{J5&rg8N2EU6xkT>E0DOfAS<)8kJNoZN8K~xx9)q7BE36#zc_O`giG(;r4{1 ziG+}dE^6lz@@nx2HoeS)hX!5%x0-qJeZ(@2yPYyi;(L^dyleF0Ie4GGfHS!C(t$)) z_N6_l*Y=5_)>!`05x&s4m;Y$BiF~KdSox7fXIxHRRnpTND{~P!wEn= z9XhTuc_P-JostD~8G}Xh5l~tUQa0<4Dp1{z^kF*ofJo)JzGWuO=Ret&~-&=BdEbIJ4F^KVoasDF%fOO1Aht6qUqaX)XfuFjzYw^lS#u z^jx{=X;B@iwnO#q)N7|+54;wbUU#cjqwR!Wv$oSZo3B8%2r>tyeJB^G>j~MCj;RsQ z>bF4o$pDQmgRGq2t0bUb!X)x(T^~b$33xdz0dE&6FeLXGWmDXPWFHD0rOdrvtf#rx zSO97ARH;@TKAG>SoUmzn07((><20s(*L{iw5qb0Zspn_Q=`ya!fi9pBU=aNMwF;9SvCZ^};!mcQjiuXb|Ko&2K$fjB7 z$YwHie>Vo91F{NhAH?SYrg32bk1`08AfgI#Xj{8+uCq)@m-L!jgF=#U!VrdCxIHg^TdeGq*bc(+~5?KQv z*CSgF^59DG0IURsf?^iE+>Rj@9SA`InAsf?sioKo8a%mbw7JDY4}v=9CVbabK-B+ zhU}o$ypP8)%^;!nNoYphl`0lnTIz{>6#2s!k(NNmJe7u$%6LiF&Du>r&51p>|N3LG z+Af^X*|!TTCaPnFbqL#UyMWfmTs0($|Db+3lkz8;R?}~3qLefuaz3bTpvN**8h+EV zgcJdCF6WFJ;>GpR;(ATaqq?Afj;3YaP+|8_l6xJmRi`Whty6)i*z#<7s7p}Is4dW# zFP)~j&v3x3nAZP*33pM{g`aj8Ws`ar#XR&BGPj=cd(V)`059FNBaxujJ>Y+Lf{X%q z-M@R`MYj(Z_mC#!4)=S-eqdXE*cZUPy+K^e4Y>!sxb^Awx!JWomh7C@A6W@){cuQZ z>cV|cZ>0AWX`abZAJdLV zL?a-S;nwQ}8{TARMB@=}?0BQW#lss1-k|51ZoO`mx(P5gjWUNXsAqh>-6;b$T8bBy z+_CCzBXP4dC60z}J>y>K!Ru;Ds;Cqx^>?cmf-)d~v63S7`=HZ6yJn21leDujp6W>f zgFfo{pdgN@TOBQok2_VT64ESR)~PlLdC56TucK1QnO287?x>?$d7t{#tRo-mA{YGt zszU1mIqOn6l#l`r+38k57~V^GCH{BvSm>Wq2uq(6--LIEfCUmwP?(l34jaZ%dJAFk zUy`Tt$RtZA-8IG^E?LV~>pr&%E0cEXh8??M{S5Z)+{X?H$514pzzp%dLr@afZ>n4> zGFhqIl(*%GCjco}Q&@YEf<@42)!-6;N#$K9kI-mYpJJ9mMU+c`C)q%hCYvMK5ms#K zNme{Se+12wtU$ka4Z)UKkX?xpY1_+paK1-{orWh_1_K@#>I33FNRL*W;qo&izI~$i zT=Iwydrko~D@qrwlvEG6Ds$r)1)%Re)3-q5g0Nhvc5%olBmXi|AR=v;`UVRHxkV!_ z@sd^1l2z0EOvP-;s#wX^u|ftH=W7*yn4K%DVZ^fCBYJ3AFs+Nnq59{V-Zj%rx)-gt zm)0e+ipE{>lE!FBc>jg}g@bHHv)e~KBJQgcikEGd@6uN=Q!-AiznBH?O?|Ll`ji}}Eg_0VK zt?Fo@va?|rfj@-hz;>ltTq>Z2oUFpx^Ef+SR)I8G2}}-%1>h5yGbS?Vz?jjhH?#_+ z3BG`j3>CY13}Oiln(Btyp}~F4z{|LWb~TC`FbtvKgUedec&+&JbzWNcmq%6c!~4 zibr?D=FHwXGiP1)5ofU47|p5@JSd1$r-$^BUdDa0G>a#y+!aSwI4P8>0*IuJXE-gs z#e-yw-8#augNEbkVGXTAl~73)p0W#?MrfgaH$-#Fp)cr}un9~h=oV^Wm!vz%<9O^_ zGzF|_u@pn{0Xkp?9;zPwDLiz*tm2`T;iIjj370e?(dX~)hY<-t>iQJL(ZE&^VWMPB z;tVr9@r*Zk+D+CiVPMZ4sDqIuWMftaVF+vBl&?wbLGNV|YC>?i=*x zNAQSo%^>vCm^7LBeUILClgD^+-=NSHcnYD@fG}*G^qm(EQpiSf5ZP*hO7A2YCAl6L zQVLukIj($lA}lRme2r$N{SGbBe~Kz#6v<$*=H4y^$obx?G1I6%QC{)t$yZLs%hyKB z*T&0RqU9~I^44pu(eizxHZU+ppS?OXHZ=ZZtf($t)Ht~&mcMd3H+Q$WoHxGUiVU)!bIW#oQtwC&2%|2&t6KW_)nJTm}A zsy0t?PtoNFZDlRI&vYr&K$~~>pgjPzNnQP2X?qQp2lptuErqCd>cbQKHWZEXa2&}shy_edT0*4l2ZA7Xb!bSUpU7C8+i|{L$&1hh3haY zDV5)c)}acwzi^ z#Jl)3c?`_?C^SIcDf0aAaK(gVa;bBaiQ9S+r8?S&Sf~8GS_HQ17Q4*UrILjT=b9IT z08hYy2^um65MvQvO6OZ|T^!blzJBl*PI=DAmwwXC+9kQ!|B9d=hL)H>6Nb2ZW7NHI zI&#y!Rdge=AxC5Yo5}9lkW?}<)fgF;6SG#z22#xcFNqC(ePS~;6f=+n>rCKB=(H@} z-h?b7iGsk0pvjT@)k+}-<&BJgCXXlKI$<-sr=KR~mI~}MJM|!7pP6<7Rfjjj`z%fI z$sM)0Z!(pzxTP5PdgLoRxZCrg3r6d%9=_ZLxwWfgykfj7UcNe7zB=YwGqRg8E|x?c zOJo(yiQP9H%Rg}D-FD`UuDQBlY{Ph2EWak^tW8Cf#PX|R&gxV|(M#K7&dSvDf&|4c z?T9(6QVB9Ml*aO_W6qjXf`XT}#+>fCd>hk_F65v)%9KP&BRWx3o+vH*?TWRr;&ngR zG~s=<_`AhZo1(?*5*4-aiVe|<4Rcm5tMWc)%*wu7&J|S8H4*~`{JLAkTW?vmeTGA; zWIZEf{-Ua2Pj&V@jtVVt{PFi_*DQuLV~a0IUR|N|8BRHx>XY%z>>DcgS0lR~ilEj~xCmPFVOk5ZQ_w`16eKKQKYFvD;5X*Od>VHj(r4B_i-LH6V z#m(FbsJrJluUx!*@yhdm^n9YI_(cmW!{w0-+38|iW}fU;#Z~_sO2J93d&&p~J&Khb zAe07Xsz6l?mRCMi&lqtJhR{#ufOk^48BUW~pq|l6nQ5h{?+6!VLk&EvOQ&7Bprdi< z)&X{N>!I#V(373t8W?c;Sq;c)Acon1p}{!3qh$a$C15!fw#a~p`UrpYf~QF;0A9u3 zG{Zn)Y*n=+m$Ysc2{nlfAQKqwP47Gn3|TuU0^y^ zj4$|ra+E#d-A>c;pc(};6@vw&P8IlX>iurDoD!6y*Xn0Vv%gD4c?2uQG zNe^3x%yoJO6C~?tokr*mwM%C1&@Pa9&@UhaS|Ni>_y)b-1`l^ly(Z{p!2=n;#iC_r zUC#xw-y$2BPYHJh_w?=D@ zjN1~$mGR=nXmR7UP1n8eZhgx?+ubuu5xt4JHSxNg(Yl?nx?SUr+ht3~FUHCmr}5A7p<9iazYU0b*N0+USFWVShwlPuL7_Z$Dt=$r<-8SQm*6y6p->zCdxo+AX zui6@|+M1}Yd%gX&_P4_`n|^e0qWwm78x)qRx6K(j_a=Bt))GOoqz26Ng7Wu@mw=gG zQ2sf)@&5H)>vlDBKX10Rn)UCRc=*JdU<4fl!|c3g66MV_E$o1oZy|wgri_&MRhobc zexwq7%t3pgrL~VfIqy;xC()$OFL6v0E$&_&b+7();Tq_o zwT|ZA&dD9ExLQ3{O;(7;x4;5XET{gBU6U7n*nTT#bE2|gl)q{iGmJhtmh*|uky}2u zgo6@r&REWb>87*pJ!ip3HC)kJ8SbY;aux3X8g)P5FvNz3%`5dN#6~tCLx$7ZlqoKQ z3fWVoEQIVE8IVu`PpX0xrQ{~SrGki5if)+FP$)JxhfS|%@Lb%kDLO+ucsCZpf{YHa}js=6KXkQnebuwLrd&gfC|4=zz zFt($X4y;E*e5H8@R;9{mbt<|WxUs8Rp~CH13X^G7OVEUpiImB3S{wpW>sF3r;53vI zqPZE0z9*3Zj4#DF^${W%YK@R0H?RTN^D0TcH*b5_|lmC z)w}{C_Md}FkHNhE&Fif3j3^HOZnPqca9is3?19Br)W1lJK1+62QlrqcGuTc~v?q(j1 zKAQqM$R#Jhs?0`^wOH^aE^#NNBUmhxT=EP_dQa%IwEod&D0KS2&;$XMC9H|;Wje+j zac4!;Spm>_dt=)*A+~YRKon5y6renj$20m+m z|JY>6+VrtQmvxj!PVlC1bN|ZW%ZFj&_9auIY-ysT9F<>va_q@O={nr4IQ-V(*>!E# zT4#&*&DpuEB_DC7tZayoT}9Etos*IHsvQ{aSmDli{?2Ir&O~MHsNp*~4AZKKI%{q@ z>p<1GT6h^Mq~qrVN3rnud;b;z!m+eZZ7s;1juA23gXuYgTqit4=8NcAnCY1=D&rs$ zG{bf4(r^-eH%Uh{;CTa?>9kftihTnk zd0&`vQ@|I?qcOkr$@;yuWOWr7{SrY$qC>CZZsiu4tn|i8bvsSX@@I=!Bb_6E29qJ1+e&`!k+S|qx`00*#|lK@tjKhhq7UA2`mA}U3F1c zUCh-Gcdd)M*3GP)rQhvf;MO&c8g4nO0BM}Czir}*E3hnbOWt!8gAE#7#vwP)yRP3!{cD3|@;Zpe_t8Qa`mY_%zG6 zDvGG3ISAASst5~F8!RQ2EJ`UGbTp|;N%!^<#l_Hz2b|~+T3Re`AuX(DQ43+8%Hfq}gqbwl8R~?0Mhx>-Z zJ>i;d*mZ5~wd&cry|*0u$fo;(HI<86|3!JrO75MNww7l7JDYjUm1G+?4IzSIO#DJDUnogsQf^1iT**=)1Z~d zTc=)PL-ddyi0v0L~y7gpRB{hkD5D33fiec)sWWA9@~9v;Mg}; znV>5{v<7p~m9U3(X}S`BuB8VtPger>Oqo#u2p}2X7U0v3zn~p@4%rJ842NAEAlm4o zK}6ueZrNFU0kCON6+&?U`x58B56zSG$Rb(fZ!PU_V@eW$Ij88A9iN0%zt@zF2Y;_m zebyrcTca!z8HiAqjO+tVQWpDBQ#$BTeWH&zDGy*O`6-{}@geA`L4A$B3WZN)J>K;s znipb4vd`s8cDaGhv4LH@|bjksWdRz$9|N{ zJ|QMcqb}3qAbA81Vf&vLB$*lx_zDqycw90D=u^s)#hd&}vSjR|4m&v)QCs=(Hd2r4t3bKkiCcgjkl`CIi*c6$R zy6LEaEj5NdRYY?t;yE?ZoElsr4ZRkc7GpX1lF|D)`E*!zT<(ZF2>-gV{Aglj(@g%1 zamM=-Gek>SRWLo8)xv+^$YYume=KWK6cl~eH2&<3${n%dow0(Jkv+HNn2Ajj4YA_J zSi#DX-M5QMzFRwyd!xE1Rtjz5zL9-uOdwWzCRP+oOS3yxx+hk&7dGRH%E!GoD)z>T z_KoaKG_IRE{L}EYO@DqdzT@%ej>ls=gxT&VVmqFQ7S-K+$~)WRk3IEF{Hej{Q-iUm z#F19Aj-_@cQM`2G{EU9KsDLHSP z(XCG-<_+DX9tTcUrW3MQf3hJ=$Vrm$xgFw@SQW#Y1yy!N;5Z!vbk{4llcBE*U0n9T z+2oA}5&F0%P)(*%uJcev8M5F2UwdP>(2}_U>xYQmbRS_iJLu+EZ+e@FykWeA4g|LA zWp-VfK8sFE#i9$h#5WL02=@@q!IVzSK`O>Rn9?&jpX7kdF~j;EvfPk(lg zAn(`9YWVN*RfboMHS;+LD#7>nNJYvgT?Wk)KG}aHQk}BVu?*F3hI^|R_NRd@CY4RV ztw0Ux)>aGS@R5^w+~>41(E;Ec8Xy3?BOMe{R8me$UH}phiY@FLYxBx)Fm^DV@6Yp+ zbX^$NlSAQN{}AShR`BN~hiTSG{0rVUj#$w@gx3)-_}%Fu2h!ve|0yys-f)W8n=&%C z0zQiy9$;2f{UX#0ndq0!)ua-*x(tXJDy@FBWe__31UnE>oCf8GFX4`cubv${JCXa+ zbBwFl6m>RDUYM!7<=pkRwGDXr+>6i6u4*0C-&UFCPtLAAbX~Z@x{-XiI0qeEBEkDVu(!o64P?ggtL`AZ9O5FLUL#8UM`j*?q@n zSDd)%I7t{?QSnIX;uWLQx54J$CkEc?8LZ0s0d5*6@}`M1aD| z9aIezh?Me%h^(j2+cJcw<8TLXCtncX#UKI~NDVhcH?iExRo4I8aUb#DqLJcX!DCuY z>cK{k=>fWL#2(i~aGnF)5&r{~`PcBY5263BA}wN+#)X!dc!Rtcc{kx{VigZWE;R-} zbo%*!Y_#I|?D~%D;p@KHwW=sydq)4CK`YouzDI-j0E}XB{Y~vP43y%9FN9K*OLGssegyP`ru>UKD+Xn zn~u}}sK>m0cGZq+)|uyK4|r!+_S|&zY9I4EZdz8Pj`^ePm_N#n`JE(=fABfKdb(uV zKC^Dtwc|nOJfUQubohH~5lA;hq(v9XdNb*SJnYd)=A;3E;XENS)Z_Na<^&iO(FDaK zszLlMP1#owO23=@6irp-gAg+L?*EH4Q6Qr@vU-z;3*uxFdjD+QmRpwOr6-%r>|>&+ zR;r5G{qa(W@dKZx5L4_Rtqq1`qGb&z@^cq6x;WpEmSRb3I7cOf+={gJMH*ERqG(QBMjJc*G(_HNJmB* z8&}V)|AfmnE}tXsBe&I9|50%Gn;!@-G`^^TU>%PNfEWF=nf|plm ztpEK1ewoqs(JsEknElaXH3)X_@IUF`dE+*iF*C|E1FKWqhDud1h-ppT4JR=8Mb_U2 zlt2!8cya)~maGPARn=uhT9y7j#zQ|EpRH#$?!eQfPrFIR0nz6Rvesb&N#|0^C!>70 zc?@&Y^wDW{8%Zjn$Ua}ccPIcOe(ZKZ}lBz!?FqUO+)={d)36A>-AB)Fl$H}sx!#6 z)n*jJOumW#2h}f|f0H@e{|v=KIr|_rh$TBjp{10eokFyNlNp9f7Zn`VH8e^#kEeeK z-_G^n>$k)c!KcYi!+Zu{{jcaLt9J+=+CHPi(b&m!o+)wxc8LZ=;G3#6k9VD%(J``XylkRp za$U@@>OF&f8e8Qc_Qr#u< z2tJx_<8^mSsWpej>nHOkdt-*R)SA8Hb!krr#+Ro(wU4h%d)hr-llF9IyfOJSmt`)~ zU9yaQVTaQ7}p{{7PD z4g9w8@T(VJxp<$W@LZdXt6MSM^$DlvyI`e}{7>ihx;RVjJv_(;baL;NQOow1$l e3d5f>Q+!exMQ_=?l>3XN`MWph|6)B4|9=1o#VK?E literal 0 HcmV?d00001 diff --git a/__pycache__/layout_window.cpython-313.pyc b/__pycache__/layout_window.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a5659d075c6cd5a3802e8fc432d7ebf99478502 GIT binary patch literal 41659 zcmch=dw3hyl_yw*X8{CBfFLPSdd@zq(l%BZP|t)5~OHB097FM zVBCqn`Fdul*wdyQCxVh}n@-XjDxIEYwr3~wPQH!oq^Fg1b{jA$gQ-@#-Lu*0&pZ3= zCtK<~oIiSh=N7680E?88cJHNhaqHf5->-AeIrrQL`T2GZ<~O%~d#>jq$Niu5p%}C5 z;2(SgjxTdQ&c{E+9pgpbLvF)U2GNLL<5PxXCed`vESis5L`yo%DhdcQJ!Ly)6K%}T z{FMDzo|t#cAv*AF5%YakvA`#Yg+80;^w~w1uh8f8<*nsjG`+}+MP*zq=X0#(eEH7` zeT_+ukk=sP9iE6??Y$Hd!@;XkUTf@XWUy}{5($Zu z*1E%6=?{+1&eok#1b;1l9w32dGxKUdE!O!6MGIxeo!hHOh zbS*fvr=Q!Ij-~uYxHIWK;5a{8dK12UCNEQQ)*wFbGw*wY z$VfZd_B}fk zx)cgOJ9c&aTr~3RWzQy0TXbwR`0VAN7&;f7h=ra-_eLki1D8i5L($8d$F3sP!STR& z=*qab7Ad*#KlTM!FLU?uozw0&2IF<{OADoq3;F9`?!0F!n7R}2Il<-_zH zo9?@ICGJ|VRlI!o18d>*(fGwL9lw`fG`%N2c>Ul^%R+v`lwrxWCT^G>j~|#Vnl&Yw z56+A8L$_-ag&hf@V=3P~eRz7u^dHRh&9u+*iM$O7(}o8q0yjvOV$vgqfA9upKlDF+VZ;FhlcU7qU6#^sVz1GH4fEPUb4|xe)I5d3;6eyVzIbb2C?ouNWbv zz7p7Le5J6Lerhx}5e$z`P6j72*Fzq;Q$2%GF^0i37>#%?1johE!H|cBStuM1 zZMJXn^o~U2ub}5gv!02FXKW%I3r5B%MmQ=4F*chnVTcB|U`R%STiDnPdJ(f@e01g?^w}hj0GDf5T)y$YXVbhiv+d ze(pJh`}v*e70-iJtdC;k7+*F7t(Q5*XUIy!mJ^ImpHW-;SU!0=FlL`wSv@`6fG2EG zV9pdOF08`o()ziup!l9~E3T|?ws%qp>a|9J(0+XupVcSqHL&vNh1-1gRm1aq4mG@7 zOIL9reVZJ9hSn@*`YIKd_FK#COn;zGYE8GG)M2Lr#lC3OV}^YdWqqkFz`}~N!b-Bf zN|i4k<)GG^eU+(U7KEvF!rsD#)jIgh_@Y_P42!4M3N8JF5~BSo^aDA zzS?hAc&p~GxU}#Q&YRyeK}9{S>?O3P$qSS`c|wxVvTf_uE4z1W9bLra7~P7w(a(0n zk7)GY;w8)F5Y0uAI^&}gWYJ#v5q)}VBy(&6vs)4Zfzin5cpxB|$4AGp-3cS1=!MX@ zcvZ4uV~mYXh9nzShSA9&+YE=!iZoy)bKop+7?CE4WC;Wbg^^q%;^)4=7lA1;zC68HH@E^Y(6ZSk&#nDQ7V#`gFwb|AX(2&jE@7glI&;4BY|Nt2*gTq zu$A^oAcj>1B?W#J42)kHm#oNuIZQ*L*q~&Z7#eJm3Ib!H$Pls!3`Yki5ILYOPoW`v ziJ^;uLG1eDXa!p!9E^>V7gZ)adMP9ovRq<;;4lCJqeGG%H69HQ1;(ReQc>ESF3-7W zY#b@d;Z!)vEgTIFAp_baye7$n$_)d%Kz~NYCCkv+KyYjf`344&b1V>unb4A0;a?VM zyo!WXNhO&((q^Tj2v3dmWBvFw&;}v@nl&ku#Y-0j&ywJH&3?_EaBo=@w$exbwfyN9 z7lj&fJFYpVeet?Qp_;x5t`z`5=wB3SKP)PH)q1bAW~P3jbp4d+ReOdz@4khz<)?(| zq);8dIO|G~Ya`;TUPa8Sc_pu!q);ZhYr6s?+gyZr!EJ(U=J^_CWPTMe7D7CsdMvQ*rilxR@ve$^*jC!R)nU?3KZeChL zp^c0_+H~^wuAEZ=TBk7GJ`N>rUxDJ%epzZJ9O_(qfeL7wDVA_`+tHwPYbK!NHsn_% z=eI&kb!*a6^SJ@5Zc>`Rw*CJO?QZg$bW2CAYVZ~NO7@yCRVqX&*vTY>b2ax7jXueAHX0tfWsppC;+0Ip zQS5yDWv@Z(p*Rh&IzbGvoMUK;R2X9TKOq5wL{+(EV8vy?ldk>ykK-HxvWky|A3W$a zd_;?jI0);ODW@!=556Cnu#O`G2W5XLD2_4=#(a5nX#Ct{Nt@mQ2W5K>F$tl#Z~><$ ze0NhOGnhwL3+bWHcf&m}e;ND2p2LR(U3yTd2?e2HfRiQ$n%WIREB6ZeXWZ)|vdL%eU6 zpWm4*Y6VtdCFBWt5IPli&9uz==Uul;ryNP)Xhuk)q-nPP&$rwH9<~pKbh=-A>5DJL z+ZGBvQzinlU9(LGQKZJXD^oVA{MyPlo4?xpHK0YW7T&8|_vZ1h9-l4#Vei|$3E!z? z(phr# zl2uEV9~Nfs1#(BoijuXJEVj;==!k;Vj7@LLAklfm7*#=;%x!Q>>+~jb#u;ZEK(R}( zFsWU|H!5GRj1Mii>ZUA9Lcwc!*Ye^#u>DRpCGyymD9D|&089yWNuh40bvBqF*VcQ* zYi=BW{rF7jLU9u&fGs^k=!_C?!76ZRzV&wNRKa^fr#xV2)m032CcgOxKY-)Q93jU0 z24wm(x-t`uPscc;cAL*|hITb((EUb2uSO^Z(<4%#Wl)Y~)=fb_U)pZvSe7&DV9@gQ zTIJ0d#QnXk^oJv(Fg$|uBZ!4k-nl541?dkvZD(n><7`wMLI~T_*f>D~9lQ2|aRA5R zZDhO_$)+8>^V)ik_x1%kx=-{!Em=E{1ln8so|5dcZ>RtGamgXO+k5?ok9SA{K#q4E zIoj_vruPP%$3Z-x6L^feLfH-^7oBLsR|7->#o75PXbIKX<0&`%B}9*fV7<&O*=&^>gOxR@Ea&z#Hbxnadb2IIE62!*1G}q);$y|G%Xbphq7vd)uWu!EaW{D&gmWX zvdVgmSe6xAx z;>|6yHOaNj({1z z?njo^!uCzvkE`tM8;n0*Z$QA0y*#-$7|FfK-oDTHyM#bf~W1}}PdfhsiUYC)s%5+Mno3}!`$TQdY^Hxb$#YElMx{d4k$@qLCJ)2~B2IrH z;+g%<0&cr8;yR;Jg7oM7xg?6f>~mT>oZmqQU<(^tUQaqhm2%fko$bO(em zz&a-;x9}qGbJCXQclT{t4(oHN(8Tx#bVivSeOs2t@Vk{w9%<(5LKJBb-M^JbBicxv z6b3V5(e;HD7lICt7(M58My77a_rVrt> zvhgS|R35#c4>f@UK%^v68d(!5^8rR<6#`yafHLy-m-^ReJurgf0{wZ5(lOg^!Z(~=nS00Zu>Lx{|~T!N?|ToRM7q(2HpocHfi(z%nq&nBa$JmFl@T&C!;u)$CGMs;d&t^L77hTM_yk#FWNjsj zW<6jCJe>j&C78rB!~g+&jVzoNK&wRD08W44$&xG0lQn?#iS&j-k`WX} znS5%ZGay4OS+h%g0F=;Zm<`?_Sk7q)lvp{EeE|nZT_a2^{SFW6e6b*<}mkPT=I0cwrSjt3Yt~Pj?yXsS z~cGflL0xf9Qv@Pj8w&Zl*5UvaH;o1Ia zA?e&k-}%?`=lJ&zABsQ_h;C6Kv}D zo$Eht;7V)mH*)!|*N$I1o^q^9I@Zkyiw-ZfdGEE}l%qE3sGZrDa%}#13!3}k4$k48 z-hoEik;-dI<~7asr#2nJzuWz(j)7#yK;r3Vk{xFffzU!nXsN-QYS@#+KS%9UDs{(vGcx_>*R;|#HK@uye65xfGtHeL@8njxB>R_-1CO# zjnCT{8m@w9j(&F5?l;mh9x-79qMakhtcHq5z`z2M#UrLlq0*vfrk;ipv{1#B4Yl2T z!FEPPg|SJ4l)BdtvG^^0`AQ7!*JtwEfY=yF2Jl59UmAdd;4IFzU?4Xu#DWBE~cmVIe`N+j=a_*jndp+&-6OsQ2u8|=M6`7rDD8$+0U%?sQVvTn19GB%xBRK;@!u|_rHGj`KBHx z-(P(8`Tou0~&Vl)1YQ6Ln9n3uMGVv-MgM+X9BDQX0T7j zu8Mz+h>QugY-;=?g^=WnJT>g^*zfFIJakf?(D^bdzXQRN5yVy*pJ#|PtyZ`hGDL!Z zOn^Yjr;k_&a(@u{7M0_|Sag&)a91SD7063Q$8-FzN|vj#zc7A2Fcuw~81vd?1m280 z2Vn85Sh@HEWGTK)`SKSe{))t3W$R50lnmh3FTB8T>q9cf{yPMg!?9P_HyRnSF3@j( z3j%JwE0tfJ%!k-tG9My*$^3e{S5T62H6>k5DOYpS)x6-^491_ke7Y%K6K^Lf>8$H! z?`&(ba&w|$%k0Iu;_p{|uWJ5cvZeKQO|qpuv9%-N?3^;+b2z7qk*=d=ieD0JB&C?B zY`(iIFqNMaURcV@pLV^no6vJGf@bpH-*bAZJLwouJPMe{d+^9FoNjsLwBo-q;D;+E zrA0w06cNF6c{bnObCSx_x74uVt>>oNWh8UaQ8RD;q2p}_O1_dm(t;4?bjw|#Y&k|q z;{)TCfAA_CU*-n3_Te|zD0~j0K|Ka{#snDJK61=Jo3{4?LM4G}V9Ksed{231nBIUm;Fx&`qs^ zwOwVp?bQ0OFn$dXheVI-rbMH++P990W^#Hb0?1cbeID&5$xd1kVQ|h_34X1w=1ipw zg_Fpm;cI<$8iPQC2cfpUhY20B^9Q52%Azz(8nG8S$bvSta80`VMnf0Ia9cBii(2V> zOOSwgnxF^^5ox%J&yqz{GDy}iM6!Y0%Y+g8;rkJFEx=yDk5r`IL>NB@S<49Sj7o+O zNk+0%LVyv6$a28C#WSLsI7c3*VNF(N7EY$sWnQI1GOUPH81Y52{IC>X%3-qLcxVKq zLtG4_`)d1?jJpYV6qaPB>ytsrO!q2-VhzQyx6}2>AYB{tIy0!0M4OZ;mlw&kjiOuH zf{{x>5DLemIFm3pyYVOqlZ?I83N^;3H1<9p09WkX}qy-00C2Dskz-bnGQ$l}I z=m+g6F*uaCFqXLd2MO}|Jc;vpzv`XooZEH>tZGmSal1hwC{|*dBN4{A{@X%Az*pD3 zvWhnyUvk8rCM5)t zLVzUeBGJT^&)w&^Hp4MPLI`}!aki%n|N13Li+Ju@D5%XA@pRAaCIL?-qeya>zQnpM z5c*09JCnlB`I_6UcRCZ~_EBx+ODZ+-)89J3C~V92!9|vqOrK}JyZ^4RM@9h5=v~Fo za?TKdJ8(P(0s!707A@Sy*lQvZn(ne@L^z;8XfhKQa<3K3m01s^qASwr%W^7tO;7f( zmK$(`KWSJo4f7_HUf%8qJ@YzxKB7HUB=G^6eqt0y$o&FY=w;gBp*c!2OkVg?KuN{fQ&gVqd6<}KL9lxT&eul2I2yOioSiGW z!zT-lvGJ6msRI0PhM(CsBhHyYqqeZ=)2qo7$7rC{DFVKylEV6w&)!NeLg1+dIUiH4vc=8>f2NIbsBX4N$qJ4`VLZ05ZK@WrpbW zxu4&vUd$h;Lp*i#Xfc)hLKqE}p5W(@AG^@2@J>#5^&j=Ld0Ks*rYwI7_jMfaXzTa1 zclr9edf+(T-`CaM)W>Wlv>)_(DW>dR7QM5tx7#yxHoCcuc8g`fr;m2@b$GhkJ^K%O z_QH5td)hrs?V)fx?)CPHK~I;@(*wyuWPt$Pyb*K#?j!57l9ul)E7eO^L8pYQbZuEt zd;8iu`aFl9&hqql+FE@bIbI$QO5fu--qG3LB&XfH-Fsktck7Y$thD`oPY2q1dro!q z^*7PKWyMFI_B5d-`kPkF8YBJ^U5yBe zP213i-inO}~XU4uxRbl=cmlfKG4G zTQYX0Ar#0Vq%@Kx-+4ym?kMLk1vZEs0$8*yokYfu&$vZhUV3?m0P)COJ@;sU`h1-; zL?@FCg3T%nIn>z)$)Gb`h0AVI8$3<&>CTg4$hHjK9kMls56pN`5q1fNR<Ek@-39OE;sURtfiR;a%YC&jOp)k7mkuOt;Y#lUAyEFBRt$nvJ!0CL4H zq`YoA*<_ai3~v6t|-Oj#7$Im}Ll;!$4Oh zG)6LF8cPLj zDQY~T5^`&+puHK_k;S>h9{F7o}Au(WB2vl z@m(|97Tt}v`=;876Mp2{k=J^z^~77ge)i4bo5PEahM(6rEtGh_(H_4T=ieB5t9`07 zQR4mEk_w0ufN5{NZoN@(z2NKOo0o20nz{JC(+fF-(#j8;n&&KkS}@&sqxpJse0;H} z{=YQ7ee%xPskWuUA_(MPNykk&*C(BjbolPJKi_q0*CMg_S(+(lL(}TH|ejw z{~MYY7Gdm&wBky(*tzKC5G4Yk zF+(UlIw>ztdSIFY2$t4A&d3DdZW@|hi2fKuGo$ww9aZ-nr74H!J%?weEV1d>oo#pO z6C2U1C)m+#!igkV9n)%LLjU#U{|Ovg6KR)#1`1i57U<4c)iI^TiHJxiBguYoA|zf7 zycmN>JJlRS7vgkc0$&V^rPK-}iO!_FUchve*&iJQkwYWM(9%GS7b6%{@xGy`&@pBF zr$(o(`k!h|wv+sQJ9Ht?B`0DP#7%EnZ(37j8gS4aIAFQWVK;Q1UzM%k`V)J_mpyu(L2M^)hHSm%2JMd z{y(Py$;xV1CpWS>Tk?Zby?ELyE=;4O^>Rbj5 zTUjB^!ki-EQ!5o4FnX;4tSr}L#-i1b@I_@X*<>k6Hlj?Vltvy&g{Zttv~ZBiNtO#% znqJ5Tkob9IltnCroTNM=!KEcZM`*wagyq}ixjXeraGl5`b{+{6JrTluH!feleB-6- zFMa9r@4Ffyuvh4Q?eewDuYK;?=i)7|e14|%ZsB@$J6v^}3@$pGGPlXrHwu34Ecqml zD_XyN2vT>lA!tW&AYjHnZ-(RuRGR6n3XpNnN1+X2wcYh885hj`X2?P#McMd(xcPZM z)FnYkiz$4=+M#?y?HlMLB(7#s;I&^pN{2peLw8MqC|N(hRh4-k*nzl25YI6_OFs{h zHtTkXkda(I=p*Snv%wk681=}u5`jdfET~{I^5y|OBllSC(WhN#gp<`HkfJsa3Se;V zq>t6X+hqN23SovRds`l(9r}*MQKpzKs|Kr(Y#y6jla(M!{RraC$^ZvE`{aqHrs&mb z(zl#sm8SLRw-MT}y`#t15$J2}d8*0l=>=^@hvdb&QK17d%8yJDSw;+C-J+1FWYSHG zhf!L#>Jb81x*3*!dd;kZ)#_%zGdf#e^m0#DpiIN^9O>)zp8(w|J9b86J+)$ErH6~w zt{HiLrtPJS%g?aMlq8!$fMnx5t8LO1NfRi;t2bP30vT=RTe0m1H)FDU+Isyx{Y@&3 zbY$~kSx@2#pxdEwmVG3vVChc7Y#z+=Ct{-KSZ`MkqnQqL2S)-&MuWI>KN*zMqJoTg zdV4%0$e3uVLC*mX6(TDcbueUwWK_uihzfOg^)%_#qH|P?jf0Dqm0P+pziUl??`o)- z>ny+GW||<)p7W&SvL|~;YqZVS=7>55d;2`}dBC%ECE}|*`(>b(^fXt?pw1PU!bDbIO=VXaFlL>XA_#L)(^&l4l?7{+JrFx7zk1mf2LQJ3KCPF;bL zN^~tZ9gz+LyCyMM4Xf@iU6GPny4s;B`@qy+(qF2Fs<8X@KzTrGRk3V8r=8*zELce` zO>0$UH#D4NIjvRGkv!A}%2%mAmDOk3!YP0K#XHmV15o=)`*bjD<>bJ^=?tA?`p}BG zMvF573g-cStd1zQM~@OE7OYK1sU;RC9c;!zezQ_ncBUu+R&UAjsm85)_{zp_IHOWR zHL9c1Y7s*Qq%i|hRd}aD8oQ6BuLr7BQ0-g*`m$A}F9Z3FSkY>{pXsayjTya>$9cGj z5V7iCaa|VMq7&QpFN$sd7sbx|7sYmv6hC@&R_@UWjO4LXV;@8cBTihp)#)FfnO%4- z$_P_?Bpv3?2ve_d`UQUxjS|0mJ?t|o<=J1j?DDUg9_}mX$8oL_$G$?Gf{Zv=GcXH^ z=?FjiTpRdPzvEwj&Zep8 z)?tO7{z#V&wOy8RVscDxq3^r}86?Cf;UU_1SahD0PuM>uzyD5_Mqs3~yJQ4AlpV@J zsu>r(YeYB2`91}ip;kR0%0Gil>Oi7J0-T4(6Wn84)n|?kec< zuL3sq0tUxp5IsLEECE%p;AX)>VdEpo^B=g^fZm;Q)+e2$=!~D;HY?6;n-k}^&0kt{ zc7gzqa@HlCb&JjhA_my6+lfxT=&V7?OO;g#N7Yov->#{^MZPL1M7w!v#y9JF>(unn z-@DgL?|8F4-VQBdGv;r_W_Nt^>Oy79bVv60>m484xU$NJc5cI#*@^E~F1UAnr*fus z`s8$5yy1x_G21kEWd3Prh>DxO)HTCj@1EwfKT!RWuRSwuoNm2tnZ9`4b`Kt9 z->#nRTd3MPZJIuL-5Tew+sSv$x2t9kFH~*GhAm0e9Gg8gdvvaKZe;H1`QU9~eloG) z*h1A)*|E#Ny>9mGLRE_r`%AWuU1-7kMYx0r>UI*;?ULEpeBEu|oyJASNp?|?t|dZZ zJcAm}co{WZ@$TP9?yUbYY^L0g9nNEd>Bk$L$MQ{oX?GqgGX163d2Eg8zX;A_mDxNG z!ciEW^xxpf!IPM%k}l7~_&eZ9hJNGfcoM=@PBaRUHhSb^4ewZ;(kOF97%>OLCamEZ zTwNyglI9$iV^&TUXEH|E)E&gj4)zS@h&6X*(-tt=yTr9f1|;VS{K#~|C&)!y1exTl zt{B8g(B+dXTQR^VnFDa_1tjtqOU6?6l94e`a@i)Ww;OMl-Kj|UPbc~Z5*wes>v)Dy z16jc*3o;ofLC*w8f*jZ=Vl~R*wTcJvDYCVlm?&Zmd>Io(tR)xYp2&J1UZkhg~D7O}c79b}wHC zLC1porrpGB`PCR-XRH3zQQl%Z!{0AhncY%0zbmoz@IqPJZCqA+I^_=}{ei^!tM@tX zb9}1-Ka>1n`Z;Xqpr04{PQz5;Cy<0ZVvuR5D4uErxEKxf4fukFYLaQFdKA>vrq42D zLRa^*G8HbE`c?H+Lq#|g=w8r(;7GcpMAc+;T`Fyk!Q(12U00>R>eE=$bX^+z%s?*- z?>D9Cy6n;}=)6SbHL&M91SaXGLvPhPjvz;;lCJivcL>4t2W!76gQ`o?ZpB(0#RUzB zwlp=@-oxasC+oY2mp>XC9HsX(GGDP6B0*-nS0RQrGyEp_O|+YO=p`&5O;YUdJ>h9; z$(AgmU>I2%ZV)5~VhMmw3j%=b&OW)z&>7&2Vx^qi={&tEyi9IHB1oRxy1+#7N#`T~ z060x4%BmHk0gzyx9+7Dz3sj{?F&RG3Af4A)HU~5+R8|C;Oq@eM0s&xOy5X~cW$G|X zFH;CGw@q`!{IdA?w42Che;`~rdm5?e)|a9ZR-2USc@@I}6Uf>xtiGrHtDgOFO3F~* zU7!qf?HBtWPT&0&oM9~6js2ud-AEH3Q%0a!OX_OI>c%>>TR7UuSZ}H+iw#cSDz{Bz z)UF!Cm=VLIEJCZsFb&lCAcU*SA?HLyU4a`55U(I@eBw5Y zEjqM_qhm}7i?|6MBC)u|_2i65)GKl9cWMVT3B#}rWimz! zxwgL$zF+XYf`zSzX6t_DzSIBL<$ts8C+ilvp1EDWROg*D&5a~#4>IK&_bm+9X6iR~ zEjqR_9J>x_r&X+279CrdUscjk6(7FqXjs14t7{C7^z6=X27Qr~{OYeUhTmb0;h}X& z-H4G%+GNldRjgT0$U9Rqs2>bac?E#Lw|EFC^^1qmnUlpGOgIQnJ;|>$VMOnz(q$tRlg$$^!CxjzbWkmRN}rF9-PTbY4Y8%1L~0Eg zyTt@Ml*Vo+k*-v>(&YMIDaxM!1jsGaTHbi_`jaVlW76HY;BHE}H_skU6+v70&V{1g zQ`Qd(O9`ug>e^F@vV)6`Cn11>VN7qTWMRZ*m8mjsvdlY`zf|5RW5jlb5tlk`jlZll z+fJ{F50}p$No;LjDC@W#OPoHFIvq@&4gw!0F{DX(4p3JshR%)*;gwL4ObWa9P9P*b zbjGl<4=BH&G=lyD?XXBkHjhfd&$Qbp@s(esgR=r?(7L(Gar`oMT9a|X4gq*|E-58| zFUunh&$Q1l`t^1OuOt7W?2;Zz546NwlbIg7AOvJP*U-vAx^Y&~U7Jy=6*cHU_cUfa zQW@AmN&>YTwH^+5fF%!h_kWgYkt0@Ul~qyh46U=(s@7OY+P;W_LX<8%LAQTip$|o2 z^dRY#X15^`(u)pc!Tp_3GcX1?F;3QAvY1|jKPDHol&pSi7rDMl)&W>JVs?^S1OFO* zex0n>$@(8*#c0^co0u%gg}dc=sX$X$CRJolxU9hc8zqc=fE1Xx%^R`!jyLz;+`q7< z>3x@XsufDHzP=s%)=M{Enr*%Lg@uYO@0V~s-ej?Nv3TQhMYBs#P~LsLd-me|rRnZuap!%5 zNmr5VQrX%!9XB0wjkhnx9m%pT%=8T#XD!q1i^UC6#kvO&Vr6d`Y`DLcbC&%2p)FTk z?58mt1-W;VXQI^mB%r>0TL)A6kqRu`6{XWQkpg z{|O+uq*wJOY>vXZPpQWn5CMy9p*vMrn=GuI*_|rfnJnC?E~)Kz9Ub?LoO9RmonCFG zuOJQ9O!&<;dd;D%2TH>QH?W4IeKg0QIdgpIbG0;;6_2obMdyN1#ub?mJK>7JMQJw0 zs8`c6kDr4xSNXD{mm&R*$3IhZQM04DNcnPYGOsq3*O<&}lr^4dh|y50dS|kFXR3N{ zvU=}A^%Hj;`_Y6B@A4+3g^rE1OIT)CYC@%%hRSff!NE;7dfNw38$z(sFzjHXyMV7o zLR>~=F-9ICzNo#4q(`^FbB@%`FcBbIev%_gKR^quwnlA%)l+DI`rwELh3K{|&ktS};YxHB}unb99iYU%9y;Y#ZV zsr4U`mXGQ5RZ_$Sm%K=x->kJy#Nl`JH7e!Nek1ulC$-FWgFip4Qfi=GcB2NPxVCUU z*GX030P43%3Gv&NoUz^CKzkQtgym&~{ab_;>etp^K(o+aNH%l|;~{6J_6;M-SJZ36 zw_E)#M*T`6F8xvtRQudiFn?kC*M!^8>`zoM3$BKx}&?1f2_WOlBHe1f?ag z)&CFjR^NS7{`Kek+*EV4ABYE$BENtUNJ=1hf06c(WjBxlLKM)Kv>fCZytT!8QpqLa z_FIrjIeSmbkapu?TqyLA{j13BtKMvcR%9z6*Ws_!=YeMBl8pY#>|2y}#lA(2(6=

`_pho@eQG4t-OtMDds4OTA##eJ$O;z?P`T@a%!3uT_E7esQ@iy+)x|xxO|nL~;4* z=>hHSS=3^nhaM#y=wSm|-j=aG*D7J!FM5~v75Hsv(ZcOUZJl0+hu9;wRvUyy*zYi} zpqM#%)IVk(4U`8;tL_9V=iqJZ!BrUcF4$z1ayv}n_6!9*p%^_GOmtt#(9=3u&@dEe zxDaS~I?!-*Q$x2@7?vO4PR9s{w^7|m^JaSMYO=6Hj;uW2jC(R>dM6<~Y1zOaz#Q@d zUUCkFhJzDf(oYe>gQ(Gnlt)jd;$in;;6lWhhJ4`FG29NL8bQ67a5^fUKO2pnhce~7 z6L^auBt}5%4NJCGyp9~9%RG{)6R)97I=gX?E$AT~Tw_+GO%k3-~;Zox(N zK~>_XIwx??!sejc!4cUzh)-6Cgo+ws>whQEMq|QON6i% z@d1*OWda_;C0S%8AN^jQX*ih_y1}NWx2-|qiiYucndLBhpB}Ze4v&z~m?&A~m+BFh zJyZ`QklH~`6yuH)|1B&uh5cLnvI9AVl0mc4~rJ zW;|bq>e1K{{}-~@iE1CY*kOv+Wm)s{^KeOyw5EmFxe#>8{g49xg#2xIhgKOZR6rTS zUL&8i-X;hG-kF8IX*M`XJM{QDR^Z(7RZ!7LFhiVYu`ZvLjF)3A8DbPaVEJL#jYk9F zvtd>Ug4rgS(I`+AO+6@%Bc0ev@)bDR$*jSbD6O1JRvAys88J3u`+!!a@p@0H(8F$s zt$UA@_$D@VEjo_L_jGcU&81ws=5ST#UVaI^`S!~5sr-7VrAsvIT*%)A<#fe$Go3Sg zW?N?aX4~h?iK1Oo)_aBJsltu#6>eNAs#~h6Un*O-v}Qx1bmPZ1v(r9h`lW+&786Cr zV79sc&f)!gM|;xI4z{swTT{&k@bA@_;y-gT>0ZBB*mS#P%JlR6 zl2@KV0Z4JhwNYrRDD}*gq9(=ODI>jRl}GyE-gA#E3g_5W5mFAFp~ksfriad4OqO`@ zvPnrZG$^n4&Yt|{<(o%t8*T@GWc}XhI|I`;(vJ)|ka*`T|5gX8dGXfHIqy=X=gqF0 zT{FS7^1c2)f9}?E^DW6u2j+uG=r^watLAr_?_7Lm3-o#>5BDcdJ(D^WNS+ELUI->n zorT_-$pC)nq2lN^T&3ssAA^aeA%7; zq^l3Tsc6F1TBM>T-ZWDKRn*7dIzH!mt9Pz7S-&e$w|nj)G{;xHU3L3na&H$D>+C(A z*wcNdFL9zjb>ivdiKi3KoJpQ|7H`odPXrRZFC@x>)8-}UwZ3xw%1r-T1Bl-8y@}f$ z(^nE}jzJ@KWesb&p;Y7UWaI96KH0br4cB;Je&Y7Yx34Tz9-TJ5VOy$!a_p}ZJg{la zVzM3MmmCFjyLP($)$a6JG`?|WXy#O+tog2E)2|^ zjkt_Ea?erp+xup~{PrQ%DuU;cbXEkJK)Ug0%F&f{bo~}R1&B{$gc7}5;e4u$`{}lZ z<96<^%k0Ok#=owuIBqch%wUH5XLkGXJ;t9EuRXrq__OV1xCb$LRU^Q~PIdxjqn^GK z@MKkB&7pU+1*A!XP+WR9e=>EP;5H&|68Y%QL|k5^LS@P^>ggtm(+z|>WkU+4_2J!| za(GuTCY<54c$VKGo+%@q^>>H|r2}fI(JljRn~*=wA_9nh*&#kP#M+CSOAyB$L9KL% zi}2N97Wyq3{sahM{kcYuU8jlR4vZ-A!Dr{`H14(c1ics)S&ZG4E=>_7FU?cWxwb$d zDqos0o3j$6;NSNK62*PgEu>|cEssLjQntpH$B2}ck6$HT#?1^WsLpj0<}It@Ay)bC zapi#L*R1UyM>ejb#*q$7jHIro1uCIwK@UD52>BYxp}c-CdzG&j7wXOmkC34v(*`; z+g7{RkbU`~4ZXI)%>}|Gne+k)faPc*Fs;a0H0dp=$|9yLBr-86^NqjHMhA>`FCn-# zbAg4t0pqsF_A-*2Dp`$X%}iHAm2$3-iiObeN2FrxH|Z{YCf%hkd60x~QhSl-kl&$6UYes`Cqh>h7MP2SRB@s%RI3kNNHYpgOK0aMP)ISfc(OsUd zr-AC}HG<(o7m{REs^sbs{|JqA%P3yQk1X!bU&`kEyiOrsg7q9##DhqzBBg!r)$fe^ z{&Q@;=FYBn&fmCr{o>oP>lfkqn+F1b{!Kv*|3-ez?^!7#20w14a%&@g8HHV;4$o)R zq5Q;q>-WqUe^dvRgu$PbzFBj#=AF8mHSqk6c!R1`=9rUN|GgeX6TTGQMypFXQ61%RNFmwX|l9$rae`^6J5Pf z+PC0_$|Afrlq^3nGoD(%2aUH-eqy2Y#MF@w8k(kuUVm|R5KB7%ulv@(?C?Uve!Tqto^U{3dVt`n27_Hb z2Ax8Sfx)%H%Oc8Q0_+SmHk5&`D&V_pzf%dS5orF2m@*^{jTxz$&)AgG5hF_3rk@c4& zHykPodn6<2D{4j)kJ4%^{xb?BPl|kUHIPL;AyZEcn(9)#V7;xab?dgaNmJdy>?dm?j8O^gz23?629b*`^y7g|d5&LR<^!yYc+>=NC#EQYF|l7aW`L zM1Z4UiocidoOZq8i@U!*h}X6*EmUt_DA|&9ZCS|Q3Yw8%PYI;TKHeI?2%5*)w;E?_ zW`nmH=0nueJ^ffdUbA zuHbk|Ipr8V_6o_rFa^6tMiS7Ar5@+CIYi87DU$6d*acglm~ zc#n}r1W4KzP~$N-(LG4OdX(3eP#Gg(Tu1^-OzgJQH=KinlpEb?-k`;TW+Fw0R=puW_jU+c` zYGzyKhH%3z>3D(`bM`D>HLi}#v?T=m()$nWg^g{CYYyHOo|K0*b(UhNW7x2cz_F5q zjB?0gJT-NwDoJoyD3yhlLC_f{$N2bcUMd?@ke#uyS8Iq(0iH+UV0d)wY&0n1MHqTb z8+w&hkM#46)Ph*n2t~u5eq}rpWfbp`Z&7yh(%UtcsdWjPprr`9t4KTYqEOA;^k!jv za8anGmV&~v>CqWud?HcYa93!QTML6rHEL@;178}(s23MjgV|&3nXQ`+ISX7G+(?~v zfv*m{)|%Cvw#fmOmi`>0cNA3mOGyX#IVK-&u<(6^gXS0o8rW-z!d=y*Ir<@7_Z$Ss zH7NFoySm(Dh|`_U;C1SSH?JN(!YSc+j;s@6;D=C9u@#o&V3Uh9;DhDJcu10olu)r} zMaAzC-2Y70dRU5F6-_6x3sxF4O)m}vm!nu4w`b`U($CW{`38b92|p~YfM{vneUr)N zVj@*_$wK_w!Y-T2Z!4y1cO`3~x^ee?0YLXk%H#EKdT)ADYqurWZd+Kpl}akF-PXx-S?3>2O^;!c;Z>`k^~b%69$S;Ut2!>$eZVXJORs3@t^SO667aXqQ-Z@}DY&X7ZkIC={5-uai&yAiUc8&&w~{%5Sa`dV=upQ*4H+%quRW^ESEZ zQUTBwRzPygj6-(S0JojTCq&$(27@__RCHkA`wc{5rI8Lv>!asBtnhQRuEiuyu&LZ7%<0 zgUMX|NkOT3?Na42Qs4BB22E`m*I^G;A-qHk zg}`{AU_2UuB=SwfWC~GfH60$8@`j^>6R`j;>fo-#S1FJ>9!KdAFhA%mFv~Z8j*_SG zeCVotNrDzyl_)2l45T9VQd(Bd;vI~t*J+IGZ53IJS zv&1S*6|74ZtRqgdE6qH7wTm2}n=Lvjm)s>&U3fd#Rx*8RL8yPZ^`0pYH)dRmri!IJ z$IC}aR(RQZNynb=*0iqY-dS&N-C=xZI}ckXLs_)>E|vgn(!ofSo|im5QM^L_Hcc`% z^Gj*I4^Lo0!F(5K(BM_h^XzRpS*@Z8ULtMsvam!x+7j=tC?E`Tq(LB+k6^=rXiO*o zVVscsHgq5uyBZl3sXIkF*5+tD+z%pd2cOUK{Qm$w%fQ0` literal 0 HcmV?d00001 diff --git a/__pycache__/prenota_sprenota_sql.cpython-313.pyc b/__pycache__/prenota_sprenota_sql.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95518bcb23a30a5d5de889175fce4378b49092e4 GIT binary patch literal 8505 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 literal 0 HcmV?d00001 diff --git a/__pycache__/reset_corsie.cpython-313.pyc b/__pycache__/reset_corsie.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0be68af6a1ea9f62bda4e109ddb6acb80195d93d GIT binary patch literal 16364 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 literal 0 HcmV?d00001 diff --git a/__pycache__/search_pallets.cpython-313.pyc b/__pycache__/search_pallets.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..775cdc1d9e37febff5a009159ab2637d9ebc1573 GIT binary patch literal 22680 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 AhyVZp literal 0 HcmV?d00001 diff --git a/__pycache__/view_celle_multiple.cpython-313.pyc b/__pycache__/view_celle_multiple.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..446d29f4dbd91de14f481295f41105eacc51fe2e GIT binary patch literal 26565 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 aL;ZKGx2m1D-0U| literal 0 HcmV?d00001 diff --git a/assets/fonts/Font Awesome 7 Brands-Regular-400.otf b/assets/fonts/Font Awesome 7 Brands-Regular-400.otf new file mode 100644 index 0000000000000000000000000000000000000000..672a35b16d10f03164ba77d1f8a7ead7aa115e7b GIT binary patch literal 199352 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%0A51l6F&c!?l^XUTV<^Arj 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 F{{^Tn=c@n! literal 0 HcmV?d00001 diff --git a/assets/fonts/Font Awesome 7 Free-Regular-400.otf b/assets/fonts/Font Awesome 7 Free-Regular-400.otf new file mode 100644 index 0000000000000000000000000000000000000000..d96d2eab9b54b5c93ec90a6b7f1abe0b5ce03736 GIT binary patch literal 87332 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 literal 0 HcmV?d00001 diff --git a/assets/fonts/Font Awesome 7 Free-Solid-900.otf b/assets/fonts/Font Awesome 7 Free-Solid-900.otf new file mode 100644 index 0000000000000000000000000000000000000000..90d72a64f36136913874154cce81912017c342b0 GIT binary patch literal 410580 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

6=3(=QdDJ{+9%rknC(TplX|uvSW1cn7 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

cKUPu3^=6 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 Wf9g8nZopW9i6duD!ZV}E=>Gr)+oPxe literal 0 HcmV?d00001 diff --git a/assets/icons/home.png b/assets/icons/home.png new file mode 100644 index 0000000000000000000000000000000000000000..f10cc0d5c865336898fe66ca2262b816201ae0f4 GIT binary patch literal 3699 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 literal 0 HcmV?d00001 diff --git a/async_loop_singleton.py b/async_loop_singleton.py new file mode 100644 index 0000000..ad765e3 --- /dev/null +++ b/async_loop_singleton.py @@ -0,0 +1,35 @@ +# async_loop_singleton.py +import asyncio, threading +from typing import Callable + +class _LoopHolder: + def __init__(self): + self.loop = None + self.thread = None + +_GLOBAL = _LoopHolder() + +def get_global_loop() -> asyncio.AbstractEventLoop: + """Start a single asyncio loop in a background thread and return it.""" + if _GLOBAL.loop: + return _GLOBAL.loop + + ready = threading.Event() + + def _run(): + _GLOBAL.loop = asyncio.new_event_loop() + asyncio.set_event_loop(_GLOBAL.loop) + ready.set() + _GLOBAL.loop.run_forever() + + _GLOBAL.thread = threading.Thread(target=_run, name="asyncio-bg-loop", daemon=True) + _GLOBAL.thread.start() + ready.wait() + return _GLOBAL.loop + +def stop_global_loop(): + if _GLOBAL.loop and _GLOBAL.loop.is_running(): + _GLOBAL.loop.call_soon_threadsafe(_GLOBAL.loop.stop) + _GLOBAL.thread.join(timeout=2) + _GLOBAL.loop = None + _GLOBAL.thread = None diff --git a/async_msssql_query.py b/async_msssql_query.py new file mode 100644 index 0000000..be00967 --- /dev/null +++ b/async_msssql_query.py @@ -0,0 +1,93 @@ +# async_msssql_query.py — loop-safe, compat rows=list, no pooling +from __future__ import annotations + +import asyncio, urllib.parse, time, logging +from typing import Any, Dict, Optional +from sqlalchemy.ext.asyncio import create_async_engine +from sqlalchemy.pool import NullPool +from sqlalchemy import text + +try: + import orjson as _json + def _dumps(obj: Any) -> str: return _json.dumps(obj, default=str).decode("utf-8") +except Exception: + import json as _json + def _dumps(obj: Any) -> str: return _json.dumps(obj, default=str) + +def make_mssql_dsn( + *, server: str, database: str, user: Optional[str]=None, password: Optional[str]=None, + driver: str="ODBC Driver 17 for SQL Server", trust_server_certificate: bool=True, + encrypt: Optional[str]=None, extra_odbc_kv: Optional[Dict[str,str]]=None +) -> str: + kv = {"DRIVER": driver, "SERVER": server, "DATABASE": database, + "TrustServerCertificate": "Yes" if trust_server_certificate else "No"} + if user: kv["UID"] = user + if password: kv["PWD"] = password + if encrypt: kv["Encrypt"] = encrypt + if extra_odbc_kv: kv.update(extra_odbc_kv) + odbc = ";".join(f"{k}={v}" for k,v in kv.items()) + ";" + return f"mssql+aioodbc:///?odbc_connect={urllib.parse.quote_plus(odbc)}" + +class AsyncMSSQLClient: + """ + Engine creato pigramente sul loop corrente, senza pool (NullPool). + Evita “Future attached to a different loop†nei reset/close del pool. + """ + def __init__(self, dsn: str, *, echo: bool=False, log: bool=True): + self._dsn = dsn + self._echo = echo + self._engine = None + self._engine_loop: Optional[asyncio.AbstractEventLoop] = None + self._logger = logging.getLogger("AsyncMSSQLClient") + if log and not self._logger.handlers: + h = logging.StreamHandler() + h.setFormatter(logging.Formatter("[%(levelname)s] %(message)s")) + self._logger.addHandler(h) + self._enable_log = log + + async def _ensure_engine(self): + if self._engine is not None: + return + loop = asyncio.get_running_loop() + self._engine = create_async_engine( + self._dsn, + echo=self._echo, + # IMPORTANTI: + poolclass=NullPool, # no pooling → no reset su loop “sbagliati†+ connect_args={"loop": loop}, # usa il loop corrente in aioodbc + ) + self._engine_loop = loop + if self._enable_log: + self._logger.info("Engine created on loop %s", id(loop)) + + async def dispose(self): + if self._engine is None: + return + # sempre sullo stesso loop in cui è nato + if asyncio.get_running_loop() is self._engine_loop: + await self._engine.dispose() + else: + fut = asyncio.run_coroutine_threadsafe(self._engine.dispose(), self._engine_loop) + fut.result(timeout=2) + self._engine = None + if self._enable_log: + self._logger.info("Engine disposed") + + async def query_json(self, sql: str, params: Optional[Dict[str, Any]]=None, *, as_dict_rows: bool=False) -> Dict[str, Any]: + await self._ensure_engine() + t0 = time.perf_counter() + async with self._engine.connect() as conn: + res = await conn.execute(text(sql), params or {}) + rows = res.fetchall() + cols = list(res.keys()) + if as_dict_rows: + rows_out = [dict(zip(cols, r)) for r in rows] + else: + rows_out = [list(r) for r in rows] + return {"columns": cols, "rows": rows_out, "elapsed_ms": round((time.perf_counter()-t0)*1000, 3)} + + async def exec(self, sql: str, params: Optional[Dict[str, Any]]=None, *, commit: bool=False) -> int: + await self._ensure_engine() + async with (self._engine.begin() if commit else self._engine.connect()) as conn: + res = await conn.execute(text(sql), params or {}) + return res.rowcount or 0 diff --git a/async_runner.py b/async_runner.py new file mode 100644 index 0000000..983a183 --- /dev/null +++ b/async_runner.py @@ -0,0 +1,25 @@ +# async_runner.py +import asyncio +from typing import Callable + +class AsyncRunner: + """Esegue un awaitable sul loop globale e richiama i callback in Tk via .after.""" + def __init__(self, tk_root, loop: asyncio.AbstractEventLoop): + self.tk = tk_root + self.loop = loop + + def run(self, awaitable, on_ok: Callable, on_err: Callable, busy=None, message: str | None=None): + if busy: busy.show(message or "Lavoro in corso…") + fut = asyncio.run_coroutine_threadsafe(awaitable, self.loop) + self._poll(fut, on_ok, on_err, busy) + + def _poll(self, fut, on_ok, on_err, busy): + if fut.done(): + if busy: busy.hide() + try: + res = fut.result() + on_ok(res) + except Exception as ex: + on_err(ex) + return + self.tk.after(50, lambda: self._poll(fut, on_ok, on_err, busy)) diff --git a/backups/autosave.tcl.bak1 b/backups/autosave.tcl.bak1 new file mode 100644 index 0000000..1dc9340 --- /dev/null +++ b/backups/autosave.tcl.bak1 @@ -0,0 +1,148 @@ +############################################################################# +# Generated by PAGE version 8.0 +# in conjunction with Tcl version 8.6 +# Sep 15, 2025 05:35:31 PM CEST platform: Windows NT +set vTcl(timestamp) "" +if {![info exists vTcl(borrow)]} { + ::vTcl::MessageBox -title Error -message "You must open project files from within PAGE." + exit} + + +set vTcl(actual_gui_font_dft_desc) TkDefaultFont +set vTcl(actual_gui_font_dft_name) TkDefaultFont +set vTcl(actual_gui_font_text_desc) TkTextFont +set vTcl(actual_gui_font_text_name) TkTextFont +set vTcl(actual_gui_font_fixed_desc) TkFixedFont +set vTcl(actual_gui_font_fixed_name) TkFixedFont +set vTcl(actual_gui_font_menu_desc) TkMenuFont +set vTcl(actual_gui_font_menu_name) TkMenuFont +set vTcl(actual_gui_font_tooltip_desc) TkDefaultFont +set vTcl(actual_gui_font_tooltip_name) TkDefaultFont +set vTcl(actual_gui_font_treeview_desc) TkDefaultFont +set vTcl(actual_gui_font_treeview_name) TkDefaultFont +########################################### +set vTcl(actual_gui_bg) #d9d9d9 +set vTcl(actual_gui_fg) #000000 +set vTcl(actual_gui_analog) #ececec +set vTcl(actual_gui_menu_analog) #ececec +set vTcl(actual_gui_menu_bg) #d9d9d9 +set vTcl(actual_gui_menu_fg) #000000 +set vTcl(complement_color) gray40 +set vTcl(analog_color_p) #c3c3c3 +set vTcl(analog_color_m) beige +set vTcl(tabfg1) black +set vTcl(tabfg2) white +set vTcl(actual_gui_menu_active_bg) #ececec +set vTcl(actual_gui_menu_active_fg) #000000 +########################################### +set vTcl(pr,autoalias) 1 +set vTcl(pr,relative_placement) 1 +set vTcl(mode) Relative +set vTcl(project_theme) default + + + +proc vTclWindow.top1 {base} { + global vTcl + if {$base == ""} { + set base .top1 + } + if {[winfo exists $base]} { + wm deiconify $base; return + } + set top $base + set target $base + ################### + # CREATING WIDGETS + ################### + vTcl::widgets::core::toplevel::createCmd $top -class Toplevel \ + -background #d9d9d9 -highlightbackground #d9d9d9 \ + -highlightcolor #000000 + wm focusmodel $top passive + wm geometry $top 600x450+374+144 + update + # set in toplevel.wgt. + global vTcl + global img_list + set vTcl(save,dflt,origin) 0 + wm maxsize $top 3364 881 + wm minsize $top 120 1 + wm overrideredirect $top 0 + wm resizable $top 1 1 + wm deiconify $top + set toptitle "Toplevel 0" + wm title $top $toptitle + namespace eval ::widgets::${top}::ClassOption {} + set ::widgets::${top}::ClassOption(-toptitle) $toptitle + vTcl:DefineAlias "$top" "Toplevel1" vTcl:Toplevel:WidgetProc "" 1 + set vTcl(real_top) {} + button "$top.but47" \ + -activebackground #d9d9d9 -activeforeground black -background #d9d9d9 \ + -disabledforeground #a3a3a3 -font "-family {Segoe UI} -size 9" \ + -foreground #000000 -highlightbackground #d9d9d9 \ + -highlightcolor #000000 -text "Button" + vTcl:DefineAlias "$top.but47" "Button1" vTcl:WidgetProc "Toplevel1" 1 + frame "$top.fra48" \ + -borderwidth 2 -relief groove -background #d9d9d9 -height 355 \ + -highlightbackground #d9d9d9 -highlightcolor #000000 -width 565 + vTcl:DefineAlias "$top.fra48" "Frame1" vTcl:WidgetProc "Toplevel1" 1 + set site_3_0 $top.fra48 + vTcl::widgets::ttk::pnotebook::createCmd "$site_3_0.pNo49" \ + -width 512 -height 304 -style "PC.TNotebook" -style PC.TNotebook + vTcl:DefineAlias "$site_3_0.pNo49" "PNotebook1" vTcl:WidgetProc "Toplevel1" 1 + $site_3_0.pNo49 configure -style "PC.TNotebook" + bind $site_3_0.pNo49 { + _button_press + } + bind $site_3_0.pNo49 { + _button_release + } + bind $site_3_0.pNo49 { + _mouse_over + } + ttk::frame "$site_3_0.pNo49.t0" + vTcl:DefineAlias "$site_3_0.pNo49.t0" "PNotebook1_t1" vTcl:WidgetProc "Toplevel1" 1 + $site_3_0.pNo49 add $site_3_0.pNo49.t0 \ + -padding 0 -sticky nsew -state normal -text "Page 1" -image image6 \ + -compound right -underline -1 + set site_5_0 $site_3_0.pNo49.t0 + ttk::frame "$site_3_0.pNo49.t1" + vTcl:DefineAlias "$site_3_0.pNo49.t1" "PNotebook1_t2" vTcl:WidgetProc "Toplevel1" 1 + $site_3_0.pNo49 add $site_3_0.pNo49.t1 \ + -padding 0 -sticky nsew -state normal -text "Page 2" -image image6 \ + -compound right -underline -1 + set site_5_1 $site_3_0.pNo49.t1 + place $site_3_0.pNo49 \ + -in $site_3_0 -x 0 -relx 0.035 -y 0 -rely 0.056 -width 0 \ + -relwidth 0.906 -height 0 -relheight 0.856 -anchor nw \ + -bordermode ignore + ################### + # SETTING GEOMETRY + ################### + place $top.but47 \ + -in $top -x 0 -relx 0.033 -y 0 -rely 0.022 -width 97 -relwidth 0 \ + -height 46 -relheight 0 -anchor nw -bordermode ignore + place $top.fra48 \ + -in $top -x 0 -relx 0.033 -y 0 -rely 0.178 -width 0 -relwidth 0.942 \ + -height 0 -relheight 0.789 -anchor nw -bordermode ignore + + vTcl:FireEvent $base <> +} + +proc 36 {args} {return 1} + + +Window show . +set btop1 "" +if {$vTcl(borrow)} { + set btop1 .bor[expr int([expr rand() * 100])] + while {[lsearch $btop1 $vTcl(tops)] != -1} { + set btop1 .bor[expr int([expr rand() * 100])] + } +} +set vTcl(btop) $btop1 +Window show .top1 $btop1 +if {$vTcl(borrow)} { + $btop1 configure -background plum +} + diff --git a/backups/autosave.tcl.bak2 b/backups/autosave.tcl.bak2 new file mode 100644 index 0000000..13f28e9 --- /dev/null +++ b/backups/autosave.tcl.bak2 @@ -0,0 +1,148 @@ +############################################################################# +# Generated by PAGE version 8.0 +# in conjunction with Tcl version 8.6 +# Sep 15, 2025 05:34:52 PM CEST platform: Windows NT +set vTcl(timestamp) "" +if {![info exists vTcl(borrow)]} { + ::vTcl::MessageBox -title Error -message "You must open project files from within PAGE." + exit} + + +set vTcl(actual_gui_font_dft_desc) TkDefaultFont +set vTcl(actual_gui_font_dft_name) TkDefaultFont +set vTcl(actual_gui_font_text_desc) TkTextFont +set vTcl(actual_gui_font_text_name) TkTextFont +set vTcl(actual_gui_font_fixed_desc) TkFixedFont +set vTcl(actual_gui_font_fixed_name) TkFixedFont +set vTcl(actual_gui_font_menu_desc) TkMenuFont +set vTcl(actual_gui_font_menu_name) TkMenuFont +set vTcl(actual_gui_font_tooltip_desc) TkDefaultFont +set vTcl(actual_gui_font_tooltip_name) TkDefaultFont +set vTcl(actual_gui_font_treeview_desc) TkDefaultFont +set vTcl(actual_gui_font_treeview_name) TkDefaultFont +########################################### +set vTcl(actual_gui_bg) #d9d9d9 +set vTcl(actual_gui_fg) #000000 +set vTcl(actual_gui_analog) #ececec +set vTcl(actual_gui_menu_analog) #ececec +set vTcl(actual_gui_menu_bg) #d9d9d9 +set vTcl(actual_gui_menu_fg) #000000 +set vTcl(complement_color) gray40 +set vTcl(analog_color_p) #c3c3c3 +set vTcl(analog_color_m) beige +set vTcl(tabfg1) black +set vTcl(tabfg2) white +set vTcl(actual_gui_menu_active_bg) #ececec +set vTcl(actual_gui_menu_active_fg) #000000 +########################################### +set vTcl(pr,autoalias) 1 +set vTcl(pr,relative_placement) 1 +set vTcl(mode) Relative +set vTcl(project_theme) default + + + +proc vTclWindow.top1 {base} { + global vTcl + if {$base == ""} { + set base .top1 + } + if {[winfo exists $base]} { + wm deiconify $base; return + } + set top $base + set target $base + ################### + # CREATING WIDGETS + ################### + vTcl::widgets::core::toplevel::createCmd $top -class Toplevel \ + -background #d9d9d9 -highlightbackground #d9d9d9 \ + -highlightcolor #000000 + wm focusmodel $top passive + wm geometry $top 600x450+374+144 + update + # set in toplevel.wgt. + global vTcl + global img_list + set vTcl(save,dflt,origin) 0 + wm maxsize $top 3364 881 + wm minsize $top 120 1 + wm overrideredirect $top 0 + wm resizable $top 1 1 + wm deiconify $top + set toptitle "Toplevel 0" + wm title $top $toptitle + namespace eval ::widgets::${top}::ClassOption {} + set ::widgets::${top}::ClassOption(-toptitle) $toptitle + vTcl:DefineAlias "$top" "Toplevel1" vTcl:Toplevel:WidgetProc "" 1 + set vTcl(real_top) {} + button "$top.but47" \ + -activebackground #d9d9d9 -activeforeground black -background #d9d9d9 \ + -disabledforeground #a3a3a3 -font "-family {Segoe UI} -size 9" \ + -foreground #000000 -highlightbackground #d9d9d9 \ + -highlightcolor #000000 -text "Button" + vTcl:DefineAlias "$top.but47" "Button1" vTcl:WidgetProc "Toplevel1" 1 + frame "$top.fra48" \ + -borderwidth 2 -relief groove -background #d9d9d9 -height 355 \ + -highlightbackground #d9d9d9 -highlightcolor #000000 -width 565 + vTcl:DefineAlias "$top.fra48" "Frame1" vTcl:WidgetProc "Toplevel1" 1 + set site_3_0 $top.fra48 + vTcl::widgets::ttk::pnotebook::createCmd "$site_3_0.pNo49" \ + -width 300 -height 200 -style "PC.TNotebook" -style PC.TNotebook + vTcl:DefineAlias "$site_3_0.pNo49" "PNotebook1" vTcl:WidgetProc "Toplevel1" 1 + $site_3_0.pNo49 configure -style "PC.TNotebook" + bind $site_3_0.pNo49 { + _button_press + } + bind $site_3_0.pNo49 { + _button_release + } + bind $site_3_0.pNo49 { + _mouse_over + } + ttk::frame "$site_3_0.pNo49.t0" + vTcl:DefineAlias "$site_3_0.pNo49.t0" "PNotebook1_t1" vTcl:WidgetProc "Toplevel1" 1 + $site_3_0.pNo49 add $site_3_0.pNo49.t0 \ + -padding 0 -sticky nsew -state normal -text "Page 1" -image image6 \ + -compound right -underline -1 + set site_5_0 $site_3_0.pNo49.t0 + ttk::frame "$site_3_0.pNo49.t1" + vTcl:DefineAlias "$site_3_0.pNo49.t1" "PNotebook1_t2" vTcl:WidgetProc "Toplevel1" 1 + $site_3_0.pNo49 add $site_3_0.pNo49.t1 \ + -padding 0 -sticky nsew -state normal -text "Page 2" -image image6 \ + -compound right -underline -1 + set site_5_1 $site_3_0.pNo49.t1 + place $site_3_0.pNo49 \ + -in $site_3_0 -x 0 -relx 0.035 -y 0 -rely 0.056 -width 0 \ + -relwidth 0.535 -height 0 -relheight 0.631 -anchor nw \ + -bordermode ignore + ################### + # SETTING GEOMETRY + ################### + place $top.but47 \ + -in $top -x 0 -relx 0.033 -y 0 -rely 0.022 -width 97 -relwidth 0 \ + -height 46 -relheight 0 -anchor nw -bordermode ignore + place $top.fra48 \ + -in $top -x 0 -relx 0.033 -y 0 -rely 0.178 -width 0 -relwidth 0.942 \ + -height 0 -relheight 0.789 -anchor nw -bordermode ignore + + vTcl:FireEvent $base <> +} + +proc 36 {args} {return 1} + + +Window show . +set btop1 "" +if {$vTcl(borrow)} { + set btop1 .bor[expr int([expr rand() * 100])] + while {[lsearch $btop1 $vTcl(tops)] != -1} { + set btop1 .bor[expr int([expr rand() * 100])] + } +} +set vTcl(btop) $btop1 +Window show .top1 $btop1 +if {$vTcl(borrow)} { + $btop1 configure -background plum +} + diff --git a/baseline_Mediseawall.json b/baseline_Mediseawall.json new file mode 100644 index 0000000..40ffe9e --- /dev/null +++ b/baseline_Mediseawall.json @@ -0,0 +1,4 @@ +{ + "db": "Mediseawall", + "baseline": {} +} \ No newline at end of file diff --git a/db_async_singleton.py b/db_async_singleton.py new file mode 100644 index 0000000..535df6b --- /dev/null +++ b/db_async_singleton.py @@ -0,0 +1,33 @@ +# db_async_singleton.py +import asyncio +from sqlalchemy.ext.asyncio import create_async_engine +from sqlalchemy import text + +class AsyncDB: + def __init__(self, engine): + self.engine = engine + + async def query_json(self, sql: str, params: dict): + async with self.engine.connect() as conn: + result = await conn.execute(text(sql), params) + rows = [tuple(r) for r in result] + return {"rows": rows} + +_ENGINE = None + +async def _make_engine_async(conn_str: str): + return create_async_engine(conn_str, pool_pre_ping=True, future=True) + +def get_db(loop: asyncio.AbstractEventLoop, conn_str: str) -> AsyncDB: + """Crea l'engine UNA volta, dentro il loop globale, e restituisce il client.""" + global _ENGINE + if _ENGINE is None: + fut = asyncio.run_coroutine_threadsafe(_make_engine_async(conn_str), loop) + _ENGINE = fut.result() + return AsyncDB(_ENGINE) + +async def dispose_async(): + global _ENGINE + if _ENGINE is not None: + await _ENGINE.dispose() + _ENGINE = None diff --git a/fix_layout_window.py b/fix_layout_window.py new file mode 100644 index 0000000..b0589b9 --- /dev/null +++ b/fix_layout_window.py @@ -0,0 +1,40 @@ +import re +from pathlib import Path + +# Path default (modifica se serve) +p = Path("./layout_window.py") +if not p.exists(): + raise SystemExit(f"File non trovato: {p}") + +src = p.read_text(encoding="utf-8") + +# 1) Rimuovi i parametri border_color="transparent" nelle chiamate configure(...). +# Gestiamo i casi ", border_color='transparent'" e "border_color='transparent'," +patterns = [ + re.compile(r""",\s*border_color\s*=\s*["']transparent["']"""), # , border_color="transparent" + re.compile(r"""border_color\s*=\s*["']transparent["']\s*,\s*""") # border_color="transparent", +] +for pat in patterns: + src = pat.sub("", src) + +# 2) Se sono rimaste virgole prima della parentesi di chiusura: ", )" -> ")" +src = re.sub(r",\s*\)", ")", src) + +# 3) (opzionale/robusto) Rimuovi border_color=None se presente in qualche versione +patterns_none = [ + re.compile(r""",\s*border_color\s*=\s*None"""), + re.compile(r"""border_color\s*=\s*None\s*,\s*""") +] +for pat in patterns_none: + src = pat.sub("", src) +src = re.sub(r",\s*\)", ")", src) + +# 4) NOTE: manteniamo eventuali border_color="blue" per l’highlight + +# Scrivi backup e nuovo file +bak = p.with_suffix(".py.bak_fix_bc_transparent") +if not bak.exists(): + bak.write_text(Path(p).read_text(encoding="utf-8"), encoding="utf-8") + +p.write_text(src, encoding="utf-8") +print(f"Patch applicata a {p}. Backup: {bak}") diff --git a/fix_query.py b/fix_query.py new file mode 100644 index 0000000..165272e --- /dev/null +++ b/fix_query.py @@ -0,0 +1,87 @@ +from pathlib import Path +import re + +p = Path("./layout_window.py") +src = p.read_text(encoding="utf-8") + +backup = p.with_suffix(".py.bak_perf") +if not backup.exists(): + backup.write_text(src, encoding="utf-8") + +# 1) Rimuovi il bind su che innescava refresh continui. +src = src.replace( + ' self.bind("", lambda e: self.after_idle(self._refresh_stats))\n', + ' # disabilitato: il refresh ad ogni generava molte query/lag\n' + ' # self.bind("", lambda e: self.after_idle(self._refresh_stats))\n' +) + +# 2) Nel metodo _refresh_stats, elimina il blocco che interroga il DB "globale". +# Riconosciamo il blocco su "sql_tot = ..." e lo neutralizziamo. +src = re.sub( + r"\n\s*# globale dal DB[\s\S]*?self\._async\.run\(.*?\)\)\n", + "\n # [patch] rimosso refresh globale da DB: calcoliamo solo dalla matrice in memoria\n", + src, + flags=re.MULTILINE +) + +# 3) Aggiungi un flag di vita finestra e un destroy sicuro +# - settiamo self._alive = True in __init__ +# - override destroy() per annullare timer e marcare _alive=False +src = src.replace( + " self._last_req = 0\n", + " self._last_req = 0\n" + " self._alive = True\n" + " self._stats_after_id = None # se mai userai un refresh periodico, potremo cancellarlo qui\n" +) + +# aggiungi metodo destroy() se non esiste già +if "def destroy(self):" not in src: + insert_point = src.find("def open_layout_window(") + destroy_method = ( + "\n def destroy(self):\n" + " # evita nuovi refresh/async dopo destroy\n" + " self._alive = False\n" + " # cancella eventuali timer\n" + " try:\n" + " if self._stats_after_id is not None:\n" + " self.after_cancel(self._stats_after_id)\n" + " except Exception:\n" + " pass\n" + " # pulizia UI leggera\n" + " try:\n" + " for w in list(self.host.winfo_children()):\n" + " w.destroy()\n" + " except Exception:\n" + " pass\n" + " try:\n" + " super().destroy()\n" + " except Exception:\n" + " pass\n\n" + ) + src = src[:insert_point] + destroy_method + src[insert_point:] + +# 4) Nei callback _ok/_err delle query, assicurati che non facciano nulla se la finestra è chiusa +# => sostituiamo 'def _ok(res):' con un guard iniziale e idem per _err. +src = re.sub( + r"def _ok\(res\):\n", + "def _ok(res):\n" + " if not getattr(self, '_alive', True) or not self.winfo_exists():\n" + " return\n", + src +) +src = re.sub( + r"def _err\(ex\):\n", + "def _err(ex):\n" + " if not getattr(self, '_alive', True) or not self.winfo_exists():\n" + " return\n", + src +) + +# 5) Piccola robustezza: prima di schedulare highlight post-ricarica controlla ancora _alive +src = src.replace( + " if self._pending_focus and self._pending_focus[0] == corsia:\n", + " if getattr(self, '_alive', True) and self._pending_focus and self._pending_focus[0] == corsia:\n" +) + +p.write_text(src, encoding="utf-8") +print(f"Patch applicata a {p} (backup in {backup}).") diff --git a/gestione_aree_frame_async.py b/gestione_aree_frame_async.py new file mode 100644 index 0000000..cd65196 --- /dev/null +++ b/gestione_aree_frame_async.py @@ -0,0 +1,170 @@ +# gestione_aree_frame_async.py +from __future__ import annotations + +import asyncio +import threading +import tkinter as tk +import customtkinter as ctk +from typing import Any, Callable, Optional + +__VERSION__ = "GestioneAreeFrame v3.2.5-singleloop" +#print("[GestioneAreeFrame] loaded", __VERSION__) + +try: + from async_msssql_query import AsyncMSSQLClient # noqa: F401 +except Exception: + AsyncMSSQLClient = object # type: ignore + +# ======================== +# Global asyncio loop +# ======================== +class _LoopHolder: + def __init__(self): + self.loop: Optional[asyncio.AbstractEventLoop] = None + self.thread: Optional[threading.Thread] = None + self.ready = threading.Event() + +_GLOBAL = _LoopHolder() + +def _run_loop(): + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + _GLOBAL.loop = loop + _GLOBAL.ready.set() + loop.run_forever() + +def get_global_loop() -> asyncio.AbstractEventLoop: + if _GLOBAL.loop is not None: + return _GLOBAL.loop + _GLOBAL.thread = threading.Thread(target=_run_loop, name="warehouse-asyncio", daemon=True) + _GLOBAL.thread.start() + _GLOBAL.ready.wait(timeout=5.0) + if _GLOBAL.loop is None: + raise RuntimeError("Impossibile avviare l'event loop globale") + return _GLOBAL.loop + +def stop_global_loop(): + if _GLOBAL.loop and _GLOBAL.loop.is_running(): + _GLOBAL.loop.call_soon_threadsafe(_GLOBAL.loop.stop) + if _GLOBAL.thread: + _GLOBAL.thread.join(timeout=2.0) + _GLOBAL.loop = None + _GLOBAL.thread = None + _GLOBAL.ready.clear() + +# ======================== +# Busy overlay +# ======================== +class BusyOverlay: + def __init__(self, parent: tk.Misc): + self.parent = parent + self._top: Optional[ctk.CTkToplevel] = None + self._pb: Optional[ctk.CTkProgressBar] = None + self._lbl: Optional[ctk.CTkLabel] = None + self._bind_id = None + + def _reposition(self): + if not self._top: + return + root = self.parent.winfo_toplevel() + root.update_idletasks() + x, y = root.winfo_rootx(), root.winfo_rooty() + w, h = root.winfo_width(), root.winfo_height() + self._top.geometry(f"{w}x{h}+{x}+{y}") + + def show(self, message="Attendere…"): + if self._top: + if self._lbl: + self._lbl.configure(text=message) + return + root = self.parent.winfo_toplevel() + top = ctk.CTkToplevel(root) + self._top = top + top.overrideredirect(True) + try: + top.attributes("-alpha", 0.22) + except tk.TclError: + pass + try: + top.configure(fg_color="#000000") + except Exception: + top.configure(bg="#000000") + top.attributes("-topmost", True) + + wrap = ctk.CTkFrame(top, corner_radius=8) + wrap.place(relx=0.5, rely=0.5, anchor="center") + self._lbl = ctk.CTkLabel(wrap, text=message, font=("Segoe UI", 11, "bold")) + self._lbl.pack(pady=(0, 10)) + self._pb = ctk.CTkProgressBar(wrap, mode="indeterminate", width=260) + self._pb.pack(fill="x") + try: + self._pb.start() + except Exception: + pass + + self._reposition() + self._bind_id = root.bind("", lambda e: self._reposition(), add="+") + + def hide(self): + if self._pb: + try: + self._pb.stop() + except Exception: + pass + self._pb = None + if self._top: + try: + self._top.destroy() + except Exception: + pass + self._top = None + root = self.parent.winfo_toplevel() + if self._bind_id: + try: + root.unbind("", self._bind_id) + except Exception: + pass + self._bind_id = None + +# ======================== +# AsyncRunner (single-loop) +# ======================== +class AsyncRunner: + """Run awaitables on the single global loop and callback on Tk main thread.""" + def __init__(self, widget: tk.Misc): + self.widget = widget + self.loop = get_global_loop() + + def run( + self, + awaitable, + on_success: Callable[[Any], None], + on_error: Optional[Callable[[BaseException], None]] = None, + busy: Optional[BusyOverlay] = None, + message: str = "Operazione in corso…", + ): + if busy: + busy.show(message) + fut = asyncio.run_coroutine_threadsafe(awaitable, self.loop) + + def _poll(): + if fut.done(): + if busy: + busy.hide() + try: + res = fut.result() + except BaseException as ex: + if on_error: + self.widget.after(0, lambda e=ex: on_error(e)) + else: + print("[AsyncRunner] Unhandled error:", repr(ex)) + else: + self.widget.after(0, lambda r=res: on_success(r)) + else: + self.widget.after(60, _poll) + + _poll() + + def close(self): + # no-op: loop is global + pass diff --git a/gestione_pickinglist.py b/gestione_pickinglist.py new file mode 100644 index 0000000..48bb032 --- /dev/null +++ b/gestione_pickinglist.py @@ -0,0 +1,668 @@ +# =================== gestione_pickinglist.py (NO-FLICKER + UX TUNING + MICRO-SPINNER) =================== + +from __future__ import annotations +import tkinter as tk +import customtkinter as ctk +from tkinter import messagebox +from typing import Optional, Any, Dict, List, Callable +from dataclasses import dataclass + +# Usa overlay e runner "collaudati" +from gestione_aree_frame_async import BusyOverlay, AsyncRunner + +from async_loop_singleton import get_global_loop +from db_async_singleton import get_db as _get_db_singleton + +# === IMPORT procedura async prenota/s-prenota (no pyodbc qui) === +import asyncio +try: + from prenota_sprenota_sql import sp_xExePackingListPallet_async, SPResult +except Exception: + async def sp_xExePackingListPallet_async(*args, **kwargs): + raise RuntimeError("sp_xExePackingListPallet_async non importabile: verifica prenota_sprenota_sql.py") + class SPResult: + def __init__(self, rc=-1, message="Procedura non disponibile", id_result=None): + self.rc = rc; self.message = message; self.id_result = id_result + + +# -------------------- SQL -------------------- +SQL_PL = """ +SELECT + COUNT(DISTINCT Pallet) AS Pallet, + COUNT(DISTINCT Lotto) AS Lotto, + COUNT(DISTINCT Articolo) AS Articolo, + COUNT(DISTINCT Descrizione) AS Descrizione, + SUM(Qta) AS Qta, + Documento, + CodNazione, + NAZIONE, + Stato, + MAX(PalletCella) AS PalletCella, + MAX(Magazzino) AS Magazzino, + MAX(Area) AS Area, + MAX(Cella) AS Cella, + MIN(Ordinamento) AS Ordinamento, + MAX(IDStato) AS IDStato +FROM dbo.XMag_ViewPackingList +GROUP BY Documento, CodNazione, NAZIONE, Stato +ORDER BY MIN(Ordinamento), Documento, NAZIONE, Stato; +""" + +SQL_PL_DETAILS = """ +SELECT * +FROM ViewPackingListRestante +WHERE Documento = :Documento +ORDER BY Ordinamento; +""" + +# -------------------- helpers -------------------- +def _rows_to_dicts(res: Dict[str, Any]) -> List[Dict[str, Any]]: + """ + Converte il payload ritornato da query_json in lista di dict. + Supporta: + - res = [ {..}, {..} ] + - res = { "rows": [..], "columns": [...] } + - res = { "data": [..], "columns": [...] } + - res = { "rows": [tuple,..], "columns": [...] } + """ + if res is None: + return [] + + if isinstance(res, list): + if not res: + return [] + if isinstance(res[0], dict): + return res + return [] + + if isinstance(res, dict): + for rows_key in ("rows", "data", "result", "records"): + if rows_key in res and isinstance(res[rows_key], list): + rows = res[rows_key] + if not rows: + return [] + if isinstance(rows[0], dict): + return rows + cols = res.get("columns") or res.get("cols") or [] + out = [] + for r in rows: + if cols and isinstance(r, (list, tuple)): + out.append({ (cols[i] if i < len(cols) else f"c{i}") : r[i] + for i in range(min(len(cols), len(r))) }) + else: + if isinstance(r, (list, tuple)): + out.append({ f"c{i}": r[i] for i in range(len(r)) }) + return out + if res and all(not isinstance(v, (list, tuple, dict)) for v in res.values()): + return [res] + + return [] + +def _s(v) -> str: + """Stringify safe: None -> '', altrimenti str(v).""" + return "" if v is None else str(v) + +def _first(d: Dict[str, Any], keys: List[str], default: str = ""): + for k in keys: + if k in d and d[k] not in (None, ""): + return d[k] + return default + +# -------------------- column specs -------------------- +@dataclass +class ColSpec: + title: str + key: str + width: int + anchor: str # 'w' | 'e' | 'center' + +# Colonne PL (in alto) — include IDStato per la colorazione +PL_COLS: List[ColSpec] = [ + ColSpec("", "__check__", 36, "w"), + ColSpec("Documento", "Documento", 120, "w"), + ColSpec("NAZIONE", "NAZIONE", 240, "w"), + ColSpec("Stato", "Stato", 110, "w"), + ColSpec("IDStato", "IDStato", 80, "e"), # nuova colonna + ColSpec("#Pallet", "Pallet", 100, "e"), + ColSpec("#Lotti", "Lotto", 100, "e"), + ColSpec("#Articoli", "Articolo", 110, "e"), + ColSpec("Qta", "Qta", 120, "e"), +] + +DET_COLS: List[ColSpec] = [ + ColSpec("UDC/Pallet", "Pallet", 150, "w"), + ColSpec("Lotto", "Lotto", 130, "w"), + ColSpec("Articolo", "Articolo", 150, "w"), + ColSpec("Descrizione","Descrizione", 320, "w"), + ColSpec("Qta", "Qta", 110, "e"), + ColSpec("Ubicazione", "Ubicazione", 320, "w"), +] + +ROW_H = 28 + + +# -------------------- Micro spinner (toolbar) -------------------- +class ToolbarSpinner: + """ + Micro-animazione leggerissima per indicare attività: + mostra una label con frame: â— â—“ â—‘ â—’ ... finché è attivo. + """ + FRAMES = ("â—", "â—“", "â—‘", "â—’") + def __init__(self, parent: tk.Widget): + self.parent = parent + self.lbl = ctk.CTkLabel(parent, text="", width=28) + self._i = 0 + self._active = False + self._job = None + + def widget(self) -> ctk.CTkLabel: + return self.lbl + + def start(self, text: str = ""): + if self._active: + return + self._active = True + self.lbl.configure(text=f"{self.FRAMES[self._i]} {text}".strip()) + self._tick() + + def stop(self): + self._active = False + if self._job is not None: + try: + self.parent.after_cancel(self._job) + except Exception: + pass + self._job = None + self.lbl.configure(text="") + + def _tick(self): + if not self._active: + return + self._i = (self._i + 1) % len(self.FRAMES) + current = self.lbl.cget("text") + # Mantieni l'eventuale testo dopo il simbolo + txt_suffix = "" + if isinstance(current, str) and len(current) > 2: + txt_suffix = current[2:] + self.lbl.configure(text=f"{self.FRAMES[self._i]}{txt_suffix}") + self._job = self.parent.after(120, self._tick) # 8 fps soft + + +# -------------------- Scrollable table -------------------- +class ScrollTable(ctk.CTkFrame): + GRID_COLOR = "#D0D5DD" + PADX_L = 8 + PADX_R = 8 + PADY = 2 + + def __init__(self, master, columns: List[ColSpec]): + super().__init__(master) + self.columns = columns + self.total_w = sum(c.width for c in self.columns) + + self.grid_rowconfigure(1, weight=1) + self.grid_columnconfigure(0, weight=1) + + # header + self.h_canvas = tk.Canvas(self, height=ROW_H, highlightthickness=0, bd=0) + self.h_inner = ctk.CTkFrame(self.h_canvas, fg_color="#f3f3f3", + height=ROW_H, width=self.total_w) + self.h_canvas.create_window((0,0), window=self.h_inner, anchor="nw", + width=self.total_w, height=ROW_H) + self.h_canvas.grid(row=0, column=0, sticky="ew") + + # body + self.b_canvas = tk.Canvas(self, highlightthickness=0, bd=0) + self.b_inner = ctk.CTkFrame(self.b_canvas, fg_color="transparent", + width=self.total_w) + self.body_window = self.b_canvas.create_window((0,0), window=self.b_inner, + anchor="nw", width=self.total_w) + self.b_canvas.grid(row=1, column=0, sticky="nsew") + + # scrollbars + self.vbar = tk.Scrollbar(self, orient="vertical", command=self.b_canvas.yview) + self.xbar = tk.Scrollbar(self, orient="horizontal", command=self._xscroll_both) + self.vbar.grid(row=1, column=1, sticky="ns") + self.xbar.grid(row=2, column=0, sticky="ew") + + # link scroll + self.b_canvas.configure(yscrollcommand=self.vbar.set, xscrollcommand=self._xscroll_set_both) + self.h_canvas.configure(xscrollcommand=self.xbar.set) + + # bind + self.h_inner.bind("", lambda e: self._sync_header_width()) + self.b_inner.bind("", lambda e: self._on_body_configure()) + + self._build_header() + + def _build_header(self): + for w in self.h_inner.winfo_children(): + w.destroy() + + row = ctk.CTkFrame(self.h_inner, fg_color="#f3f3f3", + height=ROW_H, width=self.total_w) + row.pack(fill="x", expand=False) + row.pack_propagate(False) + + for col in self.columns: + holder = ctk.CTkFrame( + row, fg_color="#f3f3f3", + width=col.width, height=ROW_H, + border_width=1, border_color=self.GRID_COLOR + ) + holder.pack(side="left", fill="y") + holder.pack_propagate(False) + + lbl = ctk.CTkLabel(holder, text=col.title, anchor="w") + lbl.pack(fill="both", padx=(self.PADX_L, self.PADX_R), pady=self.PADY) + + self.h_inner.configure(width=self.total_w, height=ROW_H) + self.h_canvas.configure(scrollregion=(0,0,self.total_w,ROW_H)) + + def _update_body_width(self): + self.b_canvas.itemconfigure(self.body_window, width=self.total_w) + sr = self.b_canvas.bbox("all") + if sr: + self.b_canvas.configure(scrollregion=(0,0,max(self.total_w, sr[2]), sr[3])) + else: + self.b_canvas.configure(scrollregion=(0,0,self.total_w,0)) + + def _on_body_configure(self): + self._update_body_width() + self._sync_header_width() + + def _sync_header_width(self): + first, _ = self.b_canvas.xview() + self.h_canvas.xview_moveto(first) + + def _xscroll_both(self, *args): + self.h_canvas.xview(*args) + self.b_canvas.xview(*args) + + def _xscroll_set_both(self, first, last): + self.h_canvas.xview_moveto(first) + self.xbar.set(first, last) + + def clear_rows(self): + for w in self.b_inner.winfo_children(): + w.destroy() + self._update_body_width() + + def add_row( + self, + values: List[str], + row_index: int, + anchors: Optional[List[str]] = None, + checkbox_builder: Optional[Callable[[tk.Widget], ctk.CTkCheckBox]] = None, + ): + row = ctk.CTkFrame(self.b_inner, fg_color="transparent", + height=ROW_H, width=self.total_w) + row.pack(fill="x", expand=False) + row.pack_propagate(False) + + for i, col in enumerate(self.columns): + holder = ctk.CTkFrame( + row, fg_color="transparent", + width=col.width, height=ROW_H, + border_width=1, border_color=self.GRID_COLOR + ) + holder.pack(side="left", fill="y") + holder.pack_propagate(False) + + if col.key == "__check__": + if checkbox_builder: + cb = checkbox_builder(holder) + cb.pack(padx=(self.PADX_L, self.PADX_R), pady=self.PADY, anchor="w") + else: + ctk.CTkLabel(holder, text="").pack(fill="both") + else: + anchor = (anchors[i] if anchors else col.anchor) + ctk.CTkLabel(holder, text=values[i], anchor=anchor).pack( + fill="both", padx=(self.PADX_L, self.PADX_R), pady=self.PADY + ) + + self._update_body_width() + + +# -------------------- PL row model -------------------- +class PLRow: + def __init__(self, pl: Dict[str, Any], on_check): + self.pl = pl + self.var = ctk.BooleanVar(value=False) + self._callback = on_check + def is_checked(self) -> bool: return self.var.get() + def set_checked(self, val: bool): self.var.set(val) + def build_checkbox(self, parent) -> ctk.CTkCheckBox: + return ctk.CTkCheckBox(parent, text="", variable=self.var, + command=lambda: self._callback(self, self.var.get())) + + +# -------------------- main frame (no-flicker + UX tuning + spinner) -------------------- +class GestionePickingListFrame(ctk.CTkFrame): + def __init__(self, master, *, db_client=None, conn_str=None): + super().__init__(master) + self.db_client = db_client or _get_db_singleton(get_global_loop(), conn_str) + self.runner = AsyncRunner(self) # runner condiviso (usa loop globale) + self.busy = BusyOverlay(self) # overlay collaudato + + self.rows_models: list[PLRow] = [] + self._detail_cache: Dict[Any, list] = {} + self.detail_doc = None + + self._first_loading: bool = False # flag per cursore d'attesa solo al primo load + + self._build_layout() + # 🔇 Niente reload immediato: carichiamo quando la finestra è idle (= già resa) + self.after_idle(self._first_show) + + def _first_show(self): + """Chiamato a finestra già resa → evitiamo sfarfallio del primo paint e mostriamo wait-cursor.""" + self._first_loading = True + try: + self.winfo_toplevel().configure(cursor="watch") + except Exception: + pass + # spinner inizia + self.spinner.start(" Carico…") + self.reload_from_db(first=True) + + # ---------- UI ---------- + def _build_layout(self): + for r in (1, 3): self.grid_rowconfigure(r, weight=1) + self.grid_columnconfigure(0, weight=1) + + top = ctk.CTkFrame(self) + top.grid(row=0, column=0, sticky="ew", padx=10, pady=(8,4)) + for i, (text, cmd) in enumerate([ + ("Ricarica", self.reload_from_db), + ("Prenota", self.on_prenota), + ("S-prenota", self.on_sprenota), + ("Esporta XLSX", self.on_export) + ]): + ctk.CTkButton(top, text=text, command=cmd).grid(row=0, column=i, padx=6) + + # --- micro spinner a destra della toolbar --- + self.spinner = ToolbarSpinner(top) + self.spinner.widget().grid(row=0, column=10, padx=(8,0)) # largo spazio a destra + + self.pl_table = ScrollTable(self, PL_COLS) + self.pl_table.grid(row=1, column=0, sticky="nsew", padx=10, pady=(4,8)) + + self.det_table = ScrollTable(self, DET_COLS) + self.det_table.grid(row=3, column=0, sticky="nsew", padx=10, pady=(4,10)) + + self._draw_details_hint() + + def _draw_details_hint(self): + self.det_table.clear_rows() + self.det_table.add_row( + values=["", "", "", "Seleziona una Picking List per vedere le UDC…", "", ""], + row_index=0, + anchors=["w"]*6 + ) + + def _apply_row_colors(self, rows: List[Dict[str, Any]]): + """Colorazione differita (after_idle) per evitare micro-jank durante l'inserimento righe.""" + try: + for idx, d in enumerate(rows): + row_widget = self.pl_table.b_inner.winfo_children()[idx] + if int(d.get("IDStato") or 0) == 1: + row_widget.configure(fg_color="#ffe6f2") # rosa tenue + else: + row_widget.configure(fg_color="transparent") + except Exception: + pass + + def _refresh_mid_rows(self, rows: List[Dict[str, Any]]): + self.pl_table.clear_rows() + self.rows_models.clear() + + for r, d in enumerate(rows): + model = PLRow(d, self.on_row_checked) + self.rows_models.append(model) + values = [ + "", # checkbox + _s(d.get("Documento")), + _s(d.get("NAZIONE")), + _s(d.get("Stato")), + _s(d.get("IDStato")), # nuova colonna visibile + _s(d.get("Pallet")), + _s(d.get("Lotto")), + _s(d.get("Articolo")), + _s(d.get("Qta")), + ] + self.pl_table.add_row( + values=values, + row_index=r, + anchors=[c.anchor for c in PL_COLS], + checkbox_builder=model.build_checkbox + ) + + # 🎯 Colora dopo che la UI è resa → no balzi visivi + self.after_idle(lambda: self._apply_row_colors(rows)) + + # ----- helpers ----- + def _get_selected_model(self) -> Optional[PLRow]: + for m in self.rows_models: + if m.is_checked(): + return m + return None + + def _recolor_row_by_documento(self, documento: str, idstato: int): + """Aggiorna colore riga e cella IDStato per il Documento indicato.""" + for idx, m in enumerate(self.rows_models): + if _s(m.pl.get("Documento")) == _s(documento): + m.pl["IDStato"] = idstato + def _paint(): + try: + row_widget = self.pl_table.b_inner.winfo_children()[idx] + row_widget.configure(fg_color="#ffe6f2" if idstato == 1 else "transparent") + row_children = row_widget.winfo_children() + if len(row_children) >= 5: + holder = row_children[4] + if holder.winfo_children(): + lbl = holder.winfo_children()[0] + if hasattr(lbl, "configure"): + lbl.configure(text=str(idstato)) + except Exception: + pass + # differisci la colorazione (smooth) + self.after_idle(_paint) + break + + def _reselect_documento_after_reload(self, documento: str): + """(Opzionale) Dopo un reload DB, riseleziona la PL con lo stesso Documento.""" + for m in self.rows_models: + if _s(m.pl.get("Documento")) == _s(documento): + m.set_checked(True) + self.on_row_checked(m, True) + break + + # ----- eventi ----- + def on_row_checked(self, model: PLRow, is_checked: bool): + # selezione esclusiva + if is_checked: + for m in self.rows_models: + if m is not model and m.is_checked(): + m.set_checked(False) + + self.detail_doc = model.pl.get("Documento") + self.spinner.start(" Carico dettagli…") # spinner ON + + async def _job(): + return await self.db_client.query_json(SQL_PL_DETAILS, {"Documento": self.detail_doc}) + + def _ok(res): + self.spinner.stop() # spinner OFF + self._detail_cache[self.detail_doc] = _rows_to_dicts(res) + # differisci il render dei dettagli (più fluido) + self.after_idle(self._refresh_details) + + def _err(ex): + self.spinner.stop() + messagebox.showerror("DB", f"Errore nel caricamento dettagli:\n{ex}") + + self.runner.run( + _job(), + on_success=_ok, + on_error=_err, + busy=self.busy, + message=f"Carico UDC per Documento {self.detail_doc}…" + ) + + else: + if not any(m.is_checked() for m in self.rows_models): + self.detail_doc = None + self._refresh_details() + + # ----- load PL ----- + def reload_from_db(self, first: bool = False): + self.spinner.start(" Carico…") # spinner ON + async def _job(): + return await self.db_client.query_json(SQL_PL, {}) + def _on_success(res): + rows = _rows_to_dicts(res) + self._refresh_mid_rows(rows) + self.spinner.stop() # spinner OFF + # se era il primo load, ripristina il cursore standard + if self._first_loading: + try: + self.winfo_toplevel().configure(cursor="") + except Exception: + pass + self._first_loading = False + def _on_error(ex): + self.spinner.stop() + if self._first_loading: + try: + self.winfo_toplevel().configure(cursor="") + except Exception: + pass + self._first_loading = False + messagebox.showerror("DB", f"Errore nel caricamento:\n{ex}") + + self.runner.run( + _job(), + on_success=_on_success, + on_error=_on_error, + busy=self.busy, + message="Caricamento Picking List…" if first else "Aggiornamento…" + ) + + def _refresh_details(self): + self.det_table.clear_rows() + if not self.detail_doc: + self._draw_details_hint() + return + + rows = self._detail_cache.get(self.detail_doc, []) + if not rows: + self.det_table.add_row(values=["", "", "", "Nessuna UDC trovata.", "", ""], + row_index=0, anchors=["w"]*6) + return + + for r, d in enumerate(rows): + pallet = _s(_first(d, ["Pallet", "UDC", "PalletID"])) + lotto = _s(_first(d, ["Lotto"])) + articolo = _s(_first(d, ["Articolo", "CodArticolo", "CodiceArticolo", "Art", "Codice"])) + descr = _s(_first(d, ["Descrizione", "Descr", "DescrArticolo", "DescArticolo", "DesArticolo"])) + qta = _s(_first(d, ["Qta", "Quantita", "Qty", "QTY"])) + ubi_raw = _first(d, ["Ubicazione", "Cella", "PalletCella"]) + loc = "Non scaffalata" if (ubi_raw is None or str(ubi_raw).strip()=="") else str(ubi_raw).strip() + + self.det_table.add_row( + values=[pallet, lotto, articolo, descr, qta, loc], + row_index=r, + anchors=[c.anchor for c in DET_COLS] + ) + + # ----- azioni ----- + def on_prenota(self): + model = self._get_selected_model() + if not model: + messagebox.showinfo("Prenota", "Seleziona una Picking List (checkbox) prima di prenotare.") + return + + documento = _s(model.pl.get("Documento")) + current = int(model.pl.get("IDStato") or 0) + desired = 1 + if current == desired: + messagebox.showinfo("Prenota", f"La Picking List {documento} è già prenotata.") + return + + id_operatore = 1 # TODO: recupera dal contesto reale + self.spinner.start(" Prenoto…") + + async def _job(): + return await sp_xExePackingListPallet_async(self.db_client, id_operatore, documento) + + def _ok(res: SPResult): + self.spinner.stop() + if res and res.rc == 0: + self._recolor_row_by_documento(documento, desired) + else: + msg = (res.message if res else "Errore sconosciuto") + messagebox.showerror("Prenota", f"Operazione non riuscita:\n{msg}") + + def _err(ex): + self.spinner.stop() + messagebox.showerror("Prenota", f"Errore:\n{ex}") + + self.runner.run( + _job(), + on_success=_ok, + on_error=_err, + busy=self.busy, + message=f"Prenoto la Picking List {documento}…" + ) + + def on_sprenota(self): + model = self._get_selected_model() + if not model: + messagebox.showinfo("S-prenota", "Seleziona una Picking List (checkbox) prima di s-prenotare.") + return + + documento = _s(model.pl.get("Documento")) + current = int(model.pl.get("IDStato") or 0) + desired = 0 + if current == desired: + messagebox.showinfo("S-prenota", f"La Picking List {documento} è già NON prenotata.") + return + + id_operatore = 1 # TODO: recupera dal contesto reale + self.spinner.start(" S-prenoto…") + + async def _job(): + return await sp_xExePackingListPallet_async(self.db_client, id_operatore, documento) + + def _ok(res: SPResult): + self.spinner.stop() + if res and res.rc == 0: + self._recolor_row_by_documento(documento, desired) + else: + msg = (res.message if res else "Errore sconosciuto") + messagebox.showerror("S-prenota", f"Operazione non riuscita:\n{msg}") + + def _err(ex): + self.spinner.stop() + messagebox.showerror("S-prenota", f"Errore:\n{ex}") + + self.runner.run( + _job(), + on_success=_ok, + on_error=_err, + busy=self.busy, + message=f"S-prenoto la Picking List {documento}…" + ) + + def on_export(self): + messagebox.showinfo("Esporta", "Stub esportazione.") + + +# factory per main +def create_frame(parent, *, db_client=None, conn_str=None) -> 'GestionePickingListFrame': + ctk.set_appearance_mode("light") + ctk.set_default_color_theme("green") + return GestionePickingListFrame(parent, db_client=db_client, conn_str=conn_str) + +# =================== /gestione_pickinglist.py =================== diff --git a/layout_window.py b/layout_window.py new file mode 100644 index 0000000..e460a93 --- /dev/null +++ b/layout_window.py @@ -0,0 +1,670 @@ +from __future__ import annotations +import tkinter as tk +from tkinter import Menu, messagebox, filedialog +import customtkinter as ctk +from datetime import datetime + +from gestione_aree_frame_async import BusyOverlay, AsyncRunner + +# ---- Color palette ---- +COLOR_EMPTY = "#B0B0B0" # grigio (vuota) +COLOR_FULL = "#FFA500" # arancione (una UDC) +COLOR_DOUBLE = "#D62728" # rosso (>=2 UDC) +FG_DARK = "#111111" +FG_LIGHT = "#FFFFFF" + + +def pct_text(p_full: float, p_double: float | None = None) -> str: + p_full = max(0.0, min(1.0, p_full)) + pf = round(p_full * 100, 1) + pe = round(100 - pf, 1) + if p_double and p_double > 0: + pd = round(p_double * 100, 1) + return f"Pieno {pf}% · Vuoto {pe}% (di cui doppie {pd}%)" + return f"Pieno {pf}% · Vuoto {pe}%" + + +class LayoutWindow(ctk.CTkToplevel): + """ + Visualizzazione layout corsie con matrice di celle. + - Ogni cella è un pulsante colorato (vuota/piena/doppia) + - Etichetta su DUE righe: + 1) "Corsia.Colonna.Fila" (una sola riga, senza andare a capo) + 2) barcode UDC (primo, se presente) + - Ricerca per barcode UDC con cambio automatico corsia + highlight cella + - Statistiche: globale e corsia selezionata + - Export XLSX + """ + def __init__(self, parent: tk.Widget, db_app): + super().__init__(parent) + self.title("Warehouse · Layout corsie") + self.geometry("1200x740") + self.minsize(980, 560) + self.resizable(True, True) + + self.db = db_app + self._busy = BusyOverlay(self) + self._async = AsyncRunner(self) + + # layout principale 5% / 80% / 15% + self.grid_rowconfigure(0, weight=5) + self.grid_rowconfigure(1, weight=80) + self.grid_rowconfigure(2, weight=15) + self.grid_columnconfigure(0, weight=1) + + # stato runtime + self.corsia_selezionata = tk.StringVar() + self.buttons: list[list[ctk.CTkButton]] = [] + self.btn_frames: list[list[ctk.CTkFrame]] = [] + self.matrix_state: list[list[int]] = [] # <— rinominata: prima era self.state + self.fila_txt: list[list[str]] = [] + self.col_txt: list[list[str]] = [] + self.desc: list[list[str]] = [] + self.udc1: list[list[str]] = [] # primo barcode UDC trovato (o "") + + # ricerca → focus differito (corsia, col, fila, barcode) + self._pending_focus: tuple[str, str, str, str] | None = None + self._highlighted: tuple[int, int] | None = None + + # anti-race: token per ignorare risposte vecchie + self._req_counter = 0 + self._last_req = 0 + self._alive = True + self._stats_after_id = None # se mai userai un refresh periodico, potremo cancellarlo qui + + self._build_top() + self._build_matrix_host() + self._build_stats() + + self._load_corsie() + # disabilitato: il refresh ad ogni generava molte query/lag + # self.bind("", lambda e: self.after_idle(self._refresh_stats)) + + # ---------------- TOP BAR ---------------- + def _build_top(self): + top = ctk.CTkFrame(self) + top.grid(row=0, column=0, sticky="nsew", padx=8, pady=6) + for i in range(4): + top.grid_columnconfigure(i, weight=0) + top.grid_columnconfigure(1, weight=1) + + # lista corsie + lf = ctk.CTkFrame(top) + lf.grid(row=0, column=0, sticky="nsw") + lf.grid_columnconfigure(0, weight=1) + ctk.CTkLabel(lf, text="Corsie", font=("", 12, "bold")).grid(row=0, column=0, sticky="w", padx=6, pady=(6, 2)) + self.lb = tk.Listbox(lf, height=6, exportselection=False) + self.lb.grid(row=1, column=0, sticky="nsw", padx=6, pady=(0, 6)) + self.lb.bind("<>", self._on_select) + + # search by barcode + srch = ctk.CTkFrame(top) + srch.grid(row=0, column=1, sticky="nsew", padx=(10, 10)) + self.search_var = tk.StringVar() + self.search_entry = ctk.CTkEntry(srch, textvariable=self.search_var, width=260) + self.search_entry.grid(row=0, column=0, sticky="w") + ctk.CTkButton(srch, text="Cerca per barcode UDC", command=self._search_udc).grid(row=0, column=1, padx=(8, 0)) + srch.grid_columnconfigure(0, weight=1) + + # toolbar + tb = ctk.CTkFrame(top) + tb.grid(row=0, column=3, sticky="ne") + ctk.CTkButton(tb, text="Aggiorna", command=self._refresh_current).grid(row=0, column=0, padx=4) + ctk.CTkButton(tb, text="Export XLSX", command=self._export_xlsx).grid(row=0, column=1, padx=4) + + # ---------------- MATRIX HOST ---------------- + def _build_matrix_host(self): + center = ctk.CTkFrame(self) + center.grid(row=1, column=0, sticky="nsew", padx=8, pady=(0, 6)) + center.grid_rowconfigure(0, weight=1) + center.grid_columnconfigure(0, weight=1) + self.host = ctk.CTkFrame(center) + self.host.grid(row=0, column=0, sticky="nsew", padx=4, pady=4) + + def _apply_cell_style(self, btn: ctk.CTkButton, state: int): + if state == 0: + btn.configure( + fg_color=COLOR_EMPTY, hover_color="#9A9A9A", + text_color=FG_DARK, border_width=0 + ) + elif state == 1: + btn.configure( + fg_color=COLOR_FULL, hover_color="#E69500", + text_color=FG_DARK, border_width=0 + ) + else: + btn.configure( + fg_color=COLOR_DOUBLE, hover_color="#B22222", + text_color=FG_LIGHT, border_width=0 + ) + + def _clear_highlight(self): + if self._highlighted and self.buttons: + r, c = self._highlighted + try: + if 0 <= r < len(self.buttons) and 0 <= c < len(self.buttons[r]): + btn = self.buttons[r][c] + if getattr(btn, "winfo_exists", None) and btn.winfo_exists(): + try: + btn.configure(border_width=0) + except Exception: + pass + # clear blue frame border + try: + fr = self.btn_frames[r][c] + if fr and getattr(fr, "winfo_exists", None) and fr.winfo_exists(): + fr.configure(border_width=0) + # in CTkFrame non esiste highlightthickness come in tk; border_* è corretto + except Exception: + pass + except Exception: + pass + self._highlighted = None + + def _rebuild_matrix(self, rows: int, cols: int, state, fila_txt, col_txt, desc, udc1, corsia): + # prima rimuovi highlight su vecchi bottoni + self._clear_highlight() + # ripulisci host + for w in self.host.winfo_children(): + w.destroy() + self.buttons.clear() + self.btn_frames.clear() + + # salva matrici + self.matrix_state, self.fila_txt, self.col_txt, self.desc, self.udc1 = state, fila_txt, col_txt, desc, udc1 + + # ridistribuisci pesi griglia + for r in range(rows): + self.host.grid_rowconfigure(r, weight=1) + for c in range(cols): + self.host.grid_columnconfigure(c, weight=1) + + # crea Frame+Button per cella (righe invertite: fila "a" in basso) + for r in range(rows): + row_btns = [] + row_frames = [] + for c in range(cols): + st = state[r][c] + code = f"{corsia}.{col_txt[r][c]}.{fila_txt[r][c]}" # PRIMA RIGA (in linea) + udc = udc1[r][c] or "" # SECONDA RIGA: barcode UDC + text = f"{code}\n{udc}" + cell = ctk.CTkFrame(self.host, corner_radius=6, border_width=0) + btn = ctk.CTkButton( + cell, + text=text, + corner_radius=6) + self._apply_cell_style(btn, st) + + rr = (rows - 1) - r # capovolgi + cell.grid(row=rr, column=c, padx=1, pady=1, sticky="nsew") + btn.pack(fill="both", expand=True) + btn.configure(command=lambda rr=r, cc=c: self._open_menu(None, rr, cc)) + btn.bind("", lambda e, rr=r, cc=c: self._open_menu(e, rr, cc)) + row_btns.append(btn) + row_frames.append(cell) + self.buttons.append(row_btns) + self.btn_frames.append(row_frames) + + # focus differito post-ricarica + if getattr(self, '_alive', True) and self._pending_focus and self._pending_focus[0] == corsia: + _, col, fila, _barcode = self._pending_focus + self._pending_focus = None + self._highlight_cell_by_labels(col, fila) + + # ---------------- CONTEXT MENU ---------------- + def _open_menu(self, event, r, c): + st = self.matrix_state[r][c] + corsia = self.corsia_selezionata.get() + label = f"{corsia}.{self.col_txt[r][c]}.{self.fila_txt[r][c]}" + m = Menu(self, tearoff=0) + m.add_command(label="Apri dettaglio", command=lambda: self._toast(f"Dettaglio {label}")) + if st == 0: + m.add_command(label="Segna pieno", command=lambda: self._set_cell(r, c, 1)) + m.add_command(label="Segna doppia", command=lambda: self._set_cell(r, c, 2)) + elif st == 1: + m.add_command(label="Segna vuoto", command=lambda: self._set_cell(r, c, 0)) + m.add_command(label="Segna doppia", command=lambda: self._set_cell(r, c, 2)) + else: + m.add_command(label="Segna vuoto", command=lambda: self._set_cell(r, c, 0)) + m.add_command(label="Segna pieno", command=lambda: self._set_cell(r, c, 1)) + m.add_separator() + m.add_command(label="Copia ubicazione", command=lambda: self._copy(label)) + x = self.winfo_pointerx() if event is None else event.x_root + y = self.winfo_pointery() if event is None else event.y_root + m.tk_popup(x, y) + + def _set_cell(self, r, c, val): + self.matrix_state[r][c] = val + btn = self.buttons[r][c] + self._apply_cell_style(btn, val) + self._refresh_stats() + + # ---------------- STATS ---------------- + def _build_stats(self): + bottom = ctk.CTkFrame(self) + bottom.grid(row=2, column=0, sticky="nsew", padx=8, pady=6) + bottom.grid_columnconfigure(0, weight=1) + + ctk.CTkLabel(bottom, text="Riempimento globale", font=("", 10, "bold")).grid(row=0, column=0, sticky="w", pady=(0, 2)) + self.tot_canvas = tk.Canvas(bottom, height=22, highlightthickness=0) + self.tot_canvas.grid(row=1, column=0, sticky="ew", padx=(0, 260)) + self.tot_text = ctk.CTkLabel(bottom, text=pct_text(0.0, 0.0)) + self.tot_text.grid(row=1, column=0, sticky="e") + + ctk.CTkLabel(bottom, text="Riempimento corsia selezionata", font=("", 10, "bold")).grid(row=2, column=0, sticky="w", pady=(10, 2)) + self.sel_canvas = tk.Canvas(bottom, height=22, highlightthickness=0) + self.sel_canvas.grid(row=3, column=0, sticky="ew", padx=(0, 260)) + self.sel_text = ctk.CTkLabel(bottom, text=pct_text(0.0, 0.0)) + self.sel_text.grid(row=3, column=0, sticky="e") + + leg = ctk.CTkFrame(bottom) + leg.grid(row=4, column=0, sticky="w", pady=(10, 0)) + ctk.CTkLabel(leg, text="Legenda celle:").grid(row=0, column=0, padx=(0, 8)) + self._legend(leg, 1, "Vuota", COLOR_EMPTY) + self._legend(leg, 3, "Piena", COLOR_FULL) + self._legend(leg, 5, "Doppia UDC", COLOR_DOUBLE) + + def _legend(self, parent, col, text, color): + box = tk.Canvas(parent, width=18, height=12, highlightthickness=0) + box.create_rectangle(0, 0, 18, 12, fill=color, width=1, outline="#444") + box.grid(row=0, column=col) + ctk.CTkLabel(parent, text=text).grid(row=0, column=col + 1, padx=(4, 12)) + + # ---------------- DATA LOADING ---------------- + def _load_corsie(self): + sql = """ + WITH C AS ( + SELECT DISTINCT LTRIM(RTRIM(Corsia)) AS Corsia + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) AND LTRIM(RTRIM(Corsia)) <> '7G' + ) + SELECT Corsia + FROM C + ORDER BY + CASE + WHEN LEFT(Corsia,3)='MAG' AND TRY_CONVERT(int, SUBSTRING(Corsia,4,50)) IS NOT NULL THEN 0 + WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN 1 + ELSE 2 + END, + CASE WHEN LEFT(Corsia,3)='MAG' THEN TRY_CONVERT(int, SUBSTRING(Corsia,4,50)) END, + CASE WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN TRY_CONVERT(int, Corsia) END, + CASE WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN SUBSTRING(Corsia, LEN(CAST(TRY_CONVERT(int, Corsia) AS varchar(20)))+1, 50) END, + Corsia; + """ + def _ok(res): + if not getattr(self, '_alive', True) or not self.winfo_exists(): + return + rows = res.get("rows", []) if isinstance(res, dict) else [] + self.lb.delete(0, tk.END) + corsie = [r[0] for r in rows] + for c in corsie: + self.lb.insert(tk.END, c) + idx = corsie.index("1A") if "1A" in corsie else (0 if corsie else -1) + if idx >= 0: + self.lb.selection_clear(0, tk.END) + self.lb.selection_set(idx) + self.lb.see(idx) + self._on_select(None) + else: + self._toast("Nessuna corsia trovata.") + self._busy.hide() + def _err(ex): + if not getattr(self, '_alive', True) or not self.winfo_exists(): + return + self._busy.hide() + messagebox.showerror("Errore", f"Caricamento corsie fallito:\n{ex}") + self._async.run(self.db.query_json(sql, {}), _ok, _err, busy=self._busy, message="Carico corsie…") + + def _on_select(self, _): + sel = self.lb.curselection() + if not sel: + return + corsia = self.lb.get(sel[0]) + self.corsia_selezionata.set(corsia) + self._load_matrix(corsia) + + def _select_corsia_in_listbox(self, corsia: str): + for i in range(self.lb.size()): + if self.lb.get(i) == corsia: + self.lb.selection_clear(0, tk.END) + self.lb.selection_set(i) + self.lb.see(i) + break + + def _load_matrix(self, corsia: str): + # nuovo token richiesta → evita che risposte vecchie spazzino la UI + self._req_counter += 1 + req_id = self._req_counter + self._last_req = req_id + + sql = """ + WITH C AS ( + SELECT + ID, + LTRIM(RTRIM(Corsia)) AS Corsia, + LTRIM(RTRIM(Fila)) AS Fila, + LTRIM(RTRIM(Colonna)) AS Colonna, + Descrizione + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) + AND LTRIM(RTRIM(Corsia)) <> '7G' AND LTRIM(RTRIM(Corsia)) = :corsia + ), + R AS ( + SELECT Fila, + DENSE_RANK() OVER ( + ORDER BY CASE WHEN TRY_CONVERT(int, Fila) IS NULL THEN 1 ELSE 0 END, + TRY_CONVERT(int, Fila), Fila + ) AS RowN + FROM C GROUP BY Fila + ), + K AS ( + SELECT Colonna, + DENSE_RANK() OVER ( + ORDER BY CASE WHEN TRY_CONVERT(int, Colonna) IS NULL THEN 1 ELSE 0 END, + TRY_CONVERT(int, Colonna), Colonna + ) AS ColN + FROM C GROUP BY Colonna + ), + S AS ( + SELECT c.ID, COUNT(DISTINCT g.BarcodePallet) AS n + FROM C AS c + LEFT JOIN dbo.XMag_GiacenzaPallet AS g ON g.IDCella = c.ID + GROUP BY c.ID + ), + U AS ( + SELECT c.ID, MIN(g.BarcodePallet) AS FirstUDC + FROM C c + LEFT JOIN dbo.XMag_GiacenzaPallet g ON g.IDCella = c.ID + GROUP BY c.ID + ) + SELECT + r.RowN, k.ColN, + CASE WHEN s.n IS NULL OR s.n = 0 THEN 0 + WHEN s.n = 1 THEN 1 + ELSE 2 END AS Stato, + c.Descrizione, + LTRIM(RTRIM(c.Fila)) AS FilaTxt, + LTRIM(RTRIM(c.Colonna)) AS ColTxt, + U.FirstUDC + FROM C c + JOIN R r ON r.Fila = c.Fila + JOIN K k ON k.Colonna = c.Colonna + LEFT JOIN S s ON s.ID = c.ID + LEFT JOIN U ON U.ID = c.ID + ORDER BY r.RowN, k.ColN; + """ + def _ok(res): + if not getattr(self, '_alive', True) or not self.winfo_exists(): + return + # ignora risposte superate + if req_id < self._last_req: + return + rows = res.get("rows", []) if isinstance(res, dict) else [] + if not rows: + # mostra matrice vuota senza rimuovere il frame (evita "schermo bianco") + self._rebuild_matrix(0, 0, [], [], [], [], [], corsia) + self._refresh_stats() + self._busy.hide() + return + max_r = max_c = 0 + for row in rows: + rown, coln = row[0], row[1] + if rown and coln: + max_r = max(max_r, int(rown)) + max_c = max(max_c, int(coln)) + mat = [[0] * max_c for _ in range(max_r)] + fila = [[""] * max_c for _ in range(max_r)] + col = [[""] * max_c for _ in range(max_r)] + desc = [[""] * max_c for _ in range(max_r)] + udc = [[""] * max_c for _ in range(max_r)] + for row in rows: + rown, coln, stato, descr, fila_txt, col_txt, first_udc = row + r = int(rown) - 1 + c = int(coln) - 1 + mat[r][c] = int(stato) + fila[r][c] = str(fila_txt or "") + col[r][c] = str(col_txt or "") + desc[r][c] = str(descr or f"{corsia}.{col_txt}.{fila_txt}") + udc[r][c] = str(first_udc or "") + self._rebuild_matrix(max_r, max_c, mat, fila, col, desc, udc, corsia) + self._refresh_stats() + self._busy.hide() + def _err(ex): + if not getattr(self, '_alive', True) or not self.winfo_exists(): + return + if req_id < self._last_req: + return + self._busy.hide() + messagebox.showerror("Errore", f"Caricamento matrice {corsia} fallito:\n{ex}") + self._async.run(self.db.query_json(sql, {"corsia": corsia}), _ok, _err, busy=self._busy, message=f"Carico corsia {corsia}…") + + # ---------------- SEARCH ---------------- + def _search_udc(self): + barcode = (self.search_var.get() or "").strip() + if not barcode: + self._toast("Inserisci un barcode UDC da cercare.") + return + + # bump token per impedire che una vecchia _load_matrix cancelli UI + self._req_counter += 1 + search_req_id = self._req_counter + self._last_req = search_req_id + + sql = """ + SELECT TOP (1) + RTRIM(c.Corsia) AS Corsia, + RTRIM(c.Colonna) AS Colonna, + RTRIM(c.Fila) AS Fila, + c.ID AS IDCella + FROM dbo.XMag_GiacenzaPallet g + JOIN dbo.Celle c ON c.ID = g.IDCella + WHERE g.BarcodePallet = :barcode + AND c.ID <> 9999 AND RTRIM(c.Corsia) <> '7G' + """ + def _ok(res): + if not getattr(self, '_alive', True) or not self.winfo_exists(): + return + if search_req_id < self._last_req: + return + rows = res.get("rows", []) if isinstance(res, dict) else [] + if not rows: + messagebox.showinfo("Ricerca", f"UDC {barcode} non trovata.", parent=self) + return + corsia, col, fila, _idc = rows[0] + corsia = str(corsia).strip(); col = str(col).strip(); fila = str(fila).strip() + self._pending_focus = (corsia, col, fila, barcode) + + # sincronizza listbox e carica SEMPRE la corsia della UDC + self._select_corsia_in_listbox(corsia) + self.corsia_selezionata.set(corsia) + self._load_matrix(corsia) # highlight avverrà in _rebuild_matrix + def _err(ex): + if not getattr(self, '_alive', True) or not self.winfo_exists(): + return + if search_req_id < self._last_req: + return + messagebox.showerror("Ricerca", f"Errore ricerca UDC:\n{ex}", parent=self) + + self._async.run(self.db.query_json(sql, {"barcode": barcode}), _ok, _err, busy=self._busy, message="Cerco UDC…") + + def _try_highlight(self, col_txt: str, fila_txt: str) -> bool: + for r in range(len(self.col_txt)): + for c in range(len(self.col_txt[r])): + if self.col_txt[r][c] == col_txt and self.fila_txt[r][c] == fila_txt: + self._clear_highlight() + btn = self.buttons[r][c] + btn.configure(border_width=3, border_color="blue") + try: + fr = self.btn_frames[r][c] + fr.configure(border_color="blue", border_width=2) + except Exception: + pass + self._highlighted = (r, c) + return True + return False + + def _highlight_cell_by_labels(self, col_txt: str, fila_txt: str): + if not self._try_highlight(col_txt, fila_txt): + self._toast("Cella trovata ma non mappabile a pulsante.") + + # ---------------- COMMANDS ---------------- + def _refresh_current(self): + if self.corsia_selezionata.get(): + self._load_matrix(self.corsia_selezionata.get()) + + def _export_xlsx(self): + if not self.matrix_state: + messagebox.showinfo("Export", "Nessuna matrice da esportare.") + return + corsia = self.corsia_selezionata.get() or "NA" + ts = datetime.now().strftime("%d_%m_%Y_%H-%M") + default = f"layout_matrice_{corsia}_{ts}.xlsx" + path = filedialog.asksaveasfilename( + title="Esporta matrice", + defaultextension=".xlsx", + initialfile=default, + filetypes=[("Excel", "*.xlsx")] + ) + if not path: + return + try: + from openpyxl import Workbook + from openpyxl.styles import PatternFill, Alignment, Font + except Exception as ex: + messagebox.showerror("Export", f"Manca openpyxl: {ex}\nInstalla con: pip install openpyxl") + return + rows = len(self.matrix_state) + cols = len(self.matrix_state[0]) if self.matrix_state else 0 + wb = Workbook() + ws1 = wb.active + ws1.title = f"Dettaglio {corsia}" + ws1.append(["Corsia", "FilaIdx", "ColIdx", "Stato", "Descrizione", "FilaTxt", "ColTxt", "UDC1"]) + for r in range(rows): + for c in range(cols): + st = self.matrix_state[r][c] + stato_lbl = "Vuota" if st == 0 else ("Piena" if st == 1 else "Doppia") + ws1.append([corsia, r + 1, c + 1, stato_lbl, + self.desc[r][c], self.fila_txt[r][c], self.col_txt[r][c], self.udc1[r][c]]) + for cell in ws1[1]: + cell.font = Font(bold=True) + + ws2 = wb.create_sheet(f"Matrice {corsia}") + fills = { + 0: PatternFill("solid", fgColor="B0B0B0"), + 1: PatternFill("solid", fgColor="FFA500"), + 2: PatternFill("solid", fgColor="D62728"), + } + center = Alignment(horizontal="center", vertical="center", wrap_text=True) + for r in range(rows): + for c in range(cols): + value = f"{corsia}.{self.col_txt[r][c]}.{self.fila_txt[r][c]}\n{self.udc1[r][c]}" + cell = ws2.cell(row=(rows - r), column=c + 1, value=value) # capovolto per avere 'a' in basso + cell.fill = fills.get(self.matrix_state[r][c], fills[0]) + cell.alignment = center + try: + wb.save(path) + self._toast(f"Esportato: {path}") + except Exception as ex: + messagebox.showerror("Export", f"Salvataggio fallito:\n{ex}") + + # ---------------- STATS ---------------- + def _refresh_stats(self): + # globale dal DB + sql_tot = """ + WITH C AS ( + SELECT ID + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) + AND LTRIM(RTRIM(Corsia)) <> '7G' + AND LTRIM(RTRIM(Fila)) IS NOT NULL + AND LTRIM(RTRIM(Colonna)) IS NOT NULL + ), + S AS ( + SELECT c.ID, COUNT(DISTINCT g.BarcodePallet) AS n + FROM C AS c LEFT JOIN dbo.XMag_GiacenzaPallet AS g ON g.IDCella = c.ID + GROUP BY c.ID + ) + SELECT + CAST(SUM(CASE WHEN s.n>0 THEN 1 ELSE 0 END) AS float)/NULLIF(COUNT(*),0) AS PercPieno, + CAST(SUM(CASE WHEN s.n>1 THEN 1 ELSE 0 END) AS float)/NULLIF(COUNT(*),0) AS PercDoppie + FROM C LEFT JOIN S s ON s.ID = C.ID; + """ + def _ok(res): + if not getattr(self, '_alive', True) or not self.winfo_exists(): + return + rows = res.get("rows", []) if isinstance(res, dict) else [] + p_full = float(rows[0][0] or 0.0) if rows else 0.0 + p_dbl = float(rows[0][1] or 0.0) if rows else 0.0 + self._draw_bar(self.tot_canvas, p_full) + self.tot_text.configure(text=pct_text(p_full, p_dbl)) + self._async.run(self.db.query_json(sql_tot, {}), _ok, lambda e: None, busy=None, message=None) + + # selezionata dalla matrice in memoria + if self.matrix_state: + tot = sum(len(r) for r in self.matrix_state) + full = sum(1 for row in self.matrix_state for v in row if v in (1, 2)) + doubles = sum(1 for row in self.matrix_state for v in row if v == 2) + p_full = (full / tot) if tot else 0.0 + p_dbl = (doubles / tot) if tot else 0.0 + else: + p_full = p_dbl = 0.0 + self._draw_bar(self.sel_canvas, p_full) + self.sel_text.configure(text=pct_text(p_full, p_dbl)) + + def _draw_bar(self, cv: tk.Canvas, p_full: float): + cv.delete("all") + w = max(300, cv.winfo_width() or 600) + h = 18 + fw = int(w * max(0.0, min(1.0, p_full))) + cv.create_rectangle(2, 2, 2 + fw, 2 + h, fill="#D62728", width=0) + cv.create_rectangle(2 + fw, 2, 2 + w, 2 + h, fill="#2CA02C", width=0) + cv.create_rectangle(2, 2, 2 + w, 2 + h, outline="#555", width=1) + + # ---------------- UTIL ---------------- + def _toast(self, msg, ms=1400): + if not hasattr(self, "_status"): + self._status = ctk.CTkLabel(self, anchor="w") + self._status.grid(row=3, column=0, sticky="ew") + self._status.configure(text=msg) + self.after(ms, lambda: self._status.configure(text="")) + + def _copy(self, txt: str): + self.clipboard_clear() + self.clipboard_append(txt) + self._toast(f"Copiato: {txt}") + + + + def destroy(self): + # evita nuovi refresh/async dopo destroy + self._alive = False + # cancella eventuali timer + try: + if self._stats_after_id is not None: + self.after_cancel(self._stats_after_id) + except Exception: + pass + # pulizia UI leggera + try: + for w in list(self.host.winfo_children()): + w.destroy() + except Exception: + pass + try: + super().destroy() + except Exception: + pass + +def open_layout_window(parent, db_app): + key = "_layout_window_singleton" + ex = getattr(parent, key, None) + if ex and ex.winfo_exists(): + try: + ex.lift() + ex.focus_force() + return ex + except Exception: + pass + w = LayoutWindow(parent, db_app) + setattr(parent, key, w) + return w diff --git a/layout_window.py.bak_fix_bc_transparent b/layout_window.py.bak_fix_bc_transparent new file mode 100644 index 0000000..bdf1fc7 --- /dev/null +++ b/layout_window.py.bak_fix_bc_transparent @@ -0,0 +1,633 @@ +from __future__ import annotations +import tkinter as tk +from tkinter import Menu, messagebox, filedialog +import customtkinter as ctk +from datetime import datetime + +from gestione_aree_frame_async import BusyOverlay, AsyncRunner + +# ---- Color palette ---- +COLOR_EMPTY = "#B0B0B0" # grigio (vuota) +COLOR_FULL = "#FFA500" # arancione (una UDC) +COLOR_DOUBLE = "#D62728" # rosso (>=2 UDC) +FG_DARK = "#111111" +FG_LIGHT = "#FFFFFF" + + +def pct_text(p_full: float, p_double: float | None = None) -> str: + p_full = max(0.0, min(1.0, p_full)) + pf = round(p_full * 100, 1) + pe = round(100 - pf, 1) + if p_double and p_double > 0: + pd = round(p_double * 100, 1) + return f"Pieno {pf}% · Vuoto {pe}% (di cui doppie {pd}%)" + return f"Pieno {pf}% · Vuoto {pe}%" + + +class LayoutWindow(ctk.CTkToplevel): + """ + Visualizzazione layout corsie con matrice di celle. + - Ogni cella è un pulsante colorato (vuota/piena/doppia) + - Etichetta su DUE righe: + 1) "Corsia.Colonna.Fila" (una sola riga, senza andare a capo) + 2) barcode UDC (primo, se presente) + - Ricerca per barcode UDC con cambio automatico corsia + highlight cella + - Statistiche: globale e corsia selezionata + - Export XLSX + """ + def __init__(self, parent: tk.Widget, db_app): + super().__init__(parent) + self.title("Warehouse · Layout corsie") + self.geometry("1200x740") + self.minsize(980, 560) + self.resizable(True, True) + + self.db = db_app + self._busy = BusyOverlay(self) + self._async = AsyncRunner(self) + + # layout principale 5% / 80% / 15% + self.grid_rowconfigure(0, weight=5) + self.grid_rowconfigure(1, weight=80) + self.grid_rowconfigure(2, weight=15) + self.grid_columnconfigure(0, weight=1) + + # stato runtime + self.corsia_selezionata = tk.StringVar() + self.buttons: list[list[ctk.CTkButton]] = [] + self.btn_frames: list[list[ctk.CTkFrame]] = [] + self.matrix_state: list[list[int]] = [] # <— rinominata: prima era self.state + self.fila_txt: list[list[str]] = [] + self.col_txt: list[list[str]] = [] + self.desc: list[list[str]] = [] + self.udc1: list[list[str]] = [] # primo barcode UDC trovato (o "") + + # ricerca → focus differito (corsia, col, fila, barcode) + self._pending_focus: tuple[str, str, str, str] | None = None + self._highlighted: tuple[int, int] | None = None + + # anti-race: token per ignorare risposte vecchie + self._req_counter = 0 + self._last_req = 0 + + self._build_top() + self._build_matrix_host() + self._build_stats() + + self._load_corsie() + self.bind("", lambda e: self.after_idle(self._refresh_stats)) + + # ---------------- TOP BAR ---------------- + def _build_top(self): + top = ctk.CTkFrame(self) + top.grid(row=0, column=0, sticky="nsew", padx=8, pady=6) + for i in range(4): + top.grid_columnconfigure(i, weight=0) + top.grid_columnconfigure(1, weight=1) + + # lista corsie + lf = ctk.CTkFrame(top) + lf.grid(row=0, column=0, sticky="nsw") + lf.grid_columnconfigure(0, weight=1) + ctk.CTkLabel(lf, text="Corsie", font=("", 12, "bold")).grid(row=0, column=0, sticky="w", padx=6, pady=(6, 2)) + self.lb = tk.Listbox(lf, height=6, exportselection=False) + self.lb.grid(row=1, column=0, sticky="nsw", padx=6, pady=(0, 6)) + self.lb.bind("<>", self._on_select) + + # search by barcode + srch = ctk.CTkFrame(top) + srch.grid(row=0, column=1, sticky="nsew", padx=(10, 10)) + self.search_var = tk.StringVar() + self.search_entry = ctk.CTkEntry(srch, textvariable=self.search_var, width=260) + self.search_entry.grid(row=0, column=0, sticky="w") + ctk.CTkButton(srch, text="Cerca per barcode UDC", command=self._search_udc).grid(row=0, column=1, padx=(8, 0)) + srch.grid_columnconfigure(0, weight=1) + + # toolbar + tb = ctk.CTkFrame(top) + tb.grid(row=0, column=3, sticky="ne") + ctk.CTkButton(tb, text="Aggiorna", command=self._refresh_current).grid(row=0, column=0, padx=4) + ctk.CTkButton(tb, text="Export XLSX", command=self._export_xlsx).grid(row=0, column=1, padx=4) + + # ---------------- MATRIX HOST ---------------- + def _build_matrix_host(self): + center = ctk.CTkFrame(self) + center.grid(row=1, column=0, sticky="nsew", padx=8, pady=(0, 6)) + center.grid_rowconfigure(0, weight=1) + center.grid_columnconfigure(0, weight=1) + self.host = ctk.CTkFrame(center) + self.host.grid(row=0, column=0, sticky="nsew", padx=4, pady=4) + + def _apply_cell_style(self, btn: ctk.CTkButton, state: int): + if state == 0: + btn.configure( + fg_color=COLOR_EMPTY, hover_color="#9A9A9A", + text_color=FG_DARK, border_width=0, border_color="transparent" + ) + elif state == 1: + btn.configure( + fg_color=COLOR_FULL, hover_color="#E69500", + text_color=FG_DARK, border_width=0, border_color="transparent" + ) + else: + btn.configure( + fg_color=COLOR_DOUBLE, hover_color="#B22222", + text_color=FG_LIGHT, border_width=0, border_color="transparent" + ) + + def _clear_highlight(self): + if self._highlighted and self.buttons: + r, c = self._highlighted + try: + if 0 <= r < len(self.buttons) and 0 <= c < len(self.buttons[r]): + btn = self.buttons[r][c] + if getattr(btn, "winfo_exists", None) and btn.winfo_exists(): + try: + btn.configure(border_width=0, border_color="transparent") + except Exception: + pass + # clear blue frame border + try: + fr = self.btn_frames[r][c] + if fr and getattr(fr, "winfo_exists", None) and fr.winfo_exists(): + fr.configure(border_width=0, border_color="transparent") + # in CTkFrame non esiste highlightthickness come in tk; border_* è corretto + except Exception: + pass + except Exception: + pass + self._highlighted = None + + def _rebuild_matrix(self, rows: int, cols: int, state, fila_txt, col_txt, desc, udc1, corsia): + # prima rimuovi highlight su vecchi bottoni + self._clear_highlight() + # ripulisci host + for w in self.host.winfo_children(): + w.destroy() + self.buttons.clear() + self.btn_frames.clear() + + # salva matrici + self.matrix_state, self.fila_txt, self.col_txt, self.desc, self.udc1 = state, fila_txt, col_txt, desc, udc1 + + # ridistribuisci pesi griglia + for r in range(rows): + self.host.grid_rowconfigure(r, weight=1) + for c in range(cols): + self.host.grid_columnconfigure(c, weight=1) + + # crea Frame+Button per cella (righe invertite: fila "a" in basso) + for r in range(rows): + row_btns = [] + row_frames = [] + for c in range(cols): + st = state[r][c] + code = f"{corsia}.{col_txt[r][c]}.{fila_txt[r][c]}" # PRIMA RIGA (in linea) + udc = udc1[r][c] or "" # SECONDA RIGA: barcode UDC + text = f"{code}\n{udc}" + cell = ctk.CTkFrame(self.host, corner_radius=6, border_width=0) + btn = ctk.CTkButton( + cell, + text=text, + corner_radius=6, + ) + self._apply_cell_style(btn, st) + + rr = (rows - 1) - r # capovolgi + cell.grid(row=rr, column=c, padx=1, pady=1, sticky="nsew") + btn.pack(fill="both", expand=True) + btn.configure(command=lambda rr=r, cc=c: self._open_menu(None, rr, cc)) + btn.bind("", lambda e, rr=r, cc=c: self._open_menu(e, rr, cc)) + row_btns.append(btn) + row_frames.append(cell) + self.buttons.append(row_btns) + self.btn_frames.append(row_frames) + + # focus differito post-ricarica + if self._pending_focus and self._pending_focus[0] == corsia: + _, col, fila, _barcode = self._pending_focus + self._pending_focus = None + self._highlight_cell_by_labels(col, fila) + + # ---------------- CONTEXT MENU ---------------- + def _open_menu(self, event, r, c): + st = self.matrix_state[r][c] + corsia = self.corsia_selezionata.get() + label = f"{corsia}.{self.col_txt[r][c]}.{self.fila_txt[r][c]}" + m = Menu(self, tearoff=0) + m.add_command(label="Apri dettaglio", command=lambda: self._toast(f"Dettaglio {label}")) + if st == 0: + m.add_command(label="Segna pieno", command=lambda: self._set_cell(r, c, 1)) + m.add_command(label="Segna doppia", command=lambda: self._set_cell(r, c, 2)) + elif st == 1: + m.add_command(label="Segna vuoto", command=lambda: self._set_cell(r, c, 0)) + m.add_command(label="Segna doppia", command=lambda: self._set_cell(r, c, 2)) + else: + m.add_command(label="Segna vuoto", command=lambda: self._set_cell(r, c, 0)) + m.add_command(label="Segna pieno", command=lambda: self._set_cell(r, c, 1)) + m.add_separator() + m.add_command(label="Copia ubicazione", command=lambda: self._copy(label)) + x = self.winfo_pointerx() if event is None else event.x_root + y = self.winfo_pointery() if event is None else event.y_root + m.tk_popup(x, y) + + def _set_cell(self, r, c, val): + self.matrix_state[r][c] = val + btn = self.buttons[r][c] + self._apply_cell_style(btn, val) + self._refresh_stats() + + # ---------------- STATS ---------------- + def _build_stats(self): + bottom = ctk.CTkFrame(self) + bottom.grid(row=2, column=0, sticky="nsew", padx=8, pady=6) + bottom.grid_columnconfigure(0, weight=1) + + ctk.CTkLabel(bottom, text="Riempimento globale", font=("", 10, "bold")).grid(row=0, column=0, sticky="w", pady=(0, 2)) + self.tot_canvas = tk.Canvas(bottom, height=22, highlightthickness=0) + self.tot_canvas.grid(row=1, column=0, sticky="ew", padx=(0, 260)) + self.tot_text = ctk.CTkLabel(bottom, text=pct_text(0.0, 0.0)) + self.tot_text.grid(row=1, column=0, sticky="e") + + ctk.CTkLabel(bottom, text="Riempimento corsia selezionata", font=("", 10, "bold")).grid(row=2, column=0, sticky="w", pady=(10, 2)) + self.sel_canvas = tk.Canvas(bottom, height=22, highlightthickness=0) + self.sel_canvas.grid(row=3, column=0, sticky="ew", padx=(0, 260)) + self.sel_text = ctk.CTkLabel(bottom, text=pct_text(0.0, 0.0)) + self.sel_text.grid(row=3, column=0, sticky="e") + + leg = ctk.CTkFrame(bottom) + leg.grid(row=4, column=0, sticky="w", pady=(10, 0)) + ctk.CTkLabel(leg, text="Legenda celle:").grid(row=0, column=0, padx=(0, 8)) + self._legend(leg, 1, "Vuota", COLOR_EMPTY) + self._legend(leg, 3, "Piena", COLOR_FULL) + self._legend(leg, 5, "Doppia UDC", COLOR_DOUBLE) + + def _legend(self, parent, col, text, color): + box = tk.Canvas(parent, width=18, height=12, highlightthickness=0) + box.create_rectangle(0, 0, 18, 12, fill=color, width=1, outline="#444") + box.grid(row=0, column=col) + ctk.CTkLabel(parent, text=text).grid(row=0, column=col + 1, padx=(4, 12)) + + # ---------------- DATA LOADING ---------------- + def _load_corsie(self): + sql = """ + WITH C AS ( + SELECT DISTINCT LTRIM(RTRIM(Corsia)) AS Corsia + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) AND LTRIM(RTRIM(Corsia)) <> '7G' + ) + SELECT Corsia + FROM C + ORDER BY + CASE + WHEN LEFT(Corsia,3)='MAG' AND TRY_CONVERT(int, SUBSTRING(Corsia,4,50)) IS NOT NULL THEN 0 + WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN 1 + ELSE 2 + END, + CASE WHEN LEFT(Corsia,3)='MAG' THEN TRY_CONVERT(int, SUBSTRING(Corsia,4,50)) END, + CASE WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN TRY_CONVERT(int, Corsia) END, + CASE WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN SUBSTRING(Corsia, LEN(CAST(TRY_CONVERT(int, Corsia) AS varchar(20)))+1, 50) END, + Corsia; + """ + def _ok(res): + rows = res.get("rows", []) if isinstance(res, dict) else [] + self.lb.delete(0, tk.END) + corsie = [r[0] for r in rows] + for c in corsie: + self.lb.insert(tk.END, c) + idx = corsie.index("1A") if "1A" in corsie else (0 if corsie else -1) + if idx >= 0: + self.lb.selection_clear(0, tk.END) + self.lb.selection_set(idx) + self.lb.see(idx) + self._on_select(None) + else: + self._toast("Nessuna corsia trovata.") + self._busy.hide() + def _err(ex): + self._busy.hide() + messagebox.showerror("Errore", f"Caricamento corsie fallito:\n{ex}") + self._async.run(self.db.query_json(sql, {}), _ok, _err, busy=self._busy, message="Carico corsie…") + + def _on_select(self, _): + sel = self.lb.curselection() + if not sel: + return + corsia = self.lb.get(sel[0]) + self.corsia_selezionata.set(corsia) + self._load_matrix(corsia) + + def _select_corsia_in_listbox(self, corsia: str): + for i in range(self.lb.size()): + if self.lb.get(i) == corsia: + self.lb.selection_clear(0, tk.END) + self.lb.selection_set(i) + self.lb.see(i) + break + + def _load_matrix(self, corsia: str): + # nuovo token richiesta → evita che risposte vecchie spazzino la UI + self._req_counter += 1 + req_id = self._req_counter + self._last_req = req_id + + sql = """ + WITH C AS ( + SELECT + ID, + LTRIM(RTRIM(Corsia)) AS Corsia, + LTRIM(RTRIM(Fila)) AS Fila, + LTRIM(RTRIM(Colonna)) AS Colonna, + Descrizione + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) + AND LTRIM(RTRIM(Corsia)) <> '7G' AND LTRIM(RTRIM(Corsia)) = :corsia + ), + R AS ( + SELECT Fila, + DENSE_RANK() OVER ( + ORDER BY CASE WHEN TRY_CONVERT(int, Fila) IS NULL THEN 1 ELSE 0 END, + TRY_CONVERT(int, Fila), Fila + ) AS RowN + FROM C GROUP BY Fila + ), + K AS ( + SELECT Colonna, + DENSE_RANK() OVER ( + ORDER BY CASE WHEN TRY_CONVERT(int, Colonna) IS NULL THEN 1 ELSE 0 END, + TRY_CONVERT(int, Colonna), Colonna + ) AS ColN + FROM C GROUP BY Colonna + ), + S AS ( + SELECT c.ID, COUNT(DISTINCT g.BarcodePallet) AS n + FROM C AS c + LEFT JOIN dbo.XMag_GiacenzaPallet AS g ON g.IDCella = c.ID + GROUP BY c.ID + ), + U AS ( + SELECT c.ID, MIN(g.BarcodePallet) AS FirstUDC + FROM C c + LEFT JOIN dbo.XMag_GiacenzaPallet g ON g.IDCella = c.ID + GROUP BY c.ID + ) + SELECT + r.RowN, k.ColN, + CASE WHEN s.n IS NULL OR s.n = 0 THEN 0 + WHEN s.n = 1 THEN 1 + ELSE 2 END AS Stato, + c.Descrizione, + LTRIM(RTRIM(c.Fila)) AS FilaTxt, + LTRIM(RTRIM(c.Colonna)) AS ColTxt, + U.FirstUDC + FROM C c + JOIN R r ON r.Fila = c.Fila + JOIN K k ON k.Colonna = c.Colonna + LEFT JOIN S s ON s.ID = c.ID + LEFT JOIN U ON U.ID = c.ID + ORDER BY r.RowN, k.ColN; + """ + def _ok(res): + # ignora risposte superate + if req_id < self._last_req: + return + rows = res.get("rows", []) if isinstance(res, dict) else [] + if not rows: + # mostra matrice vuota senza rimuovere il frame (evita "schermo bianco") + self._rebuild_matrix(0, 0, [], [], [], [], [], corsia) + self._refresh_stats() + self._busy.hide() + return + max_r = max_c = 0 + for row in rows: + rown, coln = row[0], row[1] + if rown and coln: + max_r = max(max_r, int(rown)) + max_c = max(max_c, int(coln)) + mat = [[0] * max_c for _ in range(max_r)] + fila = [[""] * max_c for _ in range(max_r)] + col = [[""] * max_c for _ in range(max_r)] + desc = [[""] * max_c for _ in range(max_r)] + udc = [[""] * max_c for _ in range(max_r)] + for row in rows: + rown, coln, stato, descr, fila_txt, col_txt, first_udc = row + r = int(rown) - 1 + c = int(coln) - 1 + mat[r][c] = int(stato) + fila[r][c] = str(fila_txt or "") + col[r][c] = str(col_txt or "") + desc[r][c] = str(descr or f"{corsia}.{col_txt}.{fila_txt}") + udc[r][c] = str(first_udc or "") + self._rebuild_matrix(max_r, max_c, mat, fila, col, desc, udc, corsia) + self._refresh_stats() + self._busy.hide() + def _err(ex): + if req_id < self._last_req: + return + self._busy.hide() + messagebox.showerror("Errore", f"Caricamento matrice {corsia} fallito:\n{ex}") + self._async.run(self.db.query_json(sql, {"corsia": corsia}), _ok, _err, busy=self._busy, message=f"Carico corsia {corsia}…") + + # ---------------- SEARCH ---------------- + def _search_udc(self): + barcode = (self.search_var.get() or "").strip() + if not barcode: + self._toast("Inserisci un barcode UDC da cercare.") + return + + # bump token per impedire che una vecchia _load_matrix cancelli UI + self._req_counter += 1 + search_req_id = self._req_counter + self._last_req = search_req_id + + sql = """ + SELECT TOP (1) + RTRIM(c.Corsia) AS Corsia, + RTRIM(c.Colonna) AS Colonna, + RTRIM(c.Fila) AS Fila, + c.ID AS IDCella + FROM dbo.XMag_GiacenzaPallet g + JOIN dbo.Celle c ON c.ID = g.IDCella + WHERE g.BarcodePallet = :barcode + AND c.ID <> 9999 AND RTRIM(c.Corsia) <> '7G' + """ + def _ok(res): + if search_req_id < self._last_req: + return + rows = res.get("rows", []) if isinstance(res, dict) else [] + if not rows: + messagebox.showinfo("Ricerca", f"UDC {barcode} non trovata.", parent=self) + return + corsia, col, fila, _idc = rows[0] + corsia = str(corsia).strip(); col = str(col).strip(); fila = str(fila).strip() + self._pending_focus = (corsia, col, fila, barcode) + + # sincronizza listbox e carica SEMPRE la corsia della UDC + self._select_corsia_in_listbox(corsia) + self.corsia_selezionata.set(corsia) + self._load_matrix(corsia) # highlight avverrà in _rebuild_matrix + def _err(ex): + if search_req_id < self._last_req: + return + messagebox.showerror("Ricerca", f"Errore ricerca UDC:\n{ex}", parent=self) + + self._async.run(self.db.query_json(sql, {"barcode": barcode}), _ok, _err, busy=self._busy, message="Cerco UDC…") + + def _try_highlight(self, col_txt: str, fila_txt: str) -> bool: + for r in range(len(self.col_txt)): + for c in range(len(self.col_txt[r])): + if self.col_txt[r][c] == col_txt and self.fila_txt[r][c] == fila_txt: + self._clear_highlight() + btn = self.buttons[r][c] + btn.configure(border_width=3, border_color="blue") + try: + fr = self.btn_frames[r][c] + fr.configure(border_color="blue", border_width=2) + except Exception: + pass + self._highlighted = (r, c) + return True + return False + + def _highlight_cell_by_labels(self, col_txt: str, fila_txt: str): + if not self._try_highlight(col_txt, fila_txt): + self._toast("Cella trovata ma non mappabile a pulsante.") + + # ---------------- COMMANDS ---------------- + def _refresh_current(self): + if self.corsia_selezionata.get(): + self._load_matrix(self.corsia_selezionata.get()) + + def _export_xlsx(self): + if not self.matrix_state: + messagebox.showinfo("Export", "Nessuna matrice da esportare.") + return + corsia = self.corsia_selezionata.get() or "NA" + ts = datetime.now().strftime("%d_%m_%Y_%H-%M") + default = f"layout_matrice_{corsia}_{ts}.xlsx" + path = filedialog.asksaveasfilename( + title="Esporta matrice", + defaultextension=".xlsx", + initialfile=default, + filetypes=[("Excel", "*.xlsx")] + ) + if not path: + return + try: + from openpyxl import Workbook + from openpyxl.styles import PatternFill, Alignment, Font + except Exception as ex: + messagebox.showerror("Export", f"Manca openpyxl: {ex}\nInstalla con: pip install openpyxl") + return + rows = len(self.matrix_state) + cols = len(self.matrix_state[0]) if self.matrix_state else 0 + wb = Workbook() + ws1 = wb.active + ws1.title = f"Dettaglio {corsia}" + ws1.append(["Corsia", "FilaIdx", "ColIdx", "Stato", "Descrizione", "FilaTxt", "ColTxt", "UDC1"]) + for r in range(rows): + for c in range(cols): + st = self.matrix_state[r][c] + stato_lbl = "Vuota" if st == 0 else ("Piena" if st == 1 else "Doppia") + ws1.append([corsia, r + 1, c + 1, stato_lbl, + self.desc[r][c], self.fila_txt[r][c], self.col_txt[r][c], self.udc1[r][c]]) + for cell in ws1[1]: + cell.font = Font(bold=True) + + ws2 = wb.create_sheet(f"Matrice {corsia}") + fills = { + 0: PatternFill("solid", fgColor="B0B0B0"), + 1: PatternFill("solid", fgColor="FFA500"), + 2: PatternFill("solid", fgColor="D62728"), + } + center = Alignment(horizontal="center", vertical="center", wrap_text=True) + for r in range(rows): + for c in range(cols): + value = f"{corsia}.{self.col_txt[r][c]}.{self.fila_txt[r][c]}\n{self.udc1[r][c]}" + cell = ws2.cell(row=(rows - r), column=c + 1, value=value) # capovolto per avere 'a' in basso + cell.fill = fills.get(self.matrix_state[r][c], fills[0]) + cell.alignment = center + try: + wb.save(path) + self._toast(f"Esportato: {path}") + except Exception as ex: + messagebox.showerror("Export", f"Salvataggio fallito:\n{ex}") + + # ---------------- STATS ---------------- + def _refresh_stats(self): + # globale dal DB + sql_tot = """ + WITH C AS ( + SELECT ID + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) + AND LTRIM(RTRIM(Corsia)) <> '7G' + AND LTRIM(RTRIM(Fila)) IS NOT NULL + AND LTRIM(RTRIM(Colonna)) IS NOT NULL + ), + S AS ( + SELECT c.ID, COUNT(DISTINCT g.BarcodePallet) AS n + FROM C AS c LEFT JOIN dbo.XMag_GiacenzaPallet AS g ON g.IDCella = c.ID + GROUP BY c.ID + ) + SELECT + CAST(SUM(CASE WHEN s.n>0 THEN 1 ELSE 0 END) AS float)/NULLIF(COUNT(*),0) AS PercPieno, + CAST(SUM(CASE WHEN s.n>1 THEN 1 ELSE 0 END) AS float)/NULLIF(COUNT(*),0) AS PercDoppie + FROM C LEFT JOIN S s ON s.ID = C.ID; + """ + def _ok(res): + rows = res.get("rows", []) if isinstance(res, dict) else [] + p_full = float(rows[0][0] or 0.0) if rows else 0.0 + p_dbl = float(rows[0][1] or 0.0) if rows else 0.0 + self._draw_bar(self.tot_canvas, p_full) + self.tot_text.configure(text=pct_text(p_full, p_dbl)) + self._async.run(self.db.query_json(sql_tot, {}), _ok, lambda e: None, busy=None, message=None) + + # selezionata dalla matrice in memoria + if self.matrix_state: + tot = sum(len(r) for r in self.matrix_state) + full = sum(1 for row in self.matrix_state for v in row if v in (1, 2)) + doubles = sum(1 for row in self.matrix_state for v in row if v == 2) + p_full = (full / tot) if tot else 0.0 + p_dbl = (doubles / tot) if tot else 0.0 + else: + p_full = p_dbl = 0.0 + self._draw_bar(self.sel_canvas, p_full) + self.sel_text.configure(text=pct_text(p_full, p_dbl)) + + def _draw_bar(self, cv: tk.Canvas, p_full: float): + cv.delete("all") + w = max(300, cv.winfo_width() or 600) + h = 18 + fw = int(w * max(0.0, min(1.0, p_full))) + cv.create_rectangle(2, 2, 2 + fw, 2 + h, fill="#D62728", width=0) + cv.create_rectangle(2 + fw, 2, 2 + w, 2 + h, fill="#2CA02C", width=0) + cv.create_rectangle(2, 2, 2 + w, 2 + h, outline="#555", width=1) + + # ---------------- UTIL ---------------- + def _toast(self, msg, ms=1400): + if not hasattr(self, "_status"): + self._status = ctk.CTkLabel(self, anchor="w") + self._status.grid(row=3, column=0, sticky="ew") + self._status.configure(text=msg) + self.after(ms, lambda: self._status.configure(text="")) + + def _copy(self, txt: str): + self.clipboard_clear() + self.clipboard_append(txt) + self._toast(f"Copiato: {txt}") + + +def open_layout_window(parent, db_app): + key = "_layout_window_singleton" + ex = getattr(parent, key, None) + if ex and ex.winfo_exists(): + try: + ex.lift() + ex.focus_force() + return ex + except Exception: + pass + w = LayoutWindow(parent, db_app) + setattr(parent, key, w) + return w diff --git a/layout_window.py.bak_perf b/layout_window.py.bak_perf new file mode 100644 index 0000000..fd94d5e --- /dev/null +++ b/layout_window.py.bak_perf @@ -0,0 +1,632 @@ +from __future__ import annotations +import tkinter as tk +from tkinter import Menu, messagebox, filedialog +import customtkinter as ctk +from datetime import datetime + +from gestione_aree_frame_async import BusyOverlay, AsyncRunner + +# ---- Color palette ---- +COLOR_EMPTY = "#B0B0B0" # grigio (vuota) +COLOR_FULL = "#FFA500" # arancione (una UDC) +COLOR_DOUBLE = "#D62728" # rosso (>=2 UDC) +FG_DARK = "#111111" +FG_LIGHT = "#FFFFFF" + + +def pct_text(p_full: float, p_double: float | None = None) -> str: + p_full = max(0.0, min(1.0, p_full)) + pf = round(p_full * 100, 1) + pe = round(100 - pf, 1) + if p_double and p_double > 0: + pd = round(p_double * 100, 1) + return f"Pieno {pf}% · Vuoto {pe}% (di cui doppie {pd}%)" + return f"Pieno {pf}% · Vuoto {pe}%" + + +class LayoutWindow(ctk.CTkToplevel): + """ + Visualizzazione layout corsie con matrice di celle. + - Ogni cella è un pulsante colorato (vuota/piena/doppia) + - Etichetta su DUE righe: + 1) "Corsia.Colonna.Fila" (una sola riga, senza andare a capo) + 2) barcode UDC (primo, se presente) + - Ricerca per barcode UDC con cambio automatico corsia + highlight cella + - Statistiche: globale e corsia selezionata + - Export XLSX + """ + def __init__(self, parent: tk.Widget, db_app): + super().__init__(parent) + self.title("Warehouse · Layout corsie") + self.geometry("1200x740") + self.minsize(980, 560) + self.resizable(True, True) + + self.db = db_app + self._busy = BusyOverlay(self) + self._async = AsyncRunner(self) + + # layout principale 5% / 80% / 15% + self.grid_rowconfigure(0, weight=5) + self.grid_rowconfigure(1, weight=80) + self.grid_rowconfigure(2, weight=15) + self.grid_columnconfigure(0, weight=1) + + # stato runtime + self.corsia_selezionata = tk.StringVar() + self.buttons: list[list[ctk.CTkButton]] = [] + self.btn_frames: list[list[ctk.CTkFrame]] = [] + self.matrix_state: list[list[int]] = [] # <— rinominata: prima era self.state + self.fila_txt: list[list[str]] = [] + self.col_txt: list[list[str]] = [] + self.desc: list[list[str]] = [] + self.udc1: list[list[str]] = [] # primo barcode UDC trovato (o "") + + # ricerca → focus differito (corsia, col, fila, barcode) + self._pending_focus: tuple[str, str, str, str] | None = None + self._highlighted: tuple[int, int] | None = None + + # anti-race: token per ignorare risposte vecchie + self._req_counter = 0 + self._last_req = 0 + + self._build_top() + self._build_matrix_host() + self._build_stats() + + self._load_corsie() + self.bind("", lambda e: self.after_idle(self._refresh_stats)) + + # ---------------- TOP BAR ---------------- + def _build_top(self): + top = ctk.CTkFrame(self) + top.grid(row=0, column=0, sticky="nsew", padx=8, pady=6) + for i in range(4): + top.grid_columnconfigure(i, weight=0) + top.grid_columnconfigure(1, weight=1) + + # lista corsie + lf = ctk.CTkFrame(top) + lf.grid(row=0, column=0, sticky="nsw") + lf.grid_columnconfigure(0, weight=1) + ctk.CTkLabel(lf, text="Corsie", font=("", 12, "bold")).grid(row=0, column=0, sticky="w", padx=6, pady=(6, 2)) + self.lb = tk.Listbox(lf, height=6, exportselection=False) + self.lb.grid(row=1, column=0, sticky="nsw", padx=6, pady=(0, 6)) + self.lb.bind("<>", self._on_select) + + # search by barcode + srch = ctk.CTkFrame(top) + srch.grid(row=0, column=1, sticky="nsew", padx=(10, 10)) + self.search_var = tk.StringVar() + self.search_entry = ctk.CTkEntry(srch, textvariable=self.search_var, width=260) + self.search_entry.grid(row=0, column=0, sticky="w") + ctk.CTkButton(srch, text="Cerca per barcode UDC", command=self._search_udc).grid(row=0, column=1, padx=(8, 0)) + srch.grid_columnconfigure(0, weight=1) + + # toolbar + tb = ctk.CTkFrame(top) + tb.grid(row=0, column=3, sticky="ne") + ctk.CTkButton(tb, text="Aggiorna", command=self._refresh_current).grid(row=0, column=0, padx=4) + ctk.CTkButton(tb, text="Export XLSX", command=self._export_xlsx).grid(row=0, column=1, padx=4) + + # ---------------- MATRIX HOST ---------------- + def _build_matrix_host(self): + center = ctk.CTkFrame(self) + center.grid(row=1, column=0, sticky="nsew", padx=8, pady=(0, 6)) + center.grid_rowconfigure(0, weight=1) + center.grid_columnconfigure(0, weight=1) + self.host = ctk.CTkFrame(center) + self.host.grid(row=0, column=0, sticky="nsew", padx=4, pady=4) + + def _apply_cell_style(self, btn: ctk.CTkButton, state: int): + if state == 0: + btn.configure( + fg_color=COLOR_EMPTY, hover_color="#9A9A9A", + text_color=FG_DARK, border_width=0 + ) + elif state == 1: + btn.configure( + fg_color=COLOR_FULL, hover_color="#E69500", + text_color=FG_DARK, border_width=0 + ) + else: + btn.configure( + fg_color=COLOR_DOUBLE, hover_color="#B22222", + text_color=FG_LIGHT, border_width=0 + ) + + def _clear_highlight(self): + if self._highlighted and self.buttons: + r, c = self._highlighted + try: + if 0 <= r < len(self.buttons) and 0 <= c < len(self.buttons[r]): + btn = self.buttons[r][c] + if getattr(btn, "winfo_exists", None) and btn.winfo_exists(): + try: + btn.configure(border_width=0) + except Exception: + pass + # clear blue frame border + try: + fr = self.btn_frames[r][c] + if fr and getattr(fr, "winfo_exists", None) and fr.winfo_exists(): + fr.configure(border_width=0) + # in CTkFrame non esiste highlightthickness come in tk; border_* è corretto + except Exception: + pass + except Exception: + pass + self._highlighted = None + + def _rebuild_matrix(self, rows: int, cols: int, state, fila_txt, col_txt, desc, udc1, corsia): + # prima rimuovi highlight su vecchi bottoni + self._clear_highlight() + # ripulisci host + for w in self.host.winfo_children(): + w.destroy() + self.buttons.clear() + self.btn_frames.clear() + + # salva matrici + self.matrix_state, self.fila_txt, self.col_txt, self.desc, self.udc1 = state, fila_txt, col_txt, desc, udc1 + + # ridistribuisci pesi griglia + for r in range(rows): + self.host.grid_rowconfigure(r, weight=1) + for c in range(cols): + self.host.grid_columnconfigure(c, weight=1) + + # crea Frame+Button per cella (righe invertite: fila "a" in basso) + for r in range(rows): + row_btns = [] + row_frames = [] + for c in range(cols): + st = state[r][c] + code = f"{corsia}.{col_txt[r][c]}.{fila_txt[r][c]}" # PRIMA RIGA (in linea) + udc = udc1[r][c] or "" # SECONDA RIGA: barcode UDC + text = f"{code}\n{udc}" + cell = ctk.CTkFrame(self.host, corner_radius=6, border_width=0) + btn = ctk.CTkButton( + cell, + text=text, + corner_radius=6) + self._apply_cell_style(btn, st) + + rr = (rows - 1) - r # capovolgi + cell.grid(row=rr, column=c, padx=1, pady=1, sticky="nsew") + btn.pack(fill="both", expand=True) + btn.configure(command=lambda rr=r, cc=c: self._open_menu(None, rr, cc)) + btn.bind("", lambda e, rr=r, cc=c: self._open_menu(e, rr, cc)) + row_btns.append(btn) + row_frames.append(cell) + self.buttons.append(row_btns) + self.btn_frames.append(row_frames) + + # focus differito post-ricarica + if self._pending_focus and self._pending_focus[0] == corsia: + _, col, fila, _barcode = self._pending_focus + self._pending_focus = None + self._highlight_cell_by_labels(col, fila) + + # ---------------- CONTEXT MENU ---------------- + def _open_menu(self, event, r, c): + st = self.matrix_state[r][c] + corsia = self.corsia_selezionata.get() + label = f"{corsia}.{self.col_txt[r][c]}.{self.fila_txt[r][c]}" + m = Menu(self, tearoff=0) + m.add_command(label="Apri dettaglio", command=lambda: self._toast(f"Dettaglio {label}")) + if st == 0: + m.add_command(label="Segna pieno", command=lambda: self._set_cell(r, c, 1)) + m.add_command(label="Segna doppia", command=lambda: self._set_cell(r, c, 2)) + elif st == 1: + m.add_command(label="Segna vuoto", command=lambda: self._set_cell(r, c, 0)) + m.add_command(label="Segna doppia", command=lambda: self._set_cell(r, c, 2)) + else: + m.add_command(label="Segna vuoto", command=lambda: self._set_cell(r, c, 0)) + m.add_command(label="Segna pieno", command=lambda: self._set_cell(r, c, 1)) + m.add_separator() + m.add_command(label="Copia ubicazione", command=lambda: self._copy(label)) + x = self.winfo_pointerx() if event is None else event.x_root + y = self.winfo_pointery() if event is None else event.y_root + m.tk_popup(x, y) + + def _set_cell(self, r, c, val): + self.matrix_state[r][c] = val + btn = self.buttons[r][c] + self._apply_cell_style(btn, val) + self._refresh_stats() + + # ---------------- STATS ---------------- + def _build_stats(self): + bottom = ctk.CTkFrame(self) + bottom.grid(row=2, column=0, sticky="nsew", padx=8, pady=6) + bottom.grid_columnconfigure(0, weight=1) + + ctk.CTkLabel(bottom, text="Riempimento globale", font=("", 10, "bold")).grid(row=0, column=0, sticky="w", pady=(0, 2)) + self.tot_canvas = tk.Canvas(bottom, height=22, highlightthickness=0) + self.tot_canvas.grid(row=1, column=0, sticky="ew", padx=(0, 260)) + self.tot_text = ctk.CTkLabel(bottom, text=pct_text(0.0, 0.0)) + self.tot_text.grid(row=1, column=0, sticky="e") + + ctk.CTkLabel(bottom, text="Riempimento corsia selezionata", font=("", 10, "bold")).grid(row=2, column=0, sticky="w", pady=(10, 2)) + self.sel_canvas = tk.Canvas(bottom, height=22, highlightthickness=0) + self.sel_canvas.grid(row=3, column=0, sticky="ew", padx=(0, 260)) + self.sel_text = ctk.CTkLabel(bottom, text=pct_text(0.0, 0.0)) + self.sel_text.grid(row=3, column=0, sticky="e") + + leg = ctk.CTkFrame(bottom) + leg.grid(row=4, column=0, sticky="w", pady=(10, 0)) + ctk.CTkLabel(leg, text="Legenda celle:").grid(row=0, column=0, padx=(0, 8)) + self._legend(leg, 1, "Vuota", COLOR_EMPTY) + self._legend(leg, 3, "Piena", COLOR_FULL) + self._legend(leg, 5, "Doppia UDC", COLOR_DOUBLE) + + def _legend(self, parent, col, text, color): + box = tk.Canvas(parent, width=18, height=12, highlightthickness=0) + box.create_rectangle(0, 0, 18, 12, fill=color, width=1, outline="#444") + box.grid(row=0, column=col) + ctk.CTkLabel(parent, text=text).grid(row=0, column=col + 1, padx=(4, 12)) + + # ---------------- DATA LOADING ---------------- + def _load_corsie(self): + sql = """ + WITH C AS ( + SELECT DISTINCT LTRIM(RTRIM(Corsia)) AS Corsia + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) AND LTRIM(RTRIM(Corsia)) <> '7G' + ) + SELECT Corsia + FROM C + ORDER BY + CASE + WHEN LEFT(Corsia,3)='MAG' AND TRY_CONVERT(int, SUBSTRING(Corsia,4,50)) IS NOT NULL THEN 0 + WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN 1 + ELSE 2 + END, + CASE WHEN LEFT(Corsia,3)='MAG' THEN TRY_CONVERT(int, SUBSTRING(Corsia,4,50)) END, + CASE WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN TRY_CONVERT(int, Corsia) END, + CASE WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN SUBSTRING(Corsia, LEN(CAST(TRY_CONVERT(int, Corsia) AS varchar(20)))+1, 50) END, + Corsia; + """ + def _ok(res): + rows = res.get("rows", []) if isinstance(res, dict) else [] + self.lb.delete(0, tk.END) + corsie = [r[0] for r in rows] + for c in corsie: + self.lb.insert(tk.END, c) + idx = corsie.index("1A") if "1A" in corsie else (0 if corsie else -1) + if idx >= 0: + self.lb.selection_clear(0, tk.END) + self.lb.selection_set(idx) + self.lb.see(idx) + self._on_select(None) + else: + self._toast("Nessuna corsia trovata.") + self._busy.hide() + def _err(ex): + self._busy.hide() + messagebox.showerror("Errore", f"Caricamento corsie fallito:\n{ex}") + self._async.run(self.db.query_json(sql, {}), _ok, _err, busy=self._busy, message="Carico corsie…") + + def _on_select(self, _): + sel = self.lb.curselection() + if not sel: + return + corsia = self.lb.get(sel[0]) + self.corsia_selezionata.set(corsia) + self._load_matrix(corsia) + + def _select_corsia_in_listbox(self, corsia: str): + for i in range(self.lb.size()): + if self.lb.get(i) == corsia: + self.lb.selection_clear(0, tk.END) + self.lb.selection_set(i) + self.lb.see(i) + break + + def _load_matrix(self, corsia: str): + # nuovo token richiesta → evita che risposte vecchie spazzino la UI + self._req_counter += 1 + req_id = self._req_counter + self._last_req = req_id + + sql = """ + WITH C AS ( + SELECT + ID, + LTRIM(RTRIM(Corsia)) AS Corsia, + LTRIM(RTRIM(Fila)) AS Fila, + LTRIM(RTRIM(Colonna)) AS Colonna, + Descrizione + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) + AND LTRIM(RTRIM(Corsia)) <> '7G' AND LTRIM(RTRIM(Corsia)) = :corsia + ), + R AS ( + SELECT Fila, + DENSE_RANK() OVER ( + ORDER BY CASE WHEN TRY_CONVERT(int, Fila) IS NULL THEN 1 ELSE 0 END, + TRY_CONVERT(int, Fila), Fila + ) AS RowN + FROM C GROUP BY Fila + ), + K AS ( + SELECT Colonna, + DENSE_RANK() OVER ( + ORDER BY CASE WHEN TRY_CONVERT(int, Colonna) IS NULL THEN 1 ELSE 0 END, + TRY_CONVERT(int, Colonna), Colonna + ) AS ColN + FROM C GROUP BY Colonna + ), + S AS ( + SELECT c.ID, COUNT(DISTINCT g.BarcodePallet) AS n + FROM C AS c + LEFT JOIN dbo.XMag_GiacenzaPallet AS g ON g.IDCella = c.ID + GROUP BY c.ID + ), + U AS ( + SELECT c.ID, MIN(g.BarcodePallet) AS FirstUDC + FROM C c + LEFT JOIN dbo.XMag_GiacenzaPallet g ON g.IDCella = c.ID + GROUP BY c.ID + ) + SELECT + r.RowN, k.ColN, + CASE WHEN s.n IS NULL OR s.n = 0 THEN 0 + WHEN s.n = 1 THEN 1 + ELSE 2 END AS Stato, + c.Descrizione, + LTRIM(RTRIM(c.Fila)) AS FilaTxt, + LTRIM(RTRIM(c.Colonna)) AS ColTxt, + U.FirstUDC + FROM C c + JOIN R r ON r.Fila = c.Fila + JOIN K k ON k.Colonna = c.Colonna + LEFT JOIN S s ON s.ID = c.ID + LEFT JOIN U ON U.ID = c.ID + ORDER BY r.RowN, k.ColN; + """ + def _ok(res): + # ignora risposte superate + if req_id < self._last_req: + return + rows = res.get("rows", []) if isinstance(res, dict) else [] + if not rows: + # mostra matrice vuota senza rimuovere il frame (evita "schermo bianco") + self._rebuild_matrix(0, 0, [], [], [], [], [], corsia) + self._refresh_stats() + self._busy.hide() + return + max_r = max_c = 0 + for row in rows: + rown, coln = row[0], row[1] + if rown and coln: + max_r = max(max_r, int(rown)) + max_c = max(max_c, int(coln)) + mat = [[0] * max_c for _ in range(max_r)] + fila = [[""] * max_c for _ in range(max_r)] + col = [[""] * max_c for _ in range(max_r)] + desc = [[""] * max_c for _ in range(max_r)] + udc = [[""] * max_c for _ in range(max_r)] + for row in rows: + rown, coln, stato, descr, fila_txt, col_txt, first_udc = row + r = int(rown) - 1 + c = int(coln) - 1 + mat[r][c] = int(stato) + fila[r][c] = str(fila_txt or "") + col[r][c] = str(col_txt or "") + desc[r][c] = str(descr or f"{corsia}.{col_txt}.{fila_txt}") + udc[r][c] = str(first_udc or "") + self._rebuild_matrix(max_r, max_c, mat, fila, col, desc, udc, corsia) + self._refresh_stats() + self._busy.hide() + def _err(ex): + if req_id < self._last_req: + return + self._busy.hide() + messagebox.showerror("Errore", f"Caricamento matrice {corsia} fallito:\n{ex}") + self._async.run(self.db.query_json(sql, {"corsia": corsia}), _ok, _err, busy=self._busy, message=f"Carico corsia {corsia}…") + + # ---------------- SEARCH ---------------- + def _search_udc(self): + barcode = (self.search_var.get() or "").strip() + if not barcode: + self._toast("Inserisci un barcode UDC da cercare.") + return + + # bump token per impedire che una vecchia _load_matrix cancelli UI + self._req_counter += 1 + search_req_id = self._req_counter + self._last_req = search_req_id + + sql = """ + SELECT TOP (1) + RTRIM(c.Corsia) AS Corsia, + RTRIM(c.Colonna) AS Colonna, + RTRIM(c.Fila) AS Fila, + c.ID AS IDCella + FROM dbo.XMag_GiacenzaPallet g + JOIN dbo.Celle c ON c.ID = g.IDCella + WHERE g.BarcodePallet = :barcode + AND c.ID <> 9999 AND RTRIM(c.Corsia) <> '7G' + """ + def _ok(res): + if search_req_id < self._last_req: + return + rows = res.get("rows", []) if isinstance(res, dict) else [] + if not rows: + messagebox.showinfo("Ricerca", f"UDC {barcode} non trovata.", parent=self) + return + corsia, col, fila, _idc = rows[0] + corsia = str(corsia).strip(); col = str(col).strip(); fila = str(fila).strip() + self._pending_focus = (corsia, col, fila, barcode) + + # sincronizza listbox e carica SEMPRE la corsia della UDC + self._select_corsia_in_listbox(corsia) + self.corsia_selezionata.set(corsia) + self._load_matrix(corsia) # highlight avverrà in _rebuild_matrix + def _err(ex): + if search_req_id < self._last_req: + return + messagebox.showerror("Ricerca", f"Errore ricerca UDC:\n{ex}", parent=self) + + self._async.run(self.db.query_json(sql, {"barcode": barcode}), _ok, _err, busy=self._busy, message="Cerco UDC…") + + def _try_highlight(self, col_txt: str, fila_txt: str) -> bool: + for r in range(len(self.col_txt)): + for c in range(len(self.col_txt[r])): + if self.col_txt[r][c] == col_txt and self.fila_txt[r][c] == fila_txt: + self._clear_highlight() + btn = self.buttons[r][c] + btn.configure(border_width=3, border_color="blue") + try: + fr = self.btn_frames[r][c] + fr.configure(border_color="blue", border_width=2) + except Exception: + pass + self._highlighted = (r, c) + return True + return False + + def _highlight_cell_by_labels(self, col_txt: str, fila_txt: str): + if not self._try_highlight(col_txt, fila_txt): + self._toast("Cella trovata ma non mappabile a pulsante.") + + # ---------------- COMMANDS ---------------- + def _refresh_current(self): + if self.corsia_selezionata.get(): + self._load_matrix(self.corsia_selezionata.get()) + + def _export_xlsx(self): + if not self.matrix_state: + messagebox.showinfo("Export", "Nessuna matrice da esportare.") + return + corsia = self.corsia_selezionata.get() or "NA" + ts = datetime.now().strftime("%d_%m_%Y_%H-%M") + default = f"layout_matrice_{corsia}_{ts}.xlsx" + path = filedialog.asksaveasfilename( + title="Esporta matrice", + defaultextension=".xlsx", + initialfile=default, + filetypes=[("Excel", "*.xlsx")] + ) + if not path: + return + try: + from openpyxl import Workbook + from openpyxl.styles import PatternFill, Alignment, Font + except Exception as ex: + messagebox.showerror("Export", f"Manca openpyxl: {ex}\nInstalla con: pip install openpyxl") + return + rows = len(self.matrix_state) + cols = len(self.matrix_state[0]) if self.matrix_state else 0 + wb = Workbook() + ws1 = wb.active + ws1.title = f"Dettaglio {corsia}" + ws1.append(["Corsia", "FilaIdx", "ColIdx", "Stato", "Descrizione", "FilaTxt", "ColTxt", "UDC1"]) + for r in range(rows): + for c in range(cols): + st = self.matrix_state[r][c] + stato_lbl = "Vuota" if st == 0 else ("Piena" if st == 1 else "Doppia") + ws1.append([corsia, r + 1, c + 1, stato_lbl, + self.desc[r][c], self.fila_txt[r][c], self.col_txt[r][c], self.udc1[r][c]]) + for cell in ws1[1]: + cell.font = Font(bold=True) + + ws2 = wb.create_sheet(f"Matrice {corsia}") + fills = { + 0: PatternFill("solid", fgColor="B0B0B0"), + 1: PatternFill("solid", fgColor="FFA500"), + 2: PatternFill("solid", fgColor="D62728"), + } + center = Alignment(horizontal="center", vertical="center", wrap_text=True) + for r in range(rows): + for c in range(cols): + value = f"{corsia}.{self.col_txt[r][c]}.{self.fila_txt[r][c]}\n{self.udc1[r][c]}" + cell = ws2.cell(row=(rows - r), column=c + 1, value=value) # capovolto per avere 'a' in basso + cell.fill = fills.get(self.matrix_state[r][c], fills[0]) + cell.alignment = center + try: + wb.save(path) + self._toast(f"Esportato: {path}") + except Exception as ex: + messagebox.showerror("Export", f"Salvataggio fallito:\n{ex}") + + # ---------------- STATS ---------------- + def _refresh_stats(self): + # globale dal DB + sql_tot = """ + WITH C AS ( + SELECT ID + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) + AND LTRIM(RTRIM(Corsia)) <> '7G' + AND LTRIM(RTRIM(Fila)) IS NOT NULL + AND LTRIM(RTRIM(Colonna)) IS NOT NULL + ), + S AS ( + SELECT c.ID, COUNT(DISTINCT g.BarcodePallet) AS n + FROM C AS c LEFT JOIN dbo.XMag_GiacenzaPallet AS g ON g.IDCella = c.ID + GROUP BY c.ID + ) + SELECT + CAST(SUM(CASE WHEN s.n>0 THEN 1 ELSE 0 END) AS float)/NULLIF(COUNT(*),0) AS PercPieno, + CAST(SUM(CASE WHEN s.n>1 THEN 1 ELSE 0 END) AS float)/NULLIF(COUNT(*),0) AS PercDoppie + FROM C LEFT JOIN S s ON s.ID = C.ID; + """ + def _ok(res): + rows = res.get("rows", []) if isinstance(res, dict) else [] + p_full = float(rows[0][0] or 0.0) if rows else 0.0 + p_dbl = float(rows[0][1] or 0.0) if rows else 0.0 + self._draw_bar(self.tot_canvas, p_full) + self.tot_text.configure(text=pct_text(p_full, p_dbl)) + self._async.run(self.db.query_json(sql_tot, {}), _ok, lambda e: None, busy=None, message=None) + + # selezionata dalla matrice in memoria + if self.matrix_state: + tot = sum(len(r) for r in self.matrix_state) + full = sum(1 for row in self.matrix_state for v in row if v in (1, 2)) + doubles = sum(1 for row in self.matrix_state for v in row if v == 2) + p_full = (full / tot) if tot else 0.0 + p_dbl = (doubles / tot) if tot else 0.0 + else: + p_full = p_dbl = 0.0 + self._draw_bar(self.sel_canvas, p_full) + self.sel_text.configure(text=pct_text(p_full, p_dbl)) + + def _draw_bar(self, cv: tk.Canvas, p_full: float): + cv.delete("all") + w = max(300, cv.winfo_width() or 600) + h = 18 + fw = int(w * max(0.0, min(1.0, p_full))) + cv.create_rectangle(2, 2, 2 + fw, 2 + h, fill="#D62728", width=0) + cv.create_rectangle(2 + fw, 2, 2 + w, 2 + h, fill="#2CA02C", width=0) + cv.create_rectangle(2, 2, 2 + w, 2 + h, outline="#555", width=1) + + # ---------------- UTIL ---------------- + def _toast(self, msg, ms=1400): + if not hasattr(self, "_status"): + self._status = ctk.CTkLabel(self, anchor="w") + self._status.grid(row=3, column=0, sticky="ew") + self._status.configure(text=msg) + self.after(ms, lambda: self._status.configure(text="")) + + def _copy(self, txt: str): + self.clipboard_clear() + self.clipboard_append(txt) + self._toast(f"Copiato: {txt}") + + +def open_layout_window(parent, db_app): + key = "_layout_window_singleton" + ex = getattr(parent, key, None) + if ex and ex.winfo_exists(): + try: + ex.lift() + ex.focus_force() + return ex + except Exception: + pass + w = LayoutWindow(parent, db_app) + setattr(parent, key, w) + return w diff --git a/main.py b/main.py new file mode 100644 index 0000000..615011c --- /dev/null +++ b/main.py @@ -0,0 +1,156 @@ + +import sys +import asyncio +import tkinter as tk +import customtkinter as ctk + +from async_msssql_query import AsyncMSSQLClient, make_mssql_dsn +from async_loop_singleton import get_global_loop + +from layout_window import open_layout_window +from view_celle_multiple import open_celle_multiple_window +from reset_corsie import open_reset_corsie_window +from search_pallets import open_search_window + +# Try factory, else frame, else app (senza passare conn_str all'App) +try: + from gestione_pickinglist import create_frame as create_pickinglist_frame +except Exception: + try: + from gestione_pickinglist import GestionePickingListFrame as _PLFrame + import customtkinter as ctk + def create_pickinglist_frame(parent, db_client=None, conn_str=None): + ctk.set_appearance_mode("light") + ctk.set_default_color_theme("green") + return _PLFrame(parent, db_client=db_client, conn_str=conn_str) + except Exception: + # Ultimo fallback: alcune versioni espongono solo la App e NON accettano conn_str + # Ultimo fallback: alcune versioni espongono solo la App e NON accettano parametri + from gestione_pickinglist import GestionePickingListApp as _PLApp + def create_pickinglist_frame(parent, db_client=None, conn_str=None): + app = _PLApp() # <-- niente parametri qui + app.mainloop() + return tk.Frame(parent) + + + +# ---- Config ---- +SERVER = r"mde3\gesterp" +DBNAME = "Mediseawall" +USER = "sa" +PASSWORD = "1Password1" + +if sys.platform.startswith("win"): + try: + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + except Exception: + pass + +# Create ONE global loop and make it the default everywhere +_loop = get_global_loop() +asyncio.set_event_loop(_loop) + +# --- DPI tracker compatibility --- +def _noop(*args, **kwargs): + return None +if not hasattr(tk.Toplevel, "block_update_dimensions_event"): + tk.Toplevel.block_update_dimensions_event = _noop # type: ignore[attr-defined] +if not hasattr(tk.Toplevel, "unblock_update_dimensions_event"): + tk.Toplevel.unblock_update_dimensions_event = _noop # type: ignore[attr-defined] + +dsn_app = make_mssql_dsn(server=SERVER, database=DBNAME, user=USER, password=PASSWORD) +db_app = AsyncMSSQLClient(dsn_app) + + +def open_pickinglist_window(parent: tk.Misc, db_client: AsyncMSSQLClient): + win = ctk.CTkToplevel(parent) + win.title("Gestione Picking List") + win.geometry("1200x700+0+100") + win.minsize(1000, 560) + + # 1) tieni la toplevel fuori scena mentre componi + try: + win.withdraw() + # opzionale: rendila invisibile anche se il WM la “intr intravede†+ win.attributes("-alpha", 0.0) + except Exception: + pass + + # 2) costruisci tutto il contenuto + frame = create_pickinglist_frame(win, db_client=db_client) + try: + frame.pack(fill="both", expand=True) + except Exception: + pass + + # 3) quando è pronta, mostra "a scatto" davanti, senza topmost + try: + win.update_idletasks() + try: + win.transient(parent) # z-order legato alla main + except Exception: + pass + try: + win.deiconify() + except Exception: + pass + win.lift() + try: + win.focus_force() + except Exception: + pass + # ripristina opacità + try: + win.attributes("-alpha", 1.0) + except Exception: + pass + except Exception: + pass + + win.bind("", lambda e: win.destroy()) + win.protocol("WM_DELETE_WINDOW", win.destroy) + return win + + + + +class Launcher(ctk.CTk): + def __init__(self): + super().__init__() + self.title("Warehouse 1.0.0") + self.geometry("1200x70+0+0") + + wrap = ctk.CTkFrame(self) + wrap.pack(pady=10, fill="x") + + ctk.CTkButton(wrap, text="Gestione Corsie", + command=lambda: open_reset_corsie_window(self, db_app)).grid(row=0, column=0, padx=6, pady=6, sticky="ew") + ctk.CTkButton(wrap, text="Gestione Layout", + command=lambda: open_layout_window(self, db_app)).grid(row=0, column=1, padx=6, pady=6, sticky="ew") + ctk.CTkButton(wrap, text="UDC Fantasma", + command=lambda: open_celle_multiple_window(self, db_app)).grid(row=0, column=2, padx=6, pady=6, sticky="ew") + ctk.CTkButton(wrap, text="Ricerca UDC", + command=lambda: open_search_window(self, db_app)).grid(row=0, column=3, padx=6, pady=6, sticky="ew") + ctk.CTkButton(wrap, text="Gestione Picking List", + command=lambda: open_pickinglist_window(self, db_app)).grid(row=0, column=4, padx=6, pady=6, sticky="ew") + + for i in range(5): + wrap.grid_columnconfigure(i, weight=1) + + def _on_close(): + try: + fut = asyncio.run_coroutine_threadsafe(db_app.dispose(), _loop) + try: + fut.result(timeout=2) + except Exception: + pass + finally: + self.destroy() + + self.protocol("WM_DELETE_WINDOW", _on_close) + + +if __name__ == "__main__": + ctk.set_appearance_mode("light") + ctk.set_default_color_theme("green") + Launcher().mainloop() diff --git a/pickinglist.sql b/pickinglist.sql new file mode 100644 index 0000000..1aecde5 --- /dev/null +++ b/pickinglist.sql @@ -0,0 +1,62 @@ +SELECT * FROM vViewMappaturaDescrizioneCorsia WHERE ( Area > 0) ORDER BY Area Desc + +SELECT * FROM Celle WHERE ( ID > 0) ORDER BY ID Desc + +SELECT TOP 1000 [mc_X] ,[minFila] ,[maxFila] ,[minColonna] ,[maxColonna] ,[mc_Numero_Magazzino] ,[mc_Numero_Area] FROM vViewMappaturaPosizCorsia WHERE [mc_Numero_Area] =1 + + +SELECT CASE WHEN Nota = 'ASC' THEN 0 ELSE CASE WHEN Nota = 'DESC' THEN 1 END END AS Nota FROM MagLayout WHERE (IDArea = 1) + +SELECT ID, Descrizione FROM Magazzini ORDER BY Descrizione + +SELECT ID, Descrizione FROM Celle ORDER BY Descrizione + +SELECT [ID],[CorsiaDescrizione] FROM vViewMappaturaDescrizioneCorsia + + + SELECT COUNT(DISTINCT Pallet) AS Pallet, COUNT(DISTINCT Lotto) AS Lotto, COUNT(DISTINCT Articolo) AS Articolo, COUNT(DISTINCT Descrizione) AS Descrizione, SUM(Qta) AS Qta, Documento, CodNazione, NAZIONE, Stato, MAX(PalletCella) AS PalletCella, MAX(Magazzino) AS Magazzino, MAX(Area) AS Area, MAX(Cella) AS Cella, MIN(Ordinamento) AS Ordinamento, MAX(IDStato) AS IDStato FROM dbo.XMag_ViewPackingList GROUP BY Documento, CodNazione, NAZIONE, Stato + + SELECT * FROM vViewPackingListRestante WHERE Documento = 237 ORDER BY Ordinamento + SELECT * FROM ViewPackingListRestante WHERE Documento = 246 ORDER BY Ordinamento + + + + +USE master; +GO + +-- (facoltativo) terminare connessioni attive +ALTER DATABASE SAMA1 SET SINGLE_USER WITH ROLLBACK IMMEDIATE; +GO + +-- Ripristino dal tuo snapshot +RESTORE DATABASE SAMA1 +FROM DATABASE_SNAPSHOT = 'SAMA1_SNAP_20251014_112623'; +GO + +-- Riporta il DB in multi-user +ALTER DATABASE SAMA1 SET MULTI_USER; +GO + + + +SELECT @@SERVERNAME AS server_name, DB_NAME() AS database_name; + +SELECT name, create_date +FROM sys.databases +WHERE source_database_id IS NOT NULL; + + +SELECT COUNT(*) AS righe FROM dbo.XMag_ViewPackingList; + +SELECT COUNT(*) AS righe FROM dbo.ViewPackingListRestante; + +SELECT Documento, Stato, IDStato, NAZIONE, COUNT(*) AS righe +FROM dbo.ViewPackingListRestante +WHERE Documento IN (240,241) +GROUP BY Documento, Stato, IDStato, NAZIONE; + + + +EXEC sp_refreshview N'dbo.XMag_ViewPackingList'; +EXEC sp_refreshview N'dbo.ViewPackingListRestante'; \ No newline at end of file diff --git a/prenota_sprenota_sql.py b/prenota_sprenota_sql.py new file mode 100644 index 0000000..5629f2b --- /dev/null +++ b/prenota_sprenota_sql.py @@ -0,0 +1,189 @@ +from __future__ import annotations +from dataclasses import dataclass +from typing import Optional, Any, Dict, List + + +@dataclass +class SPResult: + rc: int = 0 # equivalente a @RC OUTPUT + message: Optional[str] = "" # eventuale messaggio/errore + id_result: Optional[int] = None # ID del record inserito in LogPackingList + + +# --- helpers per il client async (senza conoscere l'API esatta forniamo fallback robusti) --- +async def _query_one_value(db, sql: str, params: Dict[str, Any]) -> Optional[Any]: + """ + Ritorna la prima colonna della prima riga, oppure None. + Tenta prima query_json(...), poi altri metodi comuni. + """ + if hasattr(db, "query_json"): + res = await db.query_json(sql, params) + # res può essere una lista di dict o un payload con rows/columns + if isinstance(res, list) and res: + row0 = res[0] + if isinstance(row0, dict): + # prima colonna disponibile + return next(iter(row0.values()), None) + elif isinstance(res, dict): + rows = None + for k in ("rows", "data", "result", "records"): + if k in res and isinstance(res[k], list): + rows = res[k] + break + if rows: + r0 = rows[0] + if isinstance(r0, dict): + return next(iter(r0.values()), None) + if isinstance(r0, (list, tuple)) and r0: + return r0[0] + return None + + # fallback: altri metodi (se esistono) + if hasattr(db, "query_value"): + return await db.query_value(sql, params) + if hasattr(db, "scalar"): + return await db.scalar(sql, params) + raise RuntimeError("Il client DB non espone query_json/query_value/scalar") + + +async def _query_all(db, sql: str, params: Dict[str, Any]) -> List[Dict[str, Any]]: + """Ritorna una lista di dict {col:val}.""" + if hasattr(db, "query_json"): + res = await db.query_json(sql, params) + if res is None: + return [] + if isinstance(res, list): + return res if res and isinstance(res[0], dict) else [] + if isinstance(res, dict): + for k in ("rows", "data", "result", "records"): + if k in res and isinstance(res[k], list): + rows = res[k] + if rows and isinstance(rows[0], dict): + return rows + cols = res.get("columns") or res.get("cols") or [] + out = [] + for r in rows: + if isinstance(r, (list, tuple)) and cols: + out.append({ (cols[i] if i < len(cols) else f"c{i}") : r[i] + for i in range(min(len(cols), len(r))) }) + return out + return [] + # fallback + if hasattr(db, "fetch_all"): + return await db.fetch_all(sql, params) + raise RuntimeError("Il client DB non espone query_json/fetch_all") + + +async def _execute(db, sql: str, params: Dict[str, Any]) -> int: + """ + Esegue DML e ritorna rowcount (se disponibile). + Prova .execute / .exec / .execute_non_query / altrimenti usa query_json. + """ + for name in ("execute", "exec", "execute_non_query"): + if hasattr(db, name): + rc = await getattr(db, name)(sql, params) + # alcuni client ritornano None, altri rowcount, altri payload + if isinstance(rc, int): + return rc + return 0 + # fallback rozzo: molti back-end accettano anche DML in query_json + if hasattr(db, "query_json"): + await db.query_json(sql, params) + return 0 + raise RuntimeError("Il client DB non espone metodi di esecuzione DML noti") + + +# --- Procedura portata in async, usando il client DB passato dall'app --- +async def sp_xExePackingListPallet_async(db, IDOperatore: int, Documento: str) -> SPResult: + """ + Porting asincrono di [dbo].[sp_xExePackingListPallet] usando il client DB già aperto dall'app. + Logica: + 1) Recupera LOGIN operatore + 2) Elenca le celle (DISTINCT Cella da XMag_ViewPackingList per Documento) + 3) Per ogni cella: leggi IDStato e toggla 0<->1 + aggiorna ModUtente/ModDataOra + 4) Description = TOP 1 NAZIONE per Documento + 5) Inserisci LogPackingList(Code=Documento, Description, IDInsUser=IDOperatore, InsDateTime=GETDATE()) + """ + try: + # 1) LOGIN operatore (se manca, prosegue come da SP originaria) + nominativo = await _query_one_value( + db, + "SELECT LOGIN FROM Operatori WHERE id = :IDOperatore", + {"IDOperatore": IDOperatore} + ) or "" + + # 2) Celle da trattare + celle = await _query_all( + db, + """ + SELECT DISTINCT Cella + FROM dbo.XMag_ViewPackingList + WHERE Documento = :Documento + """, + {"Documento": Documento} + ) + id_celle = [r.get("Cella") for r in celle if "Cella" in r] + + # 3) Toggle stato per ogni cella + for id_cella in id_celle: + if id_cella is None: + continue + stato = await _query_one_value( + db, + "SELECT IDStato FROM Celle WHERE ID = :IDC", + {"IDC": id_cella} + ) + if stato == 0: + await _execute( + db, + """ + UPDATE Celle + SET IDStato = 1, + ModUtente = :N, + ModDataOra = GETDATE() + WHERE ID = :IDC + """, + {"N": nominativo, "IDC": id_cella} + ) + else: + await _execute( + db, + """ + UPDATE Celle + SET IDStato = 0, + ModUtente = :N, + ModDataOra = GETDATE() + WHERE ID = :IDC + """, + {"N": nominativo, "IDC": id_cella} + ) + + # 4) Description = NAZIONE (TOP 1) + description = await _query_one_value( + db, + """ + SELECT TOP 1 NAZIONE + FROM dbo.XMag_ViewPackingList + WHERE Documento = :Documento + GROUP BY Documento, NAZIONE + ORDER BY NAZIONE + """, + {"Documento": Documento} + ) + + # 5) LogPackingList + await _execute( + db, + """ + INSERT INTO dbo.LogPackingList (Code, Description, IDInsUser, InsDateTime) + VALUES (:Code, :Descr, :IDInsUser, GETDATE()); + """, + {"Code": Documento, "Descr": description, "IDInsUser": IDOperatore} + ) + + # Se vuoi proprio l'ID appena inserito: + new_id = await _query_one_value(db, "SELECT SCOPE_IDENTITY() AS ID", {}) + return SPResult(rc=0, message="", id_result=int(new_id) if new_id is not None else None) + + except Exception as e: + return SPResult(rc=-1, message=str(e), id_result=None) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a333a0c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[project] +name = "warehouse" +version = "0.0.1" +requires-python = ">=3.12" +dependencies = [ + "sqlalchemy[asyncio]>=2.0", + "aioodbc>=0.3.3", + # "orjson>=3.9" # opzionale: il tuo codice fa fallback su json puro +] + +[project.optional-dependencies] +dev = ["pytest", "pytest-cov", "mypy", "black", "flake8"] + +[tool.pytest.ini_options] +addopts = "-q --maxfail=1" +pythonpath = ["."] diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..d411d61 --- /dev/null +++ b/readme.txt @@ -0,0 +1,50 @@ +-- dbo.XMag_DettaglioPallet source + +ALTER VIEW [dbo].[XMag_DettaglioPallet] +AS +SELECT dbo.MagazziniPallet.ID, dbo.MagazziniPallet.Tipo, dbo.MagazziniPallet.IDRiferimento, dbo.MagazziniPallet.NumeroPallet, + dbo.MagazziniPallet.IDMagazzino, dbo.MagazziniPallet.IDArea, dbo.MagazziniPallet.IDCella, dbo.MagazziniPallet.DataMagazzino, + dbo.MagazziniPallet.PesoUnitario, dbo.MagazziniPallet.Tara, dbo.MagazziniPallet.Attributo, dbo.Celle.IDStato +FROM dbo.MagazziniPallet INNER JOIN + dbo.Celle ON dbo.MagazziniPallet.IDCella = dbo.Celle.ID +WHERE (dbo.MagazziniPallet.Tipo = 'V') +UNION ALL +SELECT MagazziniPallet_1.ID, MagazziniPallet_1.Tipo, MagazziniPallet_1.IDRiferimento, MagazziniPallet_1.NumeroPallet, MagazziniPallet_1.IDMagazzino, + MagazziniPallet_1.IDArea, MagazziniPallet_1.IDCella, MagazziniPallet_1.DataMagazzino, - (1 * MagazziniPallet_1.PesoUnitario) AS PesoUnitario, + MagazziniPallet_1.Tara, MagazziniPallet_1.Attributo, Celle_1.IDStato +FROM dbo.MagazziniPallet AS MagazziniPallet_1 INNER JOIN + dbo.Celle AS Celle_1 ON MagazziniPallet_1.IDCella = Celle_1.ID +WHERE (MagazziniPallet_1.Tipo = 'P'); + +:commento +Dalla tabella Celle e MagazziniPallet ottengo l'insieme delle celle con tipo V = vuota e p=piena, le celle in questo caso possono essere di qualunque tipo cioè fare riferimento a pallet ancora in deposito oppure già spediti, o piene (1A.15.0e) o spedite (7G.01.01). + + +ALTER VIEW dbo.XMag_GiacenzaPallet +AS +SELECT Attributo AS BarcodePallet, NumeroPallet, IDMagazzino, IDArea, IDCella, SUM(PesoUnitario) AS Peso, Attributo AS CodiceProdotto, IDStato +FROM dbo.XMag_DettaglioPallet +GROUP BY NumeroPallet, IDMagazzino, IDArea, IDCella, Attributo, IDStato +HAVING (SUM(PesoUnitario) > 0); +commento: +Ricomprimo la vista ..dettaglio perchè capita che una udc sia stata allocata più volte sulla stessa cella, la riga in questione appare doppia se non si tiene conto della data in cui è avvenuta la lettura .SI potrebbe pensare di prendere sempre la data più alta , cioè l'ultima a parità di unità di carico. + + +ALTER VIEW [dbo].[XMag_GiacenzaPalletxUbicazioneCella] +AS +SELECT dbo.Celle.ID as IDCella, dbo.vXTracciaProdotti.Pallet, dbo.vXTracciaProdotti.Lotto, dbo.vXTracciaProdotti.Prodotto, dbo.vXTracciaProdotti.Descrizione, UPPER(REPLICATE('0', + 3 - DATALENGTH(dbo.Celle.Corsia)) + dbo.Celle.Corsia + '.' + + REPLICATE('0', 2 - DATALENGTH(dbo.Celle.Colonna)) + + dbo.Celle.Colonna + '.' + REPLICATE('0', 2 - DATALENGTH(dbo.Celle.Fila)) + dbo.Celle.Fila) AS Ubicazione +FROM dbo.XMag_GiacenzaPallet +INNER JOIN + dbo.vXTracciaProdotti ON dbo.XMag_GiacenzaPallet.BarcodePallet = dbo.vXTracciaProdotti.Pallet COLLATE Latin1_General_CI_AS + LEFT OUTER JOIN + dbo.Celle ON dbo.XMag_GiacenzaPallet.IDCella = dbo.Celle.ID; + + :commento +qui commbino una vista proveniente da sam in cui vado a cercare i dati della unità di carico e li combino con la tabella vista giacenzapallet, in pratica definisco dove in quale ubicazione si trova il pallet + +quindi in pratica ho + +tabella vista vista +magazzinipallet ---->xmag_Dettagliopallet--->Xmag_giacenzapallet \ No newline at end of file diff --git a/reset_corsie.py b/reset_corsie.py new file mode 100644 index 0000000..3fe0127 --- /dev/null +++ b/reset_corsie.py @@ -0,0 +1,245 @@ +# reset_corsie.py +import tkinter as tk +from tkinter import ttk, messagebox, simpledialog +import customtkinter as ctk +from datetime import datetime + +from gestione_aree_frame_async import BusyOverlay, AsyncRunner + +# ---------------- SQL ---------------- +SQL_CORSIE = """ + WITH C AS ( + SELECT DISTINCT LTRIM(RTRIM(Corsia)) AS Corsia + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) AND LTRIM(RTRIM(Corsia)) <> '7G' + ) + SELECT Corsia + FROM C + ORDER BY + CASE + WHEN LEFT(Corsia,3)='MAG' AND TRY_CONVERT(int, SUBSTRING(Corsia,4,50)) IS NOT NULL THEN 0 + WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN 1 + ELSE 2 + END, + CASE WHEN LEFT(Corsia,3)='MAG' THEN TRY_CONVERT(int, SUBSTRING(Corsia,4,50)) END, + CASE WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN TRY_CONVERT(int, Corsia) END, + CASE WHEN TRY_CONVERT(int, Corsia) IS NOT NULL THEN SUBSTRING(Corsia, LEN(CAST(TRY_CONVERT(int, Corsia) AS varchar(20)))+1, 50) END, + Corsia; +""" + +SQL_RIEPILOGO = """ +WITH C AS ( + SELECT ID, LTRIM(RTRIM(Corsia)) AS Corsia, + LTRIM(RTRIM(Colonna)) AS Colonna, + LTRIM(RTRIM(Fila)) AS Fila + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) + AND LTRIM(RTRIM(Corsia)) = :corsia +), +S AS ( + SELECT c.ID, COUNT(DISTINCT g.BarcodePallet) AS n + FROM C AS c LEFT JOIN dbo.XMag_GiacenzaPallet AS g ON g.IDCella = c.ID + GROUP BY c.ID +) +SELECT + COUNT(*) AS TotCelle, + SUM(CASE WHEN s.n>0 THEN 1 ELSE 0 END) AS CelleOccupate, + SUM(CASE WHEN s.n>1 THEN 1 ELSE 0 END) AS CelleDoppie, + SUM(COALESCE(s.n,0)) AS TotPallet +FROM C LEFT JOIN S s ON s.ID = C.ID; +""" + +SQL_DETTAGLIO = """ +WITH C AS ( + SELECT ID, LTRIM(RTRIM(Corsia)) AS Corsia, + LTRIM(RTRIM(Colonna)) AS Colonna, + LTRIM(RTRIM(Fila)) AS Fila + FROM dbo.Celle + WHERE ID <> 9999 AND (DelDataOra IS NULL) + AND LTRIM(RTRIM(Corsia)) = :corsia +), +S AS ( + SELECT c.ID, COUNT(DISTINCT g.BarcodePallet) AS n + FROM C AS c LEFT JOIN dbo.XMag_GiacenzaPallet AS g ON g.IDCella = c.ID + GROUP BY c.ID +) +SELECT c.ID AS IDCella, + CONCAT(c.Corsia, '.', c.Colonna, '.', c.Fila) AS Ubicazione, + COALESCE(s.n,0) AS NumUDC +FROM C c LEFT JOIN S s ON s.ID = c.ID +WHERE COALESCE(s.n,0) > 0 +ORDER BY TRY_CONVERT(int,c.Colonna), c.Colonna, TRY_CONVERT(int,c.Fila), c.Fila; +""" + +SQL_COUNT_DELETE = """ +SELECT COUNT(*) AS RowsToDelete +FROM dbo.MagazziniPallet mp +JOIN dbo.Celle c ON c.ID = mp.IDCella +WHERE c.ID <> 9999 AND LTRIM(RTRIM(c.Corsia)) = :corsia; +""" + +SQL_DELETE = """ +DELETE mp +FROM dbo.MagazziniPallet mp +JOIN dbo.Celle c ON c.ID = mp.IDCella +WHERE c.ID <> 9999 AND LTRIM(RTRIM(c.Corsia)) = :corsia; +""" + +class ResetCorsieWindow(ctk.CTkToplevel): + """ + Finestra per: + - selezionare una corsia + - vedere riepilogo occupazione / doppie / pallet + - vedere l'elenco celle occupate + - svuotare (DELETE MagazziniPallet) tutte le celle della corsia selezionata + """ + def __init__(self, parent, db_client): + super().__init__(parent) + self.title("Reset Corsie — svuotamento celle per corsia") + self.geometry("1000x680") + self.minsize(880, 560) + self.resizable(True, True) + + self.db = db_client + self._busy = BusyOverlay(self) + self._async = AsyncRunner(self) + + self._build_ui() + self._load_corsie() + + # ---------- UI ---------- + def _build_ui(self): + top = ctk.CTkFrame(self); top.pack(fill="x", padx=8, pady=8) + ctk.CTkLabel(top, text="Corsia:").pack(side="left") + self.cmb = ctk.CTkComboBox(top, width=140, values=[]) + self.cmb.pack(side="left", padx=(6,10)) + ctk.CTkButton(top, text="Carica", command=self.refresh).pack(side="left") + ctk.CTkButton(top, text="Svuota corsia…", command=self._ask_reset).pack(side="right") + + mid = ctk.CTkFrame(self); mid.pack(fill="both", expand=True, padx=8, pady=(0,8)) + mid.grid_columnconfigure(0, weight=1); mid.grid_rowconfigure(0, weight=1) + + self.tree = ttk.Treeview(mid, columns=("Ubicazione","NumUDC"), show="headings", selectmode="browse") + self.tree.heading("Ubicazione", text="Ubicazione") + self.tree.heading("NumUDC", text="UDC in cella") + self.tree.column("Ubicazione", width=240, anchor="w") + self.tree.column("NumUDC", width=120, anchor="e") + + sy = ttk.Scrollbar(mid, orient="vertical", command=self.tree.yview) + sx = ttk.Scrollbar(mid, orient="horizontal", command=self.tree.xview) + self.tree.configure(yscrollcommand=sy.set, xscrollcommand=sx.set) + self.tree.grid(row=0, column=0, sticky="nsew") + sy.grid(row=0, column=1, sticky="ns") + sx.grid(row=1, column=0, sticky="ew") + + bottom = ctk.CTkFrame(self) + bottom.pack(fill="x", padx=8, pady=(0,8)) + ctk.CTkLabel(bottom, text="Riepilogo", font=("Segoe UI", 12, "bold")).pack(anchor="w", padx=8, pady=(8,0)) + + g = ctk.CTkFrame(bottom) + g.pack(fill="x", padx=8, pady=8) + self.var_tot_celle = tk.StringVar(value="0") + self.var_occ = tk.StringVar(value="0") + self.var_dbl = tk.StringVar(value="0") + self.var_pallet = tk.StringVar(value="0") + + def _kv(parent, label, var, col): + ctk.CTkLabel(parent, text=label, font=("Segoe UI", 9, "bold")).grid(row=0, column=col*2, sticky="w", padx=(0,6)) + ctk.CTkLabel(parent, textvariable=var).grid(row=0, column=col*2+1, sticky="w", padx=(0,18)) + + g.grid_columnconfigure(7, weight=1) + _kv(g, "Tot. celle:", self.var_tot_celle, 0) + _kv(g, "Celle occupate:", self.var_occ, 1) + _kv(g, "Celle doppie:", self.var_dbl, 2) + _kv(g, "Tot. pallet:", self.var_pallet, 3) + + # ---------- Data ---------- + def _load_corsie(self): + def _ok(res): + rows = res.get("rows", []) if isinstance(res, dict) else [] + items = [r[0] for r in rows] + self.cmb.configure(values=items) + if items: + # auto 1A se presente + sel = "1A" if "1A" in items else items[0] + self.cmb.set(sel) + self.refresh() + else: + messagebox.showinfo("Info", "Nessuna corsia trovata.", parent=self) + def _err(ex): + messagebox.showerror("Errore", f"Caricamento corsie fallito:\n{ex}", parent=self) + self._async.run(self.db.query_json(SQL_CORSIE, {}), _ok, _err, busy=self._busy, message="Carico corsie…") + + def refresh(self): + corsia = self.cmb.get().strip() + if not corsia: + return + # riepilogo + def _ok_sum(res): + rows = res.get("rows", []) if isinstance(res, dict) else [] + if rows: + tot, occ, dbl, pallet = rows[0] + self.var_tot_celle.set(str(tot or 0)) + self.var_occ.set(str(occ or 0)) + self.var_dbl.set(str(dbl or 0)) + self.var_pallet.set(str(pallet or 0)) + else: + self.var_tot_celle.set("0"); self.var_occ.set("0"); self.var_dbl.set("0"); self.var_pallet.set("0") + def _err_sum(ex): + messagebox.showerror("Errore", f"Riepilogo fallito:\n{ex}", parent=self) + + self._async.run(self.db.query_json(SQL_RIEPILOGO, {"corsia": corsia}), _ok_sum, _err_sum, busy=self._busy, message=f"Riepilogo {corsia}…") + + # dettaglio + def _ok_det(res): + rows = res.get("rows", []) if isinstance(res, dict) else [] + for i in self.tree.get_children(): self.tree.delete(i) + for idc, ubi, n in rows: + self.tree.insert("", "end", values=(ubi, n)) + def _err_det(ex): + messagebox.showerror("Errore", f"Dettaglio fallito:\n{ex}", parent=self) + + self._async.run(self.db.query_json(SQL_DETTAGLIO, {"corsia": corsia}), _ok_det, _err_det, busy=None, message=None) + + # ---------- Reset ---------- + def _ask_reset(self): + corsia = self.cmb.get().strip() + if not corsia: + return + # Primo: quante righe verrebbero cancellate? + def _ok_count(res): + rows = res.get("rows", []) if isinstance(res, dict) else [] + n = int(rows[0][0]) if rows else 0 + if n <= 0: + messagebox.showinfo("Svuota corsia", f"Nessun pallet da rimuovere per la corsia {corsia}.", parent=self) + return + # doppia conferma + msg = (f"Verranno cancellati {n} record da MagazziniPallet per la corsia {corsia}.", + "Questa operazione è irreversibile.", + "Digitare il nome della corsia per confermare:") + confirm = simpledialog.askstring("Conferma", "\n".join(msg), parent=self) + if confirm is None: + return + if confirm.strip().upper() != corsia.upper(): + messagebox.showwarning("Annullato", "Testo di conferma non corrispondente.", parent=self) + return + self._do_reset(corsia) + def _err_count(ex): + messagebox.showerror("Errore", f"Conteggio righe da cancellare fallito:\n{ex}", parent=self) + + self._async.run(self.db.query_json(SQL_COUNT_DELETE, {"corsia": corsia}), _ok_count, _err_count, busy=self._busy, message="Verifico…") + + def _do_reset(self, corsia: str): + def _ok_del(_): + messagebox.showinfo("Completato", f"Corsia {corsia}: svuotamento completato.", parent=self) + self.refresh() + def _err_del(ex): + messagebox.showerror("Errore", f"Svuotamento fallito:\n{ex}", parent=self) + + self._async.run(self.db.query_json(SQL_DELETE, {"corsia": corsia}), _ok_del, _err_del, busy=self._busy, message=f"Svuoto {corsia}…") + + +def open_reset_corsie_window(parent, db_app): + win = ResetCorsieWindow(parent, db_app) + win.lift(); win.focus_set() + return win diff --git a/riassunto_ricerca_udc_20251005.pdf b/riassunto_ricerca_udc_20251005.pdf new file mode 100644 index 0000000..54a6f2a --- /dev/null +++ b/riassunto_ricerca_udc_20251005.pdf @@ -0,0 +1,68 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/Contents 7 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 6 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +4 0 obj +<< +/PageMode /UseNone /Pages 6 0 R /Type /Catalog +>> +endobj +5 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251005172731+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251005172731+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +6 0 obj +<< +/Count 1 /Kids [ 3 0 R ] /Type /Pages +>> +endobj +7 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1709 +>> +stream +Gat=*@;jjj&H1Hm0iGadU(Bku9dAJL2C.[\TU.Q9Q]mO#@Lm(Sp9&>cjoW[1`N*qiBFUbb:t$ZD@Ec$Rrc:#E>K^+uO]`H_<@f%R>]SYAN9dkSI:dJ(cUE,*SE%^0`$he:F5;`W^eb4D@^V>9!LX9O&Hf@H2%Yf@!>R8'^*;WLukGdAr#Q>u-o`@`@"VE16M1;YuZ(o-:h*+":B/Ybk#e6*##Bcd,69%*OtBbPWf7OqUEkie@Y+BgS`]d.rA7b-0AP&_j;*bmRA=L.#s7qe+MJk^jiTMBcL@L"Ri>^8cc#JW(b\&oP2+nLb[hu0fkQ`48tkRO3EIoNR&K@h*B8ViJ@0Gr4K<43)Ekb?5464etE>.40O/bH4]],f/an%VUh8lchsj8W2]X67"->O_#1`--2`?Z]kl)4Pm;7fUW`MRnbo*+d.RFV474lEba!uPu]6?1o(iK$eRp!Lg?Ck,p;N,]1c)ABNkcc8G":n'(1;aqN]ptL$EM4FLg"DB]oe9TuiHl`DE^R$,08$nE?+HEqVm[1\P-;6bHfD>n1b\Tr0Yg'WM1s8?n'JM8;KiGA\H0lUna6N)B7:k@&]:Yite,/M5d!,b-RLX_NbV^[\U.;:mWF?aP=o%s=ppcCl9E)X?7?5oq_DO?hLgOZGHVN6FWNW[b.&HZ"CaYrR^CM8?#;,`AK2f-^b7/K4n[PK@i'>Q0?.o(2$'Ze=7ko8h9jSPWUHe0>@9.!CYSo[8XE#Y1TX-qnH!XIfSck8%_PGV>)b=3.pqLM^Ubm$:@\%E*mpC).A.o]>sl$KXV]V)!n0m8Q2'@1R@fdm?KEa&pRc7^YEZMMqR!Zq3%&8Y[e&,D$Zoe-G$8LW,u$h1pP;3.dZB6Bh^4n]F$bicJtuA>RX;U3Lhk-7qu1ehU[4iBG7D.W)e'`FR>]a`HY:(/2lN`7fRPUHLgHmjD"ihb'_R_3(bf2OcpSbMY.8godBKC"pn`t5'>J_Sagk`EjYrUPj6Yf1)NJ/WnkE'+]?P`OYUD81gAqBphrVcZT%q/F)GC5d0Fl:Q_WIV/@9N\A+rmqX-An>"Oo1C;X%ng]E;AUL*;rnFt9^FllJqBW&Q'44ZXq<1!>.;%,L^=?Mdp2+\VY1!Woqu34/]bIsdonQ87"Ln:Ou>oUI/Mq^bb\DmJ6,'CW1H$^d>[[CQogFddhjW4K;jdn@#"PA+0>>cl1_#F't5f\4e(kendstream +endobj +xref +0 8 +0000000000 65535 f +0000000073 00000 n +0000000104 00000 n +0000000211 00000 n +0000000414 00000 n +0000000482 00000 n +0000000765 00000 n +0000000824 00000 n +trailer +<< +/ID +[<54fac52a7e33f1aa3f45091c2782a3eb><54fac52a7e33f1aa3f45091c2782a3eb>] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 5 0 R +/Root 4 0 R +/Size 8 +>> +startxref +2624 +%%EOF diff --git a/script.sql b/script.sql new file mode 100644 index 0000000000000000000000000000000000000000..8f17d852743cb492b508a948ab67babe8f85dfd1 GIT binary patch literal 274924 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 TxGZX;1IrvtIsx`nMb9 literal 0 HcmV?d00001 diff --git a/search_pallets.py b/search_pallets.py new file mode 100644 index 0000000..3823218 --- /dev/null +++ b/search_pallets.py @@ -0,0 +1,453 @@ +# search_pallets.py +# Finestra di ricerca su UDC / Lotto / Codice Prodotto +# - Tre campi: UDC, Lotto, Codice Prodotto (AND tra i campi valorizzati) +# - Ricerca su TUTTE le celle, incluse IDCella=9999 e corsia 7G +# - Risultati in una griglia: IDCella, Ubicazione, UDC, Lotto, Codice, Descrizione +# - Se la ricerca restituisce >0 righe, i campi input vengono svuotati + +from __future__ import annotations +import tkinter as tk +from tkinter import ttk, messagebox + +import customtkinter as ctk + +from gestione_aree_frame_async import BusyOverlay, AsyncRunner +from tkinter import filedialog + +# opzionale export xlsx +try: + from openpyxl import Workbook + from openpyxl.styles import Font, Alignment + _HAS_XLSX = True +except Exception: + _HAS_XLSX = False + +# opzionale: usare tksheet per avere griglie con bordi di cella +try: + from tksheet import Sheet +except Exception: + Sheet = None + +SQL_SEARCH = r""" +WITH BASE AS ( + SELECT + g.IDCella, + -- forza stringa per ricerche LIKE + CONCAT(g.BarcodePallet, '') AS UDC, + c.Corsia, + c.Colonna, + c.Fila + FROM dbo.XMag_GiacenzaPallet AS g + LEFT JOIN dbo.Celle AS c ON c.ID = g.IDCella + -- NB: qui NON escludiamo IDCella=9999 né '7G' +), +JOINED AS ( + SELECT + b.IDCella, + b.UDC, + b.Corsia, + b.Colonna, + b.Fila, + t.Lotto, + t.Prodotto, + t.Descrizione + FROM BASE b + LEFT JOIN dbo.vXTracciaProdotti AS t + ON t.Pallet COLLATE Latin1_General_CI_AS = LEFT(b.UDC, 6) COLLATE Latin1_General_CI_AS +) +SELECT + j.IDCella, + UPPER( + CONCAT( + COALESCE(LTRIM(RTRIM(j.Corsia)), 'NA'), '.', + COALESCE(LTRIM(RTRIM(CAST(j.Colonna AS varchar(32)))), 'NA'), '.', + COALESCE(LTRIM(RTRIM(CAST(j.Fila AS varchar(32)))), 'NA') + ) + ) AS Ubicazione, + j.UDC, + j.Lotto, + j.Prodotto, + j.Descrizione +FROM JOINED j +WHERE 1=1 + AND ( :udc IS NULL OR j.UDC COLLATE Latin1_General_CI_AS LIKE CONCAT('%', :udc, '%') ) + AND ( :lotto IS NULL OR j.Lotto COLLATE Latin1_General_CI_AS LIKE CONCAT('%', :lotto, '%') ) + AND ( :codice IS NULL OR j.Prodotto COLLATE Latin1_General_CI_AS LIKE CONCAT('%', :codice, '%') ) +ORDER BY + CASE WHEN j.IDCella = 9999 THEN 1 ELSE 0 END, + j.Corsia, j.Colonna, j.Fila, j.UDC, j.Lotto, j.Prodotto; +""" + +class SearchWindow(ctk.CTkToplevel): + def __init__(self, parent: tk.Widget, db_app): + super().__init__(parent) + self.title("Warehouse · Ricerca UDC/Lotto/Codice") + self.geometry("1100x720") + self.minsize(900, 560) + self.resizable(True, True) + + self.db = db_app + self._busy = BusyOverlay(self) + self._async = AsyncRunner(self) + + # stato ordinamento colonne (col -> reverse bool) + self._sort_state: dict[str, bool] = {} + + self._build_ui() + + def _build_ui(self): + # layout griglia principale + self.grid_rowconfigure(0, weight=0) + self.grid_rowconfigure(1, weight=1) + self.grid_columnconfigure(0, weight=1) + + # --- barra di ricerca --- + top = ctk.CTkFrame(self) + top.grid(row=0, column=0, sticky="nsew", padx=8, pady=8) + for i in range(8): + top.grid_columnconfigure(i, weight=0) + top.grid_columnconfigure(7, weight=1) + + ctk.CTkLabel(top, text="UDC:").grid(row=0, column=0, sticky="w") + self.var_udc = tk.StringVar() + e_udc = ctk.CTkEntry(top, textvariable=self.var_udc, width=160) + e_udc.grid(row=0, column=1, sticky="w", padx=(4, 12)) + + ctk.CTkLabel(top, text="Lotto:").grid(row=0, column=2, sticky="w") + self.var_lotto = tk.StringVar() + e_lotto = ctk.CTkEntry(top, textvariable=self.var_lotto, width=140) + e_lotto.grid(row=0, column=3, sticky="w", padx=(4, 12)) + + ctk.CTkLabel(top, text="Codice prodotto:").grid(row=0, column=4, sticky="w") + self.var_codice = tk.StringVar() + e_cod = ctk.CTkEntry(top, textvariable=self.var_codice, width=160) + e_cod.grid(row=0, column=5, sticky="w", padx=(4, 12)) + + btn = ctk.CTkButton(top, text="Cerca", command=self._do_search) + btn.grid(row=0, column=6, sticky="w") + + btn_exp = ctk.CTkButton(top, text="Esporta XLSX", command=self._export_xlsx) + btn_exp.grid(row=0, column=7, sticky="e") + + # --- griglia risultati --- + wrap = ctk.CTkFrame(self) + wrap.grid(row=1, column=0, sticky="nsew", padx=8, pady=(0, 8)) + wrap.grid_rowconfigure(0, weight=1) + wrap.grid_columnconfigure(0, weight=1) + + # forza modalità Treeview (niente tksheet) per stabilità + self.use_sheet = False + + cols = ("IDCella", "Ubicazione", "UDC", "Lotto", "Codice", "Descrizione") + self.tree = ttk.Treeview(wrap, columns=cols, show="headings") + # stile: zebra + header leggibile + self._style = ttk.Style(self) + try: + self._style.theme_use(self._style.theme_use()) + except Exception: + pass + self._style.configure("Search.Treeview", rowheight=22, font=("", 9)) + self._style.configure("Search.Treeview.Heading", font=("", 9, "bold"), background="#F3F4F6") + self._style.map("Search.Treeview", background=[("selected", "#DCEBFF")]) + self.tree.configure(style="Search.Treeview") + # tag per righe alternate + id9999 evidenziate + self.tree.tag_configure("even", background="#FFFFFF") + self.tree.tag_configure("odd", background="#F7F9FC") + # evidenzia spediti (IDCella=9999) in rosato tenue + self.tree.tag_configure("id9999", background="#FFECEC", foreground="#B00020") + + sy = ttk.Scrollbar(wrap, orient="vertical", command=self.tree.yview) + sx = ttk.Scrollbar(wrap, orient="horizontal", command=self.tree.xview) + self.tree.configure(yscrollcommand=sy.set, xscrollcommand=sx.set) + + self.tree.grid(row=0, column=0, sticky="nsew") + sy.grid(row=0, column=1, sticky="ns") + sx.grid(row=1, column=0, sticky="ew") + + # doppio click → copia UDC; gestione click header + self.tree.bind("", self._on_dclick) + self.tree.bind("", self._maybe_handle_heading_click, add=True) + self.tree.bind("", self._on_heading_double_click, add=True) + + def _apply_zebra(self): + for i, iid in enumerate(self.tree.get_children("")): + vals = self.tree.item(iid, "values") + zebra = "even" if i % 2 == 0 else "odd" + is9999 = False + if vals: + try: + is9999 = int(vals[0]) == 9999 + except Exception: + is9999 = False + tags = ("id9999", zebra) if is9999 else (zebra,) + self.tree.item(iid, tags=tags) + + # ---------------- AZIONI ---------------- + def _export_xlsx(self): + # raccogli dati dalla griglia + rows = [] + for iid in self.tree.get_children(""): + rows.append(self.tree.item(iid, "values")) + if not rows: + messagebox.showinfo("Esporta", "Non ci sono righe da esportare.", parent=self) + return + if not _HAS_XLSX: + messagebox.showerror("Esporta", "Per l'esportazione serve 'openpyxl' (pip install openpyxl).", parent=self) + return + # dialog salvataggio + from datetime import datetime + ts = datetime.now().strftime("%d_%m_%Y_%H-%M") + default_name = f"esportazione_ricerca_{ts}.xlsx" + fname = filedialog.asksaveasfilename(parent=self, title="Esporta in Excel", + defaultextension=".xlsx", + filetypes=[("Excel Workbook","*.xlsx")], + initialfile=default_name) + if not fname: + return + # crea workbook e scrivi + try: + wb = Workbook() + ws = wb.active + ws.title = "Risultati" + headers = ("IDCella","Ubicazione","UDC","Lotto","Codice","Descrizione") + for j, h in enumerate(headers, start=1): + c = ws.cell(row=1, column=j, value=h) + c.font = Font(bold=True) + c.alignment = Alignment(horizontal="center", vertical="center") + r = 2 + for row in rows: + for j, v in enumerate(row, start=1): + ws.cell(row=r, column=j, value=v) + r += 1 + # autosize + widths = {} + for row in ws.iter_rows(values_only=True): + for j, val in enumerate(row, start=1): + s = "" if val is None else str(val) + widths[j] = max(widths.get(j, 0), len(s)) + from openpyxl.utils import get_column_letter + for j, w in widths.items(): + ws.column_dimensions[get_column_letter(j)].width = min(max(w + 2, 10), 60) + wb.save(fname) + messagebox.showinfo("Esporta", f"File creato:\n{fname}", parent=self) + + except Exception as ex: + messagebox.showerror("Esporta", f"Errore durante l'esportazione:{ex}", parent=self) + def _on_dclick(self, evt): + # copia UDC solo se il doppio click avviene su una cella, non sull'header + region = self.tree.identify("region", evt.x, evt.y) + if region != "cell": + return + sel = self.tree.focus() + if not sel: + return + vals = self.tree.item(sel, "values") + if len(vals) >= 3 and vals[2]: # UDC + try: + self.clipboard_clear() + self.clipboard_append(vals[2]) + except Exception: + pass + + # --------------- ORDINAMENTO COLONNE --------------- + def _maybe_handle_heading_click(self, evt): + # evita che il click sulle intestazioni selezioni una riga fantasma + region = self.tree.identify("region", evt.x, evt.y) + if region == "heading": + return "break" + + def _on_heading_double_click(self, evt): + # doppio click su intestazione: ordina la colonna corrispondente + region = self.tree.identify("region", evt.x, evt.y) + if region != "heading": + return + col_id = self.tree.identify_column(evt.x) # es. '#1' + try: + idx = int(col_id.replace('#','')) - 1 + except Exception: + return "break" + cols = ("IDCella", "Ubicazione", "UDC", "Lotto", "Codice", "Descrizione") + if 0 <= idx < len(cols): + self._sort_by_column(cols[idx]) + return "break" + + def _sort_key_for_col(self, col: str, val: str): + if val is None: + return (1, "") # None in fondo + s = str(val) + if col in ("IDCella",): + # prova numero + try: + return (0, int(s)) + except Exception: + return (0, s.lower()) + if col in ("Lotto", "Codice", "UDC"): + return (0, s.lower()) + return (0, s.lower()) + + def _sort_by_column(self, col: str): + try: + # toggle reverse + rev = self._sort_state.get(col, False) + self._sort_state[col] = not rev + + # raccogli dati correnti + rows = [] + for iid in self.tree.get_children(""): + vals = self.tree.item(iid, "values") + row = {"iid": iid, + "IDCella": vals[0] if len(vals) > 0 else None, + "Ubicazione": vals[1] if len(vals) > 1 else None, + "UDC": vals[2] if len(vals) > 2 else None, + "Lotto": vals[3] if len(vals) > 3 else None, + "Codice": vals[4] if len(vals) > 4 else None, + "Descrizione": vals[5] if len(vals) > 5 else None} + rows.append(row) + + rows.sort(key=lambda r: self._sort_key_for_col(col, r.get(col)), reverse=rev) + + def _apply_moves(): + for index, r in enumerate(rows): + self.tree.move(r["iid"], "", index) + # aggiorna indicatori visuali nelle heading (â–²/â–¼) + for k in ("IDCella","Ubicazione","UDC","Lotto","Codice","Descrizione"): + base = { + "IDCella": "IDCella", + "Ubicazione": "Ubicazione", + "UDC": "UDC / Barcode", + "Lotto": "Lotto", + "Codice": "Codice prodotto", + "Descrizione": "Descrizione prodotto", + }[k] + if k == col: + arrow = " â–¼" if not rev else " â–²" + self.tree.heading(k, text=base + arrow) + else: + self.tree.heading(k, text=base) + self._apply_zebra() + + # posticipa le move per evitare re‑entrancy su doppio click + self.after_idle(_apply_moves) + except Exception: + # in caso di problemi non lasciamo la finestra in stato incoerente + pass + + # --- ordinamento per tksheet (doppio click sui titoli) --- + def _on_sheet_header_double_click(self, event_dict): + try: + c = event_dict.get("column") + except Exception: + return + if c is None: + return + headers = ["IDCella","Ubicazione","UDC","Lotto","Codice","Descrizione"] + if not (0 <= c < len(headers)): + return + colname = headers[c] + rev = self._sort_state.get(colname, False) + self._sort_state[colname] = not rev + + data = self.sheet.get_sheet_data(return_copy=True) + def keyf(row): + val = row[c] if c < len(row) else None + if val is None: + return (1, "") + s = str(val) + if colname == "IDCella": + try: + return (0, int(s)) + except Exception: + return (0, s.lower()) + return (0, s.lower()) + data.sort(key=keyf, reverse=rev) + self.sheet.set_sheet_data(data) + # evidenzia l'header ordinato (semplice: cambia testo temporaneamente) + try: + arrow = " â–¼" if not rev else " â–²" + hdrs = list(headers) + hdrs[c] = hdrs[c] + arrow + self.sheet.headers(hdrs) + except Exception: + pass + + def _do_search(self): + udc = (self.var_udc.get() or "").strip() + lotto = (self.var_lotto.get() or "").strip() + codice = (self.var_codice.get() or "").strip() + + # Se nessun filtro, chiedi conferma (evita estrazione enorme non voluta) + if not (udc or lotto or codice): + if not messagebox.askyesno( + "Conferma", + "Nessun filtro impostato. Vuoi cercare su TUTTO il magazzino?", + parent=self, + ): + return + + # Parametri: passa NULL se campo vuoto -> i filtri "si spengono" + params = { + "udc": (udc if udc else None), + "lotto": (lotto if lotto else None), + "codice": (codice if codice else None), + } + + def _ok(res): + rows = res.get("rows", []) if isinstance(res, dict) else [] + # --- popola UI --- + if self.use_sheet: + try: + data = [] + for r in rows: + idc, ubi, udc_v, lot_v, cod_v, desc_v = r + data.append([idc, ubi, udc_v, lot_v, cod_v, desc_v]) + self.sheet.set_sheet_data(data) + self.sheet.set_all_cell_sizes_to_text() + except Exception as ex: + # fallback di sicurezza su Treeview + self.use_sheet = False + if not self.use_sheet: + # Treeview + for iid in self.tree.get_children(): + self.tree.delete(iid) + for idx, r in enumerate(rows): + idc, ubi, udc_v, lot_v, cod_v, desc_v = r + zebra = "even" if idx % 2 == 0 else "odd" + try: + is9999 = int(idc) == 9999 + except Exception: + is9999 = False + tags = ("id9999", zebra) if is9999 else (zebra,) + self.tree.insert("", "end", values=(idc, ubi, udc_v, lot_v, cod_v, desc_v), tags=tags) + + # --- feedback utente --- + if not rows: + messagebox.showinfo( + "Nessun risultato", + "Nessuna corrispondenza trovata con le chiavi di ricerca inserite.", + parent=self, + ) + else: + # reset campi se risultato non vuoto + self.var_udc.set("") + self.var_lotto.set("") + self.var_codice.set("") + self._busy.hide() + + def _err(ex): + self._busy.hide() + messagebox.showerror("Errore ricerca", str(ex), parent=self) + + self._async.run(self.db.query_json(SQL_SEARCH, params), _ok, _err, busy=self._busy, message="Cerco…") + + +def open_search_window(parent, db_app): + key = "_search_window_singleton" + ex = getattr(parent, key, None) + if ex and ex.winfo_exists(): + try: + ex.lift(); ex.focus_force(); return ex + except Exception: + pass + w = SearchWindow(parent, db_app) + setattr(parent, key, w) + return w diff --git a/sql.txt b/sql.txt new file mode 100644 index 0000000..4930170 --- /dev/null +++ b/sql.txt @@ -0,0 +1,21 @@ +SELECT * FROM vViewMappaturaDescrizioneCorsia WHERE ( Area > 0) ORDER BY Area Desc + +SELECT * FROM Celle WHERE ( ID > 0) ORDER BY ID Desc + +SELECT TOP 1000 [mc_X] ,[minFila] ,[maxFila] ,[minColonna] ,[maxColonna] ,[mc_Numero_Magazzino] ,[mc_Numero_Area] FROM vViewMappaturaPosizCorsia WHERE [mc_Numero_Area] =1 + + +SELECT CASE WHEN Nota = 'ASC' THEN 0 ELSE CASE WHEN Nota = 'DESC' THEN 1 END END AS Nota FROM MagLayout WHERE (IDArea = 1) + +SELECT ID, Descrizione FROM Magazzini ORDER BY Descrizione + +SELECT ID, Descrizione FROM Celle ORDER BY Descrizione + +SELECT [ID],[CorsiaDescrizione] FROM vViewMappaturaDescrizioneCorsia + + + SELECT COUNT(DISTINCT Pallet) AS Pallet, COUNT(DISTINCT Lotto) AS Lotto, COUNT(DISTINCT Articolo) AS Articolo, COUNT(DISTINCT Descrizione) AS Descrizione, SUM(Qta) AS Qta, Documento, CodNazione, NAZIONE, Stato, MAX(PalletCella) AS PalletCella, MAX(Magazzino) AS Magazzino, MAX(Area) AS Area, MAX(Cella) AS Cella, MIN(Ordinamento) AS Ordinamento, MAX(IDStato) AS IDStato FROM dbo.XMag_ViewPackingList GROUP BY Documento, CodNazione, NAZIONE, Stato + + SELECT * FROM vViewPackingListRestante WHERE Documento = 237 ORDER BY Ordinamento + SELECT * FROM vViewPackingListRestante WHERE Documento = 240 ORDER BY Ordinamento + \ No newline at end of file diff --git a/view_celle_multiple.py b/view_celle_multiple.py new file mode 100644 index 0000000..eff88eb --- /dev/null +++ b/view_celle_multiple.py @@ -0,0 +1,346 @@ +# view_celle_multiple.py +import json +import tkinter as tk +from tkinter import ttk, messagebox, filedialog +import customtkinter as ctk +from datetime import datetime + +from openpyxl import Workbook +from openpyxl.styles import Font, Alignment + +from gestione_aree_frame_async import AsyncRunner + +def _json_obj(res): + if isinstance(res, str): + try: + res = json.loads(res) + except Exception as ex: + raise RuntimeError(f"Risposta non JSON: {ex}\nRaw: {res!r}") + if isinstance(res, dict) and "error" in res: + err = res.get("error") or "Errore sconosciuto" + detail = res.get("sql") or "" + raise RuntimeError(f"{err}\n{detail}") + return res if isinstance(res, dict) else {"rows": res} + +UBI_B = ( + "UPPER(" + " CONCAT(" + " RTRIM(b.Corsia), '.', RTRIM(CAST(b.Colonna AS varchar(32))), '.', RTRIM(CAST(b.Fila AS varchar(32)))" + " )" + ")" +) + +BASE_CTE = """ +WITH base AS ( + SELECT + g.IDCella, + g.BarcodePallet, + RTRIM(c.Corsia) AS Corsia, + c.Colonna, + c.Fila + FROM dbo.XMag_GiacenzaPallet AS g + JOIN dbo.Celle AS c ON c.ID = g.IDCella + WHERE g.IDCella <> 9999 AND RTRIM(c.Corsia) <> '7G' +) +""" + +SQL_CORSIE = BASE_CTE + """ +, dup_celle AS ( + SELECT IDCCella = b.IDCella + FROM base b + GROUP BY b.IDCella + HAVING COUNT(DISTINCT b.BarcodePallet) > 1 +) +SELECT DISTINCT b.Corsia +FROM base b +WHERE EXISTS (SELECT 1 FROM dup_celle d WHERE d.IDCCella = b.IDCella) +ORDER BY b.Corsia; +""" + +SQL_CELLE_DUP_PER_CORSIA = BASE_CTE + f""" +, dup_celle AS ( + SELECT b.IDCella, COUNT(DISTINCT b.BarcodePallet) AS NumUDC + FROM base b + GROUP BY b.IDCella + HAVING COUNT(DISTINCT b.BarcodePallet) > 1 +) +SELECT dc.IDCella, + {UBI_B} AS Ubicazione, + b.Colonna, b.Fila, b.Corsia, + dc.NumUDC +FROM dup_celle dc +JOIN base b ON b.IDCella = dc.IDCella +WHERE b.Corsia = RTRIM(:corsia) +GROUP BY dc.IDCella, {UBI_B}, b.Colonna, b.Fila, b.Corsia, dc.NumUDC +ORDER BY b.Colonna, b.Fila; +""" + +SQL_PALLET_IN_CELLA = BASE_CTE + """ +SELECT + b.BarcodePallet AS Pallet, + ta.Descrizione, + ta.Lotto +FROM base b +OUTER APPLY ( + SELECT TOP (1) t.Descrizione, t.Lotto + FROM dbo.vXTracciaProdotti AS t + WHERE t.Pallet = b.BarcodePallet COLLATE Latin1_General_CI_AS + ORDER BY t.Lotto +) AS ta +WHERE b.IDCella = :idcella +GROUP BY b.BarcodePallet, ta.Descrizione, ta.Lotto +ORDER BY b.BarcodePallet; +""" + +SQL_RIEPILOGO_PERCENTUALI = BASE_CTE + """ +, tot AS ( + SELECT b.Corsia, COUNT(DISTINCT b.IDCella) AS TotCelle + FROM base b GROUP BY b.Corsia +), +dup_celle AS ( + SELECT b.Corsia, b.IDCella + FROM base b + GROUP BY b.Corsia, b.IDCella + HAVING COUNT(DISTINCT b.BarcodePallet) > 1 +), +per_corsia AS ( + SELECT t.Corsia, t.TotCelle, COALESCE(d.CelleMultiple, 0) AS CelleMultiple + FROM tot t + LEFT JOIN ( + SELECT Corsia, COUNT(IDCella) AS CelleMultiple + FROM dup_celle GROUP BY Corsia + ) d ON d.Corsia = t.Corsia +), +unione AS ( + SELECT Corsia, TotCelle, CelleMultiple, + CAST(100.0 * CelleMultiple / NULLIF(TotCelle, 0) AS decimal(5,2)) AS Percentuale, + CAST(0 AS int) AS Ord + FROM per_corsia + UNION ALL + SELECT 'TOTALE' AS Corsia, + SUM(TotCelle), SUM(CelleMultiple), + CAST(100.0 * SUM(CelleMultiple) / NULLIF(SUM(TotCelle), 0) AS decimal(5,2)), + CAST(1 AS int) AS Ord + FROM per_corsia +) +SELECT Corsia, TotCelle, CelleMultiple, Percentuale +FROM unione +ORDER BY Ord, Corsia; +""" + +class CelleMultipleWindow(ctk.CTkToplevel): + def __init__(self, root, db_client, runner: AsyncRunner | None = None): + super().__init__(root) + self.title("Celle con più pallet") + self.geometry("1100x700"); self.minsize(900,550); self.resizable(True, True) + + self.db = db_client + self.runner = runner or AsyncRunner(self) + + self._build_layout() + self._bind_events() + self.refresh_all() + + def _build_layout(self): + self.grid_rowconfigure(0, weight=5) + self.grid_rowconfigure(1, weight=70) + self.grid_rowconfigure(2, weight=25, minsize=160) + self.grid_columnconfigure(0, weight=1) + + toolbar = ctk.CTkFrame(self); toolbar.grid(row=0, column=0, sticky="nsew") + ctk.CTkButton(toolbar, text="Aggiorna", command=self.refresh_all).pack(side="left", padx=6, pady=4) + ctk.CTkButton(toolbar, text="Espandi tutto", command=self.expand_all).pack(side="left", padx=6, pady=4) + ctk.CTkButton(toolbar, text="Comprimi tutto", command=self.collapse_all).pack(side="left", padx=6, pady=4) + ctk.CTkButton(toolbar, text="Esporta in XLSX", command=self.export_to_xlsx).pack(side="left", padx=6, pady=4) + + f = ctk.CTkFrame(self); f.grid(row=1, column=0, sticky="nsew", padx=6, pady=(0,6)) + f.grid_rowconfigure(0, weight=1); f.grid_columnconfigure(0, weight=1) + self.tree = ttk.Treeview(f, columns=("col2","col3"), show="tree headings", selectmode="browse") + self.tree.heading("#0", text="Nodo"); self.tree.heading("col2", text="Descrizione"); self.tree.heading("col3", text="Lotto") + y = ttk.Scrollbar(f, orient="vertical", command=self.tree.yview) + x = ttk.Scrollbar(f, orient="horizontal", command=self.tree.xview) + self.tree.configure(yscrollcommand=y.set, xscrollcommand=x.set) + self.tree.grid(row=0, column=0, sticky="nsew"); y.grid(row=0, column=1, sticky="ns"); x.grid(row=1, column=0, sticky="ew") + + sumf = ctk.CTkFrame(self) + sumf.grid(row=2, column=0, sticky="nsew", padx=6, pady=(0,6)) + ctk.CTkLabel(sumf, text="Riepilogo % celle multiple per corsia", font=("Segoe UI", 12, "bold")).pack(anchor="w", padx=8, pady=(8, 0)) + inner = ctk.CTkFrame(sumf) + inner.pack(fill="both", expand=True, padx=6, pady=6) + inner.grid_rowconfigure(0, weight=1); inner.grid_columnconfigure(0, weight=1) + self.sum_tbl = ttk.Treeview(inner, columns=("Corsia","TotCelle","CelleMultiple","Percentuale"), show="headings") + for k,t,w,a in (("Corsia","Corsia",100,"center"), + ("TotCelle","Totale celle",120,"e"), + ("CelleMultiple",">1 UDC",120,"e"), + ("Percentuale","%",80,"e")): + self.sum_tbl.heading(k, text=t); self.sum_tbl.column(k, width=w, anchor=a) + y2 = ttk.Scrollbar(inner, orient="vertical", command=self.sum_tbl.yview) + x2 = ttk.Scrollbar(inner, orient="horizontal", command=self.sum_tbl.xview) + self.sum_tbl.configure(yscrollcommand=y2.set, xscrollcommand=x2.set) + self.sum_tbl.grid(row=0, column=0, sticky="nsew"); y2.grid(row=0, column=1, sticky="ns"); x2.grid(row=1, column=0, sticky="ew") + + def _bind_events(self): + self.tree.bind("<>", self._on_open_node) + + def refresh_all(self): + self._load_corsie(); self._load_riepilogo() + + def _load_corsie(self): + self.tree.delete(*self.tree.get_children()) + async def _q(db): return await db.query_json(SQL_CORSIE, as_dict_rows=True) + self.runner.run(_q(self.db), self._fill_corsie, lambda e: messagebox.showerror("Errore", str(e), parent=self)) + + def _fill_corsie(self, res): + rows = _json_obj(res).get("rows", []) + for r in rows: + corsia = r.get("Corsia"); + if not corsia: continue + node_id = f"corsia:{corsia}" + self.tree.insert("", "end", iid=node_id, text=f"Corsia {corsia}", values=("", ""), open=False, tags=("corsia",)) + self.tree.insert(node_id, "end", iid=f"{node_id}::lazy", text="...", values=("", "")) + + def _on_open_node(self, _evt): + sel = self.tree.focus() + if not sel: return + if sel.startswith("corsia:"): + lazy_id = f"{sel}::lazy" + if lazy_id in self.tree.get_children(sel): + self.tree.delete(lazy_id) + corsia = sel.split(":",1)[1] + self._load_celle_for_corsia(sel, corsia) + elif sel.startswith("cella:"): + lazy_id = f"{sel}::lazy" + if lazy_id in self.tree.get_children(sel): + self.tree.delete(lazy_id) + idcella = int(sel.split(":",1)[1]) + for child in self.tree.get_children(sel): + self.tree.delete(child) + self._load_pallet_for_cella(sel, idcella) + + def _load_celle_for_corsia(self, parent_iid, corsia): + async def _q(db): return await db.query_json(SQL_CELLE_DUP_PER_CORSIA, params={"corsia": corsia}, as_dict_rows=True) + self.runner.run(_q(self.db), lambda res: self._fill_celle(parent_iid, res), + lambda e: messagebox.showerror("Errore", str(e), parent=self)) + + def _fill_celle(self, parent_iid, res): + rows = _json_obj(res).get("rows", []) + if not rows: + self.tree.insert(parent_iid, "end", text="(nessuna cella con >1 UDC)", values=("", "")); return + for r in rows: + idc = r["IDCella"]; ubi = r["Ubicazione"]; corsia = r.get("Corsia"); num = r.get("NumUDC", 0) + node_id = f"cella:{idc}"; label = f"{ubi} [x{num}]" + if self.tree.exists(node_id): + self.tree.item(node_id, text=label, values=(f"IDCella {idc}", "")) + else: + self.tree.insert(parent_iid, "end", iid=node_id, text=label, + values=(f"IDCella {idc}", ""), open=False, tags=("cella", f"corsia:{corsia}")) + if not any(ch.endswith("::lazy") for ch in self.tree.get_children(node_id)): + self.tree.insert(node_id, "end", iid=f"{node_id}::lazy", text="...", values=("", "")) + + def _load_pallet_for_cella(self, parent_iid, idcella: int): + async def _q(db): return await db.query_json(SQL_PALLET_IN_CELLA, params={"idcella": idcella}, as_dict_rows=True) + self.runner.run(_q(self.db), lambda res: self._fill_pallet(parent_iid, res), + lambda e: messagebox.showerror("Errore", str(e), parent=self)) + + def _fill_pallet(self, parent_iid, res): + rows = _json_obj(res).get("rows", []) + if not rows: + self.tree.insert(parent_iid, "end", text="(nessun pallet)", values=("", "")); return + parent_tags = self.tree.item(parent_iid, "tags") or () + corsia_tag = next((t for t in parent_tags if t.startswith("corsia:")), None) + corsia_val = corsia_tag.split(":",1)[1] if corsia_tag else "" + cella_ubi = self.tree.item(parent_iid, "text") + idcella_txt = self.tree.item(parent_iid, "values")[0] + idcella_num = int(idcella_txt.split()[-1]) if idcella_txt else None + + for r in rows: + pallet = r.get("Pallet", ""); desc = r.get("Descrizione", ""); lotto = r.get("Lotto", "") + leaf_id = f"pallet:{idcella_num}:{pallet}" + if self.tree.exists(leaf_id): + self.tree.item(leaf_id, text=str(pallet), values=(desc, lotto)); continue + self.tree.insert(parent_iid, "end", iid=leaf_id, text=str(pallet), + values=(desc, lotto), + tags=("pallet", f"corsia:{corsia_val}", f"ubicazione:{cella_ubi}", f"idcella:{idcella_num}")) + + def _load_riepilogo(self): + async def _q(db): return await db.query_json(SQL_RIEPILOGO_PERCENTUALI, as_dict_rows=True) + self.runner.run(_q(self.db), self._fill_riepilogo, lambda e: messagebox.showerror("Errore", str(e), parent=self)) + + def _fill_riepilogo(self, res): + rows = _json_obj(res).get("rows", []) + for i in self.sum_tbl.get_children(): self.sum_tbl.delete(i) + for r in rows: + self.sum_tbl.insert("", "end", values=(r.get("Corsia"), r.get("TotCelle",0), + r.get("CelleMultiple",0), f"{r.get('Percentuale',0):.2f}")) + + def expand_all(self): + for iid in self.tree.get_children(""): + self.tree.item(iid, open=True) + if f"{iid}::lazy" in self.tree.get_children(iid): + self.tree.delete(f"{iid}::lazy") + corsia = iid.split(":",1)[1] + self._load_celle_for_corsia(iid, corsia) + + def collapse_all(self): + for iid in self.tree.get_children(""): + self.tree.item(iid, open=False) + + def export_to_xlsx(self): + ts = datetime.now().strftime("%d_%m_%Y_%H-%M") + default_name = f"esportazione_celle_udc_multiple_{ts}.xlsx" + fname = filedialog.asksaveasfilename(parent=self, title="Esporta in Excel", + defaultextension=".xlsx", + filetypes=[("Excel Workbook","*.xlsx")], + initialfile=default_name) + if not fname: return + try: + wb = Workbook() + ws_det = wb.active; ws_det.title = "Dettaglio" + ws_sum = wb.create_sheet("Riepilogo") + det_headers = ["Corsia", "Ubicazione", "IDCella", "Pallet", "Descrizione", "Lotto"] + sum_headers = ["Corsia", "TotCelle", "CelleMultiple", "Percentuale"] + def _hdr(ws, headers): + for j,h in enumerate(headers, start=1): + cell = ws.cell(row=1, column=j, value=h) + cell.font = Font(bold=True); cell.alignment = Alignment(horizontal="center", vertical="center") + _hdr(ws_det, det_headers); _hdr(ws_sum, sum_headers) + + r = 2 + for corsia_node in self.tree.get_children(""): + for cella_node in self.tree.get_children(corsia_node): + for pallet_node in self.tree.get_children(cella_node): + tags = self.tree.item(pallet_node, "tags") or () + if "pallet" not in tags: continue + corsia = next((t.split(":",1)[1] for t in tags if t.startswith("corsia:")), "") + ubi = next((t.split(":",1)[1] for t in tags if t.startswith("ubicazione:")), "") + idcella = next((t.split(":",1)[1] for t in tags if t.startswith("idcella:")), "") + pallet = self.tree.item(pallet_node, "text") + desc, lotto = self.tree.item(pallet_node, "values") + for j,v in enumerate([corsia, ubi, idcella, pallet, desc, lotto], start=1): + ws_det.cell(row=r, column=j, value=v) + r += 1 + + r2 = 2 + for iid in self.sum_tbl.get_children(""): + vals = self.sum_tbl.item(iid, "values") + for j, v in enumerate(vals, start=1): + ws_sum.cell(row=r2, column=j, value=v) + r2 += 1 + + def _autosize(ws): + widths = {} + for row in ws.iter_rows(values_only=True): + for j, val in enumerate(row, start=1): + val_s = "" if val is None else str(val) + widths[j] = max(widths.get(j, 0), len(val_s)) + from openpyxl.utils import get_column_letter + for j, w in widths.items(): + ws.column_dimensions[get_column_letter(j)].width = min(max(w + 2, 10), 60) + + _autosize(ws_det); _autosize(ws_sum) + wb.save(fname); messagebox.showinfo("Esportazione completata", f"File creato:\n{fname}", parent=self) + except Exception as ex: + messagebox.showerror("Errore esportazione", str(ex), parent=self) + +def open_celle_multiple_window(root: tk.Tk, db_client, runner: AsyncRunner | None = None): + win = CelleMultipleWindow(root, db_client, runner=runner); win.lift(); win.focus_set(); return win diff --git a/warehouse_sp_python.py b/warehouse_sp_python.py new file mode 100644 index 0000000..22de872 --- /dev/null +++ b/warehouse_sp_python.py @@ -0,0 +1,1712 @@ +""" +Auto-generated Python port of selected SQL Server stored procedures. +Generated on 2025-10-14T11:57:38 +Notes: +- Synchronous, no threading/async. +- Uses pyodbc; install with `pip install pyodbc` and configure the connection string. +- Two procedures are fully implemented in Python (inserting into Log tables). +- All other procedures are provided as stubs with signatures and embedded T-SQL (for later porting). +""" +from __future__ import annotations +from dataclasses import dataclass +from typing import Optional, Tuple, Any +from datetime import datetime +import pyodbc + + +@dataclass +class SPResult: + message: str | None = None + id_result: int | None = None + + +def get_connection() -> pyodbc.Connection: + """Return a new pyodbc connection. + Adjust the connection string to your environment (Trusted Connection or SQL Auth). + """ + conn = pyodbc.connect( + 'DRIVER={ODBC Driver 18 for SQL Server};' + 'SERVER=localhost;' 'DATABASE=Mediseawall;' 'Trusted_Connection=Yes;' 'TrustServerCertificate=Yes;' + ) + conn.autocommit = False + return conn + + +def _insert_log(table: str, code: str | None, description: str | None) -> Tuple[int, str]: + """Internal helper used by log_operation/log_packing_list.""" + sql = f'''INSERT INTO {table} (Code, Description, IDInsUser, InsDateTime) + VALUES (?, ?, ?, GETDATE()); SELECT SCOPE_IDENTITY();''' + with get_connection() as cxn: + try: + cur = cxn.cursor() + cur.execute(sql, code, description, 1) + new_id = int(cur.fetchval()) + cxn.commit() + return new_id, '' + except Exception as e: + cxn.rollback() + return -1, str(e) + + +def sp_LogOperation(ID: int | None, Code: str | None, Description: str | None) -> SPResult: + """Python port of [dbo].[sp_LogOperation].""" + new_id, err = _insert_log('LogOperation', Code, Description) + if new_id < 0: + return SPResult(message=err, id_result=None) + return SPResult(message='', id_result=new_id) + +def sp_LogPackingList(ID: int | None, Code: str | None, Description: str | None) -> SPResult: + """Python port of [dbo].[sp_LogPackingList].""" + new_id, err = _insert_log('LogPackingList', Code, Description) + if new_id < 0: + return SPResult(message=err, id_result=None) + return SPResult(message='', id_result=new_id) + +def BackupDB() -> Any: + """ + Python stub for [dbo].[BackupDB]. + Original T-SQL for reference: + + BEGIN + -- SET NOCOUNT ON added to prevent extra result sets from + -- interfering with SELECT statements. + SET NOCOUNT ON; + + + + + + DECLARE @RC int + DECLARE @ID int + DECLARE @Descrizione varchar(32) + DECLARE @IDArea int + DECLARE @IDDimensione int + DECLARE @IDStato int + DECLARE @Ordinamento float + DECLARE @X int + DECLARE @Y int + DECLARE @Z int + DECLARE @Corsia varchar(8) + DECLARE @Colonna varchar(8) + DECLARE @Fila varchar(8) + DECLARE @PortataMassimaCella float + DECLARE @PortataMassimaColonna float + DECLARE @UnitaVolumeOccupata float + DECLARE @InsUtente varchar(50) + DECLARE @InsDataOra datetime + DECLARE @ModUtente varchar(50) + DECLARE @ModDataOra datetime + + SET @IDArea = 4 + SET @Corsia = ' 4D' + SET @Colonna = '18' + + + SET @ID = 1001 + SET @Descrizione = '1001 : : 1A - 1 - a' + SET @IDDimensione = 1 + SET @IDStato = 1 + SET @Ordinamento = 1.001000000000000e+003 + SET @X = 0 + SET @Y = 0 + SET @Z = 0 + + SET @PortataMassimaCella = 0.000000000000000e+000 + SET @PortataMassimaColonna = 0.000000000000000e+000 + SET @UnitaVolumeOccupata = 0.000000000000000e+000 + SET @InsUtente = 'raf' + SET @InsDataOra = 'set 11 2010 5:25PM' + SET @ModUtente = 'raf' + SET @ModDataOra = 'set 11 2010 5:25PM' + + declare @IDDaCopiare int + declare @IDNuovo int + + -- Imposta valori dei parametri + + -- Declare an inner cursor based + -- on au_id from the outer cursor. + + DECLARE IDDaCopiare_cursor CURSOR FOR + + + SELECT [ID] + FROM [MediSeawall].[dbo].[Aree] + + OPEN IDDaCopiare_cursor + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + WHILE @@FETCH_STATUS = 0 + BEGIN + + if @IDDaCopiare = 1 BEGIN SET @Fila = 'a' END + if @IDDaCopiare = 2 BEGIN SET @Fila = 'b' END + if @IDDaCopiare = 3 BEGIN SET @Fila = 'c' END + if @IDDaCopiare = 4 BEGIN SET @Fila = 'd' END + if @IDDaCopiare = 5 BEGIN SET @Fila = 'e' END + if @IDDaCopiare = 6 BEGIN SET @Fila = 'f' END + + SET @ID = (SELECT MAX([ID]) FROM [MediSeawall].[dbo].[Celle]) + 1 + + SET @Descrizione = CAST(@ID as char(4)) + ' cors: ' + @Corsia+ ' col: ' + @Colonna + ' fil: ' + @Fila + + EXECUTE @RC = [MediSeawall].[dbo].[spt_SaveCelle] + @ID + ,@Descrizione + ,@IDArea + ,@IDDimensione + ,@IDStato + ,@Ordinamento + ,@X + ,@Y + ,@Z + ,@Corsia + ,@Colonna + ,@Fila + ,@PortataMassimaCella + ,@PortataMassimaColonna + ,@UnitaVolumeOccupata + ,@InsUtente + ,@InsDataOra + ,@ModUtente + ,@ModDataOra + + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + END + + CLOSE IDDaCopiare_cursor + DEALLOCATE IDDaCopiare_cursor + + + + + + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def CreaNuoveCelleMDE6(Locazioni: int | None, Piani: int | None) -> Any: + """ + Python stub for [dbo].[CreaNuoveCelleMDE6]. + Original T-SQL for reference: + + char(4)) + ' cors: ' + @Corsia+ ' col: ' + @Colonna + ' fil: ' + @Fila + + EXECUTE @RC = [MediSeawall].[dbo].[spt_SaveCelle] + @ID + ,@Descrizione + ,@IDArea + ,@IDDimensione + ,@IDStato + ,@Ordinamento + ,@X + ,@Y + ,@Z + ,@Corsia + ,@Colonna + ,@Fila + ,@PortataMassimaCella + ,@PortataMassimaColonna + ,@UnitaVolumeOccupata + ,@InsUtente + ,@InsDataOra + ,@ModUtente + ,@ModDataOra + + + + SET @Piani_value = @Piani_value + 1 + END; + + SET @site_value = @site_value + 1 + END; + + + + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + END + + CLOSE IDDaCopiare_cursor + DEALLOCATE IDDaCopiare_cursor + + + + + + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def CreaNuoveCelleMDE6_BIS(Locazioni: int | None, Piani: int | None) -> Any: + """ + Python stub for [dbo].[CreaNuoveCelleMDE6_BIS]. + Original T-SQL for reference: + + char(4)) + ' cors: ' + @Corsia+ ' col: ' + @Colonna + ' fil: ' + @Fila + + EXECUTE @RC = [MediSeawall].[dbo].[spt_SaveCelle] + @ID + ,@Descrizione + ,@IDArea + ,@IDDimensione + ,@IDStato + ,@Ordinamento + ,@X + ,@Y + ,@Z + ,@Corsia + ,@Colonna + ,@Fila + ,@PortataMassimaCella + ,@PortataMassimaColonna + ,@UnitaVolumeOccupata + ,@InsUtente + ,@InsDataOra + ,@ModUtente + ,@ModDataOra + + + + SET @Piani_value = @Piani_value + 1 + END; + + SET @site_value = @site_value + 1 + END; + + + + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + END + + CLOSE IDDaCopiare_cursor + DEALLOCATE IDDaCopiare_cursor + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def CreateLoopArea(IDArea: int | None) -> Any: + """ + Python stub for [dbo].[CreateLoopArea]. + Original T-SQL for reference: + + BEGIN + -- SET NOCOUNT ON added to prevent extra result sets from + -- interfering with SELECT statements. + SET NOCOUNT ON; + + + DECLARE @ElaboraLoopBarcodePallet varchar(16) + + DECLARE @RC int + DECLARE @IDOperatore int + DECLARE @BarcodeCella varchar(8) = '9000000' + DECLARE @BarcodePallet varchar(16) = '' + DECLARE @NumeroCella int = 9000000 + + DECLARE ElaboraLoopBarcodePallet_cursor CURSOR FOR + + SELECT [BarcodePallet] + FROM [dbo].[XMag_GiacenzaPallet] + WHERE [IDArea] = @IDArea + + + OPEN ElaboraLoopBarcodePallet_cursor + FETCH NEXT FROM ElaboraLoopBarcodePallet_cursor INTO @ElaboraLoopBarcodePallet + + WHILE @@FETCH_STATUS = 0 + BEGIN + + SET @BarcodePallet = @ElaboraLoopBarcodePallet + + -- TODO: impostare qui i valori dei parametri. + + EXECUTE @RC = [sp_xMagGestioneMagazziniPallet] + @IDOperatore + ,@BarcodeCella + ,@BarcodePallet + ,@NumeroCella + ,@RC OUTPUT + + FETCH NEXT FROM ElaboraLoopBarcodePallet_cursor INTO @ElaboraLoopBarcodePallet + + END + + CLOSE ElaboraLoopBarcodePallet_cursor + DEALLOCATE ElaboraLoopBarcodePallet_cursor + + + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def sp_ControllaPrenotazionePackingListPallet(RC: str | None) -> Any: + """ + Python stub for [dbo].[sp_ControllaPrenotazionePackingListPallet]. + Original T-SQL for reference: + + BEGIN + + + DECLARE @RC int = 0 + DECLARE @IDOperatore int = 0 + DECLARE @IDCellaPrenotata int = 0 + DECLARE @Documento varchar(8) = '' + DECLARE @Nominativo varchar(50) = '' + + SELECT TOP 1 @IDCellaPrenotata = [ID] + FROM [Mediseawall].[dbo].[Celle] + where IDStato = 1 + + SELECT TOP 1 @Documento = Documento, @IDCellaPrenotata = Cella + FROM XMag_ViewPackingList + GROUP BY Documento, IDStato,Cella + HAVING (IDStato = 1) + --and Cella <> 9999 + AND Documento IN (SELECT TOP (1) CAST([Code] as int) FROM [LogPackingList] ORDER By ID DESC) + ORDer BY Documento + + IF @IDCellaPrenotata > 0 + BEGIN + + SELECT TOP 1 @Nominativo = [ModUtente] + FROM [Mediseawall].[dbo].[Celle] + where IDStato = 1 + + SELECT @IDOperatore = ID FROM Operatori WHERE LOGIN = @Nominativo + + --SELECT TOP 1 @Documento = Documento + --FROM dbo.XMag_ViewPackingList + --GROUP BY Documento, CodNazione, NAZIONE, Stato, Magazzino, Area, Cella + --HAVING (Cella = @IDCellaPrenotata) + + SELECT TOP 1 @Documento = Documento + FROM XMag_ViewPackingList + GROUP BY Documento, IDStato + HAVING (IDStato = 1) + AND Documento IN (SELECT TOP (1) CAST([Code] as int) FROM [LogPackingList] ORDER By ID DESC) + ORDER BY Documento + + EXECUTE [dbo].sp_xExePackingListPalletPrenota + @IDOperatore + ,@Documento + ,@RC OUTPUT + END + + + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def sp_OrdinaCelle() -> Any: + """ + Python stub for [dbo].[sp_OrdinaCelle]. + Original T-SQL for reference: + + INT) DESC + + OPEN IDDaCopiare_cursor + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + WHILE @@FETCH_STATUS = 0 + BEGIN + + SET @IDNuovo = @IDNuovo + 1 + + + UPDATE [MediSeawall].[dbo].[Celle] + SET [Ordinamento] = @IDNuovo + WHERE [ID] = @IDDaCopiare + + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + END + + CLOSE IDDaCopiare_cursor + DEALLOCATE IDDaCopiare_cursor + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def sp_xExePackingListPallet(IDOperatore: int | None, Documento: str | None, RC: int | None) -> Any: + """ + Python stub for [dbo].[sp_xExePackingListPallet]. + Original T-SQL for reference: + + SET @RC = 0 + -- Recupera operatore + DECLARE @Nominativo varchar(50) + SELECT @Nominativo = LOGIN FROM Operatori WHERE id = @IDOperatore + DECLARE @Stato int + PRINT @Nominativo + + + declare @IDDaCopiare int + declare @IDNuovo int + + -- Imposta valori dei parametri + + -- Declare an inner cursor based + -- on au_id from the outer cursor. + + DECLARE IDDaCopiare_cursor CURSOR FOR + + SELECT Cella + FROM dbo.XMag_ViewPackingList + GROUP BY Documento, CodNazione, NAZIONE, Stato, Magazzino, Area, Cella + HAVING (Documento = @Documento) + + OPEN IDDaCopiare_cursor + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + WHILE @@FETCH_STATUS = 0 + BEGIN + + SELECT @Stato = [IDStato] FROM [Celle] WHERE [ID] = @IDDaCopiare + + if @Stato = 0 + BEGIN + UPDATE [Celle] SET [IDStato] = 1 + ,[ModUtente] = @Nominativo + ,[ModDataOra] = GETDATE() + WHERE [ID] = @IDDaCopiare + END + ELSE + BEGIN + UPDATE [Celle] SET [IDStato] = 0 + ,[ModUtente] = @Nominativo + ,[ModDataOra] = GETDATE() + WHERE [ID] = @IDDaCopiare + END + + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + END + + CLOSE IDDaCopiare_cursor + DEALLOCATE IDDaCopiare_cursor + + + + DECLARE @ID int = 0 + DECLARE @Code varchar(64) = @Documento + DECLARE @Description varchar(255) + DECLARE @Message varchar(255) + DECLARE @IDResult int + + SELECT TOP 1 @Description = NAZIONE + FROM dbo.XMag_ViewPackingList + GROUP by Documento, NAZIONE + HAVING Documento = @Documento + -- TODO: impostare qui i valori dei parametri. + + EXECUTE @RC = [dbo].[sp_LogPackingList] + @ID + ,@Code + ,@Description + ,@Message OUTPUT + ,@IDResult OUTPUT + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def sp_xExePackingListPalletPrenota(IDOperatore: int | None, Documento: str | None, RC: int | None) -> Any: + """ + Python stub for [dbo].[sp_xExePackingListPalletPrenota]. + Original T-SQL for reference: + + SET @RC = 0 + -- Recupera operatore + DECLARE @Nominativo varchar(50) + SELECT @Nominativo = LOGIN FROM Operatori WHERE id = @IDOperatore + DECLARE @Stato int + PRINT @Nominativo + + + declare @IDDaCopiare int + declare @IDNuovo int + + -- Imposta valori dei parametri + + -- Declare an inner cursor based + -- on au_id from the outer cursor. + + DECLARE IDDaCopiare_cursor CURSOR FOR + + SELECT Cella + FROM dbo.XMag_ViewPackingList + GROUP BY Documento, CodNazione, NAZIONE, Stato, Magazzino, Area, Cella + HAVING (Documento = @Documento) + + OPEN IDDaCopiare_cursor + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + WHILE @@FETCH_STATUS = 0 + BEGIN + + + UPDATE [Celle] SET [IDStato] = 1 + ,[ModUtente] = @Nominativo + ,[ModDataOra] = GETDATE() + WHERE [ID] = @IDDaCopiare + + + + FETCH NEXT FROM IDDaCopiare_cursor INTO @IDDaCopiare + + END + + CLOSE IDDaCopiare_cursor + DEALLOCATE IDDaCopiare_cursor + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def sp_xMagGestioneAccettazione(IDOperatore: int | None, BarcodeCella: str | None, BarcodePallet: str | None, NumeroCella: int | None, RC: int | None, Out1: str | None, Out2: str | None, Out3: str | None, Out4: str | None, Out5: str | None, Out6: str | None, Out7: str | None) -> Any: + """ + Python stub for [dbo].[sp_xMagGestioneAccettazione]. + Original T-SQL for reference: + + --DECLARE @RC int + --DECLARE @IDOperatore int + --DECLARE @BarcodeCella varchar(8) + --DECLARE @BarcodePallet varchar(16) + --DECLARE @NumeroCella int + --SET @IDOperatore = 1 + SET @BarcodeCella = '9009000' + --SET @BarcodePallet = '100782' + SET @NumeroCella = 9000 + + SET @RC = 0 + -- Recupera operatore + DECLARE @Output1 varchar(16) + DECLARE @Output2 varchar(16) + DECLARE @Output3 varchar(16) + DECLARE @Output4 varchar(16) + + DECLARE @Nominativo varchar(50) + SELECT @Nominativo = LOGIN FROM Operatori WHERE id = @IDOperatore + + PRINT @Nominativo + PRINT SUBSTRING(@BarcodeCella,1,3) + PRINT SUBSTRING(@BarcodeCella,4,2) + PRINT SUBSTRING(@BarcodeCella,6,2) + -- Cerca la cella + DECLARE @IDMagazzino int ,@IDArea int, @IDCella int, @NumeroPallet int, @NewIDCella int + SET @NewIDCella = -1*(9000000 - @NumeroCella) + SET @IDMagazzino = 0 + SET @IDArea = 0 + SET @IDCella = 0 + SET @NumeroPallet = 0 + + SELECT @IDCella = [ID], @IDArea = [IDArea] + FROM [Celle] + WHERE ID = @NewIDCella + + + + if @IDArea > 0 + BEGIN + -- Magazzino da area + SELECT @IDMagazzino = [IDMagazzino] + FROM [Aree] + WHERE [ID] = @IDArea + END + ELSE + BEGIN + -- se non trova la cella recupera il magazzino di default + SELECT TOP 1 @IDMagazzino = UnitaProduzione.IDMagVersamento + FROM Operatori INNER JOIN UnitaProduzione ON Operatori.CodiceUnita = UnitaProduzione.Codice + WHERE (Operatori.ID = @IDOperatore) + + SELECT @IDCella = [ID], @IDArea = [IDArea] + FROM [Celle] + WHERE ID = 9000 + + END + + -- Recupera il peso unitario e la tara + DECLARE @PesoUnitario float, @Tara float, @IDRiferimento int + SET @PesoUnitario = 1 + SET @Tara = 0 + SET @IDRiferimento = 0 + + SELECT TOP 1 @IDRiferimento = ID + FROM [Accettazione] + WHERE (IDMagazzino = @IDMagazzino) AND (Attributo = @BarcodePallet) -- AND (NumeroPallet = @NumeroPallet) + AND PesoUnitario > 0 AND Tipo = 'V' AND [IDRiferimento] = 0 + ORDER BY ID DESC + + + UPDATE [Accettazione] + SET [ModUtente] = @Nominativo, [ModDataOra] = GETDATE(), [IDRiferimento] = @IDRiferimento + WHERE ID = @IDRiferimento AND [IDRiferimento] = 0 + + --WHERE (IDMagazzino = @IDMagazzino) AND (Attributo = @BarcodePallet) -- AND (NumeroPallet = @NumeroPallet) + --AND PesoUnitario > 0 AND Tipo = 'V' + --ORDER BY ID DESC + + IF @@ROWCOUNT > 0 -- SE TROVO QUALCOSA LA PRELIEVO - Poi Trasferisco in area transito + BEGIN + + INSERT INTO [Accettazione] ([Tipo],[IDRiferimento] ,[NumeroPallet], Attributo + ,[IDMagazzino] ,[IDArea] ,[IDCella] ,[DataMagazzino] + ,[PesoUnitario] ,[Tara],[InsUtente] ,[InsDataOra]) + + + + SELECT 'P' ,@IDRiferimento,[NumeroPallet], Attributo + ,[IDMagazzino] ,[IDArea] ,[IDCella] ,GETDATE() + ,[PesoUnitario],[Tara], @Nominativo ,GETDATE() + FROM [Accettazione] + WHERE ID = @IDRiferimento + + SET @RC = @@IDENTITY + + SELECT @Output2 = Attributo, + @Output3 = [InsUtente] , @Output4 = CAST([InsDataOra] as CHAR(16)) + FROM [Accettazione] + WHERE ID = @IDRiferimento + + + SET @Out1 = 'DIS-ACCETTAZIONE' + SET @Out2 = @Output2 + SET @Out3 = @Output3 + SET @Out4 = @Output4 + SET @Out5 = 5 + SET @Out6 = @BarcodeCella + SET @Out7 = '' + + END + ELSE + BEGIN + + -- VERSA in area cella [IDMagazzino],[IDArea],[IDCella] + INSERT INTO [Accettazione] ([Tipo] ,[IDRiferimento],[NumeroPallet], Attributo + ,[IDMagazzino],[IDArea],[IDCella],[DataMagazzino] + ,[PesoUnitario],[Tara],[InsUtente],[InsDataOra]) + VALUES ('V',@IDRiferimento,@NumeroPallet, @BarcodePallet + ,@IDMagazzino,@IDArea,@IDCella,GETDATE() + ,@PesoUnitario,@Tara,@Nominativo,GETDATE()) + + + SET @RC = @@IDENTITY + + SET @Out1 = 'ACCETTATO' + SET @Out2 = @BarcodePallet + SET @Out3 = @Nominativo + SET @Out4 = CAST(GETDATE() as CHAR(16)) + SET @Out5 = 7 + SET @Out6 = @BarcodeCella + SET @Out7 = '' + + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def sp_xMagGestioneAccettazioneOLD(IDOperatore: int | None, BarcodeCella: str | None, BarcodePallet: str | None, NumeroCella: int | None, RC: int | None, Out1: str | None, Out2: str | None, Out3: str | None, Out4: str | None, Out5: str | None, Out6: str | None, Out7: str | None) -> Any: + """ + Python stub for [dbo].[sp_xMagGestioneAccettazioneOLD]. + Original T-SQL for reference: + + --DECLARE @RC int + --DECLARE @IDOperatore int + --DECLARE @BarcodeCella varchar(8) + --DECLARE @BarcodePallet varchar(16) + --DECLARE @NumeroCella int + --SET @IDOperatore = 1 + SET @BarcodeCella = '9009000' + --SET @BarcodePallet = '100782' + SET @NumeroCella = 9000 + + SET @RC = 0 + -- Recupera operatore + DECLARE @Output1 varchar(16) + DECLARE @Output2 varchar(16) + DECLARE @Output3 varchar(16) + DECLARE @Output4 varchar(16) + + DECLARE @Nominativo varchar(50) + SELECT @Nominativo = LOGIN FROM Operatori WHERE id = @IDOperatore + + PRINT @Nominativo + PRINT SUBSTRING(@BarcodeCella,1,3) + PRINT SUBSTRING(@BarcodeCella,4,2) + PRINT SUBSTRING(@BarcodeCella,6,2) + -- Cerca la cella + DECLARE @IDMagazzino int ,@IDArea int, @IDCella int, @NumeroPallet int, @NewIDCella int + SET @NewIDCella = -1*(9000000 - @NumeroCella) + SET @IDMagazzino = 0 + SET @IDArea = 0 + SET @IDCella = 0 + SET @NumeroPallet = 0 + + SELECT @IDCella = [ID], @IDArea = [IDArea] + FROM [Celle] + WHERE ID = @NewIDCella + + + + if @IDArea > 0 + BEGIN + -- Magazzino da area + SELECT @IDMagazzino = [IDMagazzino] + FROM [Aree] + WHERE [ID] = @IDArea + END + ELSE + BEGIN + -- se non trova la cella recupera il magazzino di default + SELECT TOP 1 @IDMagazzino = UnitaProduzione.IDMagVersamento + FROM Operatori INNER JOIN UnitaProduzione ON Operatori.CodiceUnita = UnitaProduzione.Codice + WHERE (Operatori.ID = @IDOperatore) + + SELECT @IDCella = [ID], @IDArea = [IDArea] + FROM [Celle] + WHERE ID = 9000 + + END + + -- Recupera il peso unitario e la tara + DECLARE @PesoUnitario float, @Tara float, @IDRiferimento int + SET @PesoUnitario = 1 + SET @Tara = 0 + SET @IDRiferimento = 0 + + SELECT TOP 1 @IDRiferimento = ID + FROM [Accettazione] + WHERE (IDMagazzino = @IDMagazzino) AND (Attributo = @BarcodePallet) -- AND (NumeroPallet = @NumeroPallet) + AND PesoUnitario > 0 AND Tipo = 'V' + ORDER BY ID DESC + + + UPDATE [Accettazione] + SET [ModUtente] = @Nominativo, [ModDataOra] = GETDATE() + WHERE ID = @IDRiferimento + + --WHERE (IDMagazzino = @IDMagazzino) AND (Attributo = @BarcodePallet) -- AND (NumeroPallet = @NumeroPallet) + --AND PesoUnitario > 0 AND Tipo = 'V' + --ORDER BY ID DESC + + IF @@ROWCOUNT > 0 -- SE TROVO QUALCOSA LA PRELIEVO - Poi Trasferisco in area transito + BEGIN + + INSERT INTO [Accettazione] ([Tipo],[IDRiferimento] ,[NumeroPallet], Attributo + ,[IDMagazzino] ,[IDArea] ,[IDCella] ,[DataMagazzino] + ,[PesoUnitario] ,[Tara],[InsUtente] ,[InsDataOra]) + + + + SELECT 'P' ,@IDRiferimento,[NumeroPallet], Attributo + ,[IDMagazzino] ,[IDArea] ,[IDCella] ,GETDATE() + ,[PesoUnitario],[Tara], @Nominativo ,GETDATE() + FROM [Accettazione] + WHERE ID = @IDRiferimento + + SET @RC = @@IDENTITY + + SELECT @Output2 = Attributo, + @Output3 = [InsUtente] , @Output4 = CAST([InsDataOra] as CHAR(16)) + FROM [Accettazione] + WHERE ID = @IDRiferimento + + + SET @Out1 = 'ATTENZIONE' + SET @Out2 = @Output2 + SET @Out3 = @Output3 + SET @Out4 = @Output4 + SET @Out5 = 5 + SET @Out6 = @BarcodeCella + SET @Out7 = '' + + END + ELSE + BEGIN + + -- VERSA in area cella [IDMagazzino],[IDArea],[IDCella] + INSERT INTO [Accettazione] ([Tipo] ,[IDRiferimento],[NumeroPallet], Attributo + ,[IDMagazzino],[IDArea],[IDCella],[DataMagazzino] + ,[PesoUnitario],[Tara],[InsUtente],[InsDataOra]) + VALUES ('V',@IDRiferimento,@NumeroPallet, @BarcodePallet + ,@IDMagazzino,@IDArea,@IDCella,GETDATE() + ,@PesoUnitario,@Tara,@Nominativo,GETDATE()) + + + SET @RC = @@IDENTITY + + SET @Out1 = 'ACCETTATO' + SET @Out2 = @BarcodePallet + SET @Out3 = @Nominativo + SET @Out4 = CAST(GETDATE() as CHAR(16)) + SET @Out5 = 7 + SET @Out6 = @BarcodeCella + SET @Out7 = '' + + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def sp_xMagGestioneMagazziniPallet(IDOperatore: int | None, BarcodeCella: str | None, BarcodePallet: str | None, NumeroCella: int | None, RC: int | None) -> Any: + """ + Python stub for [dbo].[sp_xMagGestioneMagazziniPallet]. + Original T-SQL for reference: + + --DECLARE @RC int + --DECLARE @IDOperatore int + --DECLARE @BarcodeCella varchar(8) + --DECLARE @BarcodePallet varchar(16) + --DECLARE @NumeroCella int + --SET @IDOperatore = 1 + --SET @BarcodeCella = ' 1056' + --SET @BarcodePallet = '100782' + --SET @NumeroCella = 1056 + + SET @RC = 0 + -- Recupera operatore + DECLARE @Nominativo varchar(50) + SELECT @Nominativo = LOGIN FROM Operatori WHERE id = @IDOperatore + + PRINT @Nominativo + PRINT SUBSTRING(@BarcodeCella,1,3) + PRINT SUBSTRING(@BarcodeCella,4,2) + PRINT SUBSTRING(@BarcodeCella,6,2) + -- Cerca la cella + DECLARE @IDMagazzino int ,@IDArea int, @IDCella int, @NumeroPallet int, @NewIDCella int + SET @NewIDCella = -1*(9000000 - @NumeroCella) + SET @IDMagazzino = 0 + SET @IDArea = 0 + SET @IDCella = 0 + SET @NumeroPallet = 0 + + SELECT @IDCella = [Celle].[ID], @IDArea = [IDArea], @IDMagazzino = IDMagazzino + FROM [Celle], Aree + WHERE [Celle].ID = @NewIDCella + AND IDArea = Aree.ID + + + --WHERE [Corsia] = SUBSTRING(@BarcodeCella,1,3) + -- AND [Colonna] = SUBSTRING(@BarcodeCella,4,2) + -- AND [Fila] = SUBSTRING(@BarcodeCella,6,2) + PRINT @NumeroCella + print 'Barcode Cella' + PRINT @NewIDCella + print 'NEWNumero Cella' + + PRINT @IDCella + print 'Numero Cella' + PRINT @IDArea + print 'Numero @IDArea' + + + DECLARE @ID int + DECLARE @Code varchar(64) + DECLARE @Description varchar(255) + DECLARE @Message varchar(255) + DECLARE @IDResult int + + SET @Code = @BarcodeCella +' - '+ @BarcodePallet +' - '+ CAST(@NumeroCella as CHAR(10)) + SET @Description = CAST(@IDArea as CHAR(10)) +' - '+ CAST(@IDCella as CHAR(10)) + SET @ID= 0 + + -- TODO: impostare qui i valori dei parametri. + + EXECUTE sp_LogOperation @ID ,@Code ,@Description ,@Message OUTPUT ,@IDResult OUTPUT + + SET @ID= @IDResult + + + + if @IDArea > 0 + BEGIN + -- Magazzino da area + SELECT @IDMagazzino = [IDMagazzino] + FROM [Aree] + WHERE [ID] = @IDArea + END + ELSE + BEGIN + -- se non trova la cella recupera il magazzino di default + SELECT TOP 1 @IDMagazzino = UnitaProduzione.IDMagVersamento + FROM Operatori INNER JOIN UnitaProduzione ON Operatori.CodiceUnita = UnitaProduzione.Codice + WHERE (Operatori.ID = @IDOperatore) + + SELECT @IDCella = [Celle].[ID], @IDArea = [IDArea], @IDMagazzino = IDMagazzino + FROM [Celle], Aree + WHERE [Celle].ID = 9999 + AND IDArea = Aree.ID + END + + -- Recupera il peso unitario e la tara + DECLARE @PesoUnitario float, @Tara float, @IDRiferimento int + SET @PesoUnitario = 1 + SET @Tara = 0 + SET @IDRiferimento = 0 + + SELECT TOP 1 @IDRiferimento = ID + FROM [MagazziniPallet] + WHERE 1= 1 + --AND (IDMagazzino = @IDMagazzino) + AND (Attributo = @BarcodePallet) -- AND (NumeroPallet = @NumeroPallet) + AND PesoUnitario > 0 AND Tipo = 'V' + ORDER BY ID DESC + + + UPDATE [MagazziniPallet] + SET [ModUtente] = @Nominativo, [ModDataOra] = GETDATE() + WHERE ID = @IDRiferimento + + --WHERE (IDMagazzino = @IDMagazzino) AND (Attributo = @BarcodePallet) -- AND (NumeroPallet = @NumeroPallet) + --AND PesoUnitario > 0 AND Tipo = 'V' + --ORDER BY ID DESC + + IF @@ROWCOUNT > 0 -- SE TROVO QUALCOSA LA PRELIEVO - Poi Trasferisco in area transito + BEGIN + + INSERT INTO [MagazziniPallet] ([Tipo],[IDRiferimento] ,[NumeroPallet], Attributo + ,[IDMagazzino] ,[IDArea] ,[IDCella] ,[DataMagazzino] + ,[PesoUnitario] ,[Tara],[InsUtente] ,[InsDataOra]) + + SELECT 'P' ,@IDRiferimento,[NumeroPallet], Attributo + ,[IDMagazzino] ,[IDArea] ,[IDCella] ,GETDATE() + ,[PesoUnitario],[Tara], @Nominativo ,GETDATE() + FROM [MagazziniPallet] + WHERE ID = @IDRiferimento + -- WHERE (IDMagazzino = @IDMagazzino) AND (Attributo = @BarcodePallet) -- AND (NumeroPallet = @NumeroPallet) + -- AND PesoUnitario > 0 AND Tipo = 'V' + -- ORDER BY ID DESC + + -- disimpegna + UPDATE [Celle] SET + [IDStato] = 0 , [ModUtente] = @Nominativo ,[ModDataOra] = GETDATE() + WHERE [ID] = (SELECT [IDCella] + FROM [MagazziniPallet] + WHERE ID = @IDRiferimento) + + -- Trasferisci in area cella [IDMagazzino],[IDArea],[IDCella] + INSERT INTO [MagazziniPallet] ([Tipo] ,[IDRiferimento],[NumeroPallet], Attributo + ,[IDMagazzino],[IDArea],[IDCella],[DataMagazzino] + ,[PesoUnitario],[Tara],[InsUtente],[InsDataOra]) + VALUES ('V',@IDRiferimento,@NumeroPallet, @BarcodePallet + ,@IDMagazzino,@IDArea,@IDCella,GETDATE() + ,@PesoUnitario,@Tara,@Nominativo,GETDATE()) + + + SET @RC = @@IDENTITY + + + END + ELSE + BEGIN + + -- VERSA in area cella [IDMagazzino],[IDArea],[IDCella] + INSERT INTO [MagazziniPallet] ([Tipo] ,[IDRiferimento],[NumeroPallet], Attributo + ,[IDMagazzino],[IDArea],[IDCella],[DataMagazzino] + ,[PesoUnitario],[Tara],[InsUtente],[InsDataOra]) + VALUES ('V',@IDRiferimento,@NumeroPallet, @BarcodePallet + ,@IDMagazzino,@IDArea,@IDCella,GETDATE() + ,@PesoUnitario,@Tara,@Nominativo,GETDATE()) + + -- disimpegna + --UPDATE [Celle] SET + -- [IDStato] = 0 , [ModUtente] = @Nominativo ,[ModDataOra] = GETDATE() + --WHERE [ID] = @IDCella + + SET @RC = @@IDENTITY + + + END + + + --EXECUTE [dbo].[sp_ControllaPrenotazionePackingListPallet] + EXECUTE [dbo].[sp_ControllaPrenotazionePackingLi + -- [TRUNCATED] -- + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteAree(ID: int | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteAree]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Aree + SET ID = @ID + ,DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (ID = @ID) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteCelle(ID: int | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteCelle]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Celle + SET ID = @ID + ,DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (ID = @ID) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteCelleDimensione(ID: int | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteCelleDimensione]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE CelleDimensione + SET ID = @ID + ,DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (ID = @ID) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteCelleStati(ID: int | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteCelleStati]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE CelleStati + SET ID = @ID + ,DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (ID = @ID) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteDivisioni(Codice: str | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteDivisioni]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Divisioni + SET Codice = @Codice + ,DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (Codice = @Codice) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteMagazzini(ID: int | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteMagazzini]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Magazzini + SET DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (ID = @ID) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteOperatori(ID: int | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteOperatori]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Operatori + SET DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (ID = @ID) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteReparti(Codice: str | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteReparti]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Reparti + SET Codice = @Codice + ,DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (Codice = @Codice) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteStabilimenti(Codice: str | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteStabilimenti]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Stabilimenti + SET Codice = @Codice + ,DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (Codice = @Codice) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_DeleteUnitaProduzione(Codice: str | None, DelUtente: str | None, DelDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_DeleteUnitaProduzione]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE UnitaProduzione + SET Codice = @Codice + ,DelUtente = @DelUtente + ,DelDataOra = @DelDataOra + WHERE (Codice = @Codice) + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveAree(ID: int | None, IDMagazzino: int | None, Descrizione: str | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveAree]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Aree + SET ID = @ID + ,IDMagazzino = @IDMagazzino + ,Descrizione = @Descrizione + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + WHERE ID = @ID + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO Aree + (ID + ,IDMagazzino + ,Descrizione + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @ID + , @IDMagazzino + , @Descrizione + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveCelle(ID: int | None, Descrizione: str | None, IDArea: int | None, IDDimensione: int | None, IDStato: int | None, Ordinamento: float | None, X: int | None, Y: int | None, Z: int | None, Corsia: str | None, Colonna: str | None, Fila: str | None, PortataMassimaCella: float | None, PortataMassimaColonna: float | None, UnitaVolumeOccupata: float | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveCelle]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Celle + SET ID = @ID + ,Descrizione = @Descrizione + ,IDArea = @IDArea + ,IDDimensione = @IDDimensione + ,IDStato = @IDStato + ,Ordinamento = @Ordinamento + ,X = @X + ,Y = @Y + ,Z = @Z + ,Corsia = @Corsia + ,Colonna = @Colonna + ,Fila = @Fila + ,PortataMassimaCella = @PortataMassimaCella + ,PortataMassimaColonna = @PortataMassimaColonna + ,UnitaVolumeOccupata = @UnitaVolumeOccupata + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + WHERE ID = @ID + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO Celle + (ID + ,Descrizione + ,IDArea + ,IDDimensione + ,IDStato + ,Ordinamento + ,X + ,Y + ,Z + ,Corsia + ,Colonna + ,Fila + ,PortataMassimaCella + ,PortataMassimaColonna + ,UnitaVolumeOccupata + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @ID + , @Descrizione + , @IDArea + , @IDDimensione + , @IDStato + , @Ordinamento + , @X + , @Y + , @Z + , @Corsia + , @Colonna + , @Fila + , @PortataMassimaCella + , @PortataMassimaColonna + , @UnitaVolumeOccupata + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveCelleDimensione(ID: int | None, Descrizione: str | None, Dimensione: float | None, UnitaVolume: float | None, A: float | None, B: float | None, C: float | None, IDSolido: int | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveCelleDimensione]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE CelleDimensione + SET + Descrizione = @Descrizione + ,Dimensione = @Dimensione + ,UnitaVolume = @UnitaVolume + ,A = @A + ,B = @B + ,C = @C + ,IDSolido = @IDSolido + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + WHERE ID = @ID + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO CelleDimensione + (ID + ,Descrizione + ,Dimensione + ,UnitaVolume + ,A + ,B + ,C + ,IDSolido + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @ID + , @Descrizione + , @Dimensione + , @UnitaVolume + , @A + , @B + , @C + , @IDSolido + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveCelleStati(ID: int | None, Descrizione: str | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveCelleStati]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE CelleStati + SET + Descrizione = @Descrizione + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + WHERE ID = @ID + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO CelleStati + (ID + ,Descrizione + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @ID + , @Descrizione + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveDivisioni(Codice: str | None, Descrizione: str | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveDivisioni]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Divisioni + SET Codice = @Codice + ,Descrizione = @Descrizione + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + WHERE (Codice = @Codice) + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO Divisioni + (Codice + ,Descrizione + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @Codice + , @Descrizione + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveMagazzini(ID: int | None, Codice: str | None, CodiceDivisione: str | None, NomeBreve: str | None, Descrizione: str | None, FreqRadio: str | None, Informatizzato: str | None, ProgressivoPallet: int | None, CodiceStabilimento: str | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveMagazzini]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Magazzini + SET ID = @ID + ,Codice = @Codice + ,CodiceDivisione = @CodiceDivisione + ,NomeBreve = @NomeBreve + ,Descrizione = @Descrizione + ,FreqRadio = @FreqRadio + ,Informatizzato = @Informatizzato + ,ProgressivoPallet = @ProgressivoPallet + ,CodiceStabilimento = @CodiceStabilimento + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + WHERE ID = @ID + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO Magazzini + (ID + ,Codice + ,CodiceDivisione + ,NomeBreve + ,Descrizione + ,FreqRadio + ,Informatizzato + ,ProgressivoPallet + ,CodiceStabilimento + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @ID + , @Codice + , @CodiceDivisione + , @NomeBreve + , @Descrizione + , @FreqRadio + , @Informatizzato + , @ProgressivoPallet + , @CodiceStabilimento + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveOperatori(ID: int | None, Login: str | None, Nominativo: str | None, CodiceUnita: str | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveOperatori]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Operatori + SET ID = @ID + ,Login = @Login + ,Nominativo = @Nominativo + ,CodiceUnita = @CodiceUnita + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + WHERE ID = @ID + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO Operatori + (ID + ,Login + ,Nominativo + ,CodiceUnita + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @ID + , @Login + , @Nominativo + , @CodiceUnita + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveReparti(Codice: str | None, CodiceStabilimento: str | None, CodiceDivisione: str | None, Descrizione: str | None, PrfxLotto: int | None, PrfxAlias: str | None, PrfxCodiceLotto: str | None, IDFormato: int | None, Nota: str | None, IndiceSSCC: int | None, Prfx: str | None, VistaCommesse: str | None, CodiceAnagrafica: str | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveReparti]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Reparti + SET Codice = @Codice + ,CodiceStabilimento = @CodiceStabilimento + ,CodiceDivisione = @CodiceDivisione + ,Descrizione = @Descrizione + ,PrfxLotto = @PrfxLotto + ,PrfxAlias = @PrfxAlias + ,PrfxCodiceLotto = @PrfxCodiceLotto + ,IDFormato = @IDFormato + ,Nota = @Nota + ,IndiceSSCC = @IndiceSSCC + ,Prfx = @Prfx + ,VistaCommesse = @VistaCommesse + ,CodiceAnagrafica = @CodiceAnagrafica + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + + WHERE Codice = @Codice + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO Reparti + (Codice + ,CodiceStabilimento + ,CodiceDivisione + ,Descrizione + ,PrfxLotto + ,PrfxAlias + ,PrfxCodiceLotto + ,IDFormato + ,Nota + ,IndiceSSCC + ,Prfx + ,VistaCommesse + ,CodiceAnagrafica + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @Codice + , @CodiceStabilimento + , @CodiceDivisione + , @Descrizione + , @PrfxLotto + , @PrfxAlias + , @PrfxCodiceLotto + , @IDFormato + , @Nota + , @IndiceSSCC + , @Prfx + , @VistaCommesse + , @CodiceAnagrafica + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveStabilimenti(Codice: str | None, Descrizione: str | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveStabilimenti]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE Stabilimenti + SET Codice = @Codice + ,Descrizione = @Descrizione + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + WHERE (Codice = @Codice) + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO Stabilimenti + (Codice + ,Descrizione + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @Codice + , @Descrizione + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') + +def spt_SaveUnitaProduzione(Codice: str | None, CodiceReparto: str | None, Descrizione: str | None, IDMagPrelievo: int | None, IDMagVersamento: int | None, Nota: str | None, VistaCommesse: str | None, VistaDocumenti: str | None, VistaDettagli: str | None, InsUtente: str | None, InsDataOra: datetime | None, ModUtente: str | None, ModDataOra: datetime | None) -> Any: + """ + Python stub for [dbo].[spt_SaveUnitaProduzione]. + Original T-SQL for reference: + + SET + NOCOUNT ON + + UPDATE UnitaProduzione + SET Codice = @Codice + ,CodiceReparto = @CodiceReparto + ,Descrizione = @Descrizione + ,IDMagPrelievo = @IDMagPrelievo + ,IDMagVersamento = @IDMagVersamento + ,Nota = @Nota + ,VistaCommesse = @VistaCommesse + ,VistaDocumenti = @VistaDocumenti + ,VistaDettagli = @VistaDettagli + ,InsUtente = @InsUtente + ,InsDataOra = @InsDataOra + ,ModUtente = @ModUtente + ,ModDataOra = @ModDataOra + WHERE Codice = @Codice + + IF @@ROWCOUNT = 0 + BEGIN + + INSERT INTO UnitaProduzione + (Codice + ,CodiceReparto + ,Descrizione + ,IDMagPrelievo + ,IDMagVersamento + ,Nota + ,VistaCommesse + ,VistaDocumenti + ,VistaDettagli + ,InsUtente + ,InsDataOra + ,ModUtente + ,ModDataOra + ) VALUES + ( @Codice + , @CodiceReparto + , @Descrizione + , @IDMagPrelievo + , @IDMagVersamento + , @Nota + , @VistaCommesse + , @VistaDocumenti + , @VistaDettagli + , @InsUtente + , @InsDataOra + , @ModUtente + , @ModDataOra + ) + END + """ + raise NotImplementedError('Port this stored procedure logic into Python (step-by-step SQL).') diff --git a/warehouse_sql.log b/warehouse_sql.log new file mode 100644 index 0000000..a99d454 --- /dev/null +++ b/warehouse_sql.log @@ -0,0 +1,3270 @@ +[2025-09-19 13:35:35.058] PURPOSE: Rilevamento colonne Celle\n[2025-09-19 13:35:35.058] SQL:\n[2025-09-19 13:35:35.058] SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle');\n[2025-09-19 13:35:35.058] PARAMS: {}\n[2025-09-19 13:35:35.058] ELAPSED_MS: 0\n--------------------------------------------------------------------------------\n[2025-09-19 13:35:35.145] PURPOSE: Lista Aree\n[2025-09-19 13:35:35.145] INFO: START\n[2025-09-19 13:35:35.145] SQL:\n[2025-09-19 13:35:35.145] SELECT\n[2025-09-19 13:35:35.145] a.ID AS AreaID,\n[2025-09-19 13:35:35.145] a.Descrizione AS AreaNome,\n[2025-09-19 13:35:35.145] a.IDMagazzino AS MagID,\n[2025-09-19 13:35:35.145] m.Codice AS Magazzino\n[2025-09-19 13:35:35.145] FROM dbo.Aree a\n[2025-09-19 13:35:35.145] JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino\n[2025-09-19 13:35:35.145] WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101'\n[2025-09-19 13:35:35.145] ORDER BY m.Codice, a.Descrizione;\n[2025-09-19 13:35:35.145] PARAMS: {}\n--------------------------------------------------------------------------------\n[2025-09-19 13:35:35.161] PURPOSE: Lista Aree\n[2025-09-19 13:35:35.161] INFO: END\n[2025-09-19 13:35:35.161] SQL:\n[2025-09-19 13:35:35.161] SELECT\n[2025-09-19 13:35:35.161] a.ID AS AreaID,\n[2025-09-19 13:35:35.161] a.Descrizione AS AreaNome,\n[2025-09-19 13:35:35.161] a.IDMagazzino AS MagID,\n[2025-09-19 13:35:35.161] m.Codice AS Magazzino\n[2025-09-19 13:35:35.161] FROM dbo.Aree a\n[2025-09-19 13:35:35.161] JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino\n[2025-09-19 13:35:35.161] WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101'\n[2025-09-19 13:35:35.161] ORDER BY m.Codice, a.Descrizione;\n[2025-09-19 13:35:35.161] PARAMS: {}\n[2025-09-19 13:35:35.161] ELAPSED_MS: 14\n--------------------------------------------------------------------------------\n[2025-09-19 13:35:35.187] PURPOSE: Statistiche Scaffali per Area\n[2025-09-19 13:35:35.187] INFO: START\n[2025-09-19 13:35:35.187] SQL:\n[2025-09-19 13:35:35.187] WITH CELLE AS (\n[2025-09-19 13:35:35.187] SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale\n[2025-09-19 13:35:35.187] FROM dbo.Celle c\n[2025-09-19 13:35:35.187] WHERE c.IDArea = :area_id\n[2025-09-19 13:35:35.187] ),\n[2025-09-19 13:35:35.187] OCC AS (\n[2025-09-19 13:35:35.187] SELECT c.Scaffale, COUNT(*) AS CelleTotali\n[2025-09-19 13:35:35.187] FROM CELLE c\n[2025-09-19 13:35:35.187] GROUP BY c.Scaffale\n[2025-09-19 13:35:35.187] ),\n[2025-09-19 13:35:35.187] OCC2 AS (\n[2025-09-19 13:35:35.187] SELECT c.Scaffale,\n[2025-09-19 13:35:35.187] COUNT(DISTINCT mp.IDCella) AS CelleOccupate,\n[2025-09-19 13:35:35.187] COUNT(mp.ID) AS NPalet\n[2025-09-19 13:35:35.187] FROM CELLE c\n[2025-09-19 13:35:35.187] LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella\n[2025-09-19 13:35:35.187] GROUP BY c.Scaffale\n[2025-09-19 13:35:35.187] )\n[2025-09-19 13:35:35.187] SELECT\n[2025-09-19 13:35:35.187] ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID,\n[2025-09-19 13:35:35.187] o.Scaffale AS Scaffale,\n[2025-09-19 13:35:35.187] a.IDMagazzino AS MagID,\n[2025-09-19 13:35:35.187] m.Codice AS Magazzino,\n[2025-09-19 13:35:35.187] ISNULL(o2.NPalet,0) AS NPalet,\n[2025-09-19 13:35:35.187] o.CelleTotali AS CelleTotali,\n[2025-09-19 13:35:35.187] ISNULL(o2.CelleOccupate,0) AS CelleOccupate\n[2025-09-19 13:35:35.187] FROM OCC o\n[2025-09-19 13:35:35.187] LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale\n[2025-09-19 13:35:35.187] JOIN dbo.Aree a ON a.ID = :area_id\n[2025-09-19 13:35:35.187] JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino\n[2025-09-19 13:35:35.187] WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> ''\n[2025-09-19 13:35:35.187] ORDER BY o.Scaffale;\n[2025-09-19 13:35:35.187] PARAMS: {'area_id': 1}\n--------------------------------------------------------------------------------\n[2025-09-19 13:35:35.319] PURPOSE: Statistiche Scaffali per Area\n[2025-09-19 13:35:35.319] INFO: END\n[2025-09-19 13:35:35.319] SQL:\n[2025-09-19 13:35:35.319] WITH CELLE AS (\n[2025-09-19 13:35:35.319] SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale\n[2025-09-19 13:35:35.319] FROM dbo.Celle c\n[2025-09-19 13:35:35.319] WHERE c.IDArea = :area_id\n[2025-09-19 13:35:35.319] ),\n[2025-09-19 13:35:35.319] OCC AS (\n[2025-09-19 13:35:35.319] SELECT c.Scaffale, COUNT(*) AS CelleTotali\n[2025-09-19 13:35:35.319] FROM CELLE c\n[2025-09-19 13:35:35.319] GROUP BY c.Scaffale\n[2025-09-19 13:35:35.319] ),\n[2025-09-19 13:35:35.319] OCC2 AS (\n[2025-09-19 13:35:35.319] SELECT c.Scaffale,\n[2025-09-19 13:35:35.319] COUNT(DISTINCT mp.IDCella) AS CelleOccupate,\n[2025-09-19 13:35:35.319] COUNT(mp.ID) AS NPalet\n[2025-09-19 13:35:35.319] FROM CELLE c\n[2025-09-19 13:35:35.319] LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella\n[2025-09-19 13:35:35.319] GROUP BY c.Scaffale\n[2025-09-19 13:35:35.319] )\n[2025-09-19 13:35:35.319] SELECT\n[2025-09-19 13:35:35.319] ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID,\n[2025-09-19 13:35:35.319] o.Scaffale AS Scaffale,\n[2025-09-19 13:35:35.319] a.IDMagazzino AS MagID,\n[2025-09-19 13:35:35.319] m.Codice AS Magazzino,\n[2025-09-19 13:35:35.319] ISNULL(o2.NPalet,0) AS NPalet,\n[2025-09-19 13:35:35.319] o.CelleTotali AS CelleTotali,\n[2025-09-19 13:35:35.319] ISNULL(o2.CelleOccupate,0) AS CelleOccupate\n[2025-09-19 13:35:35.319] FROM OCC o\n[2025-09-19 13:35:35.319] LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale\n[2025-09-19 13:35:35.319] JOIN dbo.Aree a ON a.ID = :area_id\n[2025-09-19 13:35:35.319] JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino\n[2025-09-19 13:35:35.319] WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> ''\n[2025-09-19 13:35:35.319] ORDER BY o.Scaffale;\n[2025-09-19 13:35:35.319] PARAMS: {'area_id': 1}\n[2025-09-19 13:35:35.319] ELAPSED_MS: 131\n--------------------------------------------------------------------------------\n[2025-09-19 13:39:31.959] PURPOSE: Statistiche Scaffali per Area\n[2025-09-19 13:39:31.959] INFO: START\n[2025-09-19 13:39:31.959] SQL:\n[2025-09-19 13:39:31.959] WITH CELLE AS (\n[2025-09-19 13:39:31.959] SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale\n[2025-09-19 13:39:31.959] FROM dbo.Celle c\n[2025-09-19 13:39:31.959] WHERE c.IDArea = :area_id\n[2025-09-19 13:39:31.959] ),\n[2025-09-19 13:39:31.959] OCC AS (\n[2025-09-19 13:39:31.959] SELECT c.Scaffale, COUNT(*) AS CelleTotali\n[2025-09-19 13:39:31.959] FROM CELLE c\n[2025-09-19 13:39:31.959] GROUP BY c.Scaffale\n[2025-09-19 13:39:31.959] ),\n[2025-09-19 13:39:31.959] OCC2 AS (\n[2025-09-19 13:39:31.959] SELECT c.Scaffale,\n[2025-09-19 13:39:31.959] COUNT(DISTINCT mp.IDCella) AS CelleOccupate,\n[2025-09-19 13:39:31.959] COUNT(mp.ID) AS NPalet\n[2025-09-19 13:39:31.959] FROM CELLE c\n[2025-09-19 13:39:31.959] LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella\n[2025-09-19 13:39:31.959] GROUP BY c.Scaffale\n[2025-09-19 13:39:31.959] )\n[2025-09-19 13:39:31.959] SELECT\n[2025-09-19 13:39:31.959] ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID,\n[2025-09-19 13:39:31.959] o.Scaffale AS Scaffale,\n[2025-09-19 13:39:31.959] a.IDMagazzino AS MagID,\n[2025-09-19 13:39:31.959] m.Codice AS Magazzino,\n[2025-09-19 13:39:31.959] ISNULL(o2.NPalet,0) AS NPalet,\n[2025-09-19 13:39:31.959] o.CelleTotali AS CelleTotali,\n[2025-09-19 13:39:31.959] ISNULL(o2.CelleOccupate,0) AS CelleOccupate\n[2025-09-19 13:39:31.959] FROM OCC o\n[2025-09-19 13:39:31.959] LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale\n[2025-09-19 13:39:31.959] JOIN dbo.Aree a ON a.ID = :area_id\n[2025-09-19 13:39:31.959] JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino\n[2025-09-19 13:39:31.959] WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> ''\n[2025-09-19 13:39:31.959] ORDER BY o.Scaffale;\n[2025-09-19 13:39:31.959] PARAMS: {'area_id': 4}\n--------------------------------------------------------------------------------\n[2025-09-19 13:39:32.045] PURPOSE: Statistiche Scaffali per Area\n[2025-09-19 13:39:32.045] INFO: END\n[2025-09-19 13:39:32.045] SQL:\n[2025-09-19 13:39:32.045] WITH CELLE AS (\n[2025-09-19 13:39:32.045] SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale\n[2025-09-19 13:39:32.045] FROM dbo.Celle c\n[2025-09-19 13:39:32.045] WHERE c.IDArea = :area_id\n[2025-09-19 13:39:32.045] ),\n[2025-09-19 13:39:32.045] OCC AS (\n[2025-09-19 13:39:32.045] SELECT c.Scaffale, COUNT(*) AS CelleTotali\n[2025-09-19 13:39:32.045] FROM CELLE c\n[2025-09-19 13:39:32.045] GROUP BY c.Scaffale\n[2025-09-19 13:39:32.045] ),\n[2025-09-19 13:39:32.045] OCC2 AS (\n[2025-09-19 13:39:32.045] SELECT c.Scaffale,\n[2025-09-19 13:39:32.045] COUNT(DISTINCT mp.IDCella) AS CelleOccupate,\n[2025-09-19 13:39:32.045] COUNT(mp.ID) AS NPalet\n[2025-09-19 13:39:32.045] FROM CELLE c\n[2025-09-19 13:39:32.045] LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella\n[2025-09-19 13:39:32.045] GROUP BY c.Scaffale\n[2025-09-19 13:39:32.045] )\n[2025-09-19 13:39:32.045] SELECT\n[2025-09-19 13:39:32.045] ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID,\n[2025-09-19 13:39:32.045] o.Scaffale AS Scaffale,\n[2025-09-19 13:39:32.045] a.IDMagazzino AS MagID,\n[2025-09-19 13:39:32.045] m.Codice AS Magazzino,\n[2025-09-19 13:39:32.045] ISNULL(o2.NPalet,0) AS NPalet,\n[2025-09-19 13:39:32.045] o.CelleTotali AS CelleTotali,\n[2025-09-19 13:39:32.045] ISNULL(o2.CelleOccupate,0) AS CelleOccupate\n[2025-09-19 13:39:32.045] FROM OCC o\n[2025-09-19 13:39:32.045] LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale\n[2025-09-19 13:39:32.045] JOIN dbo.Aree a ON a.ID = :area_id\n[2025-09-19 13:39:32.045] JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino\n[2025-09-19 13:39:32.045] WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> ''\n[2025-09-19 13:39:32.045] ORDER BY o.Scaffale;\n[2025-09-19 13:39:32.045] PARAMS: {'area_id': 4}\n[2025-09-19 13:39:32.045] ELAPSED_MS: 85\n--------------------------------------------------------------------------------\n[2025-09-19 13:39:41.285] PURPOSE: SIMULAZIONE Azzeramento Area (conteggio)\n[2025-09-19 13:39:41.285] INFO: START\n[2025-09-19 13:39:41.285] SQL:\n[2025-09-19 13:39:41.285] SELECT COUNT(*) AS WouldDelete\n[2025-09-19 13:39:41.285] FROM dbo.MagazziniPallet mp\n[2025-09-19 13:39:41.285] JOIN dbo.Celle c ON c.ID = mp.IDCella\n[2025-09-19 13:39:41.285] WHERE c.IDArea = :area_id;\n[2025-09-19 13:39:41.285] PARAMS: {'area_id': 4}\n--------------------------------------------------------------------------------\n[2025-09-19 13:39:41.353] PURPOSE: SIMULAZIONE Azzeramento Area (conteggio)\n[2025-09-19 13:39:41.353] INFO: END\n[2025-09-19 13:39:41.353] SQL:\n[2025-09-19 13:39:41.353] SELECT COUNT(*) AS WouldDelete\n[2025-09-19 13:39:41.353] FROM dbo.MagazziniPallet mp\n[2025-09-19 13:39:41.353] JOIN dbo.Celle c ON c.ID = mp.IDCella\n[2025-09-19 13:39:41.353] WHERE c.IDArea = :area_id;\n[2025-09-19 13:39:41.353] PARAMS: {'area_id': 4}\n[2025-09-19 13:39:41.353] ELAPSED_MS: 67\n--------------------------------------------------------------------------------\n+------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-19 14:05:18.622 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL: | +| SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); | +| | +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-19 14:05:18.663 | +| PURPOSE : Lista Aree | +| | +| SQL: | +| SELECT | +| a.ID AS AreaID, | +| a.Descrizione AS AreaNome, | +| a.IDMagazzino AS MagID, | +| m.Codice AS Magazzino | +| FROM dbo.Aree a | +| JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino | +| WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' | +| ORDER BY m.Codice, a.Descrizione; | +| | +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-19 14:05:18.668 | +| PURPOSE : Lista Aree | +| ELAPSED : 3 ms | +| | +| SQL: | +| SELECT | +| a.ID AS AreaID, | +| a.Descrizione AS AreaNome, | +| a.IDMagazzino AS MagID, | +| m.Codice AS Magazzino | +| FROM dbo.Aree a | +| JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino | +| WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' | +| ORDER BY m.Codice, a.Descrizione; | +| | +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-19 14:05:18.675 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL: | +| WITH CELLE AS ( | +| SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale | +| FROM dbo.Celle c | +| WHERE c.IDArea = :area_id | +| ), | +| OCC AS ( | +| SELECT c.Scaffale, COUNT(*) AS CelleTotali | +| FROM CELLE c | +| GROUP BY c.Scaffale | +| ), | +| OCC2 AS ( | +| SELECT c.Scaffale, | +| COUNT(DISTINCT mp.IDCella) AS CelleOccupate, | +| COUNT(mp.ID) AS NPalet | +| FROM CELLE c | +| LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella | +| GROUP BY c.Scaffale | +| ) | +| SELECT | +| ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, | +| o.Scaffale AS Scaffale, | +| a.IDMagazzino AS MagID, | +| m.Codice AS Magazzino, | +| ISNULL(o2.NPalet,0) AS NPalet, | +| o.CelleTotali AS CelleTotali, | +| ISNULL(o2.CelleOccupate,0) AS CelleOccupate | +| FROM OCC o | +| LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale | +| JOIN dbo.Aree a ON a.ID = :area_id | +| JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino | +| WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' | +| ORDER BY o.Scaffale; | +| | +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-19 14:05:18.801 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 125 ms | +| | +| SQL: | +| WITH CELLE AS ( | +| SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale | +| FROM dbo.Celle c | +| WHERE c.IDArea = :area_id | +| ), | +| OCC AS ( | +| SELECT c.Scaffale, COUNT(*) AS CelleTotali | +| FROM CELLE c | +| GROUP BY c.Scaffale | +| ), | +| OCC2 AS ( | +| SELECT c.Scaffale, | +| COUNT(DISTINCT mp.IDCella) AS CelleOccupate, | +| COUNT(mp.ID) AS NPalet | +| FROM CELLE c | +| LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella | +| GROUP BY c.Scaffale | +| ) | +| SELECT | +| ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, | +| o.Scaffale AS Scaffale, | +| a.IDMagazzino AS MagID, | +| m.Codice AS Magazzino, | +| ISNULL(o2.NPalet,0) AS NPalet, | +| o.CelleTotali AS CelleTotali, | +| ISNULL(o2.CelleOccupate,0) AS CelleOccupate | +| FROM OCC o | +| LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale | +| JOIN dbo.Aree a ON a.ID = :area_id | +| JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino | +| WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' | +| ORDER BY o.Scaffale; | +| | +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-19 14:05:38.222 | +| PURPOSE : SIMULAZIONE Azzeramento Area (conteggio) | +| | +| SQL: | +| SELECT COUNT(*) AS WouldDelete | +| FROM dbo.MagazziniPallet mp | +| JOIN dbo.Celle c ON c.ID = mp.IDCella | +| WHERE c.IDArea = :area_id; | +| | +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-19 14:05:38.286 | +| PURPOSE : SIMULAZIONE Azzeramento Area (conteggio) | +| ELAPSED : 63 ms | +| | +| SQL: | +| SELECT COUNT(*) AS WouldDelete | +| FROM dbo.MagazziniPallet mp | +| JOIN dbo.Celle c ON c.ID = mp.IDCella | +| WHERE c.IDArea = :area_id; | +| | +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-19 15:57:33.565 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:16:04.836 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:16:13.102 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:16:13.103 | +| PURPOSE : Lista Aree | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:20:14.522 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:20:18.641 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:20:18.642 | +| PURPOSE : Lista Aree | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:20:47.270 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:20:57.020 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:20:57.021 | +| PURPOSE : Lista Aree | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:23:52.920 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:23:54.812 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:23:54.813 | +| PURPOSE : Lista Aree | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:38:09.469 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:38:11.042 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-29 19:38:11.043 | +| PURPOSE : Lista Aree | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-30 11:33:49.156 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-30 11:34:01.696 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-30 11:34:16.430 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-30 11:34:16.431 | +| PURPOSE : Lista Aree | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-30 11:34:17.646 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-09-30 11:34:17.647 | +| PURPOSE : Lista Aree | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE a.DelDataOra IS NULL OR a.DelDataOra = '19000101' +ORDER BY m.Codice, a.Descrizione; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:38:38.587 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:38:38.624 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:38:38.630 | +| PURPOSE : Lista Aree | +| ELAPSED : 5 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:38:38.718 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:38:38.804 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 85 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:04.697 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 4 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:04.749 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 51 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 4 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:08.033 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 11 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:08.686 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 652 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 11 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:12.809 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 11 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:12.873 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 63 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 11 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:16.609 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 13 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:16.664 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 54 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 13 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:19.066 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 14 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:19.112 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 45 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 14 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:21.897 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 12 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:21.939 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 40 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 12 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:37.725 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 13 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:37.772 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 46 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 13 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:41.282 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:39:41.345 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 63 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:44:05.736 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:44:05.806 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:44:05.809 | +| PURPOSE : Lista Aree | +| ELAPSED : 3 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:44:05.812 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:44:05.889 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 77 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:46:21.269 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:46:21.359 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:46:21.363 | +| PURPOSE : Lista Aree | +| ELAPSED : 3 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:46:21.448 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:46:21.526 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 77 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:46:37.304 | +| PURPOSE : SIMULAZIONE Azzeramento Scaffale (conteggio) | +| | +| SQL (copy/paste below): | +| | +SELECT COUNT(*) AS WouldDelete +FROM dbo.MagazziniPallet mp +JOIN dbo.Celle c ON c.ID = mp.IDCella +WHERE c.IDArea = :area_id AND CAST([Corsia] AS NVARCHAR(50)) = :scaffale; + +| PARAMS: | +| { | +| "area_id": 1, | +| "scaffale": " 1A" | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:46:37.355 | +| PURPOSE : SIMULAZIONE Azzeramento Scaffale (conteggio) | +| ELAPSED : 50 ms | +| | +| SQL (copy/paste below): | +| | +SELECT COUNT(*) AS WouldDelete +FROM dbo.MagazziniPallet mp +JOIN dbo.Celle c ON c.ID = mp.IDCella +WHERE c.IDArea = :area_id AND CAST([Corsia] AS NVARCHAR(50)) = :scaffale; + +| PARAMS: | +| { | +| "area_id": 1, | +| "scaffale": " 1A" | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:46:45.607 | +| PURPOSE : SIMULAZIONE Azzeramento Scaffale (conteggio) | +| | +| SQL (copy/paste below): | +| | +SELECT COUNT(*) AS WouldDelete +FROM dbo.MagazziniPallet mp +JOIN dbo.Celle c ON c.ID = mp.IDCella +WHERE c.IDArea = :area_id AND CAST([Corsia] AS NVARCHAR(50)) = :scaffale; + +| PARAMS: | +| { | +| "area_id": 1, | +| "scaffale": " 1A" | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:46:45.658 | +| PURPOSE : SIMULAZIONE Azzeramento Scaffale (conteggio) | +| ELAPSED : 51 ms | +| | +| SQL (copy/paste below): | +| | +SELECT COUNT(*) AS WouldDelete +FROM dbo.MagazziniPallet mp +JOIN dbo.Celle c ON c.ID = mp.IDCella +WHERE c.IDArea = :area_id AND CAST([Corsia] AS NVARCHAR(50)) = :scaffale; + +| PARAMS: | +| { | +| "area_id": 1, | +| "scaffale": " 1A" | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:56:37.640 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:56:37.706 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:56:37.711 | +| PURPOSE : Lista Aree | +| ELAPSED : 3 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:56:37.800 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:56:37.880 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 79 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:09.968 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:10.044 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:10.051 | +| PURPOSE : Lista Aree | +| ELAPSED : 6 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:10.138 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:10.221 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 82 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:40.974 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:41.012 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:41.017 | +| PURPOSE : Lista Aree | +| ELAPSED : 4 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:41.022 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:57:41.089 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 66 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:58:05.716 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:58:05.807 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 12:58:05.812 | +| PURPOSE : Lista Aree | +| ELAPSED : 4 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 17:11:06.431 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 17:11:06.462 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 17:11:06.468 | +| PURPOSE : Lista Aree | +| ELAPSED : 5 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 17:11:06.471 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-01 17:11:06.555 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 83 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:07.101 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:07.151 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:07.157 | +| PURPOSE : Lista Aree | +| ELAPSED : 5 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:07.159 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:07.239 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 79 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:17.431 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:19.489 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:19.495 | +| PURPOSE : Lista Aree | +| ELAPSED : 5 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:19.500 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | +SELECT TOP 0 1 AS ID, '' AS Scaffale, 0 AS MagID, '' AS Magazzino, 0 AS NPalet, 0 AS CelleTotali, 0 AS CelleOccupate + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:19.503 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 2 ms | +| | +| SQL (copy/paste below): | +| | +SELECT TOP 0 1 AS ID, '' AS Scaffale, 0 AS MagID, '' AS Magazzino, 0 AS NPalet, 0 AS CelleTotali, 0 AS CelleOccupate + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:23.854 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:23.861 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:23.863 | +| PURPOSE : Lista Aree | +| ELAPSED : 1 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:23.869 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-03 20:49:23.930 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 60 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:48:50.855 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:48:50.925 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:48:50.935 | +| PURPOSE : Lista Aree | +| ELAPSED : 9 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:48:50.952 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:48:51.050 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 98 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:49:34.467 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:49:37.275 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:49:37.284 | +| PURPOSE : Lista Aree | +| ELAPSED : 8 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:49:45.245 | +| PURPOSE : Rilevamento colonne Celle | +| ELAPSED : 0 ms | +| | +| SQL (copy/paste below): | +| | +SELECT LOWER(name) FROM sys.columns WHERE object_id = OBJECT_ID('dbo.Celle'); + +| PARAMS: | +| {} | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:49:45.324 | +| PURPOSE : Lista Aree | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:49:45.327 | +| PURPOSE : Lista Aree | +| ELAPSED : 2 ms | +| | +| SQL (copy/paste below): | +| | +SELECT a.ID AS AreaID, a.Descrizione AS AreaNome, a.IDMagazzino AS MagID, m.Codice AS Magazzino +FROM dbo.Aree a +JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino +WHERE len(trim(a.Descrizione)) = 2; + +| PARAMS: | +| {} | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:49:45.335 | +| PURPOSE : Statistiche Scaffali per Area | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| START | +| | ++------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +| TIMESTAMP : 2025-10-04 11:49:45.412 | +| PURPOSE : Statistiche Scaffali per Area | +| ELAPSED : 76 ms | +| | +| SQL (copy/paste below): | +| | + WITH CELLE AS ( + SELECT c.ID AS IDCella, c.IDArea, CAST([Corsia] AS NVARCHAR(50)) AS Scaffale + FROM dbo.Celle c + WHERE c.IDArea = :area_id + ), + OCC AS ( + SELECT c.Scaffale, COUNT(*) AS CelleTotali + FROM CELLE c + GROUP BY c.Scaffale + ), + OCC2 AS ( + SELECT c.Scaffale, + COUNT(DISTINCT mp.IDCella) AS CelleOccupate, + COUNT(mp.ID) AS NPalet + FROM CELLE c + LEFT JOIN dbo.MagazziniPallet mp ON mp.IDCella = c.IDCella + GROUP BY c.Scaffale + ) + SELECT + ROW_NUMBER() OVER (ORDER BY o.Scaffale) AS ID, + o.Scaffale AS Scaffale, + a.IDMagazzino AS MagID, + m.Codice AS Magazzino, + ISNULL(o2.NPalet,0) AS NPalet, + o.CelleTotali AS CelleTotali, + ISNULL(o2.CelleOccupate,0) AS CelleOccupate + FROM OCC o + LEFT JOIN OCC2 o2 ON o2.Scaffale = o.Scaffale + JOIN dbo.Aree a ON a.ID = :area_id + JOIN dbo.Magazzini m ON m.ID = a.IDMagazzino + WHERE o.Scaffale IS NOT NULL AND LTRIM(RTRIM(o.Scaffale)) <> '' + ORDER BY o.Scaffale; + + +| PARAMS: | +| { | +| "area_id": 1 | +| } | +| | +| COMMENT: | +| END | +| | ++------------------------------------------------------------------------------------------------------------+