From df8760ebe062decd90d04d67df827cd1243c3ca4 Mon Sep 17 00:00:00 2001 From: Marwan Alwali Date: Sun, 26 Jan 2025 18:24:33 +0300 Subject: [PATCH 1/3] update --- .../__pycache__/settings.cpython-311.pyc | Bin 7358 -> 7310 bytes .../__pycache__/urls.cpython-311.pyc | Bin 2157 -> 2157 bytes inventory/__pycache__/mixins.cpython-311.pyc | Bin 3600 -> 3600 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/car_inventory/__pycache__/settings.cpython-311.pyc b/car_inventory/__pycache__/settings.cpython-311.pyc index 81c8ff388d77d30d5b61a1a7e4c1dd8ac2a7ca17..398c131a749606ca371b47c2eefb6c13cad4c9b1 100644 GIT binary patch delta 485 zcmZ9H%TE(=5Xbko-O>lHQ7MTwEv1yUAa)Cs0)QVr>%(G2!CH zvx(WnQ{zz&5)-p$Jb5-=yzp1_Y+~Y|Hz)Z_X1`3Y=k)v%5<2oaFhg z4>K&GD9myJb6mtc%P6se1%?@Ozv)^3B9~Eid-~w3imur@s~?o6eG>i!E^`G-T*Vcx z;VNsabDa%taFYYP*$vM<=OZ-u7#rSu-_KC8`b*`H12667PW!oi(AR7`yRH0jaKB@}Xl;u!?oNdw zr=M)^JhNNuSdBLArgvoS`_-mb7>FqEX{2m~Kg%m84|NRh@Vujpj22C}@o1{w`k^Iz RLCrte^Lh1XTQ?46>JJ~hgc$$; delta 542 zcmZ9IL2DCn5XJYu$r|0dAZ-Ii-K1%fCbf3erfHj`(XQ#XN!w&2Zq$xSSo4-O7?VR2 zkRJU2f-HEDob@0gx+gE;L>%o_&Y@Sf*C=an~#A`86!#9q38 zUnmjw^g~)>dWbGSB^6PMB1SPx(G-FdN8DvJjcJ!5!AXupN+3l^%uotxnsH7evp*&X zF7v*!wD*afVHxim%Sp4Cqld9&hpcnlKZ=Ze=5v!$z8parh7$kHMf zk;77l@xILa$|yiNE1D?8tzja56JXi1%8|g{gRv~cBkw0m9Vy-wYyz=IC!Ml?RJ0I z8)!$O_0VoVc6!*;bgrDsHmQ zw`zt}G1vX#WGN`W=LsC;uqXS^&bmxa3h~T$LH!v~z2A|<7@y+@vLF=>B>()mz8HMR GZw~>Lbd#O{ diff --git a/car_inventory/__pycache__/urls.cpython-311.pyc b/car_inventory/__pycache__/urls.cpython-311.pyc index a83a2e89bc3afcb0e173074144eab0e62b142c5f..96a4e3f03d3f42627e28b24a33835fad608dba0f 100644 GIT binary patch delta 20 acmaDW@K%6(IWI340}!mWpSF=Zi30#WrUiKb delta 20 acmaDW@K%6(IWI340}#~gp0trWi30#YBL%kl@9 Date: Mon, 27 Jan 2025 19:24:42 +0300 Subject: [PATCH 2/3] update --- .../__pycache__/settings.cpython-311.pyc | Bin 7310 -> 7513 bytes inventory/__pycache__/forms.cpython-311.pyc | Bin 32637 -> 32295 bytes inventory/__pycache__/mixins.cpython-311.pyc | Bin 3600 -> 2391 bytes inventory/__pycache__/models.cpython-311.pyc | Bin 85837 -> 88748 bytes inventory/__pycache__/urls.cpython-311.pyc | Bin 23951 -> 23872 bytes inventory/__pycache__/utils.cpython-311.pyc | Bin 23190 -> 23390 bytes inventory/__pycache__/views.cpython-311.pyc | Bin 167313 -> 174321 bytes inventory/mixins.py | 24 +- inventory/signals.py | 3 +- inventory/utils.py | 4 +- requirements.txt | 48 +- static/css/appt-common.css | 452 +++++++++ ...jumaih-Automotive-logo_kM7B61x_AROA7K7.png | Bin 0 -> 10227 bytes static/js/app_admin/staff_index.js | 870 ++++++++++++++++++ static/js/appointments.js | 370 ++++++++ static/js/js-utils.js | 8 + static/js/modal/error_modal.js | 19 + static/js/modal/show_modal.js | 25 + .../administration/display_appointment.html | 98 ++ .../email_change_verification_code.html | 41 + templates/administration/manage_day_off.html | 152 +++ templates/administration/manage_service.html | 51 + .../administration/manage_staff_member.html | 87 ++ .../manage_staff_personal_info.html | 49 + .../administration/manage_working_hours.html | 183 ++++ templates/administration/service_list.html | 78 ++ templates/administration/staff_index.html | 409 ++++++++ templates/administration/staff_list.html | 81 ++ templates/administration/user_profile.html | 281 ++++++ .../appointment_client_information.html | 165 ++++ templates/appointment/appointments.html | 134 +++ templates/appointment/default_thank_you.html | 36 + .../appointment/enter_verification_code.html | 39 + .../appointment/rescheduling_thank_you.html | 79 ++ templates/appointment/set_password.html | 104 +++ templates/appointment/thank_you.html | 53 ++ templates/base.html | 8 +- .../admin_new_appointment_email.html | 74 ++ templates/email_sender/reminder_email.html | 97 ++ templates/email_sender/reschedule_email.html | 93 ++ templates/email_sender/thank_you_email.html | 290 ++++++ templates/inventory/car_inventory.html | 2 +- templates/modal/confirm_modal.html | 23 + templates/modal/error_modal.html | 21 + templates/modal/event_details_modal.html | 38 + templates/sales/invoices/invoice_detail.html | 12 +- templates/sales/invoices/invoice_preview.html | 163 ++-- test.txt | 12 + 48 files changed, 4649 insertions(+), 127 deletions(-) create mode 100644 static/css/appt-common.css create mode 100644 static/images/logos/vendors/Aljumaih-Automotive-logo_kM7B61x_AROA7K7.png create mode 100644 static/js/app_admin/staff_index.js create mode 100644 static/js/appointments.js create mode 100644 static/js/js-utils.js create mode 100644 static/js/modal/error_modal.js create mode 100644 static/js/modal/show_modal.js create mode 100644 templates/administration/display_appointment.html create mode 100644 templates/administration/email_change_verification_code.html create mode 100644 templates/administration/manage_day_off.html create mode 100644 templates/administration/manage_service.html create mode 100644 templates/administration/manage_staff_member.html create mode 100644 templates/administration/manage_staff_personal_info.html create mode 100644 templates/administration/manage_working_hours.html create mode 100644 templates/administration/service_list.html create mode 100644 templates/administration/staff_index.html create mode 100644 templates/administration/staff_list.html create mode 100644 templates/administration/user_profile.html create mode 100644 templates/appointment/appointment_client_information.html create mode 100644 templates/appointment/appointments.html create mode 100644 templates/appointment/default_thank_you.html create mode 100644 templates/appointment/enter_verification_code.html create mode 100644 templates/appointment/rescheduling_thank_you.html create mode 100644 templates/appointment/set_password.html create mode 100644 templates/appointment/thank_you.html create mode 100644 templates/email_sender/admin_new_appointment_email.html create mode 100644 templates/email_sender/reminder_email.html create mode 100644 templates/email_sender/reschedule_email.html create mode 100644 templates/email_sender/thank_you_email.html create mode 100644 templates/modal/confirm_modal.html create mode 100644 templates/modal/error_modal.html create mode 100644 templates/modal/event_details_modal.html create mode 100644 test.txt diff --git a/car_inventory/__pycache__/settings.cpython-311.pyc b/car_inventory/__pycache__/settings.cpython-311.pyc index 398c131a749606ca371b47c2eefb6c13cad4c9b1..165fdde1c4faf57ca202d6e7c55e46b17cff4152 100644 GIT binary patch delta 918 zcmZ8f%~MiQ6n_sfiUO67QbrU71VvHtTNHi3Lr~x$?~!$^UT-{zq@WXy3pO~d8)up~ zlN+X`O|>fe3z})uCRYvdH`GkKT6Td&$(i|`d+zUi-ZS@X;rpWYwML_+h`{-I=9~3} zwwr$b-r=UVRnUuOFk>I|VL$Yv1uWPL12~YOVGsv1G+GI4Wd&H#4mKPDJ33$pRp3A; zIB^(;$vJ`};6fLSrf=bB@g_x)>@oQZZSNYpP*Bu6f~J7G&Klh<>^P3YMBP)Gxa!%Z zVG<|7gC3Y7J*Np~2xifvpwicI>VhWK37WF2!084*)5>QQFo&}+PjVM<4i<497jQ94 z6YV8>soVx$T!y6*QOoE9AFjX(uEHuZz@Qq<=qI6pEKP#_WFbLh%Zi2-YFKOJ7A`Bn zj}ZtoMu=P;0fK~8;Cc(o;s%5;3TqgHFvhXOVFEWXi9G62D61fXDOe}iXcWEMk{(4R z#0cW#T^wnhz%9Io_YrU#AK=6CHP~#lebkbdL=kv=3<4^7YFLsyWQFSB6DePL+xGc} zs@9&)N!bJWP-B$OG@odfys0(C3c2GWH(Pi3rJenB9*f!rm8nziox@y~3`rF`_oVE; zbg+7y&hJSF?t)a*XY++4i*%ApTk?gcMa$7iHeV@eU$x2Ox<7QP;?x`HJ~I;taH+T; zGASX<#)U|L5h7e%jIlzP3(8)@50Q;Ak*FBvc%i0l+6gWx)HF>y#j~Oio$8;e;HW(7&d_QbHQ>CY z%+(&V{IkbO*3o5}beX6w->IgmF`ufdnogoR4dkk`opw}jyDlkx)#$jSbib}q+U`o! S^qX!crok&mdwt3er1oE!P4r{{ delta 756 zcmZ9J$xl;p5Xax|(XbRtYzu(_Vxq)odh()Y4<;U!6NyLv0HcYC)AmFs`A+8dnVH`td^8a&1fYT+NcF?YSk{F{h(Bm zxT?*3FIw%MV_A~kvT{c546W$MqwVM935B{)MBOZf<%J?kS~0xG zf_G=-Y+FW8miOj!U8WxNQ7`xQp`ZFOfI$pJ1^Z$4BdG!!z$gtKvKxYrhA~DX7^hK8 zkPlYW!q26XQNhK2e)tpuDLETWXQLTj&893gh9He+uMj+c1)5+gBa}z|n4?L|(-amc zfJGcGA&dx?u>vQqq>5-7S80Ydo85FZuRRD0g;;a^u6aIs0c*5~b!^}ouHy!7f>MRF zls)=ZUT+w;DS|t+49lA2xvTc^H(Jx53ci#yh5icfY0gTh!sj~d?7;)h9X z*HD>w%%`R0=11F!SHX^I=m}*jv8yR@H5yaysap>;14%|kG7;01Ui}QGxwp zT;1JQjj27&xUa^Pq-yRs{)m+{oaMrNS^g{iv*Nkzbj$`rfsOF`W@vRKvKfp77Q*JE zsyEhmJnPKFla_SHWnEa>r0NFqRkcef=I82O>m|t^5RYwVw#sx(&2Lfiy~6!Xa-2DR MW@Vk9-O0a`@E`~Uy| diff --git a/inventory/__pycache__/forms.cpython-311.pyc b/inventory/__pycache__/forms.cpython-311.pyc index b7d0f1a615bc0a91be90ff2c732aec68981abc49..eb66006bc4c985a5f2ae60581c33b24038b3a1b9 100644 GIT binary patch delta 9466 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 R9jgHcT0r{ED3ugG{s(5PnC<`o delta 9156 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 K?qt2#n*R^_^g8?i diff --git a/inventory/__pycache__/mixins.cpython-311.pyc b/inventory/__pycache__/mixins.cpython-311.pyc index a098233c53981a1b90f7ea45b0a127e67fc75a8b..6bcef338f68806ff9c0bab6fca9171b9c8d0604d 100644 GIT binary patch delta 569 zcmbOrb6tpUIWI340}$}XPfK6LI+1Vo5rn%Wor2pc{+N1BnKP4_pjNYD=WAD;ix=G`gs0az)YP0|OgpCL@Hr$Rpd~HG}o; zWJA{J;ui$8Kky>tK7+jKr^!0`0H>a^IFP-Pp-2Kq6^VfeHWbk%y*g8jaCMZBi4T4NEpzGRB8K_-fWrlSW@WXO^W@eBfm6chCJj zKl7bidFrFirY}OF1_JW+^PkLr&eof5y(ZugWN!rEJ+eV`5~mu83mT1kG+~v*y+txd zHP0%Gi>~Gc%~vEhXx#rgQA8(nLDQyE3DbPpxM5^+3+oRe7v{1&EzcQxN;Bm|Mw6F$ zVsX*P%*)n-o|cV_oRBr+y1Z;y3-TY%Y~eSg^0x4$w~eo!vvn>5sNbe-Sd5 z>=Qzp{R17eEn!N~L>RU=`zFBawR;+R!g3k=Cm}ZO+O8Wlk8N?lj(KKI=F+0h9j2;A#;{bCOK^|kh9qu(x-gAp+ z-n;-PekL9@4@vjsj0VV@E3aJFIX5)jWv8sF^SWhNdLgZG#PXm}pUkrDjED;#yI{r(RTIgW@ z6e++N3pN2^{$k`r+q(azztYmZ)6%_lsnnvBTa==>D|LO^SeE+B(ojVj-H}GWRqtyh zX}T;;7el*^QkBraoAkGE$Ia<-xTg{x+6fPB4`00>0>JOpEBngu)lyh3ht=Zc-R5vH zh-CA?8)9D(2d1zRTyAsp*$M5_e^yVWR8^t1=#XCLYh~cW{Rr61G{7T!h_$`ZB;reO z2xUR+u9E)&#>CbtIUewi?|&7S=^5Swh7^G#iyc4YF=1I8yu$)E(L0&9+spnj8neIg zpFfAyGz0&u7kb`@pdj=k;M@NdaSN^%Q4D7h6uXa&`S2`{*%}+~b63vd*qy{@;BPjO p&T303eUgvC5KWt__RlQV&twW=9fdz}?&0Hw7pNT#414j$e*wsHqKE(h diff --git a/inventory/__pycache__/models.cpython-311.pyc b/inventory/__pycache__/models.cpython-311.pyc index 17a6662eb99cac5b534815f4c4c45452f47b817f..68d5f23050abb4db37d69d84ea6155c84ab01bb0 100644 GIT binary patch delta 10973 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 X(}7m-w_u}sOT;zCfAc$yVxj*RMoW)R delta 8747 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 diff --git a/inventory/__pycache__/urls.cpython-311.pyc b/inventory/__pycache__/urls.cpython-311.pyc index df997e16b068a38ebdf40556edcc969a6cee6fd3..2f40588cd5197dd51f9bc7af3ee1a7001f948d1d 100644 GIT binary patch delta 3037 zcmZ{ldrVu`9mjp}b-2dZ-~i!uv9ZHV2w(#vEboSgpI{z_V2pVMupv&t2J;Moj;!sv zWhG7WlUlM!E7PPlQlqsMT9&M>O4LrNru|_$uVdXGTUupX_sE=%Y1KAu`<;6X)2hyb zFW=Aaaen8VYn$iZAnQLQ>X+5(6dAtmc0NDy@fCG0k-fhEK9}S#gH|qEVG7947OaI7 zPb)|j_pT_?KEFk5P1M1agv^>u74Id7u$gwQLj)o0s-?9`{!V#c3j` zhvqa|HODN*s?^@M}yb01kz8<$7oJp z-QxtcURV-)If_3@+&^VOl4U zC+RY8qj`!Nr5>+PZ-O?x9^Tehz<2aI@(ir&o5z8T(WHPI#{&t zKPAQLk`l4}m5x|Jb@X^sT%M%Z^+<-YMI~OJBo#Wg3yU^+b&N0ERO{l&9IZszq7ru| zIUwC(#F14FIymT{2LVSJ>biq&b<1JeC9M{LZfBW%5*s{Dnz-mRpx$)Sh7X*yIklmh z?Yd8%*kK9OIz)ND+yQe9wBmaWw0cwWnnvmmOFGzCRxS-W%}Je6Wx>jHOke$T{fYPW zCpPpaWBQZp;V9?X;5;$T6CdCl@K&RVP4ly!O@1$wyTt4OC#@9PiAsmhhgw$_&g*oU zQNQM*yLr<^5B@8c302)h^_Zl=CYpUw(w{Zat4M05THZ|S+nTG`Qwu48cm%l7oPp6d zn`zId&Gbw{3ssw>g|7Zy3%#-5OOec0THhe)lBBm<>CPUs(%v*T&05{mhuuat zZy_1}=r&X?GP3cBJFa@o8awFNR2Re*a{6phwy4DIymS%GaMx|*TNrpDt4-8)G3eV~ zq6}8uxqLs1o`umik$;@QC|qmX$B!`x!99d9gK_w4n^-czAi`FPDh;dEvAu_Gk3~7x z2Iq=#uJ|OYm;p<>NjuA6VSBI<9=3~tMHaOw6DQJ3PpoKDZT$S()vlC|)Vf`H;Qv;- zS*35Ml1}2gS#%iOr_B5agK>BUVS>RtyoGR{fdvk9n0aeT;ua z-$s15XF`ET%MY>4DEt_E#u&_8^_clt=4;@~9wT3?l2&%XX^+S^F=&QmENfxlg?BtA zzKcO0e1@5R24}$Bna>9qjDov!pK^>rNCm&Pn@Yos=2VH#lX2A=D>@RbaYwnf4X!Q5 zwZ+e|l6lzdG-}T?u%sr=QU;e=Mc$g4IQwBQZi;~yLf*pCE(U$9KB}yEO^kiX8EqYk za{dj@ALIP-epcd#=e_&*0E1z8*K6QM7>vT7yk_kfgPHBgrT9%JDrZ@=Mh(6$17E9_ z_R#=OcA5D`2B+W-LI;CB_;Z)Jq@O`Zoj7#fiZv!w-qu7p`vzx^arStaRg8n(XXGas zEWiZ9A_E&-N3d(8c|GtWpNa2fFbIG5nUzBfMm6}^H}PYP=3uzntUbq|E=`*L3*G>~ z>=yZY_9f+l_q)w}69X^sJz_~010Sp3Q0i6{vBJtb>L_R1;A}C@7Vl;iJ=6e|o z!*Wj^Kf>S)yo#A1g9to8m}Ia3`Mr231~#zv8dL1)^iWHxM;@5y&Et~szuA8P5D07= delta 2922 zcmY+FdrVvR703DEYq+*C#xc)udD!8Gr!R>T+R=s(0@xT#c)tv3pkOEvY_NgwNV+h2(5o3Lq3nIEJ4jJstOP7pf$3O@9fB*dGAo1kVr9c&-if`Z zsP{DXmV;=LSq1fVnj}^UQ^*c@6V*xXmPvwDlLF7iNz6sgix^c?^btli@Ohlf+{C43 ziPb`vSvDNmp6d$Dbrt8TgCCk@Ru3OyzF|B6I_2NMd?StF+##_h_)4;Bm(Xh_@0aMc zP{b?}{9%UzH5Q4rk@H=PWN6>k)nV7E_Gego zlq&9H<~fQA6YvBR@B|Yi)=kbTMm_LJf{Q&*+?FV@UW(pIlpvU>z(aJrLO z7!APdNiutZ`0q&)yq}~%ak9jQ$T^GAFf1jz*l~D}EVB`aOK~wDiOo_pCP{|5?Qu7$ZVT&9s<&tQ2S%s1v;S1HrbpqWD(|Ap35<3H zj9m6I@r4Yl@%)oH7FeGS7BW(_dYt7I$_trR_9{h<7+rwH%-pi?e68O6rih%R^A~^0J@dkp02L^rP@MxD4 z&h3hWnyfU9%EMWC^jyrUP@l_pvp$YAnkT)!KL3-J)$F3EWO9Jz#!E(?JT@`f*E8;& z;hAvl@}3-9v?a+O80hg0&h(5A`hDSf`wN}M^soDHeUAk`EKIO`!{yb>|0*mLmb>?V zU&}5nM?Lc>a#>e$L9qPM)U zsEc?^flJU|KA?|g5fS(s5uAnF<$d@Ca-bp`wXY%%^-@JH>Pkhi)hU`HHz^){)| zSzw~Erx*>sA*R8f+U0}OjNHSKVK;TLC6rclJFVpRX(j7vrJ=OaHAmZ~CQ=)<6@l_d zmCf==v-=| z#AQW2=29EZyVT}ilYU8>U#&Vl)oS)tir=UBA!$NQK{O58Ex@!x*7OKY7_G5$uTOw$ z4!h1PP=$|3J z`f;t=_McjH1NI{{5b5`hs0&>s{em>9PIb!a)Cv4`>Q*n4bF)tE+9J)aSL37g>as4> ztM$Ji=W~h^8`Qaq8*=&iIpA`GO?2W9z9sbp4IDghvq2U+IdsEcv8;!~aoEu)iz6I- zP};a#^m7=65ri=g0eG!Z&I@uF7wL6a(^;2_Lc5;6F|sDO*9CV-aBoiViYa)|Xg5!D zIK|61L@VSp$>!7Ct-hrOq(Nl5Bc%qKV; zGKDYCN|#;6zXhw|Y^NgDaA<{HOxXYGP8K>@P-muji7ZLl+y#9`H Vk17XLd1_vNMnA6)Xz@SB{{c(9Sls{s diff --git a/inventory/__pycache__/utils.cpython-311.pyc b/inventory/__pycache__/utils.cpython-311.pyc index 6aa2a8a8b53fe6329752558fa1f05525d522d14a..24d1001ec3ce3142de9372b3ae3bdb9e2b119a35 100644 GIT binary patch delta 8646 zcmbVR4R9OBb-n`*|2P07Ko9^)5aK^bks>L|)W1ZF`lo1FqA7{70zo`T22FzU;z(Nx zXwr^T%MKG$UMEswC808oBTKX+he_i4S}4-g~?I_U+rw zI>`svDwP4YNtIIhGyFiiQ~^)xB|l(?#2@8?fp=Lif_%nEA`*R+{}HdF>og6e8B2d8 zCXJFqqf%rzBkmfD%cCO^GJizVr{T-#*M)Juao(@Hz;9R!8b~uhMt^3MoQ=qFEj$DQ z0TM)_b9i(xJRH3c3B^G{=@Px&@_&AM5?16g;{cdYyQU9?GT?A(onI+W!fCEf5HHv&LU zuvaoLy?hibeNo^e`4PO?fs|y z_I;;783_XfH5mhmJT?}I%LIvW4S+gc5gQnbM@UFMe=b5I)K)YA3Zg}QHT_JMiRAQv z)uXYv9F7e};ymggLHbUSpMT`V;dWDrN9786vkJHH#4 zpZ0X}{)DERJJ~#;O=yR3Zde&YCRXUR_3rJG?p4rmb4g3wDrwcfv)oxu60RBsH9U8e zn{JUyRZ)&haI%Nv=xmqUMIs4qNK{{uc6_3Dy&u=c)+XpX+e+!qCL68rwQJ-G8uhjD z74&7_rlwsJhJ@i>-I9!6RToFrCG@j)da2AsC(Cr6kK(5{${H)X@Tn5u8xRbjk zc$w!YUtJ;&q1&?}abEgVeF=TeXQPb)yB%kom2-ONfS`7E@{(q{8+xE2pN6*?F&-Hn zj>gW0&XMR~B&Z{9q?)60WF$1g!j3&GNm2Cc@Ng&^J2MJhjf5T>3&-TBd_H4TYoHLr zMn*uc^`wJPVb%yNxj3?R?b#j4&l+pxMF;WEN~084#9!Y29+e=~oB%GKLiQS4pxr~>O? zXkae*?@-CRpgh5YSJ4NHopx|Mpyx`Swn5?xXiHAYd~wM$<)xql%S6?-LQ>Lr>6EY3 zzlv{_Hr2BulJ=?q-aQ7BA!LlWpwM4))AAYUA5aBGIRX#l62c!LS+_h-WM=6Vo4|Wp zYjPgA;?D!%l$pFRWlP}TL|azmO588?D6ZC9KE<^)?eSi?914_xjZClAq_@$AgyKVNdS1zP%?TW4au9kPN z&zkfmbAOft%xae!#pcJ&p=mJ@Uv(iX?`c35bp4QZ$6rOEA!&h`aod&=3N zI6H1Vs5m1TT;$#igVk=?u*@boSsEzaKRZ&Ihzz`)AcUJ*|JjTV)t#UeO37D z(;UyoEr?+du^^xULR}odI^fjqe{y@Xum#ku_ZV>a02leR#X7xJvD7CUwkekF^szdh z)z923x%mO5;xK)=F0?i)EP0KCD|Tm#;PEc{&wB_-p(N|!ic8aFjp>ROs;#fSA7jEG z21vCSpu&z5Z@?MmGAHp9I{4@lnjw{glQfUAMM^%F(9H6%QCHE|+eLc0zOJMNHh8^^ zI`Rd!d$u__RuOe%cQd zgJhgD6`l+x%n~g(%ynMv7sv!x>GDaA zd-1K}s*#HB!DW@JRL#tczx7oHO$kdvD-}!5IalGx!RR02wwUm2BiWFf{=TU~{18W_ zDPc|MfTQHY`oJ5C*|F_kI!bsaszA?y8=oB+O`m&d%-x0}erFC2^FqMPuVM(NZVi z0ft^{ag{v|m7qvY!54WAAY%X)Y@0kqlPxaqr;uiqM`eg)`BOSxtjHTwv#!gD$7414 zv2VD099vhR{|lhUKTj{LJD|xLskyb*kkxa#qN$$wuGSge?c#JLicr2NR4)kCX?I21 z;ZNJk=wxRF71~2^X_4ChUNdM7$lJ*AU4%bI_zpnO zzRF1ShscA-pp8f5T${$+y$h*CLHGs2DTJRRY@o5tmC)p8H<$Ap>CMgmUCvrWmsAUm zg2lTVBK`4}fF_}#*W3ZPzSwETQ{snP)KaV%!qYk{b9^pB&^5khlaLVNgAi>r7`Bdp z0IFo=-oik|4Vo26b5#ow4Q^t~x3LLOID~sAE3;NyQa+4m(R{1wD;{nEC+XF1T;{ zR6$iS&c<%IV8%5PTwP)3DN{M%_*uT9Ua_LSM2EYZHp)*Jp*=quuoX58LxBk^RWS(T z;4(MSZCGJKOT7)?j9|CdpqiSM_8zKIMGC0ZaHaNY^W(IEe=N^s4Vxesu^+}$t4c4s z*vhfnO$DNL*n9(sE&HPhp6XR41NbHIkVavVW*90H8oM9=N?(neoRg(YE$Z;|`d_P|e0hMSfUSQLsio`*6j!$e7Q|mjoxd3n!C!K^Ql8R%SP$NPj_GSz(CKW|dJYUD;-6 z%SX_+s&wSWBP^X=>*&ET58+XXmC$yzwu-((rAwXy{+%ivsjAW;`Dv95#=2jv5A9NG zV6SeqUckFsr4H>;YYBdtSMtKs-sLxH)aF>Fb`ld~zFtU!>sa15sLhCj`IL7k7KX(4 zuRu0qf_xNYOXHz7;4E2UU{}!4qmPHl*?304v~R`=necEddV%GbR~&-KTc9VX%h(Eq zHRSvBdk1R8H}S1Df8?S6b|83!okdM!qiRab#L{Cdwfv93OumQ`e8w`)vh}&XzRa{_ ztPz$c%jMF@KO;BhgXo(Ft0%vYPk)W@4+u=vr=gay<~oMSV93*Bs3#$SJ;8msLkl~| zyoQ`C(X9?6&a%a15c$zm?DU$k=MvT-m5Z>^7{XF1Gb8IxMn85=!mKu))96%BkpD8h z(G%Q@{+`hfN2If1lCkDbwz;%mG2YTyt`Aa&qte)*9M5RSqp^&I87F@tM8_kSXzQWA zNec>~4a39387)*Y&V0|9Kwb%X7n?N5qai6eC})^Z&a83bLS;)QJ;+0{Oniu)B%Sz< z<#kS>0)0*&0gcGWZR+ap+TYW4f6s0*j?bQ5VbVv!vG|z?IVy+cvG}e> z@J0|P?AL;C15eNf2T$>V(n&~D)z=~tY!i_Q%T&JB0gG``|bd#kSc6>oF8qE4x3$r`$aYRFw6XgSw? zcR9Vw{2szZW7fu*iWFmD(OAD=tiSHQWlJ{fNEvr3#+^yy&a~0-g801noPFAU(LQf{ zu#6YhfLaP-t48b8wJxFcAWiFeFSnm*F5gCW{IR6M$A5}MLk z6`^cVs9F%JW)IxbzGeBQwv?#VOi0yBGLfP>^QfyC&hZXVgqS(J6_NT<-ig+AkEJaz4*B#T`E-F`wY8HzQ zHZ2r2z3o*t?N1&%tsFa>JU{t9$8~A;VG3wJ{L*(9pB}=*4}JmhJm0TL7BvCA_!yD_ zFY2>K&RRmx^nJ3?#+Cc0x)s55$7olKWoa*(ChZ9*o?yDXMk#O28U()?%q*qRoM z%RCjgwBNEWwstSHcBfkRD6M;vfxRhVpCar_3j6K|#zmoYK`2cLUPbUG1uw`h3f=|5 z+j=Fa_!<@8x?5hQtxIWJ76O)M_dmV=se{iPoH}@?$Tzj?nFHyfQhMN_0nuNl_}hWd z1M`-quRL@@dmG+p`nLl3IxDo8I5_;_Wtx>Gy;3zNJ5(yi)o`Q)(l8j^u+ZOhINd7m32yr7$GIo8 zC%DIX*-78&@GW=m3km#TS=XD_C#~-NOP?esNJ`@_R!|qqb$LZ(L|-7 zIU|gR3GAAKqvy_NbS$WouRwFeh%v_q*^o0VhO!9BwhvpEER*QzF*$z={{e6Zg~^O| z^z=~12#^ck+D9XxFqgp5-?8R8hU8lGqH*3<>X9Yz1DCIjY?wdLK+@XtyZi}v&hpu#_#DF3OFp*yWwY}GO->ON~ zbSgESjF8o6#in$i_7(Gt@rv`3I3s>=+qnjot=O~-w*%F)yRVs-d1l0{7C1im;Dh(O z^;|_@R`-PiR}ZMorY+8?2jayr&>vQt?{Crku%&#LsQZzX2PFMyz73=TzA}0U)Y9k( zG16oGY2Hs;k3Gz{(9ax;P3AVh5@a$+k-_LlcsTbnQzMW_D?%T_Nd!!kkVg>CBYYC! zYY2adkV42H;8u{EjShUo<-=y^_r|TT(T@#Bwv!HEfqyL*-!>mR?%^9wCAt68KmF>7 t>Dqlf55JGBz0(whZ~K|R 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 OYG9$<{$Qw1>VE+BBcvMu diff --git a/inventory/__pycache__/views.cpython-311.pyc b/inventory/__pycache__/views.cpython-311.pyc index e52deaf812a26310db20fd31ddab39642fcd9e43..04480929bd33fe9678b1b8abe2620c58fbd9d5e9 100644 GIT binary patch delta 49611 zcmce931Cyj)^O%#X_~Z6_m%D~B?Y>H>|5E_f^71lP)ZX@p=rxaK`6xluWDIj@v4KO z0*bOKC~Doo?V+NOV&0=h5m3?R4l4TG|8vewnx(1F|NECHr}xf!=FH5QGv}O{yKRT= zN}DcXZ+N&)0l$~7yQ^x*N82J2nQ2?z7Q3~ZsT)(66=rQssx{4&W=%Jx(|c%5hBeca zNzb~PP-~Vci=Op0+14CWjy2bmYwd38PGMm+dDb4L9#*5tNblh_`PQDMp7b06>3f-a z(X*kZx3$1jU@bHiT8m6Y5N21HBWsGSC8iQe5LMI1+Sk;Vo}+87vGz0dqvx2K{-*wb zWK7Kf(*XKA&@>SK#?}n74mJ&@G;uXUtV2yh={de;n02^mI6WuSjIfrPO6fVVW~6nL zX%sytLHf}{O{1-2Ok=ELO=BrAxn`VoylDbGr_@ZePBKlR=WaEVty4@>tYxM$>r~TJ z>on6e>$N873X9WQXPahInzR}zO31WZ=b7fwduC0!b-rmnJ!e5#6{ZU70@DI(rKys_ zvTMv%i^&4dIp*A&h1M!lm35J6k+s@XO<~<@7F(B?mRM^{HIzON8f7(E>A6Qut+mcn zN6*HZdh1ftQp%HGBRwJ{*{v&0E3J*DM(ZlmDr=LeiPH6ibgNCP>A6?UO;)?fPS3po zH^7N-TVq;7VFfj7t?Nwd=sBk5@20;K(VI;-!{5T1TdcR5Zl$=QnilJN(|V>56qf#r zH{bw+pIu?u_%Kr_4#GeAXWB#wZu7iD;?17tL&g4Sq2Q8cg=veq55TR0Vw}RU;>=1|@+9~H<6gLdwhC|M2emTb|Oq`-eKy)cYPw|UZn6?8o!Yu~#$U~zZ7NAP_ zC;uqdXvj6jGDWIUrP}YNkg*Ul4$3JDDCZuE9S^Y+Iw7Gj?XZ-ZCpIe{hN2I8Do~j2 zr96`$&t%9mHK4@%D0T|OmSKtZfav=vdMZRugXlWTwGXSIaQG+xOgkz5T8N(>G=3Mw z&w%)u6hA#6|89z(1@W_irb-w|KE3<^MP3JybD(1Xj(m{f{swU-%IKSKkNJ8SNe`KC z0Qj(ZF2KF!c>woOo^r@DAKMzx)cw#$rFMVfnJYSx^8gTeL8nmYQ5d$BP_!9}4kYp+ zinT!O!k|=ogyO3p-o6MD1orx)6kQF`i-Qz?*t`VVcEnr*@G-L$;N#|6fJXt*x=x5b zL1ooLSxbY|^rW4lMToWqsp=_;ZGhNi5L*W%^dAka6u%teZ>0FZ(egB)w4xJA&rq(F zkgL&R@7yoXQuHc_ZVH0&a}>K8Vs8q9@bgfiy;FrRKm((O=^GziT zE-3zOGY5Ez(rt%ycN0Q^bNn>L-vjYGJk|Kr;-J`jA@)9~#qM8C8%5p^kvpmAzyWuL z;&(y(Zi)}2#XA)L0K`8S6g4Mw?jGOHg_T61F#QvPAMy>R(0@Vb!<|CUn)dOd>;@y(h0G1l`4J zKA_m65c`BLO4NR8?RiS@BqVq$2uc?ywiRNZ4vNx6KKq8(+iO4#UO}WG9Lr-e?n=FLzj(fY{fA6!`_kz5%gsLhQ8<`%4*LQtU~HeXCO}%>S<_`fZ3l)hSwG`Wmo3?ZFm1 z3V)_=%nqQ!Wy;wGInM+^>WcXtNb{}P3Gh4fKLLJk{ujWjlqr% zJ1FpbD6rFd04YK!#Z^f01EmPy50FAjDSm_${|VBRP>THtVt=*=k`OZMDEb$O{xt{@ z^%VOX#Qq+n=rD@?qgerqjv`2WIL1R9qZ9(J{{h?&5QuOmQc@xnv@u{xK^lWQjhfPE zf~JXtib62n6a`OOdWyD`!gHvnLwx%`1|oEnDArxLo(c~O(vCPt8%}BC;VA-!B`v-1 zZ160;@Eqw`e&IO^7hrSD3`LI^*fo8IgWkwo(uv52SeRsu+O2izXIpB`b)pm+Js=`# z)G}K`oz)^vsWV$@jt+|Msbo57Vch1BkcPT)b9JTkZCtiy3=|@cmQv#L3n+DKr^c=MU(V+jxl=@ z1&y{;)Igzg@g;Q3ib_j;Lv>xPOKEEm#mUm|IX$(75M_)LS4qXWc^Y@&^K#<{bl~Aq z*DtE8wfLZen26i4NM;f5#h3dK+z-GO$J?%9ma>7ss3_Xbye-Mda)J4Za?}# z?t9AEX3T+U#AiI61NyS$arO5nCiBwNywXM8jS;HbrZ9{csMT5mG7E9qh zQ%hH2;zto22H*-UFR!eru-VGXZMe_MfZrOqlGow2F={*vgW1)V8wykfT7e-(O?s)ZmRZu zj5-Ox77hTL;rY3nb55!+N@MRI-BPrfO+$+94-ucmOwS>B9>EI;u-W1{0IqO1X(}x> zHRa{|nOr<79Y)9$dI^&va7fmYa=9B`Qb<=mNtC`QDefJtbfgRHcK}dFeu+;AewHTm z=_Z%(rNZ5jeWcbt$I@THB(EWO13;%vlJ4xAsb_$c_!g#VKKfGMI>CMlpB)I^LEuF2 zPXvLTg<)R$5)rBE4B`olLOO{4-6wv4VS5mqM{ohbMFfKpe28G)#|SSWpuW|6`&Rq} zLj(HtQw$5%mwJfs^kc`sJST+@Fox)$&9;6_y0$*^=)3`mEQhH2Z!GC^05*vB^wT#O zh~RhWo`LRu`o_~wNmB8kZfRd(l7PAoavN_bGGpm3Z>*-zHtTlzTC{{32_zd7x(&a%tq|F->*q74oTVnW@T|# zvz$1#F_iksrLD3wlrO9kt=j&8taRxyPEKwU&r9bvB~HiL=F(w$nE|*|l$Uyj z=1~AU_!-hS#>3PdC0c-;5Kr*b2>MrrZLV~FPul3HwCxS|Hnm0daz^!P(X<;252c

$%NoOH%G$uZ+PhjCJyagNhCr$x0%zjeG*o9fhdZ#TrW=*4E~;D2NNseY+ODjFWakFH?J!sRe& z$ne23letR6|L9%A&oa9NnHnP|)Kcp+aB$Vtig#eScLFf##D(}wJrIX@#3M*Rkcc1& zK{A3A1h}{wLu3+C|8=Z2Vl2eFw2LZg&9K1QTp{w4^kr#;hPYwX?IROesgyMGPS$+% z@W^Im8le_7dqP=8?K0~Ei?buCr@A|7H!j@N?U8?6;E2`r;&=?x0Hu~$Y~loX5ho&O zz~BL@>e_{ME`7DRys|3wX$vCw{ zBX^%vF*V)}b{2(E@6%7z7s~3|2A6I&5`T;+)`??aRdw3jh66_8f)Q!odi=`i?CbEr34b%Dw_OTGw(Wfv5tUi<$3C~a;JPD%^AoEO2 zxd#iSRT8Nz%bkRkFKMS>1!^qWW>Y~1U@~rWaC%9vPETPwr3=%SK=)^MgYLJ?s1#V4 z^v0|bmLvT-YY3Yoot`%>_d2X$4g#K;;6ve026W_L}s=?9pIa zP$@}B~W(0`iwbcz`8PpGp zRDC@xPc*z_p5PYnXgE!mKDn+JtCC{obZ6H|gXZ+n6aA5uG-gT1W@oXzM|aHGz&t~K zxG9?1r(?TjVBwMOxnx!>3tuzQlFi`Qp|oP<=KF`spVcg){)!zU~nmnm5`o&`_)1@Ss*^SlvkCH7c%>amrW zVg&+{KFZ;#qqh*N1=5)Ez92I+mXD+r#ofq=z%Gk`Moy)jN~;!~Fa(RB!l$RgeCEuJ5ao)h1b$X04W6HoScUHzcUiTV56pxLXqRn%KbawWmnCylyTPVc3se(LJI%Dm{Ql&qv$3VU~R?C?EAQH`lELqW&_ZdE6)EWqxsl!n*qHHE;O zZObLLJWKl7ks;k)KcGJn+-L~wGcRonh;cpumu?a4&&z8n7JwM}g2a{<8TVow?c0LN zi#stIL7Ze-+9V5uI~l(y2-A-iig9e#Z4kF#8#rdEdAQ{g??rF|5G0}0(|pzu6{PuL zOuE~a%7#ju-o?gc3Z&wqvH2t@hV6OY>f2lvdP41 zgG=tNQ0T`|bv1ROO{9Jx={>w7FhGVU$vp&d>$*=4V>E&RI22HZmrg8S3F<$0a3$<= zXT%+yf8%xP$Ws_th#5%gE0az%m0XJxz!i!Dr_4-fM^D3rp2lGwe1+bkDGP2d?rr}x zd_rJUia3$QxfCT$T)jt6)9O|E{ioFjCI-v;8fJxV!&E5a!1H|g3jxVfUC!hbn~ z$i_a>+O@ILIeTna!4Q-*E9Q-t~yR>S}pzgb{teCDj%mu9VqV(RHH2WBQB>HZLOl~6M6D^thF?K7yVq?WZcr}K} z-0U<)?Z!}|`J4EJ^~z&%06rN2xKt!VK82~l6G>qUgC`h+?w^YIRMXmI^=XKlbacns z=adt0%9Rn8lDg%y@l*zJjgi=1+JX@eMc(DZM3gdLXBbNS zLrFw&R|D*$-}-F!xMW&i1~b3zp(K9%SvI2IepQ+1BH_RG$^CU+nBEbPXUFkkofk>jZsk8#*M$TQ__Y_DRIOe zY4<)0(V-?!l8$Xk%-@6Ww5t7vProDh13(~Ye@4<~vSU)|Z5CoiVg$A?GUyoi7)!yy zC2JB;6dYS!i%O3GW<)(1z>x^epi9L&SRw#Hv0uvF{Ioo9-XSsI*Uh&vr?g?qmcn-t zEftX+#KHxOEuh-}6Y@(<+tPTNPSCS|N#a&y}>b43~kDKVTz3te!N=-tmiT>8yHS^MS(`8z_ECLaabBG zK~?U*N`?0%vEQW$_mo+%_RhPTfJRa0lwz@ZPv-=GukXN*Dc6SicgRK7G` zirz6&7S?`dWFB~U&?M=_9d{Sw{DWn^6dOU^@+XrIk~Zc_$9BX?_uU&QXqD38dySqQ z_P6&=WOlD06$)uV{t31)&@7=^yv*$kR=*d4mzu-`iP?lhVF9uhhBszFM^A<=5Na4u zt1O+`q2Z>*OfTq_(y9CHvJ@74%zT8EdB=>wr>Fp?M`MNX2ukcf022{`5*8g>ITY(w zpn?kZt)17&ME`@4Rp-U821~1VB?t;Zs(&a^I<;j|H>AHPKtBbU3R2u| zJXC}1g=w_-H%C-sdhg5*Hr&As5Ay&(th8(QSQ*U_0j(3TNm~IZ9<@KPm)TJ)c7>wV zRyJ$Wti|4g{e^d#A{_Q1N%sJ7g;-Wp)+_^!ptpxHpG#R$QzLp8E}FNX-tz!_a~FeJqw90f#sm*&~t`v+h^W;Lz^MriU0S$tW@-#$gU`a-n#D* ze5woIki9;4Q|@K8A~YO~29uoH45!w3Rinu3Ee(ID5EyUWL(k2i7Gkq$9rEnozQ%wc z!x=;dT5K+3{7FF01{eXG_vP`Kh^~jn=Sw>u9)nWOl@uXS`u*YWr+A5kQ^TcSDArj$ zBTW_Sk6qsTPNN zV!UZE^sb3QnzVIq6#uC^(@UrB3lkcWB(^YFI{ZkKbpG)$>G|F|79kmDrKhMCM|#Rw z9OZd3hd?RO(&vw5NYjpnt94Dv#j#S`Bgq=G9?>BLSQEeeDoZG7=W z=y*1V-zyx7kR8IM%w7pfO@kmk);mtdA{=V-21g*_ z11?7juky|nyr;MD@{7CR!;$Ca{G- z$_)7j>Z2RD$&q(K=7&9XAOh}R=B&j_)t3|uX(4L%5f3%TX!Z(DkH*7Mr z7~0c}5EkatrnGA#H-(+mCY{kHwP{lzz@bf%20r<>gsWObWa9R)eKCjP9fqPdLy^-^ za4!quQZv>5+^@v)jp}BmQwBqQHxNd-YBlV(a!F_?nTp*@OZycR$S3^G;WB+pZj6{-m zbc&dX)Wda34AvLamw&@pRH+6fdm3nsu?!jjSZ)B_pL`-ioev4-Nv8QnmZB8^4mnyIHQ3-hKATiJS11 z*f2GNw%r;ZvCq4|FU3wcj3DSPAqTKak`8h`drJE4x$%Fda?{EFXuvtlKFd{vH#A_i zqBZIq)*Ni1lGmvMAhU>IFV3zeFtj~ym!+rzLAF{hcwrFJ+=8XtCOzvH=s~K?SrElX=%Il#IY=Xe$>jU};-bSJ(-h%>Kcd0e8 z(w0|-L{LA{Y)yvT()+LUxA%hwui;<3244M`=tV@8xE?i^3L{QB7$ZIe0Fq|4)dHKR zh6-0iN5#v)38f}*dqA5lni|9i0av9${8hU1)y#03mqZdZIN81OYGw&?NFqpwp2WT6 zM_Vgu(Ig_*MLP*`4B-97(fHSHXFv{;+h6`iIXitc>qI=eVH{uyO3I0l2G)+c2C%wnj@+Or)FAY%iX8@Lqts^hFcgZ!k$)zQ8GMh;f=O#unnKO0DsUAx zt2?}{G+u8jY1dm>>;dVOw@QWCOuF#xJ^TiZ5T9%o%*sP5S(5P-x?0)9#4*yE?-HeF z4uwfsr=sz1_a=5o<6nCttjrAtPd0@DQiMp|PvsS9%fyEO$C)l|rQ2r~Mi&YduDA-b z8MH!mwJ^lcF{He_VP(BVvYjfiGgn5ZNI8kuNT!wL1+Tb5YsoKIayS`}+|_|U7lesq zA9L@($d+{)LuUZJ{n!VMwA)W-XyQ~5vtR0dx|jVzZ1Npb&c+s=i7jl4Eq2BhpN$=G zCU(GamE(GgBX&Sr>_TVk!j{kr`pC-)b!bF;V&>Vz9%mAJoQsUwr*=dZv_%#;BMZ(& z$Lx!9L>IP27doR0uP9km(WU5^BeNXQgWIA9JEI3*Q43K+Kz2xq0NEiaqGiHmogy;H zp;acj7p04*TSg%*eGGCqBfy2@1h$3vIjt^Ungm_B4mrB3v$1)%FV6;(T5cCB3kt^a zYC;3|0M<-%@en@I)O-Y=XlhdB0UI89mQKfUjUXJWtcOB7^ar4K3QJluMtZ2NLe@P^ zmx`_?@e60bW3A#$ky4y3NXKgv*%Q1tQz(!woax7uQo=h~(!t~L()>{o_9m5C7y>0W zsmS>c(j$wt*nr7`cFaZ$10)ac1{8;fms+kUPg2<$W3x1f;N9*~e9CJxjT6fE31+4( zum+w$me6&G6X&F7|Jg%RfGxZM-Q41(-~X9qhYrlh+tuhyFL9=iKAS%NO#1k?^oh>& zi7g>p^=;a2mm?IB2`v%C(mL}(Fa5o2uxm2ULoy>UA`;^P!T<2_J6P1Pk~LG>lXD!Z zgv%;}I^nY7uK}6O&J%du6qYD#V0`I=te9u4WU;WRx?zG)3_XEd;mCV2{DI*tP8#x4 z48Q3&rb*I5)%0spc=vv=CDTdg%mpf@Xh`6ve`DFzITz3&2#@? z8B()rx!VWn|1-g&NK8Qjj1?;pcZ>AW`ziLSuE`cwiY~I?`AUlw<`kc!n^wHw;5M!ZrTk zu*eDgqJd=$XoBU=9O8|IH?7}WsQ1mRyH|BcFJr<_jb@2F>Nl3y8?uBEOJbl~=osVX za11j?_=OpUNQU=&<;HX%u2`(|JgY|cTDj3C4Lk0Hc=8bCCmWl16NF?OBz#7JL$L+6?u3x85=P5+xLU(9aakcG>AavlJLhTU z7&`sTfa#6_(_2bgZrs$gy>ycuUgZCYYk|{twPhVd=h#pr$ zRpCa^jfcixj#Pl;HuP*v(V3W{3z-G&srmZ`I#aJ{PwKwwCTCJV{Ci`WGpX=$s5(0W zWH$gxMQrgEMMx}Q1E58FHBynDwX4UTo^5Fb&a{G-@U3Rh6}9&*ZP9{ueOG#$wz$3L zHS$Y*o3;lpKFH!GK9uRm8QqpO#+fyyO*_`99qZ7JJ!eSRZfG;~a2k3zv^_5ABc1xx zHhsENpT1_aTjM(L>9NO0KRv8XKhde5=ul0B;Y>Si^_$2grHZFg_=tHzEL+e2xWwYa zmF{B|$R3r*9v7@uHgu?46~I#i_@t^yX;yisw^>bmQfUt0haKTQoDfs426e8q`*;Q& z$B@dNN#JWfVv(~~Yns$e8lRIGNyX6WZM^jkBYzpzNq+1r3Ysk&lN|L^%zO-#X=n1Z&LB4Sj5FZ0JhR>JMGXI=g5reY-1qNk^bs91q*DZ7` z7Qa_0matL6Wrbpn_s_l_&is+bhdc9UIPzye)C6G?rih#@Tp^K%d&qQ)QDx2UuhIsu zhyj#=Z}hWR>T?L5N05ks6lz`W-;ZIEW(4aH+y!JJZ~$=_u7Ld{YNO=;+QSmojA>8K zhCO9_bnKc*?XiWh$BayFX<9S>vP!8Qep%5O$c5h}UH&9V>S>JN_aB54(>*^esp#Z- z?ZuY%y#bi*K+F)dB4(J@gBEHN5V6>THB<0ExyBu&He>Vo#WO5sh()~^Wf}T`vW$-6 zTSCo(Kl{fs_7=Ta=^x6c^<@cC*}rR;i}Vpn*mg)6ZzuBi5`?G}*h4HPff~zhQkDaD z@~=sG`?ef@YK#!U%QQkiGYkxQm*%IKARdXM!xbhUNh~MfQr1wjq^&maaL01e!_O2xCkFA9(w~U1PQmY>UZv#^eK6$>_c(99c;!n8Cc( zF=@;CBv~KSN#*J77g^gWpNIbo+D@`I1l0|}byslE8^H63>k?=N2##yQ++7Ollki08 z;1>nLWl#_d7ZP}6il9TFmsO(oQQuC(smv7?g$Xt_a1n$OE_L`n=w?%x^v&l=zoarGQSL!Z%9t6>;N#XF-i*Gz1W zm0G{ZliRyTHoOS`P@p=dDAFu63FT0V{A&`ViW9OJw6zz@;Y~9IgB1B<6d!C5!uSC* zi;|9fqf(=;V61fV%XIrr$m(IY)TIAFL0zuaew_9vNa@dM;aEO;gt-sVil|0@4;wcf zQUae1PrGl`KG6|g(iUFg3@=$TwmmjFY0cQ?DeWrVt&`SGT05l~rmVE`tDbHSeDuYy zeqb@X0a>Hq3SGJkED?0>@?Po0H~sBij!LtD<^xV4S6F3@rJ@%66448qBovo+q3r8v zBLjvjat2&qaIL32Fq!$7N=G6A{Dl;^6C{a6;sI!tE8J!YcRN3VCCVn=D{Z*kEo2>L z1y9^ZE@!dNB**1v5}P3;m^+iS`$|ly*Qq4D1DAlQMAIf<;J}?}3K7A_($y=a@~GG+ z@Zv#iinQU|LF@s3p@=0(AAI|-*<>WT6L9dDco!muB(ov);J_x(!AAN{T8zL+l@=q) zM+8OZ+d$>Gr29Ub{UH^6Z@FG>U#GAW81hTI zevFlbt35PWhxi0&g>MlKkSb354QIqAd?Mol;{Rog`JUQYb6*GxpD^TOI?Tf5fNK7)-#pjAuTf1Dw= z@R_4me!M0Gq@cV%#<5$Zx<8WDBv?z^|7ahGvOKhwtblYpv=AnR*YO_ADX4&<-MXI; zvEa`A%qa9#-|55)UHCx87P4`C7h@9>NMj?wfl4SERt|a1Zxrr4z|#5KGlfuLsG64u zY)UjXd**&6xB!EjZ^H_kXy)4lR={rK$MKJoe%10T z&Xuf>{ycUGZ6ap#^GY_6MeuwT`#C2ysP;aCUP!y4#djRFZj9oXv-+ z*%)?~H>+7;>N>18vdRK?lwj4>wae?O;fOrkv7|^)w>s499wlpTh4b{QWRH%<6n;3K z#o6oYYn9OIRF14t-3G4Dtui-dso zP48paIRqad@DkIGrHkhQxWdo|=EmD5{)FM50Pvi~ARSWZ(z<1Cwn`Ho`%L^AlcI~T zh@=uPBcNih;L}+E0Y@@CJFtlQx@b_Xd0F+ZkoK9@s0g+K4b7y9ch$Uc@dD+=^MBCc{xGKzj%?1rHqD}{0 zWU~E?NvQsj{*?WS>k^sKt^r9-UI;(LlxP!@=U>O#;0nPZSYNTy6=tmvmy}o7;03x9 z2@QN=6&6eT*k3TOm!}emf50#=O>t)Xol#8fASspYrDz!7^+)UJM0PC>KRE4tjQ~^e zx-^z4Q%xW?C%(mRPGi^D0|@pW);hAIy&c^Xu8)=q31)+YcMFyUWt*ZrPtkq{wL_!mWfDCR+U_5mqOK!ELvnN?jz>b9& zYXtU!&mzJnXR?eWWd1%om1s3hQll7JPX*4ey#L9Sh7K?)=F*}Q$9Jya86Y*@A zpVW=jxYRQmDi$u3TTX+8y8CXRmLGfE%X??DG-l?Lv)RZQ$QXm{vsb;n%4H9*d+64L)-Q9}bY|ZG?P}D`wA3!Ds2NdQ(g&nI4ngiKqTtEBcM0>^ z)Otm*Lpa1tm>wCqOYc@+(mCgRYAsPX28YyJHm!%+uwTVFOFRo+>3$h`TXGh_k3cq4aBaxsT?330pza0g3xBreJ0?Qpuy9!$9 zdqUxN^A)|>Z23&a9J*%=bSSHMVF8P0>-g9LmZ2_&WV`v20+_3GAIOx_Yl?~r7ByIF z!~%#C3jz2}Y+zEPWGV;lS0}=4BH%BEp5hN7*-J176*D!dPgjNTHH9qOFaVP756shL z#XPx)rA7{hJdb$ukTVwFdJv}l9Yt)C<^dpFCFAv>V0AwbOxYA>W@h1#((QeG@gnOr zgB&4TVRd3vMQwE>?V0d)m+NpM{RhX7#%JczYUEudyJCFr6|?S|RvZjtWNlQttc}V) zW5{na^l}<{oi+41W9ajGfn&beVd&Flus98tvxe$3hUzxM5~pE_L%W1VZxEL+(lPsR zc^oWVZWV@Ne+*Rvd`u(l-W>xx>_`cV&#GZyQc?$l@=`I>!%!E`6h}brE>4TO!lwGr z&3ElVtOB^}NW=xf^P0Qn3-SDL2~+cT`>;s)U^2$YM(!*Wsk$<9Z)M`B2Bj4BC75-j z%xjVbulYS`-ubV-LZ|HcKzPmw>lkg_12KM36gNIzJ-;lxUgPCq}GRku69? zrgE|cNlzt2#CEa(X__?BqmN})seNtZO=@2Y5WM-=ec;W<0&Wfko43wiEw&mQ@gWuY z;WVVe2y_3MLKYhc-D0)dbfbo#NKdqEx-p0Qg+-8wCxq`F4u14_I3OdQh4GuBSZE{| zb@DuU!60rxgLt~pCnVAzEwGUjRnbNs8Qsv+n-a`9QRZmACQgX6$DoBARw`9ZT~%FU zD7Xz(S!{)?R#!rQcl=PjhDQ4D1_1b^Ynf!!R}|{kxe`&Vea|Z z#8c5G?goF&CN7`Oz8&!QF$1kZp73`Bv>S+$c}AMdG{_~7=8AX=B>6eZJu@W7H{GJ$ zN!=;Yl+ADI%euR5+3~V1n-NC)alubmsrNaxUMlDn&FPfeSlkJHenMFl46sKh(M z&qijRiOk&9y)Dw{j5M~W&&6gtV|(mNIcpqz#yI%tG0#tIGmdi_$Gslc7CY4$JGCYB zTuhcTru(jyZ862pnBo>KSg4@O?HwIYLqN8nDm?Wx)Pj90ov8!clk)csb0!VKzx|y_eg4E04(9aS-UFcY?cLk7ndh={cP-kpq%Et& znFV*fByG=W)26o%m_Vj*M`qtP?KSN^2h!WF4#W5)v^$M&%bMWKn$V`5=+sVhXeWYU z+>zK*UPm0-UYCf3ZH7FjA+N)FRC;{u>!Xi@Wqi6*Ki#344qRQfjF&-gbh3=6^l1oz z!QuWbR(YPlPOgTNJ&ADZAl*lZhI2I<&JC+o4dI?tU^wU3on@(9I}x}#UOgz?|4zJ8 zSgeyupNmx?=afb~m{<#TZZ7W)+6PxhUT-*-1$wO?$jV>iMz`jpjx& znn(EZN^^v?W^lI%F9|)U7^OG?pC%&MidysFHM>-8+FYkL*P+dIThxQ_ zM36Y4`|u~dcXI?^HlB`Q_!M<;$^pNhIndR3MA~TZ;6<0smJ3eaM=}J)A|<_FQ*5y z9)cl++tcCjY5WkDOX~Qp)GycjH|QXY*seDeb1*T2&=9_5h)4f2$Fp7N$uoztzXjF5 z1gj>1T63{*1hFBsLpU?kqkowz>jboYS$V5v7_+fS5y&D!WiMRPtl@^(J1=EzIMV7Y8L7=fdP;Rb(*RgYB+D z@F*@Fc#o1R#BIG4zrifDL&v?0h~B%du+eoE8+gEv!3$a44xO&B4t+76k|W*hZY)U) z>XhYR#juHMaTi8Tof-5K*YSJCvTmBCQ0DZI*5}8v2L-wq!PjUZevUYya(=(>y%&VI zcdQ0z6iCU9_6Q%nJC%b1zEQD4);VMUsDe+oXOJJRX%klOH2J1;;#WMC>(T}DWcj!`~%yif~Q7) z+xsk4Ss=Rjftf7dP6S}kQAT4>YtT;Yb=p(ur^&c_w^QW1Pij~yWiKZE^PV6R5?PO; zF!3Jp#QQhm7LD&@f?JLFlKqM7C1e!QV^}BxZ=Vmw93LVeGn3b@LYp(PSdjo?2s9Z` zcVm;`+(u=st)c<1p(ea(+@RVd&=PeO!^jf#13cLbP%8~#FAm@C55pRx*CTn8xc zYQ1JQ(<ThiI0C6{z>!&2cI(!x>!Y_z*;Gl`+vMapJ#QIG| zh8slHMJ0Kc+CN{Jnvuu|z5vJ5-7&oSdR8KH*5+1F-b-v0Eg79oH_v(Y)OXH0dY=LG2MsDOER2(|&}Oqb6V zuzYJG&_%o*6A>LcIU{)yO8!$ibgl2_SU7?xEnibfA7!Bc+F|prRKn@8_8pHs-?raG5zlxP~HDPg` z^pTDKe8S!fEf5iuXnFb~HbS1P_oCEM+xpHT)`yKEh1Mz$M)Cm*oT@Ih8NQ;j=r7FJ zZhX~TSgFUrpstz22Tumx)x;$MSR2|@TMr7$42rAOIY9OuLbfmnvETk)@4A- zc|K25SyvH!EW-S0%q*3CCHROeAz3pCQJCO2UyHjqN$MqI2DZIRq3*v-)d!Hk2!>(R z4Nw%Q-#q`dhb68V!&k3hS^QiL8zmF}0a@f5Ze@1X)OyUyZWY)iKCYfE$-rR*e($)( zfeC3o@`sf`sSe8!chs{nf?3NGma?JnEg^_s1!=)C;U-?Oluhe~1&Buxr6&M%Hd@u(6bQVyLh&msdeIM?J@v+E`u)9?7tc#V>$lwY~%aY!Pvgut4` z?rdVE@+3aVQ&zJiHna7b)vQn_tWPBKkgS-!X=q%$IpI)-zwM_fZgEfgK1^tNFQ^`W zJaxJ-FxG51lF~#ol0piT0Bog$EUXdKuy6y8SP6woYDbV{5W1CU%C-= zG>TBZVAN`F2dITdO%f&h%G3sOiG4!Hxg@CW2d08dwh2={i=yp<+3&it$-)*d$ zF%v6B*Ex_6=HoLmeP8*&&0Ay&tNVpQLwWLMwg|pSN7XRKH*RJH(+YjmwKRQqVaM!7 z@Bo4;1YXlRdFv5RFMtTRsNUA`-JMcIV>}Pt!ZPf=;n}5z%fH}a(w-QO+H`sILFyX1 zQIM3-)fh{i2xJCUjm>c4lL5Q)3k2`r>&F;DlkgHg&A_k`2&fCP@QJo_TQSE-WV!OC zyWyC+5MGTb^0tixsUsMF8j^xVFKxg?Ujk9p4Vty@`6>^e+-1p^QqN1ppbD||F}g1T3GUhlJcgU{p* zZp$0$%o}<(Z}geG(XWqoJyR`VbOS@-SFcH zZTbmL{RD?<0tnN1O(@5^Ciqu(v4QMI9`z{b3r28uoPm(Q?q*Z$sB?k)`L&f6_i>En zh!Rdn@bSYQmgP>jbFA!hjt=i4nr`H7qdq^6uQUW`iNiJ2vq3tHQ9oj_L|eZNlD1<# z|L5H>yC#J4KkjDV5~tnY>FS(dj20^jzU@({AO^u`-u4)5v}W#LLu7WV;KlQWBw;gM z`B1`V&l7U^q~36XpfOX(O;EzE4vIRypq(TWtmq+q=3{axj z_hLTpw#D~a2a-TWM0nN)ql?r`BFNt5aY(_B`l)Eb}JQp_*xU_(8#rT@KXT%ct~BP%kA zL+wE#()`d7pO()uA>RU5Bx1YBt^HPz1=!Jj__q7O1^q~|pyx*l!4KUQ%74F)O&ZmV z1rq&fXza$`rfI11k)gdEy&p>l;wv(|Uj2O2{VYeb6uVjqo1p0qodqu3ZF^ZVzh)n^jq*-P;`j@(VruCZkW#i`N*G4- zj~1veF(L%Z)FJ?B;fsB&aLQgt^fn83Z3``O|?BFo3|tIbgp|YS19kFb>^r6G%(VFAiq$!c(EBR>9g zvIPFv5q74F0UL}~T@TniY#M^+all@yX-1^;c-zykyq7-CZeSBp@wVUn1r*YY1#~nD zLnsJiMp~dr_@T8KiuK_tpYczRvc7O2wA&MG+FYy%mLBBxKBsTJ$fsh20(lorxl(*3 zALFidbG@KG5rLDx@dPWE+tQ2L;@MMY@JBP?SmfWIWD8hteteK{Jf9Scg_yMnKmaGi z${I^b9ee-{@>6IVlk%oem5xJ^O~g)yjG-Xoi%X@3{98DD6)P6ap0mmuC7P>IgpMv!7unPCS%?by#oAg!~vMXZF#ai$CfiYQ4ob1 zkQj+;k-n|MigzlO*TE;?eApiGu@2tn(&K5O@)`^1KSZx;5ZDrpONP`Sc{IqlL`_kDjK7wS1L{nP(D{bd~;ru!TK_5BDEfW$%Ab_Czyq+ScLom3>d zUSy)owFaqpO(;ujEk4FxXL=I)kYkHRu6l{($yCEVAl$-Eiw5CHv(&q2(6TTRQ3+Ty zXsMu8z`M0U+WRdPL^_(+otKJK*s^*|i=L&T6wot3AKO0Ww>1L0`rswj28VEtyv*JU ziKhnKf~X+U?pwHS;k(~t37Hwt7kDPAV`m#WY5aw%~2%aFz6QSrY&QiMDL7 zU?r~ta78Ywg)h9}=~=f<396-GhRbSW7JvI7xTnfut}J(#_=wrmIYjiGNCyz8trB}f{1hubfKSLvTpAqd6(W2HRJQlZLL<0#q)h)HPkO}rfIuOgAKRK zuJ8rbwdQh<*dT&5!lO>Hxa5&oJnl_oQH5?#c@CR1n~ylf((Hv04;MJogeFFb6!bZx z=AFE_j=FTDp&@03EDCxh!!|6Hw$msw%W@+v>NJYJ$JkGxG8?+lXLx@6+$k28vJQe= z9VT+OA#?_iBVE_3I?Y}tOQ?GjJVt}_0faT|}+o+gQ?vsCJ3Lw`joorQHFSgzwEc7W{t<3BxO=`7m8s?LDlHs759 z`_hcJ<9Wtt*nn>Rh|S>B2E!9C5aQqp$tVsV_zh!vzV;$ZF{qn-?hRP2k;d`%UlhpwRW27JGSFo=%v(^y7@qMy%a8Q(YjSc}&Q0&L%jBY*a3-f^%>#Q3Gi`BqokcCF_{@H;8o^!qABYj!ie9@4WaFkNSYcdkAFR_Eq0DGc8-JoZ;wm5 ztYA@?B4^j^eY20ue7YaFd&f?9#!h#{PH+ACJQR@fT1jc#IIZG@RyUq0PekXA8=^ch zL=Dey&gROkv3pluWNfZ?9SYd7kP3(h;6A(RZEPjrYlD9ZWT3J-$KY<&WKdF4o6HdZ z4FA`MfQZ`_X!1uagK0^&W8zib@G+Y+Y7dgyJ1WSTW(1P5Q|(0lDkxN31i+_uZn(q} z)YTC967PA5-3mg+(Mzn4GR`|_QOFQ)fE0~G`03~25LE1EtoL{vzMh-Ah?&yRn~PP< z0|1Ux?nBBt917&gL%TTYZ|?%Vm#_bf6^*|SvGxu{8hSJcY5a9asUSsoS2-F@PXP&h zo5Mb5$?94_;B;%o=d4uFHcWs4(CmL(gTX zlk2LwHdTFwHGK}iSLUrp;v)DGNBcC0^^kCD4AC)>Ve=#K#`ZtfBlYa z>q4eLf{FnxCai+?<|=G00=1sM|2>;5_t`30b1?2ITf&B-Po_vb+^aGm0|zk^YBlYU z!Xce!61c}CIOcxy14|Xs^gQB6Hnoe*SOCVPt=1x8NKvi8>R-S{l_DVJLDxI7Td_R| z5|CIX$l)_O`PbhwE&tmuApCsuBO5Ar?X4>Oa98W3|GAYQ}(d*drgCi0iV-3~zAF?1w=04p|np`cNSq<))tn+iP6a`pV;PvElw zwi@_s7hm@?yS}mo+q51)S!Yd45ZZ|wF?}$y;XnnwHUM13#4VT(L7^T!+Xu*fzlHjq z^IzD~sdA;A>@ES726Rq9E!(gb1pV~C)Fgzk5uk z3xVf@nUf*?RznGXU!S8Pz7yL)g2y6UAG|WhUW{0bVdS)lMw?(Jj#LQ7lI1#TAXSGP z4~rr{|2vD<-3jqSa5S}Yu*e#Dk3ZP$?)C8Kqi65!)CN()0_(8GJN^sO^_b{?8)?Yn z#d)a!>z*IdzcFxC;!yKsJx>*cmtir555&C9?5B_>wEx|W6vcjmEs2+Hd8apZu!P9% z!93>?pp^qwCt89IW56c}hzFd6rw$a{Qy*DQWA~}`^>tzcZuM4<;=R;>*nFg)kdrR#!HbFtK9{4kABujf}n1oNBE*tbQcNx{aZk{#=7lAQl`r=JxV~Q7|1JeQtilcaXn|_8< zKf|G#0n-|#iq?DMh1r6A6r_c7Erh}(#Ay%KQ-#305)d-Pv4zBF6AJKxX!Kjl^S|^zh+4O`4zBEZlgX`3`CJDE8Z-#XHgMZ-oJW@htH+*Qa zkTTB8Yf2H|JKlOZMW|uf zFJss%2>t;eXjAx+6d`VW!9qC7FMo*RV;FSe3Cz=s2)>R_fxD=;Fc87}nD|Y6YsSQH z$vi7RP3RX=k9*b}72dr2WEY%^h_eSX{we30lMbBgTjX4${*-BXY3*gVT{5lHh%|yP z-At=zhG&AEmiG@$8G?mPCCj7lmXF2@+5dh)%saN>p5a5o?J!0K89tx!qAVd_^Ba)u zyNS5A$MI!Z!oUtWV&@HP0)Mf;5XzIYg;9edVDy05(>tK4N)jtNhHdb(BAjOnIf5#T zzmP2qTY#O@*^Ec7YBV-;5#3-TliJz!cszqdMDQb@n^E77`X225HY?29Lz$ zPpNdIl=vc4$rEzy30R6tF6GY&(*1u(kaJi#0v%TMo~J4bs^qVI4USuMThP=V z!bm}$9Etp351}Fk8vv>q->&BAMj;`(vm$|yHv&Pk!+4!h=uP|RAa10v$;~RPkX`0?Z51WxL zBjR`T6p|)3L+T)x`jA#OV6_Y;b9{mrBj^#vf9xq_WxzGo(U;*G>p&ngrcX!%g3g1* zd|fZ0FarbXS0vN@4XBVWX#^{VImF*-xiMV+7z2F8MT;tT`2GSjhvJg}pN&DC zx^&<{U6fhp<9(zDTTbiOy@g`7AOpvSQohho1&GVew6yUC&CMhzhW0l;OJEF=hxY&E zXZj8%L4BL-WZdce!vemxP#7Q#4dc%h3fp1Lf2nUQUsNQtPsXZIF-4jGYE5Jh?NrH= zd{eQ|Ul^Ykv3(fh|9P*20;h{B?1&Lfm>A}zGO{&0hbc0+`H1#ib2-IDU=Zt zd)IT^l7Pd$ce{uE?NZ`}sP1|)AiV~2o`j^n=Sw|1KsYHcC3wSIdgAAxuQC^&aqP5dZhiUnvvUV)i9@8o9Ox@MA&Fmjm$Lh$abytF- zwzbdi`8L_jCK>xjr_E%3`+o2Beed)aYzJ>f=*C1Z-d_PQ#q zOXZ$O$!pcyHv9PlKloPPR)6XI{?hqZT3&1V%`$((s{V#m{?b*yyW3yT+F#J>x3xZ= zI8ZiMch}G?8PlWrZDWlM6m)D6i;qw^KuwbH+s@QdYK?X3gzBK>KLc~*d}LB{HasZ$ zAcgwTS~{mTL2Tt0fLozD9g$Qo!USJ z6%bq5f~1duhRa^|Ww>IO-0{dJS9di~B6TL|>bWddJ~SKLdymRIQ^qQLzi*&B^x_P* z-F|A0s#|KRmn4iJtDLpWpmL(g4C1II;5d`Vk$F@=cO~iP=h0g86mZmHFVZ%At~~Z! zDtjBzNtacgOs%rt9Djbjj%opHLO0Z$^G!WiLpFVMK5bDGb!a|oe||EbGULt0x;{o@ zEz-}_Q;uyAS=|7929O4PE&nFm#(5D|L;X|zK7S9l($nK)H}G*c2= zhUeQ8B&m5&;yv5I*Ws+)%3e%Vq9;3!7-^LlPTM!Eb>!e=O#@{oMOLv7CF#P2qFipZr=XwrbDm5mx zBYS4y@kqZKX788`N?9igm-2^5hP^efPh~46qYUIwPQQkRDxVi}#6XttQilxW?sVz< z8!5hE0#9kDP$uXruvm0r-ucaa)xJchKhfEr=+xhDq?u~2ezTE^Qadho`ZDVL8Fl>` zb-tuJ9oIxFb4xCk`%;J``^&S>Vc_Z?vFgAYEm= zi(Hv>GXv4&1{@}RWh2iHVhr7ytOwT9fg;HlB3Y(ZQ|v6mvdKLgsKE9fa(ozIS^(GQ zH&A8Ku#}at46n6wHoOLt-QD|$dj^Z7j12yU>!=Ty8SKPmeXO7Hh+2I5gAbDQ?(@o~ z&p3G>!*`#q=}_nB33_BHS2&qw#;Z!&ZYqJB&|JH`f6UL>Ppt z3NG1@yofBZlJl4=R#~EQ6t>BNI3iLPS+R;zln8jqKo@~^^F070aEg&W9d zMN`dWKQ`Va)K1##5_<%0VQsn&wijz^KY4gcLsHQW`3xT^B=II(k$(RL9=`;91%Nz?h@WQ!4_X44ScDZ3(OGbcph7^)uSHnKQBftAU8{#_L>Az2f=)jQ}}8k!aV z+|Db;zv<80`5fpOJ#`n&G7mnz-gUd^qSYg^dQi#as|2Ko7?q|RkL({B@hCJbGEJ_B zA0`{Kugf}6==~D-37_df^eE{}u^J0(ezdD+Zy>JQ-N~FI{lFedFq<)ztz@zIA!H#; z!^HVqzO~8T7xvI@#m)1&LoJzQIM7R+fSKqU{2J~XW_`?tFW_Mw*iqJuIaMu!#!fW{ zL4Z@EQq3Jd)jR|Nz8jOO-l!ix)dBNSb z0(l*Gv6AHeuynMXH@cleDv5?2@$&S1?RESYI= z7wZSRnPFc7cPXGu|EQbFCzrE3U>liL*M4KVzQ(W2tUzcyo0RSB>ghBtAl)^c-^0DG zQZMSEY_{(_$;GpatA{448TvatR5HzhG>K-8EL_{`GFj*7FJ>p4t*`X($wxIjD)l>@ zO>Pa+WQNngaJAbhS5|cG()Rr{#beAz^ zU1;=Wa4iR{0F-cpo4azM#H;lC`}yd3HEOCbaSg{{eIIMb%;5x>`rzaI^4d~aGF0x8?u=)TpHs} zCoILfoe)G}tH8!~gyWcsrGy}mFXX8go{8-{-CetyaMeL)z`A^O^BUtJywNKuZr|_W zZXnd|XYl0WSh@5+yef$&Ed7lZ{-9 zV&Jw90~b^nHb6RHG9cdrgmru|DsNQ5C4@=njF1hX0=FWd5zq=)57-FU1lR`H0q6vD z0qzDs>`lydiIFEUnIr~%!~_rQ+VJEI>oQ`SMeK)&l?t)uU|dDO9{?eMg=Z{L+Z4?| z(RvddG10veogz`j5nU5g;b93;QBCx&RP+GdwQfJ%D=w4+B`hB`kCTaS-Ea zfChl8E&O5O;|e2Gc#*=wGhRmMD**6qglQsd2RSyEb747nm9tDauHpSYk1^Rt8rXOl z*kl-35*V0#%^4HZin+c%hMsto;md>uJ`p^y@6LtBY7XU|W^rHEm)&#+1xfpQ*%ISh zy)?<1U{P~)Q7ZAV$Ec3jfUdoU2B;uq0_b}O_ zX80^sK7H&U^`;M4=J-bbdv6}3a^=WT(}R}L;L9xQV}s8eFc=A~_1=D%TFH|>MXh3M z_+#VQ6(I>3j1Hd{r&>5g6ei^=W@-zGirf0KWdYqi8sfrb{hoQvlK2BFuVkLY{@Gdw(zg299j!se~|2R(4EdFUb zNp}7@e3EMT=g0gsEyRU$uuX5W1u0pr=l24`uMNS=`{7B-P@V+EN6#YwMNNNvp8TM| z>Ea4zPg8sv%n$-ZTxgbD@f(bUuHbtOxbhi7fQZYNQ_)v1euEO~k>Ki~Q6Sx328FnM zdCp5wLqYsPwUbm0`bQ1=LQN<)4UY^VK#(=f$rhr6N;PqzfKajFOdq9|mE N(_cM8Pg+42{|!95#Yq4F delta 44109 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 VL^eiO_E`dQ@jhi&sEah_{{?y}KrH|O diff --git a/inventory/mixins.py b/inventory/mixins.py index b7762382..966a8666 100644 --- a/inventory/mixins.py +++ b/inventory/mixins.py @@ -2,17 +2,16 @@ from django import forms from django.utils.translation import get_language - class AddClassMixin: """ - Mixin for adding classes to form fields and wrapping them in a div with class 'form-floating'. + Mixin for adding classes to a model. """ def add_class_to_fields(self): """ - Adds the class to the fields of the form and wraps them in a div with class 'form-floating'. + Adds the class to the fields of the model. + :return: class names form-control or form-select """ for field_name, field in self.fields.items(): - # Add classes to the field if isinstance(field.widget, forms.Select): existing_classes = field.widget.attrs.get('class', '') field.widget.attrs['class'] = f"{existing_classes} form-select form-select-sm".strip() @@ -20,23 +19,6 @@ class AddClassMixin: existing_classes = field.widget.attrs.get('class', '') field.widget.attrs['class'] = f"{existing_classes} form-control form-control-sm".strip() - # Wrap the field in a div with class 'form-floating' - field.widget.attrs['wrapper_class'] = 'form-floating' - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.add_class_to_fields() - - def __getitem__(self, name): - """ - Overrides the __getitem__ method to wrap the field in a div with class 'form-floating'. - """ - field = super().__getitem__(name) - wrapper_class = field.field.widget.attrs.pop('wrapper_class', None) - if wrapper_class: - field = forms.utils.safety.mark_safe(f'

{field}
') - return field - class LocalizedNameMixin: """ diff --git a/inventory/signals.py b/inventory/signals.py index 4422d3ae..f550dff8 100644 --- a/inventory/signals.py +++ b/inventory/signals.py @@ -689,7 +689,8 @@ def create_item_model(sender, instance, created, **kwargs): item_type=ItemModel.ITEM_TYPE_MATERIAL, uom_model=uom, coa_model=coa, - additional_info={} + + # additional_info={} ) product = entity.get_items_all().filter(name=instance.vin).first() diff --git a/inventory/utils.py b/inventory/utils.py index 2abf4681..c0b28e3b 100644 --- a/inventory/utils.py +++ b/inventory/utils.py @@ -481,4 +481,6 @@ def to_dict(obj): obj_dict[key] = str(value) else: obj_dict[key] = str(value) - return obj_dict \ No newline at end of file + return obj_dict + + diff --git a/requirements.txt b/requirements.txt index ae0ef94c..4deb40fc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,10 @@ aiohappyeyeballs==2.4.4 aiohttp==3.11.11 -aiohttp-retry==2.8.3 +aiohttp-retry==2.9.1 aiosignal==1.3.2 alabaster==1.0.0 albucore==0.0.23 -albumentations==2.0.0 +albumentations==2.0.1 annotated-types==0.7.0 anyio==4.8.0 arabic-reshaper==3.0.0 @@ -33,7 +33,7 @@ ctranslate2==4.5.0 cycler==0.12.1 Cython==3.0.11 decorator==5.1.1 -desert==2020.11.18 +desert==2022.9.22 dill==0.3.9 distro==1.9.0 dj-rest-auth==7.0.1 @@ -53,13 +53,17 @@ django-filter==24.3 django-formtools==2.5.1 django-ledger==0.7.3 django-money==3.5.3 +django-next-url-mixin==0.4.0 django-nine==0.2.7 django-nonefield==0.4 +django-ordered-model==3.7.4 django-phonenumber-field==8.0.0 django-picklefield==3.2 +django-plans==1.2.0 django-prometheus==2.3.1 django-q2==1.7.6 django-sekizai==4.1.0 +django-sequences==3.0 django-silk==5.3.2 django-sms==0.7.0 django-sslserver==0.22 @@ -72,12 +76,13 @@ djangorestframework_simplejwt==5.4.0 djangoviz==0.1.1 docutils==0.21.2 easy-thumbnails==2.10 +emoji==2.14.1 et_xmlfile==2.0.0 -Faker==33.3.1 -filelock==3.16.1 +Faker==35.0.0 +filelock==3.17.0 fire==0.7.0 Flask==3.1.0 -fonttools==4.55.3 +fonttools==4.55.6 frozenlist==1.5.0 fsspec==2024.12.0 gprof2dot==2024.6.6 @@ -85,11 +90,11 @@ graphqlclient==0.2.4 greenlet==3.1.1 h11==0.14.0 h2==4.1.0 -hpack==4.0.0 +hpack==4.1.0 hstspreload==2025.1.1 httpcore==1.0.7 httpx==0.28.1 -hyperframe==6.0.1 +hyperframe==6.1.0 idna==3.10 imageio==2.37.0 imagesize==1.4.1 @@ -110,7 +115,7 @@ lxml==5.3.0 Markdown==3.7 markdown-it-py==3.0.0 MarkupSafe==3.0.2 -marshmallow==3.25.1 +marshmallow==3.26.0 matplotlib==3.10.0 mccabe==0.7.0 mdurl==0.1.2 @@ -121,10 +126,10 @@ mypy-extensions==1.0.0 networkx==3.4.2 newrelic==10.4.0 nltk==3.9.1 -libquadmath==2.2.2 +numpy==2.2.2 oauthlib==3.2.2 ofxtools==0.9.5 -openai==1.59.8 +openai==1.60.0 opencv-contrib-python==4.11.0.86 opencv-python==4.11.0.86 opencv-python-headless==4.11.0.86 @@ -135,8 +140,8 @@ packaging==24.2 pandas==2.2.3 pango==0.0.1 pdfkit==1.0.0 -phonenumbers==8.13.53 -pillow==11.1.0 +phonenumbers==8.13.42 +pillow==10.4.0 platformdirs==4.3.6 prometheus_client==0.21.1 propcache==0.2.1 @@ -164,7 +169,7 @@ pyobjc-framework-Cocoa==11.0 pyobjc-framework-Quartz==11.0 pyparsing==3.2.1 pyperclip==1.9.0 -pyphen==0.17.0 +pyphen==0.17.2 pypng==0.20220715.0 PyRect==0.2.0 PyScreeze==1.0.1 @@ -174,6 +179,7 @@ python-bidi==0.6.3 python-dateutil==2.9.0.post0 python-docx==1.1.2 python-openid==2.2.5 +python-stdnum==1.20 python3-saml==1.16.0 pytweening==1.2.0 pytz==2024.2 @@ -194,11 +200,12 @@ rich==13.9.4 rubicon-objc==0.5.0 sacremoses==0.1.1 scikit-image==0.25.0 -libomp runtime library==1.6.1 -libquadmath==1.15.1 -selenium==4.27.1 +scikit-learn==1.6.1 +scipy==1.15.1 +selenium==4.28.1 sentencepiece==0.2.0 shapely==2.0.6 +simsimd==6.2.1 six==1.17.0 sniffio==1.3.1 snowballstemmer==2.2.0 @@ -207,8 +214,11 @@ soupsieve==2.6 SQLAlchemy==2.0.37 sqlparse==0.5.3 stanza==1.10.1 +stringzilla==3.11.3 +suds==1.2.0 +swapper==1.3.0 sympy==1.13.1 -tablib==3.7.0 +tablib==3.8.0 termcolor==2.5.0 threadpoolctl==3.5.0 tifffile==2025.1.10 @@ -223,7 +233,7 @@ trio-websocket==0.11.1 twilio==9.4.3 typing-inspect==0.9.0 typing_extensions==4.12.2 -tzdata==2024.2 +tzdata==2025.1 Unidecode==1.3.8 upgrade-requirements==1.7.0 urllib3==2.3.0 diff --git a/static/css/appt-common.css b/static/css/appt-common.css new file mode 100644 index 00000000..c0a616fc --- /dev/null +++ b/static/css/appt-common.css @@ -0,0 +1,452 @@ +.djangoAppt_main-container { + + max-width: 1200px; + + background-color: rgba(248, 249, 250, 0.4); + border-radius: 5px; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.1); +} + +.djangoAppt_body-container { + margin: 0 auto; + max-width: 1120px; + padding: 0 15px; +} + +.djangoAppt_page-body { + display: flex; + flex-direction: row; + margin-top: 50px; +} + +.djangoAppt_appointment-calendar { + flex: 3; + padding: 20px; + + border-radius: 5px; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.1); +} + +.djangoAppt_service-description { + flex: 1; + margin-left: 20px; + padding: 20px; + background-color: #fff; + border-radius: 5px; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.1); +} + +.djangoAppt_second-part { + margin-top: 10px; +} + +.djangoAppt_calendar-and-slot { + margin-top: 20px; + display: flex; +} + +.djangoAppt_service-description-content { + margin-top: 20px; + color: black; +} + +.djangoAppt_item-name { + color: black; + font-weight: bold; + font-size: 20px; + margin-bottom: 10px; +} + +.djangoAppt_calendar { + flex: 3; +} + +.djangoAppt_slot { + flex: 2; +} + +.djangoAppt_appointment-calendar-title-timezone { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; +} + +.djangoAppt_title { + flex: 1; + font-weight: bold; + font-size: 20px; +} + +.djangoAppt_timezone-details { + flex: 1; + text-align: right; + font-size: 16px; + color: #333; +} + +.fc-day { + font-size: 12px; +} + +.fc-daygrid-day-frame { + height: 20px; +} + +a { + color: #0c042c; +} + +.djangoAppt_slot { + margin-left: 20px; +} + +.djangoAppt_slot-list { + columns: 2; + -webkit-columns: 2; + -moz-columns: 2; + margin-top: 10px; + padding-left: 10px !important; +} + +#slot-list li { + list-style-type: none; + text-align: center; +} + +.djangoAppt_appointment-slot { + border: 1px solid #ccc; + background-color: rgba(0, 48, 124, 0.95); + color: #fff; + padding: 7px; + margin-bottom: 6px; + cursor: pointer; + border-radius: 4px; +} + +.djangoAppt_appointment-slot:hover { + background-color: #fff; + color: rgba(42, 42, 42, 0.82); +} + +.selected { + background-color: #fff; + color: rgba(42, 42, 42, 0.82); +} + +.djangoAppt_next-available-date { + font-size: 16px; + font-weight: bold; + color: #333; + margin-top: 10px; + margin-left: 10px; + padding: 8px; + background-color: #f8f9fa; + border: 1px solid #dee2e6; + border-radius: 5px; + width: fit-content; +} + +/* Change the color of the buttons for the calendar */ +.fc-button { + background-color: rgba(0, 48, 124, 0.95) !important; + border-color: rgba(2, 76, 157, 0.85) !important; + color: #fff !important; +} + +/* Change the color of the buttons when hovered */ +.fc-button:hover { + background-color: #025bbb !important; + border-color: #0056b3; +} + +/* Change the color of the buttons when active or focused */ +.fc-button:active, .fc-button:focus { + background-color: #0759b2 !important; + border-color: #145294; +} + +.djangoAppt_date_chosen { + margin-left: 5px; + padding-left: 5px; + font-size: 18px; + color: #333; + font-weight: bold; +} + +.djangoAppt_btn-request-next-slot { + margin-left: 10px; + padding: 8px !important; + margin-top: -30px; +} + +.djangoAppt_no-availability-text { + margin-left: 5px; + padding-left: 5px; + color: #f00; + font-weight: bold; +} + +.disabled-day { + background-color: #ECECEC; /* light gray */ + opacity: 0.5; + pointer-events: none; /* makes it unclickable */ +} + +/* responsive */ + +/* CSS for screens larger than 1200px */ +@media (min-width: 1200px) { + .djangoAppt_page-body { + flex-direction: row; + } + + .djangoAppt_appointment-calendar { + flex: 3; + padding: 20px; + } + + .djangoAppt_service-description { + flex: 1; + margin-left: 20px; + } + + .djangoAppt_calendar { + flex: 3; + } + + .djangoAppt_slot { + flex: 2; + } + + .djangoAppt_slot { + margin-left: 20px; + } +} + +/* Select design */ + +#staff_id { + width: 100%; + padding: 2px 4px; + border: 1px solid rgba(255, 227, 227, 0.89); + border-radius: 5px; + background-color: #d4eaf5; + color: #333; + appearance: none; /* Remove default arrow icon in some browsers */ + -webkit-appearance: none; /* For Webkit browsers */ + -moz-appearance: none; /* For Firefox */ + cursor: pointer; + outline: none; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + transition: background-color 0.3s; + position: relative; + font-size: 16px; +} + +#staff_id:hover { + background-color: #f6c6c6; +} + +#staff_id:focus { + background-color: #d1dbff; +} + +/* Add a custom arrow icon using pseudo-elements */ +#staff_id::-ms-expand { + display: none; +} + +#staff_id::after { + content: '\25BC'; /* Unicode arrow character */ + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); + pointer-events: none; /* Make sure clicks pass through */ + color: #333; +} + +/* Styling the options when hovered */ +#staff_id option:hover { + background-color: #f0f0f0; + color: #333; +} + +/* Styling the options when they are active (clicked or selected with keyboard) */ +#staff_id option:active, #staff_id option:checked { + background-color: #e0e0e0; + color: #333; +} + +/* This changes the background color of the option elements when the select is open */ +#staff_id option { + background-color: #f8f8f8; + color: #333; +} + +/* For Firefox - to change the background color of the dropdown */ +#staff_id:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #333; +} + + +/* CSS for screens smaller than 1200px */ +@media (max-width: 1199px) { + .djangoAppt_page-body { + flex-direction: column; + } + + .djangoAppt_appointment-calendar { + flex: 1; + padding: 10px; + } + + .djangoAppt_service-description { + flex: 1; + margin-left: 0; + margin-top: 20px; + } + + .djangoAppt_calendar { + flex: 1; + } + + .djangoAppt_slot { + flex: 1; + } + + .djangoAppt_slot { + margin-left: 10px; + } +} + +/* CSS for screens smaller or equal to 768px */ +@media (max-width: 768px) { + .djangoAppt_main-container { + padding: 8px; + } + + .djangoAppt_body-container { + padding: 8px; + } + + .djangoAppt_appointment-calendar { + flex: 1; + padding: 10px; + } + + .djangoAppt_service-description { + flex: 1; + margin-left: 0; + margin-top: 20px; + } + + .djangoAppt_calendar-and-slot { + display: grid; + } + + .djangoAppt_slot { + margin-top: 40px; + } + + .djangoAppt_slot-list, .djangoAppt_date_chosen, .djangoAppt_no-availability-text { + margin-left: 0; + padding-left: 0; + } + + .djangoAppt_btn-request-next-slot { + margin-left: 0; + } + + /* Reduce font size for smaller screens */ + .djangoAppt_title, .djangoAppt_item-name, .djangoAppt_date_chosen, .djangoAppt_next-available-date { + font-size: 16px; + } + + .djangoAppt_timezone-details { + font-size: 14px; + } + + .fc-day { + font-size: 10px; + } +} + +/* CSS for screens smaller or equal to 768px */ +@media (max-width: 450px) { + .djangoAppt_main-container { + padding: 3px; + } + + .djangoAppt_body-container { + padding: 3px; + } + + .djangoAppt_appointment-calendar { + flex: 1; + padding: 5px; + } + + .djangoAppt_service-description { + flex: 1; + margin-left: 0; + margin-top: 20px; + } + + .djangoAppt_calendar-and-slot { + display: grid; + } + + .djangoAppt_slot { + margin-top: 40px; + } + + .djangoAppt_slot-list, .djangoAppt_date_chosen, .djangoAppt_no-availability-text { + margin-left: 0 !important; + padding-left: 0 !important; + } + + .djangoAppt_btn-request-next-slot { + margin-left: 0; + } + + /* Reduce font size for smaller screens */ + .djangoAppt_title, .djangoAppt_item-name, .djangoAppt_date_chosen, .djangoAppt_next-available-date { + font-size: 13px; + } + + .djangoAppt_timezone-details, .error-message { + font-size: 13px; + } + + .fc-day { + font-size: 11px; + } + + .fc-toolbar-title { + font-size: 14px !important; + } + + .fc { + font-size: 13px !important; + } + + .fc, .fc-button { + vertical-align: center !important; + } + + .djangoAppt_appointment-slot { + padding: 5px; + font-size: 13px; + } + + .djangoAppt_service-description { + font-size: 13px !important; + } +} + +.selected-cell { + background-color: #aaddff; /* or any color you prefer */ +} \ No newline at end of file diff --git a/static/images/logos/vendors/Aljumaih-Automotive-logo_kM7B61x_AROA7K7.png b/static/images/logos/vendors/Aljumaih-Automotive-logo_kM7B61x_AROA7K7.png new file mode 100644 index 0000000000000000000000000000000000000000..04ee0afab90cd8e708128ceef09a5fecb64efad6 GIT binary patch literal 10227 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 ay { + setTimeout(initializeCalendar, 50); + }); +}); + +const AppStateProxy = new Proxy(AppState, { + set(target, property, value) { + console.log(`Setting ${property} to ${value}`) + // Check if the property being changed is 'isCreating' + if (value === true) { + attachEventListeners(); // Attach event listeners if isCreating becomes true + // (didn't check if property is isCreating, since AppStateProxy is only set with it) + } + target[property] = value; // Set the property value + return true; // Indicate successful setting + } +}); + +function attachEventListeners() { + // Checks if the DOM is already loaded + if (document.readyState === "complete" || document.readyState === "interactive") { + // DOM is already ready, attach event listeners directly + attachEventListenersToDropdown(); + } else { + // If the DOM is not yet ready, then wait for the DOMContentLoaded event + document.addEventListener('DOMContentLoaded', function () { + attachEventListenersToDropdown(); + }); + } +} + +function attachEventListenersToDropdown() { + const staffDropdown = document.getElementById('staffSelect'); + if (staffDropdown && !staffDropdown.getAttribute('listener-attached')) { + staffDropdown.setAttribute('listener-attached', 'true'); + staffDropdown.addEventListener('change', async function () { + const selectedStaffId = this.value; + const servicesDropdown = document.getElementById('serviceSelect'); + const services = await fetchServicesForStaffMember(selectedStaffId); + updateServicesDropdown(servicesDropdown, services); + }); + } +} + + +function initializeCalendar() { + const formattedAppointments = formatAppointmentsForCalendar(appointments); + const calendarEl = document.getElementById('calendar'); + AppState.calendar = new FullCalendar.Calendar(calendarEl, getCalendarConfig(formattedAppointments)); + AppState.calendar.setOption('locale', locale); + AppState.calendar.render(); +} + +function formatAppointmentsForCalendar(appointments) { + return appointments.map(appointment => ({ + id: appointment.id, + title: appointment.service_name, + start: appointment.start_time, + end: appointment.end_time, + client_name: appointment.client_name, + backgroundColor: appointment.background_color, + })); +} + +function updateCalendarConfig() { + AppState.calendar.setOption('headerToolbar', getHeaderToolbarConfig()); + AppState.calendar.setOption('height', getCalendarHeight()); +} + +function mobileCheck() { + return window.innerWidth < Constants.MOBILE_WIDTH; +} + +function tabletCheck() { + return window.innerWidth < Constants.TABLET_WIDTH; +} + +function getEventDisplayedStyle() { + if (mobileCheck()) { + return "list-item"; + } + return "block"; +} + +function getCalendarConfig(events) { + return { + initialView: 'dayGridMonth', + headerToolbar: getHeaderToolbarConfig(), + navLinks: true, + editable: true, + dayMaxEvents: true, + height: getCalendarHeight(), + aspectRatio: 1.0, + themeSystem: 'bootstrap5', + nowIndicator: true, + bootstrapFontAwesome: { + close: 'fa-times', + prev: 'fa-chevron-left', + next: 'fa-chevron-right', + prevYear: 'fa-angle-double-left', + nextYear: 'fa-angle-double-right' + }, + defaultView: mobileCheck() ? "basicDay" : "dayGridMonth", + selectable: true, + events: events, + eventDisplay: getEventDisplayedStyle(), + timeZone: timezone, + eventClick: async function (info) { + AppState.eventIdSelected = info.event.id; + await showEventModal(info.event.id, false, false); + }, + dateClick: function (info) { + // Retrieve events for the clicked date + const dateEvents = appointments + .filter(event => moment(info.date).isSame(event.start_time, 'day')) + .sort((a, b) => new Date(a.start_time) - new Date(b.start_time)); + + // Display events in a list below the calendar + displayEventList(dateEvents, info.date); + }, + + selectAllow: function (info) { + }, + dayCellClassNames: function (info) { + const day = info.date.getDay(); + if (day === 0 || day === 6) { // 0 = Sunday, 6 = Saturday + return 'highlight-weekend'; + } + return ''; // Return empty string for regular days + }, + eventDrop: async function (info) { + await validateAndUpdateAppointmentDate(info.event, info.revert); + }, + eventDidMount: function (info) { + // If it is a mobile view, we change the event to a dot + if (mobileCheck()) { + // Find the fc-daygrid-event-dot class within the event element + // and change its style to display as a dot + const dotEl = info.el.querySelector('.fc-daygrid-event-dot') || document.createElement('span'); + dotEl.classList.add('fc-daygrid-event-dot'); + dotEl.style.borderRadius = '50%'; + dotEl.style.backgroundColor = info.event.backgroundColor; + + // Clear the inner HTML of the event element and append the dot + info.el.innerHTML = ''; + info.el.appendChild(dotEl); + } + }, + dayCellDidMount: function (dayCell) { + // Check if the day is in the past + const currentDate = new Date(); + currentDate.setHours(0, 0, 0, 0); // Reset time part to compare only dates + + if (dayCell.date >= currentDate && !tabletCheck()) { + // Attach right-click event listener only if the day is not in the past + if (AppState.isUserStaffAdmin) { + dayCell.el.addEventListener('contextmenu', function (event) { + event.preventDefault(); + handleCalendarRightClick(event, dayCell.date); + }); + } + } + }, + }; +} + +function displayEventList(events, date) { + let eventListHtml = '

' + eventsOnTxt + ' ' + moment(date).format('MMMM Do, YYYY') + '

'; + eventListHtml += '
'; + + events.forEach(function (event) { + eventListHtml += `
${event.service_name}
`; + eventListHtml += `
${moment(event.start_time).format('h:mm a')} - ${moment(event.end_time).format('h:mm a')}
`; + eventListHtml += '
'; + }); + + const date_obj = new Date(date.toISOString()) + + if (events.length === 0) { + eventListHtml += `
` + noEventTxt + `
`; + } + + eventListHtml += ``; + + const eventListContainer = document.getElementById('event-list-container'); + eventListContainer.innerHTML = eventListHtml; + + // Add click event listeners to each event item + const eventItems = eventListContainer.getElementsByClassName('event-list-item-appt'); + for (let item of eventItems) { + item.addEventListener('click', function () { + const eventId = this.getAttribute('data-event-id'); + AppState.eventIdSelected = eventId; + showEventModal(eventId, false, false).then(r => r); + }); + } +} + + +function getHeaderToolbarConfig() { + if (window.matchMedia('(max-width: 767px)').matches) { + // Mobile configuration + return { + left: 'title', right: 'prev,next,dayGridMonth,timeGridDay' + }; + } else if (window.matchMedia('(max-width: 991px)').matches) { + // Tablet configuration + return { + left: 'prev,today,next', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay' + }; + } else { + // Desktop configuration + return { + left: 'prevYear,prev,today,next,nextYear', + center: 'title', + right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek', + prevYear: 'prevYear', + nextYear: 'nextYear' + }; + } +} + +function getCalendarHeight() { + if (window.innerWidth <= Constants.MOBILE_WIDTH_SMALL) return '400px'; + if (window.innerWidth <= Constants.MOBILE_WIDTH) return '450px'; + if (window.innerWidth <= Constants.SMALL_TABLET_WIDTH) return '600px'; + if (window.innerWidth <= Constants.TABLET_WIDTH) return '650px'; + if (window.innerWidth <= Constants.MEDIUM_WIDTH) return '767px'; + return '850px'; +} + +function setUserStaffAdminFlag() { + return fetch(isUserStaffAdminURL) + .then(response => response.json()) + .then(data => { + if (data.is_staff_admin) { + AppState.isUserStaffAdmin = true; + } else { + console.error(data.message || "Error fetching user details."); + AppState.isUserStaffAdmin = false; + } + }) + .catch(error => { + console.error("Error checking user's staff admin status: ", error); + AppState.isUserStaffAdmin = false; + }); +} + +function handleCalendarRightClick(event, date) { + if (!AppState.isUserStaffAdmin) { + showErrorModal(notStaffMemberTxt) + return; + } + const contextMenu = document.getElementById("customContextMenu"); + contextMenu.style.top = `${event.pageY}px`; + contextMenu.style.left = `${event.pageX}px`; + contextMenu.style.display = 'block'; + + const newAppointmentOption = document.getElementById("newAppointmentOption"); + newAppointmentOption.onclick = () => createNewAppointment(date); + + // Hide context menu on any click + document.addEventListener('click', () => contextMenu.style.display = 'none', {once: true}); +} + +function goToEvent() { + // Get the event URL + const event = appointments.find(app => Number(app.id) === Number(AppState.eventIdSelected)); + if (event && event.url) { + closeModal() + window.location.href = event.url; + } else { + console.error("Event not found or doesn't have a URL."); + } +} + +function closeModal() { + const modal = document.getElementById("eventDetailsModal"); + const editButton = document.getElementById("eventEditBtn"); + const submitButton = document.getElementById("eventSubmitBtn"); + const closeButton = modal.querySelector(".btn-secondary[data-dismiss='modal']"); + const cancelButton = document.getElementById("eventCancelBtn"); + + // Reset the modal buttons to their default state + editButton.style.display = ""; + closeButton.style.display = ""; + submitButton.style.display = "none"; + cancelButton.style.display = "none"; + + // Reset the editing flag + AppStateProxy.isEditingAppointment = false; + + // Close the modal + $('#eventDetailsModal').modal('hide'); +} + + +// ################################################################ // +// Generic // +// ################################################################ // + + +async function cancelEdit() { + // Retrieve the appointment that matches the eventIdSelected + const appointment = appointments.find(app => Number(app.id) === Number(AppState.eventIdSelected)); + if (!appointment) { + return; + } + + // Extract only the time using Moment.js + const endTime = moment(appointment.end_time).format('HH:mm:ss'); + + // Find the modal, end time label, and end time input + const modal = document.getElementById("eventDetailsModal"); + const endTimeLabel = modal.querySelector("label[for='endTime']"); + const endTimeInput = modal.querySelector("input[name='endTime']"); + + // Set and display the end time label and input + endTimeInput.value = endTime; + endTimeLabel.style.display = ""; + endTimeInput.style.display = ""; + + // Re-show the event modal with the original data + await showEventModal(appointment.id, false, false); + toggleEditMode(); // Turn off edit mode +} + +function confirmDeleteAppointment(appointmentId) { + const deleteURL = deleteAppointmentURLTemplate + const data = {appointment_id: appointmentId}; + + fetch(deleteURL, { + method: 'POST', headers: { + 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'X-CSRFToken': getCookie('csrftoken'), + }, body: JSON.stringify(data) + }) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + $('#eventDetailsModal').modal('hide'); + let event = AppState.calendar.getEventById(appointmentId); + if (event) { + event.remove(); + } + showErrorModal(data.message, successTxt); + closeConfirmModal(); // Close the confirmation modal + + // Remove the deleted appointment from the global appointments array + appointments = appointments.filter(appointment => appointment.id !== appointmentId); + + // Refresh the event list for the current date + const currentDate = AppState.calendar.getDate(); + const dateEvents = appointments + .filter(event => moment(currentDate).isSame(event.start_time, 'day')) + .sort((a, b) => new Date(a.start_time) - new Date(b.start_time)); + displayEventList(dateEvents, currentDate); + }) + .catch(error => { + console.error('Error:', error); + showErrorModal(updateApptErrorTitleTxt); + }); +} + +function deleteAppointment() { + showModal(confirmDeletionTxt, confirmDeletionTxt, deleteBtnTxt, null, () => confirmDeleteAppointment(AppState.eventIdSelected)); +} + +function fetchServices(isEditMode = false) { + let url = isEditMode && AppState.eventIdSelected ? `${fetchServiceListForStaffURL}?appointmentId=${AppState.eventIdSelected}` : fetchServiceListForStaffURL; + return fetch(url) + .then(response => response.json()) + .then(data => data.services_offered) + .catch(error => console.error("Error fetching services: ", error)); +} + +function fetchStaffMembers(isEditMode = false) { + let url = isEditMode && AppState.eventIdSelected ? `${fetchStaffListURL}?appointmentId=${AppState.eventIdSelected}` : fetchStaffListURL; + return fetch(url) + .then(response => response.json()) + .then(data => data.staff_members) + .catch(error => console.error("Error fetching staff members: ", error)); + +} + +async function populateServices(selectedServiceId, isEditMode = false) { + const services = await fetchServices(isEditMode); + if (!services) { + showErrorModal(noServiceOfferedTxt) + } + const selectElement = document.createElement('select'); + services.forEach(service => { + const option = document.createElement('option'); + option.value = service.id; // Accessing the id + option.textContent = service.name; // Accessing the name + if (service.id === selectedServiceId) { + option.defaultSelected = true; + } + selectElement.appendChild(option); + }); + return selectElement; +} + +async function populateStaffMembers(selectedStaffId, isEditMode = false) { + const staffMembers = await fetchStaffMembers(isEditMode); + if (!staffMembers) { + showErrorModal(noStaffMemberTxt) + } + const selectElement = document.createElement('select'); + staffMembers.forEach(staff => { + const option = document.createElement('option'); + option.value = staff.id; // Accessing the id + option.textContent = staff.name; // Accessing the name + if (staff.id === selectedStaffId) { + option.defaultSelected = true; + } + selectElement.appendChild(option); + }); + return selectElement; +} + +// Function to fetch services for a specific staff member +async function fetchServicesForStaffMember(staffId) { + const url = `${fetchServiceListForStaffURL}?staff_member=${staffId}`; + try { + const response = await fetch(url); + if (!response.ok) throw new Error('Network response was not ok'); + const data = await response.json(); + return data.services_offered || []; + } catch (error) { + console.error("Error fetching services: ", error); + return []; // Return an empty array in case of error + } +} + +// Function to update services dropdown options +function updateServicesDropdown(dropdown, services) { + // Clear existing options + dropdown.innerHTML = ''; + + // Populate with new options + services.forEach(service => { + const option = new Option(service.name, service.id); // Assuming service object has id and name properties + dropdown.add(option); + }); +} +/* +function getCSRFToken() { + const metaTag = document.querySelector('meta[name="csrf-token"]'); + if (metaTag) { + return metaTag.getAttribute('content'); + } else { + console.error("CSRF token meta tag not found!"); + return null; + } +} +*/ +async function validateAndUpdateAppointmentDate(event, revertFunction) { + const updatedStartTime = event.start.toISOString(); + const updatedEndTime = event.end ? event.end.toISOString() : null; + + const data = { + appointment_id: event.id, start_time: updatedStartTime, date: event.start.toISOString().split('T')[0] + }; + + try { + const validationResponse = await fetch(validateApptDateURL, { + method: 'POST', headers: { + 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'X-CSRFToken': getCookie('csrftoken'), + }, body: JSON.stringify(data) + }); + + if (validationResponse.ok) { + await updateAppointmentDate(event, revertFunction); + } else { + const responseData = await validationResponse.json(); + showErrorModal(responseData.message); + + revertFunction(); + } + } catch (error) { + console.error('Failed to validate data:', error); + revertFunction(); + } +} + +async function updateAppointmentDate(event, revertFunction) { + const updatedStartTime = event.start.toISOString().split('T')[1]; + const updatedDate = event.start.toISOString().split('T')[0]; + + const data = { + appointment_id: event.id, start_time: updatedStartTime, date: updatedDate, + }; + + try { + const response = await fetch(updateApptDateURL, { + method: 'POST', headers: { + 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'X-CSRFToken': getCookie('csrftoken'), + }, body: JSON.stringify(data) + }); + + const responseData = await response.json(); + if (response.ok) { + showErrorModal(responseData.message, successTxt) + } else { + console.error('Failed to update appointment date. Server responded with:', response.statusText); + showErrorModal(responseData.message, updateApptErrorTitleTxt); + revertFunction(); + } + } catch (error) { + console.error('Failed to send data:', error); + revertFunction(); + } +} + +// ################################################################ // +// Create new Appt // +// ################################################################ // +function createNewAppointment(dateInput) { + let date; + if (typeof dateInput === 'string' || dateInput instanceof String) { + date = new Date(dateInput); + } else { + date = dateInput; + } + + const day = date.getDate().toString().padStart(2, '0'); + const month = (date.getMonth() + 1).toString().padStart(2, '0'); // getMonth() returns 0-11 + const year = date.getFullYear(); + const formattedDate = `${year}-${month}-${day}`; + const defaultStartTime = `${formattedDate}T09:00:00`; + + showCreateAppointmentModal(defaultStartTime, formattedDate).then(() => { + }); +} + +async function showCreateAppointmentModal(defaultStartTime, formattedDate) { + const servicesDropdown = await populateServices(null, false); + let staffDropdown = null; + if (isUserSuperUser) { + staffDropdown = await populateStaffMembers(null, false); + staffDropdown.id = "staffSelect"; + staffDropdown.disabled = false; // Enable dropdown + attachEventListenersToDropdown(); // Attach event listener + } + servicesDropdown.id = "serviceSelect"; + servicesDropdown.disabled = false; // Enable dropdown + + document.getElementById('eventModalBody').innerHTML = prepareCreateAppointmentModalContent(servicesDropdown, staffDropdown, defaultStartTime, formattedDate); + + adjustCreateAppointmentModalButtons(); + AppStateProxy.isCreating = true; + $('#eventDetailsModal').modal('show'); +} + +function adjustCreateAppointmentModalButtons() { + document.getElementById("eventSubmitBtn").style.display = ""; + document.getElementById("eventCancelBtn").style.display = "none"; + document.getElementById("eventEditBtn").style.display = "none"; + document.getElementById("eventDeleteBtn").style.display = "none"; + document.getElementById("eventGoBtn").style.display = "none"; +} + +// ################################################################ // +// Show Event Modal // +// ################################################################ // + +// Extract Appointment Data +async function getAppointmentData(eventId, isCreatingMode, defaultStartTime) { + if (eventId && !isCreatingMode) { + const appointment = appointments.find(app => Number(app.id) === Number(eventId)); + if (!appointment) { + showErrorModal(apptNotFoundTxt, errorTxt); + return null; + } + return appointment; + } + return { + id: null, + service_name: '', + start_time: defaultStartTime, + end_time: '', + client_name: '', + client_email: '', + client_phone: '', + client_address: '', + additional_info: '', + want_reminder: false, + background_color: '', + timezone: '', + }; +} + +// Populate Services Dropdown +async function getServiceDropdown(serviceId, isEditMode) { + const servicesDropdown = await populateServices(serviceId, !isEditMode); + servicesDropdown.id = "serviceSelect"; + servicesDropdown.disabled = !isEditMode; + return servicesDropdown; +} + +// Populate Staff Dropdown +async function getStaffDropdown(staffId, isEditMode) { + const staffDropdown = await populateStaffMembers(staffId, !isEditMode); + staffDropdown.id = "staffSelect"; + staffDropdown.disabled = !isEditMode; + return staffDropdown; +} + +// Show Event Modal +async function showEventModal(eventId = null, isEditMode, isCreatingMode = false, defaultStartTime = '') { + const appointment = await getAppointmentData(eventId, isCreatingMode, defaultStartTime); + if (!appointment) return; + + const servicesDropdown = await getServiceDropdown(appointment.service_id, isEditMode); + let staffDropdown = null; + if (isUserSuperUser) { + staffDropdown = await getStaffDropdown(appointment.staff_id, isEditMode); + attachEventListenersToDropdown(); // Attach event listener + } + + document.getElementById('eventModalBody').innerHTML = generateModalContent(appointment, servicesDropdown, isEditMode, staffDropdown); + adjustModalButtonsVisibility(isEditMode, isCreatingMode); + $('#eventDetailsModal').modal('show'); +} + +// Adjust Modal Buttons Visibility +function adjustModalButtonsVisibility(isEditMode, isCreatingMode) { + const editButton = document.getElementById("eventEditBtn"); + const submitButton = document.getElementById("eventSubmitBtn"); + const deleteButton = document.getElementById("eventDeleteBtn"); + const goButton = document.getElementById("eventGoBtn"); + + editButton.style.display = !isEditMode && !isCreatingMode ? "" : "none"; + submitButton.style.display = isCreatingMode || isEditMode ? "" : "none"; + deleteButton.style.display = !isEditMode && !isCreatingMode ? "" : "none"; + goButton.style.display = isCreatingMode ? "none" : ""; +} + +// ################################################################ // +// Edit Logic // +// ################################################################ // + +function toggleEditMode() { + const modal = document.getElementById("eventDetailsModal"); + const appointment = appointments.find(app => Number(app.id) === Number(AppState.eventIdSelected)); + AppStateProxy.isCreating = false; // Turn off creating mode + + // Proceed only if an appointment is found + if (appointment) { + AppStateProxy.isEditingAppointment = !AppState.isEditingAppointment; // Toggle the editing state + updateModalUIForEditMode(modal, AppState.isEditingAppointment); + } else { + console.error("Appointment not found!"); + } +} + +function updateModalUIForEditMode(modal, isEditingAppointment) { + const inputs = modal.querySelectorAll("input"); + const staffDropdown = document.getElementById("staffSelect"); + const servicesDropdown = document.getElementById("serviceSelect"); + const editButton = document.getElementById("eventEditBtn"); + const submitButton = document.getElementById("eventSubmitBtn"); + const closeButton = modal.querySelector(".btn-secondary[data-dismiss='modal']"); + const cancelButton = document.getElementById("eventCancelBtn"); + const deleteButton = document.getElementById("eventDeleteBtn"); + const goButton = document.getElementById("eventGoBtn"); + const endTimeLabel = modal.querySelector("label[for='endTime']"); + const endTimeInput = modal.querySelector("input[name='endTime']"); + + // Toggle input and dropdown enable/disable state + inputs.forEach(input => input.disabled = !isEditingAppointment); + staffDropdown.disabled = !isEditingAppointment; + servicesDropdown.disabled = !isEditingAppointment; + + // Toggle visibility of UI elements + toggleElementVisibility(editButton, !isEditingAppointment); + toggleElementVisibility(submitButton, isEditingAppointment); + toggleElementVisibility(cancelButton, isEditingAppointment); + toggleElementVisibility(deleteButton, !isEditingAppointment); + toggleElementVisibility(closeButton, !isEditingAppointment); + toggleElementVisibility(endTimeLabel, !isEditingAppointment); // Show end time in view mode + toggleElementVisibility(endTimeInput, !isEditingAppointment); // Show end time in view mode + toggleElementVisibility(goButton, !isEditingAppointment); +} + +function toggleElementVisibility(element, isVisible) { + if (element) { + element.style.display = isVisible ? "" : "none"; + } +} + +// ################################################################ // +// Submit Logic // +// ################################################################ // + +async function submitChanges() { + const modal = document.getElementById("eventDetailsModal"); + const formData = collectFormDataFromModal(modal); + + if (!validateFormData(formData)) return; + + const response = await sendAppointmentData(formData); + if (response.ok) { + const responseData = await response.json(); + if (AppState.isCreating) { + addNewAppointmentToCalendar(responseData.appt[0]); + } else { + updateExistingAppointmentInCalendar(responseData.appt); + } + + AppState.calendar.render(); + } else { + const responseData = await response.json(); + showErrorModal(responseData.message); + } + closeModal(); + +} + +// Collect form data from modal +function collectFormDataFromModal(modal) { + const inputs = modal.querySelectorAll("input"); + const serviceId = modal.querySelector("#serviceSelect").value; + let staffId = null; + + if (isUserSuperUser) { + // If the user is a superuser, get the staff ID from the dropdown + const staffDropdown = modal.querySelector("#staffSelect"); + if (staffDropdown) { + staffId = staffDropdown.value; + } + } + + const data = { + isCreating: AppState.isCreating, + service_id: serviceId, + appointment_id: AppState.eventIdSelected + }; + + if (staffId) { + data.staff_member = staffId; + } + + inputs.forEach(input => { + if (input.name !== "date") { + let key = input.name.replace(/([A-Z])/g, '_$1').toLowerCase(); + data[key] = input.value; + } + }); + + if (AppState.isCreating) { + data["date"] = modal.querySelector('input[name="date"]').value; + } + + // Special handling for checkbox + const wantReminderCheckbox = modal.querySelector('input[name="want_reminder"]'); + if (!wantReminderCheckbox.checked) { + data['want_reminder'] = 'false'; + } else { + data['want_reminder'] = 'true'; + } + + return data; +} + +// Validate form data +function validateFormData(data) { + return validateEmail(data["client_email"]); +} + +// Validate email +function validateEmail(email) { + const emailInput = document.querySelector('input[name="clientEmail"]'); + const emailError = document.getElementById("emailError"); + + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailRegex.test(emailInput.value)) { + emailInput.style.border = "1px solid red"; + emailError.textContent = "Invalid email address, yeah."; + emailError.style.color = "red"; + emailError.style.display = "inline"; + return false; + } else { + emailInput.style.border = ""; + emailError.textContent = ""; + emailError.style.display = "none"; + return true; + } +} + +// Send appointment data to server +async function sendAppointmentData(data) { + const headers = { + 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'X-CSRFToken': getCookie('csrftoken'), + }; + + return fetch(updateApptMinInfoURL, { + method: 'POST', headers: headers, body: JSON.stringify(data) + }); +} + +// Add new appointment to calendar +function addNewAppointmentToCalendar(newAppointment) { + const newEvent = formatAppointmentsForCalendar([newAppointment])[0]; + appointments.push(newAppointment); + AppState.calendar.addEvent(newEvent); +} + +// Update existing appointment in calendar +function updateExistingAppointmentInCalendar(appointment) { + let eventToUpdate = AppState.calendar.getEventById(AppState.eventIdSelected); + if (eventToUpdate) { + updateEventProperties(eventToUpdate, appointment); + } + // update appointment in appointments array + const index = appointments.findIndex(app => Number(app.id) === Number(AppState.eventIdSelected)); + if (index !== -1) { + appointments[index] = appointment; + } +} + +// Update event properties +function updateEventProperties(event, appointment) { + event.setProp('title', appointment.service_name); + event.setStart(moment(appointment.start_time).format('YYYY-MM-DDTHH:mm:ss')); + event.setEnd(appointment.end_time); + event.setExtendedProp('client_name', appointment.client_name); + event.setProp('backgroundColor', appointment.background_color); +} diff --git a/static/js/appointments.js b/static/js/appointments.js new file mode 100644 index 00000000..1df6b5d3 --- /dev/null +++ b/static/js/appointments.js @@ -0,0 +1,370 @@ +const calendarEl = document.getElementById('calendar'); +let nextAvailableDateSelector = $('.djangoAppt_next-available-date') +const body = $('body'); +let nonWorkingDays = []; +let selectedDate = rescheduledDate || null; +let staffId = $('#staff_id').val() || null; +let previouslySelectedCell = null; +let isRequestInProgress = false; + +const calendar = new FullCalendar.Calendar(calendarEl, { + initialView: 'dayGridMonth', + initialDate: selectedDate, + timeZone: timezone, + headerToolbar: { + left: 'title', + right: 'prev,today,next', + }, + height: '400px', + themeSystem: 'bootstrap', + nowIndicator: true, + bootstrapFontAwesome: { + close: 'fa-times', + prev: 'fa-chevron-left', + next: 'fa-chevron-right', + prevYear: 'fa-angle-double-left', + nextYear: 'fa-angle-double-right' + }, + selectable: true, + dateClick: function (info) { + const day = info.date.getDay(); // Get the day of the week (0 for Sunday, 6 for Saturday) + if (nonWorkingDays.includes(day)) { + return; + } + + // If there's a previously selected cell, remove the class + if (previouslySelectedCell) { + previouslySelectedCell.classList.remove('selected-cell'); + } + + // Add the class to the currently clicked cell + info.dayEl.classList.add('selected-cell'); + + // Store the currently clicked cell + previouslySelectedCell = info.dayEl; + + selectedDate = info.dateStr; + getAvailableSlots(info.dateStr, staffId); + }, + datesSet: function (info) { + highlightSelectedDate(); + }, + selectAllow: function (info) { + const day = info.start.getDay(); // Get the day of the week (0 for Sunday, 6 for Saturday) + if (nonWorkingDays.includes(day)) { + return false; // Disallow selection for non-working days + } + return (info.start >= getDateWithoutTime(new Date())); + }, + dayCellClassNames: function (info) { + const day = info.date.getDay(); + if (nonWorkingDays.includes(day)) { + return ['disabled-day']; + } + return []; + }, +}); + +calendar.setOption('locale', locale); + +$(document).ready(function () { + staffId = $('#staff_id').val() || null; + calendar.render(); + const currentDate = rescheduledDate || moment.tz(timezone).format('YYYY-MM-DD'); + getAvailableSlots(currentDate, staffId); +}); + +function highlightSelectedDate() { + setTimeout(function () { + const dateCell = document.querySelector(`.fc-daygrid-day[data-date='${selectedDate}']`); + if (dateCell) { + dateCell.classList.add('selected-cell'); + previouslySelectedCell = dateCell; + } + }, 10); +} + +body.on('click', '.djangoAppt_btn-request-next-slot', function () { + const serviceId = $(this).data('service-id'); + requestNextAvailableSlot(serviceId); +}) + +body.on('click', '.btn-submit-appointment', function () { + const selectedSlot = $('.djangoAppt_appointment-slot.selected').text(); + const selectedDate = $('.djangoAppt_date_chosen').text(); + if (!selectedSlot || !selectedDate) { + alert(selectDateAndTimeAlertTxt); + return; + } + if (selectedSlot && selectedDate) { + const startTime = convertTo24Hour(selectedSlot); + const APPOINTMENT_BASE_TEMPLATE = localStorage.getItem('APPOINTMENT_BASE_TEMPLATE'); + // Convert the selectedDate string to a valid format + const dateParts = selectedDate.split(', '); + const monthDayYear = dateParts[1] + "," + dateParts[2]; + const formattedDate = new Date(monthDayYear + " " + startTime); + + const date = formattedDate.toISOString().slice(0, 10); + const endTimeDate = new Date(formattedDate.getTime() + serviceDuration * 60000); + const endTime = formatTime(endTimeDate); + const reasonForRescheduling = $('#reason_for_rescheduling').val(); + const form = $('.appointment-form'); + let formAction = rescheduledDate ? appointmentRescheduleURL : appointmentRequestSubmitURL; + form.attr('action', formAction); + if (!form.find('input[name="appointment_request_id"]').length) { + form.append($('', { + type: 'hidden', + name: 'appointment_request_id', + value: appointmentRequestId + })); + } + form.append($('', {type: 'hidden', name: 'date', value: date})); + form.append($('', {type: 'hidden', name: 'start_time', value: startTime})); + form.append($('', {type: 'hidden', name: 'end_time', value: endTime})); + form.append($('', {type: 'hidden', name: 'service', value: serviceId})); + form.append($('', {type: 'hidden', name: 'reason_for_rescheduling', value: reasonForRescheduling})); + form.submit(); + } else { + const warningContainer = $('.warning-message'); + if (warningContainer.find('submit-warning') === 0) { + warningContainer.append('

' + selectTimeSlotWarningTxt + '

'); + } + } +}); + +$('#staff_id').on('change', function () { + staffId = $(this).val() || null; // If staffId is an empty string, set it to null + let currentDate = null + if (selectedDate == null) { + currentDate = moment.tz(timezone).format('YYYY-MM-DD'); + } else { + currentDate = selectedDate; + } + fetchNonWorkingDays(staffId, function (newNonWorkingDays) { + nonWorkingDays = newNonWorkingDays; // Update the nonWorkingDays array + calendar.render(); // Re-render the calendar to apply changes + + // Fetch available slots for the current date + getAvailableSlots(currentDate, staffId); + }); +}); + + +function fetchNonWorkingDays(staffId, callback) { + if (!staffId || staffId === 'none') { + nonWorkingDays = []; // Reset nonWorkingDays + calendar.render(); // Re-render the calendar + callback([]); + return; // Exit the function early + } + let ajaxData = { + 'staff_member': staffId, + }; + + $.ajax({ + url: getNonWorkingDaysURL, + data: ajaxData, + dataType: 'json', + success: function (data) { + if (data.error) { + console.error('Error fetching non-working days:', data.message); + callback([]); + } else { + nonWorkingDays = data.non_working_days; + calendar.render(); + callback(data.non_working_days); + } + } + }); +} + +function getDateWithoutTime(dt) { + dt.setHours(0, 0, 0, 0); + return dt; +} + +function convertTo24Hour(time12h) { + const [time, modifier] = time12h.split(' '); + let [hours, minutes] = time.split(':'); + + if (hours === '12') { + hours = '00'; + } + + if (modifier.toUpperCase() === 'PM') { + hours = parseInt(hours, 10) + 12; + } + + return `${hours}:${minutes}`; +} + +function formatTime(date) { + const hours = date.getHours(); + const minutes = date.getMinutes(); + return (hours < 10 ? '0' + hours : hours) + ':' + (minutes < 10 ? '0' + minutes : minutes); +} + +function getAvailableSlots(selectedDate, staffId = null) { + // Update the slot list with the available slots for the selected date + const slotList = $('#slot-list'); + const slotContainer = $('.slot-container'); + const errorMessageContainer = $('.error-message'); + + // Clear previous error messages and slots + slotList.empty(); + errorMessageContainer.find('.djangoAppt_no-availability-text').remove(); + + // Remove the "Next available date" message + nextAvailableDateSelector = $('.djangoAppt_next-available-date'); // Update the selector + nextAvailableDateSelector.remove(); + + // Correctly check if staffId is 'none', null, or undefined and exit the function if true + // Check if 'staffId' is 'none', null, or undefined and display an error message + if (staffId === 'none' || staffId === null || staffId === undefined) { + console.log('No staff ID provided, displaying error message.'); + const errorMessage = $('

' + noStaffMemberSelectedTxt + '

'); + errorMessageContainer.append(errorMessage); + // Optionally disable the "submit" button here + $('.btn-submit-appointment').attr('disabled', 'disabled'); + return; // Exit the function early + } + + let ajaxData = { + 'selected_date': selectedDate, + 'staff_member': staffId, + }; + fetchNonWorkingDays(staffId, function (nonWorkingDays) { + // Check if nonWorkingDays is an array + if (Array.isArray(nonWorkingDays)) { + // Update the FullCalendar configuration + // calendar.setOption('hiddenDays', nonWorkingDays); + } else { + // Handle the case where there's an error or no data + // For now, we'll just log it, but you can handle it more gracefully if needed + console.error('Failed to get non-working days:', nonWorkingDays); + } + }); + + // Send an AJAX request to get the available slots for the selected date + if (isRequestInProgress) { + return; // Exit the function if a request is already in progress + } + isRequestInProgress = true; + $.ajax({ + url: availableSlotsAjaxURL, + data: ajaxData, + dataType: 'json', + success: function (data) { + if (data.available_slots.length === 0) { + const selectedDateObj = moment.tz(selectedDate, timezone); + const selectedD = selectedDateObj.toDate(); + const today = new Date(); + today.setHours(0, 0, 0, 0); + + if (selectedD < today) { + // Show an error message + errorMessageContainer.append('

' + dateInPastErrorTxt + '

'); + if (slotContainer.find('.djangoAppt_btn-request-next-slot').length === 0) { + slotContainer.append(``); + } + // Disable the 'submit' button + $('.btn-submit-appointment').attr('disabled', 'disabled'); + } else { + errorMessageContainer.find('.djangoAppt_no-availability-text').remove(); + if (errorMessageContainer.find('.djangoAppt_no-availability-text').length === 0) { + errorMessageContainer.append(`

${data.message}

`); + } + // Check if the returned message is 'No availability' + if (data.message.toLowerCase() === 'no availability') { + if (slotContainer.find('.djangoAppt_btn-request-next-slot').length === 0) { + slotContainer.append(``); + } + } else { + $('.djangoAppt_btn-request-next-slot').remove(); + } + } + } else { + // remove the button to request for next available slot + $('.djangoAppt_no-availability-text').remove(); + $('.djangoAppt_btn-request-next-slot').remove(); + const uniqueSlots = [...new Set(data.available_slots)]; // remove duplicates + for (let i = 0; i < uniqueSlots.length; i++) { + slotList.append('
  • ' + uniqueSlots[i] + '
  • '); + } + + // Attach click event to the slots + $('.djangoAppt_appointment-slot').on('click', function () { + // Remove the 'selected' class from all other appointment slots + $('.djangoAppt_appointment-slot').removeClass('selected'); + + // Add the 'selected' class to the clicked appointment slot + $(this).addClass('selected'); + + // Enable the submit button + $('.btn-submit-appointment').removeAttr('disabled'); + + // Continue with the existing logic + const selectedSlot = $(this).text(); + $('#service-datetime-chosen').text(data.date_chosen + ' ' + selectedSlot); + }); + } + // Update the date chosen + $('.djangoAppt_date_chosen').text(data.date_chosen); + $('#service-datetime-chosen').text(data.date_chosen); + isRequestInProgress = false; + }, + error: function() { + isRequestInProgress = false; // Ensure the flag is reset even if the request fails + } + }); +} + +function requestNextAvailableSlot(serviceId) { + const requestNextAvailableSlotURL = requestNextAvailableSlotURLTemplate.replace('0', serviceId); + if (staffId === null) { + return; + } + let ajaxData = { + 'staff_member': staffId, + }; + $.ajax({ + url: requestNextAvailableSlotURL, + data: ajaxData, + dataType: 'json', + success: function (data) { + // If there's an error, just log it and return + let nextAvailableDateResponse = null; + let formattedDate = null; + if (data.error) { + nextAvailableDateResponse = data.message; + } else { + // Set the date in the calendar to the next available date + nextAvailableDateResponse = data.next_available_date; + const selectedDateObj = moment.tz(nextAvailableDateResponse, timezone); + const nextAvailableDate = selectedDateObj.toDate(); + formattedDate = new Intl.DateTimeFormat('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric' + }).format(nextAvailableDate); + } + + // Check if the .next-available-date element already exists + nextAvailableDateSelector = $('.djangoAppt_next-available-date'); // Update the selector + let nextAvailableDateText = null; + if (data.error) { + nextAvailableDateText = nextAvailableDateResponse; + } else { + nextAvailableDateText = `Next available date: ${formattedDate}`; + } + if (nextAvailableDateSelector.length > 0) { + // Update the content of the existing .next-available-date element + nextAvailableDateSelector.text(nextAvailableDateText); + } else { + // If the .next-available-date element doesn't exist, create and append it + const nextDateText = `

    ${nextAvailableDateText}

    `; + $('.djangoAppt_btn-request-next-slot').after(nextDateText); + } + } + }); +} diff --git a/static/js/js-utils.js b/static/js/js-utils.js new file mode 100644 index 00000000..ba791270 --- /dev/null +++ b/static/js/js-utils.js @@ -0,0 +1,8 @@ +document.addEventListener('DOMContentLoaded', function () { + const messageElements = document.querySelectorAll('.alert-dismissible'); + setTimeout(function () { + messageElements.forEach(function (element) { + element.style.display = 'none'; + }); + }, 5000); +}); diff --git a/static/js/modal/error_modal.js b/static/js/modal/error_modal.js new file mode 100644 index 00000000..a64887f9 --- /dev/null +++ b/static/js/modal/error_modal.js @@ -0,0 +1,19 @@ +let errorModalInstance = null; + +function showErrorModal(message, title = errorTxt) { + // Insert the error message into the modal + document.getElementById('errorModalLabel').textContent = title; + document.getElementById('errorModalMessage').textContent = message; + + // Show the modal + if (!errorModalInstance) { + errorModalInstance = new bootstrap.Modal(document.getElementById('errorModal')); + } + errorModalInstance.show(); +} + +function closeErrorModal() { + if (errorModalInstance) { + errorModalInstance.hide(); + } +} \ No newline at end of file diff --git a/static/js/modal/show_modal.js b/static/js/modal/show_modal.js new file mode 100644 index 00000000..7dac8b7c --- /dev/null +++ b/static/js/modal/show_modal.js @@ -0,0 +1,25 @@ +function showModal(title, body, actionText, actionUrl, actionCallback) { + // Set the content of the modal + document.getElementById('modalLabel').innerText = title; + document.getElementById('modalBody').innerText = body; + const actionBtn = document.getElementById('modalActionBtn'); + actionBtn.innerText = actionText; + + // Determine the type of action: callback function or URL + if (actionCallback) { + actionBtn.onclick = () => { + actionCallback(); + closeModal(); // Close the modal after action + }; + } else if (actionUrl) { + actionBtn.href = actionUrl; + } + + // Display the modal + $('#confirmModal').modal('show'); +} + + +function closeConfirmModal() { + $('#confirmModal').modal('hide'); +} \ No newline at end of file diff --git a/templates/administration/display_appointment.html b/templates/administration/display_appointment.html new file mode 100644 index 00000000..0071e007 --- /dev/null +++ b/templates/administration/display_appointment.html @@ -0,0 +1,98 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customCSS %} + + +{% endblock %} +{% block title %} + {{ page_title }} +{% endblock %} +{% block description %} + {{ page_description }} +{% endblock %} +{% block body %} +
    +
    +
    +
    +

    {{ page_title }}

    +
    +
    + + {% trans 'Date' %}: {{ appointment.get_date }} +
    +
    + + {% trans 'Start time' %}: {{ appointment.get_start_time|time:"g:i A" }} +
    +
    + + {% trans 'End time' %}: {{ appointment.get_end_time|time:"g:i A" }} +
    +
    + + {% trans 'Service' %}: {{ appointment.get_service_name }} +
    +
    + + {% trans 'Client' %}: {{ appointment.get_client_name }} +
    +
    + + {% trans 'Email' %}: {{ appointment.client.email }} +
    +
    + + {% trans 'Phone' %}: {{ appointment.phone }} +
    +
    + + {% trans 'Wants reminder' %}: {{ appointment.want_reminder }} +
    +
    + + {% trans 'Client address' %}: {{ appointment.address }} +
    +
    + + {% trans 'Additional Information' %}: {{ appointment.additional_info }} +
    +
    + + {% trans 'Is paid' %}: {{ appointment.is_paid_text }} +
    +
    + + {% trans 'Service price' %}: {{ appointment.get_appointment_amount_to_pay_text }} +
    +
    +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +
    +
    +{% endblock %} +{% block customJS %} + + + + + + +{% endblock %} diff --git a/templates/administration/email_change_verification_code.html b/templates/administration/email_change_verification_code.html new file mode 100644 index 00000000..d080e5a8 --- /dev/null +++ b/templates/administration/email_change_verification_code.html @@ -0,0 +1,41 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customCSS %} + +{% endblock %} +{% block title %} + {% trans 'Enter Verification Code' %} +{% endblock %} +{% block description %} + {% trans 'Enter Verification Code' %} +{% endblock %} +{% block body %} +
    +
    +
    +

    {% trans 'Enter Verification Code' %}

    +

    {% trans "We've sent a verification code to your email. Please enter it below" %}:

    +
    + {% csrf_token %} + + +
    +
    +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +{% endblock %} +{% block customJS %} + +{% endblock %} diff --git a/templates/administration/manage_day_off.html b/templates/administration/manage_day_off.html new file mode 100644 index 00000000..0e8c7411 --- /dev/null +++ b/templates/administration/manage_day_off.html @@ -0,0 +1,152 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} + +{% block customCSS %} + + + +{% endblock %} + +{% block body %} +
    +
    +
    +

    {% trans "Manage Days Off" %}

    + +
    + {% csrf_token %} + + {% if error_message %} + + {% endif %} + + {% if days_off_form.staff_member %} +
    + + {{ days_off_form.staff_member }} +
    + {% endif %} + + +
    + + + + +
    + + +
    + + + + +
    + + +
    + + +
    + + + +
    +
    + {% if days_off_form.errors %} +
    + {{ days_off_form.errors }} +
    + {% endif %} +
    + +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    + {% include 'modal/error_modal.html' %} +
    +
    +
    +{% endblock %} + +{% block customJS %} + + + + + + +{% endblock %} diff --git a/templates/administration/manage_service.html b/templates/administration/manage_service.html new file mode 100644 index 00000000..187cc410 --- /dev/null +++ b/templates/administration/manage_service.html @@ -0,0 +1,51 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} + +{% block customCSS %} + + +{% endblock %} + +{% block body %} +
    +{% endblock %} + +{% block customJS %} + +{% endblock %} diff --git a/templates/administration/manage_staff_member.html b/templates/administration/manage_staff_member.html new file mode 100644 index 00000000..4c7ce226 --- /dev/null +++ b/templates/administration/manage_staff_member.html @@ -0,0 +1,87 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} + +{% block customCSS %} + +{% endblock %} + +{% block body %} +
    +
    +
    +

    {% trans 'Staff Appointment Information' %}

    +
    + {% csrf_token %} + {% if form.user %} +
    + {{ form.user.label_tag }} + {{ form.user.errors }} + {{ form.user }} +
    +
    + + {% translate 'User not found' %} ? {% translate 'Create staff member manually' %} + +
    + {% endif %} + +
    + {{ form.services_offered.label_tag }} + {{ form.services_offered.errors }} + {{ form.services_offered }} +
    {% trans 'Hold down “Control”, or “Command” on a Mac, to select more than one.' %} +
    + +
    + {{ form.slot_duration.label_tag }} + {{ form.slot_duration }} + {{ form.slot_duration.help_text }} +
    + +
    + {{ form.lead_time.label_tag }} + {{ form.lead_time }} + {{ form.lead_time.help_text }} +
    + +
    + {{ form.finish_time.label_tag }} + {{ form.finish_time }} + {{ form.finish_time.help_text }} +
    + +
    + {{ form.appointment_buffer_time.label_tag }} + {{ form.appointment_buffer_time }} + {{ form.appointment_buffer_time.help_text }} +
    + +
    + {{ form.work_on_saturday }} + {{ form.work_on_saturday.label_tag }} +
    + +
    + {{ form.work_on_sunday }} + {{ form.work_on_sunday.label_tag }} +
    + + +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +
    +
    +{% endblock %} + +{% block customJS %} + +{% endblock %} diff --git a/templates/administration/manage_staff_personal_info.html b/templates/administration/manage_staff_personal_info.html new file mode 100644 index 00000000..a9c07358 --- /dev/null +++ b/templates/administration/manage_staff_personal_info.html @@ -0,0 +1,49 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} + +{% block customCSS %} + +{% endblock %} + +{% block body %} +
    +
    +
    +

    {% trans 'Staff Personal Information' %}

    +
    + {% csrf_token %} + +
    + {{ form.first_name.label_tag }} + {{ form.first_name }} +
    + +
    + {{ form.last_name.label_tag }} + {{ form.last_name }} +
    + +
    + {{ form.email.label_tag }} + {{ form.email }} +
    + + +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +
    +
    +{% endblock %} + +{% block customJS %} + +{% endblock %} diff --git a/templates/administration/manage_working_hours.html b/templates/administration/manage_working_hours.html new file mode 100644 index 00000000..819f383d --- /dev/null +++ b/templates/administration/manage_working_hours.html @@ -0,0 +1,183 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} + +{% block customCSS %} + + + + + +{% endblock %} + +{% block body %} +
    +
    +
    +

    {% trans "Manage Working Hours" %}

    +
    + {% csrf_token %} + + {% if working_hours_form.staff_member %} +
    + + {{ working_hours_form.staff_member }} +
    + {% endif %} + +
    + + {{ working_hours_form.day_of_week }} +
    + +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    + +
    +
    +
    +
    +
    + + + + + +
    + {% include 'modal/error_modal.html' %} +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +
    +
    +{% endblock %} +{% block customJS %} + + + + + + + + + +{% endblock %} + diff --git a/templates/administration/service_list.html b/templates/administration/service_list.html new file mode 100644 index 00000000..4251649c --- /dev/null +++ b/templates/administration/service_list.html @@ -0,0 +1,78 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load static %} + +{% block title %} + {% trans 'Service List' %} +{% endblock %} +{% block description %} + {% trans 'Service List' %}. +{% endblock %} +{% block body %} + +
    +
    +
    +

    {% trans 'Service List' %}

    +
    +
    + + + + + + + + + + + {% for service in services %} + + + + + + + {% empty %} + + + + {% endfor %} + +
    {% trans 'Name' %}{% trans 'Duration' %}{% trans 'Price' %}{% trans 'Action' %}
    {{ service.name }}{{ service.get_duration }}{{ service.get_price_text }} +
    + + + + {% translate "Are you sure you want to delete this service?" as d_modal_message %} + {% if request.user.is_superuser %} + + + + + + + {% endif %} +
    +
    {% trans 'No service found' %}.
    +
    +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    + +{% endblock %} + +{% block customJS %} + +{% endblock %} diff --git a/templates/administration/staff_index.html b/templates/administration/staff_index.html new file mode 100644 index 00000000..e1683d2d --- /dev/null +++ b/templates/administration/staff_index.html @@ -0,0 +1,409 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customMetaTag %} + +{% endblock %} +{% block customCSS %} + + + +{% endblock %} +{% block title %} + {{ page_title }} +{% endblock %} +{% block description %} + {{ page_description }} +{% endblock %} +{% block body %} +
    +
    +
    +
    +
    +
    + + {% include 'modal/event_details_modal.html' %} + {% include 'modal/error_modal.html' %} + +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +
    + + + {% include 'modal/confirm_modal.html' %} +{% endblock %} + + +{% block customJS %} + + + + + + + + + + + + +{% endblock %} diff --git a/templates/administration/staff_list.html b/templates/administration/staff_list.html new file mode 100644 index 00000000..70fb7142 --- /dev/null +++ b/templates/administration/staff_list.html @@ -0,0 +1,81 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load static %} +{% block customCSS %} + + + +{% endblock %} +{% block title %} + Staff Members List +{% endblock %} +{% block description %} + {% trans 'List of all staff members' %}. +{% endblock %} +{% block body %} + +
    +
    +
    +

    {% trans 'Staff Members' %}

    + +
    +
    + + + + + + + + + + {% for staff_member in staff_members %} + + + + + + {% empty %} + + + + {% endfor %} + + {% trans "PS: Remove means, deleting the staff status of the user. The user account is still active." %} + + +
    {% trans 'Name' %}{% trans 'Email' %}{% trans 'Details' %}
    {{ staff_member.get_staff_member_name }}{{ staff_member.user.email|default:"N/A" }} + {% trans 'View Profile' %} + {% trans 'Remove' %} +
    {% trans 'No staff members found' %}.
    +
    +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    + +{% endblock %} + +{% block customJS %} + +{% endblock %} diff --git a/templates/administration/user_profile.html b/templates/administration/user_profile.html new file mode 100644 index 00000000..c762c671 --- /dev/null +++ b/templates/administration/user_profile.html @@ -0,0 +1,281 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customCSS %} + + + + +{% endblock %} +{% block title %} + {{ page_title }} +{% endblock %} +{% block description %} + {{ page_description }} +{% endblock %} +{% block body %} +
    +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    + {% translate "Confirm Deletion" as modal_title %} + {% translate "Delete" as delete_btn_modal %} + +

    {% trans 'Personal Information' %}

    + +
    +

    {% trans 'First name' %}: {{ user.first_name|default:user.username }}

    +

    {% trans 'Last name' %}: {{ user.last_name|default:"N/A" }}

    +

    {% trans 'Email' %}: {{ user.email|default:"N/A" }}

    +
    + + + +
    + + +
    +

    {% trans 'Appointment Information' %}

    + + {{ service_msg }} + + {% if staff_member %} +
    +

    + {% trans 'Slot duration' %}: {{ staff_member.get_slot_duration_text }} + +

    +

    {% trans 'General start time' %}: {{ staff_member.get_lead_time }}

    +

    {% trans 'General end time' %}: {{ staff_member.get_finish_time }}

    +

    + {% trans 'Weekend days you work' %}: {{ staff_member.get_weekend_days_worked_text }} +

    + +

    + {% trans 'Appointment buffer time' %}: {{ staff_member.get_appointment_buffer_time_text }} + +

    + +
    + + + + {% else %} +
    +

    {% trans 'No staff member information yet for this user' %}.

    +
    + + + + {% endif %} + +
    + + +
    +

    {% trans 'Days Off' %}

    + + + + + {% trans "Days off are days you're not working, you need to set them for holidays as well so clients don't book you those days." %} + +
    + + + + + + + + + + + {% for day_off in days_off %} + + + + + + + {% empty %} + + + + {% endfor %} + +
    {% trans 'Start date' %}{% trans 'End date' %}{% trans 'Description' %}{% trans 'Action' %}
    {{ day_off.start_date }}{{ day_off.end_date }}{{ day_off.description }} +
    + {% if superuser %} + + + + {% else %} + + + + {% endif %} + {% translate "Are you sure you want to delete this working hours?" as d_modal_message %} + {% if superuser %} + + + + {% else %} + + + + {% endif %} +
    +
    {% trans 'No days off have been set' %}.
    +
    +
    + + +
    +

    {% trans 'Working Hours' %}

    + + + + + {% trans "Note: If you are a staff member, your working hours will be used to determine when you are available for appointments." %} + +
    + + + + + + + + + + + {% for working_hour in working_hours %} + + + + + + + {% empty %} + + + + {% endfor %} + +
    {% trans 'Day' %}{% trans 'Start time' %}{% trans 'End time' %}{% trans 'Action' %}
    {{ working_hour.get_day_of_week_str }}{{ working_hour.start_time|time:"g:i A" }}{{ working_hour.end_time|time:"g:i A" }} +
    + {% if superuser %} + + + + {% else %} + + + + {% endif %} + {% translate "Are you sure you want to delete this working hours?" as w_modal_message %} + {% if superuser %} + + + + {% else %} + + + + {% endif %} +
    +
    {% trans 'No working hours have been set' %}.
    +
    +
    + + +
    +

    {% trans 'Service Offered' %}

    + + {% if not superuser %} + {% trans "To add/modify a new service, make a request to an admin." %} + {% trans "Changes made in one service will change it for every staff member." %} + {% endif %} + +
    + + + + + + + + + + + + {% for service in services_offered %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
    {% trans 'Name' %}{% trans 'Description' %}{% trans 'Duration' %}{% trans 'Price' %}{% trans 'Down payment' %}
    {{ service.name }}{{ service.description|default:"N/A" }}{{ service.get_duration }}{{ service.get_price_text }}{{ service.get_down_payment_text }}
    {% trans 'No service offered yet' %}.
    +
    +
    +
    + + {% include 'modal/confirm_modal.html' %} +
    +{% endblock %} +{% block customJS %} + + + + + + + + + +{% endblock %} + diff --git a/templates/appointment/appointment_client_information.html b/templates/appointment/appointment_client_information.html new file mode 100644 index 00000000..acac34a0 --- /dev/null +++ b/templates/appointment/appointment_client_information.html @@ -0,0 +1,165 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customCSS %} + +{% endblock %} +{% block title %} + {% translate 'Client Information' %} - {{ ar.get_service_name }} +{% endblock %} +{% block description %} + {% blocktranslate with service_name=ar.get_service_name %} + Your appointment request for {{ service_name }} has been submitted. + Please provide your information to create an account and complete the payment process. + {% endblocktranslate %} +{% endblock %} +{% block body %} +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} + +
    + {% csrf_token %} + +
    +
    {% trans "Service Details" %}
    + +
    + +
    +
    {{ ar.get_service_name }}
    +
    + {{ ar.date }} {% trans "at" %} {{ ar.start_time }} +
    +
    {{ ar.service.get_duration }}
    +
    + +
    + {% if ar.is_a_paid_service %} + {% if APPOINTMENT_PAYMENT_URL %} +
    +
    {% trans "Payment Details" %}
    +
    +
    {% trans "Total" %}
    +
    ${{ ar.get_service_price }}
    +
    +
    + + {% if ar.accepts_down_payment %} + + {% endif %} +
    +
    + {% else %} + + {% endif %} + {% else %} + + {% endif %} +
    +
    +
    +
    +{% endblock %} +{% block customJS %} + +{% endblock %} diff --git a/templates/appointment/appointments.html b/templates/appointment/appointments.html new file mode 100644 index 00000000..10cb6359 --- /dev/null +++ b/templates/appointment/appointments.html @@ -0,0 +1,134 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customCSS %} + + +{% endblock %} +{% block title %} + {{ page_title }} +{% endblock %} +{% block description %} + {{ page_description }} +{% endblock %} +{% block body %} +
    +
    +
    +

    + {% if page_header %}{{ page_header }}{% else %}{{ service.name }}{% endif %}

    + + {% trans "Check out our availability and book the date and time that works for you" %} + +
    + +
    +
    +
    +
    + {% trans "Select a date and time" %} +
    +
    + {% trans "Timezone" %}: {{ timezoneTxt }} +
    +
    +
    +
    +
    +
    +
    +
    {{ date_chosen }}
    +
    +
    +
      + +
    +
    + +
    +
    + {% if rescheduled_date %} +
    + + +
    + {% endif %} +
    +
    +
    + {% csrf_token %} +
    + + +
    + +
    {% trans "Service Details" %}
    +
    +
    +

    {{ service.name }}

    +

    {{ date_chosen }}

    +

    {{ service.get_duration }}

    +

    {{ service.get_price_text }}

    + +
    +
    +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +
    +{% endblock %} + +{% block customJS %} + + + + + + + + +{% endblock %} diff --git a/templates/appointment/default_thank_you.html b/templates/appointment/default_thank_you.html new file mode 100644 index 00000000..7d066b6c --- /dev/null +++ b/templates/appointment/default_thank_you.html @@ -0,0 +1,36 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customCSS %} + +{% endblock %} +{% block title %} + {{ page_title }} +{% endblock %} +{% block description %} + {{ page_description }} +{% endblock %} +{% block body %} +
    +
    +

    {% trans "See you soon" %} !

    +

    {% trans "We've successfully scheduled your appointment! Please check your email for all the details" %}.

    +

    {% trans "Appointment details" %}:

    +
      +
    • {% trans 'Service' %}: {{ appointment.get_service_name }}
    • +
    • {% trans 'Appointment Date' %}: {{ appointment.get_appointment_date }}
    • +
    • {% trans 'Appointment Time' %}: {{ appointment.get_start_time }}
    • +
    • {% trans 'Duration' %}: {{ appointment.get_service_duration }}
    • +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +{% endblock %} +{% block customJS %} + +{% endblock %} \ No newline at end of file diff --git a/templates/appointment/enter_verification_code.html b/templates/appointment/enter_verification_code.html new file mode 100644 index 00000000..6b157a11 --- /dev/null +++ b/templates/appointment/enter_verification_code.html @@ -0,0 +1,39 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} + +{% block customCSS %} + +{% endblock %} + +{% block title %}{% trans 'Enter Verification Code' %}{% endblock %} +{% block description %}{% trans 'Enter Verification Code' %}{% endblock %} + +{% block body %} +
    +
    +

    {% trans 'Enter Verification Code' %}

    +

    {% trans "We've sent a verification code to your email. Please enter it below" %}:

    + +
    + {% csrf_token %} +
    + + +
    + +
    + + {% if messages %} + {% for message in messages %} +
    + {{ message }} +
    + {% endfor %} + {% endif %} +
    +
    +{% endblock %} + +{% block customJS %} +{% endblock %} \ No newline at end of file diff --git a/templates/appointment/rescheduling_thank_you.html b/templates/appointment/rescheduling_thank_you.html new file mode 100644 index 00000000..715c917a --- /dev/null +++ b/templates/appointment/rescheduling_thank_you.html @@ -0,0 +1,79 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customCSS %} + +{% endblock %} +{% block title %} + {% trans "Rescheduling Successful" %} +{% endblock %} +{% block description %} + {% trans "Your appointment rescheduling was successful. Please confirm via email." %} +{% endblock %} +{% block body %} +
    +
    +
    +

    {% trans "Rescheduling Successful" %}

    +

    {% trans "Your appointment rescheduling request has been successfully submitted. Please check your email and click on the confirmation link to finalize the rescheduling process." %}

    + {% trans "Go to Homepage" %} +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +{% endblock %} +{% block customJS %} + +{% endblock %} \ No newline at end of file diff --git a/templates/appointment/set_password.html b/templates/appointment/set_password.html new file mode 100644 index 00000000..8c39db2e --- /dev/null +++ b/templates/appointment/set_password.html @@ -0,0 +1,104 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customCSS %} + +{% endblock %} +{% block title %} + {% trans 'Reset Your Password' %} +{% endblock %} +{% block description %} + {% trans 'Reset Your Password' %} +{% endblock %} +{% block body %} +
    +

    {% trans 'Reset Your Password' %}

    + + {% if messages %} +
      + {% for message in messages %} + {{ message }} + {% endfor %} +
    + {% endif %} + + +
    + {% csrf_token %} + {{ form.as_p }} + +
    +{% endblock %} +{% block customJS %} + +{% endblock %} \ No newline at end of file diff --git a/templates/appointment/thank_you.html b/templates/appointment/thank_you.html new file mode 100644 index 00000000..335760b8 --- /dev/null +++ b/templates/appointment/thank_you.html @@ -0,0 +1,53 @@ +{% extends BASE_TEMPLATE %} +{% load i18n %} +{% load static %} +{% block customCSS %} + +{% endblock %} +{% block title %}{{ page_title }}{% endblock %} +{% block description %}{{ page_description }}{% endblock %} +{% block body %} +
    +

    {{ page_title }}

    +

    + {{ page_message }} +

    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +{% endblock %} +{% block customJS %} + +{% endblock %} diff --git a/templates/base.html b/templates/base.html index 7599a954..f0adc4ae 100644 --- a/templates/base.html +++ b/templates/base.html @@ -46,7 +46,9 @@ {% endif %} - + {% block customCSS %} {% endblock %} @@ -56,13 +58,13 @@
    {% include 'header.html' %}
    -
    + {% block content %} {% endblock content%} {% block body %} {% endblock body%} -
    + {% include 'footer.html' %}
    diff --git a/templates/email_sender/admin_new_appointment_email.html b/templates/email_sender/admin_new_appointment_email.html new file mode 100644 index 00000000..4d75d8a1 --- /dev/null +++ b/templates/email_sender/admin_new_appointment_email.html @@ -0,0 +1,74 @@ +{% load i18n %} + + + + + + {% translate 'Appointment Request Notification' %} + + + + + + diff --git a/templates/email_sender/reminder_email.html b/templates/email_sender/reminder_email.html new file mode 100644 index 00000000..0c58b6c7 --- /dev/null +++ b/templates/email_sender/reminder_email.html @@ -0,0 +1,97 @@ +{% load i18n %} + + + + + + {% translate 'Appointment Reminder' %} + + + + + + diff --git a/templates/email_sender/reschedule_email.html b/templates/email_sender/reschedule_email.html new file mode 100644 index 00000000..00d3b08f --- /dev/null +++ b/templates/email_sender/reschedule_email.html @@ -0,0 +1,93 @@ +{% load i18n %} + + + + + {% trans "Appointment Reschedule Confirmation" %} + + + + + + + diff --git a/templates/email_sender/thank_you_email.html b/templates/email_sender/thank_you_email.html new file mode 100644 index 00000000..1f9b23db --- /dev/null +++ b/templates/email_sender/thank_you_email.html @@ -0,0 +1,290 @@ +{% load i18n %} +{% load static %} + + + + + + + + + +
    + {% if pre_header %} + {{ pre_header }} + {% endif %} +
    + + + + + + + + + + + +
    + + + + + + + + + + + + + + + +
    + {% comment %}{% endcomment %} +
    +

    {{ main_title }}

    +
    + + + + + + + +
    + {{ month_year }} +
    + {{ day }} +
    +
    + +

    + {% trans 'Thank you for choosing us.' %} +

    +
    + +
    + + + {% if account_details %} + + + + + + + {% if activation_link %} + + + + {% endif %} + + + + + {% endif %} + {% if more_details %} + + + + {% endif %} + {% if reschedule_link %} + + + + {% endif %} + + + + +
    +

    Hi {{ first_name }},

    +

    {{ message_1 }}

    +
    +

    {{ message_2 }}

    +
    +

    {% trans 'Account Activation' %}

    +

    + {% blocktranslate with link=activation_link %} + To activate your account and set your password, please use the following secure + link: Set Your Password. Please + note that this link will expire in 2 days for your security. + {% endblocktranslate %} +

    +
    +

    {% trans "Account Information" %}

    +
    +
      + {% for key, value in account_details.items %} +
    • {{ key }}: {{ value }}
    • + {% endfor %} +
    +
    + +
    +

    {% trans "Appointment Details" %}

    +
    +
      + {% for key, value in more_details.items %} +
    • {{ key }}: {{ value }}
    • + {% endfor %} +
    +
    + +
    +

    {% trans 'Rescheduling' %}

    +

    + {% translate 'If your plans change and you need to reschedule your appointment, you can easily do so by following this link: ' %} + + {% translate 'Reschedule Appointment' %} + +

    +
    +

    {% trans 'Support' %}

    +

    + {% blocktranslate %} + Should you have any inquiries or require further assistance, our support team is here to + help. You can reach us anytime. + {% endblocktranslate %} +

    +

    + {% trans "We look forward to serving you and ensuring that your experience with us is both rewarding and satisfactory." %} +

    +

    {% trans "Warm regards" %},

    +

    {% trans "The Team" %}

    +
    + +
    + + + + + +
    + © {{ current_year }} {{ company }}. {% trans "All rights reserved" %}. +
    + +
    + + + diff --git a/templates/inventory/car_inventory.html b/templates/inventory/car_inventory.html index 8355d1bf..c6a7bbc5 100644 --- a/templates/inventory/car_inventory.html +++ b/templates/inventory/car_inventory.html @@ -34,7 +34,7 @@
    -

    {{ cars.first.id_car_make.get_local_name }}{{ cars.first.id_car_model.get_local_name }}

    +

    {{ cars.first.id_car_make.get_local_name }} {{ cars.first.id_car_model.get_local_name }}

    {{ cars.first.id_car_serie.name }}, {{ cars.first.id_car_trim.name }}

    diff --git a/templates/modal/confirm_modal.html b/templates/modal/confirm_modal.html new file mode 100644 index 00000000..da3daab8 --- /dev/null +++ b/templates/modal/confirm_modal.html @@ -0,0 +1,23 @@ +{% load i18n %} + + diff --git a/templates/modal/error_modal.html b/templates/modal/error_modal.html new file mode 100644 index 00000000..0213a1bd --- /dev/null +++ b/templates/modal/error_modal.html @@ -0,0 +1,21 @@ +{% load i18n %} + + diff --git a/templates/modal/event_details_modal.html b/templates/modal/event_details_modal.html new file mode 100644 index 00000000..5f141122 --- /dev/null +++ b/templates/modal/event_details_modal.html @@ -0,0 +1,38 @@ +{% load i18n %} + + diff --git a/templates/sales/invoices/invoice_detail.html b/templates/sales/invoices/invoice_detail.html index d65994a9..b17f5159 100644 --- a/templates/sales/invoices/invoice_detail.html +++ b/templates/sales/invoices/invoice_detail.html @@ -55,7 +55,7 @@ -
    +

    {% trans 'Invoice' %}

    @@ -82,8 +82,8 @@

    {% trans 'Paid Amount' %}

    -

    ${{invoice.amount_paid}}

    -
    Owned ${{invoice.get_amount_open}}
    +

    {{invoice.amount_paid}} {{ _("SAR") }}

    +
    {{ _("Owned") }} {{invoice.get_amount_open|floatformat}} {{ _("SAR") }}
    {{invoice.get_progress_percent}}%
    @@ -135,9 +135,9 @@

    {% trans 'Due Amount' %}

    {% if invoice.is_paid %} -

    ${{invoice.amount_due}}

    +

    {{invoice.amount_due}} {{ _("SAR") }}

    {% else %} -

    ${{invoice.amount_due}}

    +

    {{invoice.amount_due}} {{ _("SAR") }}

    {% endif %}
    @@ -259,7 +259,7 @@
    - +
    {% endblock %} {% block customJS %} diff --git a/templates/sales/invoices/invoice_preview.html b/templates/sales/invoices/invoice_preview.html index b077abc9..55facc0a 100644 --- a/templates/sales/invoices/invoice_preview.html +++ b/templates/sales/invoices/invoice_preview.html @@ -1,3 +1,4 @@ +{% load i18n static%} @@ -44,6 +45,13 @@ .invoice-details { margin-bottom: 2.5rem; } + .invoice-details-en { + text-align: left; + } + .invoice-details-ar { + text-align: right; + + } .invoice-details p { margin: 0.75rem 0; color: #555; @@ -119,80 +127,84 @@
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    invoice

    -

    Thank you for choosing us. We appreciate your business!

    + +

    Invoice / فاتورة

    +

    -
    -

    invoice Number: #{{invoice.invoice_number}}

    -

    Date: {{invoice.date_in_review}}

    -

    Customer: {{invoice.customer.customer_name}}

    -

    Email: {{invoice.customer.email}}

    -

    Terms: {{invoice.terms|title}}

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Invoice Number + + {{invoice.invoice_number}} + + رقم الفاتورة +
    + Date + + {{invoice.date_in_review}} + + التاريخ +
    + Customer + + {{invoice.customer.customer_name}} + + العميل +
    + Email + + {{invoice.customer.email}} + + البريد الالكتروني +
    + Terms + + {{invoice.get_terms_display}} + + طريقة الدفع +
    + +
    -
    +
    - - - - + + + + @@ -201,7 +213,7 @@ - + {% endfor %} @@ -210,28 +222,29 @@
    -

    VAT ({{vat}}%): ${{vat_amount}}

    -

    Additional Services: +

    VAT/ضريبة القيمة المضافة ({{vat}}%): {{vat_amount}} {{ _("SAR") }}

    +

    Additional Services/ الخدمات الإضافية
    {% for service in additional_services %} - {{service.name}} - ${{service.price}}
    + {{service.name}} - {{service.price}} {{ _("SAR") }}
    {% endfor %}

    -

    Total Amount: ${{total}}

    +

    Total/الإجمالي {{total}} {{ _("SAR") }}

    - + @@ -245,9 +258,9 @@ // Options for html2pdf.js const options = { margin: 0, // No margin - filename: 'invoice.pdf', // Name of the downloaded file + filename: '{{invoice.invoice_number}}.pdf', // Name of the downloaded file image: { type: 'jpeg', quality: 0.98 }, // Image quality - html2canvas: { + html2canvas: { scale: 2, // Increase scale for better quality scrollX: 0, // Ensure no horizontal scroll offset scrollY: 0, // Ensure no vertical scroll offset diff --git a/test.txt b/test.txt new file mode 100644 index 00000000..929c2e93 --- /dev/null +++ b/test.txt @@ -0,0 +1,12 @@ + + + +from django.core.mail import send_mail + +send_mail( + 'Test Email Subject', + 'This is a test email message.', + 'info@tenhal.sa', # From email + ['recipient@example.com'], # To email + fail_silently=False, +) \ No newline at end of file From 0ea8d6a22075f8462baac3254fe36e3add6f8bde Mon Sep 17 00:00:00 2001 From: Marwan Alwali Date: Mon, 27 Jan 2025 20:40:32 +0300 Subject: [PATCH 3/3] update --- .../__pycache__/urls.cpython-311.pyc | Bin 2157 -> 2072 bytes inventory/__pycache__/forms.cpython-311.pyc | Bin 32295 -> 32186 bytes inventory/__pycache__/mixins.cpython-311.pyc | Bin 2391 -> 2391 bytes inventory/__pycache__/models.cpython-311.pyc | Bin 88748 -> 89883 bytes inventory/__pycache__/urls.cpython-311.pyc | Bin 23872 -> 25381 bytes inventory/__pycache__/utils.cpython-311.pyc | Bin 23390 -> 27328 bytes inventory/__pycache__/views.cpython-311.pyc | Bin 174321 -> 178219 bytes .../custom_filters.cpython-311.pyc | Bin 1896 -> 7093 bytes templates/header.html | 2 +- 9 files changed, 1 insertion(+), 1 deletion(-) diff --git a/car_inventory/__pycache__/urls.cpython-311.pyc b/car_inventory/__pycache__/urls.cpython-311.pyc index 96a4e3f03d3f42627e28b24a33835fad608dba0f..18c91183906ec5afca18ddafada6c21ab8edc14a 100644 GIT binary patch delta 91 zcmaDWFhf9nIWI340}upno}Qk~!octt#DM_;DC6^yjq24*Y|A(p7*=ykzQCl*s51E< hlO&_+W(nqfjGJGvI5RTJZPsIZ&B*joaIy)9B>;Vx6>0zg delta 169 zcmbOs@K!*5IWI340}!mWpO&7Ht1V*!vVj-^s(2X~qWDwTgBdi{H-BK-$H-sBR*;jJSFB&f1*SKz wWbt5RG~fJ*^);jP4Hk|Dmkx;u<`c|k*jyCWxFW1^kwxeG~6h$#Je%q{G_L`YFbV~eY f@v7_0mTZh%9~dx+39eK8KZ3-+V390x1{wzdn`Tt# delta 377 zcmdn>n{oLcM&9MTyj%=Ga4>vY`qhcNl8nbTsy8tS^QCfRxq`$&U>OSo!)lhzyO<*L zgj0b0=?tk1QH&`JQB0}KQ7kEw-zn-${-!AJnZi1UDT*V7Eto-*{g+U1Vos`mQA%o& zTYgclo^NVN;w|?0_{5x?`1qn3KvP~a1BoIZAfd@rR1BnUaU|#G=BDPA6i;4I=w}!J z6l#FO8v>FYtTzOuI@lhFt4=7LQnw;(L*NSU3*r_R#VxLgTilRPn=Du)!p_Pp%=LkR zd9tmx#$^8@UdLh^6k|Rxv9SW>F^P{Lu`gI8HYXNEF*E+yyr=XvGi&Su*Cqa&S5;nT awq$1nnuAG9aGm1+5hVTvi)4{A&@ll0C}*_* diff --git a/inventory/__pycache__/mixins.cpython-311.pyc b/inventory/__pycache__/mixins.cpython-311.pyc index 6bcef338f68806ff9c0bab6fca9171b9c8d0604d..b69c4e092dfce1885a05ac04010cb0455a6e5386 100644 GIT binary patch delta 20 acmcaEbX|yhIWI340}yQ5Jbfd#4<`UVUj?=R delta 20 acmcaEbX|yhIWI340}$}XPus}t!wCR4?F7C6 diff --git a/inventory/__pycache__/models.cpython-311.pyc b/inventory/__pycache__/models.cpython-311.pyc index 68d5f23050abb4db37d69d84ea6155c84ab01bb0..c4ce307c3d403f05aece48617f1a4df70e6c6ae0 100644 GIT binary patch delta 21253 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 aW5Uc*K|0YN>^0n$^eyVY8=#RD=Klc-#R)tB delta 20454 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 Tk>gHS)}%tFEZo5wwwL@5m2)<$ delta 2437 zcma)-eQZlRRzQhXY+ z&6El@;`4w726m1uY|v4Zyj$-i>v;?Lu(h;kQjW{Vr*YRs^1HTibe6c=2d!>&na4iZ z*adirT(7N$QyQ-@HAy~p`jija%TSkI2+4}Z4<}Y1{0%nkF3=0|mc6ib5%6^|8$XQ% zKcAl>Kdp6v*II?C$+HZQyCR3_0a!V+kTa8LhkNejFJBm^&aKy4sB>VcnmPlTeT>@2 zmIeFsp%-Fmh3DeYOOIdLv6Wkl8;A|sU+S7=GD}a?v3^PbVG6`2D2$S9?2(OH)2*;5j+Qe zN_1l^5s|0zUU36#{w4r2vl>GF=`Vo#X$WV?TN~R-USr0uv0w6sJV`V*D-N$0ZF;!G zhWXKZRlzER)dMRRMkbrbKxUlpzf<8LPi&&K_fuiz#EP7asVk84y8yMoo|Ba6&2=X9 z146d1uetyM<2q zt^N(C{M&cZXuASFUI)N?9>#Bx^Su?#*TC>&z)t{gGq^4I;pgF>!_*?V(Oc7h6~tcv z;HKdsze5qsBxld8+RdRIE(**BGo6 z=57Hd05{3S0iRK4VyE))z#ReICQBpROYa2_E8Zd2(F)VgK)gX78LbiDWFot7tKowA zeR6Pghxbn)ehcQ1UUG~TMgj-pp_q)nonNn)%JEb*H5*(ljlaU`1)_~M*jHVH{zpLG z&vT?SQ0=}6dOqO%S{MYJSB%PJ_NI$fWgFySWd}$ zF%-dSC&X~;@oCbzznWFe=zib9A2EYlz^q6)y)ebPZt^gD#Qo4&*SHrk{v~Y9zgoBs zx+NMvmSD{_2%)8pCozwhbqosm)m0(v~*O;-MB##?qO#bY_Lhb8#xvk5aguDgJbT<%x< zzw5u`XLh6c4<%*f?D!tDpf>H$3cG1xw_4au{ye^IY-y*uKd9PwYW4|gpU6t}RN9b{ zdec&`CiPRPKO+sMr9t&e5jA#Hl?F8lQwe89Cly^8(VG^%nz)&Yn{y?crG14nS=hZ} znD^(b%DDqa(Yhk@IY(BoWd-qEoP|n-bs3>GEwpMvI~CeVRq)g>GLG=ewzbse%GjFI zw&rUNx^++;IYdV$)!Dg!a9j^R0Nr4aABGmt!#@f=00w59Mf-Tw*39hU2$&g9n{tI@ zIoL9`)Sw0qsP;b1evsM^W~EvxHD#opwA7gHET}xk{V(!I`7cW>(@FpU diff --git a/inventory/__pycache__/views.cpython-311.pyc b/inventory/__pycache__/views.cpython-311.pyc index 04480929bd33fe9678b1b8abe2620c58fbd9d5e9..99c2be70f0bb9e5009c441f10d80de4f3ae4e4dd 100644 GIT binary patch delta 40761 zcmc(|34Bz=5;r=1l9?=%l_Zdmkd+7t5cYjd0>~N&yNHG%Ge964X97Y12ShGz2zb74_le*-`FDxXwQI={4H(fmaf8|QE2u)OkXDmKmE#Lsc%*UrC|(#Mr=p8pT}+q-;A z#dY(q&HMs{!OOO3l|gB} zwp;sOYnZ=7F=rlHz97nke)XUEn)XCc^6*<3cL?DQwaxUyxQ*k6 zQQUCbXo?M{^z`dWf4deFoGhf)Gq{VmLz_hKPHky$zPL*}NY8g`CxW|ly2qApoph~X zA0;{DPH33FQ~Q-L?$tUQyNF%d5M!Fyt<58NpSIeV7P*H@olT|Au}#++j0v6Q((^o9 zu^)90XpP3?!F#QjQ;qjo7Z7~VdIiD#)+-4f;9N>5DqBhh$ zq+Mz1A`WZoOljg_?H+nQqCH{il62I%obo+pEhqShwSr)swUXdJwR5I~OCRO(s;Rsc zR9=x^d5>|dO0jl|o#q!?&#^TWyHblWCk#H$@2lwjD#EU!nj49K^sE2Of1K!E-G=Tb zv^zq&IR3?H*HYSb0qA&=W7kvc)dA@EH|6VSlkZa$x}i&*mDY!}w9 z)@|2{`7iO)c6xf5pLWpGNi8a@i#VnA3`<_}iuHEFf7L1pzQ!foK_%SDCCu<+b|c5% zMe%o2ynn+saqK-5yOWx=bq9N0dpImjyrI2Huvz;$EY0yIap!?H+>;kvba#!kRCCDecRBVUiakuR{-XFE$39H4M>ws& z=)F%=9c@F^2ioW1UBri)$(%O3g>!h6a(FC2{vUB{J;fdmnE!t%|Hs?p|FKqU?$YTK zihHt6+!^g*a~H>_)~AUtpII9Se$Hh)LuEW0fP(*V>~j?Re1O=qRK^Q!%J_oQyhv&O zLuveF;7i5eAbop+qF)M-qvpVjG#* z*}m%aytRqA@GU2Ooszy0fT-`R&4ly4^-Y35Sl=S}qxEfqKXIzll;W&3BwdynGYZzK1=aNGwJ_n~b%sjty)`E#kSi`Et@=~u@3h_L?KMz#OOaUWCM zCp~R5{EGhFdWMq!Vg2-4!*(&BhDzf7XN3AWjTSLcogDw8=d=D<5~jkKUr_9q{v=au z5XXK+v0wXFmSTg6)8F`u1%(?q)j3Lao|w#n5#=2s3BjaokLr{aLdm}ikUW%=e^1GO zAZ-`#pafwY^dklRL^-z6{e%(D7#9fR=Kz$NIrbNdy-1^8t45==5ghv~#r_t6Lyky} z{+*)#2#|FYVo9GGz<8?&fD!G&P#7bqt=tg_F)o~7#xW9(r%O0=0U@MV7m|sQLVS@t zI30+HP{hxVqo*)_inry{b9ew&Cs4SVaXPy4j^Ml_eX60CPZ@S{p+qrCv=0iGP8f-l zT?}WJL{G6KkUaX(a|ieML(g&U5s04SF$P(|IU=RJ^L9~@O!*|k?xV1dCUX{Z?erU;3@+ zN`L9MBAfowZ^b3_mwqd{(O>$l=uUqf-C=oh8+YcK6NNTHwxzUIT7;V8!b@R1BGH!I zM%Z#)IH`<7#M*M{H=|8nJzRL{MT|()Gh$X7#GWq1Ova;HF<#d;c)hG~GY#Fd>;4gQ zGFX_k83}nYr53ehaapCMveZ^$wbWSZY7?ABQL4>O-e>Rd!p+gaiw;? z>!o6yHZ;52G(8P)VyZ26`&Ct{wWPGFa&ehj;VsW;tX^7GY4a%-C8~EKnXsul@p3P~ zF6~HmYSJczM_O%`a+_LWFI!T%vRXY(VOrg%+3yC$Zw4lC)F<5Fl=fy$R})7(A!AdN zB<-gD{k6%tkB|lbd+q@9Iv^eaII4~8k<^7#zeMk~u@kB)Y;($NSLIpD?A4Z<(xuIs zy~hl(Su0)@U+3&GJ1FLDq*DM+12k%*dr#}%K#w^w>IwSej9Fr zW$G)y(Hrjl0hcR|*YMs1&hrq z{{jpL_!!{IGk~806cWfWtDeSJKSQWr!+(yjK#gst2-H~raW}P=FeFEq>qZY5EwY)H z|3msO2-tm^=^O$9{%|$ZV?$ldbk5aG1M|NIP6Ghv!=2-MyaHrVX7)IG*x>nhIzDs5 zRQ%KNzc*+Z*Cp0HJnUYP!2KZ<{b6wxX#l++XqFL4Gg>GMr)hDSt=wvNhOSs?Q`gvS zH3y8$6lXZlb%}EZb5dpw%es+LqUx@SU!>RCj?|;%is4F}=%uxcSWMkD=GG)_;m8j% zxz}wW9F=w07FOqJ;i&$izjo`WLa|v|nnhCG`B6qu=IOJ}(6UPEd8AnN z7TS-@3J5qu>?=!4ZFalf?RA=0S<1_-2ZHssWij+p9!!b6ghvu5YZD7C+J=K2O+&%f zxpK#FB|+OhX1oKOKOl;7qWt^iWRwnRa~dnEthRD>3Z6r#{^P-6LHX!?7kp7e@rr`f zvv~EFh940K&<(|}riTl9vudepLbL|ENn4a}(>vgg5RbY~^WPTTZza6isEL(a)pSc~ zO<7f?dK*R6K*Q>3~0_! z=1obN)fv3TW>II+XvTQQKwyHKKuYLgr>pa7yC)7FxstG)!DW?;tDNRC8oy|0t*|V& z`3ztY?qD7;ANiaSP*A~e!+x-@9b#W@A7 zDOC%Ap!ay4d7j*zCNfaUsB5`9JM~jkFp-#_LkwOCbic;Xeq@d1zYt%yZ*h+xk)gd_mM^+$@ypUl z5C<+Bx3GkgsnF1B9{{gvhGKL^!HOuaDz%iCR9Y%*YG2@NL(L#hq#wOH*h924ysW~q z#6}Y%nmXL1IhUm;pmFS2`AGNtP`8U-o+^H=%UfP7M(gY~`LmbpVKyP|MVSqhgO7Q1 zJ;DIK*PbdLr;nJ|Yw6b|X#*Zets7I(TVW-yvVw!86O-94@alZ@TJ-@$31<|I6D1{O zm=RdW_@KsS#qAnb3GXP1XA8y4rM(Di0pMQNpPq8UbgmFX2DlR0fq)UfON&m)9tyLE zQLHatGOK%vRBc-I(-;HJ#%t%^Hfr5heD1($Gfhaca zTAN6idenBIfsTv~(lS-*nmnFcY1>q@sSkB_`zoz?b*47!t#s|b>X5-`JF?RKdWM%p zF`&2y0cZG9n&*|2TNaT8^^{g@?~}71aVRjbsk9r>03Ef1_H`lLhjxowaua24iZZOu zQIjBM-AvI3Lj9$eYiLIDod73L1WYnF2iQpDr~n*@)IMLCDn@A`t0wXsw50!5WWsV^ zhfD;^0;#)vrRRIsrMTpjs!bfzllCZMQzi z)5|{2{UCDpYbLGR>aND|)E?hyec#H`?5nf8aZ?1eUY%jopoLZCRjOT$(VkwNI7EN~ z?qF=HhT^sTmN<%NfT3FSnvHr(92HVbP~xyavkq0Fw=>X<8>ozZnpF zXBbR5U4`%*kE_Q|m%3|9EyEpkFw%2WF`fW&f>d;0^-4WTe)O?O)ao2JMsSyU!4>-D zE(%?=VaKFE*}RBs6t*^aSfFPM1v$fYn-$KR)&mkn*7nz$HpOebu8EJx8v%o^w5pVZ8_$Q?-{o-EZrgCDRxTT7n}YSG!cELC@1tUx;@L+L&&%RxiQz+=y@Gs01s&2 zZ0Vuv?$_(muPYOyAE8j1w*=}2-oDIElEAKr$=f=Ix&25-v@foouA9=@>>K_!g)?Ba zPyl*(dct}V`pHL21nDZAwFE1OAVT-de$ioS)3oW^60}`6hKoAw;EhFkCzr2fD&vM7 z2rg2+8sj+X6Qqtofm}Z8kv94Qd3L2d$z$`3Ssd4n-PFxTaeRBzoB^D;fwH08SfO!u z<r6k)d3kszjJ*3D;on&6@kAt+7TlMUfOUl#bdDTR#!6Y0jII=Wwn(hvi|8 zIRhbgcF4C{%V2C-%4gctRb?~*_p#=GClvJ$00Y&+Gkw^g8$uVg$=fnTgI2lC#xra+ z8VrdEC^=`431m>8VMmeD8n63T{U+Mn{(g#!2@g2sZbps-LJSANg(F(uhvKyI?Ynik zYi66F$BwPyP3`d=+j=`eUobZqS%{04*-C5vtl_jnTB@9urI^Lr+I_b`+rtfV=9a5N zA!rAvt+eG@R+p2g+EIYE0(F-1$T86htKqx8^8M*bvi5`4nKSy)@jj>t;Rbh_F%Xy0 zbfe5tu6}_^dD_VtXYn*q3C-j5Hfo{r$S6SB&JcG(mj6ZsMcHlTR6Cosq^!nPVb>`$ zQA|31xcx#6>NiwSZMt?;OCqNXm;Isk@NG+5i%?6t3QE-v0RoFbUzzFnjOwU<1RT}{ zEDEuILlo5iB8>oGor3=AjCQ$#N-Aj5N+zf7c{vLt(5$uprv+$eIE0D9t<(A=Xq82;iVj-Cun5^lh+r-H?kg0N z(275c(>C6HtS4(ZFiaOB6S*I3HMW3`+~2e-?@1DWXshojvZ36zGaerE*zwBUlp7Ge1*|$Affg|0y(6f|e{)Z5Hk9?pP6_{knTY26Hm76nugbVziz2b@nmHxb0cF z1!N(urcoCo5KNTbMV%>MH5l=_0JoX;G81*uk<}Db!UTM;BnOgTT9_umCXk@L zcK>*t)=&kGYnrjG7NYL(1N(&orm-`urm93=eA2rdn#jErz}=cjIDmrp5^#ptR+pBq zBo~~w86hmrAWM0<>K&h0a9fZHt?!-;FxBp{KGwf=FKTD@Wr-{;?7@3ngFG|x=?C`| zu{?TAdH3w=8}KB6u+gx65=Ea!eA_|b8|}#cOGFRtt^MOjjx*-c0@}a>-%s#X2(s!l zFIKB6+^k{2mB^FD)hnc@3Dw@(X3F|3n-p8?qtJ?&}PrBx6u3 zxzNY)Ruez%sY4y-d57<4>Jqb5OQn6WEuf>E8RZ?s0}4CsJTRyLsans6?$>3;tjLW+ z$=Lt;p=BoKew=pY;l8=F1aDB;-VN66U2dK@gkrAi?zA*P(;h#ZY)qnvVcI)~N3tR< z4U(3%N_<_PhxY~PnI>rO9b0C;6WqNEV5?UANM;e0x~h@z^Rvc+Y(+R#m^eZYtZ)m%31o*)|^VcWF%b!pSsC}Z80 zff&w|>zDw_f=K(?LkK%v|6vo%8DC1?bPvtsq*SX`+0<-GKc?fw-`p6a0>%^*OG$YXVJ)LWQ1Zn@Rr!8KUq<#PNqvN*Xm3s?Ujb|(-pV7}d zMaoCJ@W|Q52-3c8$Px8g;xiN2%n!VZ<_s@fX{UV*#3XAgL*EnXXXvwf_yDEyh!Rjo z^d{D-0Q@p_J?tf_4c4{Is)c@`;}SszIqMC zx*L^!McRhv)ldg7H!?1AtrX7AM zBa%BESI?-f)82h4BLSL+E9aT|LC40voXGB}m+SIgz6E{nnUkxPMgzPzak6@?Vyv5a zDp<^(OvI8xt*Rj(b7|Ge${KPiv>x2mSCM}%NE-)m1;AJWa`po>pa`VY^P51Ks{m)Ut6v?Zi_`?&aB2KD zxbDMO6GZkj;4queebfs8ZTm=4W48ER8{OEA`$$ncep4@9Fs+>7V|g2nU(d(~dB39= zmcMpq4MiXf;3xEs%PAF>o3%5I^Yn@o=@of+SO=}LX_2_UuBmC4h}%aQ&vJ&Aa=)~x z#Oj~5O>d}kSrsfn(JVl$Ab$msk?bUPq1$zzIJ?7Li+k*|ZbZUaL`$n4Kup)BG-ryA zT2=ESx^==%@8NG=Hvx3`IK3Mv16sX2fqYmi_|X$c?GbKmhF091pryYRL5m-~-kP!m zZQE8u#Uopm2WIIZl+8kM7*9Occ^FSDBV2qyeKZps2Z+*I-ddy2(`ITVZ?6+`VTmVc zKfL{9&$$%u471s5Xtkt<+$jy9D8$Ep1y@}a)!skdX%KCLbkF5=4b04Btj~bT7G>+n zJMl=%eW$yrHw_~81-#Kgez-$~YAfFrz#s$i{9WvF_yiw+P*)*rG+fH_*XmHtJ5(V%Dx);BHiaWj&M(A{$FOv=nUvv6t|c z2expXQM_NPvZlo4mVr*ARdt$f!HGdi(mPg@azduuBT=4;lAVKsD=B|pJ%t?N$#+tM zh!UE1xJ6#Aq*VFf++zkA^EpXp)cg0-K+UVps8%d%V30XpwW5T@TIGkyrAyndTtq(Y z+gMdrv&K_Fbr}+}?p=;2R?_8o`m>s7Uw)XFy9tyhf^zHzL9VT+he9j{^$i~CW8~Uo zB~?>f9AfkB6O?%J+#Bo69}QB(7FuYUt;vr&cR_W?<6!}_#A@cDcOs#^`te|4)l8p^ zpk7+|Ne{C|*!uRx8?`l`q?;bY`;FSJPr4-V02b+HCV8zESE+NgrcdT}LPL=MZ#QsJ zoG$afYNO92^f-ifP8#jw&*H@X1C-`ClU0m1c6v*(mXWWH`^7cjp&6YO#o5s>7P3jK zTf`l7GsLE1s$Rn@sp`#?WKrFBXBJ?v!sd&z&t7-g!{E=HE~}8|YJfEayler@Yqfu# z?J;BvF&|H1 zbLH)!bd=0+zc%Qb%hT==h`>o?j@+x8L`#1xGwlNEZtd+Kv*)+VXwaqJ4@7|?neX`s z^Rvzx5aw;yy+{GjsLlCll3wy&o~UR~|MV(#n42$TId)S#S;Rb4GADjUChhg(RvqXU z!ff4vXg@bxza@HyP#>hc-vb9`5GL&%iA>$OcE8#f*{>bHEo1rO*wGxhf><$l3h=E2|Jn!}T(+bOl%pRoivEd>DAXq!0|ZdYOBvD%^ar;~`} zbj(PsueGt7-}oa-F&MQAe^}d7H>jHW2(tB?=Nv}O0!?=4%qh7Z2>f!}5iwS;)T0VE zU33tlLL7n#d#t2^@@-{^vzNY@LY=0S)zr>5*SeE#t9}MDxFK~DjyCDj+;(MoO*>|* z+^&cmQ`>p&2#>e0$w&1$=9lM|yv9+ABof8LZ2Mu~r9a>H}CWEBqoh0FWr_Fu?p z(W1Y(1=zF`k}eZK^;D2P~aTcXHt(2-Pw z`ZNIAP;J1|GX$tTFduM+aV@GXuHzpr>0IkSK(G-9tb_VG+C4>dPRa& zw1?$u`cs=Fo1#RrygySsaXGWWtEqT$;wADdXn{cJ^=1w*ku8W|)?CCBms$WkFZaHd z$FoFET1XIu@?iEcFj@U^KhlST+q;V7Qm~CW{W@d-j;X(TGWF8(6T-Y4LLO~498w0( zs0xd^+=pF}M1a9me|1+eousIq=5_-W5+Gx)$k4f>u+~yvk^OVUXa_UoJ(N}8sZS5k z1d(utV+65JQ)wB>>)ysv7JOT)EYw+$h^saUi4M^#DSB_sxWCj>Xlq69jHPKWPIJZh zP##N^kE|Cx#G9h4pJl=dF&eD((fRV1o+3S|0Tg%#us9$A%#r+7LFIZoru8q4CvdVO1vJ2&E8#G_W)Yrp&;PoxT){4Gxu z{OMrT#Y6Z*U=oj0Y*Gaptdf8XP$F;XEhgx`mL%EITdXPw#1(JmoF$jg0IIz_Nkf(Z z%S_t2EeY~)ACaIlCM^hSmGZYD1&i&eTFV_BwY1kd%8`A=cyTwMEvVnwSIiKO8!5}$ z@L9IXrIzwBef#w%yX+2>f^hXF0=mb56hR=H=`aM0^oMJ0)2#b9O8ERBix79j6F`7f zLgwK~JbNwho}O}ahr%Rec#3fBp#;+PAGc91@9Hm7O>1d}Y`@-p7RD?;=r1aCgFNs~ z9WNuNP?pXxmV*CRMtLUq4p0qJ$|+YleXz)v=7FN8&i~Bz`QKTd8Ys-BEacHuzCTbL z?eaOK=YIfS5^x#9u1cSk2M38P$E{S7`V~;n{O#;XYF$&c8;TG})2^L=7O??6gE>eH za6RfMrwkS=bdk-G#cRlY#uH`v;1H2Mu`6M@4gbkRoyv6lt(h~#!)y4&3K{=hzc^vQB>icr873P#5IU;_JO7Sk%F_Cmejw!Ol05TA}e|*p&s;4({91?1E6av5FMcmJ#B;5%VDKKchuWKK+XaRvw{Sz|Qv6)UJ`@64P-s&p6EG6J*Os zF`&Iw1oq1KC|NXoyN2~Ba0TEIxoDIauQ&WC=&G^u+fic7%zTP#XHTUwVw$?dQdw5( znw)s#FOUW+L_q-mHp!N*N=Lb?hhmhwM~fJ}9~B0$g$u|O>Oa|f54 zR496jQ?j;DjL2to$@@+H{8<~p`)dK%x{0mwAzOC>qL%6w`BR~=gtCXLqq=R4R}2SR5lK7#A^XwBao42aBk(+VoiAy z#XG}rN`W^fJ459!V?|0L+Z33;vaVd{QkLo_nKw?P7-tai&(%*GCvJ9|S3ivxb6h(H z*h`rCr(Qy$t~U4fDdbE(c{bkh1%!A4_`&>~h$pT^AkL0Qtj;{taS~o91MI--6g)9I zlLGnG)v1VQ276iO;NHNzX14vg0}(9|kh8xdq7r~zhpq*Ct_PFL+%87>UfzZf`od71 zxy0LxlZm&p3FXuJlquq{P&V^utye=k1Q=g%;FT9|^CM{bj zo+j6g-xFvO7%ff{4;*$iz*Z$mT#A$3W{U)oDM!v0m+L#|+IR+eSk!AEAD=C{6a*TU zSrSlU;1St^+5se!NZJ=+BdF{#N6gek!lGLoJLiZp(;{G&%80q5*X4m^(aTC$MCxLo zw@Z*8kCy@&pht-I^lu$OLAHEtt}yCkEY->QZm!rSO68_`qF2D);HALNGzrujmZ3<1 z{;u8-bD8L>7q={k_gB@=yo`j^aS3>LJ5`CSRpvNPg7%`0tU8WB{oufXGsNYKQ_mp@ z53oIeR!*fjBgR(Q?6kNy4u^?pV1|e|BRmsV?2q8-&mQCy>e<13O$_0+a_-6S1*9xg z%5!FYj|JiZg?9}4PVLn%KoTak2Yh#ZGTmOG^s@&7&0IMjOzjT%u7@z0EZ3aH+@UD# zTLRc(t$;z#*( znMm#OHmEnzJcD-m&r(e&-T+`EP%H2IL39btV}{md%5y)6PIAyP5#?Y;@R*Ym(08(% zxS+451uu<-Y)u(&vCL;O1`n}6VD0wE_Hf|63ZKWu74^3B8iK_?i zpUWR}Ulr-H)72tIR*q7_Wv{D5N7IeS=q5SwD)D*RHau?!xP^dc=Y^Z4a{6kK z>qw#kRSig>rtOIdFY%p0a=W~2f98D$G6(2@x-FnweAp;2Unwq;X=_AJ-D`Xpl51;4f5+{VgL_uaMC}GWezS6~{_tJTMpEyroRT@?7FjBnyPe)NFz~UA zy9q55G+sq0v?v$X_08;o$1@w_MmEKbl)cu9rM}w0xmFaAHjv^4vAzR$s9@hIuROd? zBxarjjUM@KMFXz@)uzbgYLTK04VACGAiBz&^&*P52NjV$=O;!n$m{Paf}Kfkyt%IgGctpc1ztF5|b>0fDrLk^K4#>-b60_Sz13Hodh z|4ez&Uomp#Cs2X2w{H{)34sMNccZvOOp(PK#f&8^jcpFpdU=qJ%-WU4zv$WbgF67D zW%xB>z0Q~Wbv3!~8sQM@>o3_PwkYCL`S513JRQwTt4Xjg&-8lx5?3jG>jX2_xc zpyA&p9sdxcBDq(uBUJM1JLJp%5Ysb|Ui~KueUyMF8LIFY1=J3dA6`cW_Z3@2oLDMX zY!Uf-Z`dG@ZxOx7RQPm@ShApj@ab3(v+)C@y$9K1!s-mNudHy!^FDL^f*SpBEnP9B zFORTA$fI*U(!4^T^&+7>aGgl*$f}oS##AZ#aVd%qr1Lt_Eo32j#(3POm06#Az33+T za1%xR9Wm{Qsy{3@-XP+-GUWmFE$%W_0cOkNH;78TRSxN`LdUH7$*XP@d8P+|wYUDz zjpQ%u!@Rf%UXY5W2`G4Bx~j}dt3PTCS}0hrjH@aa<f>2-}v+A4}z#Pp*SZB7Vz z{c`hHXI_R0JFi_^tD{GOBD9z#&v?C3@U?Gq+dn;oc1I= zIU{gU4K2IV?hm^8>lOLMF7fMh#zC~&!gayZD+F*hDnO{Qj<55BT7YlIb(1jh$UMOU(pzSiE%Yf@B@bCcaCWUA@@F z`@yp1eo@Z%AyUCSGca;VG*deNkVuki9uN@@ug`5a%DxX^55WBZO98x|X>Qe%q!Si7y z@Jd~VXqEwLA<~X$@;C7mL+|RB0L^$kg9z>#pWEt@X$y~Q$2jKy+&{RdoRk0DD|(qAU+O9O*_+2b>vnJxnOco4)n!DrDF|S<|XCnohra5{*v# zF!U`>Gf{99z+M1u%oaRx+wypU5y(CFIEttX$o3eXTFpH|JpVMzrTCwm_g#q4C`_fl##&rcXV5oLz&UR30L$HY!?zh)VoBun0- zBex}cqh!@1A}46ox?ownnWjZ!J|fTEqIGnk-qCSUioLs>{t@k2A+11>+QK8Tn&ZVz zGHe~)8QA6aPD;A=QbvUQ>JgEg;8Wx>7}orw9h=)xHiRl2hO7%-7V8eRnlPc#e@Za- z=bv>7;eY}BV>OMSzco4X)yGBhL}Ly7P_CbK25ZQ=U_uXCXS9ai6WscS*_q_SEYh!M z0ZHsKuT8_kemX7eYhAi_icrs>rO;fpUFD=Y(b>TlE%Jy-%lVK@y)nv7$i;&Pkga?cr*$n?`OiEqc`z8;g? z6w|Xgre|YJPYRKdw?yuUzBPJ#^!pL<%@HYg%x%2n(x!+B%@GqCBPP5bm)w}r>nP2G z1~$bFY>pe)7%}jSIi}g1+GI{|Hm7eG`+m0p&D};Ue7jrW>)i?))W&XwP2DCncbl|f z?6s4(hc^c&HwSk;oz{(Br)=-s6rA$DIc;}nlR2l^oI{Dtv8O|$Plx86j!oD-Z`52JyO2&xQOjg1H;etL-M7pQ)I?; zL3bvMi^?Q9Q>;Pv1htVfx+Mh00NGu-5YbWsmQi&%3UV5CF0)2J3z4bZhlU@*QDN3}iisK#?BgKV!QpFZAj%^u}&$)dTZq~cu(77(9jM0qj1q(VK zhW}P(NvZtlF)>6qWS@F5rI0NWW(@c6JxJ1kh}?)XhIF6F$kX+rt7$!W zwT!nXnvaVqT{+_jLTz*BXD0*#tcI%XEN?q5T<2su1#1i6o+wiu7YQcNME)h14fWF> z7o&vosgNI>5Glhj1~H8^Vxa0OlgFcsXE0ICl)t}!_YC3jdI^f-I(zIwWCiZduMc-IpOQ!H;npOtb-!c7j>#YB$2Vv%d0K5lt6_di|`=J};ik zizdF4SorxT*tZ;D!XY1efgBOf%2!_y{o9*fuu<@Lrx!WkHNcZ{+Ka-q!8k{kn3fmC zU~v`fm8AN<{}KByVjlwfKloEO_S~Gmu6fpggkG%1~kZ zht*OmL&a^Um?^i~Ou9Udc4^9{BO*n-BJX)geBF-p1!741(wB$20i1yJB}h70GD4TW zJb7#uN#BH%Vu6?hr{e+FrE2UG^lL$wsRvwJtdFAhjR0I7%G;->pOs&q5(AV^!{j^D zmELmZD(K>y3G`U*O8I!@Md|jvll@UGfEL;KiYU=*)SqjFyIt;8 z1_Wa(x%};CrR*TsVW8%9*WK|7m`;goZ0MvPA$iQ+~9w5=|s>MkcY3$r-_Nk;=~ zb3JV@-X%)k4IlQ&AcbK+(r%{)$6+?J;IJywz0Sm1(3H$ zx#TU{z8x)Ze@oobj{DKe?zF#Vcl#^f`KTGdA9CB<;s%}P`Soe1#Ye)->xR&uYOXXp zMK=dm9TNdMvfKy7G8Npdyc(Q!bOB=hG&t*R*2&&kBJ_7F#mzk7j@VXl%VSOvXPiI; zCCitb;w###TmP8LOg{OrVEL{gNdBZnpG1?(7oMG7XjuVnL_KRS}(BmBOcX7y; zk45ufuTO-XCvbfhw!vb zR((qI5w;E{Q-CvMj-_S>?V9&d?>q%%55Q6+>5N9c8BbIpmj}Q|VKgF z2r;U3KA&#)#x{H(&jI@eSRCLRa7HfbTUKc;agVbqkKQpTr2qv)KnZYP;Tg%3pna~q z^fQs|;BMp{!&wxV5#BDt<5@U6ve?U_h9G0m%Ot9=BRh5*zz9@>5fKEyE&T&xKO-va z@dU`8YxQHo8@bWXe@6QyFQY^~>cc-5&*5}|*G-W4C2fels=n8kqS`a!=6FV2wE=cO9gI- zD6!JD+h*4@AK+k7I*-yrknDGW6L{@SPrk=3R8}%qf@@qsKN(}*lu)cQCIXuw=x9n! z2`)6NH}E}}T{cmE&RExOhC=Vz;l-5Zj`|rti5|g)UZ(gNRy^rvid>uiy``5?diO{U z8Em*H5{%0z@CE6-NEVH2Q^)jQMY;&(5lE;%%GJM#c_m)MjoXDcL*zsF+Z4x)t)NWR z%GSmCR%$HoPvI+TstD^9+52}|gL2J#>l=R;or8RYiG8(;0oom7FX7fQqh)wo2Ai7P#l3oMzuc-QeH{0q3SP-zNnn{^aqtYbG^%>l1~+a! zmFmMv)GgkVKQonsCQ|Mw{NAQXu2Dfwm0HvhsLM@O;H1y>qi7BIg02Z7aNtP zBJ3O?AD|gq@JmW;6|{qghOQH+AD>EK5|-e#1(>djzWzV}5AsxDgJ<@*Uv4%jIka`* zh)J1Q#wJz38`hlBv#B`ul>t+#mbAYtaTX!*Y(U6g`N z6iIhm(x%Ln_L8OK9;Q32Su>N_#%=Zi3gvnkaovRPU8Zaam&-#DN=AIZnSV=!($$n; zCXODZnSYk-6{+lKXKE9uZd`Q0=GusQ0mRCPC}pZ{L2T4#HLIhP zv0I$=2-l3wy(q$S_W;+dEK;V$D5)Y>j*3yHx3gizk6dVUXDAx8-D4f?8<$&A8GtNs zYCdIkVS~Z_Po_mFq4I`!#Vpffm67^zwKbSO+rYOJ)~}0I=o1}%P~VXNeF4}=*+yBl z^PvfK46wZFFb}VJXzBubqE5*S>xR%m0)C5=e0>cqC$Nv-u4=&s#n4yA#wpjiHzU`@ zDVHz085P?`ps4K>FaQJ99l#eTlSMlp=L+FGQjcfC98ij{GK!4hQT>P&(z?!q!t&Tr7#d>|m5#={spJW=N21a|tyABSp!~B9+3KCBZ8ZwH>o4eB0i^$HI$M#c zDm3J^qBAd9>1^CdCC`&nla=Ra#zI!)D?LqXAW|rOx+Pp#y z!<~knlVIghfX@I}0q{s;q}O!%arJwso7zjJRaaN3HL#l36v``7mCmMe2!P58YPaDN_}n9b~o8&NT(PO&tp{~l z>FiXDJd#5#mexlY<&>_<4FBDOlaZyjXjU^kO#78}7-a!mFF)+6xVFEX{brVOGw`Z!464qU^dyaC2 z%MZOPN4Ywr2S}Q&V259t?3$Uh)H{*##sh3%N|B81KDQvAQqrbUe`k@(m7YpoRdHFP(C#=JMNSp^;E_W z;Os#n&kSfTW!2A!{24dp<-O>J?M-r3FD1?R6czN8ysMW|Mhv67EM=EG<%oV`>yyki z`F5Vtd%7QIm?`%j-pUm&qoDqk z-pU-sF^R(ItO56u87P{CcqzoftIoM#*3?j_&X5|*YFs2iALhhn7Iik#d33AWJI$_- z5Ja(hrw4;qyF*>orcbPqd-{=a*CLCH+#b&d3LuY?H9` z@|H60+wGfo&w(I-)3UL@vQBU3=X7g@II>ZGIY2R+o(I+o^0xs>mUyu~W1vzlvQ8lE zC4f@|{H;{3kNjwWk}x4}F}_B~cfXy3VtfT@SgE~=r!R&PvO0C07ZHkXwf< z^xak682EX(avN{bru3Gy7c^Z5J2#S!~Mk=dyi9D@KB(dxY`Op~JoxXLHlC8X>O91T=?jwI4 zrEJXN1(kP^!+Qk$WD*6F?Q!228XlLg7SZOE2ts@x*gkwph0&ybh|qwuuY1NQ*^Vrv zY~hrD!G=rzAF|oynD6XFHUcO=pv~_%1fs)uM z@Dx8?Zp^0-|NQTdNYPvFDp2y;TkZ5V?B9_6&p<9fj!Z6eyD2`?O_a5T${VA>WAgX3 zmPKb6W^Qm{+TDH^$huQmVQ)3$(t^#_v7{x3%7?}({aggM`F;(1HT{OXKm*;EpcP;M zG1}f=rWewA(lO&m(QTF=7Lm+Xy**6UjU(U6mBD=2y8fqeN)T=3uD^Jx(pN0XKvjbD zJA>HU9tL+d&ppXW!Q%+K=vfW%IO6rw^CrD!NC@0Y`UcN7JGx8d%@dU&Vxs)dMCDE* z$}&m$atca?4~EnI-9mT`q)q;h$vY=2gT*Y_G+EiimiR0cqo6tkfF0uOd~YBUsl#&> z!V&cplrWd=9VlB+5B6Tp0t%Do9S&ic(}0v=u8^*$YuN zn^Qb*dK~)4-_#40ltZ?#%QuP@d>n)4c%5b_|Iz1op?+OSzb}(LV7zGa=L%kC%v92i zt04b!`*6~Z3uY=q^*LD^>%+@dazzGK@P4)j>wBKfw6FAk1`7bJOa$e8LB`KgTwihd z8O*;g_7@;s1o#!e+YAq;{*Hk5xj$x(l55^fS*w2l(Zl<+6jc~0pdFS|vNTCcd}i}a zNUH#Kb3L)XmzZIpjHv&$)?hwt_gfh-8x|*A zp)^pRqPt$}Gp|&lg1X&|UIa%_Z9)N!DERaNeQAkiCTr5MWRR!2h@NXv7F2qPUV#$Z zCAt)`SOL-3Jp9P#B@h*{AXnvO51vYf6S2NE$XKLwGDcG11N9>pDRXg0g7+@<`iD!E z{b6(2hxH4%;yG)euZFS`XO6xOmGcI`ZNR%7pc$`k0+3Ro6>evQenX^dZ{2hH_hVkZ zR}4>6-vL?!QoT!0E&?~W6m6+Yu2j1A_#J}(ArLnM(R(H#*zZgNokE}$_oh^}2zAHu zy7~!n1sSfB(<+@QNU0>p56%?C$n{mqsvOQ0EAn)vfS}$gUR??GxP;`q@RY;Q|O6?WHyvP1Fj@x8!z`%E4vG}KrYTwU{0{J17GS! zqcyE&=_d?ax1DDKiAS-o3DaeKv|@}Xlm}KQOLXJ(8`)7+vi{D|0MBK#dhYBNVZS!7 zc*41@p9yeZ6a`~Q{SH<59)SJeKj5h+P&=YY_5xrOcJO!2eKr6r0}k(i@Y)%C4uF^W zS&{P*fHBB{c|HYCDFD0-`y@Cz7aZmJb&}pQnXShN$rry!AWUBecb&fOL>=wT`giThJRB3i?SgXZ8fD!~)({v@$Pn!V!kHuN1#08=K}}p@ zKq?4DL_sLW@sGU5qx`71D0D>f{_`ocTn5r=Q?Ret-kUce zyZ(4DP^RzV;g&mld$$#ZVZ%J<_ZM`ffi8d&p%a!&2bxdE_rsy%Ous|NY4r=%D!be_ za!YZwk}l53%&W=5xl2yCTIr*EmyXw8eYNsXu;T(XH-EW@uB7Ca;(e~W!3{P<3-H7$ z(L27(Mi?tmHdxsTVr86<2zJ_E1MzOXU_k*W3}1b(T<#32urHy7fGn4s=?x!Em&DMX z7%Uv?cV%^_I@{_`ZBmxdMMAicE5DDL2a0wH^R0Hu6IMpCT z0o>ar)sXg64Mh~d9=}u$b$I)!Mj#4cpEngTjaJP&k1w;+7o;zv?^YLBNK{L0Gnd+I zEM>HrY7ikgBWAcZTR`+E34ct2zdOx0$to)4X>dBC$MJ5Y*|d-`mA-#no)hYfFJ5U; zX**K+8oG;z7CEMtt)5uvj74FsgE~y54?8by9Tq*7b~5>m4^anxnI>3w}SkV`HaoExCCQ^*CD5oICb(R=0D;ptPiO27sX8n9k=71n9^{OjTz( zvk}&rwO|nu?Wadapk@uI!)Aa@0K*Ul@B~WFqM!|)f9HZtM#`}*(9;hy;?_(peOQts zwS9pH3u-g;t)abDmRNi5MS8C&v7=k?@sA?)Ymn0b;H7R9r~`No)IptjsXHA%c*9iu zQ#V6I2+c!IlBbLKN*F8o>~IW)uK09UbUJs>bRgt$e9-}a<~c)3N~~3-B_;kOjsb}P zFA|C0rGmt450&Q>#TZHlfP8^oy)hnYt2(**X*;yKV%w)x%?Ak$;K619Zr5=L12{=! zsfBps$Z?)>9r5VNZ3@j~1|aJHvcyYK20&Bm5;;7Y`c`+CWzG;QU4C3abBy}vEy@DL zbRS4QD_2~vJWFo60XHZgC9v0e0>UQ(OajQ3xi>1eE#ON+ozZlr)v~f?X`cJ~aBQ=tX@;Q$fD-yf7BA$@g^nBu@Jey z!$#YWu$!6t&`JcF7g_9OrG>bdc8N21V$t|%>b1!DIHw@=vPwvh`UC=>1^5c!9KiPg zKLW&2(dzX8y8(^@Gy>q;&}y>-kiXT+-#+D!htj?b{VS6ESwIz^@#9a~sXg%23!pc^ zFo5v@_;M3}0f|4#!{4jnkGrTCV)?Tl>MeM>4L}0i18}cGR}Aq5{d`kCU-Zrwqw~$- zeE+nH>y}kqBCN&&!~rA$@GY{Lc*+6j3BZFmkI6j5@`yPK5rqIV0A>Ts1-J~raV4My zU@5>d02Kh6?NnU-#PP6NIRKz$hzrvSbM5Wxg+ zn2!&D@i8Sn;6o>492CfhQ1TGnA7B_jKEMP3?33jUs4BKVs>=YdZ&1bVI^KQ8d$o9D z6K@E@&KiBE3-3fxv6Dl^HVIx>=XGjcK;~sw2QP~9ilX`yaGn9c!V|Cc@Jb20{n^9K z&SUnE50Dyr2 zg8&8_4O8gs0v>r>V)f4omem<+k_L35%>bJS{1Q5XT*xcSZKKpxl#Du$!G1?FeJ?mj z2)a#ug{H*SPur#}52kP4(W$)u|3Hv(u5*3ATa_J=865>3t@MCCL1GF~<^#j)U%yYu z4HD<&Zx4{?{Cs`yy$XG?=zRU+2bB!b^IS}j$U=gw^8ntb?GrfQdr#E)2zmW}WxgZE zAf|~XLy_lyqoL@uVQ7nBEl delta 37104 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 AuK)l5 delta 546 zcmZWlF;Buk6n@uhOKC+U0Tc*P6HKUoKurw03yT|zX>8L#ijZq%(ZRvN&6rb2oSZNQ z7NhB z3{z8@sLP=mmizdmy(mROVojNlk4_v{Om!1{% trans 'bills'|capfirst %} - +
    {% trans 'bills'|capfirst %}
    ItemQuantityUnit PriceTotalItem
    الصنف
    Quantity
    العدد
    Unit Price
    سعر الوحدة
    Total
    الإجمالي
    {{item.info.make}} {{item.quantity}} {{item.finances.selling_price}}{{item.total}}{{item.total}}
    +
    +
    +

    {{ page_title }}

    +
    + {% csrf_token %} + {{ form.as_p }} + {% if btn_text %} + + {% else %} + {% if request.user.is_superuser and service.id %} + + {% endif %} + {% endif %} +
    +
    + {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
    +
    +
    +