From 93db2fe7f52e04027fa7b517df9bb13213e16be1 Mon Sep 17 00:00:00 2001 From: aminhashemi92 Date: Tue, 9 Sep 2025 13:15:42 +0330 Subject: [PATCH] fix installation step and utm standarded. --- db.sqlite3 | Bin 2859008 -> 2940928 bytes installations/models.py | 4 +- .../installation_assign_step.html | 33 +++- .../installation_report_step.html | 95 ++++++----- installations/views.py | 155 ++++++++++++------ invoices/views.py | 2 +- locations/models.py | 2 +- .../templates/processes/request_list.html | 2 +- wells/forms.py | 2 - wells/models.py | 4 +- 10 files changed, 191 insertions(+), 108 deletions(-) diff --git a/db.sqlite3 b/db.sqlite3 index a04ea6caf5f679b74eb1fceea53bad861e7619c5..2f70da4f778ed3d7877c0fde5d64adb2f7aaebbc 100644 GIT binary patch delta 64195 zcmeFaXc8U|5t*B?zb>OArJFWC&MKL?wz+ zZddVoz3!hNO1m2s6-9Oz5SM_sA+orFg1%E#Gn1ZVg7JReulJt8s-8Yo=X6!qa_Vfo zsOf)%MNR93#w?|W$6ye*7-Ik3S{4+0c-GcEoS&Yl9#D5$2B;6I^AX^{o zlu2qgcQUPfqGEs%mz8yw&KJngy_RA@U0F~$P?)%KYGtvIv+~x;54YekMxYrcBx7an{m~2fUX?ZqeN6+S-G@FI32o){;&UU-S!?nhe=d_F{mfh zU$jnZgaayRzF$IVq9{pbvmFYH>Li1@PMx%_)0)xhkU^r^(5H{tWN;RE-QGZzI|Bb) z?odyEpr_AU?e_Wt;b1$Epf5CY{G7?tcQ4-c^zIw>+_Zb?%5~$0%A$J6pdNbIRfE)( zt~L8DX2~hAa^kvUGi)w+yzvJ0X>~k2!1?OX^F#}OfUX5XTROgKwI%<5ON#$E_LO$)DIv2N+1A-Y@DN6;mVJ+SyU(;KRG`$7@7k4%5Wc!eZltWEo;_<+y} zx-Q()8}8}zRQo+)pEpd_x{FI>{*FjNQ`-7fs|BQ?)#6Dt8}3@vX9V@Qx>x;H{aAfp z-K;*NZctxRk7_w<#0OOKXk-usQIjC>LXs_Qwwk^#=uK}bs%>SqLR*e4L*1#Kre>%P=-V7yKRfYk zOP{&UwWdr*5L1F!8+K3{DUey4#X55MT4W*3*B12A23Jd3C+S7&Tf|r+J(X!wZDyNf zJ!w5+Jz(8${mi<{y2JV&K-bquPax|r_Hodd{%vp*zqwaBB5NPy9TN0QA?NhM|cmox?=vtVXp#iG7L*M%?DWfxJ#>W9IYmM}R zY8;Ivs63MFc~#0TW!Gcqia|$%MSW9HKU04Pf?udV!-)D;J*@6hH)%Od(mK^7v#LP$ zqpeb28m%ggK@z7an9Ti&ahvoeX@0HPT(HM{jrmIR73PWNi_908&olQ2gon-Fs-LRg zn)ksF9Y?a7inGWM+oTW4q1TGDw2j-P{zf)jqh`TG-;-G|@=WF#dwI}b{FlTtk!J$U zdI$!V8UEziA3QtBvlBe~ooB!C>^RSk@$6TY6&ZfvKY!-gPc$3b?H5!e-rg`>`&dQkRSsBGB0c^7o`Fbp&>akViEy)$C0%PVlLlX>LE5FKqx-y; zsC_DZxxcDE5J#=kNlNO`{fhlY`x5&i`+WNx`%L>(Z9_e}+eVstV?_Q@CFN@?u0>ag zQq;1V7#E?ViseJgX3GZ4i*wGOim&^9!pxt89vw8!i7GaB@Q(V!QM z2EAZ3=mn!eFBlDaagBDvJ!k;}8vTfIHQKFM7g%Rmr&z~ZM_JFa_S2eIqfwlOFBsr7 z=mn!eFBlDa!D!G6MuT238ua2CZOP+kerH95*CoKrg_ria`YC-)+f`9~jr7@wvTUBP z$K9JwmZ*Ix40v>u9BUR8=)*<24kwR(FV<^aKSSRM(*JQec>hb|?_X&akF}z#J(??x z6`_#H087U2>d(Z{WQ0NDz%MHH?)Fl<%bsQLY**|it=WOIY>a6j*3HF1t#2-V9R`WL zniyU9sA3;xA7t-mud(;E`|Z_0rYu&tM{bGt`iWIon^+~U7Nu#bU%%^NijJqPP`Y~tywU1lBIu0nz2s46OriUvYqlG zCi3~Q0<4W*AU`aTy`PKuH0h$0dA3N17d`%&6LwFZB_V`_Jv^ z>GoEK!@)qnXLvpZ+}+dTt&T)IZkW1;6z~q$4@QHA=UO8O^$hrW2K?0?wr%k| zJ^i6-Psj~83{SU(`=AZM>Ij?yB4NYYlyJYV+Us+dcmr<3niK^BJ^kKleue!qP?Z`bEaU4r!_S zf>zsToURH+?bZ8@XS?M8NcX~0NR-;5oLc<5`Y-if{1Y4+8`T@t>(qt#dwd2CsaLBr zWru8*Mf??Zt5>KK)r-^%)brH-Y9F;H{v7YZ+wr^j4g3-=SN&?0T8f{=|AQYUXACds z+U0Cqh_i8LY{xSC6CFcGRTmya>gvzhShB!VqZZK!Nixs`xc! z6jbpmo_)!){XF}EXZv`zmuJm1Q^e0{W*0xBnN9qZXP?ka75C80A%4t%?dI7oo_)l# z4_Ou!Kj1&#=h;r4?cmvVo^9jVR-SF)*=C--$Fof|Q^a?9_72ZB^6YJ%y~VRPX=WEU z(99;<-=Miwe4S<%a^G=hwwC>t@!PJQWwo5{t1kg3_`G_DI#V62mP5a#!v?#ItX^D} zZT1HI;w`WN3&b_Iv=}H)Uz-4jYHo zpk0&N6^U-Ka1_L#z=^?e`}Hk0PlOgQ>AmJFi!6-&Ql z>3)`e!P0#!-OJKumVVCC&sh2?OFv=h9+rO0(%mfG#nO*h`XNg{VCnlT-O17&Q(3m1 zrQ2A#m8Dx)x|yZ#v2+tl-(~4LEZxY`w^{lYOW$Pa2A00T($}$M2Bw8wH)+t~;?8om zS{IuyF4FyowKMcaAr~8T&d#R%d{!1syLP2%W~O%aIMYoIDcklEF*YH3f?jB2Yj%_| zsW3kziaMA#Tu{;z(Vc=u}0AE50E~d+|!8T#oSD?4GN^i zWh21JxZTxWuiHaB#n}T$ekiw#wqTR_W+6RM1kgmPBko|>OTo$yFFY#cCxj@SbK{WGPhD4L7F2ua}oihqU{$f!gW4EpOMD zO4Jfs=mi3W`ip7_jGFBV5}&y-L@HNUcAJJOE(+gFY>k#xB&Wt~gA%jth2o~0isAmo zn>s=I#`1-bHZ8vb(pQ&{g7m@VXKQEOXL)8dX*{Pwwnif1a9ElQfca$TVPiUR_bHRD zZrGsx;?HpRa&}j%>1}=0Ask&_YyC4HvU)38?Y-DOTZGfxL-zaaciC6kZ?<1=Z%`jo zA5`yE_raN-3XtAXUsaz|*Md;#2lZR~Y^~H`JHyU)A2UXC>Fh^S$(6t6R%nms+RhM( zJCcc_7|k)TQ!++Z(X|<)*%sAqxY&NSUHw$qqI_Zh-oC^BfO5=UuWnRUC=H6=zDtqp z&)Tn557>vRUntM3MCoh)N|@mz)UC?Dm5Y^5_6_jZ zm#D8PrS^yIXDb7gD*Fj_okRUlJzZ^7rYf2CP4>I(lgV_Kt)E~g51e!i0AWqUMz*0c z>_ZFLK7yvwOhnhRM@DD?{VAjQG_#<2tc};u9}>D+ySBYKwu6Pd^4wVE zIlSO(db*R;Pw4x7Q?nhh?NAGaw~Z3WO&6e27)SN=TD(B~5w2&@Ys0U?P3voH%N26? z-9n?)6ZQt(XbnJrSam$FD|vNhJ{D0}dwGa0+{tnL^o8M1W(UnuNcHO`(dj3usd_WdSBG1K~Q6I&gvZ-)9`!0;_= z%WMTgJ$-@da1j0?_;pe>-R>ku-Yt}kz^4WR_%dzibo)9%k<@(@;kzKhI0%v`n0Y(Y z90B%6vxs3b2#xegqOD&MYyBeoPio%daN}D39**&jXK3C@Mgtpc49zVGG&jf4tOhi; zX8=tDMbk;Rc>NlBhjv($-mwZ();HOa!||$BmehZ%H-iA{MPTGqlCjP1b|_z}cd8Ab zOBkv4R&$ge$p!STRaPHWZv&as47CZwrd`M?xT`1!)%(=z)%Vo1)k4)o-rr{T2;UO4 z9kL&Yf4jYmT)f@x64m3{!tM5@W;WMge4Nnid+fU;g+8!&jEy!){FVIpnfau%`a%a0LDW`X_CHMBE-9Dd?Y; z*D2D&?RHNa=c%4jf0+VPck0ScYo@HPO+$`aq`YKMpM>M2U3p3R^?&~dgZOe~#E``k z75czu!a6DNvjWwW_klc)?{Jb|p8oYuJ)XUtj( zdi=hyzWF*xz#9e>LZ^E8X9NtFq{I*cp=siMQf*=a13)5fz+iZz7XC>}?c(v|`-y4J zNKzqB5Hx2xWn@cr5L5WBoHT95oJr6M_$Mms>!HhGq=Uxu7p9?j6SNdbf0}Di+G;vl zf~09h8j@A2UQyOJ(t3jWy8&u7rTT+WhFQJS*tr3!tVtsEJe*Wp{b{ZyJ}~IJ&_+5P-Rb4dFN7^VV5<8g8P9R{7yB)Uorf7+x*RdEw4j=Fc=$Ew#7{qg^6^hH3}1GCJC3&OcciJ z$Wo&FRS;49Z~t1zW-6Sl!pSO}tRjqGUjyBh4^0--2?lk7`Nvd$nyWT_rx}*LdK_)Y zQquU0DsVbM?KV^}oBQa;U1HvY{1Aj!$s>}fV*-(2$eob?dObc^$O1l)Q29YS17p|| z-1V4i*JHaL-hG{mCRCElQ`fFM_^s%X0y)NXg*^VCH?Y1g9o3#{Qv;?z6PA=%@zSRB z^-Y~oov=p3t}c~=#kSZs-8RP7&*mlWf-XI@$pu{`i)h#gOVkEZ^J_V(10lHIUo~OU zgh}Ja`~7lRx>PQbb_zJ68rF50T@8PnHEH(?hjZ!`8v(CJ}e)rY_p zlzf@-xka8NooO&XN4Aa6nW(vrWK0xE-gcwwj+-ja5~b6$@Q)euWxK5z^q-8`J|^6( zH671zfzB7WN*E3|38c=Khsl>GGRB%{5g}K2TKndUj56UFr{IXWw1EhpJFFRDiNk7o;LHlBAQc)E||;lfINbmv+}kJEhI| zBM>5P!f)bN@$+~ceiA>7AHetEJMap;4F3aPi|68*_zFA;kHe$!a6A~FgZoHt%R}V; za$nF37w;3a1D%{$AjkI=XIo)tb7l{hXnlXmy;@LkG3EN8X*4Y)Pyd-agvdYT_JTe# zOoF#Po~i5=T*eA?V`-^&>+3~i=4N~7oHFf_3TF*M>QF;Jc#6JkxgaM>G6&~iTtHU|j9om-=NX)a3}Gnh=S4@9WX@Xe zb_&3M8iXyVw^1|II)@24#xx_AkICQ3pUKqXAogbkzGs}ihz_t{OwKDJ5FSEZCc_mG z$OqvElh29>M1b&viC#qnLO%HMF3B9}tSl9ALHvEQUJ`K*1>;QqY@OK;hcVO)$PMfl(dC6);A-U<3LNeTZH| zPauL8!`mB$2BKc58o5v!m^=I;eItD=y(hgQt&yL$R$23{ovf1OXUo@?9hUW$yE7~c zEtgpOSt=}w`3LD=mLkhs%Tv~WlJE{^0hzJ7;Cj;isMBmcD1Rk4%OA_{%Uj6e@y=(X zP4eUNNO^#Knp`S(!YA<8cn5wNKY~}{g?KU^fqO%@8qp8vQ?wDSL-(O&Xf_%L^ZZN{ zfcf1OSz%rumiEGQepAw}>I`IH@h+B0Oztj8!}-kz z_{~>nCP^1+H(u%-BC*r5jNz0FH!(A@kg&>1VrE+*W5i(s&19U$V2GJf$cULyNQj+c z5l-hYW-%cnW-uWkW+EYBCx;zjSkPgbN$8*)Wk|C)@LLZ2h69;)1mSEB+s9#hIgBYn zB%H@#dpPW44r4kG#FrR^n65)cOxGbHrrnS*69ORwY7HChTc+2L&^zSoDbB%k^_&cg z(ImD&SP(8{*kRRu{0isj5$Fx6$#91&vqYPUmAnx+r&JzhNrS+j5C=54APq?G$AwOWk-WM^`KZ%&HZ>y_atJbe-bgX-4XHc{0Z3*6!CHX z>ln}2NE9&}i6UmEJ0j-GHfG~e#6R$oM|sAEr-<3`6miBOe)oHx9b}n|wfP@8-#}3j z6o{-J*>n+Qh5xei%*Hb|u|(OzfANh)X46cR`G}Ea4&$r5%!afm=kl95JY#b}l-V>9 z<*w{z39QkKJeygfT*-e`@T{C?W!k<^oX=CKdE!mOb60a<705UYXfHu5a`HqYPU8B?NMP$g>wL@)^QLX`{f6uhj3=Z`3bfUm1e??2Z3HtI^%)c61B60d~m+Xb!4J zQ_w_oG3=Ma&>++g)u5ip5Bp{rDnvOb138cd_Rl}0W6}@OLFp^0Sq{ryxjW2q7mS$B zFfL7?=01Uc!AI}`yuTOz47A%j@O$_z+=O4i&wyV05&SQFFJ6Tk@s0R8*cq?JSK_Jo zQdnWez^44Zv_;w|ACkXOKP8Svt5d6LcCHf1+xwh7qLdAht65sb((Wv+q$y@R6aIr; zpJeF?mj2FCCbPuH*)?OR@UQIp7nc6a(w|uRBTIi^=~0#*Vd-HUrDP7VAK$a|AWOev zDdWNLx9s{GmV$N{%74XD(C)%DXm=rH3>pUQE?jfzH5WdEb{Fn|b{A66?n27AHw@Zc zxc(T7+aLq=E~KE|g%s4gkb-&_QpVe1Q18MusCOaV!BWuf!Zm1jAqDL&q>S;yo7pvJ zci|3bcOeDsE~KE{g%q^Akb-s>(zjR&+FdiO(4gLhTcF;Bl&NrmcC1opMaF zo89g~zL`@nN*naG^EnfG0xUsD-S$FY8cm8||IPlR{otw}okirlhP(n&|BnKh)V-FI zq2(QMJ`ENPuaIp=otYM;QYlt)l?+8C-yC%w(&~P6I*eq)m(FWQ-B-?AwRyigUx5{M zJ@5!m^X>n%ubf4tHo1&02{yjT+W01GlS}x`VwzcnN6BelI&T#5tJ<4?IC}{J`7B|x z^t=I#QRVtWml?vY~6~0v}e5+LWR;lo;V z*-okO#azJ$7?Y`Bwwfz^HCOm*u3)yBD||Iq_-d|Twwf!Lt>y}5tGU8i5d||=MB%K6 z!dVf8vmy#-MHJ48D4Z2hfEA%krowpQ!r!Q6nq?pF)a!lOW9*FrbXdQk0LXsN0Iqr zSH>0scC436*>wp^*%VadB95StX9YZC42}W^ScaVPU>Y)Jo-`Silfq-tp9WIj6vL3QXpp*z{DrF=4QIc!#HyhSuAHRAW!CH4igPyq1_|-V$w&>>?7Pq`rynoZX;y*#NJ?XvJHl3Pq8$3MKZ#w>}-B4VmBFML=&%WT#b z4KXhgm;r)jotAl(u-$*OZB{a(D6~ooyE#ME5wO+V|ywsT0NBgreYX#6K z?3zW{qQ`E_>MYW>kAM}imK?b-C;R%UJF>K@JF-8jK&vFJ<$-I+q^9ii$OQ$?TJ4#p zY_~}MQ{eQHOW(*IBM2IGwu_nFD%|W=;bymr_$6EA#r-_vyoShm4UzL2Vl#(vUW1$6 zD%|W=5kKLuJv?J#4@G2R4@G2R4@LZl!#-qL%nu< zxeP??hPmPi1F^We9u(0_+AsCaG?8>4m-GIr(K*@V?NK>52^X`=-M43jwUt|PrwR0@ zuz{x9oMAZyGP@c+I;X3k!3%SXHj8GV3)kh`DUf?F$(ct636+JS zsfJ7!Dyy~dgd8{*j1+$&{V&fs3yGt|pS8xzb6j-%OVn<&J7^zFm6$v`IcJ@N8DZTc zEs5o)Yj>W^7$vT+&jBIwt;}?o>wuG1E~0A zZSB1|!=>uyrBw#=A@kSfX7g_Ijuvf+`Gomr%f)(~3e~2N#@C#g#9ibpB+a+wbSKL8 z!k${+)j5xdq^6)GOS}ESoG)<_Bk)YNvxF?kc6vy^Y-exsLzZ&{8Cj8;O`IP&FC;IQ zXWm85zq{f#va}-8NgnO$EY$9PB4>*9Uv}OK`rJS#vqtuWiujPD0 zrWZQB+Nd{j9x{mnwP8CW*5_q;nTv#7zczxi0s2)o31Ps4`qBk&OD>5na_w4KEw6Z1rd8 zf5TOz;p*J(KqulsLw>AfE%oQ zlYFFg5WmOA%`LE`nP=u+V1kJyQsep(QM+M&?q`zJ|Awh#`-deNUWU>OCcNO@9B>DM zNmejm#uJAGJsvP2fqyn_Z8Ued1Ko@E7>H|D!5J3x2l^K6!RgqhnHqDwBC*XX=mIL& zBWNG#d0XzkMD#0=z6V}7DwCt^z-+;cF*jl+^0Z(k-LzqLv@v3Kw6S0&Ry2wKq!ZC3 z-a#`XR(QtWE@lS~BVqzz(C9E2V&X(2VoSXdeadgLW!Z?fvQvW*P2hJg;@Jf(12rrq zA+g2MD7{2ZyTUoGuLWD^Z4g_q44vTF&pcyCU<>-1|6)6c1+jg>g4kkjL7TM5s@#p` zRp?>Er9wA@befbeN#fVyCh;k8r8rj{EB2P&mL8W@NV7oeJRF5kw)7{NQVU~!p{r{d z%&%M}NBB#OPBt{<4yPNdjXb~A z42QP2batX|>aI8FuHVpIzn-`j@oS|1om|+VUtzh7U)I5z**$Xl>$wWCjm}ZEahr3& zAbr6*xr&JIV0*{m_j1RxrvUjH+yF%DX+}=I0d;PAFLwk3V!Y3Kxxh^O7)M|uy*A~l z+CMf?bn`dls$|#(zypX?t#o5*F$Hr@4B-SrmT^=94md%EjQy6bm!*YD`AHzuwf z_-(uOMS~;_F<3VkXG_#UsYcR}miLk+NLqt%yb<8!loLOM*BY?N@Kf89x z2UEa^TW_|)9Rt9k-|GjX5>5CdH(St}cjdk+l8PCfE#%PWx#@Om6VR(MSl=}+l4^jS zSJG;}$X#S|0wroM1pnROLkWT*viZB*vLv?ypW7dZ5WxNh8L&Th7^U!@NM^i{YnB56 zu)4`uUzce?n&qcl5HSPm07OoTOfslhrsV%3{uS7fhaA$)=x6ZR&YLWzp`VSu?V(w6fPS3py{0$;89Fo-8eg>!ygfo5BK)cJAUmH`ok?f_ z9B_NQUW%sd`jPEEO#)5orvb3n6Ap$rnhQ>W#tR!{1iVI4HVV+V{a}E_(VVYGlkh#E zjR$8%up$hTp^rGK$-)t>x`sjnVSnslM(D95^)PjL3a89G;*9tM zu?LAh;%Hsp69(r{H?Kc56?sq46Nr&7f3$7&U?3a`((2{c*OImWc4TVfp3hql()KJ$ zPZPnMJkOacT`d^M+C^ojlU|F;SCNkwrI%742yJwA;ltpscQUW5G2nBDy{Mclx-mUd zJC>Gj9*pe3LV?9vxknJk#yz%q>A1y^xZE-!9VheSR11{Db*V`3hBgHBu+5M&*6Ar}B_8 z2UyTd`?vNN?91&JsyozwGY58)y}EmM6L)PE#@E+h3Ff5}^(!1>rfBd5ugC57N~(5Y zmFrA#yos(_-AhkZ6NX!uIz)LqA)n8OY~4%#qBNLGgGDsBEBic>ZN1wix{8k)RCSI4 zLc|`hWqde+0ohUInA)-_!>{Nde(JAWF!aU>>_peHc*8=Z2{! z33P*kfJ(`eQP;Uu7(5psR!9uZDg#vd4cv4OGgl_+#Khg1)-net;;G5H0#-hmqY~Bb zrP4ikscElikLd%`Rx)IG!Sz~!J8dmLl2jmm_LunCU*czf#81|e$PU(` z$h2wXNqD1hS-$q@%=GU$7!0wUHp{<#6U`PuCY563t*NxJ%kDy(^KSwcWgI z!y?L`xo2p;*#+CPg-5iytf)CJQ40<8X#C6X7t$B4Izzd^AJYt)2B)K~srzrg0!dyC|5cn2Jm}rYINLbQc&Txmag=eWaUhtHEilh9*PEx9C$1V^P(o&H zFDMa>joO{t3$Dam1b%j}%&>~N)3eO|n~mgwUYRpWG50#gT>OE#_ycqC2j=1r3=Uis zy9z!!hlw@>7YGFwmF3Z;=|75Er`CY6jX`Nvn#3CN@sYe7(NYJ^EhEkQ@?kA`sZb`* zR}{HO*UF+gvb(bAdGgd!xHqb*X#T39g;+aQSa`XSxW3BI&@QMhdQ4dLO@3FSI}q}? z(RIZ2OJ0^XrhDN|fi6{M@?k|$4VhC}bP+l7SRp10{{fip>t3XhnmY;+*LHQ}G z0DGHk?42M65MM}y!!!^~S=HzBgo2gQ70XDUNhRsp)oTlHs@BkvikHn`MaE=E2qc`F zzAcOd5p0>DnyxRbCu?e)5JIJ1mRT4J@?L#KA?aRU=#RpB#{Sd41MW`Y3DBSn0be8# z38541!acyfdC>3e!NG~zANHf)Qo{WKh?NoydfXv&yqyBoLBAVh+*sQp2N^UH19|Vf1tA0ss$q1EDbbsa-fk4FIpqA5*|RJp&$yy8&Eq5dDx6 z9;F4`p@=7pj;1UCaByM{dn4#byYK)olVNnYUAQ+4os15pf=B5S1|b5UCxX6DRe-_+ zVGkVx2UEb^%w3!M6?@Tl?ZJIve=rh22U5VJ41q5Q%t#o0o1y@R``vDMfN$D`gU=2S z__{r~HxdAj8-3Ll9)(Z=G_*)47y<-ewk-gQp&MeOgn~g|1nqAZ9`JYqe)L7Va4$&R zyl7t=coeWR0w4>E_|e`r1!8dEufbysHMa`~uPK-%pSKH#76yXov)1rv1O##569Qq7 zpbPxy)7AwNa99VzLG($xa0ox+_M<)R!Gobt2paHlD|i&-i~IqC{zxR`M!Q=TXn}ho zzF-*bY7b6>$ArA-qtPrak;&GCaz5J6-@zh%gO5NG_m*yJ67|q4(Q^ zyCFJPD2R5p3lBi#B@fz>1dnaE>;XVH>xPABdr|?u9dkJJFbu+NDd6ll4l!+DsY6@a zg~J&U)`=~8IP`zZejkDT*d0Wh^#$~B7=dn|2ff!WJQSo4xT#%ufbNv&T^+m&iv*h3 z{n+LPCeqFG3cG4|bu0Rb@gwoGQH1(Fxp5m$@;Dr(2yBkHn+`uipMb+E;|=1{cHwX+ z3VLvf9?m)_fdCHQ0Y5I*7vP&EkDM2R9tsC=QM>RU$TIx6FeRLd=V2N12XKK79&Kp> zEdYCw*MnWU0?BY_zt@ZN+l9L!?okluwS{xJdjuppP(QZ?9*rvyVg=v{B7U6HQXm-~ z4#92~!rAS@sTj?Tv)YA2tg}D_cTK>d|6?uW4-ksLEOFz^M1j_DSf@i?>}(J2rtWlJ zoRIx>dPxdV6qRC;%%RPHPtqi$o-d zJH_D9M7Uhgjj#vs!7>u|Vn@3OX!u4iR#U?vW~>{;tA4Ds2ls_SJ{Y8S4v)6P>*WvN z0f8L+`LL~B1YTH3-Pqb59Qd_xAdD^T!h;|k3t=;ZN0U4vX%Bd+y&!@MhOwzF0uL;d z;p%WG0FL0;*e*N({FV>P?ZW-Q?*uWX@Ti^%hsZ*l0PIC@@Imb%0Dccx4h(vi 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 delta 17635 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 P{IQkZv;3CcbWZp`_%`uZ diff --git a/installations/models.py b/installations/models.py index 62f7ecc..98fc452 100644 --- a/installations/models.py +++ b/installations/models.py @@ -42,8 +42,8 @@ class InstallationReport(BaseModel): new_water_meter_serial = models.CharField(max_length=50, null=True, blank=True, verbose_name='سریال کنتور جدید') seal_number = models.CharField(max_length=50, null=True, blank=True, verbose_name='شماره پلمپ') is_meter_suspicious = models.BooleanField(default=False, verbose_name='کنتور مشکوک است؟') - utm_x = models.DecimalField(max_digits=10, decimal_places=6, null=True, blank=True, verbose_name='UTM X') - utm_y = models.DecimalField(max_digits=10, decimal_places=6, null=True, blank=True, verbose_name='UTM Y') + utm_x = models.DecimalField(max_digits=10, decimal_places=0, null=True, blank=True, verbose_name='UTM X') + utm_y = models.DecimalField(max_digits=10, decimal_places=0, null=True, blank=True, verbose_name='UTM Y') description = models.TextField(blank=True, verbose_name='توضیحات') created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='ایجادکننده') approved = models.BooleanField(default=False, verbose_name='تایید شده') diff --git a/installations/templates/installations/installation_assign_step.html b/installations/templates/installations/installation_assign_step.html index 2bdbe4d..f78b3d8 100644 --- a/installations/templates/installations/installation_assign_step.html +++ b/installations/templates/installations/installation_assign_step.html @@ -22,7 +22,12 @@ {% endblock %} {% block content %} + {% include '_toasts.html' %} + + +{% instance_info_modal instance %} +
@@ -30,11 +35,13 @@

{{ step.name }}: {{ instance.process.name }}

- اشتراک آب: {{ instance.well.water_subscription_number|default:"-" }} - | نماینده: {{ instance.representative.profile.national_code|default:"-" }} + {% instance_info instance %}
- بازگشت + + + بازگشت +
@@ -64,17 +71,17 @@
{% if assignment.assigned_by or assignment.installer %} -
+
{% if assignment.assigned_by %}
-
تعیین‌کننده نصاب
+
تعیین‌کننده نصاب
{{ assignment.assigned_by.get_full_name|default:assignment.assigned_by.username }} ({{ assignment.assigned_by.username }})
{% endif %} {% if assignment.updated %}
-
تاریخ ثبت/ویرایش
+
تاریخ ثبت/ویرایش
{{ assignment.updated|to_jalali }}
{% endif %} @@ -83,14 +90,22 @@ {% endif %}
{% if previous_step %} - قبلی + + + قبلی + {% else %} {% endif %} {% if is_manager %} - + {% else %} - بعدی + + بعدی + + {% endif %}
diff --git a/installations/templates/installations/installation_report_step.html b/installations/templates/installations/installation_report_step.html index 6044f53..946c7b4 100644 --- a/installations/templates/installations/installation_report_step.html +++ b/installations/templates/installations/installation_report_step.html @@ -35,7 +35,12 @@ {% endblock %} {% block content %} + {% include '_toasts.html' %} + + +{% instance_info_modal instance %} +
@@ -43,11 +48,13 @@

{{ step.name }}: {{ instance.process.name }}

- اشتراک آب: {{ instance.well.water_subscription_number|default:"-" }} - | نماینده: {{ instance.representative.profile.national_code|default:"-" }} + {% instance_info instance %}
- بازگشت + + + بازگشت +
@@ -55,18 +62,15 @@
{% if report and not edit_mode %} -
-
-
- {% if request.user|is_installer %} - ویرایش گزارش نصب - {% else %} - - {% endif %} -
-
-
- {% if step_instance and step_instance.status == 'rejected' and step_instance.get_latest_rejection %} +
+ {% if user_is_installer %} + + + ویرایش گزارش نصب + + {% endif %} +
+ {% if step_instance and step_instance.status == 'rejected' and step_instance.get_latest_rejection %} {% endif %} +
+

تاریخ مراجعه: {{ report.visited_date|to_jalali|default:'-' }}

@@ -151,7 +157,7 @@
وضعیت تاییدها
{% if user_can_approve %}
- +
{% endif %} @@ -184,18 +190,28 @@
{% if previous_step %} - قبلی + + + قبلی + {% else %} {% endif %} {% if next_step %} - بعدی + + بعدی + + {% endif %}
{% else %} - {% if not request.user|is_installer %} -
شما مجوز ثبت/ویرایش گزارش نصب را ندارید. اطلاعات به صورت فقط خواندنی نمایش داده می‌شود.
+ + {% if not user_is_installer %} +
شما مجوز ثبت/ویرایش گزارش نصب را ندارید.
{% endif %} + + {% if user_is_installer %} +
{% csrf_token %}
@@ -203,40 +219,40 @@
- +
- +
- +
- +
- +
- +
- +
- {% if request.user|is_installer %} + {% if user_is_installer %} {% endif %}
@@ -246,7 +262,7 @@
photo - {% if request.user|is_installer %} + {% if user_is_installer %} {% endif %} @@ -347,24 +363,28 @@
- +
- + {% endif %}
{% if previous_step %} - قبلی + + + قبلی + {% else %} {% endif %}
- {% if request.user|is_installer %} - - {% else %} - + {% if user_is_installer %} + {% endif %} {% if next_step %} - بعدی + + بعدی + + {% endif %}
@@ -499,7 +519,6 @@ try { if (sessionStorage.getItem('install_report_saved') === '1') { sessionStorage.removeItem('install_report_saved'); - showToast('گزارش نصب با موفقیت ثبت شد', 'success'); } } catch(_) {} })(); diff --git a/installations/views.py b/installations/views.py index 8c3dc7e..ac27db9 100644 --- a/installations/views.py +++ b/installations/views.py @@ -19,7 +19,7 @@ def installation_assign_step(request, instance_id, step_id): next_step = instance.process.steps.filter(order__gt=step.order).first() # Installers list (profiles that have installer role) - installers = Profile.objects.filter(roles__slug=UserRoles.INSTALLER.value).select_related('user').all() + installers = Profile.objects.filter(roles__slug=UserRoles.INSTALLER.value, county=instance.well.county).select_related('user').all() assignment, _ = InstallationAssignment.objects.get_or_create(process_instance=instance) # Role flags @@ -72,17 +72,56 @@ def installation_assign_step(request, instance_id, step_id): }) +def create_item_changes_for_report(report, remove_map, add_map, quote_price_map): + """Helper function to create item changes for a report""" + # Create remove changes + for item_id, qty in remove_map.items(): + up = quote_price_map.get(item_id) + total = (up * qty) if up is not None else None + InstallationItemChange.objects.create( + report=report, + item_id=item_id, + change_type='remove', + quantity=qty, + unit_price=up, + total_price=total, + ) + + # Create add changes + for item_id, data in add_map.items(): + unit_price = data.get('price') + qty = data.get('qty') or 1 + total = (unit_price * qty) if (unit_price is not None) else None + InstallationItemChange.objects.create( + report=report, + item_id=item_id, + change_type='add', + quantity=qty, + unit_price=unit_price, + total_price=total, + ) + + @login_required def installation_report_step(request, instance_id, step_id): instance = get_object_or_404(ProcessInstance, id=instance_id) step = get_object_or_404(instance.process.steps, id=step_id) + previous_step = instance.process.steps.filter(order__lt=step.order).last() next_step = instance.process.steps.filter(order__gt=step.order).first() + assignment = InstallationAssignment.objects.filter(process_instance=instance).first() existing_report = InstallationReport.objects.filter(assignment=assignment).order_by('-created').first() - # Only installers can enter edit mode - user_is_installer = hasattr(request.user, 'profile') and request.user.profile.has_role(UserRoles.INSTALLER) + + # Only the assigned installer can create/edit the report + try: + has_installer_role = bool(getattr(request.user, 'profile', None) and request.user.profile.has_role(UserRoles.INSTALLER)) + except Exception: + has_installer_role = False + is_assigned_installer = bool(assignment and assignment.installer_id == request.user.id) + user_is_installer = bool(has_installer_role and is_assigned_installer) edit_mode = True if (request.GET.get('edit') == '1' and user_is_installer) else False + # current quote items baseline quote = Quote.objects.filter(process_instance=instance).first() quote_items = list(quote.items.select_related('item').all()) if quote else [] @@ -100,7 +139,14 @@ def installation_report_step(request, instance_id, step_id): reqs = list(step.approver_requirements.select_related('role').all()) user_roles_qs = getattr(getattr(request.user, 'profile', None), 'roles', None) user_roles = list(user_roles_qs.all()) if user_roles_qs is not None else [] - user_can_approve = any(r.role in user_roles for r in reqs) + # Align permission check with invoices flow (role id intersection) + try: + req_role_ids = {r.role_id for r in reqs} + user_role_ids = {ur.id for ur in user_roles} + can_approve_reject = len(req_role_ids.intersection(user_role_ids)) > 0 + except Exception: + can_approve_reject = False + user_can_approve = can_approve_reject approvals_list = list(step_instance.approvals.select_related('role').all()) approvals_by_role = {a.role_id: a for a in approvals_list} approver_statuses = [ @@ -160,6 +206,13 @@ def installation_report_step(request, instance_id, step_id): StepRejection.objects.create(step_instance=step_instance, rejected_by=request.user, reason=reason) existing_report.approved = False existing_report.save() + # If current step moved ahead of this step, reset it back for correction (align with invoices) + try: + if instance.current_step and instance.current_step.order > step.order: + instance.current_step = step + instance.save(update_fields=['current_step']) + except Exception: + pass messages.success(request, 'گزارش رد شد و برای اصلاح به نصاب بازگشت.') return redirect('processes:step_detail', instance_id=instance.id, step_id=step.id) @@ -177,6 +230,21 @@ def installation_report_step(request, instance_id, step_id): is_suspicious = True if request.POST.get('is_meter_suspicious') == 'on' else False utm_x = request.POST.get('utm_x') or None utm_y = request.POST.get('utm_y') or None + # Normalize UTM to integer meters + if utm_x is not None and utm_x != '': + try: + utm_x = int(Decimal(str(utm_x))) + except InvalidOperation: + utm_x = None + else: + utm_x = None + if utm_y is not None and utm_y != '': + try: + utm_y = int(Decimal(str(utm_y))) + except InvalidOperation: + utm_y = None + else: + utm_y = None # Build maps from form fields: remove and add remove_map = {} @@ -221,8 +289,6 @@ def installation_report_step(request, instance_id, step_id): unit_price = item_obj.unit_price if item_obj else None add_map[item_id] = {'qty': qty, 'price': unit_price} - # اجازهٔ ثبت همزمان حذف و افزودن برای یک قلم (بدون محدودیت و ادغام) - if existing_report and edit_mode: report = existing_report report.description = description @@ -247,29 +313,7 @@ def installation_report_step(request, instance_id, step_id): InstallationPhoto.objects.create(report=report, image=f) # replace item changes with new submission report.item_changes.all().delete() - for item_id, qty in remove_map.items(): - up = quote_price_map.get(item_id) - total = (up * qty) if up is not None else None - InstallationItemChange.objects.create( - report=report, - item_id=item_id, - change_type='remove', - quantity=qty, - unit_price=up, - total_price=total, - ) - for item_id, data in add_map.items(): - unit_price = data.get('price') - qty = data.get('qty') or 1 - total = (unit_price * qty) if (unit_price is not None) else None - InstallationItemChange.objects.create( - report=report, - item_id=item_id, - change_type='add', - quantity=qty, - unit_price=unit_price, - total_price=total, - ) + create_item_changes_for_report(report, remove_map, add_map, quote_price_map) else: report = InstallationReport.objects.create( assignment=assignment, @@ -286,29 +330,7 @@ def installation_report_step(request, instance_id, step_id): for f in request.FILES.getlist('photos'): InstallationPhoto.objects.create(report=report, image=f) # item changes - for item_id, qty in remove_map.items(): - up = quote_price_map.get(item_id) - total = (up * qty) if up is not None else None - InstallationItemChange.objects.create( - report=report, - item_id=item_id, - change_type='remove', - quantity=qty, - unit_price=up, - total_price=total, - ) - for item_id, data in add_map.items(): - unit_price = data.get('price') - qty = data.get('qty') or 1 - total = (unit_price * qty) if (unit_price is not None) else None - InstallationItemChange.objects.create( - report=report, - item_id=item_id, - change_type='add', - quantity=qty, - unit_price=unit_price, - total_price=total, - ) + create_item_changes_for_report(report, remove_map, add_map, quote_price_map) # After installer submits/edits, set step back to in_progress and clear approvals step_instance.status = 'in_progress' @@ -319,6 +341,33 @@ def installation_report_step(request, instance_id, step_id): except Exception: pass + # If the report was edited, ensure downstream steps reopen like invoices flow + try: + subsequent_steps = instance.process.steps.filter(order__gt=step.order) + for subsequent_step in subsequent_steps: + subsequent_step_instance = instance.step_instances.filter(step=subsequent_step).first() + if subsequent_step_instance and subsequent_step_instance.status == 'completed': + # Reopen the step + instance.step_instances.filter(step=subsequent_step).update( + status='in_progress', + completed_at=None + ) + # Clear previous approvals if any + try: + subsequent_step_instance.approvals.all().delete() + except Exception: + pass + except Exception: + pass + + # If current step is ahead of this step, reset it back to this step + try: + if instance.current_step and instance.current_step.order > step.order: + instance.current_step = step + instance.save(update_fields=['current_step']) + except Exception: + pass + messages.success(request, 'گزارش ثبت شد و در انتظار تایید است.') return redirect('processes:step_detail', instance_id=instance.id, step_id=step.id) @@ -340,6 +389,7 @@ def installation_report_step(request, instance_id, step_id): 'assignment': assignment, 'report': existing_report, 'edit_mode': edit_mode, + 'user_is_installer': user_is_installer, 'quote': quote, 'quote_items': quote_items, 'all_items': items, @@ -351,6 +401,7 @@ def installation_report_step(request, instance_id, step_id): 'step_instance': step_instance, 'approver_statuses': approver_statuses, 'user_can_approve': user_can_approve, + 'can_approve_reject': can_approve_reject, }) diff --git a/invoices/views.py b/invoices/views.py index b271a29..ea99eb7 100644 --- a/invoices/views.py +++ b/invoices/views.py @@ -408,7 +408,7 @@ def quote_payment_step(request, instance_id, step_id): defaults={'approved_by': request.user, 'decision': 'rejected', 'reason': reason} ) StepRejection.objects.create(step_instance=step_instance, rejected_by=request.user, reason=reason) - # If current step is ahead of this step, reset it back to this step + # If current step is ahead of this step, reset it back to this step try: if instance.current_step and instance.current_step.order > step.order: instance.current_step = step diff --git a/locations/models.py b/locations/models.py index d3de371..bca8971 100644 --- a/locations/models.py +++ b/locations/models.py @@ -11,7 +11,7 @@ class City(NameSlugModel): return self.name class County(NameSlugModel): - city = models.ForeignKey(City, on_delete=models.CASCADE, verbose_name="شهرستان") + city = models.ForeignKey(City, on_delete=models.CASCADE, verbose_name="استان") class Meta: verbose_name = "شهرستان" diff --git a/processes/templates/processes/request_list.html b/processes/templates/processes/request_list.html index dfcf4bc..feb1294 100644 --- a/processes/templates/processes/request_list.html +++ b/processes/templates/processes/request_list.html @@ -479,7 +479,7 @@ $('#requests-table').DataTable({ pageLength: 10, lengthMenu: [[10, 25, 50, -1], [10, 25, 50, "همه"]], - order: [[0, 'desc']], + order: [], responsive: true, }); let currentWellId = null; diff --git a/wells/forms.py b/wells/forms.py index 1649d01..5f39178 100644 --- a/wells/forms.py +++ b/wells/forms.py @@ -82,12 +82,10 @@ class WellForm(forms.ModelForm): 'utm_x': forms.NumberInput(attrs={ 'class': 'form-control', 'placeholder': 'X UTM', - 'step': '0.000001' }), 'utm_y': forms.NumberInput(attrs={ 'class': 'form-control', 'placeholder': 'Y UTM', - 'step': '0.000001' }), 'utm_zone': forms.NumberInput(attrs={ 'class': 'form-control', diff --git a/wells/models.py b/wells/models.py index c0663f9..89e9aad 100644 --- a/wells/models.py +++ b/wells/models.py @@ -78,14 +78,14 @@ class Well(SluggedModel): utm_x = models.DecimalField( max_digits=10, - decimal_places=6, + decimal_places=0, verbose_name="X UTM", null=True, blank=True ) utm_y = models.DecimalField( max_digits=10, - decimal_places=6, + decimal_places=0, verbose_name="Y UTM", null=True, blank=True