From 08ac7201c08faf0b26056085070df14ca1d67041 Mon Sep 17 00:00:00 2001 From: "holger.trampe" Date: Thu, 14 Jan 2021 18:10:55 +0100 Subject: [PATCH] Bugs und Zeiterfassungsprobleme fix --- cloud/views.py | 2 +- dump.rdb | Bin 164854 -> 14615 bytes timemanagement/views.py | 1 - users/templates/users/searchres.html | 10 +- users/urls.py | 2 +- users/views.py | 436 +++++++++++++++++++++++---- 6 files changed, 395 insertions(+), 56 deletions(-) diff --git a/cloud/views.py b/cloud/views.py index d7f30d8..3ff9352 100644 --- a/cloud/views.py +++ b/cloud/views.py @@ -251,7 +251,7 @@ def adddirbyajax(request, parent): # VALIDATE FILE-TYPE file_ext_arr = request.FILES['uploadedfile'].name.split(".") file_ext = file_ext_arr[len(file_ext_arr)-1] - allowed_types = ["txt", "TXT", "png", "PNG", "jpeg", "JPEG", "jpg", "JPG", "PDF", "pdf", "csv", "CSV", "DOC", "doc", "DOCX", "docx", "ODT", "odt", "PPT", "ppt", "PPTX", "pptx", "XLS", "xls", "XLSX", "xlsx", "mov", "MOV", "SVG", "svg", "ZIP", "zip", "RAR", "rar", "EPS", "eps", "MP3", "mp3", "WAV", "wav", "avi", "AVI", "FLV", "flv", "MP4", "mp4", "PAGES", "pages", "NUMBERS", "numbers", "ics", "ICS"] + allowed_types = ["txt", "TXT", "png", "PNG", "jpeg", "JPEG", "jpg", "JPG", "PDF", "pdf", "csv", "CSV", "DOC", "doc", "DOCX", "docx", "ODT", "odt", "PPT", "ppt", "PPTX", "pptx", "XLS", "xls", "XLSX", "xlsx", "xlsm", "XLSM", "mov", "MOV", "SVG", "svg", "ZIP", "zip", "RAR", "rar", "EPS", "eps", "MP3", "mp3", "WAV", "wav", "avi", "AVI", "FLV", "flv", "MP4", "mp4", "PAGES", "pages", "NUMBERS", "numbers", "ics", "ICS"] file_ok = False for t in allowed_types: diff --git a/dump.rdb b/dump.rdb index 47941652c2e9f86fc8b27f2b2ae76e8fad7c0cf8..1e8d4269fd023e11a2ba2be51eaf0ab8f3bc5817 100644 GIT binary patch literal 14615 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 literal 164854 zcmeF42b5J+vi_S6bd#eXD)c=aKt$!_pd+^6hyv;;m;;`Os04|M89_xE6-Ba$7{EYK zj9?BZB04IF0hJ_(VGJk&2L8X@*k1Zh zM;_BtmStyqok3yHckn^O!a;fF!SccO_PRU&1F!Fp!OxX#&+~`$?H9h#s@>M!+Y5#c z4ugaGh5cT*vTKX1?e*OO(LnFCZg7CSlU$cHHJH71mpIf|p>Y8D-va<3Hb_e(A zJ9uE|_l^4c2M3PjYJnZPs%-1J899pXM4A)mhU~eT%t~|Zs^wUr=CYH zo%!w+Bkvw^@xbtrp#uYVNZ6a78XWd7^uyj4^c@z?@7-J2@9m%K_U|8F(7X4o?{_Qz zvBGq}R=51;9Np6FAhB=LNS1XYavVLfg= zX)2~?TWaE}Y~R-To0h)sI+muoh7+2)>8qX+hK}b%i5GHJMUAYn%bPq|=hu}-l#Q-; z)w-dzmjC$D8CIJ`RXy469&Fri50>t^${%ZY%i)EWFK5T;jelFteXD-C^}9otykR%r z|Fw)QXIlTd<;&Um?R#x}YyJUSuQ{rCR_h5>E$P4Q+n=!YktcS3`&%|$b+dfQ)^$DZ zduG3?p6oCA_A?({@Y`}ULwa=e>7{RLC!cmh#+LKdiu=o#v-8_OblB+J!V|V^ywnxkxZ~ON9wcGmm&Trr1yW*_vmwxe)eaWnaRXy2X^6l>(xutwLKew#fJ=?Y&>AvS% zhN|NUabUWpI=-oCx`T&Sq=K^1euGzz{O+5k$L6noyr8-dlJ<9^P&Q>fAT~vY9;uNN z+LmGaT4eZvY5PXfpC0m^-KnIoUe+%&bB@l~a+3aZGj_Dk6Y~MdH+orTTapeuAF>W*zdYt+gsoIQc=d1lXQSz4&D65X}8^1*lGP! zZ8Nr<3I|v=`lE*0r(E-GibojfrkJ^2ldtq%64Kt0gYtKHbP%>LeC3zMYG+&3_aJdG~ElFATlI7 zR4g^pJ=Jk6-Lq`R_Z3A|6eo;y!?CP_o6o&`$1fnYI5s^~Q9aEHWyRNZ$9GKM1vMJ3 z#(%7+@~jPaUKZD;Wk<5+>flaA*8RxvG|w~xTjvK6d9qaN1^Ad zVW^(4xwzcs&v$pdd_&cnS3Tm~U3QwK1&XDFR%Bw(Qb?3^#ZdX=ieXx=Z%B$4DYgp6 zH!NS*OwZK=T{WY~l|$Px0>AYGzXAK??oDgcw!BCemKBkk={{Lm6x#l> z9lrs_7&aX@bhOa-ebcaXB~m?~O`+<7TFG^$wW%p?5GtNSVn_Z* zX3EwzUCvpg_!e+u!≦6xXK3hcQ^ICS#3-x{hHQfn%GN%3inpy}!65w$0GBWFLbytZzIf^1cSrGZ2=7zo`yOAzq#8uc!o~3%W%wPMV>hkwi=wCC`OvJUR z;9RZ9k}VJa;Dw&W24nxffOkIt9MGrL_Xz3~%I8zs=Pm?d2 zGOkfvo0b`dJf>vUNbY%G^<~>sa7}>tP|-X$2oyG-%NsM`E+n75?P$7%hjDc~a9!Ia z02r_ofd{YQEbQ~#8d7cdI6$+>#JGK{aS_#{RZfd5j>Q~Kgx;U;)N3~$pd;lCq4WhGUh^^`o z^EA)4gH=CFdpWMnfM{$)vLnl`rU#nkx)#(Q!7lW52d{s_jYr3}sjGNAhh1ZPitcfc z*tPg$+m$tw$Z0QmwN`AK4t^^Bs6f#Z_%^ zug<#-9M99DAh3a9vf=ErcI}ICZE|E?(=#K_WaGLhm`7+c9k^aY^9X@J65B8XN5+vIdDo$_ZQ|Bc({dEwQ!LOvK7?a#L|{Cd2o<=u ze!StwyqG=&s1dS-EKiAC9faxxd>*!H1PrqS%erIngv&`jga&ZXGjgX@$1C}9B?8wsi?|1=`nAZ`$ zG-ANQ6q_#F&IkeLCb-q-tc8Y+19Hs34=uKjl4rmw*`IfsG%l`9 zMU!2{!;a%a69fU3kDbLzNKh}=fY_y zcH5ryE{eNO+psL099$0Z+=?8}cPxAzTNIkh@!VsZ{(X2{n<2qMkCXrxicNzo%L9$@ z8=z%ylzrp)yg?~86^JUIt!Ib$3dM?eJ{F-HhS=OtPLczh=f&Zj1XDzkV1hs+ipd}y z{(m`mW7N5EZQ5WD-eZKn2iG}@0}j`C1qy@?h{Wvw$@o5TZOVLG3j~6n4|QAhJ;$=i zU1dLtLf>?PcV76LAJ?X%!Y4QHH^rt5hz!)o4ozYV zEG5|0Qi+hlMUW0y5~tF!Le~M>K^DQ{g7YARA{dcSCYQYR?nNi3*bIUHRusbf@-0P` z%hKT1NF_B{u(y_^yK)3+<$B~re7eXDLGf%(7#t(CEM@$`=N})}rm7f%q9CfXKLS~| z9mgj{vi$%&?^xzl%l>w3T$^BT%~B#ohMd!7kt5*dR39fAnlMb!zeY6g9@nN5sc<+T zSOet1I|VF(?-f~O@w}e!>Yk?@6W1mV4Gs*fW4dq`E+@k?RXO6rfok!*lU8d-r`RNq zQ~(7QM7@Rkb;-&jsH4Dw_w*Ihk)ZX7PNdpMF~r_?%ejWgCKHi$Q;DALd61c6Gl1l` zJecDk630bA0zRv22O>N`1xpU07Ydb_4)F;613+X`vB6*)E!olB?D0!-D`Rh%LI9vm zSk-tuQ*kZd6g~%7O+CRfS*N4m)bIx)V6mfo6Z#Iml9&xqruA*Hb#aPK6_yZKNtKh+ z;TdG>awv##LO91;_9UBwfP6-UXW)}Vve{6T;=iB=zydueYkug}<190zz|*z*tH_IzBMhQfmYj6^a>w!n6B zd1wwFLaNH<#1(-093?PYZ0=@{Ax*kR#WS|3) z89JPQW9|EBr^#_`MlkmQeu(k~8zZ#IK5(J1VS%P-5Yg{6n>R78O$;I&;Wf9 zxg>=i-`d2bXqv`%a`mCP!7XuZvU3zlIHE*Dm^2O74cQ2gL4n1Y2$f?yK0Y?ZrY4RL zWE?Ko*Jb=U1S)xp>k17PK~=&F@jgicLzWei5^{WjYY`j7Cz~;H3s1i|#inh_29h#j z2DpF|LzqbdP&VSUJ99R6c`vIA?u9sn`$K%wD{D_FIEicRQFT!%pFrXb`1 z+SK429vnx`CekIrrV0T@6yT2d)-D9IY_k;vnFVSuDLA`ricJf~0G13Yh6Ih62FS1s z#fJG6stI3}*z1O7S!4=e8y}4tX(&||i+T%(PL`W3_`X$&O>}I~g*=j_C>(3{9~unL z_Hb#YqXw2_1wP>eG62Sc%9?>QbVxVgaq(BSA-4M+oGv+=Q*EZx!=%%x^qzLYXDK#Wk3jyWkk#-$ z6^HT|_)0iEw!LXdp`lUk;tvqL=&BWv8nIRIr5qC5(SijR7q3pS36+O?VehdYsbUM> z*-b1nP#6}qRnu@(5Pu1yFls#^## zsL|_i^pM{IJ7_+*0Q79G-aI+BP5gm@2L$(_?WJ()Q5PeW>d;j{A>Bwk;>WfLIS-GA z|EC}$xC82Nkqo?oMNvb(*zrfmv2DUE1%zVCeB{~|Q~)J!C_+>o2#OWcz2lY-hsAxL zP&G;jpNLcB!$7A+WOXvY6Yw12Z`QS#+dsu7E&^@|AqH5MGz|xetAx3vE^a8Kn3DK9 z^v z9ymV5Cc!Ks@s$Hq);i>~!*RCUka!L=#4|{w5X4@}x&la(^dW8#SqEH;%9BLaJ&XGH zNU^C?6cMliW`{H)gaUI3${GboO4+`pN+CoqsR8blB#vqVah_$UCb|p-O@n>H7Wdg& zm7g7U4EEXyssD=-Gc{Q`r0UAngGkb3UlNqO?~4SE18)hEI6(R!XiJ&$v|}`V=JZBc zF>T_41M0i*h}2=>0QfQ<6p6*_dff)}7(RF((uLO!Hc(fbrq_;ZllaDGhiQP5LeXq?xvb-vHI{m4yU>H;Lo4i7DVcb$R&t=D0Qq=oDTNhj1dnq|^_{ zC6RMbmhwn!yngq!h;38h+yJ`a&^h1^xt(BIp;!r0Y^}gq{>_0KD`3Po0azG1)`laZZb;N1Ibd6oK;W*tAo#Rh+b84N zbSb@|l*7p)Gofk-sf7kXNAU#*?ps<;o#3&!Hc4KI>M#$;*r*pT9gh6- z{nH+bYm=fIsfJ+qNg}{t4m1!;CMIhU@7KKc!|XY6ZF+b*oCU!|JTX-Yj#LQu067sU zoQ7APF1bIhO+^UR0!|H%6~H8jO4WnzAb?P(vy2w!F1tIfO%S(E=0;8gKk0}P2J{+v z37H4fm98mYO}##@&B)Z$z$N+D5DPehSHvJOfj3Oi!B$%@zV_O02ppsJ9WNaj*QP^d7p$zpCE-79*ev2Hn*rVzpJKZuM;&r{T$>QQ zs5f!(C{73?oJ|E<$rg}IBmH)IPP*?Oacv6XLx;3B(f<+D(C>h*s4v-Mok$nGS)UE) z8rLQ~Pz2hBvLw+%RS1nq#uULNQw;+It^aBBesOIgQ5HHefu`V-!A^+ch)p)hr^*Sl zAHQlxtGG5P!U+Bj!~hp$^KNBbwy5!=iIM|HaR)rMy-8e~qPoXUq=X$Qe0|Nf0@y%K zCiD$?Q?SoZgJauNDf1wHf}JHJfU%?QrQ4jWh*~j)R{5Qdtzz3mo~0nW!++pI4AfB( zN7E8qJ@R8!(T{7lv~m1rSKujZ=rnYIFiognZ5R>i`t%)AS9)>t)v;|Vo<->s=711K z&mx}*P+~#BqG1N>YhGWwe%y6}mrWOnSn|Rd zJ96W$Q}CW7*N~YwdALc+D?kQBC&&dt8xNw_nf%vB)r26B8QM^&43C-s|kxknpjTJYx>YyLwBSo_S54!O0ZB2rbZ;@b5TTr zZc=a`#1AABLAz+__P92wGs6kv=xquXU~LzufLlhi8o>nF-u#!3k8P7;oE6a$9U_eq zbs3PD$c$hyU;v>50p(uANz_={K3{H2Qy z`Y^6did;OUEh7zKf07haM@FHIHU(wA<7vZYzyDfXn;=;jI(TmKOd)y~q$|}@Dua9| znu*SP=IfW^+N7(T%%5+MbAzX~J(v#43IT^6H?IV@b?*CoT$|``LcB--NkgsN1uvnH z2>3oKq?=xwtk(dI{kL#ZMiUA|<*t@D22|tT+hG9Or;855=|#nipI@+!MSF zj)`2`45{-7G6;P3&8*sUQfvl9R0u9~(TJVc$5aNOb*Y;~^fjOol8lH<0P-JYGBpP3 zkZ3z##!$6D!w^C@E-9Q4*Cw0~3;-#HU^^k_g}4to7R@Fms6`xoj-46+;vhJ zhV?T;sB}0MfH6cC-5{`6ykQ8#m3JRK786SieKW2l&kjtoks1U6_44iZ&PGwfE{ zabSu~;SErx5yzmUh}=RxhoV9b4VT^G&^Z`TH>ACVLJeHH3FS+PQ8!p4fE--ct>mQ> zQ*4S}E^1gPQ)szE0>Y-WiQ$yxpydKXmsl{A0O=sC1^g_oh)fx#!PG=iEi!&Oz^-8wJ9D& z>yJHLCFDPHp-Ot&5dtdm|~MIH+r=w zL&3q5oKkFo;UeflO+ZX3nnbw_C}SY(5y>219Tt$tPO1s%3W%8Sb-j5hHfi5OAWEAK z@fK>A_eCnjH==Teic~iw_88+l2y=?SwB=Y#up&q#sGPwv&+fJVaqm?AMz}B6#%qhn z2wlcG4nzf&Fu}qR!bldn5IRvPr=kOdtEZ$d+RzMH^f&_g&idsEC$3G3Z`4Tz_p2D9 zVCxD63py^+BaW6SpLAkdGsPx-mehVJ;6QB)$p$}8F!ad404AE&ve5Y9N z!dbvhqx9ww(DgFb?{HvTn>bARY(T$=&?7D6Ty zK!j4C#6=+#RC+Qqg>=}2(&l%VjRs1wAgm(iSR91=M7iHmoX# zG)3OZX&23o0@6cIgBIu;LB45D?tFi7Y@38$;oM9@8eWCo(|rs|g>%|BCrXqNR%_ z61J$L{B!ed3**|Pz9}?sY#~wuk!c9g1SdG4lacopZQJ_DlW}bda112oyNizv#PR4} zWUC4$2f2rF*~7QZi*1t(hRsePPUz<$!6+J`pCRiK&B2lL(cF!5?Q^ zKn&UJ)T0rS$Uk&@_4br?rnQL?GA#s6Kqb)%OnnpkBK-i4XraCEj`7pt+5~0d)6n;@ znP4kvibjS6Cq#QKE&Z<7eZ&1z2m(Cm3sa4=0sQK&%^wWx)do0qPi64xei z$6_V|`dW(ahyhVolFGt>0Z2uILGwosniSV25t^8edXYo}k&l7TQ>YXZkf?70{m#C9 z=ES%*W#K((X5eEYeS@wNJ>en>5=l9y^48}^j)`lNHQ~1qwlg%02?;0z$c-6gVAH~Z z+)%wRcjWN6HYv&A=0qzr0%kZ2cx2JY6%kHxdx6rq(`7^A+Vnsu(1-z=1ArgL12n0E zMtu%g2ne2h#}EDE+62o6XhVczS7>;s^iV8yMDd+`6M4`p@42yUT9k%E;FAG{1e_SQ z=w2jOM9L%pWt4sUFXzQwr^~`ng21MLZHVj4EFf(pYFPL>AmfxLb{rSirqD4`#wLFk z&FNrNAU)*{hIgPmqZ4cTrnyJQwTW68w?y>x$Tz5&2+T?0hn6Ht@#rJ(ee=FUNeZp?Zefplhs3o>GYfm~*r?z`gd_9-@* zp}-sG+|fJ=v?g|uxDpijCnzb)kdVKN0s>Mq*2%79o06o^BNrfILHa$a&u48@Y??H1 zv55t6f#}08I3$;3h0w4ep2Nf@H9q)lPy>F65(lk9LT7KFTw|JuJG1NAC2?)K$mtB0 zjrg56Dbq2)9wkY|1;PgV*1y}mQykZ(#xxmr4s05G2|^yN5ls$Alo=@lDm72(yiSU1 zQ(=Fj(ZjuwJdzW#m#BF7l>JD<$fM6*(Yr9NO|Z5A#Uj?;N_pmsur z4Oyj2i0j#)l(E@I%qS524_;358Dt5VaGX(_8#hR?i8P*LNZG!eFD3y-g-l4G!3?w+ zs=h>oMCD1IK~GKjo)=J7W10x=39O|?+s5Xm*aYpab0&HFzn-!i8mVwxSMR*$z zAp_+I3a|>qr@%|_d%!k<9*~4;$9yn%95JFQKTSki-m+n@%GWZPk~3(Z2jO;olB ziqCYO-w@X(+Rw=3-I5&=)~QEhAN}h=1ama!7H&T zSv5(aj7&e!yIS2ojB67w$@-X|1cQtFr|C+i5nk8Wr-+(VdH8jAeGu0s;xDGOqOT_# z6n)SX`Un9O%0;$FRVw$iZSSYp1h23&X_}<31kD~D2r?ziNH`xMM)xF|!yr$gKaqbi zlR_Zoh(iG+CDP;j@|1h##I;GGkn%IlISfmI$8v}-_z?Qpc&{*d!Sh3UJs8&}t#-m? zhz4ukD`yg-$zj+B@&R5#q`oN+dLXV%*agZRbXCy##5gYG;fU6BdZ7*KXyBzQR;;-{ zwoSkyx_pvWFfEt{IO{`+ktmaZYp#2#mv>)Wnei&l*^fiMVe)Kq2N z;%4{8wMjPuIg3FyLmh!iJeY*-MQxWHK}c_A<}bTDu1$)L_+U_+)ef zu$cHzwgMWaz<0}my z5&C4P0KhGv6m}UL68RJIm){)MCc<{eIS5qtI^T%4Y5=3?tVYd2>DYPqm&G^5wJGqX zic}5#23Rq4C=LkP0tF=Fjp#yr3{*SF8qtV&qLjj$eRk!-+_*M1WGirM09$aK$TgS-K~Bqn4gsD`@300p=ft%M zIxtxsBsMx0qA&w8=<6}b`Ot;JVm+7JwN_l4q%vq>P)<`x6aksq7QT=21d}UBaNG{h z{rlI~D&u6CaYr;nY9tCkK#&&73M!Fgo-`f6LrY+L@)%MH5?b;OG4FwCX|MytVenA6 zY*~vJQ)~i$(2I(}ccNVdwyV6_3Rl58=xT{1Cc*KI;HRh>5q_vjioSQ$H>CMIzx8~U zH8sVi=+7siK>k8)S3C?I6ohgFHbOD)yAs3g_-9xkHUOuSkbwi?fAD-j2ur`<)(a=3 z*hIe$S%kkMdw~$JILl(5nh0M!fNV%`oR9?gOg0qEzr#5~UW$aCHIR8L1Lrjw9M>ki zEC~V8Oi0qc&&f zKR>QbgfToK?+)n2UZ-k;>lDLzU zZ=w)jW{&8Z1uhCkz2%pE>%_H5DV<6>8V3Qn5$>Ro0Ns*E!TN*B!;V{zE{JQB5K&&z zVsafm8GZ>~jJ7)k)XdzYNLlfDZfu(ncWhBXZ-AH~N^mV2-;-P$mxi8X(zV~zj=N3@ zCJ}QB0x?$+{U`iCU7LI#Tt8!;wD8V59*=Dk9*6O7(2gh)=))7>izZ*P28c|&lzPg9 z{Ma_jWuz#l$UEpmVHPO7nwU+?2v^EsZggdr%kttry9(P68!EIxkQY#)s40+8!-}EK zU|7Qpqh4-Yn+Qq;5e!D4SsZBsX*bCS2p{pTjZ);8ryA$PwF$WpkX?}>h7ij_{0jku z7?x4Cf_-+5{P2limsF0MY0o?K0ySuQw&~;%$R0Qi$|0x<0Vt}y*E>!6DXvXoog9FZ zK?&tqF`pWdCQen*%9Jg}xUIIwwTViGQ7G_$Vons*Eink3`Uh>@RL~)9KmR&sYh0T^ zI7H(xb7*G)0944C>;kJw5^M1q!mRaeH^;TfOcffsXi`Q>Nl>Ed!O%U3HsTyvo$6gR z{=2W^+GM&7{UH$EG{=EMsKpCD6;_1lX2{vxzZok1sNYGZSarxZi;IYXTbyr+9brd5Iz+HX+V@DT-4KPd{FNgKW1%Qo3tvT=|FNr zQ4j6{#U|~C&^OegU4tRl?QYodT3nm#8pvc6cnpz2D7td5{6Gxcv&6s=B=pX; zCk$K=*QQGmf?-LBzBxx|WZ?gZ>zpO#JutdJopScVd2wx`I>Zo-rIfVAmJ;1!2yQ4I zibiZ*zM;p@55%>};6t99`F^yWi1Dtret><7gpPNe9S;<(ez#H1ZDgpLlR zU)0Y>$F+%^9h#pC6Mh}t1(IagMWJA05F0tCGe=!`bzGYiWkNAF1W-rim>7qqSIB^= zsgdER=5b#iKRB*UxMN!5%DbP*u<1FYEtLI4@tI;0s)42Nwi^)FCi9mq=6jIDU;=>% zt}ZgE%aGHH3avYP?A8n7+N2Mdw1(L-Vul-u5y=j@hb_`V(tBHed)u}su1#Je^Z-Nz z1tj7oifi_znE4F*2`b0P!=yw*{IWU%lKmdn{l8~?_ z+DCv-Os#Wh#$j3@%}HB|TNT8$3Dt!b3PKr?5i&|4I4Q^TK5aM}D1X+Ob8=H`QUb>_ zvNagnLdH*!L7R-EfD%4(*}#z)V$aT`O&g#j<|ot5B-BixCuj~Bnp?GZH@;dKf2OsG zB!awCjG2V|K&p$@3Y67rz(RCQ2yw4Fx`^TA~sy?*t5>2t14ENiiC< zc=X;>n<$+qJSSzHg33hV0uLtMC+!YUQRPj} zsE@@oRtdo`K%2R892~}j(RwCEpYh;0CZq`3$<0RYlVXz^J0cb_DvIdJ#4prCLUoJ) zygUn(CHmMz2NKdq1hmj~FuxEED5B`$gAxn|jeThGQ&9ub3wp~al_);6r~PonjBHs3aVVZc3gp|zthGiN5NaAa|Xn< z$sQsQ(tE>`*CuHegN;qm4#zGN%o-XEp$QYpK(gD# ztJe8(ZI;tMOyXde9eIbCNy5ZUA|^T>1BBzvY5C(RDK_CG7`~%Hy0fcAAjErkq!-X@ z2uhe8E%rHHlli37BIyH%P^Fv1X5tugED^fgwtPpAxHh?3i{cTaIE*-3ivALDp$9r1 zAq+-w{?W9V-Q(I6genjTDn#_OaY%U@Cb~o0`q2NHclAN{bc<_~1VfA#B+(YFNl3V0 zR|LyMPX^4I5nOw3?_=WHWUC85M0iE1N~9!1Mi5BQpkfL~t_*u_T9>#sncfIhBS!v; z{7ASO2m#)M4_7NjIbMF~;6vitq>-9KLk^6O!}~FdMx*5ruSmWOe28vuaayWP>i+b# zAO?hn=R4pYkpLog<%^)+;@r44iAiE| z3MCt&F&AWr^qsfQG(yVIG?G2P@B63K$vcf-ifa>I0jdUL;-)g<5d|}**SVs50$k_Ws}Fwu zsT7+WGx7Qr0i!MtzVT5!P;l$0`BG_}OAn#sGKLLfh_BY)gS+=n9 zH$q#E9ucRAf(U+(o6a>NoUGQz_wBULGW?Q0OBz5&AanlAsRw#AJ5#TXkfoT0!kp@wqh`cYGKD{K> zCbRg&$ZBRZ;k!j?j3@#w7NgwQ+%9?s#>`TiWNYF`shARvNM(3ANMfmc4!)zwb8&4l zRaIaykRsh@bis2yAJSZUG0`K4?w+THXa9#y1bz&YRiN+%QB01&+o#78nI$ZUA4;Nn zDr815-<(acVE&1kf^E?pN7eYdiN`#XvQ9{B(p#K3|CjeE${A!v>}I4e94uK9^QGwe z=3kQ|ksabwpzRnY!mw79;QE2nZ+kM;rkGxU%tK7BBTc6(8%>dLk)UB3T21a;;NjU7 ztRH^K5J*830T}bdrF6u<>~Fh`iEERg<3Jg9KjV#vM@-J(n8LG(J5yxHr@r@(86MXr zEm!4d3*j3YU5Hg7Wa6`t)&uj6=%M4k+w^4RJ&&66kDuMZNupH6TatBgewi%A5_!8@kM(hFid+Gy5nBPyN(jwh zGU#XH05dY48|zP=TCygtO^_nff*>tW1u>t2-c^D-83&%4jx^8cHRjF_ zEvZ0*=Ku{M0YqHb1Gs@ExT5(7%j4SQ#NdqR;f7BWJOjnzkUlS@)sWOU(D|=6d@IE! zs%Z8z>K8=kLQEhOP>dZxkHB0p5*SG+-`Ivwo?=KlqHzufFaj|JE{#OL-Or5=iEERC zDky2PEu2#M9VxgH?tTK-0Cz*b`{!efxHik%HbKrDe!(Y`4ATybt7o^0YmuymSB~fy z*Cv~YP(U_HO%K8o85>h1M3O+?kihrfe%HT!T$`jZ#5i0G@r`eUumL~He?S7lWJ%L$ zIcaN2icK+12Q&c7CC2~I?M-sPXf-iv$s;oQ5)24Co7hK^fRLVkE-Jl91^83wi^!T% z_tCm>ZL+~hw!~rN8zCTO_#=ri(tMUI#DG&@-IyQOCUieBnP(84BnDzgG6pgCoN;Nu zRc32^y(CZA+}&mEoVh<9`pjkR-+nlA>3JO>4r-uFKhqx-A;*9 z)_kz|>x*tYGh@q1Ue17Sf*m9DWwQs-4>392EtG>Il-ldH*ww&Z;?TM1_uO2> z$!}(CImye~AAMt=@y?@jC$t&$!sv`G=iZS!Z*|_C$4X0S;;|;Lxb4;GoD-uZqv!9a z?t`TLopjV`(qrwtCU54b{ZHK-E}Hyx#+H-xSjX3SzuxgT_Brp}b4GlgvE?K^*5%tq ze675FhI!GXI~HVYIZ2Oo&~@L`y7SAMKRL{s^GU{*lk`}R^gI2LQ9X}ae95ForeXM~D@wba3|RZO(SWOqyBDS#NhtmXDe@nVLga5+?S2HK)F>O-1Ao&fb@XH6 z+j_f>eq3GBy)fOx$<@UZ3!(O)mv%qtlAp?wrGZ7YTkdYa=9-dM3e(N?xDW*lg)ZJx@>FSboIbwKf;{94&Nw%z6Rl`$P7q82Oc2vy7m5ERCcFt@qzOF9B zL&eP2)g=>~{O73H;_q@0fapa(XH#okTk=4iLy^?Aq_nNVB2p@7QZ&Iz?^OM2(+ z9E>YHSMd8_+~WM)^1-;$mDvz8Yl=J8-DM!}5f>FTt6ymx@A}ebbIXSS7uBw%8&YwT z{~Q9$iz|MuLFL)Qr3LkNojuGK$}OLHTzYa*{oL}A$3@$U-!Axl;_=#&X0?n^D$Y_% zXJ(T`45hhkzsP3pM(ODV6i;^!vo7*;#6STSo6QjIqEAcqs*{|dU3_GnUXVs>}&A*IvuD@J$oK*cXh2j+-*;l&^3h`B^Xy|eVham9bnQl;D0 zmkgF3u9KWm-tK`q$r&Ne!y0&{oBBM>B;8grT;nbK8c97F8!q4=?}GRcI&t$|l zO-&x{{7Abx8Cy<8#~@xB~|(C zKNHo`{tjBcKfH!GnQ`r?*U@=*?m64;xOCq}8Cy;=<`21{>#Oa%x1I9Del1pHY&jLX zZg-`Iw2Bx}9Q~-nlFx2x`}2k4&gfCy2TA)o>6ACg&)oZf_G=cuxvkzA3^mNya*~Pl z8TXy-l|GUaJ@ft}e#Vwlkyw|F9y0u#D$bn)nwX+)>#pXp8LjJV4ZVI&PhXy5Tz+UdnTC!U=B z%}aHb^sDZJr2QQxl=$>tsti;{9E}2B+(^%$Ow>>){`@HEu^!ldSBK(y=X}?x(bA7H zww$ELDtl(;ls@*wIe(vi%FK){C+V@S$yzb#*ZLRSaAVoMt24Hoq{nKr`M?chI=ygy za7E*NGPazg$67Ie=~pY~3~14{`||HHww$EL8hT-?j^khH*=tn4D^AGRa*`fvSc6+m zXmZVl{jv_6eO1Pmlg?vt(F|Sm%qHQQ7?g^1>d^AR1w#RSK3s|A2#xm#?XIc&YJ0Pv^1pbaztWv08L}`?2Sa8+5=Oub;eMb>C~+-=RzA5AVK8daT)l zuD(#2`)H!0*|JH-mXq{YlkIOOt@{3ZZ_BmMAC$4>Bt6zC?~Q)X>epqjb&0%3GPazg z$Lcew!J@(rW5yi()~9(HTTaqrU2(yW69e)(hZJ)<^NTQ^?g}t+?RTg7KR!_~Mdz8#A_?q{o`FU#a`+d7tF3I_0rycVyJ~W2N(0Y3GXPyx6%( zmnDTCf7g1&mVZCrc=8uFR+))-g?qciErp2qLDAc`Cp<6z-tP0BeP~Kmd+N^= z{nP#qb8;EUSw3n+hcac@3={Ghq-QcNg!!bq)K+Srq%VA_ksrN2W5*F0TTT*1k2vPG zqJ~@UtaHR!YbRuEIY|^<+@a0YjanT3c)k2f7H4cZ6+WqK^xS7o-_i1m+j>6efAL<% zmXk!$OZIR3-b>$X{c6O@yu&iKoFt0=b;X0@j`Ip;O=>Wz+QsP_pR5WOQ8xPMMw@3o z(EQDMiA&p6JIAQ;a?+t_?yLLb8z=EtkGB40%&CR*KJdRdtx9R>pYd2}e<$6|mKCtA zZ1llyvn`(n*=z5=^6itVyX$JaoTSG(_Wbi^-O%ahv*t`Ku6EvEzZ4KYL`x-cHhE4WG03je5I5>V6lLB{H_0q{k{)_m4woe)9O3;P?^MK9e>6SV@o7 zwc|^rtJn1Fb>z$y)vf{5csWUrwfFG3+SP@Pr}mrJcR+I!elx$a}KzZ zh}rO#q6r3O^41#`QYjx$b&-T8p_4*mr27xtRPBQX&4WIvUVd=~h7Zx;VRo%~Ay^_ zeT#Rs5zE_E+2sCbc3q8^ll1BzFS@18<7dB{zjjsUO&NPTNw5BG>m%>H{jP4K-r8L9 ze#Vwl;nmAVcRVtGMEy5cPI~V8m+#Eja*`ga*|^eq%MQG2!S!{fR(otzjrUGEkL4@k zVp)bVa$|uQ)oiO=4&X4L5j8v`?RDX?p6@XD>6bS5|L*F&*KVusdrkX0h+CO(scT%e z#du`y_vXG;nd#9NNA>)YeUb+|PDthOIKoUxCU^jJeyH+bTy@Xg#=FWc4Diq-h-Bt6!} z^BP^efBRlIdWXJ$cE&zd(qldR_%BaxJ>t-hZa=%n zhZ$Q=I*%1_#jLo}RArR7m>kR;Z9U{xXOm&v;xaMev9iyMzPRDc>D&JK%*3#|50dtG zG@mP&7&feh+}Y zNqVe%u5VD#_WP+9JnRwa#sF>9}rRb~(CAiOiqDST+7wNsnb6+2QVO zmp0FHYIVun-bs3_oCWn;u77bxvvEJqx+`NJE9tSazG^)sf6Q|^4HJv1-A!EMkCpUT z%X)mi@Pls0K0B-ZEk9@M?WFTqO#0>$IC0kyW6EW2`rz(ATijn^Ftwh$8YMX6t2<9F z{M_j>u+7N39$&I})S{{$X19#Qq+L1VKl-)8@}HBrPzv7}aiu(7i_3*TfD!j)G4VUs zvbYu-mbQT@?lfnXxVT|VcN0Sza47}1&N0TF8`C^hXfU|?gd1zsAn|k#J{jAPe#}7;;qW&Nxt$I<1b3yn;@*{@NNx}Y++P%OLxjxrzPq$g zwaMvt&5$4F_C0>tnv$x%#h-CXfAl5FKSauM*c6qQlXTfjuQ{ZDzX8wXEV#&3Gq#)x zm%VehUe@}$Cx*N@eAwN+Cl*w-q&>U!e|onjW0o7<_SvhyjI|D))Okx)-{LRXt;v`* z@P&8o|7P-m!?U0M<%f(dry^$U+^x~tgmT5;v09VqO$JxBq&>U!e|onjgZ9~vmb~!H zvZalu9W-NXRo~(-*{$hZm#NKcDu1wWwkF4+rQ03-u>?t{`P~ry-_wtTq&DqNr21dvZut! zb&@yPLYP;&$yNl@bT{boH;i+Qe!ICh(Y-%oy(7VmG%?OPA*DyoH(t=U3c*UG!~k`R&(5jp|pr{aUPsTepjP z)-vs)Em=m zwOc+nw5n0!AKAJi7xxl-W@2vO`@Y<{ewJUdy_PRa9kRh{ZTHR*SKG90lNDfv9qbp~ zx_9VuPcV0z`QpMkE+G~b%n?tNNPuU6zGIx~4#swJC8U7O8aU~R``c|{9_#h0^u z@jGe&4sCmAVtE5DnXzmK97ttGlS}(#yJq-l$=7*YpzB7VG$czd`Z3FrhGwZnn~OiG z6@;Dl%2L;tw9Ar9ic9)3rP}lUUauCThUXMOj&cVt*MLcftSP>v4n-X%1K75#BsOIG zeptMrmKBu@t8K_8@Y=&hZ7!RWgTO2Cv$RC_x_00=YN%*TwJts-N6Zu8d2_(vT0*bG zwadV31>l@`FH3EEbuC{h-cyLujE@U zH}x=;x$U9SD-B$mTPe8)QrzXr^If%}w4G!C40uh49lMr+7d{dR;ld^2iOkL`28aG*4iscu-Q%B~?$}n)4)zIE)*Dg!_ ztYl*?E!zLB+6wpVF}D1G!VX<>17?ux(ve5!eBO3mHuo*HOJu9Ea=?Rmb{M&S(EgPi zZtrsvjk5z|7Z&>L^SWN%@$#}~ulcIihN}Gjp9x~S_xZoMe3BcPoRQ_=V0SKu%jm^& z_zzf4GC?@)$mR8>b}88OPXF1}ZlJF5a(+(`$|K{~FCJS@X?^pc%Z84>yQ(*|Co-Cl z0_vW~$QUMWjFvU7HQN&z_e91$k@3GVGA7B0CjCykJMZw3ZT9}OU$rO5)HoC+$%vs3 zHQmvr=j?Oe|JQd}RfVCyBvAiOMwCa!`S+f5?$8Z4K0Itwew9-m_e91$kj+HUuTthC(bQA~`7wX3FlKP6T z&YV56*WFLG9zDO^B^g^zG8gZA>%y$3zkTDpHWRjeo3Z6o|Kv#Htr?FFpZ)sEDs_4PixysS&UY@nd9O2y`_6v<$IBi#wg3O}H(s&lcQ;(a4qd}= z1I?nCpj*Cbb9bL-6N{8kRq3ygxKYEqaLnJoe*ME%M$0D6s(Rc%lWL~@9p7Y-lI0PN zH6h#fY-BnVh6356zya-Dv31Hu@A%B>Icwnii;o|4;;4)*r(#1eF8`k`Hy0kc*Y!rf zZ{}odIq5!gq?!t{CaQC&&=D&^Ow!RR`w^Wpp&`2h{medMYnQI~wYcoDFE8v~-3Lkg zJ4}gUs2_)ynklb)p$8c z^z-i7^@bh0veoNNkGQ?s^iPeKlSDtal@9Jz_l{PtkGiDq`5F6I$wTnkq`Z44ZqXVw zd#T=zj4daLex{ABS2AVZgj+6MenqvewV{fOzMU;(x zW8If89&_!%*LPgnyhFy8lMekjrp(0^p2w}l6b5C@(+n=ta6|_p;?A&K5APjOII8KV z3m1$z{gwIEeUP-jV}+*cyIQELk)a#D>Ci&tXuu^dcQ&LE&aEsD@~Fd|cNW!d-SNKtSUjxT%UYn?AX za!%nZW$lJvRM<6t+a;48fH;=sC2 zsF;dDGUlQv>fXi`+8h-TpwL-`j_acc)NBp465_ik6geF!X9QFWHFQrpDu3ITP4a{g z9h2-TvJjxx=4v4wX-?wpTqDw5J8^4$F7n|1A#zvC2_uwNg`Of?2=5(V2=5i!K!W!)=jTss6mgQzjm z%q1$i$fTT5q~I<=%8H~;1-9WMq~gx`iVSM!F0|i1uVvXa%e$0LPpsXu3q_W>XBYkz zyRaex@7#soeLL)f>l%OGdq)4g7VO!Ddv@Vp&T{*Mi>&bo2rwdcm#zm?{o|Ix1%mj7Jf1Smjd!&U-Khq7}b zi|FSf3Jr6KylOf7YFJ*NXqM%O)-+2aWrA(70;0BtZq*d+WQ7`PV{#}m8v5gOAHl61 z$)>~QTY(xH4xxsKkBrrFU6i~8naD6a;#5F0u&GkI3Unrh6B|w6Kxzu5q#9DY#u`F- z)Vng>bsD{KhG=iAFPI*psS*%E^~BUXPoYK5l&;C6+{T?_gz7>~rD-oBwz;my2whsm zJT#z8C`WM}L>?h_VngC*#9d&F{bhhcn8Gk0f_@jMMzAbpYp<(X296sSL%Sk4KzZPt{??L6J(uof&uJ!<$8ZW0J z8Qghxe(pN%GH;(N?wPY!1M^QVt{VA7_c_ig*2+GEvf zyjhdEdF!*r>hm8tGwYk2hbLw1C|Bg>JI~IPed~{Gu;TlR%|(ZNQPq<6oSpw$ai;>$ zl#OoFKia?7*xp}$xOP^rs&>X-5_f*5N^a_U`G#S&va<4;xr6)kJ*3Z|0Ye8K;`Ryq z`xp0C%8o1RHh5s@_Z4@+SRfOEIB>wBdQ4~!b;i6A@)bI8Ty9Wi+P`AcC}SBG0o?S& zTqhN3!eyA0V+8(yqZ;j;OOmwdsxHk(fuWYSTS0qZ+oCCpY~NrCt1eM!1X(cA&J3YQ z0>+ur@dT>UkSLmzsRjlOFD{>TlC%lQ69RKo*CFDQjKlE2d_)F$zo)tI(y|-rvTW1j zW7xD(sZ=ugYxoqGzqdmF9?eLk*aS$iDAI^40fAv6 z?lJH+9cbx7ml%!%lCtP`GQuy`9QIybWt+0;f)jZzY}4yRvDg6_aVLT))2tN864*&a zA)sn9-8^7cJF+zXJ01iL18j|OOZ)x{Q*74wM(eEYs~=6ZDFg>HUqoY9wQH03<3%!hBpb?geilzL7Eym@ z5{9_8n^_Z*BU1&jU23Kr3I#e1oJ!@PFkPp~p)({(?!4!HZv-d75T6l7b%`lQ3D`Fmy1IZQXK0AxE z$=1_kQ&Bxj(qY#a7z6_aur~nTbkotfipGxjV_C}m{&~lz*sSpo{{4UKV5Zot@fD=! zKXuEJ+{%02&;k|W4h@1v6DcW*<(q72n(r9J;ajG}x1*g8LevwRjW^(%J~XEvBBa0} zXl-Y0S)5{1HB5ucWYSX6k&{s+2U~5U!Twms+>l#Ba_{vitQ{OO+^%9a#Yx+5gt@_1Igg%+t8Ax!i+n{RpC9jbeE>K zcwoY*7pK^)v5fD)CqCFe#b%Aiq19h@X4@2-R^;Q)HJNTw2M0lp&0HGAM$Z-C^LZLAvTs| z!D~{>_Dq>gN9#Wu*g;Q2Y+;YthFtvq?8YfJO=c77Ov+(n6CW(mq{-0_EX^fExK1QN zo~w~4Y6!o?qFoV$6h-LLEDwTz-<1b%%c*>hU@qX`14SY93Rg+!O-c=psxfuJ4DbX-Bss(k95CV7 zVr&m38=@=zUtG~H&Xzmjo=TSs6hf9Mr&Lk4yA-e{0Z^d^Ty zW`0lNawqi9RLq1kB+z&&WgV4?Mt~55+RNEjUeF`OCe^IKl-VPAA;KpR#AVE<21o*S z`E;^}8Z{RJk7*+p&_YNhgJqzBGKg0UhnhRB_p`MsuakayBlIbrz&z=SX1l~}ZpS0C zdjOfpkOI!1rBQWaPw22}xH+7Z3iN~q^Mc@jk4v81@k=EPrm#3sh=ECjPvVsdClA~( zBAVYBz9F%JWX4d0<*01!Ym?GTYbQZ$gUA8ec2<@l6K}Tv2(Q0v94M zb1j$C64_$4k->iw8YsPF$B^uRTfKnF94tVY39xiI#Rgbe!2>Az(|5gaVv0?XAK-I9 zD~#*{)$qVJfd)592n`Hfq81oxU`~p1#8Jivh%3YSN~S38un+I)KWh8(%ImDL%%_Rj zWNnH~F&E51t^x`cGXVro%hWLvj7a0sO4*hST7%gH%=iM76VZ7k0p0z~S;XPum{(2x zY-y^^bhn?UyOn(5v11pe*sSpw-r$Qm^HOZOBwd_DNJwUyX(0+ffH&U=Pp9Eg4N2q! zKu)USFvbcWKRViM@qCa4aQecBqx|#vLq0=$;-yW z;g`s|M6!qyffg4LVC6e*T73KKm2KiYeM10GpGXP&Zv$S5wPM@`UrDtjTs!}okWKyx z`ED^rgZIFoIyD02S$h7IuR5mKv?Ja*Uzt%eU>k=-2B@J5%*F|0-NbhkR3Hk&7s~>B zpgr&+$|(;21;xKX!p@S1bCIDVwt_nFq z1k7bOIEoumIv{gkP=~n5(4a&Cli{v>`pl9Pn;M&rA`jpgAqB33HKV&HA}Ul@f{1)m z1;HaTp;iLu4qPS}qI%GLlRq##$H|${s6mR&8c(R4KK_Q>6r1FNe>?>;-88_JFFm+% zY32PX`!b0pGz`sIe2K`@*ny%TMSj3E9^R)N0(W^uVzNtMXh>}$hCZTQq2&N!$1{ER zdhxZ&HpyR!=}g}Sy^uu_dk7H`$4FMuyabU%PXiu=#Dr7MbR9IxKpl=4|FNnekYDha zF*U`e$cNeL7NM7|q5>Y6zGIsU$2LFsp;c8*117fj_-&2W=#4rA5aJPXI zQf;Oi(3Ng@%HwtG)l0Fd8{}>DoH>R~@@26LP4=J*BcqWDAd=yrn>YoPiD2wC$Qp!9 z3IG&GMNv_8-U`gfoN&c&;6h(C^afBWhH4e=l9D48(pWKlkso;Vv2Y1O#OZ*_1 zT)Y_IRLB%0xo4+$Holr-Qx~FtCRDj-g!D@~%@}!IX6q^R&1((G)5;j5od@4{i*%7`?)?5jqh5<+((S)Rj^J|0FWdmU+ z2h3CzZA{r^`=r=(OasuVLH+RG0#5>&Nm6kWpj%Ics}yzw*$4yz^hUr#h)BRFRaXW{ zA(7hgbC0J|o}I8o3It3AN%I~+xIW1*OdYd<*wPXS9{*m5s(9%nU>?~v&WqiK8#gqs zzcy^26q_1TSZ(&n z%~Nfn)2DS3&m;6#zQXu81XC6f47>1Y61gB=)nx2wfFjB!IH^D{HW8U_$Sd0agALmj zRetu!<8T^OTA4yeHJev2vJhFbabzL2Xo&~qQ8}kP0{#>DDA-Ll3gO?7RrQDC8@`lc zlSn9z7=kv!B58~`s@xc&sv_b;cS?9)h%8S8a~r_V?j)0Ta3oO7IuC!^hs~R%*d+5| zt25!2L{1kvH3JS#d}Zpt%y^Qe5V%X&RlySMEYhTx4!Lo&wpB)GQ z1?W+jCWR!&2e5Olh?CGYD7V;41SlkKjF2V0RTLmC2bZ%(Y_(OI!nVF}!0RbCYb*qH z_g=Il)h0>-6Q+oK2U?qoxz6tQV7f@X6u2gdM*u_1f+;Cb!RrT4M=a&L8Q#g&LF)>mnusUkR~0ZcSL#zks`e#O^_x;TvayTWpXXC(9HUv=U&E)Za>q2rIE@cv~@#tVgVg$E&?!D}zH~i;sYG@+R zGn|;mLuVas#<&LRpC7zQiX_l}Ia6uafBYuAHKho+v&qP);-u>O>ZlUHpCFBgthx=c zt%7+S#D{v45FLwm z3K|3f+ki^kM$yHIpc45b1gKy{Mn*^YuEnbK`fn!H7US~*hA|?`$+FL)$F4p%aio&N z-vX4+=lHtld3zn5?uI4)h_G$`b^ML6{!2|WhxB1=+&rdcP$hLhT%#k?O*6;ahv9Tb z?M<^JtWNpTTc3UyY??Ww@Skh1e_5o`eDu=&zSn0=Z`|S6J3pGXI&Uh?IZrmahyzlg8r__|&Y#L8cf?mD*Q*lu4nrUsg34neG8 z-N(PvOP&+gX84p!rkO(!>+11k@8;=0z0BoHQ7=t1hagtDx{Is1$MkdLjcQTFG;;`I zoeR1&qW03<=_ZscHO@412x7e`5q0`N>r*eXt=noiWRQ|(lz=bp1hFdDhO2u%>{a8=fEdhWHu)=yj|O*4le z*28=?Kd)8#!R$|u6lF~_halFe#a&0O_~csA8O1v+FwGo-SXncMjr#UiMawnlw~3~i zLlCRl?d!)U|1jcK+rAYQ)65}=HL~)$wi{n?PgjntZrGHZ62uDl%OZ&NaOZ=_p`E@u zYuz`nmT9Zw3$c8**+B>>SNs~wfx@?IP`g`gp53GIPNSDevT1dE;=#w{o|ebc)rZ0b zZvGOA7HFpd?S%;KGD@^^;4nv$M$+dO@*`7&gbR{N5Gz74Uz0G%fb5Q)!`++W1${OF zSs**E+xo3v)-&)DN_sq4x9zB|;zEvTfQgxqNpR_vCS2lCBxhaL+8IzHK;i>LIGADp z6?(NG&N?pK+hk~+kokW!84?`5-DyU~k~h_#tFIpLt}3cOzkjlk^E!t0)0(0$BXU>N2v5}zGK~A)}9^~-S4cCN&nI#M10P(+-I-l z?3?a`@LK8j8ZA(&93fvm$7dThd`=$toXHW(3UoQ{ju{zq%rM$X*={HIG>fO}TZR4_ z2JduTIQ01G31$vOObvYwVkl5xvuXGn zi>RtBRL)W1L9GNu7IdpY)eV(%y`c$NX#7nGM)(=))d&+Gz&E@(mV(UAu(6u9s2ekZp;De8(RUgxvz0}k|g zxbCC!Ld|xjnM1seeuyRvo>ys9`CXN^#6}wOg8pj{5%D`aBd*tbT5Gh_KJ0zJwO|82 zM8xmpn~*Pa!L;)>wn#I`Z|c;5%^`kAKSUo4udwi)uv~PrHQP=Zo$G(?AtIjVaIO_+ zUQa$=_kM|1zZ)%4N<2@%yXMpL_-Z~yex`ojFLL#(@WJZ1>Z2a{{UW}e3}MVZc4N1mS<)m8N{Rw#|RqeSffF1eT(04s>1vxbNGZ>ldsvZFRgz>U1BN z&lQb$@3WDEF4y;)m@44aA&B*XyV|#HW<+QFqSV;hrmc=I#PZo<0>oOmx9!2UAM7Z# zb;sB%{=SIM=lE)6A&AxVR;8)Urbfio*@^nbvcMG))kf)-77D?C=T!g2?`lNAXU8XE`5G1jVznDPVu$wY z#bY(AboaYgB;cVmf><|Sgl!U@4o^E`eCr*4Z?mu0_BA6%5G&8+GiAE8E?MW)+-7r4 zGlw8n@2{q7-&b|M2(vi+4u}KZEP`15clA1LYqBn!Dc{cTGI_w}5X2gEs_w+&U#`qN zq}#NHrfn8MtVIoXoH@`S&72F97X4tFIRvrxUWz$JGi|I_qNwqvnd1wwe2&QfnU8Fj zjsI?#bl}LL?h&PoUM6K(faIQL@l52q(BO|gZd9}|&&o>}l0r|cK36Glp=ebG`&MkV zXv_tJwgTfMm;}O@0~(nze2pGoUD(0eKFCA=i9{yI+BF(ucNmM%)hNJ{!0401svUJO zJ=bVKv#p+X1c3zT3@~wtX<-Eu1tOTW(AF*JWMCFw6afTDGZopqr{wDH2b%tLt(?&k zrQ~{;+ybSDv49}y6n7YPBzH7_;mUUzOf$!eqzOsw7waE27_uuicGZ@pnT<^P*B&B* z@b)u@+jLxWbwS|?pH47ZqEtCV1mT~?T@D|(yI8()2d;i(nmJyCPdG%~2JGDWeO#7~ z8(+3AVPw+3_7ElVJawP9ojBFOoXlu8D0A3e!%_d9rZ2-@!`2n?(@om#W8ROx@+j7WV*mrl z5{ufs0D2+c`+vX8~6L2%1pk*Qua*%xvl8y7|E418xh@xKJR+$8g!JkC^m5%-2z4?y*-J6oJ8VlB800ahUYoL=3VsVMWc02m8~bf z=9k*LS@+jxmhG<-=65DJ;FIX}H3=uN>dTDhwmkcE^G81}{laL4-k!ujP9kxn+ddgJ zr+)E0KQ8%U))=F8PL-4B%aQuz9f2b)RW6OCMYCTkbhqu^ezX4LEJiPr6v#DPyewMtMS@lV!pl0lkEDAp3&yuWmFCj*|9CLUgGK@4TCQ_!{LA>0 zt!56qXS9f^a?E`BH=kT`NNsg;kGtsF{Vto=ddKf#mCxt+;;bWHV(_q5)v~-SxHW2E z@EU*DHDGgymzWWJ{=v9ApGOvHOcZFl}`R*3NAC zq^|8^;m;Nx_dhKf@ahn(%^E%-cdztgT7TZKcQMme$BVU2_wo&;o;J+e`Q0sPYE?4L z9D-PJOruw88#anR)UNk2)6DUOSU%apfmo$am7H~ST!q-D*&i8(NhyI|pU?5dN=^`~ zbDx6C4_-a~W$tZuzXQpD%^`?&DgSp5YIXmR?|srT+uv;t*c^gb?p$5hk9@Vf`L0j1 z{brgu1hFz%_r<4a_hFuUQT-xKGlwA7s+%|CH-)Pev!=VT*)($qVvU<|d+g8O7N2w^ z?Gr;~)l~Vi2x46-u(@x!se4~7h^pSowAJy2SU$Omfmp%sRBL*8$vR=z{u3MgeG#9} z@x_Tu5UbeN-I{%S=>(VgX?MRHf&w;&AeMD(6Z+8CS(+BQaN?$Et3wd$;?n!M@9zxi zA&TYvCgTWrbqHeBu2Vna!nuW$do&QDON3+BlCTiZgxsXv<_yx4uu(e2DY#8RNe%*Y!B#3GINWt^ z3^3p8w9GCqW+!Y&!@~tvwXd_Y#e)Jf!rpF(DI4O&<%A8{U+BH-y;okCUOB^eyWehz zDI4O&-lP~;eafdGJR99(@QNE&c~GD7&HcU<_n^W0q=9Yn2PdD7^cOUWH2U~{}M;B?pP zad-BVo2{O&Tbg%^Y37jd?8?RSY5DBkzgI?&@jD(0cy&m4Hc$C(__75}EG;dCDyQR173Z#s2dA9>tn+GhC*&wL7&KstR}g-VuOOvd~3HdGg53ha4i^fF0? zXXk>lcmgy_f^cZk&$IlgkOIzpjsqo^$e>gVSv3*S6r{{tOc4i zou)y{k3L&po71q2HC=>D zlhBifQISgpcBfIPn9OO=Zx);x$^7l3!1{(~4@G+}{*oy_O1W_>$gCQmndK6+;Yw4_L6>vZ%52Gm#kjC?nw-8*`>1m@so{v8%dD?+^=OyAd3vLRoGPC>iI&Ef=eAXCeCtV3p{w6iSpk3Q-e@V| zQ_uVHk?+zK+dlEV6X9o!R_N`g{`OP<2Y>1$)(+db@cU;mKkhn}*;&EpAg9Ww?km=Y zSZMMh?`Qy(F-h^xrdf4wZ>-X6@`xV{`!16FD*rM`k=)ZP9!+_u>OeEhrGm6j=0uR^ zQeZWNyg9;)y^wh^gBw z=_E)sIY7?Hs@C*rB@F_zp0ul=@^(FHhfcf*-75s?tVT=LnqdqS9FefavqB+5thsDg za?+q~FQq|71F z;13^k`LN5N$vw|)8S|NG=DdjpJ%=&=?2NX1zuwY$YvU6?8=3U>Fa~%SNxag#R+**! zHs5YiclC%~MoXO%5DWM)l6d9fkNq;%%q-_$v7)ly?E(Rt^Cn*L9L8Rc>wJ=yuAS{^ z(?%POR_N_v4Dc`#j~W-UTq)JE%bp_a`9elZohpaXmq&#h8syR-E{p*MNb*u5@)a)V zVM1lm?qD#GhkW~Y<*q$nS3YKP)gi9u{=SIM=RlMZ^c>L5r0hs@KucFpkX})sHjW7k z%u^7LGvvk8?FA>swK|=3g8u{+zFymxImF{k&zN=6%gPPHR;_#BG;MXf9>?iE(Yed< z{aJTsnE&(S;ij2G5P9vKvvKLO9>~?=(`$oFGlwAZkb~tK>{Ke%J<_vlBh$?BBC^w6 z>w{_YZoK@Q->{+9CDY6yh}FrRb>_+z^u{5t4;bdHQi50kf9Spt%cqz(5G(wf$Cal% zsFVNtnZ|w(mH2#)FVS#m6%UzdYsso>O~S)65}=l{+%)mXAtq8L_1F)~cqNLlDby|JlP~Ihqdq{Nm8X zrkO(!Yt?~m58E!(vIl?L#P4SAfR8dktW_D}GIpquJL|rT1rD0FI=&D~g3>IeHYp8S z${fVwA#O{%@GlB?Zw~b>J;v&^HC?MFN2(Ng^zeY++wAi>9Ex%%6QOO(4y|jI5oOio zK=T%~mla-hB#N=N4gRU{w96kpn|UF7oWJWDusH;=23vNIsXgOzNV~LYCYojrL98{u z$vtMCid%oV?D+M*O`&`>}s%IZfti7SH2&8ka(r z6(|wy0WwPR=>63B8wE}dMRzizH)mR0P>|Oo0kiR^fMk#2DbGjHfCg6FI#A7QO zwGO@0Zq&LR<395{?Dn}tzRV%$W-of^%UsVg*JW>Q^4q5dY>pS*5;oSg;_Dk~{x6D5 z89dCe^CrnOkr^9Hkg!noi%+k1=+w1Jy{2XT{kQ^NNrHq^DqhGmf6}8?^EUSMI~^IY zIbI}8*w|TTBL)k-jeI_bks!q-qu(9< zJRC}xrpjg!bj$O)*3s3Q>x?Q}<720KYJIY>kbGi>-m&+G_zWd`}?o^>oGlw8nj{y%_+{&E$)wK*0{dVdB zZf?&C^4o3wj>7{GI>c98AWo)G`PSgrbp8w1rc0m-SXBy zvT(A5VI(^xIM5=?I-rB=sknnGT$5EWIk9L;r4&iyG?c)>U&!;k!_&ALjv*rn0=bMW zUwVlHrJ)RRMO^8-hp8BK;zc`&ItyPsy|hWuSA&auHT0&x2Q;}Q^sJ!Q94tj5b1+Qx zr#S>`^Ypwl=EcFWWhTevTxyy*UaUlO+hdmGF(Y2$=A`UP z`qdvE+hA}=H`Df&c!@0oJ8oUFZD*yNtC|`P!KK8927KzhULxU`jfwyIhg}c&D~)ew zFqHUud(4tNX2icO>tD8htvMH~?%dV#hH1y_jepyeb@kuE*@h97*k;2VD#oEfwD8Q1E~YaMQb+Efw=^D0bXJS z&d#EH9sx54A#?=Ms>{yYJXE#I{+FlXlN?~v{~Df%)h8n;xG*T-qSZ>0Bpwuh5~W`P zzS&f4#l2loO`hC!zwhtbvA&)IX$#un;^7LBCczkmjHWU)mw{-|uAtG2Cypu0jEa$G zPnJBt*Lmt!)65}`Y5%at%Ehg%X8t-NT_e-X@j51_yT;5l2fwhlD)VcY%P{sy34jH> zSp?pHTTsn%tDS3OiC*{pE^P*E4uSWfr$+qP@$~GGR(9SB(>BWs?@srMpRQJ);Er1` zt}64cY32}+T>M9o!)Z!hpQ;R3{B8jXc(dMsWX_X~E_pz*xDJv862bNc=;K8+*J6qt zou>{A!8=rpA7RknYM$(z zy~6As>*7r_halGLPVuidWaMAOye`$mG;;`Iz0R)G2_H1jxoox?ZJId*u};QS{yO6L zp2@9U-G-QE4neG26{dIZ@NB}!8(rE}H_aShh=s_E)i4h!X#&P2(XVJ{IhTt^TEMQ~ z*f~AMdOT)p)8<#_EKh%+ncvr2pU>ftQ>IjwM*F`2<`F%)fSFcS0V@d4%MJ&LvDR#H zHW<6HU$GAPHyZZcrYMT=_1eD7A&52jJY?QRp?>k%k>|= zS7yn(hI#|3vN{B@>h9aZ^;(*~VEnon^-NnGf>`yZj9q(dV!sZ{UKJW(nmGiqs^rPu zVcEUHOG0br8D^R}1hKMwOE(T3r1s9!-+9S2b9^BdMz$G|wKEP3wu7gLmT(~x91@}$ z7G2JQ=q;${wVxQa>(=su!ReY@GkTdMQxkuwyC(NEi|28`OLSRltQ{li9HZ*9_8R8z zSw+=C!DHm`NFmbby+*GV!wCXV7D1Ry*=f~*i6;TmOpHX(t^J*l2VB9AimjNa_|2M~ zoY5YeeVIeh?e~!L5%u|T!_oTPym zkMZc#;#v%y4%UuB71-!p7`xFYFry)jjglN31#Oq03BuxPOrxbhb4fI7vjpk&sSId* z!lj*7Fxjba*5FJM%30{uLKO_*Cmf4j!@?Ae10_BV`Av}HA>}DjNd7@%gp+7q&~!$W zP{wX&?Y5H{K#QVq$QgnLMPqDyICxvobtS){wR5_;oX#nmHh%1?bU(vsqm@p{u}N;7 zJ8~#;9H6xSWp2fh8K^nqt9fC1dVi@AhzhgRb6jHOhos$oD)`oh)-68@)`D$L24W5G|RfSv-$} z@FeK2WEaJVAht!rf(QZyRNUYULsbk+=#*5E&{KDSs!Na+nQ_*MaPT?>gvRmK${{?( zFys#MahV~m!BOXJQ@_98!^r9sZ9y_NdrVGjjc)lHb6~D+4slISmy|f!^iIipFBhNL zX_`52T$5*C$KMZ+Q@)_LmAavPXk^kqXULkSIjIm-GJX3r$KawdNbz!rucLusH+=2WDcb z4KMLHB*Mw_rkUf#L8tpl`;z_Ye)FK=_!(E~n`RCHx5cj})j6Ylm$m7rK7LOF1-w}V z+|oZfHY4-o!`8^y-$$FaI$m&dy1&TOXI7~K;rTlid41S4a|mMfne}a?w)@VQIfL)| z-?rlmP<(ypz7UJk^eetgU>N9o%NkmlTspl6s8w0SC=S%d5`w($r=lNr+A?E6v-Y+z zMr)fgr;*&#vUncnU=&u;Xi#F&JZH^=9EC3at*9VAMVGG~JgE>1kio>yg6@h^7~~(& ze*k_g8Cu~EgoKQosE5}2!>v~@#%v$GwZ<=XjjT>dFp!+h9+Q2UL%@v}c8BzDywZAv zpHa>@OEDM=$?1VtJSOMpmcFz7ibF zS!(v$JR6uBS@M?TOf$!eg9-aO^}(!(#fB`G`n;(BkN;i?WImy;o!onT0X6K|uYT(> z2K>Fgfz0o{U7}eMb%}QEqIPahM<(hK1-mpVU96^w8qJ})FHw|&>3s+^14tE0wo%Cb zs?aNOpvRJPDU<_~0l+B_dO_G(uJ%p&S$dD?-}z0KuI2)%W=#O8pkk*)2rVMbEP*r{ z^AMCPYQ&Y9fA=@>-=n*gwhJ;Ucq}f`47j~LL%j}{i>BlU;o{A zx2qsBhtReInQmmg85z}A2HA4ir7);|idVar9`Sd76GAhZhDkn$gTlLm^P5GM8gnHM zUSk=%%hkgFR5yphDH60M-L0IqSt zj=HfbPNVO%-1pZr@AEfZ0tJdoR8-*jb+$~DbzI$4C`{Rvw+6bQqP#;R}X%^4pL`8!#5k4){ z(=m4L5(O5-nG$L`N+^rLbk9%`I>8+(%VEAs1O2AXU=OW#C>bd(L}+N&_5?&6Dm03M zrU48Xs~-shPnSzm04%Itud3_VuY#{!bO?lQF(zzy#yw96x{G9 z={b((P3aC#tm&TDKT=CyRPb>3su4{Pr%1{0}&g9nFv&@Oi z!Rq`^b4Yx4DD!*UKHWd+oo;h?|7MywZ{jmgPJa2$`SZJ7y4Gz(t2u^|PLlE2Uuu=f ztym1#7pjcJ=tV#?O#=d?Y#v|rGy@7>K!Gv`fA={bvW2e=aq_nK1Pp2Za5B8h`D)#&)}CNtMEzt(cUInI*%=2L`=Z{px21_7W^qC#ZE zVW%ivn2(bokw=3jiq{wpwRq1o@S<{8Ej{nnn6>hHj+ukEcm8`agB`P%3a4^or*cIy`i2tF?1YsN%GBMDxp(tBuW`wvP$zqU4L0^U_ z(YiOy#Yr3zzn~<=2rx&1Di!0xvP?liuyF`@a`d*1aI{%);P$3$qq3>!^3df~5OE=E zi+&G>LuT~QH(LKG6glmO=qehG{x+o*6Jfe(~??AE6ttRT_EEeE$6|HWoGCMwg* zxySv*p5*q+vt55R2kYZC2MeN`L)`M?NAi!%&N~C@7jzoNV=1}q2W$>;%lerJTSfdq6(k;I|)2VukoFhP-kFUqa90?Lqyzr4ykvua~ERU zEyzGGFwGp|-t{xh4D549D7ZA6W9xClum0_s{%7Dc2@^J^y>_CI>)m2&-@onm97Mpt z=qpUXBpwa6NEPEQdU}k41TpTj0%+o7WJD-M*CW1FzK>-#^SD~Q*Q3IRJPHzxzKA4` z-_*omLUK>DcpfLimtsf|S7|h}t1ezb9so@)G`xSPC^3rePcx#o5_J&>Ur2%rNg->u zC^&QQG>NPLrC-i->!y&&f@en#0a|w8#1sXEf({!<=0F1CVs)I$rDr`9ba%?Cs)Aw; z;>QR;c!s5|8AAlor4y87M{yQhOJEj(+8yQ?HIYIf!B~F}gIb5?;PqQ~FqHY6Cv%G6 zIcITy7xd5uB6%`0HV!1JAp4e9T8c%3S&}`?zco|h_6#>b_dsm3{AHCi8|K@%7 zI;^DfvdH7(76J)QR_7T;Jr`>5GDIfvFTH4jysXomLH%LsqQ%kgH2&yw|2cGhJqMf~ zV1VKoUSMGevY{>{hc(D1f$2jK?TIFsdbzH!^B0WfHuvc2cQonqwSAdGZb+@zow+Z! zx<3CqZd@&+Zz(0gZNTPuZ%8@^M!iXAzAu)x?2;~qP3@^-ju&m5?j3yO_I%d{Y&^Z^ zfZw`00j~}T{U>O3yH>8sWGNjx!?6D@RaVCv`a9hvx?cExUfu`OzWni|X4={DLWI-Z zCVg??%U0o)yFd6ft!d`?ifN&Z%j(V0tN>0qPQo0l zWr8^b-RgeTD)S7gaSz)5p8wfUUpwZ@951>hjPVW6ezaQ0g^y~ypQl47qZRr`Z7e~; zf-9+q9Tq-6=vw@BE+ey3Wn&2vHq3T==+7&c?)`8|?~$gN<3+-RjXi$UrM>$_#i-D^x`R9ms#B<=g)Q~>sK)Z$>5;W^D$h)JF1po71P@V3Q zjc&a>Qo`Qx`n6|%s{sUT4ne~AYh`&}FFba1-t*r!^Lv{ET^%nHI^E;qqPyP6R&Gtd z`AiPe%pvHuyxzXJ4MQ81e6_SuKhw-1=r*^ad&h@ zn$}*qAb3L$zeyJYHisbAl!xc~EuJy@S@YYSYMQoLz7UH={*6IG4Bcfchwd;L{ZOa_ zB1a~H=~1%lao*$jR+eW6yXGIp9J#b|0_Qe*nIyx3uM+1jlY5%Q^EiyVDG=8Hc4ER^ z+x4h9z`vke*dVEN&k)KgSdi+dn)G(z0&v4rQv;N8ohn0;D=9Fz@U}H#iDj4 zqE4gGvOp;)cz|RA?f}gndhl8+BHOm+OY5IH-L{?L_lx*?4!T5;BDF&*1mYZ^z?6Z@ z7|v!So<=7Nod}m#HrU&;Xo;(ns#I%z#x!#XE;s&Y8uMP6_cl*-&OT(CIbK|Ly0vdF zj@w@(!}R#jx#vtXhk)d+>=)ksHFt(yIrH;-O*4mp@c*;SQ6zZlx? zY1F3$1{Yq$?=Cc%^8zn9kfe0FbA0vi-pUuN3#r{_`ptsi^Eo;d5yoFI_JO{8H0bGl zZVILgG*qc&Xo!&OcIPj1{IL8*T=n>3(SGw{1Z)mLtoD^Z9kP5!;!?^wn*>*aSHBVcm~Vm)~Eio4l$QcUD}m*3OB0h>b*>)3}6W-sr&xcHpt z>tC6+Sp>1Z93NA(cHxk9!?L&YI~fu1>JY>_5Fc}ADp#t@;{46-n6^5;5DTMoU?#Jx zkU(<)u`uw0*&>X_@HA$B^|S!4Q^`He;&~hf;Pk;8hNlG? zWgg78Xc$^UiP%noaRxVHT&2@d5`|`Gox06h?j7{bU=T?ZRm=dQV_2~}^j6^fAXo#Z z8j_Bv4RIVO))1}X#tSYsQ3I@@b z)>R(xG*jftW-koiJ|(^|xpz-^^<>O}X%qp;nmM1Q+0kpt)J+33`TgAmY>pQs6RuPD zv=2vb%v9!s?;jRuWpvn6cAZMjsDIx1Ah`Td_{m!}X1BP;w*Ky-(c7oW`5?G_c4btT z!(aBQL|?8{)iiUwxSVi4w%j{#_w=rNbGNJw4j^6kf9re@SMc;kyRz3C)?fAf{lSe* z+Yn!_Kt!C%psJ0lHflu*#4*vah)zVb=78$K<;v-ltz@Tg@E!F6^)THN>>hDMNU!_ z36kv`=AR)KB+!_~)c=MP(SNB54!cB)5dOiO3C2iJ|B^wX?4p!JFdthes!8uz`VZqyS7_<)~H;*>!GK` z4GC8MukAg7@V;q3K6`po=EGH{O)YNPViO2IBh+YlwM5mPmo8pDXqq_$!u7o`^=QoJ zFALMwg|YemUiauf^t&hUyxe)VQm!+N9=16edD^ta_65)Sh?*S=mx6>=at#=VnR0Le zP#DFBbfm-6vU$GUoxY3q)rAhdFXHn#B8VwKPYLNEjJ{(iPI5^odht3BG-Nyz zXG5pNJ??p8ZR_+@^;1hsGl$^mmxns64XWC^Se}YeerL1-UL7x<7GAUI28uKXa~} zaCzI!lFMsOGH-PVVwL3=sLouxAfQDOm26zVfmOP= zA!x;LJJ++JOZiO;r^lDc!*|<#%->Vz^EnU>Mok`rLJFG9LC5HjFhZn(AqGP;93otj z4Xt~=Va7F$cG6F>FX?KUIRvqy*Qarwxvk`WFm3A}rkO(!Yk$6FmkyjQz9V>Q8^h=? zMFFX=L*Z+)2x8r;S+&Hk)pAuH-f!J=(^iKd)`+N|_DtP6qI2eHf0$qHjf%Ft7tAe z+H@Elv7WirA{&BtL{DDS&F^p0=W|f9;aLHLj~Hykl@}aD5JLyeHYgeqc2SA$td$oE zrLNySzed=;&hH{-z~&IdieK^Mi@4#19^ROl-@Mf!h&3_O@=YB=2bL{+?Q~OrPhG&P zLl7(fnyeqjVxT~t&T6m^2y+aQSTNI;F&j~+K<0|e)dTCf>QI0UM9)J z&0mOwl6#uPLqdlRMwFOEaA30-b9Z5)+hs@74uo+Wp%{eWbygk=2xc)WgJE!1wtH$b zkmJ@st_CF?QAA1(tTB01RRd+A2=+NJ!nk-y4=^0%aM?9pw5AKvOFZeoTB6gZp}XB$ zEg1B)&N-2g&Xy^MU8A9+jX%jMvW$vRY!Q5Fc8+1}A_v(VDFRLKXvO3deMlz)tvq%R zyeJM^%M2V6pALrv`ZU>2S!-ZmT+k`uqFu;CN@xMqBo=pFz%d4Yz+TAnXsfrr2zo>0 zlCan{9=4j-^s}GleY9cs-z$c^UF?)Bwiizm7F#-$t6h$2AumEQh?Cx)?Emj4+lz-u zO%iK%iiN5v6tEQV9O|_D&{338N7h^*A(iw3a(tO`X)F=U>;COK^}OEUk9>wA5lI5j zgv3>Yy4)(&-{!A_y8#i}RF6^J)F zfMprb0uM?l2ZJ$3TD0a4637L0{p7q$9v+*0=H~ueeosLsw}_rKOl*#>zmwP;7%Gr( zFX*=#7s}jTRjhE=PbV0Cd?~pR25gQu+)FrUBj#;;d9}#Alk*yMd0=GH+k=+OLGwbZ z(_MG(qg6A9eSbM$udIISN(Q{MBvg&*y){p@BJ+x`Z=cWaar=PH@rJ4i2kpmlH#b*4 zeCNCH?gfs#J!pRu(Y$WO={}X|GBGNuZI_zJV(DfBT#uGZ4?=E@2JR&@L(uq>yb3ri6vd^ zTU3dsxO#2ofr>NZ7cG8Y^?QUnU~`D4=v6b#jHouHZm;gR(ZZ7%fsWKPv6)6DUOScu9&LaKpR6*Ujpu1JiC z3o9Z}2l!5*4z8y%zq#M>_P5*5zy4}K$PIsA#OHHdV0jZ%3DGQzn>Zpah$Sq#F)jZ2XUjG;`^xXOwSdhbh;{HcrBja0y-S3DIP$b0l>qL?k2Uw^@g`xx=jq@zTU^viLLv#e;BGQYZs{f5-S2(D3 zpkW<}1Pw%MJQ`-8=Z&64sItgpe`<~x)E8ne}MhldZZy~wm@vP1p zYp_MS#K@oK;N=s{Avk)cbs2fhl;XF-O0Di~nmJw^O*lf+=awA5s`}|o*>m+>YGl&C z^av4j&wFO_`3xDG(m!=QnaOB@QsoE{bdRFS++WtbQ0VzGMSe5Q951>j9HE|{zsg>& zPP@Lf3y$ZEO!}7|A>wmhMT$cktoT-X{bY4kqXkNpBjn5Hp#7T>L6OXAkP+Y+pcj;R zBnga|V9%9B&xrZ+MLVVA&r0@rxpwh!e_zDsa}cNtw4RaX1?V8~$S6}Ne!*|BNUVVS zmqf|+_no-*!-y`$+W#7Ch+QdJ*MQ9-=x!}=FI&SE>6ZO^=D}stR>zC(PIvkZt$WT- z+hOvP&&E|T%^ZTGL&q?uGp;%G^XV%sdYEPo!O^vmT?&U?toVNS;b+V<$BUy*_k@c@ zA5Zxqro*;lUCc9wAXe5iW$)VNS{=>BbLM^Mz7Wf$kG7y>g}fsYeo*ZI6{ZY{Hc+d{ zyyy`1D7k;R$(FhmyOe$YBrMz23Jp#foxCLd)1<^va&k}0=Xo51hIEW&vWy00SUb|A zJWHc2&r;T?5Zw3m@|K0i7?DUz4DShrQC?R#2I_I3II>F+a@0#{5jr!vhW>HcIwY7A zdF$LLnE@bzEe;*#9HT4ACkbBf-#<~< zd*)2@Q}HF|7;QvK@H)9|NZ18p3{C}>Cb2bGaDvxAbt?R7%{v84uRL92yJ_Zl@jBtC zZaNq_a%}N?E6Qv}d zgJ)w+Gso+#5{~NKIl;x}Z5;YEy6a5CB;4Dh`oDTqiLcIik#DtQBW>pLD>XL09zZFJC+JXQa} zfSdHwES|@qhnYvS3i|5c{~%l@Ycx3a6%e!1p~zOrx?c-}ya|X17;E+H3^dea&H-Io zQKTIzW@ts+QHW=2Z@aR;#Qk#_mq{H;8=0LF&*pQ9{xk>R)G=iB36f8QeNn%`H< zfLD_Ef$_sSl^dvUO34Cts^APC5R%SfQa5cT{GIl04q;F z_|4kd8yd{(*@rTEnI!k%FAT8BJ4%sumX{+%eo^R*EU)w6tq?j#nnx} z;Y`d5g)RpKss&KsA{9hI=t_{SzemvM1C*ir`9{ad>9+1s*4B)U+rTfKw94r1Q?ixG zy}Retjm*JvyfKG>@8Ync!tycJvT@}y-Z9M_0=_y!@Q#V!oci&H*egd*mwaht(tqRm zAQ)a_z^-Chm6NkKj@;}w8CJmOgJ5{6v0Ayt;-^(^*H|2Hv>B;#TnUEj=i}p}3wym& zZ}Bg+zOG`}ul3(}K8Pzg^~+~UbdSExPrmQ$VA_WGas`+e!9a#f0~*>v?*a-h@L=gG z_Zs73F)5-qu~cj%SNgg@Y^fKO`sefaMSMO7DuNP)*$*V!XpWZ=E2Dr5L1IV}gGok8 z)WkC7N%g{gf^)@eE_u&y3Wk8qA-HVIu*y;I(C=+}ZM$>VwAJzAGKMG1R_NFNV3boS z+x(1a<`9tlAnsB6!Wq{#EcatRzcao8Zx#W`?0xvyk3a9(hMIb#q-m?;1xcrS<)e~a zDz%7O)Mm_1!(>NFFgxJYA&52c<v=NRj|8IiJPbp{zsv}qKp-}x=P$Re!cW$+5H5;7;VD6$s)HBfYBQS`3^>&zWMpPKP;GnH#vw`LjqO1B9 z0PQg7aE4l{OOLqo(4GlF%*fasb`EqBCgL##EXVOmIeAzKsE8?ve~+k+(A)^JU> zBZ#LIYyD6ev*En0e_GTf9HL$;2)9GG7L!I&%>1l++mZr_Ss5KbE|+Lm1&Y61U`eP$ z1#`Hqe<%tg5*L#UT6Qeaew3+%$Swvp)e216z04>6r?I~=6i2ByVGkxN7wWnz#cCM1uDktP|OzZ}m} zX!WEx2>zhsla)mgs}ihAjBS1F=hmv>7^oD%s%E#vg;G3ti)|BwF#0qxJFZ;39rIh5 z>e96tG0h423A(_xw9u1f1?qBv=DAQGw^Me3LFvZoy_G08<`FI?^2Sr_{3m=iR;qtW-260A!4 zTl(`;O0b6E!3OZBH3I19M8#_kal4=OeRa6|tE<5`s@{=JGso+8cX$w|-P0kDUc|kQ z-Scfz!wchE#CeN2ZxP2A;*i*J^)HSk*RoA-w?!If-X~6C$LSZ}`S_1d@|RxH%i%ZO zOTYl=jU5vZ=ix}n6%?ZE{cwD@^hO}~7IEGp&RfLsg*fB_)NaVS?33E<>-;RP*|$dD WQ>w%`-V4y{vX!e9vGskn`TqgutV{O* diff --git a/timemanagement/views.py b/timemanagement/views.py index bab1b07..fb03c10 100644 --- a/timemanagement/views.py +++ b/timemanagement/views.py @@ -40,7 +40,6 @@ def loadingFreeDays(plz): # CALCULATE FREEDAYS AS JSON year = today = date.today().year - URL = "https://feiertage-api.de/api/" PARAMS = {'jahr':year,'nur_land':land} r = requests.get(url = URL, params = PARAMS) diff --git a/users/templates/users/searchres.html b/users/templates/users/searchres.html index e078d21..ef32b65 100644 --- a/users/templates/users/searchres.html +++ b/users/templates/users/searchres.html @@ -54,10 +54,16 @@

Dateien

{% if res_files|length > 0 %} {% for s in res_files %} -   {{s.name}}

+   {{s.name}} | + {% if s.parent.is_root %} + Zum Heimatverzeichnis + {% else %} + Zum Ordner {{s.parent}} + {% endif %} +

{% endfor %} {% else %} -

Keine Ergebnisse bei Mitarbeitern

+

Keine Ergebnisse bei Dateien

{% endif %}
diff --git a/users/urls.py b/users/urls.py index 65302b3..04fa6c3 100644 --- a/users/urls.py +++ b/users/urls.py @@ -46,7 +46,7 @@ urlpatterns = [ path('icsall/', views.getICSFileAll, name="geticsall"), path('icspublic//', views.getICSFileEx, name="getics"), path('icspublicall//', views.getICSFileExAll, name="geticsall"), - + path('recalculateabsence/', views.recalculateAbsence, name="recalculateabsence"), ] diff --git a/users/views.py b/users/views.py index 727acde..b270a67 100644 --- a/users/views.py +++ b/users/views.py @@ -1286,6 +1286,14 @@ def support(request): else: messages.success(request, f'Supportanfrage erfolgreich! Ihre Ticketnummer ist '+ str(r.json()) +'!') + send_mail( + "Digitale Agentur: " + str(problemconc), + "Hallo " + name, ", wir haben Ihre Anfrage unter der Ticketnummer " + str(r.json()) + " aufgenommen. Vielen Dank. Ihr Team der Digitalen Agentur", + 'noreply@digitale-agentur.com', + [mail], + fail_silently=True + ) + return render(request, 'users/support_done.html', context) else: @@ -1460,23 +1468,31 @@ class landingPage(TemplateView): ''' def absencecheck(user, daytocheck): returnstat = False - print("ABSENCECHECK") absencedays = Absence.objects.filter(agency=user.profile.agency, user=user, confirm_status=0) & (Absence.objects.filter(agency=user.profile.agency, user=user, start=daytocheck) | (Absence.objects.filter(agency=user.profile.agency, user=user, start__lt=daytocheck) & Absence.objects.filter(agency=user.profile.agency, user=user, end__gt=daytocheck)) | Absence.objects.filter(agency=user.profile.agency, user=user, end=daytocheck)) if(len(absencedays) > 0): returnstat = True return returnstat + + + # CRONJOBS UM 00:05! def cronactionsdaily(request, code): data = {} + today = date.today() + mailstatus = "BEGIN CRONJOB DAILY" + str(today) + if(code == settings.CRONAPIKEY): allusers = User.objects.all() ''' Pro User gibt es das Feld loose_holiday in der UserTime-Info. Ist dieser Tag vorbei, muss die Differenz der days_inuse des VORJHARES in den Rest das AKTUELLEN JAHRES gespeichert werden! ''' - today = date.today() + for user in allusers: + + mailstatus += "\n USER: " + user.first_name + " " + user.last_name + " ID: (" + str(user.pk) + ")" + # REST URLAUB BERECHNUNG #try: usertimedata = UserTime.objects.get(user=user) @@ -1496,72 +1512,220 @@ def cronactionsdaily(request, code): day = day # Restetag erreicht, Reste ins nächste Jahr übertragen + ''' DAS IST UNNÖTIG ''' + ''' if(str(day_tocheck) == str(day) and str(month_tocheck) == str(month)): sourceyear = today.year this_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear, user=user))[0] next_year = list(UserYearAbsenceInfo.objects.filter(year=sourceyear+1, user=user))[0] next_year.restdays = this_year.days - this_year.days_inuse next_year.save() + ''' - if(user.usertime.usetime): - workdays = Workday.objects.filter(user=user, end=None) - for wd in workdays: - wd.end = datetime(wd.start.year, wd.start.month, wd.start.day, 23, 59) - wd.save() + # Arbeitstage beenden + try: + if(user.usertime.usetime): + try: + workdays = Workday.objects.filter(user=user, end=None) + for wd in workdays: + mailstatus += "\n WORKDAY AUTEND ID " + wd.pk + wd.end = datetime(wd.start.year, wd.start.month, wd.start.day, 23, 59) + wd.save() + except: + mailstatus += "ERROR WORKDAYS AUTO END" - yesterday = date.today() - timedelta(days=1) - weekday = yesterday.weekday() + # AUTO ARBEITSTAGE HINZUFÜGEN + try: + yesterday = date.today() - timedelta(days=1) + weekday = yesterday.weekday() - workdays_yesterday = len(Workday.objects.filter(user=user, start__day=yesterday.day, start__month=yesterday.month, start__year=yesterday.year)) + workdays_yesterday = len(Workday.objects.filter(user=user, start__day=yesterday.day, start__month=yesterday.month, start__year=yesterday.year)) - targettworktime = 0.0 - # Mitarbeiter hat für den gestrigen Tag keine Zeiten erfasst, daher automatisch auf null wenn KEINE Abwesenheit eingetragen wurde - if(weekday == 0): - targettworktime = user.usertime.wd_mo - if(weekday == 1): - targettworktime = user.usertime.wd_tu - if(weekday == 2): - targettworktime = user.usertime.wd_we - if(weekday == 3): - targettworktime = user.usertime.wd_th - if(weekday == 4): - targettworktime = user.usertime.wd_fr - if(weekday == 5): - targettworktime = user.usertime.wd_sa - if(weekday == 6): - targettworktime = user.usertime.wd_so + targettworktime = 0.0 + # Mitarbeiter hat für den gestrigen Tag keine Zeiten erfasst, daher automatisch auf null wenn KEINE Abwesenheit eingetragen wurde + if(weekday == 0): + targettworktime = user.usertime.wd_mo + if(weekday == 1): + targettworktime = user.usertime.wd_tu + if(weekday == 2): + targettworktime = user.usertime.wd_we + if(weekday == 3): + targettworktime = user.usertime.wd_th + if(weekday == 4): + targettworktime = user.usertime.wd_fr + if(weekday == 5): + targettworktime = user.usertime.wd_sa + if(weekday == 6): + targettworktime = user.usertime.wd_so - # Es wird nur ein Arbeitstag erstellt, wenn KEINE Abwesenheiten vorliegen und der Nutzer an diesem Tag arbeiten muss - if(workdays_yesterday == 0 and absencecheck(user, yesterday) == False and targettworktime > 0.0 and user.usertime.usetime_start <= today): - workdaytemp = Workday(user=user, agency=user.profile.agency, start=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), end=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), target=targettworktime) - workdaytemp.save() + # Es wird nur ein Arbeitstag erstellt, wenn KEINE Abwesenheiten vorliegen und der Nutzer an diesem Tag arbeiten muss + if(workdays_yesterday == 0 and absencecheck(user, yesterday) == False and targettworktime > 0.0 and user.usertime.usetime_start <= today): + workdaytemp = Workday(user=user, agency=user.profile.agency, start=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), end=datetime(yesterday.year, yesterday.month, yesterday.day, 8, 0), target=targettworktime) + workdaytemp.save() + except: + mailstatus += "ERROR AUTO ADDING WORKDAYS" + try: + # Erinnerungsmails/Push bei Vertretung verschicken + one_week_later = date.today() + timedelta(days=7) + + repre_absence = Absence.objects.filter(representator=user, start=one_week_later, confirm_status=0) + + for r in repre_absence: + if(r.representator.usernotifications.absence_user_is_rep_reminder_mail): + sendMailNoti(" in einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!", user) - # Erinnerungsmails/Push bei Vertretung verschicken - one_week_later = date.today() + timedelta(days=7) - - repre_absence = Absence.objects.filter(representator=user, start=one_week_later, confirm_status=0) - - for r in repre_absence: - if(r.representator.usernotifications.absence_user_is_rep_reminder_mail): - sendMailNoti(" in einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!", user) + if(r.representator.usernotifications.absence_user_is_rep_reminder_push): + newnotification = UserNotification(touser=user, notificationtext="Erinnerung für Abwesenheitsvertretung!", notificationtype="", elementid=r.pk) + newnotification.save() - if(r.representator.usernotifications.absence_user_is_rep_reminder_push): - newnotification = UserNotification(touser=user, notificationtext="Erinnerung für Abwesenheitsvertretung!", notificationtype="", elementid=r.pk) - newnotification.save() - - channel_layer = channels.layers.get_channel_layer() - async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Abwesenheit | In einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!"}) - - data.update({"status " + str(user.pk) : "ok"}) - #except ObjectDoesNotExist: - # data.update({"status" + str(user.pk) : "no usertime found for " + user.get_full_name()}) + channel_layer = channels.layers.get_channel_layer() + async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Abwesenheit | In einer Woche startet Ihre Vertretung für " + r.user.first_name + " " + r.user.last_name + "!"}) + except: + mailstatus += "ERROR REMINDER ABSENCEMAIL" + + data.update({"status " + str(user.pk) : "ok"}) + except ObjectDoesNotExist: + data.update({"status" + str(user.pk) : "no usertime found for " + user.get_full_name()}) + mailstatus += "USER HAS NO USERTIMEOBJECT USER-ID: " + str(user.pk) else: - print("API CODE FAILED") data.update({"status" : "failed"}) + + send_mail( + 'DAILYCRONJOB FEEDBACK', + mailstatus, + 'noreply@digitale-agentur.com', + ["htrampe@gmail.com", "info@digitale-agentur.com"], + fail_silently=True + ) + return JsonResponse(data) +#import datetime +from django.db.models.signals import post_save +from users.signals import save_newabsence +from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays, Absence + +def recalculateAbsence(request, code): + data = {} + calcstat = "BEGIN RECALCULATE ABSENCE" + today = date.today() + year = today.year + post_save.disconnect(save_newabsence, sender=Absence) + + if(code == settings.CRONAPIKEY): + + for user in User.objects.all(): + calcstat += "\n USER " + str(user.pk) + try: + abinfo_lastyear = UserYearAbsenceInfo.objects.get(user=user, year=str(int(year)-1)) + abinfo_thisyear = UserYearAbsenceInfo.objects.get(user=user, year=year) + + abinfo_thisyear.restdays = abinfo_lastyear.days - abinfo_lastyear.days_inuse + abinfo_thisyear.save() + + calcstat += " DAYS UPDATED - NEW RESTDAYS: " + str(abinfo_thisyear.restdays) + + for ab in Absence.objects.filter(user=user, start__year=year): + if(ab.reason.is_holiday): + calculateNewAbsenceDate(ab) + + daysinuse_thisyear = 0.0 + for ab in Absence.objects.filter(user=user, start__year=year): + daysinuse_thisyear += ab.holidays_normal + + calcstat += " NEW DAYSINUSE THIS YEAR " + str(daysinuse_thisyear) + + abinfo_thisyear.days_inuse = daysinuse_thisyear + abinfo_thisyear.save() + except: + calcstat += "ERROR LASTYEAR/THISYEAR USER " + str(user.pk) + + post_save.connect(save_newabsence, sender=Absence) + send_mail( + 'RECALCULATING ABSENCE YEAR INFO PROTOCOLL', + calcstat, + 'noreply@digitale-agentur.com', + ["info@digitale-agentur.com"], + #["htrampe@gmail.com"], + fail_silently=True + ) + return JsonResponse(data) + + + +def calculateNewAbsenceDate(instance): + + newdata = getFinalHolidayData(instance) + + abinfo = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year))[0] + abinfo_lastyear = "" + abinfo_nextyear = "" + + is_lastyear = False + + abinfo_lastyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year-1)) + if(len(abinfo_lastyear) > 0): + is_lastyear = True + abinfo_lastyear = abinfo_lastyear[0] + + is_nextyear = False + abinfo_nextyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year+1)) + if(len(abinfo_nextyear) > 0): + is_nextyear = True + abinfo_nextyear = abinfo_nextyear[0] + + multiple_info_needays = False + if(hasattr(newdata[3], "__len__")): + multiple_info_needays = True + + # Gleiches Jahr MIT Rest + if(multiple_info_needays and newdata[3][2] == False): + # Rest ist positiv, daher bleibt rest übrig, rest wird in absence gespeichert und vom rest des Jahres-Restes abgezogen + # Rest ist positiv, damit bleibt Rest übrig + if(newdata[3][0] > 0): + instance.holidays_rest = abinfo.restdays - newdata[3][0] + instance.save() + abinfo.restdays = newdata[3][0] + abinfo.save() + # Rest ist negativ + elif(newdata[3][0] < 0): + instance.holidays_rest = (abinfo.restdays - newdata[3][0]) - newdata[3][0]*(-1) + instance.holidays_normal = newdata[3][0]*(-1) + instance.save() + abinfo.restdays = 0 + abinfo.days_inuse = abinfo.days_inuse + newdata[3][0]*(-1) + abinfo.save() + # Rest ist Urlaubsdauer + else: + instance.holidays_rest = abinfo.restdays + instance.save() + #abinfo.days_inuse = abinfo.days_inuse + abinfo.restdays + abinfo.restdays = 0 + abinfo.save() + # Gleiches Jahr ohne Rest + elif(not multiple_info_needays): + abinfo.days_inuse = abinfo.days_inuse + newdata[3] + abinfo.save() + instance.holidays_normal = newdata[3] + instance.save() + # Mehrere Jahre + elif(multiple_info_needays and newdata[3][2] == True): + + abinfo.days_inuse = abinfo.days_inuse + newdata[3][0] + abinfo.save() + abinfo_nextyear.days_inuse = abinfo_nextyear.days_inuse + newdata[3][1] + abinfo_nextyear.restdays = abinfo_nextyear.restdays - newdata[3][3] + abinfo_nextyear.save() + + # Hier werden alle benötigten Tage von Vor- und Nächstem Jahr gespeichert + instance.holidays_normal = newdata[3][0] + instance.holidays_rest = 0 + instance.holidays_normal_next = newdata[3][1] + instance.holidays_rest_next = newdata[3][3] + instance.save() + ''' ABRECHNUNG CRON JOB @@ -1570,8 +1734,10 @@ def cronactionsdaily(request, code): from dateutil.relativedelta import * def cronactionsbill(request, code): data = {} + today = date.today() + mailstatus = "BEGIN CRONJOB BILL" + str(today) + if(code == settings.CRONAPIKEY): - today = date.today() # Check, ob Rechnungen bezahlt wurden unpaid_bills = AgencyBills.objects.all() @@ -1598,7 +1764,6 @@ def cronactionsbill(request, code): # Alle Rechnungen laden, deren Letzter Tag HEUTE ist und bei ausgewähltem Paymentplan 1 eine neue Rechnung erstellen, Mailverschicke, Nutzeraccouns zählen und neue Rechnung in der Agentur hinterlegen new_bills = AgencyBills.objects.filter(end=today) - for bill in new_bills: if bill.agency.paymentstatus == 0 and bill.agency.paymentplan == 1: @@ -1715,8 +1880,18 @@ def cronactionsbill(request, code): msg_html = render_to_string('users/newbill_mail.html', {}) send_mail('Digitale Agentur | Rechnung', 'Sehr geehrte Nutzer, es wurde eine Rechnung für Ihre Digitale Agentur erstellt. Diese können Sie unter Einstellungen, Abrechnung einsehen.','noreply@digitale-agentur.com',[mail_to_send],html_message=msg_html,fail_silently=True) data.update({"newBill_" + str(agency.pk) : newbill.lexid}) + mailstatus += "NEW BILL FOR AGENCY " + str(agency.pk) else: data.update({"status" : "failed"}) + + send_mail( + 'DAILYCRONJOB BILLS FEEDBACK', + mailstatus, + 'noreply@digitale-agentur.com', + ["htrampe@gmail.com", "info@digitale-agentur.com"], + fail_silently=True + ) + return JsonResponse(data) @@ -1736,3 +1911,162 @@ def sendMailNoti(notificationtext, user_touched, linktarget=""): def isAlive(request): return JsonResponse({"status" : True}) + +''' AB HIER WIEDER RAUSNEHMEN ''' +def getFinalHolidayData(abscence): + user = abscence.user + usertimedata = UserTime.objects.get(user=user) + today = date.today() + start_day_obj = abscence.start + end_day_obj = abscence.end + + try: + holidayloose_date = datetime.date(start_day_obj.year, int(usertimedata.loose_holidedate.split(".")[1]), int(usertimedata.loose_holidedate.split(".")[0])) + except: + holidayloose_date = datetime.date(2020, int(usertimedata.loose_holidedate.split(".")[1]), int(usertimedata.loose_holidedate.split(".")[0])) + + #start_half = abscence.start_ishalf + #end_half = abscence.end_ishalf + + start_half = False + if abscence.startday_info == "1" or abscence.startday_info == "2": + start_half = True + + end_half = False + if abscence.endday_info == "1" or abscence.endday_info == "2": + end_half = True + + choosenyear = abscence.start.year + yeardata = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, year=choosenyear))[0] + + holiday_thisyear = 0 + holiday_lastyear = yeardata.restdays + holiday_nextyear = 0 + + try: + holiday_nextyear = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, + year=choosenyear+1))[0].days - list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, + year=choosenyear+1))[0].days_inuse + holiday_nextyear_rest = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, + year=choosenyear+1))[0].restdays + except: + holiday_nextyear = yeardata.days + + # Urlaub innerhalb eines Jahres inkl. Prüfung auf Resturlaubsanspruch + if(end_day_obj.year == start_day_obj.year): + # Startt des Urlaubs NACH Verfallsdatum - nur aktuelles JAhr und die Zahl interessiert + if(start_day_obj > holidayloose_date): + need_days = (calculateHolidays(user, start_day_obj, end_day_obj, start_half, end_half))*(-1) + holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days + else: + need_days = (calculateHolidays(user, start_day_obj, end_day_obj, start_half, end_half))*(-1) + # Kein Resturlaub + if(yeardata.restdays == 0.0): + holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days + # Resturlaub vorhanden, berechne mit Resturlaub + else: + holiday_lastyear = yeardata.restdays + holiday_thisyear = yeardata.days - yeardata.days_inuse + temp_holiday = holiday_lastyear - need_days + if(temp_holiday < 0): + holiday_lastyear = 0 + holiday_thisyear = yeardata.days - yeardata.days_inuse + temp_holiday + need_days = [temp_holiday, holiday_thisyear, False] + else: + holiday_lastyear = yeardata.restdays - need_days + need_days = [temp_holiday, holiday_lastyear, False] + # Urlaub geht über das nächstes Jahr hinweg + else: + two_years = True + holiday_lastyear = yeardata.restdays + date_splitter = datetime.date(end_day_obj.year, 1, 1) + + need_days_this = (calculateHolidays(user, start_day_obj, date_splitter, start_half, False))*(-1) + + need_days_next = (calculateHolidays(user, date_splitter, end_day_obj, False, end_half))*(-1) + + need_days = (calculateHolidays(user, start_day_obj, date_splitter, start_half, False))*(-1) + (calculateHolidays(user, date_splitter, end_day_obj, False, end_half))*(-1) + holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days_this + days_nextyear_normal = 0 + days_nextyear_rest = 0 + # Urlaub nächstes Jahr MIT und OHNE Rest + if(holiday_nextyear_rest == 0.0): + holiday_nextyear = holiday_nextyear - (calculateHolidays(user, date_splitter, end_day_obj, False, end_half))*(-1) + else: + temprest = holiday_nextyear_rest - need_days_next + # Rest reicht! + if(temprest >= 0): + holiday_nextyear_rest = temprest + days_nextyear_normal = 0 + days_nextyear_rest = need_days_next + # Rest reicht nicht + else: + holiday_nextyear_rest = 0 + holiday_nextyear += temprest + days_nextyear_rest = need_days_next + temprest + days_nextyear_normal = temprest * -1 + + # TAGE NORMAL, TAGE NEXT NORMAL, TRUE für 2jahre, TAGE NEXT REST + need_days = [need_days_this, days_nextyear_normal, True, days_nextyear_rest] + + data = [ holiday_thisyear, holiday_lastyear, holiday_nextyear, need_days ] + return data + + +def calculateHolidays(user, start, end, start_half, end_half): + restdays = 0 + allfreedays = FreeDays.objects.filter(agency=user.profile.agency) + if(end == start): + if(start_half): + return restdays - 0.5 + else: + return restdays - 1 + else: + if(end < start): + return False + else: + counter = 0 + if(start_half): + counter -= 0.5 + if(end_half): + counter -= 0.5 + + weekdays = [] + freedaycounter = 0 + for dt in daterange(start, end): + day_found = False + if dt.isoweekday() not in weekdays: + counter += 1 + for freeday in allfreedays.all(): + if(dt == freeday.day): + freedaycounter += 1 + day_found = True + if day_found == False: + if(dt.isoweekday() == 1): + if user.usertime.wd_mo == 0.0: + freedaycounter += 1 + elif(dt.isoweekday() == 2): + if user.usertime.wd_tu == 0.0: + freedaycounter += 1 + elif(dt.isoweekday() == 3): + if user.usertime.wd_we == 0.0: + freedaycounter += 1 + elif(dt.isoweekday() == 4): + if user.usertime.wd_th == 0.0: + freedaycounter += 1 + elif(dt.isoweekday() == 5): + if user.usertime.wd_fr == 0.0: + freedaycounter += 1 + elif(dt.isoweekday() == 6): + if user.usertime.wd_sa == 0.0: + freedaycounter += 1 + elif(dt.isoweekday() == 7): + if user.usertime.wd_so == 0.0: + freedaycounter += 1 + + return restdays - counter + freedaycounter + +# Gibt die Woche als Wochentage zurück +def daterange(date1, date2): + for n in range(int ((date2 - date1).days)+1): + yield date1 + timedelta(n)