From 561a34f10861c88c65dac8d3032d3d466e4dafad Mon Sep 17 00:00:00 2001 From: db_huang <18006480240@163.com> Date: Thu, 5 Nov 2026 11:12:24 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=94=E6=AC=BE=E8=AE=B0=E5=BD=95=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=B9=B3=E5=8F=B0=E3=80=81=E5=95=86=E5=93=81ID?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=8C=E4=BF=AE=E6=94=B9=E8=BF=94=E6=AC=BE?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E7=95=8C=E9=9D=A2=EF=BC=8C=E6=96=B0=E5=8A=A0?= =?UTF-8?q?=E8=B5=84=E9=87=91=E7=BB=9F=E8=AE=A1=E3=80=81=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=83=85=E5=86=B5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/__pycache__/config.cpython-313.pyc | Bin 8194 -> 8244 bytes backend/app/__pycache__/llm.cpython-313.pyc | Bin 35572 -> 38318 bytes backend/app/__pycache__/main.cpython-313.pyc | Bin 366949 -> 390373 bytes .../app/__pycache__/models.cpython-313.pyc | Bin 34947 -> 35610 bytes .../app/__pycache__/schemas.cpython-313.pyc | Bin 6760 -> 7821 bytes .../screenshot_storage.cpython-313.pyc | Bin 4924 -> 5501 bytes backend/app/main.py | 440 ++++++++++++++++-- backend/app/models.py | 24 + backend/app/schemas.py | 18 + .../test_auth.cpython-313-pytest-9.1.1.pyc | Bin 304993 -> 332936 bytes ...authorization.cpython-313-pytest-9.1.1.pyc | Bin 26078 -> 34320 bytes ...ment_accounts.cpython-313-pytest-9.1.1.pyc | Bin 32624 -> 52537 bytes ...efund_records.cpython-313-pytest-9.1.1.pyc | Bin 30359 -> 33578 bytes backend/tests/test_auth.py | 164 ++++++- backend/tests/test_refund_payment_accounts.py | 88 +++- backend/tests/test_refund_records.py | 4 +- frontend/package-lock.json | 10 +- frontend/package.json | 17 +- frontend/src/CreateAnswerTasksPage.jsx | 101 ++-- frontend/src/CreateAskTasksPage.jsx | 117 ++++- frontend/src/RefundManagementPage.jsx | 120 ++++- frontend/src/RefundRecordsPage.jsx | 10 +- frontend/src/TaskBoardPage.jsx | 46 +- frontend/src/admin.css | 61 ++- 24 files changed, 1100 insertions(+), 120 deletions(-) diff --git a/backend/app/__pycache__/config.cpython-313.pyc b/backend/app/__pycache__/config.cpython-313.pyc index 4b2033e728f7c64f8eae178d1034aefad55c558e..da43880d622dbbb25a79dc89ea5e7b0925bf17a1 100644 GIT binary patch delta 81 zcmZp2*y6zbnU|M~0SM~*Uv1q3l)BsEHmq6w`VZfP{DY2ndV?bM`sDZ}#KYsJQ;H;PX9*lBJ$3mE^1P z)I^=oC#g;1f_#S7y=c!aA1g%HU)pTZV)bWvr3p3xJ8DC1NinsFx@r^1jVuKCBX z`e|e8M<*1^>ZS|hVJZ`hu6B!Di=1fGkL;aW*hJPKNtgsRW4dv*a0`|R2F90M#T(-2 zFC;%u$R9V=G?;0B-~~ykoIYInwZV{y4CvCb)*7#>l-W;wg$$K@Mo#f8t35k4z5899hA<#clqdV z8lOstx_5c&V{x$txkEzC4ym=F9Kc2#a;x1&s_PvJ0;THuS0%(7nmJ@P^G2Ih0$IJ@ zF)J(GSYm}S7&9wtt1ZB2GR`ww*V*dojTLp3=8eV;W=o}MZMDf*ZmL)Zd84Vm-dIyp zn^3>W;ag@g*&2wcrp!Gj5(aXE;Ln-`u&R;kQ+qe3?oMr)&>C~Z+Lm(Sk@mU0kyCrs ziMQ3MJ?hk6^^C@OcSW9VzwvFPJ(<;|^{CT&)ib+gGd}}4T!rgp$2>Q(KYg(B|LFdx zM)$|PbAA@SgrCGja-3;5tf-RegTlR{xe{KGAu7;x~j@^yqmAmlN+fPJRSii zQ!%4}-jY#`F#ylRmnElvqhz~VvI(}NAonZMk;;02v!q-^aOa6Hf*(Lb9Kgy+v(uf= zzc_Gu{}%Xj9^1Rc+5FUC<2I3IFj^;dI)wti4CY#BjtblV`RYx{CR92gb*sL3>ZEFbbDhUQ~ogESid531?2$(F^4Q4`O zfI1GjE&?=iuD$){{kOXhz?|#R*DHI~`M1^I>rsENS1mNo`&i|(KmWFF(!c2@wd>l; zUk&cnO~0+n=+R|dsJN}0+oPL%z4G1ZZ?5SsTGpGh?2g92C99>VY13^@WRE7YR}lFmPn+z=2o#E_4C?-sR`}F60W)h04EYB-h5_o*U5qH=lZT( z6DQc;v=1@^FErxRwjUil@iflnTI=9Tdyul{5+IDI@A6@o*}&FrIIP~xvCAj&xtFie zdG(o*MeOV9f*lgqZs62$XY+ZwNV#S*4rWi+z`;Y#-ADTmu)!QT2}i2$>hsW@xH^58 zo^f`(*!hw27%wMLa1iM;s+T9k;)#@7ZJTP$UwQ{U%IZm7ZM}_T1H<^va`kxLUt!`G z^21^NUWNQH=PxhhNjN?1l`Od<>+JS=pO-ASOJDS9=JRNR#+($waTc#q1GHvOiI>~V zW$+e>TR&BzCITf;B3Udc2%}!wsFV|+*-!(CtyF@ys5Hg0#k<7&OKq=0TV>G{`n~D? zbiP&-yzEzkuiz*63%Ue_yF)!!@NwsH?MzN`t@dX7f=-2}f9^iMJUPrrEq zK_n0h(FpzsIslsQze!I5u!uT{St5r5tQ8n7gAd6;+I;HppH@-?S%Uu@NiqWncp@xyHl2)UD}(n^ibNXK|OxUyH~91E?w8{SJUM2Yqeif+TEZ@?f&g6 zUXAPxn%T7A*P5WFjd!#GhrITAwVB%GXZcq>&&IUbyJOR?FYB(|FwAlDB!v=49+Q+y z?sHs3h2(RN^R1NJ58#60J`arKynOHagq>2{o|M%yDXV)S>G834E3J3b+Qx-{dN76h z2Cj=+!CS|}xZjKqoIjqs86KEBQE@X>0r<{%U2d%Ootc^X+(_wrk@DQw&J%$@m-B^m zOL!5V)A_UTN3JRoAo_%?Odoa@G#4Iu$5*a(E169LA5|6 zB?wCpmLrchnM==4h)qLr?7TXprpiiEjm0(qhsOpJu~b{C$Qmda)P%j>3NW};W*aG@ zeiIkO*F%j}4d5O%q~gHUW5!KxB3tLqiSv0ryz{4%7E2TpfI=qH*tkl6ltI{`mWqN% zD1AOIjc=yCajE=|sVe@5)Rdr0ibuXF2nh&N5fTxmAxuX|LP$nPK}e+!;!`A55*jxp z)((mh4B^)q1JN{&7z3AW7;6{*Me|@EwGS@yFtqiWbH`qnVc4-B)b5Bq5Ow;9RTw<8 z7xeqXCV`nxuz8@*$Jztu&irRXm#6`Zm8PZc_U#aoH6>v)DT4@yiF^8X+pMv2 zIq@mQF4$AziTyFeQJbrctF*v!L!Eem_b`r_2A+R}~!rW;DwiRnJ zw+^8WVLgJl6PP0a4)2N@v&rIqOGP91b9!`E7#~WzW<~qn1t#d0v+k2}+@D-#tW%e9 zhmTH5?+vebBdtB~*3|A5t9tWH-Lp*>HuTOm9bNi*T2n!Hcm*9dyMwQ!w`RX%59QuU zPhL1ddLtogN*Z~2Ex8RS3o;xX^-jrq`s#Tn8MXJjf1IqA>1Ocj*6RSAn{NV{b- z*N}x=Z(A`-v z^Or(4hb#jGpW!^xFCyRu69)p@Z|uk+-CSMIY_-92v`d1XBYBfP$chd@i^?2FD?|iF z?K2qHsq2k{zPZ zf;?Zbwq=7T@7iQ0Pa*^$$Am!O2r7|ej6_0E#X{s2M-rSA08xjKMGbSPCO()>TeQ*6 ztPJXKg4YGn-b}_^Izk)*vpme3n1#hrmx39hQNMzjq*3RB87Jmpq(QTW7h#oDuABC? z9YZg5v1_*dtM}}~|6lj)zjw`E^-tfk-B(1s>3_own;tHl8jPNa`*Jw;LI`$0na(eq zUTokA>Mzj7vADzo2$=vbMeOnseMiD_BUXF}n0}9pe*tLZ?q~|T7ni&XcM5(f{YlZs zQzS`de%N2_wFYjDYWW(tH3DA+XpoTyPdk=BYf;eafn@<|cg-@sL^2ZmG|o?8YS3>b+nNjSNob6?8>#3ca#GPtOD^=x-Jj1J#q( zPWPOsgxewfOF=sYkDgnq6#V6o6Lbs%7zWb%+=oK^(X2uaCePWFAKZ zcpTnEnP~nqH87@d8N>#~7I0$)j~M-rG1pyKlu|tH>=DMfdCh!@x8O(H@?#7WGo+E+ zYCei9^>gzT&2{HS)1rA}ToN=5>?z7ZmqZ=`{>K95l4LB@(+6qbl0-7nn`r@&`Xs3! znJFpJnk9mtMVqNz&5!Mh#-vRMEM4T5IL297%-k5%bnGcD9?31C%V&&JkB(wFjzSs* zD>fW94*L%mq95*aH78Eg5JOuFp0GdU)+Dj#zeKl&Y=WN1clKo#{UgrI+aP*#(0aOf zafRC_xwv>q`IN8sN$^d1*fIGhd=lCbA8a?GtgrJw$Zf0z51140hTq-0VEzi)dV}vn z`oN*U$WR%ChS1+|$ja*~H+_r4fh*-uz*W4y!NxuqkPsXiUZSnO0Ap^VViqjks-j5s zJ*ea1ov{8zLU$L%Y3_PQv~FnM((65|G3Tzzuk&@`$Gjr8t)$mKuG3cH!{@!Fjn9qd z-kO!1tCikJ%$fj&cSEI!Q3-(WX;rzA9`A)JF&`aKAeX++Wh(QP(hroGDk$CZODN!^ zA9C^ndFQPqRTAx49Oml?Zy}XBe7#KUX1bOu1kX*9nKw1&a?Z5 zb~O*4IRO8GJ_J|smL>>2JI}xF+_`t4>%>6UX^18uQ+$^fUs=;`BrDg3m6tZb^;>(;^iK1`Ts)5Vbvtq1z@Wl4PJ=-vJ?GE#cap%G34)?#fz5i<>${5iHTi+ z-VxB%xoE_fht8WWz_w0$9es)?< zRLa@vo~Sw3Lwcg}dwmzuXUn5Pdfq=t zjn7tdZ$&51OPAgVjDh@(bXB&}$Q5LO|W5XuqE2)GEM;b1o7mskXI zu|~8PU?p;pvKC<-LM?&?p$?%4f!T}onER@gnB$H=i{BIKD#*w;g)g8*Zs(bGClwM2 zPfLkjBID_kWDW02`^iW1*m(YcQri%i(efmJ!#oG4kF0gCD9oDYPM8^;_0 zhbLnxgCIXSN$WQUX;~G%z~Z)Vq=z;a&40*?dmNi@K-h}#6v8%y?Fc&&b|E~2(2UT6 zkV6xn2;pC#c~6AdN7cYLYk+;&@G!#j2yBCoU=EiRF7qP`ifkluCuw zY#s5UC%Q`P)UAP{LjgZ9sjapVluBgCa2nwpf&+oQI{ui`0XXC}b@;o05ns#TWhSUA z9V#3w8*8OQY2IkAXt33h(OEk@RyV+pOUzb>Ld>u^I~28M_&`!AzFerD$PECi7l3Pv zSOWWWWJipAE_C#E=ZzgEJ_9FhND%{xQ*i8oI0%oLx~eMt2*U=PgmgVHI=sZMSP3w4 z7}Np!*e<*MRj6Pu9r(xPYt0olQO$%QIR+sc;SK`RL`;!bvDkrd6QLX7F2ctM{Rl${ z%qzW*xz7>sv^wPFn`|(Dxvild+`}|>gxKj}Ymakd`jlPL#S@^M1z+MCYRr$4La2rR zob@_=qA48I{(&Y#sgzG|T{6r;(k^{~$*`B4*S4k(bC9%EJiugF8^9Ox-2oGZIn1;t zJz(i@VmR;Hnl;QpayE%27m}~bE~Y;~%J8G~v!>gE7r%yYwGDHawgWGw7p!9XZq^@I z`F=zMpCf4lE=9=&~6=RBSBnQMKX2HpPvDR4&6`%Q7C3>Qry=;3%?qp6 z5^Z%j2{&;Nm(Po+))8H`p6FRzF)y+@ibPc#hymhCK{YSB+DMEntezKB9ZO=X<4Bx| zYmnC!(al?8{0#{cc&wD;NTQ%=h!esZk}L{Ao5ZbFkYpjeAxVg6NC9bTLz)t_EGj|A z($a^tLvn?nXL8d|Hu#e)vY{TPGljxC6hcF*5=<;@oR9&H&1}GoL;0ZD z1q~^~lM^Z{i|H2$*^qLF_RzqG%2fzC!Feuj;q&vTNxm;i-Qir{=5{toDk6G)#1&W> z7Es70%4obkhx($L^7{Af>fiO|^(UX|f8>R0Pwe>q^s@tpjtsp0cK<`WuRr%ff7ijQ zC%gN*jtAt1!@O3~G&;Rvi<_*cuSLH&K?n0LDLvlxZK6j8VUtOUUg>OHBf6T3ogEzw zZEfvE9qT2vql38HJG`V6bm9VDV-9arIQbfWFxe2XfFI-x$_4x_j=mOSQH_NzJ;BkE z`Ej&6RvS>ozRWA;@>L4j6}Ow8N2kY&hG`tNFS?sYz(1`fb$SjTKjJu>hIV(v(CG-{%RrJNgX}mRg#Q|lHB84Nma?~;~?ZEk_tKw{m<7C zGiJ8X7m`aCR6tNtwz`_c2P8Rht|K#1pmMrA>qO$gVKm+OkP=MRJ35@iBRU%0F0bhF zl4cMV!k;ID=A<0u`)E%}y??^AOVNvewe-luv+^^Q?}hhOEb6UT)K?)~GUo0#@425& z?K5Wg8nZt&<{n$x8@;&4*4(qCxhJ}1hx*I#=pBzGUu=b)^Tte!eDVZ+TBfJ8(UVA z%17GTT31SHBChp`9xk)?=wx;8Jy zkK;><0QnliR<<09lp==8bF6eXttXE_vZNuRr^D^?i1<-?d~IIhz^pjm9t|KgmBDF@ zcC?5tk-&H3SnG7Gbb1?CkrzSh9#lULpUo!jvv6Zyct9~GQWZ50r1?DbrlSdR5G&0p zDv4hKLNW_68!;CE>uVfcU6efuiz3wkN$zZFA`KYbk5TnHCvmm9TFAW+%MTBBNd;@S zMf8#idakIdun|%`;eb$!;T>#r_#JH~CqZLHpsaW<&yNpmE?Fp3MS+AEXy5oIBbGt% zJMqW?tN=RSJc)mhZZl8h|AoF~{>9vA)G;Dr5V43jL_8t^k%&k_BqLG~sfaX0I>JO> zu}qL@c>0AUn^sPo968E#?W?oU&nCLYWP-A!SnY0gv96OW%$$wDB}j4+Xg#RI5*y9t zTfqj0oWhi1`t+n!Qwap67{^Lq+ZxBvR~j;6XCY}r;L}NEFd8(fEK&77%=vu=Y8CV8 zpkN8?DmyIaKc}VTSD2;J+w&mC)S04QGoC zd2}0BH=8=ACx@dwixfB(-#$Gx|I1)LJFX1&*bEk4NCl^%vEw>pkC0}cMT=)-((k96 zb)%&sSiVg9)Qke&Mc^Q&dsaqBbjlAu+I@x1ypvl&}@R6zH9;ktttDxz zK#i0mS`n)OE$|1=zznj6eqt5;?GPbuL26I&+pswFw2A>6^0ze+kiIWGh0AKqEpPMr=cDN9;i0+9Nv=Xo$$8 zh=qt6r=`Gi@?Dq{sqVpYlyQ%>H(5=iL=co&LPB2BzY^i zpl31ZHAE4n%bl+El9D)GEh5>6Qi?$9L!Lm`5KkhWLewFiMm&Q!0LYIfI%YiCw|5Z5 zFCbX=Ix%zz!KP(7hVDbGL^L6WXMl(hm2{15qSF=nVuNP+Jnfj1%$Lwzb29ZkpoD|r z>6CNakMz%Za{_$jX})wu<)xJSPOa-+av|${^G5}J)%Msa^vN#bWA4OOT;B{eAWbI_dMU@P~7sIr*3F?bR4Th7WYD<(C3ltbG<}qBN z!*F@pB9r{%WUFRDmi&_}s}^ECtMgoHxIag0T@c1fPRSSX?EmaJ8lmMQ9rX^A44YL?#1 zvr+bs50$upw}rz7d;%*DV2iM$v1CuEmf>E*?!rDblq#4*Wr%z+=hE3Cj9gU(Z0Gg% zaUmU>KBQAu9FpOiPE$nEfu&KgIUKj_&r^Ah!x6286=T!Ym4h!bS|g#K76li|Z{lia z2K}N<_jlSeA*3tvHk~k*I+ta|PAHeBbIp7PXO9lmUpJk;TVdoYs4F88ydjhteClQ} z?>7;=-)w9F{mU{FUx~7^Nhk~Hjl5y@C!6JhtW0K$5@o_zSCloXnIByf-J4~Mu%oSJ zk3E6<>ht)8^jN(yeM(4bQL8y87)IBf4YFb7d>M6G(}N93o-(?!W-i#l{He75-k+(^ zq53N5&F}>J&4LH~Sr8@I@!)~YM)q(x$aiey@-aHHn;VN! zwx!E}kPm&Mwtx50fp_-zKYQ@%iI=W*o;FqQi;klObyG8LJk@pM#RL7P_K!M-UfaC~ zlD6E=n@wBp*c6!A^9R@zV3lo%cEmrjF_`~<*cr&kDOzi9Rc*q; zH`CMhCH{iH@5-559p%sepRT+HD`XCQ#Hruam7^CYA0gPeU>}D5As@{gK6BKDpq0OZ zMWC6MR6~b)blQ?4csfEmKsphJ5To2S`glp@_IW#eUP*aB?kyyRS9}1@PjtcZB=FIz zm#0U416p6gpXVkR{!QG~ePeQUmko=0>X!B_S~ke>_4HKT7kb`ol@A)V`q}bLmAB*Q zzi&$o3@m?^*T?Pg(J6h#tX^Z*C1Xxtr$f(Izh6{XtLHvQveZnIpV!Z_K;(i-j?@() zr)g`$)fZJ72w&8vEi9E^EVOFoTjU>GtXhbDGQDVFp}eP1xv(_w`xPy+sKeN|mk=)_ zUZKkxOZ^uxcof0>=4%+jt^_^kFEKQHHY42-&DV|^QF08GzC!#85kS0wxQws@JX%1= zlZMV}(Rfy)nx;r)Kcs4DO4F^9@eq=9FhfngMz6!$>TQFwB*+@UW)45N*Mu?VZbi${ zxkjqMC-627Y?RC_&*rFGG}E`s40=JygevBC)%0C4D^??f30ff>JWm98DR_gI($PPO z>vY5BTZj~*LN3YxiqV3RzS3OJ$56hde!;L>$O606LM;9Zc@Pt4M?1lurD`Eg2_Ye# zF@Z4=8Olw&Hl(R+8Ym!%9&1TYojh#B(SorDtYsRyKYK1s%Sy`*O3nCY(`G3B`qtyYn>mPHJ@Huo;S>FbUkTbl z`rWD&`lr?m6yERrIO* zDs!$HV)iUKa8GY+Zs*$G*!&~;y|I?=`rg=|B#;WR`S>AU%d(b0n9HOne!V>D2NO8fqApvVCLaPL*`+0 z#2+#*$j-A1F@YU{>o6oB79*A-a1eslni=Yg7zG>v!D^S6SSc#}WFe8oa zyNhYAfMd?@eF;jKPp&lZ7vE8p><5k>eb6NPk)szLT*WKtgr9#tn^k@Ti`b9o2EcLZ z7KU#lssM0r-0o}vPf1!RhN=pKCV?e=w9hm#jNaLq{$(s#DTN3kRm7R%;%4ZXItZtkeP zQ!8d)jqoCTi2D)i5bF^e5E~I&5Dy{D)c?b zZ603Th?<>48Y)J`v4EWvLh6;Q4ReNC`&!E4wU2N4_Hu`RCF4Wh&C5{Kq= zER^v~Aoh_n3jP)P>Eoq-{M6Yhlp;KCA87Xfc@$Cc69Jj)X0}dm$>R z;0KKMRxiO)i2@Z4A&w&0p`U#$H5jc0NXj-h{Az)p%h1;nA(8^fD`~N@tgTIwMtneQ z^m*N6q}P(V*#|#Ci5^K646r^+s&)~sq?>}D6B;CP0^o@N49ydJ!3Xt+-C4?sP*GRF zxW~y)#!ly#1lLRkwq1*jP`9~TTJYMNH8>AN5y77ZilEWZo}KjAUcdi&tcZPd%$Ag5 z^a6qz8D=AzG5R9nB;qWh2k|?Eg!l&0kN6gW%TiLVTPUSRzf{|aq z_r&H7au_&bzRli)g-N{Oz^p+IUfpK)I$=4ZI637uN(QIU?X+*)7`{^0=^f@fp9~BaD*I?$s(GCB_s<3l1-RRI0CrA1HlV$ z&_P83Pw+&eg12}A`gCLP1y`P;a)@UTFMRs^s(NOR9OU_a|8Fq8J$+PHS65e6S9gzR zo{lXY`NXEI(1T-4w(8ICgvb=s`s~UT0QtN=`LfUu577MMmCO6vPKX znu1f$HWdZ)!DhwwTW45fAVD)bmXD>saeO@eO^|;R<=-SeiKZv>$@JIEo9S;#(Eul7 zRurZ3X%w_}_Q0Y+{2&_F%@#7qKv&T)epu0PemG6j&mK{f$LGM;7G?|}VRKOP$P2r~$P35OTo{|fi zJ*}vaFQjqP?CC`__!&hr`I$wt_*q3od=aD%RC2+yXBQRo#YH82Nl__ZT2#iD70u!2 z6wT%5(uyIoRl<*?BBp35zmz6~&R$kj%h%F)*lfM9kV%+Ww31&*6T)ZnMNZyX)WkOx zHS^6ytN2wkJ!1CiqBZ=QqP6_mq87fTXdS=KtgsFpps*H}|0Zs{#6%=gLOms zpEzdSA8Vd)mPvKFtYmH9T8ifM#H|43h!I;0C@HhBMq+2(2E0H0W*i1_du~uTP3jhqY0!PT8 zwg9M1x!{c)7E1Nz=CNEBMdBtd+iLaIxY@c%1wDh@9GZIzMUU3xGypA^rryd8vu?F+ z!;;t`sW#Mc4X4@LDNZA-+qgXV^A}KaBQYQPbsIN|7ogO4+-Rsi2L6yPYHqBYzXS5V z=f*+p@sKxx=HH&D+R6!B-*Bk&|DlgI+-@Q(|V_b7gVP7@c!m0X%E$0 zfeh>}N`3(5>&Fxd@@@e612+}Yr&+gj>qenma~C%q{>|WKaRpa0|1Q{DV0P z&Ni1oxQK>Ta|umZpqVgOJqVk+!MgxtiM#Q zzmHpHtpF0^c-BH%G|TTt&V#A49E^5detgR?3AA zP|T_+X5)A-yk0etjhwV%lT^`%_tO->QmJdrUI5&xfUZ5mtp>ucfj=aXnp=w?_-BD{ zZuBmh%ELIpSZ+N{IV7hbxi`?1=V{77m#^y8H2H;qsxF%H zqEygVu9c>~1mkxVG>T1Zq$w{4q+CN&UXfF<(Q9eSt59PL4DogJ?KOCF;p_GE^)Rmd6Oc;a5vMpw}7|5Ta+i0bCXc7VstgxNt9SK10HkxvjmPYV`H5VGM091C+oMW_X_ng~l z&bw6bNPLH)`i?jkj_Z2?>Ojh@flQHB`3KFDMi>>vPMZ2YP9LD$o%HPk?k?+n-O?C;D9;xh%{{bWM?lJ6nsPjV)o@IkATp8FB&fB$aeNm>0ntKUzfUD2+gXqh0nX_`4i-4>( z&00xEraR8B$VJZuNUB+{dL>nNQAgkW;+H{wquj-EuSsBhg72$9$$7XNI6na5l{Y}A z*Lwgs9|+)$zX9OQ9ss@$1n}110PuDX0N(@xc;{~bIMM^aw}AkT{tW=fdI0z?0D!Q< zq#K3w0#WcDmh+MNdpdv7%9M=2EiiTdfhG7KXnjfh6u$38fV;ofIDP<=6*Z6>xD2I* zmTT{UN>>0XlRor<>H&yw2nfZsByu`>0J#u=&$#241%j9$0G9ix2Y?>~vH0g@0d&Wr zvj>oi0YF?Qd_c0mxc}Jqmf7n~U9ai8_T@23DN%{t|46go$Ueg*Fccx{wBz;x`9031LSXkAiw^bAiwDb^4lIDF9m}9?*9bx`yL>F zrywQsa_$d*6C~0Sr831bTFJ4eRn3{07F7^VG0R7qn(0{NDNW|YTo&PJK<1QbDbe8&Oc7OA{ z`z&U;OV)HB0{)qdsOY)hyQ4CL@CvC{(war=)RLgt|L)eezcYRR=mnMp5UcFZzX=dY z=j9MJ_n%%snLtwg^*;bbl6V1Y!8}p)0ZzSdh}8zZ`j#P?3TD z_(vcR0c9@)*nSXTeF*sF=>)*B2k$YI_q@%h0RdI7W>iu$LQ8aVp&wXZuma~5!qW7D zr3P4xF!$RC7i4Suz_Bl|tF4=4$^Sbb~&0xd{=6(>h(s3M8(U%4}A##qXA995H$uYfO^&U9D2t2G8DT1YDgqd;4u8aZT zNTLQxe|)LzlgJUhAcyqRfk=M`{P>UWV>;n@22Q7_Ud@Ec9T*g!G`(MOATdWEu$W%J z!T^|WKE?KhWN#dStSDsyNsR(7t{3p|eh3opYfBmg7n+Ivj{=J7o{c8-YBYj2x)i5J z_Xki+^ft<&s7!*tWc&joHQxn}$o`twK|wQ>BPlc-V7(4fz}W*~8Vv{1a1iKoFUi9o zZ*VUJBl|>9s80;}FVe9mYh?5S9fhMwr@7FW806}&KfRe_NH1{FePRk!g?B4ob$nUJc@W z7)cw%S@AvmjglKQqj?JN`Bn>rqk+ZI9iyG$BHS1R130C~MaD|}55>k=Q7X{FAnA<| zA1{|30M)@5g_H?$N-D&EhCjNs0npOqce`vDQLZN*!dd&jj%@ z3JeBq>zqdq(bt7zXc6YuZF(ro_;^d#AnrXZWR0Fv=1@>cK84T zH^6&C4;~5dH-J_|z1c`L;Yt{KA7@bQ!T0LWSTEiDia~BVuwe-#)&EWe5n!^7^8)Z; z?62SCMclg&O!Y}~4+!Ha1XtgEU*!eSL#+7cMUUQln*x-(_a9B0)xG*Z!8@Rn`@nyV zw{Z#-hK%CBwg>(bB@n`~jGmLdJ8EdZOM4OB2Zio-ce76?^+VJ3UYxpXD>yI!+w@6v zi0IaMH-M966kCQQcVA*aHAD)z5qJ5~!k~Mp-D($jY19XaS}%*vRBNMjasXh`y>$sD z++Jb<q>Et8AfN&Wp&v05(vMu2&W#s@o(~1Lo>%K)`i5`+K{W z=(5}Ua*d&UxsA#fByeDZLazpkdk?ZKX8_2K|Cb(1Nc8IS?Y&TdA>!_^E`>poW^b@4 zk47oQZK-f9E2;RucoMM7cLK}66rs8lr^#KtS}Kz|3jqIDrzt(-(2bMl04%y*oDWUy z@{UaRDNo=076C5K?&+ynAno2>h|Wde)aQW8@qdFJNP^wHAeT!d=#z=}bnAtLH!=f= zps7{|J??}@P|#LE?xn{yy3vFihRW~06}X?tWRQN47M`M*56tagU zxq2|2bj-m!Za6QV?geUr1gcM_X!GI=HQ|s-fUH{BXDuWc6n)lP4Lt=tP*T#9OmGMb z$~^~@*2_=_dm(0%`qd|5hp2FRt!Eyz4`4wa!}zSEV@1!m1mIoOC*Bg;FL=@JG3Ert zD24W7FC-UtLsIzH@Mtr3kd~%rVFKE&mdXlaML+fNHZ&PW}&vjcoymm`MX+2r?g zd1W&CMS7gGfp(V%kY}pZNLdX9?7K3FR#3dE751LIj+}lJ{@#N>uLW{Bw9o>fpy_nO z5unF(x`~uJXvpUSeZLz`FAEj`fq$$UaK!zCUQAFg_oA;(xO=qal8@o`5FDsLrN#{1 z%$gqOg@B}veumO_favmrIoXR374Xm`G~D-S_Bdq(O*bGBeY*R9qoS8jaCnaQqF`e` zo%+a&ae(0R>8=1d0D%ALJvRsO&R&hIgwzwVtovAIKwe72Gu+lq^cbHsOKU)Qd*>^< zt_kOnYdFzGI-L6iPHe)Yh74#F!jqJe|DtAp1@(e{N)bSBX%o`T>wy2PkM02D^uZ4R z5|}SYYJ&1M;&G~1znc3Y-sjy~a~$oGeXo{3>RW4hl@@l; zWxXr{&{NzG32gq$Ud^xWr}^$@ruuHjg~BD_ClN*wEnF1IgfcGMJ9S2r{}nhI)`H#?i^ z?T#iPbnK{Tr6)qlo{mL)d2KVtMld9*ZNd0QNL#{0Gh;d*1Fh~S9@VmjX5J}`pL{5P z!ql-=i_^|KtpzppwGL+!UuB(Ucdlq^XtY*0)Y#WpSKA#mRm*Futc$CvS3ula)!1ki zE=@M8S^(NaA*mpptZAE3FqutAfdqac1RmAuWp>`qn=v6CgGAx}!dKPnFuGn?Ha(B5 z74DfnNQEo!DQ!olN0ab15cLE(n-|yDI-Ru*4qI)FI7z3BV%$V5c#cgIwiS#MLv}Jc zv7wnnh>Ma~wYYK^lRS{AG(lDRWWfcwv5Z1768`XUC@p010ENP$6z4XRWbx~ND8t2L zD~L%6IbuPuGEz)luGEXqr>YXfvrjXLgINn3u9z7DRaG2gQPts+gg)~J)~UVmlCayR zMT_?bsp4H`MJ4u+J{I3upfp8>vSoTn6~DqcA zo769x)Lk3xE`K*exl2!d9{X?@t%oEvjG^zp4zPliMtj~?6+lHM7T-5!#CQXA8$ zO>WmFyHoSpwR!Y4wOyOKr}}v2r1n9R+O?A|s+6JX)>&OzMWQycU1L5GktmjJFFT%= z*O`{zo|b=TLVMcGj)+;pjv1+w!eTe8PsF5dR^J?SA|d&o+Sm&!MR?pVYK1oVgjT;* zyG47m{-nXQdG$@>-E1_EY{&~3V27(g7)_37Q_jpMQ?ABD)W6etjAm#h+WIMfJr=kD zgKIIk4g;iohDrt~te=$$jK6iN02V_!JBs zKp!mL*GL8h2O!m> zT2)ooZ1>f}q;T6}WK`QqNN91qd`gmw#l9)~w4fdE^bH+Nbj z((EE$P;FHlXzt9P@nQZ9evR+`K>LB<_-11rI_S9mnl z4fTyx)lE)p2$)o2(MVe(-%!(B-DInEG=UVg*?GQ!=f8w94+sOUyhcr#;PJLcu52Ix zIj(YS?1zvC6vu}7(-8P5C)8KQsm?;mv%<}lSuU)Zp~_$~*cN?LRm0+{hHOBgMb}hc zRaZx&s;0%+)s7a8J)1^;#`$yh;LbBo+yk|k7WMKPT8te5rD*2q7alu(Xcx^4Y6O|k z45&*`gVt6#maeeNuP78;inBMpbmoD(;6GYHU(?XMw$?!*2G!b~{@0(4*zS#YoZsDc zZpX7{Zr=puNsDGxZ6g+LrUGWilV^mDr(e2@e+bHYw96WtO^&L1yGP$-U(;lx98`^? z;C)mI@zd!e@B^=U9YahUeX7oYpO!g4AmM_E3p;&Sk#~jm7oH( z7Dh~|Wa32g*R0Bvf}$HQ9j7S_3bPP8FG=XSQkU;wIh4{M_9+~0e#JO|QUfqcpjQDk z6iZ2ls#HRsWQ!lX%0}hXK+%aLRbf`#uCOQo%s`llq=K=Ku`?Bl2_#*@NKq339HXcZ z4=*B-E>2+~S&-q?w34q}LV!KKha#mJ#G?g0>0Djgv@Ao({}a+Y z>Y9f7s#=GKMHmNfA7+2iXPs;lap6SK!J6-%la zjSJb@IRt{=&ch^go48~7uSIQc+O}%T)t$lP_e4CLxHoa1^T53Q>pN1$9}gaXEdP>| zh2qy{<&q3GgK5Sg|FU(P#BE=;Zs*TI0-*gB{Lld6=P`}}l&7poS%m)@c?$$t2jqBE zbq%1%_~RH4w@oc8DJd+UT4PbQzry8SlP}^jl%E{z__yNWpj#i3TwU|v3-AQZ&m@8t+a8+cX8jf1X z)6xrZ4pWjR@v1}ZP*p|(_2^>>f_bN<^G@x@15Q;l;>J={RC;B!w?@ zmjM?=3D66iKt3^xuZ>nl5+78d^e3%w>B z0Xd@=IRxP)ja9K0-RYHD;&8k>_-xzOqyKhZj1@DDHD{AKGk3x@I^Lw1X5P*r{7I1d>_ zg>4w>`)C!wN~gMbRsE`>r@#vB{>TGa8Y>fH6t zPFMZ<_WJd|qFR{BKyCp;e+ror1`;btDbt}Fe_R*8bNcSGJIgu~hVA1IjPBHpck9L< z8+Xa62f){+7etaL2SEUaKvw#sv9(S1`dKy3N$W8JOB?z-t0tpz!dRf8)wy73y0vEA zsLTx+Ey1qJNrM*D)=coFm~yaIj_*A*M;=aJ5|82&)*P0~0oK6_pgrfZhQ?CR)$1{0 zL#@5uX|JoZ^QE=bE959m&Y(4{&LNd!CoI690ah14s9cDE)(y)XK5``BH2Hr5IRUB< zlDg%E(3}Yfo_Rq$FT4Pt&TPBo+`|VlCRP6M(p_V*Rj6QfWCAN;lP=n3GYY9MTW^M} zFI#W%p#pIp=T3&o69y}g9!k@r_cD5IjYsF}yT|BFruK`Gw>ul^R@rM%WM>3ZrAD7=ptwOBunwGZ zlr=v`Fsh||Lvy1?)9hH;+|Xo)rP{x-jXyBJPlI@reAQ|X3xJ#+C4?SB;{?jZh?~=+ z^_l~`78uu~fwd$o79Ac{J=*HL4igPcwM}()o0Os!hdszdx@099dszX%Cqh-UO`H!v z1XZa%X!DY-bvqeYly&M;+Vv?N`qb8`CxXMbuHCY>J!alM?$G-7%;Juic^$#?T4$a# z1Z^FA<5+jphy(NAEPrRg;RWpmu65eSWn4#Ch3i<;5#^3i;`r_3JHyl4!_)VLKN-J2 z{=gN7syi~K{4;#&(Wchf?y!oJ!QnqKIQ@=}yGW-YEXiPX7oz@Ep$r)UnpvN)bIKlV zhc2T_qfiCGiZ3jpwdf+FicoLX{A5&whKst}bUO#{8U4)ggA<;b&>m8-S@oGA#I1`4~0Iuup?%CXUvrLm?<4G(>BjSxS;^+r!Yl$q?mDAhC3neKy^o0)!5eAr;-Mp zh%%puO!{>6)SZUTn2h$AjD0B`F`1n)!`owqACJj95(W#?&X~#1I;#slm8lER0vJp&@MnA^lXIDq5VJ zLG+A6DW;5IlEjb-FkR4N!lE%E&fQL;BE|vx)TDu2jP*8VVTA&B1Qq331X{-F3QrI4 ziWtQJum-^X(4qao=_^CT+@T~v9MVc6j3c3A_<*q@CpXMfMTA+DoPjgu5-w;A<4`9l zyqTw7QBwQobBiimeD`iP+-OmACN6jk!zdgYu`HU665O}ylv;~M9QGL-DYj~ePF$O= zf?68!^R3DVad|%YfS$-Fp+iHtFfJV6>)^9T@Xw1sxOxKUd4={0-AJXd;?Go9`~+pP zVhKr6RDyjYJsL$77zJP}5GRuitCuATsZ2(MWDT6(22^Vv4~4&a^5D6rcYgKEGia4> zz5n!!4}96W5td`H@;WcPa`x5-&u+fs%=Md3AG-1MOM9gB(=Xh7?!{-$?b*1W@fe&< zuBxVHCm72$c35VBdateH8GugpF%^{)aR6ZH0je8Zf2hE#Wi;uJJUohvD558lg|IHN zDtNev$1@z^l@{m(cyAdTB%bAzyvhQrBwh_ZF4i;F#@nx;vb2|l;a|T@m8EpKy$1YU z)lD<295tYcYW09+wU4CGI9eOw@OKe&CJNhEq=;REfaCr=!~n->aHMuK0UW1;vh=ZN zgq6o6j*Dd~blws3aU7U-l?q|lxdidZB2|R=ghr)z!Sn!gPI@Y|7R3Ts2hIyX(3$yAGVWr!_;*o3M5;1|bl5Txusc1!2kOvtm3d>W1)WE#<|9=#cQJoXw4P z-V*{&LP|IwHg(Qq=shfG^Ch4=>?=LYl12|phhJImTpG)`wnq(hXI6GZS=}Mlli@Mj^V`FR?wfj`;x$c2_#C%!j^x8z z4Q*yvB-!9mqBvZSGX2b>vOI7x$}?na+6zxOWPzBIJa*N~&`1KNE?iS>Z$x)x zhJjjE9!;&IwyCzN&Z7f3l2PQ*OG|Y$sdyD4Isxg=PlKpO3%uUg;BeYKIgY0_ zUEEN!RvJ@SeJQ-N#OIudz3dF(IRN?}sN=i=BA2(TT%Q_DCr$DDlM6T*KbaITF&$eRou;&QQ`!k_*on|Y zck(=U$Q4~GMex8bg)&&(I-^UgQAHyP3%4xn3`%c@|1u_niPsS{wKHgDd(g}y(eA6P zZj3H)SJj?~G4Bq(Gq@ur!?k(ViST%F!uAP!;yc2#I>YnY!}Csr#B_$3+e6HqA$jc~ zc^x66IztK$4L*|IrBp{2ihrp?oSRVhph5kKR=J>0&G0~H;Hv2J$kufdr7QP6^a z|D;zKBQGk5DjIrtqp3>?vEQA;U`*bO8$Ls+c*|H2Iz4x|^6f+|yuCeKKSQB;d%P0j z?VR|Tr+8VVbK(Z zxrzw?S$u7w6)Rxdb_bnTMeq&+Y(0Xlg?OL`!4u+B=_`2(o^OC6qlj>{x*qlt@@pO= z2~-=R8U{1w%-%=OY`U`<4L2}hV1My1`vi#`M-V=x30+@33a=hr#o9)@)I;nycncc= zI=>PEoRTY>achh}h&6x1@*27==vd0*rbB?Y&@6ciV{ITO?L0_D*g0&V0>KGxeLed1 zS3`{g()P}h&4g@eo3qSH!ZssFRZ|0OX!2-m@bSVswI!kZFe8`8Q;U z5V|6|K*QgR1#iLNRt&acfOZ_e9RmRZ7^2G;YMZuVD3kjzG*L=@Hv47Yu&x^Hp;{O} zJ1+u^9zF|UcYQwDAavFbGa#`&BnLL0h6v$~aasH?kRZwHM=*vI_JHJSsN1jQZ%3T& zzyN{rJB4+QLFA}#pCc96<88-4)qZTNt;=zMNxU0NpuXgHVIqzoSOl_rT6lToxCGk6 z-B@f728ap27h)8b2!2{-AE@xSu;d?vfVz>)=0#MD!gkShe1_@(q~9Ps&F?3Vv{^w` zk}bmNrai7L2)PX_K7+xt5O@sbWyOWI;({rK#T<{kSGt8y;$Bgk)tLi|lw(g*vZ9B852{7KoF6R!Vqk0MBSJ@c~Z~Bbe6>V7XZNH4a}jTs)V+C1#7} z>y(KmK)X`j7}_%b2H~aauGA%2w17skMJFU(KL{6mD^I`@u*|457)usNo<+_qLrjqx z7$CihKZh!jFkvj01}SdWIH@01uxR22f`53BLob}Vx^e3={AMAe*H@1A77;@} zQ6?~zqs2uNz)`aP3ph9M zQ;1ogD&uqEj^kV}`j*%_$dsNEvos|vG2Zoa6)cniqxLHJ-fZsH!IY%p#GjS=%y7lL zI43g<3#}V&{9X)VcpAmke&Bj>x9>qrUUdVlJG0Is(HW2an>>*qn{fIhfB)sjlN z{tC+3mgsUDQa4U`U|SZc61U&QgbQc3r7Ml4FAE{thr;g?`fDgXDa^SoMP)2$RKWQZ z$T5^AV2V;-+9m%!DF4>TzoY4|uJkM|uPfauzgNreAUJPJB~q>yasjGJTLLbNL z&hYyGeEm0?{T{#h!o53YGRuhY)sAT{PaIDV^4Y4SlYF)+-*G*sC)odDYXa-IxgN&5 zptz#2++0yGrMS?1`MTzUY17P8%Ze=}rRE+`%<~G$r_L-WPaiQnL%8kE@Sv}rz3%)C z+rK(+?b+L(87ySp{w%YI2w&dbrlPwE!rnVdjK3#)D~-w%_8yE3`rQX**znPqVuEFZ z1|&V*mS{;4CW|R5{sX{Q`2LRV%nBlG6ghPr6lf_Ea(50F7E~LBn4MuvJrOc@E+p3q zH|=~wMHlSCygR>F8a=V%XBny}6>N?1hlIswP5ah$D_8U zWl$d^mum)+S$N{^-*8y>?aEBQ2nd#fsd)qlupd5K3qKweY#-Uz1g@y~PT`MT$;?nj zNWABj@L#Y~v?Bj2M6sIi{XNkkXrt2ITmE-Q&SBaj@7+rneuZ#o_i`4^QK4*Ql#sY< zi+UNncm@b%_YHuh0K}=mTS}qvzrlO=wh=5sT*?S>d*_mW3w3+zGJ970^Rm@eFamqu zF!f(hprukMy*EbS?wh6@#t#+lx-U+Rk_lENFWfhfd?1{$FLS?rs)d zzCR)F7=l6zSTeMAkPUm?wX5trt}X(W1K;55vlzT21U*ogoyLCvFCKMuLtS&d!=neU zk^^vqwWB92VERbePND9BnXv}xg{})d-WQyuLfZpPLcxRarpRtwCU6g~ibc!aW300; zt*TxtAB3c9?MuQJ4^CG9hzQ*zq(4*+n=Kdq#Uu#Z9x_Bp%dYn@4+F&7`IkX>?xAZk z^C!Nvs?F7zU*4Wy?&cbf=Qno5uKX~+ao@Z>QMQeeU;sPFr;OoSXK$Ik z)9_DY+J#^M&=sQ4hP6GuuaF5kF=YIO*q}tUn~m*C5dL`NMCRXX*`1XCks%)&ce#gD zxGjs^6;VFu}c9Bcfzt$Nt2-GClZES(6G>Xt+(?!*4ugTA4R*9Mto!# zaZ=d*WMr0m$Q<`vt9#A@_kx9P+j95974G!9j@0_&Ar3DNK~VXp5XG3uq^%u?2h+TP3xcFqQ&IIJTBkA{FwL;o~schQXA8 zzgP@25|+tP;pzj0uD5^@4(FMgGt{pq#y4jx-!Pk2DcCm+@vBtIw}u6;idMg!p1dkS zb;O*!DqD4QsA)A}k443=Rx96)h+iF}d~ayV>LIH4+4$Atl^-ziYfMV_faEo1WqXEc z&2aX^i1;=6%8s!3wL0bTNYmPQ_9I37TC?(_(eZ1CEB`sp%f>nAYX6r{Yr9<*7a&Y+A2jzX*$8 zZ&aQh9lt(Fd1jnxeJ*=;Q2hFl%5!P)8#KzV!ltUOW)$B<2XBaFzZsMW@o$y!8X^sC3{ejTr0W6=C&(yvL>{ASj#$+#%L~?^=or9 zmxk+Gh~{^lz9mNUyIJ3otNVSlew{}1Z+)?TU99Hc3Ho)Jx_{^C*R#4mjQaKQnm>~C z>$5a}jMQ&nHGgXK8=^FS#$r$YOww=2()^i@DE^tN-!Mt@=U9yYhY7nnLMav~NtF5v zIGndISUCJe6r45!%Ql743wxd(v;;o22OGFH_(UY9hET(4A=J^ho-;t)$OS=YqG2#i z38A^LaS7?LpoTD#rbp2*nu~#ySS}92cnsn6yAsc#B?xTW0$l=Kr6*ccusn{|B*FiY zBni&tlpKQ%Us&-632kjfBw6@RTXU${YpruBbRjlCTsfLG3#}jNgvXzW7@WkVvI>)8 z1Z&Z9Y1weN2gDyda8PoVWUnG2NbWSNOdv-9%5Vk#=56-qD z&t{RK;>Ino*w8;$HZId*gq3xc#ROsY2%oRPiwSrtWQ=`{-6A!%G)Z`07$`jd+#Fa= z>klp(LiMG-p}EPnxVFUx8z1LjN_n*4&_RD+1OF+!QX8m6_{SY7seU7Y{|s|ZLC|8D zGHb@H(h75_rMQ^CAgno*Yi^14rj<$Q=4pk~3oOMI=3J_*Zab7NJboxsNIx_nik_Zs z37S?=QHUq-B`}+WQ-?;8589%ik0hqYp&Rs6z9*%5rA?T7Fj|=V!gQ+hpMK%mn42&g zwYH?^<&#hRC86ZSShZw22z4)xArA`=z4+va-Ua`IJt>BP>EY!=uqBZEh_LykMi;IH z`5<_uI+{0OEEt0Um=TV#8!>h>22B_=W3UQ?2+WPdfNFH~_-2Ig?_;}(n3@WKM+aIT zc4=VSh1vrieT^M9UuX)S#0aZjzJe)c1oz7^5wuT6tcbxH_;a2X{&+dd)y0H{s!wPm z+)=PQ0MS$0FgNTGs2~bTMi=3Z%|4Otd@oqwRXw1ZNcPd4B{d1MB+A`EiZSN%~D!mshC+-KI^K& zY1FRb(O=KU;;?DpYDcqUsU1A@4Rv*RAqb8H<1U(XPXw=cN^X4Wb453RIT4+{lH=7_ z-OTfN+@5+~(S_C~WW8|@J#Al2#P;dn&N%(XLhuAneKV^9yRaYrza}nW+-b3}rLLdka`i zngvd4z_$M@P#oqVHhv=n&AIS;`o-(dU%T(TxK9lEKpEpYv-QbyPwYLnZ4+F`IkSBy z-3j9HJbW*NBD@IEorU@;2W;5z{4ywd4E~(BhHq7z&=_vGdgImZ#PJ=P@vt-an7T8) zpgq07U9`U4w85?2aKaGWI-Bkfx1{D&HKx|)(4KkE0%m!ScIL>N_a0)S7pS!30sif9 zG*#I6UW(xQSE!3qW;3*x6?6p#$4E5J=IUy@)9GPx9|_iW9QGVp2jX;NrWP@UKZSQR zV=i|_fOkMKHx^Hz9Xk~re|+G?L#tn1_x!peqdO*57&-=8+70vE>^!(2^7EUM=kaw= z8g_U90i+E0V&v_JH5fw);8DY=hPtL@JRWHI2w?|#Veezx4OwnBOWHZ#j5UxCs~L%* z?tg0&aS21-9&AR2f>VRWfNN0Fc7n`a!pgVfa(wmarkE@wz5MH4cH)&Leih;@yzus9 z7O@mhog`60#5?Y>xQE13Fw({nzFv#eY{h`?Z)}1z*edE-NJu&olR@(sejiplg5{Lb z_S`!V_mGu-j0D?}SXB!k@p;>ZBUdqSPvyk1X)fAH6WtVoU2iz~(M0bd@J@v1n@0RX zsK>v72&G`g1PnG}3;L?&re!v1V+U6Pb3p3ni5C2``vIf ze-z&dZSOt-dlGXzv2E+#GvGCv8~!ouN{XIN+OxvmNxOodVGJ*v@$0cQADW&BdA8@; zrW8!Gl^4#n6mk__j%<{7u3+_w*46CEz~YCd@%xJwZ(kO>jQI30?=d-XV!aitC%g zqV~8^bYI8ltasXK?5psoiQT)YiI~#sWN@65x38*gXoiWlx~jGbniUSTM<-Ag4*|%I z8e8MC28W#<=i)`E_m}Wx`)3l1;cdvalOHCqZ~zVf(oMKzBCwsQ2HL%wu$e8w@Xkr( zMuG3-U9{Z|keU(A(_VF8kNtF~UBe!Dl#LCI0e$X+Gk6Njuj{E&pb8(&0Z$Nh%hWY2 zg-xxhCLSB*=i~a^11CY2fT&mo3{M3KkD#I&gj50we zXnrriH7VO(Jh6jN=K5Ssne-tc|C3!3b7^}r*GcU2DGYpk#b1jwkp&wXTs}5}IGhub zE^eVK>V7CVL@8vRyh>szNyY9txq~U@CjxElep{4R{sK2r4LAwXb# zO*;OfaLs4wTo2l|AY`O%z_{FtuavfQqR>fAoglj*15~k}z_i_`gg-ws$5G}A@^(t1 z<6}@hPbuV|`pbX+5dO!E&?JzB)}>wOsab<<0eh!NpC2zPVjD{LNo+#ow#LUr(y8UirrV;d6kSrLo9D4I*0Weqa>DD0H5mwsB z9wO{IojY_jj*4F`Mc8U;9ZNwftiY2=OKO)kVjx@TO-Ya+W(A9J~#Z_bd5&Yy?k;!Bs4K)3Sydej>c^ zlZdeD{8&kq1WV_l>ZatPH?+Kfr?#;p^y8F1RID1!8g*f-J(I z7z3PyUU^HQ&Vf{q(!Qpe-c|EYd|~3(v1+uBYLsmYzW#(sS%^q86kq-g#9T%eVmKA~ zH-#&|8zW&YpSJX2&A)@?-@@Ps27Tl7E@t^~;*Y{>51dT?;ifk12T)`+a;yNj!TCm0 zgi!mnu`TiY6O4;Oqln=k@P`pN(w%=DV?Nw7f_hMxo)M*o*W^Pw6z#XM64F=dN*}!d zPDi7Qr|mWp7%YEZoYWMTXe-=$Ay$1HN?xaId;G#fO2$kC%g+-MD0#_cDEq|ElgPWm z_dic_ArDHDlpX-|lb9ZD?Z8}AgaKU9KkZQ)c^47L3KCNy?WwsDh&hz>2v7Zzp#B%+ z?ohUM{F0_&KmlI*a|ku=q@&evI982=0~bKx(giFrVM>9Ue(HaUiB;J4pS;LZP}`%e zgR8U6Xl>pBuPvFvYhNV^`tM9>aC?(=RxPpf|3DOwDE#{v^9>ja@TRpqAJC& zE%PyLBL-#+=%JMJ*eQCL#eY17`lG+a47#;}{o!#)Bs)W2>%=cHR5_~QI!O(D5}+>* zad}kqLP`Iu?TPerYy-a(PjumVHaNEPDK>|?*rQtEXjtu_d;|AOqym1{;qL)7*jUg8gPE-<;+Vwdk!MzwHJP0$78b!gZ8p&9pl&6CODNkcT z)&bX%Bo}}Izm!l{wYC(G!+eR@oyOn}q|zCToyFiB2EJt(J#<5_wVuCi3;cIxd-TpT z2Os3E(60;~ZG!(5Ydj-P5`iN0+WY8pv(>GX{ z`nz;+KS@$7V0_Xj+&W{WsX`5656M0M7d-R|8UL{8UJSeJbK;5W_FyJ^FbG@#Fg(NFpGaeWVSp5J=5n#kbSS_-3)wd#g8u=Brw7B) z`Tsp;qye2^@n&xVr&v{UU6ZuZ*axZ7A}JgT;hM>#2F(s@2DGtZ(+h;&Cs+ut-%D7% zg|Fy_%ZTBTf5%DMf$Dua|AM6pBY2vbo`L2EKwXa!uB5>trV-5%r*!C4qZGH8Nl6~% zLLHKUE=Ua$8Q?n#aAln!VM5?y0&JzhypjR%M@4-KnJ#_K;R2$L!OsV6DWu(y*NF)y zFrcFL6O09lT4cRY?9UVk&i{n5H^uraGDKSPP-S;gye|vJ1`Qx;@bu8N%_+jd?^4CM zY!bqllwxK!nN98x*JP6<*Z;E$%YZgLI$WhnM_H*ppmq*r2*1{*1B=5BH$f0lTuiPQ zYOd<4i=>H9PN zNM>>8Br;=uciDX2jNqu)tpsrUjndi9*Rfl^1D*kT5^dt1`?ivv6!RyOln51cv;sU4 zR0OwS;W|dFn@mRaJZOAb#Y`*tg*%lE)L_A5lk^xSAC0|_!GNMeryIIIC5-(_Jy4$) zL$+U`KZ}?FJXmdDK$mT|Vr(P^)CY77i{P@2&U9Ekplg<2fX!5h^#vqtCQew%uZp}O zsUC_wI#&a5=|e_JW(9*idX|VmkFwEZt$3jTIAs>3tz{2JP9e{+uw=WSWn&MXnNErc z`KLI1CK;tce&Cad*f5jis_FE4Q+#kH$#mhOMzVLP<%5>F+`9m_@E8 zlabvjsEc;Gq%|LgO8eE4+xQgrg;E=b%A*1^2mG#Re0jZUPl=DuCNXBJsv~UGRp7j! zeoz~D_~?c`Uk=zD5zovfJLJZxTTv8>$((85L4SV6#p>Cu+s=zmoPP1eGdJ$V`(Kam zJhN*bbqIrgKnT*ZM?Ps!o#RjyCNfOm!6hU~Wq~rs#iA0DDSHzW*{FltN=Srqh_sl7 zi+*^a224WSsiJ*)8X!2KFAB*6$G3^^&mqIf7b2NUlIe$N_~#&(pNCYyqd5|RTCw{k z>R`lASnwdKCD$Z%l+fD@hv;XlydR8Oj~VL} z;_kU5GO7ieJ_sq@MqNBMm!zm{0LvqG%_XmZ0R#uG2QwD`VE)bw%>13n9GGF0Mv_i7 zdK$z(rYYD`J_Z{xFk^sY>tX9^SJ>gOh{Fcf%TwY|3rPa@FS3vX)iP+bOI%?g?-=L` z`Yxy>edFn1#XRyb$@ZhbBPU5DD}!1vkXTr9QuziiV?Ie$Er;yC#JTgygHlgYnYnxw zRtZFYJXZei$n!N&k+);81Olh8r4^MVPF)8{Au6%X0w1$^zLM-T(N4^SLi{WU#6>ey zQ3t0iB4s2Mw%CA$=@*^&SD@|baO4~k-~>C|`NB`f@h^z)E+p~eRMIS-g!si{FcAYp z7nbQh(2^iR3Ir^P#c!)fx*7#tvPz6wOrDh-zGBh};+eVvA!q}HsehS72a@tI9l6h8 z&|svf#6X{oztiLDNW2rbjUG-$1Z+e5z_~0T3DJ2@&!zw=8Kn5Aj0HuP*Dc?Lqe7=FCh}uRHd?mHw`d?G~3M-P)3z6@2{0+VnKVhC~%!~zuzjj)JUuZ6_%D)H7va!Ujb_H?+b z$HIq!R`5tQe%-;Gl`!4Ocj88#j2VbH!n!8~`$vhq5o1`=qrpuJlpXQnXFQ24qoaXZ z5*FVQC@i`Tnv*{AhV!`R;yYY&+d1K5c76fb3RPyS#Hmi=qH_ukzTt%=@m(i*U@9Gi zE3p+NzY$?ygTb{B_%|{j7rr8d*g30tyWIg_ZGbI8xT&`ZiY-uyPdAZa-3I5+CbB{q z>Oe?zgy=+VPzv>XGw~xL6Vg#+0z*+P{|?0aHvT;s;;?ljN;Iz};lwHCttA7=UvMfe zivk&lK=>`#NZ)4tjgZwWo?lA_!-6lgh19#!v4)?^b@)mLz(0#9J?Kuye$0IY1Ij#T z&Qm+zqjWacOWW?PFm8Msvgxgeh8th8Pq0{}qKJaUS>w^c`NUdHV=YeW$3=D>;IvlE zTt^brcRPiE@jii_e+QtZ~BMUlBh5^ z*vo-Op848u@(`UX;i=Uf>|G6q7np#PsI3W|3yc1jD zDEQD;IO=Ww!oWhe&EgNOB*vFnA(hZ&K-tzuiC$d09SHXV){5Ty`Ejp zMrff&y2>mN@9{g})c>h4_yp#F9l*GIcfqmp$tzgBn1ZiJeU{T_2a7lDAn{QK@9~>5 z77h%-k)dp+kXXbEE8yx&x;&V%sQklBqy+<6TN z4%fhN>V3mG7>4r^ab+Zcdf*NcIj6F~S5FUDfEYCS@Zo~9l`zs7(n!Mxk@UzN0n7vT zutnP+=&b(AA=eh5n}sHCR+UD3>lFoi#uv;%?HZE zLFA**a(CNs{U$Or=X&r1J7G41S$&}9VEt3|oukS=991T5Xi#Gjf#6qW)}o0Z?)`&| zETn?)DX7Hn0^r@CV&XlJcq_uyQn-iGUd?$SheDhPq6_ZhVemZt$fY>{FqteKyn&>9 zMKqPpZ(xZ&g{)_=xN#GFx3##M(UP5F&So+zEZ7s|H)3$VBwoC6Gsz9vj8Ld1(?K72 zz4+E`VRbe}X3TJvec{xDstda^NwRuW+>d``!TJ7UU)|nLs~h~O)PpAYUFUDiIjOmy8$S_cizG^&3|S4<=2YP22$@MP{is(Y z%p;dPaonXJ%ZVbTiMjM618Xt(2~kHSI`PEN1CeDD*~5w9bCm4iJT-)`E5he!+1I1h z5WX9fJtxTco<4g{nCboSf`N0QBdVdJz6VdZ;QPf*YCOMVQItzr;`hr)P_#pd#FifT zDh@%_=YTH(K9vAs0Y9%Mj@m{BOogun%D1yn1zWr#u?8kXi2*gY4~Fk#CEVQds%H3B zASlbHY)k|i1R5VKGzeCUhqsYrr4~M~gSuAIT+DWo8>$Ns@Tj1p#oTRxncq5q@AygJ z0<448;@qp4$YEOFEzt-N+L{0}!2lnCxm-0d_g1(S=H5=&@W3iYhX!nsAo0~!#vH-v z!9GyKwKB!bMiA;6OHg?VRRrQwAA=g4^BKr(8gs+==)xO}}LOTmojj4zBMZm_t1$e-J2P}RD-HYO)`qI7Pvtt^+kMr2?B7XJt!94NzzIPq?>1+`CeXLNddbo%kIjMu`% z^LLZ6;-p<KA{ikQpSs~>;l&$eB0z6k_bPQ_mG>6ClXS27vEXDZ+d&ea8xCe zLPkRQ)@fa%6~>U(*_VE-7PsF^hSdC+sZ7yd`cbPi>zyd?cMd8JR=fhY57@)TU<~6K zNH{z+vUmvlhB3T2hkYYejbToBaUT1oS`Fb*MNaV;?a_%j#S``K=~Ynvz2J!A!OHgr z5eVgzwg=00!;&z7{d@7N_}LyZ+!X}Mhkq8wk}@nc68#M8=T$BL8WsX>k=?>{=&!|B zAgk;M$MFY88Z`~xg?OMt#uIOIu64k-mb!VV#BF||l9s&aPIw;*#;C=&?;{!Dr|Y^8wt+~4yxsW#d5Ec0 zioZQT%+ddZij<=Rv4btnoCnD$X0TdZ`XJ%5&|;HVjCvWU1%{{L0Ta45$0_KmFP?jl zq^UoK_6MrP(1*y}ETm;OWuFWQkgvF?1&s{KK5%_44&&IA0QCu%H$Z6jSX>JmfgrEm z&8Rb}Zb$7IxNOEX`{io2&Lf(kXb|+Qr0%CuW4lrUAT zhwli^d<53as&1n+&`St0XCE6?Tsc%i2|hYE#fu(ipb8sS*RsNf6=}ES@(38!?yi#m zzo6p!-p^6pp=SOMxGF^V31wuYu}>=izq1HdfUxo3RQvDQ1)p7X|G-Ez3j+@YU4d6Z zFQrF3wUI=bIg`W^fT4b#!Ksvt#u;QL_!S*sN+NSH7Cp6sSc|@Vv}Dz-eVmxUzk-%W zl!aPs=m!eu%8fLSeyqU4i0?g4;-NSiD3N`ac3(pxyrnar0Ktx~4|MZ{CsA%F@S+Vk zOc5I**i@x)shnR~fjRX5vGyMDQC8Xi@I22meKM(&neAgsRVJHTK zKtd5n;7O3SIJ-3{5&pqc{B20R`ECVihFTTJA?7bQ@naHXyv4Oy%)s5$NKX~q* z$3FZ0y&8$d)ESXjD*}UpTsoa3c048(%qBV#j2EVVE<>eAQ$Ik#CE=DHtL+?J`S$1l z@8vLZKr$dqLcJrteoPwJp9!n&_#BuX{CW&qB;3@X9kT7LtrnrDmMSWLCnfoI(f0_~ zsynHulk5eqt7X$z5j+O%;2k0k8JiUq_ono?NkKvoVkZQspJW~|=fyMwA7#4$8u>?f zPh*LMX+S3b2qE|8B`{%0$Ww#lJ7U1&(oi3)xCZ29B=RxUdYbwdVw*GTq1zUGbB1m# zKcVWG84;!7nVEWgCo_F4%N2V=i^aO}x|{J^E6&z2wpbx6bVY z^Fr3;Op-5kXI_8lLXzT+zI4%Ian6+*mZFotO_<}PbWc1!2!QD>{@E0|g|LbnpOOxWE8L1*^m|&e;w`UA8A`E6jqyMCY3UO} z)^Wxt=(9$9o9f?Xw2GJQGjh=D=*SA8wfz(BfqL8e?IMr(m|N%fgHT4LsLsh=2l7x+A<$#ECzZKC9P zY0?PKm@?ubtqS2x#WS`HqnfKL*9Cn6CWI1VGr(6gj+pX8+=L3$Khv(#7b57+7JqvI z)I-aSk|||*7$F?5?VP;e?a2!Qs4K)UU(Gj>5Mz7?HG*x;#}nF|LdOgGT&Fnq0z^+& zi0Buk9N%w|bsqADcRb$4dGqdt`FP8|kE#gSM2R@HhmeT+8TE%*wTv+s7xHV8{I?RRnYQ=6XM=#D0FADEdXiy<(+xXmfD)+tWkHX9TugOS|8Z)3_?xkFuFs+st}WdK8wuN0Vn zPKRA|ER4THh?|EkoW01{4fWJu^-F_Su`oe`#?(M`Qf{mj*S~}@gt!KYYJ@EPZNZQi zrE8oQhB=`&4O^33AqYjL-sfG}Wo}|f|o}`bwM^5(6*c+a3G(*)_MdQm-zrhN|puvJlLg+JyJb7f7*H^=)A|p=+a#qut z_(q(5S@K-d5xv;2i{B(c(K`yS6Rg>@#;;KDtl8D<>`X3gPcHQvD1ubJ;}48!8FF~! zp^+U4<$e>#LigLTZ@#G7U&ThJi~Sakh8B42>A1X>m50|JTH6sf&~J+u`(Ke z;OWgPBap8@hU1|Yp15yi1RD0oaXd7{5OgONjx$waHlW{vL{c;kqt>Vrr z_I!D^>YJZF_!69<@=XRy0-975ysIH`Bx})lHx~Lgl=^1w~J-GCY zE5GI1!`lyS?{Ez|lUQ^l|Iw2BOF9yVd=X>LvYw}k&U2NS)G}QXo`)#YRSdmQ9t>W( zFiq0Mu9h+{U05mM+YKbR(Cnxz&>uCzd87ZhewF=ViSY;7CV945e6$+W(YLQj7o50& z=N}|C3?an1Mm+K+MuK=V(n8Juo8Q44$KFq^J@0`A@;wj)EBN)yG_fI8vJWW0`7}9D zEv|5aCs}Bj4c>qpMSGXxkPO28CN6%-FEal}G3fEi zR7ASSd=rlaQ7UeXrZOKOeBF=z$YZRtRZa`PK2=R|7Q~J5Y8(o2@J)aK6{OfG$%>@J zU{XxCV$7phydhO7d+d0dO0J8-e|rRshJv^-FtbCHz9r==QMlch|CUr@uvbnAR&?iE z(o|0PgcCp&CNM!H`n5q;P!eOG1xEp7Q;t{SHz*A7=Q2H;2w$F;Y`x@Hm4{#{?!F5* zRr{WnY;u8D3$z?o95KjNSQQ*eT_6S7tWo%65mRu*UbEQpjg&UTYXdWj=vM5{p3)%Q z7$GcycrS^Z5IxzS%ML*E_=*V=!j5LcpD3n*?6e@;Kx7-FiIOz^=4OZ3_h+Nd1gVM0_ijzJqrMzoYniI5>&ojgQr^mp@Ol8}L0v zDqxnYKfuQvi%2PC&8l@TG|!R%M5?I&rh0o(f*3&i2ezqNzh>3Q460 zTE!ToETp>$N(3|(+zC-o?BNGr6BBt}XarO)G9DrV>T&UYr_|WGqf5F?@)ZKdgMhkb z@A^IK{R%>a>3uERh#+XGZ%Z8FHz1PGyR*#&%uWHI?}U95{TA|rUW(s0m|k=8+b9gw z?AYh^+sO|coYFknA47g1SXZ-NL;3zViUD$U?DNeNSMR^tpFk0?pp)KQ)0t7xo>AdX zq!?JyN!(W>>i5_CT@(h56s{zhVn8Ux(F2V+?eRJOREhz$b954v#rB zrXyjHKa(OsD>?REC6?}A+L>79YfmimXHhh$CMNu@Ib46Jz9VkP`5cPPrLNBM=aE03 zh^!2M0r?BjwYvs2Z@F`nzlg%cL~blTTGf#^7NkbCzl0+DBh$O3qYjQfKEOYKA_fAA z`>yv7BL85t^XOn->xkA7&HB5o2d$k+jIA0O?npyVOc^=q^zO*)+w?aqo0=TQGp zN*dN@(r`)|K}og#k>tOE0AcWtBL8SDehm4?N;E8E{Np5qV*TR-!3h-fPZZz1CwbRR z;=p7ir8h74PvOv1gfd&?^V2vqUDD;`b!BFCC8uAg&akqr zmpdJ^ll70s!g(Pfadw9O#WDG_bMz;QVrJ)v56?(0c{g700qM~i|GxB|BFRF#0r*-n zkRN+GF>A8L@nhwWE6|M`Bfvar1%%aS%fX^1zrnM z3)wBA`dtadl#`I4m#|m~lKXMOpwbX_EDI!*du<`oD6&9*t`Bc`3c4B)j2$(9(511TdLn4k5_LfFQ#$X+1Hd3+)-sxN(HX?rr+Wmq_dpJ;7%rH!~{CBGJ-Q zLM)PKLV}kAjZmuXGVl;ijfA4pYYp&Gq6m)ylSTuR8gKttnj%%SPW@P#FXi0_$Z6UU zbmAv7i~$73TmX_>0E#5(iX@ha(D)&DQm)HTF7iUg@2$^3P~3K-6z@wm1@^fex?|qw zuYT(4&QS~A9u?$?Aa{VBuW^Ta9Uc#kLDu4NI4A zCFxLVCA7VRN~xTr;anauW@a&P2+t<=iDSiUpGm1!Vk7}W>Kb;n{_8X8fK)nAL#nlV zSMOQvR}g{)x_y(x)csTa280NkX0})l+Yj0Orh($<-z2AxqJc}D`?mXSy-SjKr|#b0`u>GmK#g!RApc&}R<>>o1^K zAW}lGz9I?$ixP${A%8z~3~wtgzJGDssKp(niw}-&TfV|ipv4gv;PW0{d}#5}MICvg zfpEw9%PFA;!lj5H!X>|kaQniyNcCw5x3<%n-|o!sboOs|_U~{G^be(yjBqbY8cs<; zgiHP)!X-Z=+#3HF@`n*Fg&5zqrH?soc-8!Z`PjC$)am{S5>JbX;?O^&yr}atBxL*o z8j?u`!j>v$i?9D7MJGq;G6!_Iv%9i$188>zW%KI>iqW4-qsBONFX#$p#pqusi6M7{ zJjL^^K{xm5Qf>CmP(HLCqa|6w}YVZ_qOCwg=A;HLQWoE1lMSgc_j?)yWy> zrEKE>tV^${wc)(9QyRwSECUdq3O3jOAtT*8p;#6d`X}Kd$xAoCe)n6r+d0$%8j^& zfUHQ>Ao1_7rDQ3OB^vnhYCc~8dC6dFVFWWoA7qy-rAwqDCIO1QKxT780;3KJqK_EqI7X81M2HD4JcP+RYf=_JtUMiO+@WqNI3DEb&ia7th zl$UZ1kq=f(6p#;zox`WUJ$!n^b;`>A%mYxgV=Lwd4$x#8vM;Jc9g4ZIRlM>8TE9hn z@`LnZ*^MZm6}^vqWVHRKi{2pK{kK#aLtF&9h#@Y5niW=23uyIf=#vh#;56{X4o&r5 ztM1+(rF`io@%oQak^E!WvIg1b7*I~6Lf|2 zqBm9bQ6J}UCKkfX3VP&LeV_8}nGbqNV_x*Ztx*3v-K5gCz_in3jd&uuX`5SP${d$v zlP`R+!=udG8_@?}n$d%C(>^_LH_UxP$Ade~Hz7T#Q0;l=a4k%I5tWCVA3NUPT(cfG zIs~Ey7S8BJj;TH(LxNf&;k~sCu^J!b1Obv2H;%*CZK1baF3co-2VDvRS16986> zpxdoYuwPN9c@yOAkekl5*yX?n1r~-rz4xX8{-aN)KO_t*GAwB}nFADSB~}Ue1yKt%$SR^vPKPnb7Ev?yANznT-n8(8jT%^%K2( zrxY_nBkXGSuG+K8uZ$4;jIzT=kt3&`EJg%TdT{}Eh=D>`{f^Z7*;g_7WHkGT`U{b1 zok_!w%p)SlZ$ftBtOV&b3xz=uhUqmM#egmhvPA3@j@J3YwfU)mi0U`u*x=5QGuubb z)MA)Rk}FE~m-tgD2U!<>xBs})&it0f)6Ra!8~s@n4Pq{*WnyRUxc1y}ow<{b&++F_ zG{`xk_wvXOA`Uk%ZArx)j*{~Q9OKiKjXGB6*8;jqX_?eky+I3txXWy@`->=Fp|1Zp z>3DfCFi)zMPA{)*Te+oU`Bp6w)E_t^eGq6RRK8d@kE^cjtlrRGy`i&uTYL4kj_RNJ zjassBnC1RH_JedJ7_HsEwxtSmoWGRH_tOo+_w#~*={T;oEvV9hAShGX(nlSud4APX ztBx&dOP%5`r!pY?;*Zokdd;KPU`$8sAJLgm{B}YyIy+oTt>j7;1%r#Fs8v$i>T9&{ z2=SI#zSp!wqP#U?yG6d*cfOWGb&@Wn094$uxor!tYFoeYgUV$+KYyWt^XW$5LPwQ! ztE9D3MAW4Vb5OzPOL(h11-zE2a-6&1(uHEZ+uD$Wd4GpvPKEw=MmR56D&~wZzL7dU zW3JBHW=^rpHAJ`NJK>7i)!;Gw+$y)!enm@E<1*8tp?zQ;a~&rG^YDc+ML{>c*EKGg z3W`ulM;_AE)q=g{Ha%Rav_>c=1!6@@j65+O;y`WT@>8Vh|0Bjdp(HU`B@*oNU&6Y# z$B#i9%8kdt#o{=5fGCKT%f$=FWasVB@u8cSn5s-s?^ZIKjxRS6kri8&rL_v$wmV7z zJYpX~Q-}Rf5pqzb_^N`-GbstU^?6}2tvTr z^VbhMFItmlZEs6(2#74`LCiUa%u2Oc( z*e&<;N1g#a%X%Te%JBm^&mhlW^Qyeqv#e&^%3JwO(lnK zn8HMwmEwps25}W;oiW#}S3kq-G9ty8r-oOt|49wUz7^;P=?tlTsZjw6Affm;+l#^q zLzl^_Aj>O~ZE4B4&s^DL!?| zdC;h}yW}+6eDvrqChX`#4PvlM&KvN-vemcvny)=tbF%X7n8jb8v8|AUec}g3nh*8OMmU!AFkN3sLTDziBo9ExX=-?tq<-}UgMmhGag*Z;E71WR2 zxo?~B?e}%M%GzCJ5XV8RS!Yjeo_=@b!OG6GVGvsFO!FL@{(R+Am7Q03+OP0HI0u=m zI(t%c%H5d83JQt*%i z#m1ve2k6qvcgWY_8VXq*L^^tZEs8bfgT0SPzoYsQP$F^}wH@v*)yohb#~LZXMq09tcq$__KBP zwB~t`i_LABe5|59W*otKqiZ+_Piypf1%Jc_BykSyeZxmy8~O<+XT7|7?iWyte zuf+!$^3UB}Ic1$WSGMO|*_q>Mo8vieG2|Q1>kLsQKc1&Isask%X3AqFHUmCSYo4*U zMNP7ur2d`&aR?5CHaAeKs3q#v_!=I)z=IQHQ~?2M3bo~Xx13~Lj)+BOk&-2^f~Mfl zv*awvvjlNqRCZ8l2E%Fcg+Dvyu4H>J`d*gq)kn$s%VwIq#7(njEf@>6)Ds z+)d6c-xFQBWSI*$)FYs=&L-8TwAu4x(9NKfbt(pl!eqB90qCA)V@#F|lZvGg->V3a&)Fbz8<`#M;40~=4f@nBl+T56LDhxn+P zEV!CQaqDGfXypVLS}}n~8MGA#iLe`y=|M9V>1udqrU@%|L~_9Qa!5j^SQ**UBL(xinf$Q+m6ar+p9%_e*Gz>-)4MdpZ0 zg~zCwm)!%1>}hgon$v=I1uhjTI!DfUd!+UX(>!&IzG+T(g6Q5Lk14)i(au3+o|+~> zkfDDM^$J}Ff?=U|XlmG}%VoYKs+GiK|Ek-eYja)o_S{7$6Yq*SVmMa&Zqh`AE?q>& zbw76{OMwFxFCm9E8lkx#v3Z3Df|m;~oa<1Bc4)hve7``A+79O9oBHDjlL600NStY` zV?NXHP?^GJ3K@lyk?9p+!!~FZ`uRXYZq6cU{#!cTtDys&}KVIvW*B?}(mG>UU)R@k#AT)8CDnA;!$)?SAo0d7RN1nxE=6 z>dba>+>&^Fu3RR=V(nk%$}K+Z4v{-f*8i``8-_CPJr7ddVMz!^ASWoUoLcfC`Fzaw zW}NT>g?Tf>Z0No3Yh+Rw*wH_|E_PDoKPQLrL-=TS3e|Q;1$PF%D19xRKE*t{X!ru7 z68M7!^_zKemQkRtOiSy_^W=ZY?j!`d4fG~JLw8ib?AKBXYL>BXZ9Tm}7S`NIfa42f z1yh}eerYl{&(K$WV()T!YX)7hK@XNe(8m>W{t67%a)?T=kn@b063X2scCL_%vY%rp z)gb0uD=S@=U$dchRnWh=cKHSo_gkonzq~@Oyn^rXBy|mPgD|3tGrak*f!-Uz6EN6F zH`mq#=%XEhMMo|C4f?vuB4*dfi;cX&{zm++M!v$r(m02agI-w__F8#VLErAi!L zo+~(5*=Dh^R?hU@je5}xMld|!_ag(=KT91wg???rg?K>V2v-*@Y($b%_se0TMO)(< zCCl%=6y_fe#M? zZ0a54{1W*!b8Oowdl)D5n)@{4HMR!B`W}?+j@>Bit7LcPJ(L#i(K71RYZS-4k$c6= zRdO~csrprNn(-kNoMCC*ze+B$*m?A6IA{n$`+13aD>7j(XEYwToTWYQvY7xgqN7zz z%&Rxb3DSK+-6&`K)V(MiIF>jfw&*Z)c`fsf&B$*jwUkF|HNoO1x9#JUj|cP^{qkkhS873Dv91+|lDyg8O5q4u!fQ-rOS3 zz;LB(l~WAI(2fUMhi{c1!=qo~@7v^3BQ32JiWs|B?`WNE(BCYH45zM(4HhMqE=CRx-GP)EUm9ww^bcS zk)b6WG1VA1c%wrL8J`~?xC#M^pNB2&NwCm*)=-t`t<)KEJ z-ND`s@X241ec!^Ja<0}L^%)u$?o8xZgwa0_!yhP9s3YpL6r4z1;H5*mQbZT#Qji<2 z9qF~!bIx$%o4{F&Jl%?}opQF}1S&owe%vWPi`MVBQBG;?{J9(@ttJ$)DFz?>WcLH- z?tHG7RdlmTi_u46h;bD^Yf%JO?$RUt^R+#(Ga9o*65= zOmHSTy+_VIFyd~6mGBuVtmU?}k%2xs85W5_ixlCF!>8p<=WuL;F_1M4w# z&<9SF!#ng?^6`k1ktB`O=930ZLC7h*xQL>e;10v^9xBwcNqs!=lS~H+<}zce?_q{g zeG^dlcdP3cU@ZeYqi&HO)cY7bFNDCu`w7zxuTxz3YmpE_!W&4%Ns=d9I1@wZ2o-#q z+WHKf9`JH$@ET2t+U)g_mqGWFu$n+w7*>p`PEha_au_l8g}K5kEye>@t(m=`$#d$t zLaKnCRk;_* zdPxyG8}YEHr9~XQ4V;54aq2eAP@=uG4JA$^I+(3> zC-*=?QWp7mhu=xQ@bTg-r84`3G1e|h?RC(gyJcLrFzrrUH%%vfJLTm02+0z6z~uOT zN@g5uL2`g`2$!rHti`@U zAd(|fAQcH9T19d*ILvYa%ndB<2Xn_un*rDfF|Zl+#3z7rNdf?CzgcfBl%R5^3S^WMd9?*($6<_uYrdK*3#0p1>v z4S>^xECFz8Cp59-pqyfT2LK&T0KJX@niv3RS-Yt$1kf(=)|2Sxb!qw-ar~g18{M8a zx83Gx(`zPnnr8pb*=oB(e#lht9tL_AP%WVrP_|5z>&cdTPl`#LIV2C1uf#0=A34{4 z(Tt}3JRw^;Xvvn?+;C>#071(XwVgp5Bbb7CS}7YFoA>JCX}q6qe-_tLaa^{*GNNPYEE_zQ2#`U-Q>JS z?Ep#x93xH??<00SnxcL{c|O#$Nl72|K>dhf{!FE?Ms$Hfk5kHD5LrisKBg=rEum@I z5v8?>W>`Y_NU-9YA7?uUZNm#$Qbzyryz|KzwHQRIBIT! z#?qvP3^T?!FVv`K#6RwlGbWy*C{vAEy^+h8>n&btNsCih_zqe2 zwbnlhbHm0Dkn=W}zo~`P%bv+{jCg4=w$0ell3lzr3b<$FLV1=rxy;}Y%T6fKqV-Y{J^0#5L`E-yt4ai_le5gmoFMm#5pDu8^yR>;Ea+dnisGN2l&6DMD{Ylu zk~LCRMh=aXqFURxO2_`t@Xot({UUbg>r_ZOc(1N8XH(>VH`7Tr(F zCB%p`J%d4`{`MF&M?|l}9r_b>jXTMwK;ETZrVs7_P}CR5$IN$RyKIBH#4sd>S79VR z{AVmhM?y&a;Tbt4o_3j@3`_CZGjfi>0#LjvV*en2hf_?{v+{KP34Bm|Gz8BuZFp90 zHpYerF)(yVFUh6+D2!T9Z9~83yd)2iTl8YjOY&f!9}U;27E9MockDR;mO9J)1AD(R3zzuvuuEe5U17%d&bZ#s{|lL(viQQoMZEER=r4|r2981D4A zf*lH8-@w|2-IF{b{_>B(ARB+o z-q_H$^D$1zq1MHErQio~KNQQx=S$N@Y`*MkF!`o^EuyL@bT3vswqN46S#))APyv<( zDH-DMTM&*KISTM=e@m`lpONfs*2Rmg)AC?5bXv0Xy1E20r%lcp<(Qw?pajh1#)0<3 zN~?3!C3+p6?2*`~*w`o7_+E!M5tefk0>)FEoF`s9+9tb-oL;*(p@LQheswTxSLgD= zM9b6}2qjjb67AthMa=ZboHTa$9;)7W1CSxTcQe|HCij({-qHzoCHOhF&KnnOF$8^I z6fe9fXXkt4f@4<~`(MU%+9u|hGy&ijBlkSQ*m zs#wI46|hhkze|s|Va0%5`b1x>C$l_qUMb$#b+qa5&#Ol$Efg{!MEq0!d5s8VghD2S zGD9IVLhew=f>2f{WE~X}{H>8OjBXv&=401o2QoD6cs)BK&Laom6@)9Y1iQ#t;`_{! z8(B+2pIP!Ev*h-f1q+XV{Gq%)vlK*T$?r2ua28N4lM4FGQWU5~=Z!}Hii07Di*E~? zgZ2!A0iC#B% zg{HRVk5*V6zn|Fnj+{5t>?K`5o0o*jOT8wzWo$dg&Nc#~y*V(F zq+Q?_WW+00Jr=Jl;;=kot5yX;>KTCdw_v=Hl3s@4SaVbA!e zQ%+D)>yo&}sH(N0ByH=B^`>}JshBs(GZ+%!L&T^q*(I&lhNr#@Jm7lG5_D#~VoAZm zsHoZ)t|Pb-JVV8UU2b?VV7L)i^aygZ@QCDu709W#8EWJ9;IuN>Iw6;Dy@Wi>>ZanwYl+Z)> zX~ee~CH}etCBAgSp)yT7r%j|H!-8c73>+3NM2d0Uv3RJR&dp0Vs+x&=bv>%lbhoM` zvGh-JiP-xmxzM(eqKOBg?h!BkNnT*vjgP1bQFYryw5+5@|MjL@Ke_#=#&J-0h{|p` zEy_X#Qa}o!TCurXo>zQ5eN{hioM(o5kto(L$T>^d){+A`$bhO?s%E*;@}4|i(E`7T0l1ewLOdG4sWEn(%mw+5dh{weMEhy9^YGr1bm8Oqa%$>dDEnr96zM_oHd5q6(`s%~t z_wUO&dO913^T|qrv)f(=c@xO>X|LHb7pNgkoPQtJk>F9{91!z??6M6-chhNZ3^a=Y zAILerGI<(!F5 zJ)*P?Ueq3aRh#*$GjWc63&;j!OWF~&BXM9y+@Q|5;q7t5JK{#}n2wUWN8I3RPUtYD z16Dsm!02IbGYtM-Md*8ZBgl6QPF#+?U~l*EOcIln78d$<0U=&tO+yY;8dnO!Nl2*z}!6;d#{E03eIyGkcgxHuF}E9^`g)z(jV zKazhJy<7jTIq%~b=LNhIJI*c={wz=NjkC9H_kFF?{S2c0h^If0=|}Q;s1eBv!-4g( zFC3Vu%vVC$YL$)Qz%>0reJEv%zS0m1tTJ312q0>bagGsRo#ZpFgg7j=no>tnP$+RD@~QAixfHA#0BP1BwCHYV$)IzEHkY#q4YA- zS}IL{5V_8DE&bVI+D4_9nYR0=_+rz~!o{yN&o(2=9P>gmiqA1GHlsNGLF5widiqmu z-e^YgIcC+2(pQ=rC{p|QM9UNl0#hxO7L=Z9@mNrr{vdLmrH1~jw5+zE^i<0l%NI}w znP|C&VzuI1EkC2cb(V=%6u-_g)r#Wu2a(gP3+T@xYn2tnud^(+;^SK_ODIw+z1CVs zfqLt;RJz`}jY`uWL~gfEwc*cn+e{lu*ITc&q4ZkovRM?X6|c6{P@vYf&W7T(whcBE zr$30?Xqym)Ka--SM4@=CZE6&XSKFphBuXP=O;mk2uqA4&T}u&neJtN0EfPb|$y58i zQkJ^JrF*rsa7l&kk1_VEqm6%bo8Z3hN?kHgdA}n5YMb(bRf4;12p_ClkDrsjmiesz zB^@3EM(lb#q8&t6?|mlcMlqX#kuF#+w!g}5A8q~f7&(Bq%lkFwVT{1I;j)W=-Vk@v z{>0fCC2F^b6z3v`H~$Xuoh0WpIgD-i5|--@?5I~Gg+7DJX0GT2W$krE$PIcJ2|bxl zi0Dq(v;n4XYgs8d_~f=a65HP{+WtmK;*YX2OU(b9d_m(!6l(kkfGwf*+P}-!>l4Ee z(a<`!_b;==+0W#pF`u;JN%9sArW&=uGFKx|y#_I0Qw9NJ)62l7SqJHb%KMP&YWK^9 z(*KBW{c^gq7tS^jG``b`((`gMj6+O0kG*_6;j&^lMXm^Gj46~eJSaXwp1lSjjFx$f zco-SxJTlye@TfEXV~ot`Foge#YOUHp^%^5WYbqU_x-B)}h_6{eO7%misXU1YIG5e! zQtnt{!P8ZFX!NF_(63r&U67MxZOlqTW9DeR?F;#OLuzQG)KT;WH!9bt2Tba+Z)LY! zu87&+%C8KXPbqKVJF_sk&rlQJCx<)Cld_NDnD!l{##_af@8prO-%a0?w zikLdPybem5j+VWMNvMvaCiXS1laMfvM^YVa5Uan3M$#)(k{4X&e;M0egUQP*Ok**< z#-n$HY7F#&bviWQ5k?9^vjgvp@x814JlOi?4|0iKW3LY6I*z@-7rx znR_|5!zyMDmXd7>-a`x&7jt6u2}-n9A_0uLQoT|j#S-IE(FZu4-wg?HAT?fO$Ln(3 z0K4`rJeM>n$jqoSd(DM`Xl6*#Uc*0+0%J091|>Z?;*1On!hr^Z8o>k6ugke)u-GF0 zrYNxk99jc2bXA0f_~#8PP2-s%Jof;8R*eybtsYmP{c%ZJv4!yq2QQqzaNA(B=rkzh zzC#5it>;`0UZvbB7*0cjLixPm8}cJ$-K9t)Ct~s!bVcs+vkOh>i|l z_Q)N1vQ$UXEOk*vI!AsP$JG`G>kS+x)g;Q0Ob(wv0w+5J-xt+JWwU7kea@_i4~@#? zX}vaG-fDR{^2zBFd_lW72%VW=28!3wWhaOllX9i3>iJby<5m=ewEO_8;;=47Q~pNy z?Tq-$q*VSl>iz>;dVn;a(H=ds%{=q}JGuXXEiq8ll=kSUZRV*&|2z9W0EpkT=re`a ztlV!uQha<$+tsygHnmN!3bREiiGHO3?``T{jZU3Xq^ywHwzhE>`WUzojoM@eXFg}c zqz$V!>=9cn%2eON9qU3AJhdxB*>^l01|~oe_#&uDX@=acU%O*k z%ZOtO+7?{hm6)+>R#!&<)B4mdr+ZhWSc_V4b@mIZQf7-q9r(WP;s#sO-PfjwvstpW z^)o9yTh|;mT;&-IMqHxDDRvgi?xr2@z%639MR76)Bf^kzHS zhhK0DLt?g;nB8Y$j+U6yXCk%{e8rX9XJVd~nAc}wJ|`CB_n8=Y9mWF_VPLG;z)OQ& z28W0l29p7nIOQMAuN41|Q)WmdVtTytFS%cesE$*T#q*uA#Z>Ak17odR)FdcVkl~>O zrNUC;=|9|n8<{{=u@9jtn?s3$>R6IP8KjhZ28dY>Wrl)`;x2~*<8!ws;+d8bF*{L7 zlm>~FiAss0pXCq-5|t%Vg}9KY%r`NX2HjHWRC0YG?$Onr3S%%#te7P7+}f zhd0(ERE8e#=##|ZZ8uEkOrgvVlEZtij~P~BI*JyZx`UjbwB)N) z>?Lx-6cjU$J|fU=A|QteD&`=MGvRg7-(8a}CMR%$)YFxXc)~_IRHZfT&_|*cx0siwwoh#XIBA;33 z&h}f#XVoR8_-*8i(xs&N?eKjOtxHK4#c4{W?;C#%Ma1fy$<402QxB%LTy-?QBYE)Y z#0q~LrNsA@l0YdAU0P=I=DW8a+}>6)^4Q#t%(16a$N3W}$=PR;i;|M?X^q=;B;#28 z!jAMSPA8A@CsR_24verVch5LD#%RXXx?^{F&r)lR|qIe7p7j+}5*cWQ2LhIXPOaIVVRc7sg8BhYV%lfC}9k zW1RD&^=}rZ%ukTp;4jg4l;zLwAN@{6{Cu18u2mv8A$ESD;oSmhexX>Fsf>|cY;DO@ zuuadq8M3K6MnDYc{U>Cr#egR_^+Y_1v%kdMKqw*E0IHG`BCrBp>GtaRZdKrdAYL4Q z77~^pxRqFoP0Q=mH*I(qmx&`JivgIXDofO7DTy&5s?8JS)vr@T*JJu3NohJh0hf2P zq$s_|UR5AI%2E=hM6)br%&Y)cfmUh_O)uWLh&J0q)Yd1W<&(#6JGXcLxnnnc{0vUf zhyL}4JJbb~aUnU2#DHvNzQ*DHHP!J2=5Pa{m5_v>_-(dQDE}f#ypgS>XnVy9DoQr! zLdqd0X`S%84zFY07?`2Vi{>O4NyaoT{N;TrFFb$uHSg!O{UWQB1q8?h8 zNWtyGrseC_G^`F;N>f#2+e+&!9da&35Gg*Dqpa)KWsB*wW#eB@>I~6)$Lt-`lg<(q zxk`<89L@_Jhpny8$$Y%Lim?Mj2W7))D07d~_fxckWb4P+;6k(GHmNxY;Lc)W( z7PF!n9O`x9o^3+UenmZ7g5(`|oqJurQl+)CAflcB$X8U!q_q<=*URN(aebj;m!W`o zYoRiIA=%anG&oAz==*B$0GcVt8Q7+8Bwx=?sEsrr$cA~u?C|m;#bwxx$UDW1B4r;$ zxXu(QUno!sX)jeYN#bs+TDz*YPBR0@8~JwHg6~5mq{qX1KF4qxA3o!?HujP&3X96T zgGNU1yI8`pKed*tV7XI1CM@KWc(@DnEfA(BC~L3j#zXDVet2Gqq7!6vwHX30ECC)-XXy1CPhy{SI<*oD=dFYIgZ5ikvknKNfWL7aW~TPT zzBjJTVO)U|9_Tj`KG9>Nvx~h0l}xd;QE!n0(PF~}y`?nrY>YYE_BrVXQn z+r(9al%N0S4bd=IDUsd~0|qPUiOf%8ZscvWD0o-9PplZM6#IG}em7;IrJwx%IogZ& z+AX!A|bNT-Z%MHiB+bHLTA(Si3)8Qr4tMaP=vfeMMi2)T# zvh8||#Yx)E{wj&tarzvwr9yeqcjmubpM?+D3)-U>wwV|H-#B1<+N0;SndhOZqMx{7 z>vFkI>m6P0fv5H9T}j!epV9?FdH1dfA z@#_kxmJBPA98Jr%JA~~@gH;A0b9NZk#pNHw%T-N>{*^8^=p~C>m96Rjuvj&Hm15>h zffVkkWrl?Cm%n~pN}#0vB~luHLwcLY8DK3-@Ws$4OI6;s7da5{Zm*S@UX`*|SGU$I_>qDdau9f;| z47Gx5b;nlD@hTn%KM<0GZP+Hx;|cj-ZvcQ8abk=T-=mKJL4ug;f;2oG+$Er__t3@p zW5F&d5{C-GDlO~>XT#e#+8-UO*rZr7Zm5i>)FL95jRLS3DresZR5&U2E`7XQ6)VQd zsP4W;P`YXu=2XL3eINr>W}6tC&U2?~Pmr{Aqb2;EiQ;%2iUupQi6!Il7+O)VKvj0r z@mtbGIDdBUc4do{D*^6sL$gKs2+TuzOTPGxO@asX>-k9iDfayNRo7s(jL-_a@K1R+}3?Oa+@P6omC5*k^|x;?tRJ{1~O6&;_&r+=7fkI4kR&6Acnd1FW+?r8PKA|{iuePwx&r(w5 zDlH)WO6$#z<$AMNKVC73uU^NR;eGh%35-?J66o|5&QwyR+qfBWpgGZXSyi_N0Un&f zWSBF$F1sqcS7(cNuT=69iIU)7#Pn$9FO!8?ab^}4I4_elZYj4O5xl_ZDIO(z?ycN& zyeP@*qerBzELi>AJA##(r9gqZ#IRYoNzpf&Q_9})Jwo?zZKhND;1jmUh&dw<)#E&!)rein-qo+Z?(93j#A|t4RY$Q zHAqu05k}u8JHTOyPk3x7`5WZX?3<($fy(8GoY3OPr^T`2 zF%3LxDQk}avgy*NDejTs^r>)NT#hT`FFi|no`cgZSMb@Bj)L9F>gon{6lK0hr0-qC4c$Qwc)+dza~FET0n>xOr##cdA&-)-F+g2Z zau+!?YoSoLX*sUq)vam{#XU&Q2`WQJ0+j^WV2F_416oQ?CaW>{Qn$21GfPWzLNmW{ z6Zx(uz#8jUuEaAX>Pu7!kKfHy6D%x1%Z3o9T0qV*YT?u5{DOk{#Ns+x~*A?SD-h;Qj?m328%eal4c~ z1RmJX_`dwgvw9d`{6`cr-z65#SJJFuH9B$4e5FX*)OujP;ktkxgh)Vg zagCC1eGoCf$EA3~GBLXdoB91UxaQf?dcH>4BHNy)Drr~2F}-n>QV`HL|B9v;H^&hn zd%&x7CuQd5Vp?BjIAk29vK`S5QSv&1v zBnBo?7`TxpW_UCF&%m8XExMQB`jfzAPHhOTvFeLx00TAv*MxedpW%0C%U{IAdgbjP zT>EcO<`P_Q*!WX$4VZN0Rx(_}U-}Oq<;I3V8XAkNDu|?8`7xEuoHI)Y!O636iocGQOWNA5czpeHQwAo>NIj5Cx;ACL70JZ zM=THveTc^}oSm1-?Nk%r&b3iPO<~1%wS}tS2ALb`syC1w1oarjHT6fKKBNG9Sk}_| zp#A{`?9t-O&B|jM_cMn!HfQULTa=}8B{zopp>=?7E+C}kv#jex16#@Ca>K4|}LS4w@<#sC{TIzsx60nVTg0bC_UR&S#^%qyd2 zYg}yt5Ny!&Vgxg680d^uOdG1VRxgLeIVhvY>U!Cs5&eFK;d>r6CPlZ-{F(Ag#jY{# zSndV$rA>U~|J z+U}j+tNi4%8zE=P&(>4s=SK3EM#@z_$ZYxvd+*Hd_UygCPZ^Xd#$D-K z{970wI`oA3tencxmijoj`)n;WA*4N2!QzYh_`w5`20uth7<+{9*!r#G_@?T z7@~$p*I7u_(n%b)s9LWDRzK~twE506pI1*xgJ%Cr14aT~|!p-mQDK-sQX}sw26yGkH+^{NzDr%#Kd8yWQ+=nb>YFG4(66&KwITDz#-;XU<6c>na%1S#U*r!4(|^qjyg| z9hKV^~2Xvsy|xOkv#H@Grf8Jk@-iLbT}t; zI;XWer*$}Iv@KcJxkPPWqIN84JfC2VHSU-S>-GlIO_O&{-aU-C*0zKlmFgC8L?~Ht zq2>J#faW$GG_c&y=~J8hi}IS>i{o4SH7l92{$H5pVq7Vh+%3O^6`}e&l&^U~DH86? z`RN#1UK|?xtmJ?#Gx5=0FhH?fNe7h^jfmt|lPP49u&zwQqs1TYRLaG&Ir2c464o${ zcnewK7mDdsVzJL)u!@y;DFvM0-Xp(Q_brsbImZ{sF*Kwu?Xh~Lb)nG0taWZo4E}l0 z_OLoChqA@oUn?FTt*yxsYmFAyCc;mjKK{(7&)oglO%I&A`N+9PpZe_g_x&%I7Ol<~ z0bi9@7cVScV&QqsbT1#?*ZHsz<`v~=IE;}2uU@{^VKR~t5EDLp`0ceUdD-toYc>4N zmpOf|cWM-)hhB|Z!mVQZ7+E6kdzm;5uW4TF6KKUxq_u0%mhLOm&sWJAOdAL-*huP1 zJn|bQ$9f8}3uqnoYkluGN}QCMncJB;v^{fZXXdD51G`*lovwm*S3#$%^vFQ*_q&z; z=Jf2&^g-?EgG5RTglE!YAUC3mvDo}>F}X!)iKpWWlP=u`Amv(hg^|S?rH{qfCvla8 zMZ|L8|=;}mLMR!9%age)||egXjzKk-JT>>8(NX0>XiRmQ4JEdf`Y z(!v}F2M4gO8@Hq$6XTq55K%T`nua*KRoS-}Nf~tC>5|rkuw_+IuqLdrv3Pb#YihQe#Jqxcg7TK!30Kw!nbr864*Vom$HS?s+8tKq!MiMN2} zsHF4P(CBVhU5)QkPtlL{8|qYuxoK-D>p;Zcsf% z!cG#`3TyizP-&K_%dGQ?r0%#4^&2*=BaND%hNAi|78aCvaUp!*(T|^LKKID4VPXqp zGK_}cF~@T^-~F#Y+~WKA*&9E(>!EXZ9o6XPPj7zmlN~!hx#Q=b-1We@M{c2f`)>K< z;d_x4V%wh{x%J$>U!L3D3e8!>ocqP|(4swe&#kB(v^Ue+0Xl=XBqla!U&6&Q>7}by zTJPa4XP8cx-8U(49Z{CVg;ITrcK593h|2_#VFz${rzr#fy6{SgWxwT2RQ&0L z+>WTc5AE@Lyk}ywI%7-QV@r=Z+G8s?RMH+>a^%`ax8A?CJ$4xAf#~S3&AMpko`t8K z1)a{~c4u*?v%K9|-r*e3VITORJ#Ej@4*P7j~x2YEPSWCO)$(EwjtzJ8w`DqWwC>9!*c>#C)uG?3>%-IO096AJt{D z?cUyDO6f`h+H1iRa`i1roXOr6m(^j(61TP}+0kc{a&{YUwe!{T3LRUVee#fU%2Y_4 z+iv5^YS_xI={5}LkDp41SF(XOiiS6d01P#r^GB4*WJUyp61z#+4sp3;&+=EJ@{HlSq0i>;B-GfSr z;T#G+(R$Z|%6dIG|JI|pyebyMk1B&xnN3Z}Y+Ft}L%#RP87hh0fEjAI|0qO+h~hfm z`r1+DPAQ*pB@yf0#+vHd_4Rc)e4aphw^F@f1B}suWUf{JDfa$Oaph1sbtJ8<&D2mv zeOt+wMy)012XX3m$}B#4uh46@h6g;Ze6Nq&LomCUoaI<~Dopi`KBlCR>8r)Zl({~2 z9aUq3v*w#0fBX>#)0^pA>k(0usBzwz^nZeCc#0h0l*>l(@07qSb0$8R`_8bYb4Irr zi?Oj9+aaC8iRay@!gw)^$UUT+g>rP}?T&6#!LVJ4u>(&SHyr3IoyK|f)AOs{RsaN- zAEbWRZN?J-?Bi($p7&QBTMJ+`Vj}`#NGB2(8W&_%(3rJMr<;k$+aUdk^`Bn)CKRX6F z2O_69_y=V{BHj3?{J`vY1o-datS~jb@JV88;JDmaYf!9p`Pc7v&YNV07+d>&U&J%--FMe>?>+b2bI(0Ty9#yDen^=grYOuC9>P;V z#6K{|IDS4-4#rCDeUj2R2LKB;w zmS?CDxws0&%D8k&X}t2TUeLR^{b@NdCJ#CAAKAs4B#rKTVonm2RP18ZGtm9m@r*oI zEPF;CCLVbP=fa1ck*%FqeHqW`gZc4hht69QOC0^IB0PJX3m&Lj#r^ZJq5Aq6nB!5N zm6KA!BGrr=C_EAZ6jr=g{;Zr>>S%Z3OZcTL4hUB#qsu!3wm5orKP#`5783a`R07hp zfHYDgPlf?$W}zIAA_7vR_BB2Rq~SP0^wE>088fm8$0Rg39zaMdkZXeU9#H#Gq@ILk z@RVpV_oQ62kV#Joa1HJyVoy_Jb3-i|e*BDv0g;luu?1^J7i=G0(2!j)e{#W+$pvm6 zvwP*@v76g5I!tE{?SKE?+i|(`gOl>*wy`LxFirbfY=2HJ^zd523&A%A8}fgV3gO{7 zXvz|?Fs>08at#{GJb4GrTiO){Y*;2PscUX;1ogjg-f1HS4NuFC_O_kvZCVoQZH&+l z2}M7K^HjSOZ(I^f5LqYX1c#P}IAt`oZx(x>m&e=Y%I8fcwOkfG&&wU2`(53e{TD6M zFIwgsvs_=f%DZ~KfAv;<^;X}?CU3L$8BDX{4ig3n{UBkvc`4m!sxq&lz;g3y4^hQ63vdP>|m!6uXODJ%+`Em-p!aPSt%qz@`$rs`kX3t_7adw-R(CaeUO$HJw z<+T*2Qf{O``azUs@@9J5DmPPOB8&Y2LlWEMn4Fw zQ8pNF8|bZ8*+f4TO1+0dH!Iud^9(Zo0XX=qRdt+$SA`+b%{!Ot2Goz zKZr70T}N*l)J+tnUTvZ%_39o9q#s1t03BR>OSw$N;cmp`>N(XE58sd$(`eQ4y=D8B z9jZQ}b&c)Pj*dO5b&ow(a6Ipkk;m)3lNO#_3Ab(Ds?}as^(keIxcLQnEDlgkz97FO zS(yg`#l7_RTRA}?_bY*bvup26#AM(PrPQnPtp);JS&!A%uc7gKzPR@(qMUQ@GHgc?*vi?{zI3qyE}Dh~V+(MCf|pTOSTtluiR zEC%j*=2bbxI<;m-f3#|)U)t-=rPM7^)h$CP9V_lU@{$BY)%oI&6U>E{f@o9CTwKt9 z9Tb?&VL?^QCb?wyFr{esJtv5 z!6Ss_4LM7NTnNUXUVmNAi;hNUp&|W6LP>PrM{ylhF)Np|u7^2hr8u{Vly^wFEQR?k zi*XmZrGDx1g&#%^d_Yk#D_0r%N%G2Sw$&9eYEndtwaT=z#?U7D%^SGn_L+F}4LK*F zxF2CvkWdq%s;tc=;%`5IW?ku)gW^vqwo76vkM^2GixFgKCi}(CHa#M6%$Zj6IBFBlCcjRPqVVPL> zuKacEov51OL*+&y)tFq(XXNq5`ctYf!m3IyE((@?- zv{|my@-QBk8as(UQ7CT|_lif($}3`DrGVE61PEY@llGpx-xFDP2}UxV}=U+eTxW_#`A6_jn}C`tJs@FDQ23*+waMvhI2Gt>sVk%cnUaJ zuu%&!I1ZqA$M&=s|Gs?CGciP9G?u~>`3c0df+C=S%}v{z+L$N2U=#n}_wc9=Z_j9} zXRNyy%KwaWGl!Y@K;G|#c4|Z-406MSabWWWuRNf9+aW~hr+sj+2_+!j8E73;P#b}E z0+$fzB)})Vte3;52aGt{D;b9jo`KVZ(8;KAmOXe<@hc|N#y}Iin3%3aBaDmT=B+UC6(Sz7PoySr&xHXzb1b7 znVjYc&SJzPnTAFL0$Z?w@(W!s;S1%WfMa`mb6XQ%$PBJ~ES4aNt43^~Ar#zDFI$x&q;kQ|HKZ?3E>2$h3DAlBi+nq{IY9>|bLhTRjNvh#qk@;^qU;3Sx^Kbbg4^b|Ng6LSyaLCSz zH&OpZk%bVV5j(<%{~8T$mb4jk;WnBdq*_CcU1;jepzr4hTOl_44$9(rHVHwrW$=Oe zh_7*NXD-r3#^7VXBvyPa-{H*Z$~{_hEdRLYl(PEf5@oD)PVSt13F0Xz9E`vDR;9pv z4D8yM^0XdFQlcfSj|1o;Jngy)YRG$>$^y?&*twUgx);^fW>I|~r3%ibCnoH3=;@yn zg)tOqU}z|nl<$C?X+i9;ipo&fVcN%}Xei|L%1WN20u{;(BFCaAKaT=(ykln{pX*(* z@sv_0PAke-c~0^iSQt@e#7zW_>BJ9>;=k%_b|)g9h5=%-h3^pMiBf`bV&c64{KdjH zY*=5Mt44Ib*6I)`+i>*Gnz&uI$ zH9+G%#-^zG^U)(E)Fba9*8$`EgB+FoAWtb0%WTT};eBuvvzT^piHm9DS83iw8#v9p zo3?tDuyTj(4SvLnHYLx{m3nLGU=(n}ctD1m;}2E)1T~!RJq}U#T&jC=0?70BCU!Bc zEkq0EPzx%_8vi)aVOI(aot`q*=@BDUcv$fw)ckW}q8T?DXFHU?4W4Xu9-Jo8$ii(B zOuP_*N@4oFi)0tP|I~fYoD@+Fn|Ii9);L7Y^Kfdwp$X!i zXvH47m<0>5HaFk&q@BT6GR)mRX^zMu@e2PzSH)p`cPmwLGnzzyWV#wtl?Xz@E~Lrc zCOZ_jvnG}-BBhVHaQv~tIFn31GB+-ulV6y}4xatt9Ut7(p*<>o7Ng`_Eksqp>^~Qy zQnNb|7CwUW1H;;@>jgBBMptq(T`n8`i4(forX_!jh7lp)^xC-vT~h&s6Uf{wC!!@4guW4#`=!E4(v^o>iJbwy@q zy8JsoqPKh=7BP6xa)`&{lsLnU*7vKS zkG1iL*@g>~``Tb~Tf9||1#wh7F6NLYEr-!!V0@$3r6fl>6%!2i zH$rX$#|P|>;9GK!4dtFB$AxE4FGFYV!j-UZ_J~vbJ3+Br*ewb%5{&r-u{cq&M~0BA zy5q&HcqQEo>uDGEnK+uLIOB|qk&s6Xn9moH&&XMJG;0`%qpG6BTQ^Cr7s2MZx-Re#brcJM2MK)yU4>#LWs_dZ)_ox6l*-J)vYUs!SM&8og>A3Np zA;u&t2^+Ki18o?MTn9+BK^qL&#{2tjg0|E9Pab;z&;=9%+bia~m;+9qJ)vXW!|nJltXl!+cnM6wPzG$y9*G=Y#O8D7$fy$ie0 zZX9vKN7$7_-S$v|pHO;cUqWld1N4>o9u}Jm6&~oJ3C^e?(vfNLHBi>M}~hJDTNGSz;Ul zk-nlCs-%4v zw|8m7U8!Qp;Uy$Za2;{L!t_1Uj=TFzrj^nxVkSqit+ZjY%{`;jlsa>9`LM+~(laBZ z#c46m6wVrrmp>#*i!)>XkTkm(FV9EJj>pdnnG)dMd~t8K0%JTGN|&@@aL+-LnGbMs z2qPi3o4Y0C-0C{|%331V)6)$ERuX=`1_4MZ-4F4QT%!xQWeDJ_^OOSnT2$#l>XQdVmQ5)YJ$cG?;LNAzD<7<9 zN3KC8dEX&ELs|DGzMon8MtE@^0%fgoRH>=sSjHT?jvE5c*+A)6DSE6H8KfB2A`OMmOLLfDWl91w+@D?g|wHA1Jx#x{S_+vvC{HsWr zEnU+yWu%g%@Ks99jqe6`)I~##UG1Htr$(y9W&&FXd`w}V5I9d@H-&Wo1f&(L91)O9 z$H9s!1(Qti?x3L>4tSTQJ*oJ!P7JAFk)2G>kF-Uw@sx%QIGz|+ z)9XG0R}r|I;#~(2yx5Rr5VR0|yE;hPg7hpz-qum_76J)nPi` zaB}J^71f3Y%nU-U%r!Q~=vt&l0N4FF%Jnc}v=SotL`y6kuMAT!MqNG;d&Vo?f~}N+ zS=&ohxv+)qUC2b4KP%SB4Ex*e&$6xUy*< zbNLkIRoTNC-bvZqL~RYBgT}w%SoC+-8mf$8h%kh1R->s*c9=9>SZD6ee*5N3Y`D5y z4v*G|OX^aan;Kx;uayP07pfDAzs*oGVDaB%N{{V{nyGC6A3K_7F^jBtdUFSAJCL1G z`RM<>pB9JB>I<9N-%7^jH+#nDm_f~}n5$%3EF0!X+bci1rLBmYKonPFAvoVd(I$aeCo0dQ81qdo(=Lw=)iFp&oa)Ak%a8Psd0Y0 zX)f-g>=}_1KS&9!8uM;MpA4GyB2|p(ACH2gl(nigQ3f>cjYA{W@c0mD3)e_T%z)K! z6W*%rMuVot_AFYUG|5F&v87CmKu2Ds0+^0aaFC947-}(o@%mzAxOrKuur5)S8+PD$ zIUQI;!^UktUE#*^bafa_;EKmli?~@KD&J16xPv|n>hYl2I3CyBR2tl^cIvo|m~fbE zZ!S?1;Hm<$saWyl66J@WS2r$I#+l=?kzJ*hg`I_QCI4cx@GV#BJnv95xkuCKTgaOE#3ApB0RxYm{UplsS_N=+J^JZ0+ zub#E0&|+M$Aj z8fZ*Sm9ioKyEI1prAo=H`FfC}RNe~`xJ+tg@2u-~M$dmk8|y)lvQ8N>?#5W^ zbj0c~9aH@i7rZiYfw3h17GZ%1)}wEP-S@q)7Nc!Kb+mfXwoWNCEV}cO^G~YAmsAkd z3ch)vdcTug9aF7>DrUElCixxrzyHuLp)gWS_2Hz~)8H(mekarioQ7Vpan=TK|4UzyM`*l{Ks|lL<_kwNS~pyP67m+1`F6)yR8+< zDs5E!JrtKI09UStQgP+@c8X2Ama@JM0Coek9k^OBvK0;7PFdbSpSS~ff)h3dv7JI+ zuOwMI5$}rFo`0-YelIE146(dUPQ2@nwTfgpKy`p=!;MOQB~306w%=1w4pnObfqewH z@vIBvc-0?BU9zE=CIiQ8;L9 zYpQFmH9CR^7kmcXND+QbAXKZ6*5`csz;&TY1}xilY$9{FJVdDnwS$BqU^K`MT!$yn z#LMvGG7u}MwiLmjJ2y2dIqFXkc3;nfi5l0r+(H?+_ObVS8qjDe-JNjQA!=VsTM!Rd%YxP?NeMm>06b(kvUw~>*yPw z9npa>a^g_dn%yRP+LZ}09565}wCj5Q-L8z2*rNm{cgVysOAbPt85)=9B3=Y|vRp>J zM})V(i~5%Wlp7c>q|0!+anq$ryg52f+8}+B@>m(W;gdR-cx)vyJFy>h4o2FpEwPIH7 z?5f3!YM0EauANm`S-xa>rQ4X8)M|}nUdG)0C!PZG-lm-%?OB?YhpDEF9$r>x2xzYp zspN_BK0SRvfQA{bG7!;F>!8AFDE?nY8CvU`>!4oVz{51)*a>ZMXu=S`7qGLP1jDf2 z50MitmcnFnZBrt?88#GxDg)0^9XrGwdzBIK)cXNTD_kQZPbU03NlcTD-OX1}?@%8` z4PNX?y9`XOIY;W5womDh4UXU{swb@%71}T8@iqXAIc^OTgS#k{DIj+y6GtA*lTjw7 z8+Y9RaSL)nnc6#4yZ^Xkdo*6NukNpab|pRW0BWPe?F23%z(a|L19t&ehC7sZ^GrmZ zp^?wq10GM$(<|@mKc|sE&DV%dVwq#Uggm;(hHdeAo$nAYT&pA(F-iXRtpX|($bfVV z2QXsSekIv*4EZj{rPS*b$vl-vxxq%8H6n{fsjBt}J@dywv=lu|)QS0`rv2!j#}KnM zP8{41gUh>n9@(!vBIg@qoQB`clutHVXNWARx3n$-d&Mm`C^a5lFNn-&zobz9PGmUP zFDYS!mNC7LqH<@mD#;LQfI$$L)Us-RKBWjv+6yQ5GB61E{H^E@B7)E#hJ9XC!VrNh z0_nJl2Ud|W`~;eEWn9l+exR(9n9>GRsAu8pELlqIsXVCMAsKALP~+`FRw7_Gx~`#i z(;i;Z3!_7X#+clpb(_cCPUh9ZipqNvl6no|HxLrA zhuWe29=Sc#bNXgwoy}lzadJB2XUec@8lXlM@1(2;G3^6Ag4O0j8VLgd6_t0JwL6e2 z7(}uo2FpvW+Dyufkv&g5f!sYrrwSti4qT`MW#6eaVJv)WFELU=UA34{%=?=(Lm(4c zTtf>!<2pod?jl4TC2%(Z&#wqFPj{4B7g~w9qfVlB23N()4Wm7z{r5aIh6xiBFzyf6 zAd4Pw_zvs-MD<&TYS*HGZKu`{G!Rv8NLo=5u+0X0I&bsSfYzTY^EQ}XV+^a0d z3KDgn^0w^c!>9+52lNreR}bLa%P4jR4VIY%W)a}#^Yq9LTPY?`1@;l(9C*{ucL-Kf zOKm%0hKLQMJw^HRnha86EZYG~eRC5L>yIgfuF@E-d!7YC-0x}hWdrprY7k`Qe@3qr zRHGsaTTic*^u!C)Jo+%7z;R^Qzx|y{nJ*{6M2(sfP;re0OcfAfEV9569s_Fg4m&Pn zY5{y07vD4OA?4>%BC+t(nX_Su40nBv-1F(f%1U$WD$4g|s==KEVlATjm{KRbCLTSe zOdLiu8?41?`t%n9%%jIr8Xn7$^mJY%KcZx0rqMG^eykNdX+OmCz*-^JKBA;s-a@_R z#*51zQT`aVN2z;M`Qt{~cteK7l!v0>>SA3huAnzJ7?>xz1dQ;q%u2xP2~S)Qx2T6o zL%MK$Xv~8VSQamCcud)7Y-bWsQ*3AS3Mg$l9#?)dVIcwnaaAo%^^ma4g+RTbv7ByQ zFsF>>Py)L7hz}q)3+VN3ZKYMhG0a^VAL+AQL6AToH#6}Nh@uxiU_Dde(f6&WOa)IO!G z3AD$HW6vtjati#T6j zBZKMZy*c@BCx1x zwT$s+_-<$#5f*Ohz;08cfvP1^bPKqAn1;|2=*8X&Czfr^O)W47$`hR@GS6&A_dQe< zXK->D)8g9%kKj3hMwsGcLS9J?Q9yW%LyCWkgI=@HB#AT@<&Ff%xr z5g||@UVcX@kY4J!`CS}>4jU+3OF$b2$*id!i3omK_|AX|Bw2-YR!J)&!A3x;TdJiH zo>D{U!phOoIbFqBWsW(+Dy~1P6y!Ll)n8MlIT*JfQMvTY7^hVZS4Z`;$_&Zd6Z@WG zm1<_9n0CUzM^8SXok3bm9Uf;y`LweL2$;(&19mcWN*7XFwqQy2QbsgW1J(wni48F1 zsnu_V&5-`38R!(P??a^Xde2?&D>ljOfc1$Flvjs;CtN^ibMIf3tkFr-_GEznjs_(8 z;;%}Hl7ZOb_CyS`UH5is1$2}7HJlG zwGyxq2+8kwbs-WIa4dk~7OgF`nue_{ysYp7^JkP0utFAvJL!#qDb}@3J1gkP)&k=# za4^)SIcc7dz(^yX@gRP%X@*VbNlK_-H_%{6TXE&FPf0cBS;bHLlr)cns`ahJDwBv+ zIIW^(-e{ha5=IhWa>ZN*t$Z3TwBjNK&6l7|ycT6Q?$$o0@F+?^>!GoxT^3FGq6l!O`sf4q#tJIvw|E5&rcAYI7zwR- zXTI-drxkWWaYG?_a72aC2Vjdg^39!q86EyyTlqr9f3@) zQq<~^RGh)@NIVv_ClL^y+6)UMbx60+B~(=hHjl5o)Go z8w!9m&<`WjFMva|I#K+eU5#@jBO=C&>5~dO-2~6?JT%MRGvA@kFst2Av9-W%8KT-- z;6NmMCwy`IIa0k%yb`4*#<(Mj&HeYovrW}M5MM;8xBg{w?%iLU+`XB0`WC8jEdlbEY; zqa{jBj=QjI=0?vr$*2H9(!3@C;XG-{&&2d-H90@@eK@`&{K25r4^kDyzUlnY5a(}x~`y}}CRm1A7^w&5nY`_~Dy6u)YbzWAX(I_-4c_4bpK$u;` z25_w~`$MzMUX@stT&1{8@E2SZuePQp70amLgkS~DEf#ljafCYs*EodaQWMHr&8WAf zC857>HlwG*TM~S?_P2~;-r`b|B2t%rkbxR#2Sm0@Enc_{&mdfI$pAXR+r3Vj*!+Y! zN~;4u|B=!#*n(gX+E6Gb=!95;1Om6YRCQH8BHwJPGPxxl{cI(mh~7y#*5p6(c-PkG zE7$4M*K=dB0Bjl5P;N;(b(d=BR8c^{4!;T-I4l?u*XU!wy1jAxCfLHNWTQLi+JWVR z*8vjjgYjtELH4L1{Z|x$3*HxbsM`aM29kTX(dGPB7hO zyy)zsCthjzbc7cf7S8V?>>S0aZ)kT6Y89<(T9!NqkQwnXy${Ne*x169u(K3ejo1!a zz)I^;Q)6pDZQFsSXulKwBz0WOl~f!b?8+3{BT|#q^s+q^I#kijCv)Q?4aC*5WuR8g zV-eY0$=V!@ky|l^}@3)cB;3KU^>yC~0Pg$hn zU;g4#wk5r`c-@wKB*|yX=~|)NhT*r@5#x8H>5jA`7wehDM|bO)6Mc?}y@kd8!by7J zr2UI@XZn$9-8oDor>grsad~=NNw-yxo4DWFYm4^VQgvJEk;&b$#~S_9m+JU8eAy}6 za(p^u*KKJ>=J{;-Mh~H3ATe`OCnPa*~=$TVqbxi3UHO4<`sy=G!{&|NM>dve# z+bL(^x#6a`lut&$JmG%%bY{*YTYR}~k8TlXQ`H%sMAIT^h1Baz@;fthXNJ$2r5CLD zST-+`?4QLuBP}1t(WCCH(4EuwuRgT3%XxIiaZ6vcDLJb*IlDJ~L~mAcZvrZJxVAS1 z#px-9WPUkioG)ek`ABPo{ag%X&=+q~VdxbZo}Ve1MilotGyKjx-I<>U>x}xyN|ZRl z{@L)vcuSuN;NxL<)t!0!mmOKvmnR-bQ%88>ObeuCQm-rZ$b`eo{H{XXRp@h#)W@tx z+67YFKVu!qQ6I<9qwbokyT%_{ePruVXZIC-k*4h7z1bsr^Gka(ijGcz?b+TO>Ybd4 z{+!u*&TRN8KJT!^#+{3z#OEoW^Nv{5JRgnJ=YXSV@gcA28 z`wK-efG-x7xTiZ`nm#M4GCIoZ99?P6^-gl)Ss$5DnG*BLn5mVSiKnbKgzQZ%soU99 zLPNIa;tcgJ$wL}wl@O&oNb{C0s{D!O<25vwf?JNzZ056tZ$050l*MD9LCBZ|ZOkp+ zL`AT+B~c3E616=Ecna8!y&zz#c0K0KE8@;9HDGxV^S|B$(RSQt8zLVHClngFx#eOR#^sfu1oH`m-Yo}g zSV|hmN(|J=SXYj$$FS9yQ5Y>3*n+1O+oN3tXqXLj(32M}Hjc5f>Gd4F@>V2~X#5NU ztP4DmzVfE-*Yxx>0BPPdlc!@U4&#Z35)BRQMk3q?0s3Wq7*CXHj0M+E08OS|BEqdG zEZnraa#!TfBkyUrZ|kqNK6JT%!cu+0QeW{h?~0YaY_~6^(x0+cPg#4~=D1<8-&v?T z3y-e8Z|&V{b?1cBktzPjB0aLmA6cwN79VZ%MV39D?w{n=C%L_=H~3fA>-aaRUUzyL zK9Qw}&C(}wziIf-U?1KI(Tu~{XEmvju-}@PEY=)e^V3W2Xt-YuhopSH$Vw${6Dy>HkCUskO@t5MHtM1@Wfu`AY{#ofbuitaDcol{RoX8I#b^vDu_ zKWxP$S0Tj=GW*MHQx0bd?~f(tcueC@~fy8W>*BRgC!1o7aapeQQCyzP=gLJ{;Fg8 zhuyMhx8#O1hj$V!Zga7Wi5S}?jWW9-tX+r+*}WDZCPy75rsS!K9=B3#t1_2M7^q+@ zF&1#;4&wkqH#SHHH47eGG^7Fw2~~_6d537gloEO4Bh>4V4pC{KX#8m)kr91ROxds> zgz;C0p^dCBIP3}}e8YATIPE&^CY1RB4Z}8+hG95v{Qc8UIdi+lo^qD-x)P4Y9$W37 zwp^dK{G4o_FIhUu(Ff6q;;kHYQi{cC>9d<0F?|ktGFgHcg~5ffaWz*-c6x0c=KrJ^{Dm{-BsIQyFk4C7Osns|2j}mN@ zVuCw1drJhYwd^}!c6DZ5>JT&ArC4!jI}EZPd{WLZ!=dR5@^GM2K$EHY}DvFNFkV=iyrxK}gFo=W*>x{;WUC?J?oC0hYRh|XFVL@|qzty!?n1#ffp$0|mY>h$`V%S1| z5YPq+)eQUXDEw=pZ*TNSMQV}cd2P~6pL5ouN!_kfk#J%1YUHR#k~+%0&RMdhxn^K((lZvFNbzMX@}(}q3ZPC3(5CEgmPWJG1dPSrs6tAyu87)~OG7D_q9PvV>da?>Y11?&56J&Y0j zr3SAAu&%mgn0X-=NEWv;$ueFNw~s=}Y{+HI3B*M)k)^hpg8tG&%QMM6^G!LXn)Lo} z@J$Ln4OI~*DwTxJ(t{2UjdlKmSsAjC49lFGP1EEo(`KpAzLaGShPmSXx1PD{dc#O! zJIR6Jdf?2@e-<>Z820gQi7#I^1#TC}c%Mv~xU)v9Q-k_d zJQ?FdoPaUWh_4J-gL(0?A8>}7LJZ>%SmwhbjN(JGG9DYtd2~KM01}? zm^E$g7}L{Z3d$4Z4~U}hEf`@hQS&EOOXER5=r7--(FrlcjMQr8L?D40KoaxyA&yFH zE>ZI=_aJ6jf;d=$Gpa>iWf4rb+*hK`5?A)X$@&W>asPSqPd!yiJ=mH7r}o&(^qXC& zp^oCe>N0o`8>k5FZb%96Q=t9=%bu|2dFD4q&iwQ!pWT5s44s~YI47pVtg_9$Ka!dQ z4v9zVh0XZ}b0kibs(IV*LxRcF>uXSahY7m^xSeV`(DYNwsjP9n_Exh!Z*8222mC?UIwt^L&PeKVs`1{%c!SDSMUA2@MtWi)71KR48( zVn-c&7)=*N36SA zwr5#kS&Gdag=`pAm-TabIQ)6@MswoADs?n6h4EX9o9QKfokTY|)K1+v=RXj=bL8DVL*#tVoC#~TRaWf(cYU6KrjqwKHfW=QuzP#ugvcnOj7Gw2=!s1- z=iO2U-#>?zN=}bEI*d5Z>94OlhHWmz2JNccOT#;xCO`3MO!30a!W!F^EPQXzMls=^ zU^EscWzRf$?FY9%cIJ+|-hK4O>{25=8joZs9vJvgjjqm;Vn)e>M4+hrHT>DFqTQXjI^%L(taU)8?4f1!Nc=A2iwLNy@ zfaeaQLhn9u{h1%$p#8#%ZFNvRKHT}+x6TaS!XE<;G$Pd6F9|Q9%@$MFL4-9#Nh5}u zPYVsgO3MLnzyi^rs*AFu<~~a3GLZ*RZXGF(K{$zfH(k*P+#7!{H5G^?E{~FSe*-A*L-H%jnk3u413ZTH3w# z_?QQ4gVT7G9<|zQTOA(7T6!$$$@C}FgE1=gs4B0m>NIU2ea@1O^4`P@kaj(>@aRH4 z@uH4py{?oaMY^ltsOl}Au8)|ZyJnE7mqed+STKvr^r*|dw#$1{3r~5Jq+Z2Be&9|y za%s5%d)6DDfls~3S^ne_J-LLIq;&_@`6EXj+0dJq>Q5Z5Cl1HD;Iv>}P_0-O;7D%4 zz6IATqMR1)Te$zyQ^++b?Nq_!V-tJ@!PUYbMi&hTA6sBcZF9T0u|SO3xWRSvqh3C_{89u;z7FnK@IO+z8Pj+&pxC_MGvexFf(h1%59Vi03w{@tuGF z!tM-Pd>ouUZM+l_9vaD^o=>n>uZdxSAZIM@{X~XPGDeK)!Z|k;B|KJ%LrO=&JQs(2 zaS=ksM~K+<@CZG%?XaaFM;w^)X3MBG3l`n}Q*v?IJ$@f6L0<`_7u$rW#v znbYC6=EONU;oBRAJmGaLSi39H0&(5_N~V%)LI$ssEEK;jPe|#CJ90ey^);cgMmuxA z(av14VLDts6Cy=;JDnlZSIF$hUGPa$rGjL$$X1n%AhG3;92D#3imXw<;GyZXLiG!E zlUuAqV#gJRoymrPxWAXfv6CUML@w^-7AG++xQx)$3pf_K>F7omB&a zY~>=hHjn8Q^M>rYr32m}S1uz9a;apDjl#r)$ylt7Fk64UI+w@5*qr26#HmgHn(2#Jpnu9t6S>Pm`rKXyie)>@5>`z-R!Hk;I&>V<@ z=`=jsi2g*G#>u5pxdf?GPEhI;+2VAk)vWK&qq?%cepQiGaHUse4pJSglsNsa{yDKK z;H0obR+&cw#r@IU>BSazMwp<-x!F{h`3(jF>k^d5K>GrAW7(qPSFMv4QsRUHc9Lz@ z!cu)>vms(<3%OvnaFzZ}N=sK2jfEE*B;!a%xpuH9Bd&APOhTY2;vQHl&SnLsQhdS%P>K@UVRT*sj# zF@&;!Bh;a-WNw6caz=8%VXT3MvOG(eSh17!JPFf7N@EZn$Ot->+F2*wFH|GrYmJPw z$5Eqt;%|Pdh>uFa_q^_i8@zLf+TV6)#r0D==AMp;ziG~qh^{d{S3#HNiz(_@a5^se zG)|A5K3j(0mZ#hDx+;9Ok*7w_^^cyXkDliry+j|qE86~i~Yqj z^x_%E?Y`ngoLjzb%lF%gbX(EUi+r}Rr^*)j%hu>+Yy4%kdReV^;|^chPL4=X{I*iv zR@$BJvrYfRVTreV<}_KI`x;L<^MWTQbZX-BSf=4LSB*IzWr|Lqir9Q~Dw3t!vbroj z+wgnR@5{P7%U?KMFPwhtGG8Go5`8GjM{O(6Z3SIu)wuqnBkx5^{o||j@m1bcn|$Nz zhiX={zj%&bJjY+WKrdc!vdCBLsXA?Q9*q2cW{kG-0 zZMk>FYM-r|y$utB{I(HrK72IGXPfl+RR5G!`jl1vDeLqp>%8lmd{efevC;jFytJ~IkYwCQqO{b|FhwHZCe%olAZXMl$ad2wp3jfS? z`pk9ynVa;Po4oZqe4d#*!x8pB9j*NjCu>%VfxkpkeEN|^-NSuxll^gX^td?|UtD>| zqF(XiA~n@>8GJSSoOAuo1t%r&^Nz@alMhTjZHt0CM_ZcTM#I0W=C1X(ulE;B(+j5g z3ufyDvwa0~k6-+U?I*VTE7t23>-`m*^omWsiUyyp@r{V+1Br)RN2J5aN7m>u!+a6L z?^Ewqk2d*6kZVe(&g_@~MA5uKgO^k2=JE-bp~D+Jcu_h*>p4e1XFooEYc>^?I{ZCLDpJj?zhi1IB&lphfPC{;&_>EqPJ zYv=Eqe=0KHrxf^=QMxjUN$fIx^fIq|y*_%qPubvC8g-@dl(L1kTgJZ2nQ*Ah>qz%1 z>BcTACTy2Q8epy3&rk=^^$9NQzc5byhrHwfEt20SFcrK7+vPqhy3XEu^?Uc;{@$VM zAOwJy8$*O~Jz`bDbSJOL4^k4=8GD$X2rq#&I!a2MSxfgIwBJ(jBLp5L@E8F;Xyi+! z!PAi(!VP1Wb76*HpIARpEeP}QM&-fRC5&A1DI~KFd}I=;19!_w%Ipa$=Ua4P;$(W?xX`X)Ne;Up0g<_=6}Js_fjRFB~fs-ZWpO9 zK;?OHndDHBdW*U9cvVJ!cv^0iOdR_(X#_H+zXmXT*-*KxlEJ;o;v|3K3_Wp%FL74KvezA{ zz0t1Ij;Q^Y9=zg6uFsL-cjW1gJfEZBXqN7n=yz;8R(Cv_R3ewJ@J?NMY86x>>-}q+ zyjz-ltG4M=w|SLqJow@6%nlDPwZ;u_?SX8XjL)Mo^&~)`KeWzd!T zxikAOQRWsnN_kOE632gHw#cI}Yj#FqM|tQ8Y`X8+1?A7E9cF7G@tyovCG~G1`uTdC z56S)AQWqmidgNrJZF1{2632GB})Ye*^?fdjYY% zL@IxecoiGwrM(V}jWnkK()jTHx5rHm@8qc=K!zk>y6$+|W9$WouR=%{wz zC3j!)P}A`wf5`&9WC1wedo2DDv-A5dA2{xm&*nzv%L zZm;$#FeWN4nW~nET|MT+p5s&1Rc0$|Rlvhv#te13BO6E$qF-#Dq0TYf#*lbd%R;jZ zA4Ji{<#|TUP}pQVG71@)ypS+5neH(KWopL@jnzOQA2l#W8MjQ-$|RF3xb6UDCdMe? zR7{T>)xMQxUodaFm z-2xV0Qp`B^nAHS7fu(H_?surlRMFwa-4GTYZJetvCWXCyZ3xh1t29Eqc_mJ6v)?mY z#HoEsvbcAX5^u)@G}D}{QH9qnWs0sFF>95Zq{PnSo2*im@Z!*+)6+JcIr{PytZAZ9j@NkWPfaq9-DJIF|TW$Kfg@RFY_gi?@dVe zClo^B-y4_WC-v;S-tklY<16&>6(@^*s>_m zM?{dVC=j>KQyrr3NN`7lsht4(I%{VFJmwTUGE&h|V8_lN&s$@$=i2k`IA;Ui~ye#uKt@H{C(J5SlY zPJp>WVjv6#eb9O$%ck5RdixWk3}aHnm-EzAhaZ_lCgMYzNsL*cCT_W~hfj@L38i?E zb~w$OQR0g&g<9pv`$ryY_KjWinQSh@4h7&mPG{4Nwvy-K;kfaAv5 zJX|~5GG9$Jm)eN43wFVM^HmT7@z!nTH1325jB@@%Cy?{!PS0N=s1Mi?^nF& zCd|4Ja@mW^0e<`w#UTnlmgB_yOU?1-nmkdv5M{o*4qm^q-*$+fEmUn0e3A<(v4M{G zWvFVzK*jM;714RFGQk=-`BEJ6Cg1W4Iq{aovMbIV6~u+zJ?K-qJKFf4bM93=Kdv{HP16Mkf&cIoh zJD$HNZWsNAjzz+TNrd<+Qi_!m#!H=l`7#wJ?&egwVU`$7NdEIo?&L{Od&C*{m}}so z#<@g|$uo+KXeM5b|Elk99$4cc5szq27acE3E?WbR-LeUZgt+vG<`DlIK1e8%h#6^4 zQjpRqPEUmcqwKe1rHIabU%F-@j3zSw4KymEnFP1}VcbB(%j^&Pj*X2MQKuve`Zac= z*>w>zpbZ)S4Im++IXf6c7-fVYUd}+6S(I+a)F3&6Y+gCfSX+T4$3k~X&4Phw1BV#M zB(>P=PGg=XJ;;6!5Jc@&B3{`N0CO*&5mkFyR4!9XOD6-v><&QtnnIanr#n*N3vuvR z{>gjK-t>rwd09@5z*+s7gFV_SR&nz(b*yI^Wx@;NSCk3gle!a`XzK{@u6sJ75UWM2 zphm>eki-{+(OFQ^|3+-HDGD#)&Poo~pyuXKruM;{G8;<~9(w8@9qb`d4^d5-|1?)UJRP7TGRoYP>XrYZw~b0i&Me zwi;*qlnGPRkUa4ExSETd?&#-ePvyh@&(%pU2FJopU}<6fakT z242-F$Ghk>96gIaw|%jx0c0;MFNf6;mRV=br7pW0hijBqcq~Wc6r`_v7-<#SP?+6O z;wM$=cJcD}q0s$kC2sJ%^nI);2X2z%BivE6RzVT5bKjrR#GAiEt>4VS;`aVD*|gwZq1I~r;p48W zmGmgwu#UwZ8^dnr?wZk}el?c0_NUC5d zlQuN#`NS=BRK_%7ACP72?f9&XDFK^^;GM&>_!=m&qM2kFCCpCgacXbGkek~3#jG_D zk@rx>zX2FZp~n%l_Q#Tfw}IBxG^xpk0UX8|yT4=kx?@Ji+}@}Je^j;}m3_3$8bF6I(U171{Yj}{ulu^aMYQU!deU|Eq2+DJ?gWmOgg4i)lwU~ct>OA;hlBmJ9 zQ526g$CLj*<8-~N-=S(q1TG4<6W3lRS;(!bI6m&BHW9wI!7 z{-<$rf-)dl4<*X}-TuNbOM=>4C^uYp7V+sia&u!F<_*b*-bI9F>UENq4(@gF$p-bG zFu3v8T6Lx5DMbuEYA#f9iDleVD?8x=?f;j~Fsab>+)oR)_MV!5ts z+e+4WW2i3H&2?~swzEm-_3CJ=mP%>T#FzDIhKDrGVfk&Kt{RgZVh**C#65>za|z@T zAZmF*`{3+bE1)mK2n;7cn+&ZG0QNC=v}|tLVwkM4^>?5)k|KY*(6~$ocx0=4jg*v#J7}EWPEWreaFoEk1b#r^8333f+O(~)zRfTfewKniCGZ6SR%9Thbj=NbYxM0q zVeCrXM3()uO%%R^fag+z9h8E^b%xs#a#j+EuC1+Wfo6Ukb78f$+I19@tOf4)%t@oLjzA-UtpEXK=ME3-ZnaRrNvZ;A zrx*@&*k{v~^m+{eLEv@*zaVfAfqMyb6L^RKn^j^9R?pMx%LGml_zM9RPB6dB7Nppq z6q%9oXl(OnCAGbZKrMl-1lSoG?WZ)dkf5~_NTs~kX<-MwUPs^-0*@0oN#F$nFA;c^ zz-t6PBH&U0@(C0X7(-y3hv0GoD+#P3P(xr7fd&Gb32Y$hrCC}17|H-Qt>c~$gOOQ4QG3jvKlJAq3H>?Lp|fx8IYty1~FrpJ2;bQ5@hz(WKc zA@DeXCkfn5wR?u1o+I!Qfina?B#=%$^EEw5G_U$-%%#y&E`cHf?7)6HJ(0_Kt%87O zK0)$`tt}=%-iFy}t+tAu$UUL9mcV)fwFJo7nMPj5G;$iI?IO@d;1UAlZb-YFKnDTx z6{B?$xP`z^2rQ<$-AYdnTg2;4xD88I@U_PXJVAgAE37^aq|;;WmBAF+EOFiZfucFtE49~4yKVEu0RZnY{!<4shzX394>q2vSlp~+sR_{ zRvKA*V)GY#kKfStCVeQ4E`e%vSIoHmK^HqTx(C6!*Q}tV(Sf*e;L67#ECHmGAC1l} zG!pDbwYF%HlCCQ8wAIC*VQC;zUCj4~g z@z1f=PwDOB)ETSKIZdO+bx-w;oO#Y9OEE|G z^wH1pHJ{QCF3g$L?%sxKVH)T04%}J}Jt_ED2!|%~O=lPe47}IB_ zpgvpA4Lj6_&E~#Lu}#CN(g&J)Ut@aC$JTNjH}%G3^vU$_rYpHmr3YMlNlfkIkGS$| zv40xDp_OJ+I_!ZU*;FZ}*MU^{2sfW^(q9iBw!T9Ag_zk9^ zCnF7>KHe-%lPunh(S0~Zw;XHZAMg4)8o`3r`m^b0o zn}gn=hhxfl{x$b46koKd!!sKYcqFOMM8DmY#_#dUPx-xXrI^vKP99f>Z@tdUF4#&b z?vv?_t4j~T`tqYuVSb!1?rB%EGNL5wkp+Dw{2ZTfo_?qYM)aBS)R)`ye!IF+_1L9L zBpO`w+l^Y%?@7h@^{%Zu&jFNfc%PZR^`%meCta1~jTrBfE_!W!gSYWw-}>frCYw|# z9i7w1zsF?b_aw$Eg?rs=&+`N2G@%b(uq&m$#QBhK|KT!quXIk#zFZxVqe$DOu1T;4 zfZvnD&+{)OC^~1RpuQ+^{pIRm=~Iz$g_OE$Egpf%A^F9xp#R_rzlF$|`U5I+$PbZm9D%Y}Gex z^={klE#0mcwfvJ4^i@a^Qfb#bn#HBvm>>8#*7i^O>4WUpqh=SaqiP|4`t4q0{Cd~b zf64(tY|yv9D@AIDdeNu^w5A@aQAjnHe@>!Jc=Kv|KBZquQg#kX(ol%EmcWft<;bziH08idMno(50EQeF3mB2%Au6S9AK4VpatTked;*RCGz)dH#n>g*_zP?41 zwhNr;A8=osU>8oO=bRVfOuOjn_dDmEoO|!N=bn4#y_Z+U^f@xvz_c8->UpLWwzAD? zBhyW`(u$muD7EV{HP+%*u5sS!rTYzdDYNv^by23BdQ!C=HmlAysJK62+7RT+M=hj6 zNb>0T8leh<8+PF%9Meu%<5G-G9!u`RPb!f9_&DoVMd_MA8JFO-8=?dBrR5u#2?wHp zuXxAjO&gO%j60KLWnLqPCh{sdJ-cRIR7Z+pu3O?}-v*e4#E@wtOgfX1mF*TsQ^iUQ z`VlRF_w>jDg(>Yk&HxD%i9VbGzEB%8Z;4QJ14LkPj$A|_<&lHK4?8VEUc5{$BIM#V zEyVsX}~~;GVHCqeZx9_%11W z^YKXWLT&8(PepCC9K6�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 at+XSVq)=y}z3kCm0|9=4|H%nRo delta 8619 zcmbVRd3;;PamMlhLGTs{g5U}86va!ob<(6nQ8y(KI;{vy7q;^xaX(c;Z^PC*Bf&ScR`=^_i1<&T*Z@lK(<%?WfLYfS@I=#a_ ze<&Ndt6E)dpAQ zJOS$r25BXEcB~JZI&QJ5)j8$ra(0gL6j?+WY8-k`rAa-NCweM#mG>@E-(6GKW^z_6 zOqG?SRUYfF5?anGSv8Q;Xpd(1YCA^!-d?RgAiWb-C37EJK4B+~GbvG%e`ILL(>J6= z(|vxLik_$`u-mUmx6eEAJ5q@nWCeaQLxX{!+wU3HCOXhk$ZOU9Jlm+WL7Efv?A0{4 zr@uci;txm7o?-mDcW8cHBom^XKv0vOa6ocj(LB$PkJ`FvNxYidA2^dDE2%?yEqcwR zT7PJVCZ*Qer_>U6=4>a_x!nm4Ui%u^k!Z7FL~V=UOD%!RL7GMy&+ zTTHW#RnB%=TQUrW6FHVbTYP!rztXBU=2+CC!W?x^QRbGCq@^r_BTS0iYJ)S;(plh~ zM)a{IX-+LV2F@laC=n-5g&HrcNH2rF`kNxlwyOBpPCIEk$jI`fzN-J|s1-??HCJk? zDofeI+AHen5+mt0S0%NsPiWd*j@~X1wF-XKkd7lp(}t^b99@N}G2Ii@X|1(Ms*O-} z&X9Ej*2bo2K_}Bj=k*5Z)#StsHCEhbWEw0~9~3u?E~W;XWieK{1h53K0?E?{)fgqQq=kN~Ip1T}=Fp80B?_fmhL-eyMrFTBFz9x0iMi z^K1eZL^FaET73QixgJl(P}mb52@wU)TNj9WRj|jBzkvj@36KTYsLpmbY`Tit+aO^Y zGqu^Q4%A%-SP5W$Z%2tq?m}rD;0A!3IA5V&E-A|I#Uo$_{SSRE)JG+MtKPG%Veg_fFNKOKmtO5FyI!zZa^Af51D>lc0^ zjL%W+#ItJS;_Jj>b!KtXPB!c`8h}tey360d^Ys8kdwo3OaV(uOdBS0BI2aDe8&T&5 zFxP5Osspew%(`drSWnRCpbc88@+;Cgj8?06!s)FqLi!SbT|A8vyUjDtEM;eZ3ISq& zwUIk~g8hUu67X!~t0hZ>c#fB1bNdg3c;!S#g#$A!!3K%>oG2oQrUwTDlp^vX?NjX? z^;rj?!1NwffsP}Vsk#3hG5K8S2(*Wozs)F;)#%BAh)qeUZ621-ct4z)5TV`dPVK% z3Yf`p;BJ&S8tVDV)CR7Ag!2Zh?g%LIuRp#0@>35@jNO&Q)~oo)>-86;OR3Ws{m35! zc+n40DQXUl^bOm5p^z`&muIQwOscLIVP$3OZZeLc7*T7wH;U@`SyT0osAR?(QDWme zP+}8ZU~DZ9a}Jdli;o8RI!a8Sw@`|LMR}MIo)y%E?ofgNL4>Z-bIP0;60Sy2bciA zB8aB7}`Wc^QsP#rxL zB3A|5tZJmEM18m|R~=|GtM5_yo*uKh&{L}ZswZnSp3u|1#^fph?P!BdV~!&gDsmR` z{TF*EF0~}2c|_gfcn?l1YnCKw#&#n0V{_VAT1wJ*;)cDb9@$V~W(l@Og}Q0OboG}T ztexewtFRR+Vir~Km<}4R(pg0bS2f9azmc_e$ea#YJCM~_Eq_4|v~+6P#-`h_Jp6{pd~G5~fGcNE%E%490U>_DC)mzgnuPHZsrZVNb<6asE9WF? zq8A@Ba0{KP9Njf_VymRGe5UYkTLMa%YLtMo|=@HhvE1;TklJODmJ4 zRqCA#>!_Vufn4!cjs$(Ph)(74QJmGR3DU(ir*0NkYSyx*BT2LF5A<0-#HwIxyi+~s z!)T*(I$s}B>56P}WyYA^bVXOq3G-U$q-&*Jfon*-FTO&!&{v(SzPATgZilXg>job+ zv_EDhdepUWv59Gq&Y~V0lXPdZ?hKlkInKGxdCvJHZz6fK^BUL}vvI){S_^4eT3BaM zlFs6UPKt90?bue*Xme&Iouo?}4DGaW+vQB!xYx?V)W6R`G?uqhDfuG*5A@6_Ni-wu z3GKwCoyodSeRh4}jKs00pL!gQvx(E*k^ZoI$mib~O&{JH+BHP?pjOu+(MedWMqPQO zeA;j>`!EK01n?-}lzQHELbR(jH&hn$fr(@4gM03}{N!K9bI*e}*jC}llQ8UJ`bhn*{J_-zz2Y@0EhJ?2#LHLc!l5)sc$_Xu&A1COas6Gjv1`MOl7 zzxnzV)Hb$&2(0MoGypR!|D2#(renCr@QgUC$2|^1Y!OfOI0PA_7d6psK%eYU^=1FA z)?75^ZrR<_P~^$v@Wj1x+)6}KK3en97rP`2P|`00Fk1q;)Cb-Vgefwv9Zs=eDScZY z`Z+r10gtMi2OUcn({nOobD#u=<*NWD5zL^hi&Cy%9X*qjbuCpd4>r%^nZD9PPPORO zYJxhPWHH%fJ_dMRHTv4b8*00+q71o4w2&y+nNaW5Zt-cmDNQ==>z=wk*mbjE7Eg=| zC7vg2URfm6*%B)*>1|Upa}bhqfad{B4J$0*42RE%GNCrrS%3(VKrmR|>ve zJUsM}FqTpS-*9B9f4LAV)UAQSd|vtM(L%p5smBBJ>#xOg9iR*&@Y!Rb5+y~RaQ~n_ z2XCARR%h|x`uwsWJ`Jt&FrQ6qR6KK(@51g*zh{4X&^f zwn)GU_0pd6qK2(}c<)kS1lN71)I0ksMV0z$UkhEro4+}GLuK6JFY|FI#G?UHy6&sv z2h(Qxll={a0Uy6Ko zW7`3XFcwp#FQVkZ|H@5t9IYDJte zWqxmv5gQf!$ED&AH~=#xAfgVAy(o&OxL*PX&a01aYw}DP$DRHR#CR9b33v~{c3!-FdAJ|Ch zdtL20($IdDXMfs0u<$-$v;UNRkYuqHrbxi+uo%3>i_m5|VdtugcN`WrSS<$C(-~I! zL}{Yehi&TfIpw3-l(L!UQ5*bmra7}HDa&(Zx^mO$*_GwY=5)+RsbWS%BeDBjFc(Mqbg8>HPrrACe z81VU9cF@JoKEmquu#dj{hV457((duw<8ROHl0Ti=DS-@(?r1feHxFv|aDcuM+kGLs zR~z#6;d7=owAbE8pFF)Jv(vjVdw;-Bx5}_awI1oEUhwJFPMU+7w1)>helvYI(t=@n z!D{!|k;dA6Ui%Ii7$&J^=ND|PcKhZ*8fB-Z1w*7Y8tV7>{hF6L_iDOspGF;+rADu< zd1!j8=;R6WpHrtG#B&u1n> zb=#A>U+|7QmXEDJHveSJ@x>R@mS3uw`Ao^VqVbyUu{Fnx$M%fp+b^bdUus(LLdnZr z<4v2!)*dT9X*xakfxPj8=@-*BU22&7%yloPjW?_xTY2Z!W2;Vvk8c>yslAxCUTs`e zsy=DW6bsaKcb**Wg{>aI0N_@@alrk6Cjid@&H*j}-URS1{t`-u0i1Yp62(afAKiR1 z^0~sXnPVD<37!qitDJ2pC!9mYsAi%H6%W7O^$uSa{Na-^rP(@9r77 olxm4PsSSQ7yVZktkJu&+W^tXEEVYQ6#L3z(Nc$#1wiyin1KvUE3;+NC diff --git a/backend/app/__pycache__/schemas.cpython-313.pyc b/backend/app/__pycache__/schemas.cpython-313.pyc index 48d29dcf015f62a591c7cc2d140b172b02a0a9a3..ad595d2d96a5ccac471998cdf14706b3851d1fd5 100644 GIT binary patch delta 3204 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 JWj<&h`45^1SgZg5 delta 769 zcmZutO-NKx6u#%Zci+r=Gw;p6+N7vBhBMI*^nwhPNF^D|qMIlP!RO95aB@-v}kFxC<;nOg*GB?VoEnHg3i54t1jGg&Ue0ZzH{&SlY4u_-E|zB z;CVgyarULX=(cD-$YM|Xf;Ot>4Q_N0MwmWI^Cma*0UkhXFghB{Tin9fEZ8i7H(0Pe zlUZppYw!@WRmSiP7E+lo3m2S!wa!7k&0NL0|6wCnJex%n9Yt}+(^yoY7@`28m_l(i zSYvU85(k5mg%mzVqxdU)LPBv({(1NcbnhxAMOyES>^xZBdirc@`PI&oH`@=F#h`u$ zZ2yk_0U+*=(0&8b{ynP+ydZYycy}{s?vrsC*QNkNbtYl5>$I^Sh+nqVySKxOSS28C2R3M@!su$e(}rgrx#H0l int: + """Mark dispatched answer tasks as expired after a strict 24-hour window.""" + now = datetime.utcnow() + statement = select(AnswerSubmission).where( + AnswerSubmission.status == "待用户完成", + AnswerSubmission.updated_at < now - ANSWER_TASK_TIMEOUT, + ) + if submission_id is not None: + statement = statement.where(AnswerSubmission.id == submission_id) + expired = db.scalars(statement).unique().all() + for record in expired: + record.status = "已超时" + record.updated_at = now + if expired: + db.flush() + return len(expired) + + def _ask_assignment_expired(assignment: AskAssignment | None, now: datetime | None = None) -> bool: if not assignment or assignment.status not in {"待选择", "进行中"}: return False @@ -171,6 +190,101 @@ def _product_token_error(value: object, qr_image: object = None) -> str | None: return None +_COMMERCE_PLATFORMS = ( + (("taobao.com", "tmall.com", "tb.cn", "e.tb.cn"), "淘宝"), + (("jd.com", "3.cn"), "京东"), + (("pinduoduo.com", "yangkeduo.com"), "拼多多"), + (("douyin.com", "iesdouyin.com"), "抖音电商"), + (("vip.com",), "唯品会"), +) + + +def _commerce_platform(hostname: str, text_value: str = "") -> str: + host = str(hostname or "").lower().strip(".") + for domains, label in _COMMERCE_PLATFORMS: + if any(host == domain or host.endswith("." + domain) for domain in domains): + return label + compact = str(text_value or "") + for marker, label in (("【淘宝】", "淘宝"), ("京东", "京东"), ("拼多多", "拼多多"), ("抖音", "抖音电商")): + if marker in compact: + return label + return "" + + +def _extract_product_metadata(source: object, fetched_url: str = "", fetched_text: str = "") -> dict: + raw = str(source or "").strip() + combined = "\n".join(value for value in (raw, fetched_url, fetched_text) if value) + urls = re.findall(r"https?://[^\s<>\"',。]+", combined, flags=re.IGNORECASE) + parsed_urls = [urllib.parse.urlparse(url.replace("&", "&")) for url in urls] + platform = next( + (_commerce_platform(parsed.hostname or "", combined) for parsed in parsed_urls if _commerce_platform(parsed.hostname or "", combined)), + "", + ) or _commerce_platform("", combined) + product_id = "" + for pattern in ( + r"(?:itemIds?|item_id|itemId)[=:\"'\s]+(\d{6,})", + r"[?&]id=(\d{6,})", + r"/item/(\d{6,})", + r"/product/(\d{6,})", + ): + match = re.search(pattern, combined, flags=re.IGNORECASE) + if match: + product_id = match.group(1) + break + shop_name = "" + for pattern in ( + r'["\'](?:shopName|shop_name|sellerNick|seller_name)["\']\s*[:=]\s*["\']([^"\']{1,255})', + r"(?:shopName|shop_name|sellerNick|seller_name)=([^&\"'\s]{1,255})", + r"店铺(?:名称)?[::]\s*([^\n,,]{1,255})", + ): + match = re.search(pattern, combined, flags=re.IGNORECASE) + if match: + shop_name = urllib.parse.unquote(match.group(1)).strip() + break + title_match = re.search(r"「([^」]{1,255})」", raw) + return { + "ecommerce_platform": platform, + "product_id": product_id, + "shop_name": shop_name, + "product_name": title_match.group(1).strip() if title_match else "", + "resolved_url": fetched_url or (urls[0] if urls else ""), + } + + +def _resolve_product_metadata(source: object) -> dict: + raw = str(source or "").strip() + if not raw: + raise HTTPException(status_code=400, detail="请粘贴淘口令、商品链接或先上传商品二维码") + initial = _extract_product_metadata(raw) + url_match = re.search(r"https?://[^\s<>\"',。]+", raw, flags=re.IGNORECASE) + if not url_match: + return initial + source_url = url_match.group(0) + parsed = urllib.parse.urlparse(source_url) + if parsed.scheme not in {"http", "https"} or not _commerce_platform(parsed.hostname or "", raw): + return initial + class CommerceRedirectHandler(urllib.request.HTTPRedirectHandler): + def redirect_request(self, req, fp, code, msg, headers, newurl): + target = urllib.parse.urlparse(newurl) + if target.scheme not in {"http", "https"} or not _commerce_platform(target.hostname or "", raw): + raise urllib.error.URLError("商品短链跳转到了不受支持的地址") + return super().redirect_request(req, fp, code, msg, headers, newurl) + + request = urllib.request.Request( + source_url, + headers={"User-Agent": "Mozilla/5.0 (compatible; WendajiaProductResolver/1.0)"}, + ) + try: + with urllib.request.build_opener(CommerceRedirectHandler()).open(request, timeout=10) as response: + final_url = response.geturl() + body = response.read(1024 * 1024).decode( + response.headers.get_content_charset() or "utf-8", errors="ignore" + ) + except Exception: + return initial + return _extract_product_metadata(raw, final_url, body) + + def _decode_product_qr_image(value: object, filename: object = "") -> tuple[bytes | None, str | None, str | None]: """Decode the small data URL sent by the create-task form.""" if value is None: @@ -330,6 +444,10 @@ def startup(): if "amount_fen" not in {column["name"] for column in inspect(engine).get_columns("refund_recipients")}: with engine.begin() as connection: connection.execute(text("ALTER TABLE refund_recipients ADD COLUMN amount_fen INTEGER NULL")) + adjustment_columns = {column["name"] for column in inspect(engine).get_columns("refund_account_adjustments")} + if "adjustment_type" not in adjustment_columns: + with engine.begin() as connection: + connection.execute(text("ALTER TABLE refund_account_adjustments ADD COLUMN adjustment_type VARCHAR(32) NOT NULL DEFAULT '资金调整'")) settings.screenshot_storage_dir.mkdir(parents=True, exist_ok=True) for screenshot_table in ("answer_screenshots", "ask_assignment_batch_screenshots", "ask_assignment_screenshots"): screenshot_column_defs = {column["name"]: column for column in inspect(engine).get_columns(screenshot_table)} @@ -348,6 +466,14 @@ def startup(): if "shop_name" not in columns: with engine.begin() as connection: connection.execute(text("ALTER TABLE ask_tasks ADD COLUMN shop_name VARCHAR(255) NOT NULL DEFAULT ''")) + for column_name, column_type in { + "ecommerce_platform": "VARCHAR(64) NOT NULL DEFAULT ''", + "product_id": "VARCHAR(128) NOT NULL DEFAULT ''", + }.items(): + if column_name not in columns: + with engine.begin() as connection: + connection.execute(text(f"ALTER TABLE ask_tasks ADD COLUMN {column_name} {column_type}")) + columns.add(column_name) if "owner_id" not in columns: with engine.begin() as connection: connection.execute(text("ALTER TABLE ask_tasks ADD COLUMN owner_id INTEGER NULL")) @@ -391,6 +517,7 @@ def startup(): "is_dept_manager": "BOOLEAN NOT NULL DEFAULT 0", "answer_public_token": "VARCHAR(96) NULL", "last_answer_shop_name": "VARCHAR(255) NULL", + "last_answer_ecommerce_platform": "VARCHAR(64) NULL", } for column_name, column_type in admin_user_migrations.items(): if column_name not in admin_user_columns: @@ -403,6 +530,22 @@ def startup(): if "shop_name" not in answer_submission_columns: with engine.begin() as connection: connection.execute(text("ALTER TABLE answer_submissions ADD COLUMN shop_name VARCHAR(255) NOT NULL DEFAULT ''")) + for column_name, column_type in { + "ecommerce_platform": "VARCHAR(64) NOT NULL DEFAULT ''", + "product_id": "VARCHAR(128) NOT NULL DEFAULT ''", + }.items(): + if column_name not in answer_submission_columns: + with engine.begin() as connection: + connection.execute(text(f"ALTER TABLE answer_submissions ADD COLUMN {column_name} {column_type}")) + refund_record_columns = {column["name"] for column in inspect(engine).get_columns("refund_records")} + for column_name, column_type in { + "ecommerce_platform": "VARCHAR(64) NOT NULL DEFAULT ''", + "product_id": "VARCHAR(128) NOT NULL DEFAULT ''", + "payer_account_id": "INTEGER NULL", + }.items(): + if column_name not in refund_record_columns: + with engine.begin() as connection: + connection.execute(text(f"ALTER TABLE refund_records ADD COLUMN {column_name} {column_type}")) answer_user_columns = {column["name"] for column in inspect(engine).get_columns("answer_users")} if "taobao_id" not in answer_user_columns: with engine.begin() as connection: @@ -493,7 +636,10 @@ def _migrate_alipay_transfer_attempts(bind): "out_biz_no": "VARCHAR(64) NULL", "order_no": "VARCHAR(64) NOT NULL DEFAULT ''", "shop_name": "VARCHAR(255) NOT NULL DEFAULT ''", + "ecommerce_platform": "VARCHAR(64) NOT NULL DEFAULT ''", + "product_id": "VARCHAR(128) NOT NULL DEFAULT ''", "owner_id": "BIGINT NULL", + "payer_account_id": "BIGINT NULL", "payer_account": "VARCHAR(128) NOT NULL DEFAULT ''", "operator_name": "VARCHAR(64) NOT NULL DEFAULT ''", "created_by_id": "BIGINT NOT NULL DEFAULT 0", @@ -571,6 +717,11 @@ def require_user_manager(user: AdminUser = Depends(current_user)) -> AdminUser: return user +@app.post("/api/admin/product-metadata/resolve") +def resolve_product_metadata(payload: dict, _: AdminUser = Depends(current_user)): + return {"success": True, "data": _resolve_product_metadata(payload.get("source"))} + + @app.get("/api/health") def health(): return {"success": True, "message": "ok"} @@ -1450,6 +1601,8 @@ def _submission_data( "phone": _public_user_account(record.user), **(_refund_recipient_data(record, "answer_submission") if include_images else {"alipay_account": "", "payee_name": ""}), "shop_name": record.shop_name or "", + "ecommerce_platform": record.ecommerce_platform or "", + "product_id": record.product_id or "", "status": record.status, "recognition_failed": record.status == "识别失败" or _has_legacy_fake_ocr_questions(record), "created_at": record.created_at.isoformat(), @@ -1487,6 +1640,8 @@ def _task_board_data(record: AnswerSubmission, include_images: bool = True, imag "taobao_id": record.user.taobao_id, "phone": _public_user_account(record.user), "shop_name": record.shop_name or "", + "ecommerce_platform": record.ecommerce_platform or "", + "product_id": record.product_id or "", "status": record.status, "created_at": record.created_at.isoformat(), "updated_at": record.updated_at.isoformat(), @@ -1505,6 +1660,7 @@ def _task_board_data(record: AnswerSubmission, include_images: bool = True, imag "已通过": "待返款", "已完成": "已完成", "未通过": "进行中", + "已超时": "已超时", "已撤销": "已撤销", } # "待审核" and "待返款" mean the user has submitted evidence, not that @@ -1519,7 +1675,9 @@ def _task_board_data(record: AnswerSubmission, include_images: bool = True, imag "creator_name": record.owner.display_name if record.owner else "运营后台", "qa_count": len(selected), "claimed_count": 1, "submitted_count": 1 if record.status in {"待审核", "已通过", "已完成"} else 0, "pending_review_count": 1 if record.status == "待审核" else 0, "completed_count": completed_count, "total_count": len(selected), - "can_cancel": record.status in {"待用户完成", "待审核", "未通过"}, + "can_cancel": record.status in {"待用户完成", "待审核", "未通过", "已超时"}, + "can_reactivate": record.status == "已超时", + "reactivate_endpoint": f"/api/admin/task-board/{record.id}/reactivate" if record.status == "已超时" else None, "can_delete": True, "delete_endpoint": f"/api/admin/task-board/{record.id}", "refund_endpoint": f"/api/admin/task-board/{record.id}/confirm-refund" if record.status == "已通过" else None, @@ -1582,6 +1740,8 @@ def _ask_assignment_child_data(assignment: AskAssignment) -> dict: "task_type_label": "提问任务", "product_name": task.product_name, "shop_name": task.shop_name, + "ecommerce_platform": task.ecommerce_platform, + "product_id": task.product_id, "product_link": task.product_link, "status": assignment.status, "status_label": status_label, @@ -1673,6 +1833,8 @@ def _ask_batch_child_data(batch: AskAssignmentBatch) -> dict: "task_type_label": "提问任务", "product_name": task.product_name, "shop_name": task.shop_name, + "ecommerce_platform": task.ecommerce_platform, + "product_id": task.product_id, "product_link": task.product_link, "status": batch.status, "status_label": status_label, @@ -1779,6 +1941,8 @@ def _ask_task_data(task: AskTask, include_questions: bool = True) -> dict: "task_id": task.task_no, "task_type": "ask", "task_type_label": "提问任务", "public_token": task.public_token or task.task_no, "shop_name": task.shop_name, + "ecommerce_platform": task.ecommerce_platform, + "product_id": task.product_id, "product_name": task.product_name, "product_link": task.product_link, # Keep the persisted task state alongside the display label. The # create-task page uses this value to switch to the publish-success @@ -1966,6 +2130,7 @@ def admin_answer_link(user: AdminUser = Depends(current_user), db: Session = Dep "token": stored_user.answer_public_token, "path": f"/answer/{stored_user.answer_public_token}", "last_shop_name": stored_user.last_answer_shop_name or "", + "last_ecommerce_platform": stored_user.last_answer_ecommerce_platform or "", }} @@ -2439,6 +2604,8 @@ def ask_assignment_review_decision(assignment_id: int, payload: dict, user: Admi def answer_my_submissions(token: str, owner_token: str, include_images: bool = False, db: Session = Depends(get_db)): user = _answer_user_from_token(token, db) owner = _answer_link_owner(owner_token, db) + if _expire_answer_tasks(db): + db.commit() statement = select(AnswerSubmission).where( AnswerSubmission.user_id == user.id, AnswerSubmission.owner_id == owner.id, @@ -2451,6 +2618,8 @@ def answer_my_submissions(token: str, owner_token: str, include_images: bool = F def answer_submission_detail(submission_id: int, token: str, owner_token: str, db: Session = Depends(get_db)): user = _answer_user_from_token(token, db) owner = _answer_link_owner(owner_token, db) + if _expire_answer_tasks(db, submission_id): + db.commit() record = db.get(AnswerSubmission, submission_id) if not record or record.user_id != user.id or record.owner_id != owner.id: raise HTTPException(status_code=404, detail="任务不存在") @@ -2573,6 +2742,8 @@ async def answer_create_submission( @app.get("/api/admin/answer-task-drafts") def admin_answer_task_drafts(user: AdminUser = Depends(current_user), db: Session = Depends(get_db)): + if _expire_answer_tasks(db): + db.commit() records = db.scalars(select(AnswerSubmission).where(AnswerSubmission.status.in_(["待筛选", "识别失败", "待运营派发", "已派发", "待用户完成"])).where(_answer_owner_clause(user)).order_by(AnswerSubmission.created_at.desc())).unique().all() return {"success": True, "data": [_submission_data(record, include_images=False) for record in records]} @@ -2674,6 +2845,12 @@ def reject_answer_task_draft(submission_id: int, user: AdminUser = Depends(curre @app.post("/api/admin/ask-tasks/generate") def generate_ask_task(payload: dict, user: AdminUser = Depends(current_user), db: Session = Depends(get_db)): shop_name = str(payload.get("shop_name", "")).strip() + ecommerce_platform = str(payload.get("ecommerce_platform", "")).strip() + if len(ecommerce_platform) > 64: + raise HTTPException(status_code=400, detail="电商平台不能超过64个字符") + product_id = str(payload.get("product_id", "")).strip() + if len(product_id) > 128: + raise HTTPException(status_code=400, detail="商品ID不能超过128个字符") product_link = str(payload.get("product_link", "")).strip() product_qr_data, product_qr_content_type, product_qr_name = _decode_product_qr_image( payload.get("product_qr_image"), payload.get("product_qr_image_name") @@ -2735,7 +2912,16 @@ def generate_ask_task(payload: dict, user: AdminUser = Depends(current_user), db if task.status != "草稿": raise HTTPException(status_code=409, detail="已发布任务不能重新生成") _dedupe_draft_ask_questions(task, db) + # Regeneration is a full replacement. The resulting draft must contain + # exactly the requested number of questions, regardless of how the old + # draft questions were added. + for existing_question in list(task.questions): + db.delete(existing_question) + db.flush() + db.expire(task, ["questions"]) task.shop_name = shop_name + task.ecommerce_platform = ecommerce_platform + task.product_id = product_id task.product_link = product_link task.product_qr_image_data = product_qr_data task.product_qr_image_content_type = product_qr_content_type @@ -2750,7 +2936,7 @@ def generate_ask_task(payload: dict, user: AdminUser = Depends(current_user), db task.purchase_channel = str(payload.get("purchase_channel", "")) task.claim_questions_per_user = claim_limit else: - task = AskTask(task_no=f"TASK{datetime.utcnow().strftime('%Y%m%d%H%M%S')}{uuid.uuid4().hex[:4].upper()}", owner_id=user.id, shop_name=shop_name, product_link=product_link, product_qr_image_data=product_qr_data, product_qr_image_content_type=product_qr_content_type, product_qr_image_name=product_qr_name, product_name=product_name or "待补充商品", category=str(payload.get("category", "")), benefits=str(payload.get("benefits", "")), selling_points=str(payload.get("selling_points", "")), language_style=str(payload.get("language_style", "")), target_group=str(payload.get("target_group", "")), usage_scene=str(payload.get("usage_scene", "")), purchase_channel=str(payload.get("purchase_channel", "")), claim_questions_per_user=claim_limit, status="草稿") + task = AskTask(task_no=f"TASK{datetime.utcnow().strftime('%Y%m%d%H%M%S')}{uuid.uuid4().hex[:4].upper()}", owner_id=user.id, shop_name=shop_name, ecommerce_platform=ecommerce_platform, product_id=product_id, product_link=product_link, product_qr_image_data=product_qr_data, product_qr_image_content_type=product_qr_content_type, product_qr_image_name=product_qr_name, product_name=product_name or "待补充商品", category=str(payload.get("category", "")), benefits=str(payload.get("benefits", "")), selling_points=str(payload.get("selling_points", "")), language_style=str(payload.get("language_style", "")), target_group=str(payload.get("target_group", "")), usage_scene=str(payload.get("usage_scene", "")), purchase_channel=str(payload.get("purchase_channel", "")), claim_questions_per_user=claim_limit, status="草稿") db.add(task); db.flush() next_sequence = max((question.sequence_no for question in task.questions), default=0) + 1 for index, question in enumerate(generated): @@ -2861,12 +3047,22 @@ def delete_ask_question(task_id: int, question_id: int, user: AdminUser = Depend return {"success": True, "data": {"id": question_id}} -def _ask_publish_fields(payload: dict) -> tuple[str, str, bytes | None, str | None, str | None, int]: +def _ask_publish_fields(payload: dict) -> tuple[str, str, str, str, bytes | None, str | None, str | None, int]: shop_name = str(payload.get("shop_name", "")).strip() if not shop_name: raise HTTPException(status_code=400, detail="请填写店铺名称") if len(shop_name) > 255: raise HTTPException(status_code=400, detail="店铺名称不能超过255个字符") + ecommerce_platform = str(payload.get("ecommerce_platform", "")).strip() + if not ecommerce_platform: + raise HTTPException(status_code=400, detail="请填写电商平台") + if len(ecommerce_platform) > 64: + raise HTTPException(status_code=400, detail="电商平台不能超过64个字符") + product_id = str(payload.get("product_id", "")).strip() + if not product_id: + raise HTTPException(status_code=400, detail="请填写商品ID") + if len(product_id) > 128: + raise HTTPException(status_code=400, detail="商品ID不能超过128个字符") product_link = str(payload.get("product_link", "")).strip() qr_data, qr_content_type, qr_name = _decode_product_qr_image( payload.get("product_qr_image"), payload.get("product_qr_image_name") @@ -2883,12 +3079,14 @@ def _ask_publish_fields(payload: dict) -> tuple[str, str, bytes | None, str | No raise HTTPException(status_code=400, detail="每个用户可领取的问题数量必须是 2-20 的整数") if claim_limit < 2 or claim_limit > 20: raise HTTPException(status_code=400, detail="每个用户可领取的问题数量必须在 2-20 条之间") - return shop_name, product_link, qr_data, qr_content_type, qr_name, claim_limit + return shop_name, ecommerce_platform, product_id, product_link, qr_data, qr_content_type, qr_name, claim_limit def _apply_ask_publish_fields(task: AskTask, payload: dict) -> None: - shop_name, product_link, qr_data, qr_content_type, qr_name, claim_limit = _ask_publish_fields(payload) + shop_name, ecommerce_platform, product_id, product_link, qr_data, qr_content_type, qr_name, claim_limit = _ask_publish_fields(payload) task.shop_name = shop_name + task.ecommerce_platform = ecommerce_platform + task.product_id = product_id task.product_link = product_link task.product_qr_image_data = qr_data task.product_qr_image_content_type = qr_content_type @@ -2935,6 +3133,8 @@ def create_and_publish_ask_task(payload: dict, user: AdminUser = Depends(current task_no=f"TASK{datetime.utcnow().strftime('%Y%m%d%H%M%S')}{uuid.uuid4().hex[:4].upper()}", owner_id=user.id, shop_name="", + ecommerce_platform="", + product_id="", product_link="", product_name=str(payload.get("product_name", "")).strip() or "待补充商品", category=str(payload.get("category", "")), @@ -3004,6 +3204,10 @@ def publish_ask_task(task_id: int, payload: dict = Body(default={}), user: Admin raise HTTPException(status_code=400, detail=f"无法发布任务:{product_token_error}") if not task.shop_name: raise HTTPException(status_code=400, detail="请填写店铺名称") + if not task.ecommerce_platform: + raise HTTPException(status_code=400, detail="请填写电商平台") + if not task.product_id: + raise HTTPException(status_code=400, detail="请填写商品ID") if not any(q.selected for q in task.questions): raise HTTPException(status_code=400, detail="请至少选择一个提问") if not task.public_token: task.public_token = _new_ask_public_token(db) @@ -3076,13 +3280,28 @@ def publish_answer_task(submission_id: int, payload: dict = Body(default={}), us raise HTTPException(status_code=400, detail="派发前必须填写店铺名称") if len(shop_name) > 255: raise HTTPException(status_code=400, detail="店铺名称不能超过255个字符") + ecommerce_platform = str(payload.get("ecommerce_platform", "")).strip() + if not ecommerce_platform: + raise HTTPException(status_code=400, detail="派发前必须填写电商平台") + if len(ecommerce_platform) > 64: + raise HTTPException(status_code=400, detail="电商平台不能超过64个字符") + product_id = str(payload.get("product_id", "")).strip() + if not product_id: + raise HTTPException(status_code=400, detail="派发前必须填写商品ID") + if len(product_id) > 128: + raise HTTPException(status_code=400, detail="商品ID不能超过128个字符") record.shop_name = shop_name + record.ecommerce_platform = ecommerce_platform + record.product_id = product_id if record.owner_id is None: record.owner_id = user.id stored_user = db.get(AdminUser, user.id) if stored_user: stored_user.last_answer_shop_name = shop_name - record.status = "待用户完成"; db.commit() + stored_user.last_answer_ecommerce_platform = ecommerce_platform + record.status = "待用户完成" + record.updated_at = datetime.utcnow() + db.commit() return {"success": True, "data": _submission_data(record, include_images=False)} @@ -3100,9 +3319,11 @@ def admin_task_board( ): if _release_expired_ask_assignments(db): db.commit() + if _expire_answer_tasks(db): + db.commit() page = max(page, 1) page_size = min(max(page_size, 10), 100) - task_statuses = ["待用户完成", "待审核", "已通过", "已完成", "未通过", "已撤销"] + task_statuses = ["待用户完成", "待审核", "已通过", "已完成", "未通过", "已超时", "已撤销"] answer_candidate = ( select( literal("answer").label("record_kind"), @@ -3435,10 +3656,13 @@ def _snapshot_refund(db, record, kind, user, payer_account="", alipay_trade_no=" snapshot = RefundRecord( target_kind=kind, target_id=record.id, owner_id=task.owner_id, shop_name=task.shop_name or "", + ecommerce_platform=getattr(task, "ecommerce_platform", "") or "", + product_id=getattr(task, "product_id", "") or "", order_no=record.submission_no if kind == "answer_submission" else task.task_no, payee_name=identity["payee_name"], payee_account=identity["alipay_account"], amount_fen=identity["refund_amount_fen"], operator_name=user.display_name, - payer_account=payer_account.strip(), alipay_trade_no=alipay_trade_no.strip(), + payer_account_id=getattr(payer_account, "id", None), + payer_account=getattr(payer_account, "name", payer_account).strip(), alipay_trade_no=alipay_trade_no.strip(), ) db.add(snapshot) return snapshot @@ -3469,10 +3693,13 @@ def _complete_alipay_refund_order(db: Session, order: AlipayRefundOrder, trade_n target_id=order.target_id, owner_id=order.owner_id, shop_name=order.shop_name or "", + ecommerce_platform=order.ecommerce_platform or "", + product_id=order.product_id or "", order_no=order.order_no or "", payee_name=order.payee_name or "", payee_account=order.account or "", amount_fen=order.amount_fen, + payer_account_id=order.payer_account_id, operator_name=order.operator_name or "系统自动对账", payer_account=order.payer_account or "", alipay_trade_no=trade_no, @@ -3522,7 +3749,7 @@ def _finalize_refund_confirmation( ) return - _snapshot_refund(db, record, kind, user, payer.name, trade_no) + _snapshot_refund(db, record, kind, user, payer, trade_no) if kind == "ask_batch": record.status = "paid" record.updated_at = datetime.utcnow() @@ -3646,7 +3873,7 @@ def _refund_record_query(user, q, start_date, end_date): def _refund_record_data(record): return {key: getattr(record, key) for key in ( - "id", "shop_name", "order_no", "payee_name", "payee_account", "amount_fen", + "id", "shop_name", "ecommerce_platform", "product_id", "order_no", "payee_name", "payee_account", "amount_fen", "payer_account", "operator_name", "alipay_trade_no", "transferred_at", )} @@ -3667,15 +3894,15 @@ def export_refund_records(q: str = "", start_date: str = "", end_date: str = "", query = _refund_record_query(user, q, start_date, end_date) output = io.StringIO() writer = csv.writer(output) - writer.writerow(["店铺名称", "转账时间", "订单号", "收款人", "收款账号", "返款金额(元)", "付款账户", "操作人", "支付宝流水"]) + writer.writerow(["店铺名称", "电商平台", "商品ID", "转账时间", "订单号", "收款人", "收款账号", "返款金额(元)", "付款账户", "操作人", "支付宝流水"]) total = 0 def safe(value): value = str(value or "") return "'" + value if value.lstrip().startswith(("=", "+", "-", "@")) or value.startswith(("\t", "\r", "\n")) else value for record in db.scalars(query.order_by(RefundRecord.transferred_at.desc(), RefundRecord.id.desc()).execution_options(yield_per=500)): total += record.amount_fen - writer.writerow([safe(record.shop_name), (record.transferred_at + timedelta(hours=8)).strftime("%Y-%m-%d %H:%M:%S"), safe(record.order_no), safe(record.payee_name), safe(record.payee_account), f"{record.amount_fen / 100:.2f}", safe(record.payer_account), safe(record.operator_name), safe(record.alipay_trade_no)]) - writer.writerow(["合计", "", "", "", "", f"{total / 100:.2f}", "", "", ""]) + writer.writerow([safe(record.shop_name), safe(record.ecommerce_platform), safe(record.product_id), (record.transferred_at + timedelta(hours=8)).strftime("%Y-%m-%d %H:%M:%S"), safe(record.order_no), safe(record.payee_name), safe(record.payee_account), f"{record.amount_fen / 100:.2f}", safe(record.payer_account), safe(record.operator_name), safe(record.alipay_trade_no)]) + writer.writerow(["合计", "", "", "", "", "", "", f"{total / 100:.2f}", "", "", ""]) return Response(content="\ufeff" + output.getvalue(), media_type="text/csv; charset=utf-8", headers={"Content-Disposition": 'attachment; filename="refund-records.csv"'}) @@ -3774,6 +4001,9 @@ def _perform_alipay_refund(db: Session, record, kind: str, user: AdminUser, paye order.error_message = "支付宝转账仍在处理中,请稍后重新查询" db.commit() raise HTTPException(status_code=409, detail=order.error_message) + available_fen = _payment_account_usage(db, payer)["available_fen"] + if amount_fen > available_fen: + raise HTTPException(status_code=400, detail="付款账户可用余额不足,请先追加资金") out_biz_no = f"RF{datetime.utcnow():%Y%m%d%H%M%S}{uuid.uuid4().hex[:12].upper()}" if not order: task = record.assignment.task if kind == "ask_batch" else record.task if kind == "ask_assignment" else record @@ -3783,6 +4013,8 @@ def _perform_alipay_refund(db: Session, record, kind: str, user: AdminUser, paye out_biz_no=out_biz_no, order_no=record.submission_no if kind == "answer_submission" else task.task_no, shop_name=task.shop_name or "", + ecommerce_platform=getattr(task, "ecommerce_platform", "") or "", + product_id=getattr(task, "product_id", "") or "", owner_id=task.owner_id, operator_name=user.display_name, ) @@ -3791,6 +4023,7 @@ def _perform_alipay_refund(db: Session, record, kind: str, user: AdminUser, paye order.amount_fen = amount_fen order.account = identity["alipay_account"] order.payee_name = identity["payee_name"] + order.payer_account_id = payer.id order.payer_account = payer.name order.created_by_id = user.id order.operator_name = user.display_name @@ -3909,6 +4142,8 @@ async def confirm_ask_assignment_refund(assignment_id: int, refund_amount: str | @app.get("/api/admin/task-board/{submission_id}") def admin_task_board_detail(submission_id: int, user: AdminUser = Depends(current_user), db: Session = Depends(get_db)): + if _expire_answer_tasks(db, submission_id): + db.commit() record = db.scalar( select(AnswerSubmission) .where(AnswerSubmission.id == submission_id) @@ -3920,7 +4155,7 @@ def admin_task_board_detail(submission_id: int, user: AdminUser = Depends(curren AnswerScreenshot.content_type, )) ) - if not record or record.status not in {"待用户完成", "待审核", "已通过", "已完成", "未通过", "已撤销"} or not _can_access_answer_submission(record, user): + if not record or record.status not in {"待用户完成", "待审核", "已通过", "已完成", "未通过", "已超时", "已撤销"} or not _can_access_answer_submission(record, user): raise HTTPException(status_code=404, detail="任务不存在") return {"success": True, "data": _task_board_data(record, image_endpoints=True)} @@ -3954,6 +4189,8 @@ async def confirm_answer_refund(submission_id: int, refund_amount: str | None = @app.post("/api/admin/task-board/{submission_id}/cancel") def admin_task_board_cancel(submission_id: int, user: AdminUser = Depends(current_user), db: Session = Depends(get_db)): + if _expire_answer_tasks(db, submission_id): + db.commit() record = db.get(AnswerSubmission, submission_id) if not record or not _can_access_answer_submission(record, user): raise HTTPException(status_code=404, detail="任务不存在") @@ -3961,19 +4198,38 @@ def admin_task_board_cancel(submission_id: int, user: AdminUser = Depends(curren raise HTTPException(status_code=409, detail="任务已经撤销") if record.status == "已通过": raise HTTPException(status_code=409, detail="已完成任务不能撤销") - if record.status not in {"待用户完成", "待审核", "未通过"}: + if record.status not in {"待用户完成", "待审核", "未通过", "已超时"}: raise HTTPException(status_code=400, detail="当前状态不能撤销") record.status = "已撤销" db.commit(); db.refresh(record) return {"success": True, "data": _task_board_data(record)} +@app.post("/api/admin/task-board/{submission_id}/reactivate") +def admin_task_board_reactivate(submission_id: int, user: AdminUser = Depends(current_user), db: Session = Depends(get_db)): + if _expire_answer_tasks(db, submission_id): + db.commit() + record = db.get(AnswerSubmission, submission_id) + if not record or not _can_access_answer_submission(record, user): + raise HTTPException(status_code=404, detail="任务不存在") + if record.status != "已超时": + raise HTTPException(status_code=409, detail="只有已超时任务可以重新激活") + record.status = "待用户完成" + record.updated_at = datetime.utcnow() + db.commit(); db.refresh(record) + return {"success": True, "data": _task_board_data(record, include_images=True, image_endpoints=True)} + + @app.post("/api/answer/me/submissions/{submission_id}/completion") async def answer_completion(submission_id: int, token: str = Form(...), owner_token: str = Form(...), files: list[UploadFile] = File(...), payment_files: list[UploadFile] = File(default=[]), alipay_account: str = Form(default=""), payee_name: str = Form(default=""), db: Session = Depends(get_db)): - user = _answer_user_from_token(token, db); owner = _answer_link_owner(owner_token, db); record = db.get(AnswerSubmission, submission_id) + user = _answer_user_from_token(token, db); owner = _answer_link_owner(owner_token, db) + if _expire_answer_tasks(db, submission_id): + db.commit() + record = db.get(AnswerSubmission, submission_id) if not record or record.user_id != user.id or record.owner_id != owner.id: raise HTTPException(status_code=404, detail="任务不存在") record_status = record.status + if record_status == "已超时": raise HTTPException(status_code=409, detail="任务已超时,请联系运营重新激活") if record_status not in ("待用户完成", "未通过"): raise HTTPException(status_code=400, detail="当前任务不能提交完成截图") if not files or len(files) > 10: raise HTTPException(status_code=400, detail="最多上传10张截图") if len(payment_files) > 1: raise HTTPException(status_code=400, detail="最多上传一张收款二维码") @@ -5077,12 +5333,33 @@ def login_logs(_: AdminUser = Depends(require_super_admin), db: Session = Depend return {"success": True, "data": [{"username": x.username, "success": x.success, "ip_address": x.ip_address, "created_at": x.created_at.isoformat()} for x in logs]} -def _payment_account_data(account: RefundPaymentAccount) -> dict: +def _payment_account_usage(db: Session, account: RefundPaymentAccount) -> dict: + used_fen = db.scalar(select(func.coalesce(func.sum(RefundRecord.amount_fen), 0)).where( + or_(RefundRecord.payer_account_id == account.id, + (RefundRecord.payer_account_id.is_(None)) & (RefundRecord.payer_account == account.name)), + )) or 0 + processing_fen = db.scalar(select(func.coalesce(func.sum(AlipayRefundOrder.amount_fen), 0)).where( + or_(AlipayRefundOrder.payer_account_id == account.id, + (AlipayRefundOrder.payer_account_id.is_(None)) & (AlipayRefundOrder.payer_account == account.name)), + AlipayRefundOrder.status == "pending", + )) or 0 + return { + "used_fen": int(used_fen), + "processing_fen": int(processing_fen), + "available_fen": max(int(account.balance_fen) - int(used_fen) - int(processing_fen), 0), + } + + +def _payment_account_data(account: RefundPaymentAccount, db: Session | None = None) -> dict: + usage = _payment_account_usage(db, account) if db is not None else { + "used_fen": 0, "processing_fen": 0, "available_fen": account.balance_fen, + } return { "id": account.id, "name": account.name, "type": "alipay", "alipay_account": account.alipay_account, "balance_fen": account.balance_fen, "single_limit_fen": account.single_limit_fen, "is_active": account.is_active, "updated_at": account.updated_at, + **usage, } @@ -5092,7 +5369,7 @@ def available_refund_payment_accounts(user: AdminUser = Depends(current_user), d if user.role_code not in {"super_admin", "dept_manager"}: statement = statement.where(RefundPaymentAccount.id == user.refund_payment_account_id) accounts = db.scalars(statement.order_by(RefundPaymentAccount.id)).all() - return {"success": True, "data": [_payment_account_data(account) for account in accounts]} + return {"success": True, "data": [_payment_account_data(account, db) for account in accounts]} @app.get("/api/admin/refund-payment-accounts") @@ -5107,39 +5384,143 @@ def refund_payment_accounts(q: str = "", page: int = 1, page_size: int = 10, RefundPaymentAccount.alipay_account.contains(term, autoescape=True))) total = db.scalar(select(func.count()).select_from(statement.subquery())) or 0 records = db.scalars(statement.order_by(RefundPaymentAccount.id.desc()).offset((page - 1) * page_size).limit(page_size)).all() - return {"success": True, "data": {"items": [_payment_account_data(item) for item in records], + items = [_payment_account_data(item, db) for item in records] + all_accounts = db.scalars(select(RefundPaymentAccount)).all() + all_items = [_payment_account_data(item, db) for item in all_accounts] + summary = { + "balance_fen": sum(item["balance_fen"] for item in all_items), + "used_fen": sum(item["used_fen"] for item in all_items), + "processing_fen": sum(item["processing_fen"] for item in all_items), + "available_fen": sum(item["available_fen"] for item in all_items), + } + return {"success": True, "data": {"items": items, "summary": summary, "total": total, "page": page, "page_size": page_size}} -def _save_payment_account(db: Session, account: RefundPaymentAccount, payload: RefundPaymentAccountSave): +def _save_payment_account(db: Session, account: RefundPaymentAccount, payload: RefundPaymentAccountSave, user: AdminUser): + is_new = account.id is None account.name = payload.name account.alipay_account = payload.alipay_account - account.balance_fen = int(payload.balance * 100) + if is_new: + account.balance_fen = int(payload.balance * 100) account.single_limit_fen = int(payload.single_limit * 100) account.is_active = payload.is_active db.add(account) try: + db.flush() + if is_new and account.balance_fen: + db.add(RefundAccountAdjustment( + account_id=account.id, + amount_fen=account.balance_fen, + balance_after_fen=account.balance_fen, + adjustment_type="初始资金", + note="新增账户初始资金", + operator_name=user.display_name, + )) db.commit() except IntegrityError: db.rollback() raise HTTPException(status_code=409, detail="该支付宝账户已存在,请编辑现有账户") db.refresh(account) - return {"success": True, "data": _payment_account_data(account)} + return {"success": True, "data": _payment_account_data(account, db)} @app.post("/api/admin/refund-payment-accounts", status_code=201) def create_refund_payment_account(payload: RefundPaymentAccountSave, - _: AdminUser = Depends(require_super_admin), db: Session = Depends(get_db)): - return _save_payment_account(db, RefundPaymentAccount(), payload) + user: AdminUser = Depends(require_super_admin), db: Session = Depends(get_db)): + return _save_payment_account(db, RefundPaymentAccount(), payload, user) @app.patch("/api/admin/refund-payment-accounts/{account_id}") def update_refund_payment_account(account_id: int, payload: RefundPaymentAccountSave, - _: AdminUser = Depends(require_super_admin), db: Session = Depends(get_db)): - account = db.get(RefundPaymentAccount, account_id) + user: AdminUser = Depends(require_super_admin), db: Session = Depends(get_db)): + account = db.scalar(select(RefundPaymentAccount).where(RefundPaymentAccount.id == account_id).with_for_update()) if account is None: raise HTTPException(status_code=404, detail="付款账户不存在") - return _save_payment_account(db, account, payload) + return _save_payment_account(db, account, payload, user) + + +@app.post("/api/admin/refund-payment-accounts/{account_id}/funds") +def adjust_refund_payment_account_funds( + account_id: int, payload: RefundFundAdjustment, + user: AdminUser = Depends(require_super_admin), db: Session = Depends(get_db), +): + account = db.scalar(select(RefundPaymentAccount).where(RefundPaymentAccount.id == account_id).with_for_update()) + if account is None: + raise HTTPException(status_code=404, detail="付款账户不存在") + amount_fen = int(payload.amount * 100) + if payload.adjustment_type == "追加资金" and amount_fen <= 0: + raise HTTPException(status_code=400, detail="追加资金金额必须大于 0") + if payload.adjustment_type == "资金调整" and not payload.note: + raise HTTPException(status_code=400, detail="资金调整必须填写原因") + usage = _payment_account_usage(db, account) + new_balance_fen = account.balance_fen + amount_fen + committed_fen = usage["used_fen"] + usage["processing_fen"] + if new_balance_fen < committed_fen: + raise HTTPException(status_code=400, detail="调整后的累计入账不能低于已使用与处理中金额之和") + account.balance_fen = new_balance_fen + db.add(RefundAccountAdjustment( + account_id=account.id, + amount_fen=amount_fen, + balance_after_fen=new_balance_fen, + adjustment_type=payload.adjustment_type, + note=payload.note or "追加资金", + operator_name=user.display_name, + )) + db.commit() + db.refresh(account) + return {"success": True, "data": _payment_account_data(account, db)} + + +@app.get("/api/admin/refund-payment-accounts/{account_id}/ledger") +def refund_payment_account_ledger(account_id: int, page: int = 1, page_size: int = 10, + _: AdminUser = Depends(require_super_admin), db: Session = Depends(get_db)): + account = db.get(RefundPaymentAccount, account_id) + if not account: + raise HTTPException(status_code=404, detail="付款账户不存在") + page = max(page, 1) + page_size = min(max(page_size, 1), 50) + adjustments = select( + literal("adjustment").label("type"), RefundAccountAdjustment.id.label("record_id"), + RefundAccountAdjustment.adjustment_type.label("type_label"), RefundAccountAdjustment.amount_fen.label("amount_fen"), + literal("已完成").label("status"), literal("").label("order_no"), + RefundAccountAdjustment.note.label("note"), RefundAccountAdjustment.operator_name.label("operator_name"), + RefundAccountAdjustment.created_at.label("created_at"), + ).where(RefundAccountAdjustment.account_id == account_id) + refunds = select( + literal("refund").label("type"), RefundRecord.id.label("record_id"), + literal("返款支出").label("type_label"), (-RefundRecord.amount_fen).label("amount_fen"), + literal("已完成").label("status"), RefundRecord.order_no.label("order_no"), + func.coalesce(RefundRecord.shop_name, RefundRecord.payee_name, "").label("note"), + RefundRecord.operator_name.label("operator_name"), RefundRecord.transferred_at.label("created_at"), + ).where(or_(RefundRecord.payer_account_id == account.id, + (RefundRecord.payer_account_id.is_(None)) & (RefundRecord.payer_account == account.name))) + pending = select( + literal("processing").label("type"), AlipayRefundOrder.id.label("record_id"), + literal("处理中冻结").label("type_label"), (-AlipayRefundOrder.amount_fen).label("amount_fen"), + literal("处理中").label("status"), AlipayRefundOrder.order_no.label("order_no"), + func.coalesce(AlipayRefundOrder.shop_name, AlipayRefundOrder.payee_name, "").label("note"), + AlipayRefundOrder.operator_name.label("operator_name"), AlipayRefundOrder.created_at.label("created_at"), + ).where( + or_(AlipayRefundOrder.payer_account_id == account.id, + (AlipayRefundOrder.payer_account_id.is_(None)) & (AlipayRefundOrder.payer_account == account.name)), + AlipayRefundOrder.status == "pending", + ) + ledger_rows = union_all(adjustments, refunds, pending).subquery() + total = db.scalar(select(func.count()).select_from(ledger_rows)) or 0 + rows = db.execute( + select(ledger_rows).order_by(ledger_rows.c.created_at.desc(), ledger_rows.c.record_id.desc()) + .offset((page - 1) * page_size).limit(page_size) + ).mappings().all() + items = [{**dict(row), "id": f"{row['type']}-{row['record_id']}"} for row in rows] + return {"success": True, "data": { + "account": _payment_account_data(account, db), + "items": items, + "total": total, + "page": page, + "page_size": page_size, + "total_pages": max(1, (total + page_size - 1) // page_size), + }} @app.delete("/api/admin/refund-payment-accounts/{account_id}") @@ -5150,6 +5531,7 @@ def delete_refund_payment_account(account_id: int, raise HTTPException(status_code=404, detail="付款账户不存在") db.delete(account) db.execute(update(AdminUser).where(AdminUser.refund_payment_account_id == account_id).values(refund_payment_account_id=None)) + db.query(RefundAccountAdjustment).filter(RefundAccountAdjustment.account_id == account_id).delete() db.commit() return {"success": True} diff --git a/backend/app/models.py b/backend/app/models.py index 8adecb0..4a2020f 100644 --- a/backend/app/models.py +++ b/backend/app/models.py @@ -20,6 +20,19 @@ class RefundPaymentAccount(Base): updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) +class RefundAccountAdjustment(Base): + __tablename__ = "refund_account_adjustments" + + id: Mapped[int] = mapped_column(Integer, primary_key=True) + account_id: Mapped[int] = mapped_column(ForeignKey("refund_payment_accounts.id"), index=True) + amount_fen: Mapped[int] = mapped_column(Integer) + balance_after_fen: Mapped[int] = mapped_column(Integer) + adjustment_type: Mapped[str] = mapped_column(String(32), default="资金调整") + note: Mapped[str] = mapped_column(String(255), default="人工调整资金总额") + operator_name: Mapped[str] = mapped_column(String(64), default="") + created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True) + + class RefundRecord(Base): """Immutable confirmation snapshot; deliberately independent of task deletion.""" __tablename__ = "refund_records" @@ -29,10 +42,13 @@ class RefundRecord(Base): target_id: Mapped[int] = mapped_column(Integer) owner_id: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True) shop_name: Mapped[str] = mapped_column(String(255), default="") + ecommerce_platform: Mapped[str] = mapped_column(String(64), default="") + product_id: Mapped[str] = mapped_column(String(128), default="") order_no: Mapped[str] = mapped_column(String(64), index=True) payee_name: Mapped[str] = mapped_column(String(64), default="") payee_account: Mapped[str] = mapped_column(String(128), default="") amount_fen: Mapped[int] = mapped_column(Integer) + payer_account_id: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True) payer_account: Mapped[str] = mapped_column(String(128), default="") operator_name: Mapped[str] = mapped_column(String(64)) alipay_trade_no: Mapped[str] = mapped_column(String(128), default="") @@ -51,9 +67,12 @@ class AlipayRefundOrder(Base): amount_fen: Mapped[int] = mapped_column(Integer) order_no: Mapped[str] = mapped_column(String(64), default="") shop_name: Mapped[str] = mapped_column(String(255), default="") + ecommerce_platform: Mapped[str] = mapped_column(String(64), default="") + product_id: Mapped[str] = mapped_column(String(128), default="") owner_id: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True) account: Mapped[str] = mapped_column(String(128)) payee_name: Mapped[str] = mapped_column(String(64)) + payer_account_id: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True) payer_account: Mapped[str] = mapped_column(String(128), default="") created_by_id: Mapped[int] = mapped_column(Integer, index=True) operator_name: Mapped[str] = mapped_column(String(64), default="") @@ -98,6 +117,7 @@ class AdminUser(Base): # cookie and is safe to embed in a long-lived URL. answer_public_token: Mapped[str | None] = mapped_column(String(96), unique=True, index=True, nullable=True) last_answer_shop_name: Mapped[str | None] = mapped_column(String(255), nullable=True) + last_answer_ecommerce_platform: Mapped[str | None] = mapped_column(String(64), nullable=True) is_active: Mapped[bool] = mapped_column(Boolean, default=True, index=True) last_login_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) @@ -225,6 +245,8 @@ class AnswerSubmission(Base): # handle multiple stores and the same user can submit through different # operator links. shop_name: Mapped[str] = mapped_column(String(255), default="") + ecommerce_platform: Mapped[str] = mapped_column(String(64), default="") + product_id: Mapped[str] = mapped_column(String(128), default="") # 用户上传受邀截图后立即进入运营筛选队列。 status: Mapped[str] = mapped_column(String(32), default="待筛选", index=True) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True) @@ -303,6 +325,8 @@ class AskTask(Base): product_qr_image_content_type: Mapped[str | None] = mapped_column(String(64), nullable=True) product_qr_image_name: Mapped[str | None] = mapped_column(String(255), nullable=True) shop_name: Mapped[str] = mapped_column(String(255), default="") + ecommerce_platform: Mapped[str] = mapped_column(String(64), default="") + product_id: Mapped[str] = mapped_column(String(128), default="") product_name: Mapped[str] = mapped_column(String(255)) category: Mapped[str] = mapped_column(String(100), default="") benefits: Mapped[str] = mapped_column(Text, default="") diff --git a/backend/app/schemas.py b/backend/app/schemas.py index 4ebc056..d7fa282 100644 --- a/backend/app/schemas.py +++ b/backend/app/schemas.py @@ -16,6 +16,24 @@ class RefundPaymentAccountSave(BaseModel): return value.strip() if isinstance(value, str) else value +class RefundFundAdjustment(BaseModel): + adjustment_type: str = Field(pattern=r"^(追加资金|资金调整)$") + amount: Decimal = Field(ge=-9999999.99, le=9999999.99, decimal_places=2, allow_inf_nan=False) + note: str = Field(default="", max_length=255) + + @field_validator("note", mode="before") + @classmethod + def strip_note(cls, value): + return value.strip() if isinstance(value, str) else value + + @field_validator("amount") + @classmethod + def reject_zero_amount(cls, value): + if value == 0: + raise ValueError("调整金额不能为 0") + return value + + class LoginRequest(BaseModel): username: str = Field(min_length=1, max_length=64) password: str = Field(min_length=1, max_length=128) diff --git a/backend/tests/__pycache__/test_auth.cpython-313-pytest-9.1.1.pyc b/backend/tests/__pycache__/test_auth.cpython-313-pytest-9.1.1.pyc index 390e3f74fa4a108546f2cdffca2484b69283088f..0c58ecd394e56d16fc73c07922ca6ff4a352b76a 100644 GIT binary patch delta 29777 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 delta 18100 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 diff --git a/backend/tests/__pycache__/test_payment_account_authorization.cpython-313-pytest-9.1.1.pyc b/backend/tests/__pycache__/test_payment_account_authorization.cpython-313-pytest-9.1.1.pyc index 0379eb4c22cb7ccfb937447d5b228faf16253880..735b36e564141fcc2638f94f5fe016cb26530a71 100644 GIT binary patch delta 8679 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 diff --git a/backend/tests/__pycache__/test_refund_records.cpython-313-pytest-9.1.1.pyc b/backend/tests/__pycache__/test_refund_records.cpython-313-pytest-9.1.1.pyc index bfd95577b2c535d6c60c234710ebb494e77ad6cb..b03e45656ccd8fdff3a6e08792eaf0dae0a2d32a 100644 GIT binary patch delta 2883 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 I*N2Nf0tvfqNdN!< diff --git a/backend/tests/test_auth.py b/backend/tests/test_auth.py index 7701db6..9635d5a 100644 --- a/backend/tests/test_auth.py +++ b/backend/tests/test_auth.py @@ -439,6 +439,77 @@ def test_task_board_is_available_to_operator(): assert count_data["total"] == count_data["ask"] + count_data["answer"] +def test_answer_task_expires_after_24_hours_and_can_be_reactivated(): + unique = uuid4().hex[:10] + submission_id = None + with TestClient(app) as client: + assert client.post( + "/api/admin/auth/login", + json={"username": "operator", "password": "operator123456"}, + ).status_code == 200 + with main_module.SessionLocal() as db: + owner = db.scalar( + main_module.select(main_module.AdminUser).where(main_module.AdminUser.username == "operator") + ) + public_user = main_module.AnswerUser( + public_id=f"U{unique[:7]}", + phone=f"137{uuid4().int % 100_000_000:08d}", + auth_token=uuid4().hex, + ) + db.add(public_user) + db.flush() + expired_at = datetime.utcnow() - timedelta(hours=24, seconds=1) + submission = main_module.AnswerSubmission( + submission_no=f"ANS{unique.upper()}", + user_id=public_user.id, + owner_id=owner.id, + status="待用户完成", + shop_name="超时测试店铺", + ecommerce_platform="淘宝", + product_id="TIMEOUT-1", + created_at=expired_at, + updated_at=expired_at, + ) + db.add(submission) + db.flush() + db.add(main_module.AnswerRecognizedQuestion( + submission_id=submission.id, + sequence_no=1, + product_title="超时测试商品", + question_text="这个任务会超时吗", + answer_text="会", + selected=True, + )) + db.commit() + submission_id = submission.id + + drafts = client.get("/api/admin/answer-task-drafts") + assert drafts.status_code == 200 + assert submission_id not in {item["id"] for item in drafts.json()["data"]} + + board_item = next(item for item in task_board_items(client) if item.get("id") == submission_id) + assert board_item["status"] == "已超时" + assert board_item["status_label"] == "已超时" + assert board_item["can_reactivate"] is True + assert board_item["can_cancel"] is True + + detail = client.get(f"/api/admin/task-board/{submission_id}") + assert detail.status_code == 200 + assert detail.json()["data"]["status"] == "已超时" + + reactivated = client.post(f"/api/admin/task-board/{submission_id}/reactivate") + assert reactivated.status_code == 200 + assert reactivated.json()["data"]["status"] == "待用户完成" + assert reactivated.json()["data"]["status_label"] == "进行中" + assert reactivated.json()["data"]["can_reactivate"] is False + + cancelled = client.post(f"/api/admin/task-board/{submission_id}/cancel") + assert cancelled.status_code == 200 + assert cancelled.json()["data"]["status"] == "已撤销" + + assert client.delete(f"/api/admin/task-board/{submission_id}").status_code == 200 + + def test_taobao_id_login_is_shared_by_both_user_portals(): taobao_id = f"tb{uuid4().hex[:14]}" with TestClient(app) as client: @@ -555,14 +626,31 @@ def test_answer_task_publish_remembers_operator_shop_name(): db.commit() submission_id = submission.id + missing_platform = client.post( + f"/api/admin/answer-task-drafts/{submission_id}/publish", + json={"shop_name": remembered_shop, "product_id": "ANSWER-MEMORY-1"}, + ) + assert missing_platform.status_code == 400 + assert missing_platform.json()["detail"] == "派发前必须填写电商平台" + + missing_product_id = client.post( + f"/api/admin/answer-task-drafts/{submission_id}/publish", + json={"shop_name": remembered_shop, "ecommerce_platform": "淘宝"}, + ) + assert missing_product_id.status_code == 400 + assert missing_product_id.json()["detail"] == "派发前必须填写商品ID" + published = client.post( f"/api/admin/answer-task-drafts/{submission_id}/publish", - json={"shop_name": remembered_shop}, + json={"shop_name": remembered_shop, "ecommerce_platform": "淘宝", "product_id": "ANSWER-MEMORY-1"}, ) assert published.status_code == 200 + assert published.json()["data"]["ecommerce_platform"] == "淘宝" + assert published.json()["data"]["product_id"] == "ANSWER-MEMORY-1" link_settings = client.get("/api/admin/auth/answer-link") assert link_settings.status_code == 200 assert link_settings.json()["data"]["last_shop_name"] == remembered_shop + assert link_settings.json()["data"]["last_ecommerce_platform"] == "淘宝" with main_module.SessionLocal() as db: owner = db.scalar( main_module.select(main_module.AdminUser).where(main_module.AdminUser.username == "operator") @@ -836,7 +924,7 @@ def test_answer_rejection_reason_syncs_to_public_user(monkeypatch): assert client.patch(f"/api/admin/answer-task-drafts/questions/{question_id}", json={"selected": True}).status_code == 200 assert client.post( f"/api/admin/answer-task-drafts/{submission['id']}/publish", - json={"shop_name": "测试店铺"}, + json={"shop_name": "测试店铺", "ecommerce_platform": "淘宝", "product_id": "ANSWER-COMPLETE-1"}, ).status_code == 200 completed = client.post( f"/api/answer/me/submissions/{submission['id']}/completion", @@ -869,7 +957,7 @@ def test_ask_task_publish_appears_on_task_board(monkeypatch): ) assert generation_without_publish_fields.status_code == 200 assert generation_without_publish_fields.json()["data"]["status"] == "草稿" - generated = client.post("/api/admin/ask-tasks/generate", json={"shop_name": "测试店铺", "product_link": "https://item.example.com/1", "product_name": "测试商品", "question_count": 3}) + generated = client.post("/api/admin/ask-tasks/generate", json={"shop_name": "测试店铺", "ecommerce_platform": "淘宝", "product_id": "911640908772", "product_link": "https://item.example.com/1", "product_name": "测试商品", "question_count": 3}) assert generated.status_code == 200 task = generated.json()["data"] assert task["public_token"] is None @@ -887,9 +975,23 @@ def test_ask_task_publish_appears_on_task_board(monkeypatch): assert created["qa_count"] == 3 assert created["public_token"] == public_token assert created["shop_name"] == "测试店铺" + assert created["ecommerce_platform"] == "淘宝" + assert created["product_id"] == "911640908772" detail = client.get(created["detail_endpoint"]) assert detail.status_code == 200 assert detail.json()["data"]["shop_name"] == "测试店铺" + assert detail.json()["data"]["ecommerce_platform"] == "淘宝" + assert detail.json()["data"]["product_id"] == "911640908772" + + +def test_taobao_product_metadata_extracts_platform_and_item_id(): + source = "【淘宝】https://e.tb.cn/h.example?tk=ABC 「测试商品」" + html = "var url='https://pages-fast.m.taobao.com/detail?itemIds=911640908772&shopName=%E6%B5%8B%E8%AF%95%E5%BA%97%E9%93%BA';" + result = main_module._extract_product_metadata(source, "https://e.tb.cn/h.example", html) + assert result["ecommerce_platform"] == "淘宝" + assert result["product_id"] == "911640908772" + assert result["shop_name"] == "测试店铺" + assert result["product_name"] == "测试商品" def test_imported_questions_can_publish_without_ai_generation(): @@ -899,6 +1001,8 @@ def test_imported_questions_can_publish_without_ai_generation(): "/api/admin/ask-tasks/publish", json={ "shop_name": "直接发布测试店铺", + "ecommerce_platform": "淘宝", + "product_id": "911640908772", "product_link": "TOKEN-DIRECT-PUBLISH", "product_name": "直接发布测试商品", "claim_questions_per_user": 20, @@ -912,6 +1016,8 @@ def test_imported_questions_can_publish_without_ai_generation(): data = published.json()["data"] assert data["status"] == "已发布" assert data["shop_name"] == "直接发布测试店铺" + assert data["ecommerce_platform"] == "淘宝" + assert data["product_id"] == "911640908772" assert data["claim_questions_per_user"] == 20 assert [item["question"] for item in data["selected_questions"]] == ["批量导入问题一?", "自主添加问题二?"] assert [item["source"] for item in data["selected_questions"]] == ["批量导入", "自主添加"] @@ -922,10 +1028,38 @@ def test_imported_questions_can_publish_without_ai_generation(): ) assert missing_fields.status_code == 400 + missing_platform = client.post( + "/api/admin/ask-tasks/publish", + json={ + "shop_name": "必填校验店铺", + "product_id": "REQUIRED-1", + "product_link": "TOKEN-REQUIRED-PLATFORM", + "claim_questions_per_user": 5, + "questions": [{"question": "缺少电商平台?", "source": "自主添加"}], + }, + ) + assert missing_platform.status_code == 400 + assert missing_platform.json()["detail"] == "请填写电商平台" + + missing_product_id = client.post( + "/api/admin/ask-tasks/publish", + json={ + "shop_name": "必填校验店铺", + "ecommerce_platform": "淘宝", + "product_link": "TOKEN-REQUIRED-PRODUCT-ID", + "claim_questions_per_user": 5, + "questions": [{"question": "缺少商品ID?", "source": "自主添加"}], + }, + ) + assert missing_product_id.status_code == 400 + assert missing_product_id.json()["detail"] == "请填写商品ID" + over_limit = client.post( "/api/admin/ask-tasks/publish", json={ "shop_name": "领取上限测试店铺", + "ecommerce_platform": "淘宝", + "product_id": "CLAIM-LIMIT-1", "product_link": "TOKEN-CLAIM-LIMIT", "claim_questions_per_user": 21, "questions": [{"question": "超过领取上限?", "source": "自主添加"}], @@ -988,19 +1122,31 @@ def test_ask_task_accepts_qr_image_without_token_and_excludes_it_from_ai(monkeyp assert public_token -def test_ask_task_regeneration_appends_to_existing_questions(monkeypatch): +def test_ask_task_regeneration_replaces_all_questions_with_requested_count(monkeypatch): monkeypatch.setattr(main_module, "generate_questions", fake_ask_questions) with TestClient(app) as client: assert client.post("/api/admin/auth/login", json={"username": "operator", "password": "operator123456"}).status_code == 200 - first = client.post("/api/admin/ask-tasks/generate", json={"shop_name": "追加测试店铺", "product_link": "https://item.example.com/append", "product_name": "追加测试商品", "question_count": 2}) + first = client.post("/api/admin/ask-tasks/generate", json={"shop_name": "覆盖测试店铺", "product_link": "https://item.example.com/replace", "product_name": "覆盖测试商品", "question_count": 2}) assert first.status_code == 200 task = first.json()["data"] assert len(task["selected_questions"]) == 2 - second = client.post("/api/admin/ask-tasks/generate", json={"task_id": task["id"], "shop_name": "追加测试店铺", "product_link": "https://item.example.com/append", "product_name": "追加测试商品", "question_count": 2}) + added = client.post( + f"/api/admin/ask-tasks/{task['id']}/questions", + json={"question": "运营手动保留的问题", "source": "自主添加"}, + ) + assert added.status_code == 200 + second = client.post("/api/admin/ask-tasks/generate", json={"task_id": task["id"], "shop_name": "覆盖测试店铺", "product_link": "https://item.example.com/replace", "product_name": "覆盖测试商品", "question_count": 5}) assert second.status_code == 200 questions = second.json()["data"]["selected_questions"] - assert len(questions) == 4 - assert [item["sequence_no"] for item in questions] == [1, 2, 3, 4] + assert len(questions) == 5 + assert all(item["source"] == "AI生成" for item in questions) + assert all(item["question"] != "运营手动保留的问题" for item in questions) + + ai_question = next(item for item in questions if item["source"] == "AI生成") + deleted = client.delete(f"/api/admin/ask-tasks/{task['id']}/questions/{ai_question['id']}") + assert deleted.status_code == 200 + with main_module.SessionLocal() as db: + assert db.get(main_module.AskQuestion, ai_question["id"]) is None def test_public_ask_assignment_expires_after_selection_timeout(monkeypatch): @@ -1308,7 +1454,7 @@ def test_approved_answer_appears_as_pending_refund_with_detail(monkeypatch): assert client.patch(f"/api/admin/answer-task-drafts/questions/{question_id}", json={"selected": True}).status_code == 200 assert client.post( f"/api/admin/answer-task-drafts/{created['id']}/publish", - json={"shop_name": "测试店铺"}, + json={"shop_name": "测试店铺", "ecommerce_platform": "淘宝", "product_id": "ANSWER-REFUND-1"}, ).status_code == 200 completed = client.post( f"/api/answer/me/submissions/{created['id']}/completion", diff --git a/backend/tests/test_refund_payment_accounts.py b/backend/tests/test_refund_payment_accounts.py index bd43a65..0668c47 100644 --- a/backend/tests/test_refund_payment_accounts.py +++ b/backend/tests/test_refund_payment_accounts.py @@ -6,7 +6,7 @@ from sqlalchemy.pool import StaticPool from app import main from app.database import Base, get_db -from app.models import AdminUser, RefundPaymentAccount +from app.models import AdminUser, AlipayRefundOrder, RefundPaymentAccount, RefundRecord ENDPOINT = "/api/admin/refund-payment-accounts" @@ -43,12 +43,94 @@ def test_create_edit_and_persist_cents(setup): assert response.status_code == 200, response.text db.expire_all() saved = db.get(RefundPaymentAccount, record["id"]) - assert saved.balance_fen == 0 + assert saved.balance_fen == 500001 assert not saved.is_active assert saved.updated_at is not None assert client.get(ENDPOINT).json()["data"]["items"][0]["is_active"] is False +def test_append_and_adjust_funds_with_ledger(setup): + db, client, _ = setup + account = client.post(ENDPOINT, json=PAYLOAD).json()["data"] + response = client.post(f"{ENDPOINT}/{account['id']}/funds", json={ + "adjustment_type": "追加资金", "amount": "1000.00", "note": "追加预算", + }) + assert response.status_code == 200, response.text + assert response.json()["data"]["balance_fen"] == 600001 + response = client.post(f"{ENDPOINT}/{account['id']}/funds", json={ + "adjustment_type": "资金调整", "amount": "-10.01", "note": "修正录入", + }) + assert response.status_code == 200, response.text + assert response.json()["data"]["balance_fen"] == 599000 + db.expire_all() + assert db.get(RefundPaymentAccount, account["id"]).balance_fen == 599000 + labels = {item["type_label"] for item in client.get(f"{ENDPOINT}/{account['id']}/ledger").json()["data"]["items"]} + assert {"初始资金", "追加资金", "资金调整"}.issubset(labels) + + +def test_fund_adjustment_validation_and_committed_floor(setup): + db, client, admin = setup + account = client.post(ENDPOINT, json=PAYLOAD).json()["data"] + assert client.post(f"{ENDPOINT}/{account['id']}/funds", json={ + "adjustment_type": "追加资金", "amount": "-1.00", "note": "", + }).status_code == 400 + assert client.post(f"{ENDPOINT}/{account['id']}/funds", json={ + "adjustment_type": "资金调整", "amount": "1.00", "note": "", + }).status_code == 400 + assert client.post(f"{ENDPOINT}/{account['id']}/funds", json={ + "adjustment_type": "资金调整", "amount": "0.00", "note": "无效调整", + }).status_code == 422 + db.add(RefundRecord( + target_kind="answer_submission", target_id=991001, owner_id=admin.id, order_no="ANS-FLOOR-1", + payee_name="测试用户", payee_account="floor@example.com", amount_fen=400000, + payer_account_id=account["id"], payer_account=account["name"], operator_name=admin.display_name, + alipay_trade_no="TRADE-FLOOR-1", + )) + db.commit() + response = client.post(f"{ENDPOINT}/{account['id']}/funds", json={ + "adjustment_type": "资金调整", "amount": "-1000.02", "note": "过度调减", + }) + assert response.status_code == 400 + assert "不能低于" in response.json()["detail"] + + +def test_account_usage_summary_and_ledger(setup): + db, client, admin = setup + account = client.post(ENDPOINT, json=PAYLOAD).json()["data"] + db.add(RefundRecord( + target_kind="answer_submission", target_id=900001, owner_id=admin.id, + shop_name="测试店铺", order_no="ANS-USAGE-1", payee_name="测试用户", + payee_account="user@example.com", amount_fen=12345, + payer_account_id=account["id"], payer_account=account["name"], + operator_name=admin.display_name, alipay_trade_no="TRADE-USAGE-1", + )) + db.add(AlipayRefundOrder( + target_kind="answer_submission", target_id=900002, out_biz_no="RF-USAGE-PENDING", + amount_fen=5000, order_no="ANS-USAGE-2", account="user2@example.com", + payee_name="测试用户2", payer_account_id=account["id"], payer_account=account["name"], + created_by_id=admin.id, operator_name=admin.display_name, status="pending", + )) + db.commit() + + item = client.get(ENDPOINT).json()["data"]["items"][0] + assert item["used_fen"] == 12345 + assert item["processing_fen"] == 5000 + assert item["available_fen"] == 482656 + ledger = client.get(f"{ENDPOINT}/{account['id']}/ledger") + assert ledger.status_code == 200 + ledger_data = ledger.json()["data"] + assert ledger_data["total"] == 3 + assert ledger_data["page"] == 1 + assert ledger_data["page_size"] == 10 + types = {row["type"] for row in ledger_data["items"]} + assert {"adjustment", "refund", "processing"}.issubset(types) + first_page = client.get(f"{ENDPOINT}/{account['id']}/ledger", params={"page": 1, "page_size": 2}).json()["data"] + second_page = client.get(f"{ENDPOINT}/{account['id']}/ledger", params={"page": 2, "page_size": 2}).json()["data"] + assert first_page["total_pages"] == 2 + assert len(first_page["items"]) == 2 + assert len(second_page["items"]) == 1 + + def test_duplicate_and_failed_edit_preserve_accounts(setup): db, client, _ = setup first = client.post(ENDPOINT, json=PAYLOAD).json()["data"] @@ -88,11 +170,13 @@ def test_reject_invalid_account(setup, changes): def test_permissions_and_missing_account(setup): db, client, admin = setup assert client.patch(f"{ENDPOINT}/999", json=PAYLOAD).status_code == 404 + assert client.post(f"{ENDPOINT}/999/funds", json={"adjustment_type": "追加资金", "amount": "1.00", "note": ""}).status_code == 404 admin.role_code = "operator" db.commit() assert client.get(ENDPOINT).status_code == 403 assert client.post(ENDPOINT, json=PAYLOAD).status_code == 403 assert client.patch(f"{ENDPOINT}/999", json=PAYLOAD).status_code == 403 + assert client.post(f"{ENDPOINT}/999/funds", json={"adjustment_type": "追加资金", "amount": "1.00", "note": ""}).status_code == 403 assert client.delete(f"{ENDPOINT}/999").status_code == 403 diff --git a/backend/tests/test_refund_records.py b/backend/tests/test_refund_records.py index d3acc40..dd8b5d3 100644 --- a/backend/tests/test_refund_records.py +++ b/backend/tests/test_refund_records.py @@ -120,8 +120,8 @@ def test_scope_date_range_pagination_and_export(setup): assert len(page["items"]) == 2 and page["total"] == 12 and page["total_amount_fen"] == 600 exported = client.get(f"/api/admin/refund-records/export?{query}") rows = list(csv.reader(io.StringIO(exported.content.decode("utf-8-sig")))) - assert len(rows) == 14 and rows[-1][5] == "6.00" - assert rows[1][0] == "'=unsafe" and rows[1][1] == "2026-10-22 00:00:00" + assert len(rows) == 14 and rows[-1][7] == "6.00" + assert rows[1][0] == "'=unsafe" and rows[1][3] == "2026-10-22 00:00:00" owner.role_code = "dept_manager" db.commit() assert client.get(f"/api/admin/refund-records?{query}").json()["data"]["total"] == 13 diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4d9509b..0697681 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,13 +9,13 @@ "version": "0.1.0", "dependencies": { "@vitejs/plugin-react": "latest", + "jsqr": "^1.4.0", "lucide-react": "latest", "react": "latest", "react-dom": "latest", "typescript": "latest", "vite": "latest" - }, - "devDependencies": {} + } }, "node_modules/@oxc-project/types": { "version": "0.146.0", @@ -679,6 +679,12 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/jsqr": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz", + "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==", + "license": "Apache-2.0" + }, "node_modules/lightningcss": { "version": "1.33.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index cc60149..c1b402f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -3,7 +3,18 @@ "private": true, "version": "0.1.0", "type": "module", - "scripts": {"dev": "vite", "build": "vite build", "preview": "vite preview"}, - "dependencies": {"@vitejs/plugin-react": "latest", "vite": "latest", "typescript": "latest", "react": "latest", "react-dom": "latest", "lucide-react": "latest"}, - "devDependencies": {} + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@vitejs/plugin-react": "latest", + "jsqr": "^1.4.0", + "lucide-react": "latest", + "react": "latest", + "react-dom": "latest", + "typescript": "latest", + "vite": "latest" + } } diff --git a/frontend/src/CreateAnswerTasksPage.jsx b/frontend/src/CreateAnswerTasksPage.jsx index 356ecf5..7d528cf 100644 --- a/frontend/src/CreateAnswerTasksPage.jsx +++ b/frontend/src/CreateAnswerTasksPage.jsx @@ -7,13 +7,15 @@ export default function CreateAnswerTasksPageV2({ api, user }) { const [detailBusy, setDetailBusy] = useState('') const [error, setError] = useState('') const [rejecting, setRejecting] = useState(null) - const [shopNames, setShopNames] = useState({}) + const [publishing, setPublishing] = useState(null) + const [publishForm, setPublishForm] = useState({ ecommerce_platform: '', shop_name: '', product_id: '' }) const [answerLink, setAnswerLink] = useState('') const [linkCopied, setLinkCopied] = useState(false) const editingAnswersRef = useRef(new Set()) - const editedShopNamesRef = useRef(new Set()) const shopMemoryKey = `answer_last_shop_name_${user?.id || 'current'}` + const platformMemoryKey = `answer_last_ecommerce_platform_${user?.id || 'current'}` const lastShopNameRef = useRef(window.localStorage.getItem(shopMemoryKey) || '') + const lastPlatformRef = useRef(window.localStorage.getItem(platformMemoryKey) || '') useEffect(() => { let active = true @@ -24,10 +26,11 @@ export default function CreateAnswerTasksPageV2({ api, user }) { if (remembered) { lastShopNameRef.current = remembered window.localStorage.setItem(shopMemoryKey, remembered) - setShopNames(current => Object.fromEntries(Object.entries(current).map(([recordId, value]) => [ - recordId, - !value && !editedShopNamesRef.current.has(Number(recordId)) ? remembered : value, - ]))) + } + const rememberedPlatform = String(result.data?.last_ecommerce_platform || '').trim() + if (rememberedPlatform) { + lastPlatformRef.current = rememberedPlatform + window.localStorage.setItem(platformMemoryKey, rememberedPlatform) } }).catch(() => {}) return () => { active = false } @@ -66,13 +69,6 @@ export default function CreateAnswerTasksPageV2({ api, user }) { })), } })) - setShopNames(current => { - const next = { ...current } - result.data.forEach(record => { - if (next[record.id] === undefined) next[record.id] = record.shop_name || lastShopNameRef.current || '' - }) - return next - }) setExpanded(current => { const next = { ...current } result.data.forEach((record, index) => { @@ -165,31 +161,63 @@ export default function CreateAnswerTasksPageV2({ api, user }) { } } - async function publish(record) { - const shopName = String(shopNames[record.id] ?? record.shop_name ?? '').trim() - if (!shopName) { - setError(`请先为用户 ${record.user_id} 填写店铺名`) - setExpanded(current => ({ ...current, [record.id]: true })) - return - } + function openPublish(record) { if (!record.questions.some(question => question.selected)) { setError(`请先在用户 ${record.user_id} 下选择至少一个问题`) setExpanded(current => ({ ...current, [record.id]: true })) return } + setError('') + setPublishing(record) + setPublishForm({ + ecommerce_platform: record.ecommerce_platform || lastPlatformRef.current || '', + shop_name: record.shop_name || lastShopNameRef.current || '', + product_id: '', + }) + } + + function updatePublishField(field, value) { + setPublishForm(current => ({ ...current, [field]: value })) + const remembered = value.trim() + if (!remembered) return + if (field === 'shop_name') { + lastShopNameRef.current = remembered + window.localStorage.setItem(shopMemoryKey, remembered) + } else if (field === 'ecommerce_platform') { + lastPlatformRef.current = remembered + window.localStorage.setItem(platformMemoryKey, remembered) + } + } + + function closePublish() { + if (busy) return + setPublishing(null) + setPublishForm(current => ({ ...current, product_id: '' })) + setError('') + } + + async function publish() { + const record = publishing + if (!record) return + const ecommercePlatform = publishForm.ecommerce_platform.trim() + const shopName = publishForm.shop_name.trim() + const productId = publishForm.product_id.trim() + if (!ecommercePlatform) return setError('请填写电商平台') + if (!shopName) return setError('请填写店铺名称') + if (!productId) return setError('请填写商品ID') setBusy(record.id) setError('') try { await api(`/api/admin/answer-task-drafts/${record.id}/publish`, { method: 'POST', - body: JSON.stringify({ shop_name: shopName }), + body: JSON.stringify({ ecommerce_platform: ecommercePlatform, shop_name: shopName, product_id: productId }), }) lastShopNameRef.current = shopName + lastPlatformRef.current = ecommercePlatform window.localStorage.setItem(shopMemoryKey, shopName) - setShopNames(current => Object.fromEntries(Object.entries(current).map(([recordId, value]) => [ - recordId, - !value && !editedShopNamesRef.current.has(Number(recordId)) ? shopName : value, - ]))) + window.localStorage.setItem(platformMemoryKey, ecommercePlatform) + setPublishing(null) + setPublishForm({ ecommerce_platform: ecommercePlatform, shop_name: shopName, product_id: '' }) await load() } catch (err) { setError(err.message) @@ -198,16 +226,6 @@ export default function CreateAnswerTasksPageV2({ api, user }) { } } - function updateShopName(recordId, value) { - editedShopNamesRef.current.add(recordId) - setShopNames(current => ({ ...current, [recordId]: value })) - const remembered = value.trim() - if (remembered) { - lastShopNameRef.current = remembered - window.localStorage.setItem(shopMemoryKey, remembered) - } - } - async function reject(record) { if (!record || busy) return setBusy(record.id) @@ -282,11 +300,10 @@ export default function CreateAnswerTasksPageV2({ api, user }) {
淘宝ID:{record.user_id}{record.submission_no}已选 {selected}/{record.questions.length} 题
- {identifying && 正在识别,请等待…} {recognitionFailed && 识别失败,请重新识别} - + {open && record.questions.map(question =>
@@ -309,6 +326,16 @@ export default function CreateAnswerTasksPageV2({ api, user }) { })} + {publishing &&
event.target === event.currentTarget && closePublish()}> +
{ event.preventDefault(); publish() }}> +

生成回答任务

确认后将派发用户 {publishing.user_id} 已勾选的问题

+ + + + {error &&
{error}
} +
+
+
} {rejecting &&
event.target === event.currentTarget && setRejecting(null)}>

确认打回

diff --git a/frontend/src/CreateAskTasksPage.jsx b/frontend/src/CreateAskTasksPage.jsx index 878b95f..4f4de89 100644 --- a/frontend/src/CreateAskTasksPage.jsx +++ b/frontend/src/CreateAskTasksPage.jsx @@ -1,10 +1,13 @@ import React, { useEffect, useRef, useState } from "react"; import { Check, Copy, FileUp, Link2, Plus, Sparkles, X } from "lucide-react"; +import jsQR from "jsqr"; import { analyzeProductIntent, validateGenerationOptions } from "./productIntent.js"; import { clearPageCache, readPageCache, writePageCache } from "./pageCache.js"; const blankForm = { shop_name: "", + ecommerce_platform: "", + product_id: "", product_link: "", product_qr_image: "", product_qr_image_name: "", @@ -40,6 +43,17 @@ function isAddedQuestion(item) { return ADDED_QUESTION_SOURCES.has(item?.source) || String(item?.id || "").startsWith("new-"); } +function withoutTransientProductFields(value = {}) { + const { product_qr: _discardedProductQr, ...rest } = value; + return { + ...rest, + product_id: "", + product_link: "", + product_qr_image: "", + product_qr_image_name: "", + }; +} + async function readReferenceFile(file, requestApi) { if (!file) return ""; if (/\.xlsx$/i.test(file.name)) { @@ -54,7 +68,10 @@ function isAddedQuestion(item) { export default function CreateAskTasksPage({ api, librarySelection = [], onLibrarySelectionConsumed }) { const cached = readPageCache("create-ask-task", {}); const [form, setForm] = useState(() => { - const restored = { ...blankForm, ...(cached.form || {}) }; + // Product identifiers and QR/token data are one-time publish inputs. Never + // restore them from an older page cache; only shop and platform may carry + // over to the next task. + const restored = withoutTransientProductFields({ ...blankForm, ...(cached.form || {}) }); if (!String(restored.claim_questions_per_user ?? "").trim()) { restored.claim_questions_per_user = "5"; } @@ -70,6 +87,7 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra ); const [editing, setEditing] = useState(null); const [busy, setBusy] = useState(false); + const [resolvingProduct, setResolvingProduct] = useState(false); const [error, setError] = useState(""); const [referenceFile, setReferenceFile] = useState(null); const referenceInputRef = useRef(null); @@ -83,7 +101,13 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra const processingLibrarySelection = useRef(false); const consumedLibrarySelectionKey = useRef(""); useEffect(() => { - writePageCache("create-ask-task", { form, task, questions, referenceQa, referenceFileName }); + writePageCache("create-ask-task", { + form: withoutTransientProductFields(form), + task: task ? withoutTransientProductFields(task) : task, + questions, + referenceQa, + referenceFileName, + }); }, [form, task, questions, referenceQa, referenceFileName]); useEffect(() => { if (!librarySelection.length) { @@ -105,6 +129,50 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra }, [librarySelection, onLibrarySelectionConsumed]); const update = (key, value) => setForm((current) => ({ ...current, [key]: value })); + async function resolveProduct(sourceValue) { + const source = String(sourceValue ?? form.product_link).trim(); + if (!source) return; + setResolvingProduct(true); + setError(""); + try { + const result = await api("/api/admin/product-metadata/resolve", { + method: "POST", + body: JSON.stringify({ source }), + }); + const metadata = result.data || {}; + setForm((current) => ({ + ...current, + product_link: source, + ecommerce_platform: metadata.ecommerce_platform || current.ecommerce_platform, + product_id: metadata.product_id || current.product_id, + shop_name: metadata.shop_name || current.shop_name, + product_name: current.product_name || metadata.product_name || "", + })); + if (!metadata.ecommerce_platform && !metadata.product_id && !metadata.shop_name) { + setError("暂未识别出商品信息,请检查淘口令/二维码或手工填写"); + } + } catch (err) { + setError(err.message || "商品信息识别失败"); + } finally { + setResolvingProduct(false); + } + } + async function decodeProductQr(file) { + try { + const bitmap = await createImageBitmap(file); + const canvas = document.createElement("canvas"); + canvas.width = bitmap.width; + canvas.height = bitmap.height; + const context = canvas.getContext("2d", { willReadFrequently: true }); + context.drawImage(bitmap, 0, 0); + const image = context.getImageData(0, 0, canvas.width, canvas.height); + bitmap.close?.(); + const rawValue = String(jsQR(image.data, image.width, image.height)?.data || "").trim(); + if (rawValue) await resolveProduct(rawValue); + } catch { + // Keep the uploaded QR for the task even when this browser cannot decode it. + } + } async function selectReferenceFile(file) { setReferenceFile(file); setReferenceFileName(file?.name || ""); @@ -147,6 +215,7 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra product_qr_image: String(reader.result || ""), product_qr_image_name: file.name, })); + void decodeProductQr(file); }; reader.onerror = () => setError("商品二维码图片读取失败,请重试"); reader.readAsDataURL(file); @@ -161,6 +230,18 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra if (productQrInputRef.current) productQrInputRef.current.value = ""; } + function clearTransientProductInputs() { + setForm((current) => withoutTransientProductFields(current)); + if (productQrInputRef.current) productQrInputRef.current.value = ""; + } + + function closePublishDialog() { + if (busy) return; + clearTransientProductInputs(); + setPublishOpen(false); + setError(""); + } + useEffect(() => { if (!publishOpen) return undefined; const pasteProductQr = (event) => { @@ -315,7 +396,7 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra async function removeQuestion(index) { const question = questions[index]; - if (!question || !isAddedQuestion(question)) return; + if (!question) return; setBusy(true); setError(""); try { @@ -323,9 +404,9 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra await api(`/api/admin/ask-tasks/${task.id}/questions/${question.id}`, { method: "DELETE" }); } setQuestions((current) => current.filter((_, itemIndex) => itemIndex !== index)); - if (editing === index) setEditing(null); + setEditing((current) => current === index ? null : current > index ? current - 1 : current); } catch (err) { - setError(err.message || "移除提问失败"); + setError(err.message || "删除提问失败"); } finally { setBusy(false); } @@ -445,6 +526,8 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra const selectedQuestions = checkedQuestions.length ? checkedQuestions : questions.filter((item) => item.question.trim()); if (!selectedQuestions.length) return setError("请至少添加一个提问"); if (!form.shop_name.trim()) return setError("请填写店铺名称"); + if (!form.ecommerce_platform.trim()) return setError("请填写电商平台"); + if (!form.product_id.trim()) return setError("请填写商品ID"); if (!form.product_link.trim() && !form.product_qr_image) return setError("请填写商品淘口令或上传商品二维码"); const claimLimit = Number(form.claim_questions_per_user); if (!Number.isInteger(claimLimit) || claimLimit < 2 || claimLimit > 20) return setError("每个用户可领取的问题数量必须填写 2-20 的整数"); @@ -469,6 +552,7 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra // Keep the state explicit so the success/link view renders on the first // click instead of waiting for a second request to return 409. setTask({ ...result.data, status: result.data.status || "已发布" }); + clearTransientProductInputs(); setPublishOpen(false); } catch (err) { setError(err.message); @@ -788,6 +872,9 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra ) : ( {question.question} )} + - {isAddedQuestion(question) && ( - - )} 来源:{question.source || "AI生成"} · 可编辑后发布
@@ -825,20 +907,27 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra {addDialog === "manual" && setAddDialog(null)} onAdd={addManualQuestion} />} {addDialog === "import" && setAddDialog(null)} onImport={addImportedQuestions} />} {publishOpen && ( -
event.target === event.currentTarget && !busy && setPublishOpen(false)}> +
event.target === event.currentTarget && closePublishDialog()}>
{ event.preventDefault(); publish(); }}>

发布提问任务

本次将发布 {questions.some((item) => item.selected) ? questions.filter((item) => item.selected).length : questions.length} 条问题

- +
+
+ + +
selectProductQr(event.target.files?.[0] || null)} /> {form.product_qr_image ? ( @@ -866,7 +955,7 @@ export default function CreateAskTasksPage({ api, librarySelection = [], onLibra 每名用户在该链接中最多可领取 2-20 条问题,默认 5 条 {error &&
{error}
} -
+
)} diff --git a/frontend/src/RefundManagementPage.jsx b/frontend/src/RefundManagementPage.jsx index f8fc537..6c7fc07 100644 --- a/frontend/src/RefundManagementPage.jsx +++ b/frontend/src/RefundManagementPage.jsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from "react"; -import { Plus, Search, X, Pencil, Trash2 } from "lucide-react"; +import { Plus, Search, X, Pencil, Trash2, History } from "lucide-react"; import { formatDateTime } from "./time.js"; const endpoint = "/api/admin/refund-payment-accounts"; @@ -7,7 +7,7 @@ const money = (fen) => (fen / 100).toFixed(2); const emptyForm = () => ({ name: "", alipay_account: "", balance: "0.00", single_limit: "500.00", is_active: true }); export default function RefundManagementPage({ api }) { - const [data, setData] = useState({ items: [], total: 0 }); + const [data, setData] = useState({ items: [], total: 0, summary: {} }); const [query, setQuery] = useState(""); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(10); @@ -20,6 +20,15 @@ export default function RefundManagementPage({ api }) { const [saveError, setSaveError] = useState(""); const [deleting, setDeleting] = useState(null); const [deleteError, setDeleteError] = useState(""); + const [ledger, setLedger] = useState(null); + const [ledgerLoading, setLedgerLoading] = useState(false); + const [ledgerPage, setLedgerPage] = useState(1); + const [ledgerPageSize, setLedgerPageSize] = useState(10); + const [funding, setFunding] = useState(null); + const [fundAmount, setFundAmount] = useState(""); + const [fundNote, setFundNote] = useState(""); + const [fundSaving, setFundSaving] = useState(false); + const [fundError, setFundError] = useState(""); useEffect(() => { let cancelled = false; @@ -52,7 +61,8 @@ export default function RefundManagementPage({ api }) { setSaveError(""); try { if (!form.name.trim() || !form.alipay_account.trim()) throw new Error("请填写账户名称和支付宝账户"); - for (const [key, label] of [["balance", "可用余额"], ["single_limit", "单次付款限额"]]) { + const moneyFields = editing.id ? [["single_limit", "单次付款限额"]] : [["balance", "初始资金"], ["single_limit", "单次付款限额"]]; + for (const [key, label] of moneyFields) { if (!/^\d+(\.\d{1,2})?$/.test(form[key]) || Number(form[key]) > 9999999.99 || (key === "single_limit" && Number(form[key]) <= 0)) { throw new Error(`${label}需填写有效金额,最多两位小数,最高 9999999.99 元${key === "single_limit" ? ",且必须大于 0" : ""}`); @@ -82,11 +92,70 @@ export default function RefundManagementPage({ api }) { } finally { setDeleting(null); } } + async function loadLedger(account, targetPage = 1, targetPageSize = ledgerPageSize) { + setLedger({ account, items: [] }); + setLedgerLoading(true); + try { + const result = await api(endpoint + "/" + account.id + "/ledger?" + new URLSearchParams({ page: targetPage, page_size: targetPageSize })); + setLedger(result.data); + setLedgerPage(result.data.page); + setLedgerPageSize(result.data.page_size); + } catch (err) { + setLedger({ account, items: [], error: err.message }); + } finally { + setLedgerLoading(false); + } + } + + async function openLedger(account) { + setLedgerPage(1); + await loadLedger(account, 1, ledgerPageSize); + } + + function openFunding(account, type) { + setFunding({ account, type }); + setFundAmount(""); + setFundNote(""); + setFundError(""); + } + + async function saveFunds(event) { + event.preventDefault(); + if (fundSaving) return; + setFundSaving(true); + setFundError(""); + try { + const amountPattern = funding.type === "追加资金" ? /^\d+(\.\d{1,2})?$/ : /^-?\d+(\.\d{1,2})?$/; + const amount = Number(fundAmount); + if (!amountPattern.test(fundAmount) || !Number.isFinite(amount) || amount === 0 || Math.abs(amount) > 9999999.99 || + (funding.type === "追加资金" && amount <= 0)) { + throw new Error(funding.type === "追加资金" ? "追加金额必须大于 0,最多两位小数" : "请输入非 0 的调整金额,减少资金请填写负数"); + } + if (funding.type === "资金调整" && !fundNote.trim()) throw new Error("资金调整必须填写原因"); + await api(`${endpoint}/${funding.account.id}/funds`, { + method: "POST", + body: JSON.stringify({ adjustment_type: funding.type, amount: fundAmount, note: fundNote.trim() }), + }); + setFunding(null); + setReload((n) => n + 1); + } catch (err) { + setFundError(err.message || "资金操作失败,请重试"); + } finally { + setFundSaving(false); + } + } + const pages = Math.max(1, Math.ceil(data.total / pageSize)); return <>

返款管理

管理返款使用的支付宝付款账户。

-
代付接口暂未接入,此处仅维护付款账户资料,不会发起转账。可用余额为人工录入值,后续接入接口后再同步。
+
+
累计入账¥{money(data.summary?.balance_fen || 0)}初始资金与后续追加合计
+
累计已使用¥{money(data.summary?.used_fen || 0)}已确认成功的返款
+
处理中¥{money(data.summary?.processing_fen || 0)}结果未明确,暂时冻结
+
可用余额¥{money(data.summary?.available_fen || 0)}累计入账减已使用和冻结
+
+
页面显示的是系统账面资金,不代表支付宝实际余额。返款成功后自动计入已使用,处理中订单会冻结对应金额。
@@ -95,14 +164,15 @@ export default function RefundManagementPage({ api }) { {deleteError &&
{deleteError}
}
- + - {loading ? : error ? null : data.items.length ? data.items.map((account) => + {loading ? : error ? null : data.items.length ? data.items.map((account) => - + + - - ) : } + + ) : }
类型账户名称支付宝账户可用余额单次付款限额状态更新时间操作类型账户名称支付宝账户累计入账已使用处理中可用余额单次限额状态操作
加载中…
加载中…
支付宝{account.name}{account.alipay_account}¥{money(account.balance_fen)}¥{money(account.single_limit_fen)}¥{money(account.balance_fen)}¥{money(account.used_fen)}¥{money(account.processing_fen)}¥{money(account.available_fen)}¥{money(account.single_limit_fen)} {account.is_active ? "启用" : "禁用"}{formatDateTime(account.updated_at)}
{query ? "未找到匹配账户" : "暂无付款账户,请点击新增付款账户"}
{query ? "未找到匹配账户" : "暂无付款账户,请点击新增付款账户"}
@@ -118,14 +188,42 @@ export default function RefundManagementPage({ api }) {
- + {editing.id ? : }
-

余额由人工维护;保存资料不会产生实际付款。

+

{editing.id ? "账户资金请使用“追加资金”或“资金调整”,每次变化都会记录流水。" : "初始资金保存后不能在编辑账户中直接修改,后续通过追加资金或资金调整维护。"}

{saveError &&
{saveError}
}
} + {ledger &&
+

{ledger.account?.name || "付款账户"}资金流水

资金调整、成功返款和处理中冻结记录

+ {ledgerLoading ?
加载中…
: ledger.error ?
{ledger.error}
: <> +
累计入账¥{money(ledger.account.balance_fen)}已使用¥{money(ledger.account.used_fen)}处理中¥{money(ledger.account.processing_fen)}可用余额¥{money(ledger.account.available_fen)}
+
{ledger.items.length ? ledger.items.map((item) =>
+
{item.type_label}{item.order_no || item.note || "--"}
+
= 0 ? "income" : "expense"}>{item.amount_fen >= 0 ? "+" : "-"}¥{money(Math.abs(item.amount_fen))}{formatDateTime(item.created_at)} · {item.operator_name || "系统"}
+
) :
暂无资金流水
}
+
+ 共 {ledger.total || 0} 条 + + {ledgerPage} / {ledger.total_pages || 1} + + +
+ } +
} + {funding &&
+

{funding.type}

{funding.account.name}

+
当前累计入账¥{money(funding.account.balance_fen)}当前可用余额¥{money(funding.account.available_fen)}
+
+ + +

{funding.type === "追加资金" ? "仅允许增加资金,提交后会立即计入累计入账并生成流水。" : "允许增加或减少,但调整后的累计入账不能低于已使用与处理中金额之和。"}

+ {fundError &&
{fundError}
} +
+
+
} ; } diff --git a/frontend/src/RefundRecordsPage.jsx b/frontend/src/RefundRecordsPage.jsx index 2419161..9d77bad 100644 --- a/frontend/src/RefundRecordsPage.jsx +++ b/frontend/src/RefundRecordsPage.jsx @@ -75,11 +75,11 @@ export default function RefundRecordsPage({ api }) { {error &&

{error}

}
- {["店铺名称", "转账时间", "订单号", "收款人", "收款账号", "返款金额", "付款账户", "操作人", "支付宝流水"].map((title) => )} - {loading || error ? : data.items.length ? data.items.map((item) => - - ) : } - {!loading && !error && } + {["店铺名称", "电商平台", "商品ID", "转账时间", "订单号", "收款人", "收款账号", "返款金额", "付款账户", "操作人", "支付宝流水"].map((title) => )} + {loading || error ? : data.items.length ? data.items.map((item) => + + ) : } + {!loading && !error && }
{title}
{loading ? "加载中…" : "记录加载失败,请调整筛选或重新进入页面"}
{item.shop_name || "—"}{formatDateTime(item.transferred_at)}{item.order_no}{item.payee_name || "—"}{item.payee_account || "—"}{money(item.amount_fen)}{item.payer_account || "—"}{item.operator_name || "—"}{item.alipay_trade_no || "—"}
暂无返款记录
合计(当前筛选全部记录){money(data.total_amount_fen)}
{title}
{loading ? "加载中…" : "记录加载失败,请调整筛选或重新进入页面"}
{item.shop_name || "—"}{item.ecommerce_platform || "—"}{item.product_id || "—"}{formatDateTime(item.transferred_at)}{item.order_no}{item.payee_name || "—"}{item.payee_account || "—"}{money(item.amount_fen)}{item.payer_account || "—"}{item.operator_name || "—"}{item.alipay_trade_no || "—"}
暂无返款记录
合计(当前筛选全部记录){money(data.total_amount_fen)}
diff --git a/frontend/src/TaskBoardPage.jsx b/frontend/src/TaskBoardPage.jsx index 1694577..0834888 100644 --- a/frontend/src/TaskBoardPage.jsx +++ b/frontend/src/TaskBoardPage.jsx @@ -11,6 +11,7 @@ const STATUS_FILTERS = [ ]; const STATUS_ALIASES = { "待用户完成": "进行中", + "已超时": "已超时", "未通过": "进行中", "已发布": "进行中", }; @@ -47,7 +48,7 @@ function TaskDetailLoading() { ); } -export function TaskDetail({ task, close, onConfirmRefund, onSaveRefundAmount, api, hasNextRefund, onNextRefund, nextBusy, readOnly = false }) { +export function TaskDetail({ task, close, onConfirmRefund, onSaveRefundAmount, onReactivate, onCancel, actionBusy, api, hasNextRefund, onNextRefund, nextBusy, readOnly = false }) { const [amount, setAmount] = useState(""); const [payerAccount, setPayerAccount] = useState(""); const [paymentAccounts, setPaymentAccounts] = useState([]); @@ -79,6 +80,9 @@ export function TaskDetail({ task, close, onConfirmRefund, onSaveRefundAmount, a const [linkCopied, setLinkCopied] = useState(false); const isAskTask = task.task_type === "ask" || task.task_type_label === "提问任务"; + const isAnswerTask = + task.task_type === "answer" || task.task_type_label === "回答任务"; + const hasProductMetadata = isAskTask || isAnswerTask; const askTaskToken = task.public_token || task.task_id; const taskLink = isAskTask && askTaskToken ? `${window.location.origin}/ask/${encodeURIComponent(askTaskToken)}` @@ -180,10 +184,16 @@ export function TaskDetail({ task, close, onConfirmRefund, onSaveRefundAmount, a
)} -
+
{task.shop_name && 店铺名称{task.shop_name || "--"} } + {hasProductMetadata && + 电商平台{task.ecommerce_platform || "历史任务未填写"} + } + {hasProductMetadata && + 商品ID{task.product_id || "历史任务未填写"} + } 商品名称{task.product_name} @@ -305,6 +315,16 @@ export function TaskDetail({ task, close, onConfirmRefund, onSaveRefundAmount, a
}