From 49c4d4dab1645093446c9b2b263411b903df524b Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Fri, 6 Feb 2026 04:38:47 +0000 Subject: [PATCH] Autosave: 20260206-043847 --- assets/pasted-20260206-043257-ab1cccfb.png | Bin 0 -> 20235 bytes config/__pycache__/settings.cpython-311.pyc | Bin 6112 -> 6112 bytes config/__pycache__/urls.cpython-311.pyc | Bin 1370 -> 1370 bytes config/__pycache__/wsgi.cpython-311.pyc | Bin 679 -> 679 bytes core/__pycache__/models.cpython-311.pyc | Bin 39301 -> 39301 bytes core/__pycache__/urls.cpython-311.pyc | Bin 11244 -> 11353 bytes core/__pycache__/views.cpython-311.pyc | Bin 134414 -> 140516 bytes core/templates/core/customer_display.html | 277 ++++++++++++++++++++ core/templates/core/pos.html | 74 ++++++ core/urls.py | 1 + core/views.py | 170 +++++++++++- hr/__pycache__/admin.cpython-311.pyc | Bin 2780 -> 2780 bytes hr/__pycache__/views.cpython-311.pyc | Bin 10129 -> 10129 bytes 13 files changed, 521 insertions(+), 1 deletion(-) create mode 100644 assets/pasted-20260206-043257-ab1cccfb.png create mode 100644 core/templates/core/customer_display.html diff --git a/assets/pasted-20260206-043257-ab1cccfb.png b/assets/pasted-20260206-043257-ab1cccfb.png new file mode 100644 index 0000000000000000000000000000000000000000..5af04b9fccd33ce57f666f61150e3f479d57e078 GIT binary patch literal 20235 zcmeEt^;?@w7iJP1O3?tt3GPseySo-EE~U5?cT(J;SaEkR?!kGB6)WyVibHYT@P6O! zwfi6Jwb%XtWWvmO&fLe(%oCxeB8!Pmj1B+*Fy-Z>Gynh){3Ea!6&d~qeO4&xW#pnE zD*>n;C;bB-AXK7q%~0NG?T6R-UoE-FqooffFUn|6IYD2_r8Oa*IvzdE(pb2XIEaCTt@lJW&SdLX)y;9qET0n} z8LpU|8YS}8Q5cS7Xs%DHl~jX0R)yJQb#IA0BUSKE0=$IRFXU^JQ`YC~_3I8xX6L(n zcvU{OiELfhGla)R_Hx%bw>%bS{H#)Zg`bzpsaf#~AT`JVz~(m9P#_)S3z0t=6`N{0 zQWJh?tcb6@yEUD`3_6>_Q(gZ`Q03e8*#bcMHWV0Gil(6j?k3|8b__5Gk!IG(%gt50 z$B&bf3+8bQZ4bj5D$VP2+TPZIL450N1A&3VM96@AIw^@>ZH+HTBV7Z%C*4DJ(eKrS zg^xTW)e!|6?4v|6NkW}H)`H@5O^)7o#Qx7U63MvTB@{hLA5N&OWh334v(%_2>lNP> zKR&)OaI?_S#b0ZUhug}39*~<`ioN#KK%B#F7)?E-VnsN|$~f6{N!xPWwB&SMs%}N* z9-;aQ_v3#zksz4mLQpf27Bm|{qNZs#%~s7zAl(zV+IhMtO1Js_imZbi1h>X$Qvjt+ zVPO*A=Le$VQEx1gW`~dq32>!^^qfl8>94=+`Ld}*x*dET00ck+Cmhe1`0^C9$DOg8 zU3!Ym>kIS60ZgU*G1{ur2kJPp-516ZOl7TD+SQ#LJKIyXs6ensG=!x6UQ(zD7y<{*-5N z!0knSzJ=OkQRfr4=za^s>VCj&52&%;u92uq$~S-Kw7Ugt`JRd--c!vS066`N01*IE zpER%UAAmL}5CP>^*5vAxwf5IWEV@njw6wH~15&>&;GBslC`6p#;ntq-x?Smwg1S5r$lx~JD1^p}z0^^pOXALGPfY&MwA_|Z6Z7;kb<)Vim z%5!mC+AG4I28h1%$ z)N(v2sGGEpgn5pMJ$EFW)Y+8@K}x`$uw3r-<(Ns%@tQ6+wpy+CmQ3OCLWQ9ee7%P(Dx@5b z@bBN+)AoP@xD#kEB?gV@qrD>DjyrYNj=R4Xre3E|`%>|w7Tm=fJX2aGyfylU#rQt4 z>05Y5FkDJua*Ssu6xyZ}C*8J$T9P3FVvL)P7m_2t2AM4<7_e(8i*?Z2uF$@e_RIp; zstkktP_9VqL@D#{U;we-Tr_XL*Pr%$L0Uwb#f^k<^CCgsF4o9c?#kSt$X&Flh9l1fZ$J=KtLzR@zy9S4WI7Mb4wTm4eS!eXQQpNz(VS#%7-J@S)V?k6`% zXig)dA2JFxB`n`?F9n2=QvC#!9_WAs4rjofh;M(BVf(4i9jARA$rabho-RhO9y8{% z3jwUi(9Vj`;;^Y31dA2+alZI1e*}Tph++EnQ$lnUsLl>z?HL%}x@#{BDdqbZi=u9L zarqj4ze~-(&J`O{4iWO$>vt|Zw%`RM@NxpMZv!z1+17WJyKSOYa0%A2`VdUcBoTO@ z1>gVtt}N1aiN<~LT0s+R>wk-s8J;xk^THbJ+1*Z3TP3z>zKRD2M3&!S3`M8e*_{P+)6k!k3oj-<4h6Pkb< z##`5#Ku`vzDD9JuzLFGXKVdAnR52~^V~%i4)%}$RG!x+^lll8b?NTcMDwGC_B)KrX@d64 z`!YPfVSR@NHP-p*W!G?*g#QH2XWxA zB7DCcrKK&Xf9O@MqEmh4_L2_n0p>FD<1x@iKc)!iaqQ zclI1XdtR@oRKD~GZXW`GMga(9h(wB{1^D}m2Wq&ZVyhjPut7(vYkMa)Z$|?)6f%cL zrTh~n1u1aV?cs9qnrzJ^%@lFb)<4wtL=jWRmsCE&#eGu1cy)ZiyG;5>BQqcrBDdJm6N9)~ z2SH*VU30gLvl{_&at)|jzY*522G5?ck`7Z$gFf8JOeCvg@Xa*^_gu6N;S2kY4Tcm7bUw=>F1b_H{?UPX+HsbW#6YB&LEQFC<+KXi;l}DTPiyFR$FY1>c16*NoRT zkp(qMI~Wd6$Ql6=0P2$F0LpV*w1{Pl-MsSbxE-AbM3CeK%BZ}YF6)?+Z7RL9$Ak{& z!w6vZYk+| z^`i{%P&xH82?l`qfN;1w%4KmOHrOCsLNNT%keJJVbW(c z4a*#il!Zusf~&|;9PT;BKqPEjY-CU%_F%TEl-n1$D^x_JVcXfYj#@ddk7Tl(^G^|5 zUiK1t!sbWTR$Kss8fkM;MQ<1f>8{GGxs5WIvBFC~z38V@$d^qCbG&uk$Ew=91!fB{ zlOFFu@CK(Ub#ryZKLAV42a!n z2MxJUg4ijd2*m9Vjx0$@u_M2odNTArb|7fIsTqyw{t|9e;U7yX^&7|ZbaZZQ9}5*2 zRVyJ^G@kL8#aK%@zlc5s^La;L89tn`f3hboHT#{Y)Bs2cv$3z;Iq%3PJrrmp;NVcl znNL@pv4W>dUJ-Bs?cTWTHHV|GdyJ0kg-ZeX}CF+A-{ zMU~U7%8mm908s-P7IZLgYUx`^ISezsXJAkP1&8l82?bf1!K=pEqqn30-&!PCwgMvlO`evT zY%o&uFA-?CFE*Tc!Z&CDP#_36`!^LE=g*7&Kni#f-rl%EAcika=3^mJV0bCpi)a!i z0hIh0>^QSH|HAYN8Gt4xA;E!&txoo0oe*juAQs!?5G*BC{om;@5dfr|`Cl^c0JV4Y z`E4(OT^g?INw0uXn)GnvAjbR$ASUGouULkoUU38D#1ypj6{Iw&;fq#3(f|Nz{HXEa z`>6kNN`|0TUXJ~;66M9LhOGc5SOA<^@V|Q`254#_g#mHZ4gY1v)CoJ#51SGJ{(tg+ z7ux{>(ZTT#3%Ke>XL1rV;ict>Kk-pOL`o7;nzk=2T2yYQ6S~QFI3C_ zp%j~)S0s)oo-Y^wz4Y?bLb~0vOf)!8=y0;B!^Dk%;dELQ2n1d==F3QxGu@9wl&ZXx zYmo9JY~}ArfnkvR&_QD|IMRQB@v-88F+or)87ZS4I1=1U_(9;Jq^awn5fXWBso&f$ ze7q0J$q7C&emh6g&JdoSO-u?6AJ!-C%L-h8S0a2bHkL3s0ywG%+}%uQhZ6?_C>&=g zZNB(Ez;~5YrhMZ10q`XejKhuo0^tnN;svISONJ1_tc-D^8%sB87#)9a1hh7*HmqY3bR!U;40sEkCmkm(YJ( zGaXTu&;OzKh>NX`@DkYQUW00l$A`56`N%^rs#y6HF{}??G+c401GG|%DD8S- z40Gan#A(wcKlEh|H>d|Hep;_S_>pp0pO9U;Z;=NE1^|K4E|wfy z^%JLk69?*=nuUJjiMoCN;d^H} zzPp)2;TQbDcvM#0bX(k=z4Ma5$ZOZIkc>~aEHivG2=0cwz;#FK9Nk=)TPFETqd7+_6>Gy58zMp09dUL&D4+)?kG zGoKFS@ors~&~G|=ME5*vysx9 zESlg57q|`01@Q#}=wZY0QqstDn;9W8GD=O4N9T2Mq`VA1Y^7zSG`~vjJZ~-DagR zU^3Mx5|V*Aq+((9OZyrhC?zYsu}wc{E|%jTAJ6A5Kq7hEhJoO7JvjOgdx1ri+R@0X zjibPbm%h_Ea1jviwewE9(lAP!Rq_ljYpRzD+NjIm{w*L-8fS05OZaYJ(DZ&)n9uiu zNI_8%hiE-+TwQ%{wiD&*(I4Q0MG70}5Ym0Dv?3&rt?;=JQ?J8h^tqk1XO6< zf0l$hjsMBv`tpeb#pB7FKc3Z9{h@}|-FYq_@!<`#Z~lnFHHYXGIh|i0kA|r-1wCG$ z)pY`-p&Cy=+Dh7p>@=@#@k_1^^x>Xn&?+ERYDVnPa^lM7$;=d}$xy4y5?COiNs2|S zl@6e!N@($8KK9&16B4#(Djv@c;oKV9Dv61Rj~^cE4i^W6}TSfZ;R4@CgWe;K_1P3iyM(H6z?4fpUm9D6k36mRgadq?FtS zO=&T1u7~8Ll>B+^SB$g|RZpjX|5i+oqx_eauhh<;=^NKGotDk-a?4!jJgCZ--#RSm zdF+)3sXf*z1Z|CW(xz`tp1;O_cVz#}ZV((Cshwwf(>JSQJ|76J6{v31p{hIid2%zM zTEXeO+;@8YcZhxIYn`?2TLm%?^afO->OF;13CV_dYB(}x-dNM4Ojui&{( z+>O6I$mrV{L3*RHn2Z+ZQWJR|4H(g3`(ngd&# z_`(b+z$U^DZ0HM9Q`3xgHXmHS4WmG!%mwMT`jb70xG}j`J)sdqAzh2|;^=EM72tzF zph(0*h)JF9&#L$Ms{yxQDMMl{YmSX4bJ^4W-~aIWGa+ypd#;L%)x3A&_k2f&C3MZA z^3gKautM=?ogdMM1_(AWV{gSl{y?A|pfS zc?oTKA2qgR1gE^*Dane8ica4nHdWmKnMLjiQ^udLpC4^-kgpHICc18shu$)&-s?BD zO-*UcD=0WwXEe>g(W9bHHzl{?TRa(4d^u2EkP;c&U`Ny}A^g=@ObmkneC3?m?eHvA3 z`c><4wRDN}!WyMAv{NaoZLyTR_N|w%hnDI-P1g*Mjxz;RGtvHfY{OX*^cXD7aOiCk z_K8o+GPL%yU_-+Ul0I{3c#YcNfD_ui>P%mVFSpX(+_3}??eLhEfOTW~C?JRWYM(H! zT_(C8-jnJp8(my0lm)#UXDA)>C&__RWsQpcBK1Lm-DW*i2sL5Yp!Vw{1k!rU9Wa5( z<1^3JRfgkWU%(UB6qkzWNe{v-w+5e_?&AYxUjFhDrD^kW}q61h!|0llGL=3<%J6mt+8mr{>c$TyDM;Zwbg0tlF(+xK_ zl58BsbQkHfQ8Ph}|EWl^?c!Cl-tKsgtdS{|x9guTekiZaPBwz#$$83C>vUOf_Om=rFMTN153WUFsV7}g z-K(6$OIL?I!8#@Dhh9Fk4#Ap=rtcMT@bM7=ayJ$TpC^o^K1%uEFWB*UJb@sK4dP;A z01@L3qH>!YtCrDfg!{Uy)EM3S5gFf%Q@p05#h8R36!VRHm!EC3w8`0uQkXBfk|IrD z;+r?~E~k{i_@39sE@$(K?3-u*B%YaXBIBo~m>l!2&C5QMtkdIP>`x+e!oyq+xvxq;yN!N zBE}6wO=cvx&GynM#YLvQIVXMj3of;uS9VH1J8$5oE!MbTa#l|i%`2s;1CN3oQlR1*I)S zw@66IDPEAv<~224gW#6q73Z5h^}@rIsMi}+lT|M77DK}d>^=De+&b`ejQo+lk7xA_ zR_QY}8Z@BWLt~E?3(VV5mw7&-9=AWbKUh9``__F-*t(N}*jT~Mdlf>9%R{^Q^;Ge6 z;i8$t@`vrW$9>IFe>Wx(-%IX?qw4kqzpGcciM)~_Qfg`dHiF+9uu0cU;hd<>Kh7jzXezYJwyn@RLO^)Sq;DJu%;Ir(QYhyXsBpu{m$+Vgim(fk$4?zX|X;O zL&EX5zO|*?h0xV%j=<+NMSsNTtB%XwsO^*H!?Vc?UVya8LA4K!KdV6~*lvF;TAX2kBM3n3p2yz#nzb2nEy0G4fsQj*CHP4tJy>x` zmh!I>kBWt5iYQ#lA<_VZd&3}-JHw#&CG|g2EwcGzepTshKFTL@UQ*!U;1VH<<$sXl z$S+_E!UjRL1D5&C5Cz=!0;BEjZR^J~#YYHOPe+5WOlLc8Tbdk2lOzUiqX}BTlA$fTE+63mP7tbFn`0&W2G$*smGNpQLy`!B8Ya#8qeJnde5sKBd6r6 zvRMzYZ|$=H-RIy~m9Wz1n7~_MKD4-+_IZ{(cGs2X^yOH8y4z|VfVoc1{h`FiYf{{9 zDmCzf-z{9hMvLEEqhNrh$=PfBJQU3caC>8j6sEM9`1hvK5Qxcukv&xcXNVUr$*x+)&9-xD;N0P8AV>jEz5HsT7nkER;kNB;r+Nn>*f2tDKo=9 z7o{6zxNlHsK27L2&$=)zcF=Hsrj2*PW%w!5j1HxLMh&)!A{%@S%y{zG)FR-@8`7LhEQmzDRJ5w27rj}jON zu#X6WIs^tEE#d;~q4OH{RO&0!op*&}Np4z$m>D!` z=h=M{BoKokX{Kv6Hv|{Mz!ftW84qYd8n4@?Zq`FZdDJoe1(3T!3p1`JXmQCE zi#Cdq;YN>BWSM6Tz2Z%~rGQvmB!O{Ofyys0oTavTcKjF^eRo&Fj) zwjfqLW<*K^>X*e(YSA+JwwmTaHof!=Fd5fGGDn~}_7sPRw`04#14c0=G!g24Wl3;C z<_^gqCqK|96_!(fuT6>ukoR&Ya`4Br^rf*Bp%Vp>=e^8FgX08&4hPIQ78bq8(Iy zKe=Nc5fLG_?==Sfh5RuSiJ&r}#i2ZsjY7_j?Vj`9J1q#e`oJ(Flb#U0^NMeTdpp&EiTiHC|1CyYXaC!GW$5&GLthdC>`w zA|9X7t+O zEx+AHLZtce5=tgh0AFkvJyafpW>HBiAy=53S6o>D01!Kzy_?HpTiy9I#0cmT&1FUW zscfQK)tufRTBBufS0?oZiq6X_oj;-pCK2*fUK9WeuO;c4tVauPc|_z*YqIcF8%_b< z26nSnw4{X(X;PZTNX4}_VgOs0G%vm(*!|M}%w}gq&3S>sd#_^103bNX%pbUBSSmr1 z8H77G-E_MLVFL1m7IQe95n`bzOTF(~8JX_7=r~0Nq(h9~@6ysKH|qqKEuwc5hor&$ z;E>ZxhcGl#n+yf-zrQVF>e#)@m@hry+z>#yFPYhC81 zwez<2Kv(>@G>3cC)r0_HpLhJO;YCA8~HuYDjVr^J-gFUcSBr5p=V7%}(4#p1+5*bP2mcDYya-#y79Xn(5$cQ92CRuW40MOA|V`QWhQvfKP zN>&Y$+ExGpV>Pim&x>;UjBfW`0H1mXyLTL=VC>TCqmK&9B`!aItZ0wL(F4L;Ul9=i zgZD492m#lul`C%=1C-3Ns!GI5x99-QP} z(WJDu-63B2?`CA)*YpK)rt&|oEjULM(Km()LALn$O#c|AM4QoK31jf~YXt4{lA zqI|*QNMWBiB5b)4`3`k$N%df8$=0T}`!|51Mc`8(Il*&X3-ZA`AaB@oF?BJoE6RQg zDQnf-gWl54b3HEJoHYg+{`v+A;&^x2dg>Xvwvu{0x1>qz_%^cjfgveCE5cgw(&IwB z8U5p!TKq%w7snhOC%aHsx^3gccjjg0vmTsXT&S}u+F_2~*p>yfPJFzkf~6r0)_&%o zr;bnA6b9=(1ARDQ9QKy%d9nt_RlWf+yRLF+W}VavSfI>eoAjbWL#|O-NLe|G8+W{j zt*r;gYlYnjbjznP@un5q*)d)nsF&s9P81`jeCy1;`%$!F0lS!tJ=&U=F=uzd`+-hF z*SbIf9J(gM9A(kp6$W9*&Lfm(Ur@lmKj>}-1#MPzsd}WarO5q!%Jx+@JSsT~Y*gu9 z@Ddmz0uXVx?K?ggcH)({X=+aqJ@lV|zq zg@uZsEkfhEi+S>fKK`Nji}4^@bYxRpZ&fc7hgCF8DNEjo=WzPumoq&a>AE?v5(N_n zlaa}c7}P5fvG^dSFw`&C&~N$A=t|bJ%w=gCR#Use^Y@vHtl79LHl^}ni5S2yrT4YZ zZ;~vHj1$xgJ$(fOMkDh$}b>|H{UG4%d_Fj?=sLt z+fuP|@ajZf1P)QroNIt4ByS4F6#-@(fA&BH$m|=cucPtKxl+rl_pNGS9R@xQ2`KEo zV$YjOFf{u^u=^~ChVWG6(;E3C_B|Sb&0o#ow}b0+XC7dBi17|(9Tn<@<>_5k0Hf?A zX0N|PuZaYhtoniS7O#s@m0Dzd1`R)?w@22?EHB^IAaO7$=v&p~4(%fv{01m8HU74e zuXOSlYHkAkGr<(@;Zdd)2rCW4e^sH$P}e_uGECJFCU#B@N^oFGglU8Dj>~-0vR3Cw zVXJ;uM~M>Ghpg}PdZuvTDN;r=(b5`8rs`42WoaXe4Nav06BVxfQdYuy_5?$oDY0uh=F3Amn3CMaf;Ep#jKSaR>3gDta|rmJKQ(? zxMhsEBXgxhqHF#cQwb!Es;+!kM8dz2uJDP9n=$hd9X=B(?0d@$uhDkRwBqI)szP<` zsZ36go$yo|S^1MoVK#*KK51!j=>0PvyG38K%(X`|0d)6@X@|3<2=QE!BPb4cd|a(~ zbxopIcllZC29%>hnr~t%CG>88esn&fAVv_SrIX$}wF6h4LQF`{M8-0hB$I#nv_!SAGcNPQ!6me zQf(E}Q-~j5k{GF4DY?mIea!WSKEAmWq-uyPvw|+;lL3b9 zBNvj=Zg1W6IM>CccU1B+{2+s4upV^K(Xy-M!%lJUDNoLV>Oq=AlqKfx9a}{vgFih_ z`AY(eQr{Q=fFth%UJBMV)`OZ`3b92-c=Jx7X7}DAZpP{O zOR-tac-Hei>`PU3J8)`6(=%_@-|=oa%WJk6az8e97|Mnc^R=v~b-~!CK7bdzbN5d$ z(A-U?gZ{AI_-^O>ZMW(emafIVk0nOw?q$2H!KO&(G1`!vk?P$e*RNJI9DsyA(0nt{ zk}Oq(R&}=9w~kX$uDnE>6cEyWStB-SadDf?G)dse_G4_p$I$9e%o@&YM%%aVos3*M z04J_ZGI}U&SVPFw&NFAD-4jZndo|m(i<4VbRY@E))~!W9V6;)oc=wNarV)t~wBM8W z@d>(usJ(CGwXS5gqq_Jutm$fGB34)UrIi|G{DS+2M(Dkn>o1JLE< z{bDYEuZ}OK$80suJD;%il8#YbBeor${I|BA^d4YVB_EE;y;|BXZCX3oKE)lPzM5+H zRYH0?bHgkNj-8}%3?eo0#dOr*Qah1FG?6sB>@K))t8Tvq+_UzM=*|2<5*HmVhwZF2 zhFH*~9E{yhh96E;E?oa630_Jm4Zd{pQ3W3+f7?;7(AX-{v3O?+q89FKs*g>72Ht;U zEx6DFeh$R>OY?cDCS}6K`9KS))%$dasZzhF^_Ph2hw?xLXicZpHXSCH z6;Zt2@{h)vD(%$Dp1bsQ&RsI%IhTH&sQ4(7*wMbvKfwnl;?hnvRsne;q6=_y{HpRtqHw7%9R?HV&*C%u z16=WM<{HIhV*Sp^J+M^S&NBEE2hO)tz}gA@=eJCEZErm1i7f0==5twD3IKi8GX!nw z$^-4bva|k=;?&E=+h6N+Hp>aM40vS+EHh|RQiXrb@7h{%X_;vxbD2WJ!rI}vo1IEh z%LNjcdRLLfP48qXnMp=P{iU2lTHMK_grYg<@qhMMn)4cZTXLPo!1+W5P967fsW12i z!ZSdof(N4Jz5k|FK|6| zYeFjQ0@5}w9_`&pE!Ps}bM0Aezbro-W^hQGRH9S?@ND?6yS3YUW=9wNh`%+6ZBFgJ zoAVT? z3z1ZL7QS-7uXsq`p2W5p!?G|dkGXyW>vaSkt7LxJEwd>EJYWNUXII{=(mNo(Ezct9 z4`Tq~RnHOFWP02^bzQCVEd>(^G`yn?s&*HBWYYr_H1I;oSfx#Rb)lX*E~;~AP}6JF zXt&fo+tN1wXJQu*L49EbGWRjhC3%zT40Op85$t0rqbku=L;(+2^c$*Ed(5X4A5b58 zIo-uCsd!lCnZ$D!E^CV<#Ktka@^aP89+bh^qv(@(p?e*WzL> zpw1c8r)NVrQvlyd_Bka!BdnAYWb5E2tXpxGpu1UpE2?Mm(QT=p_EAs{bX8W9+D>Z1 zh%KtuQzu*AJ>(0fa$v%iHW{TxcV97l6ke%7MRIlVmW4W&ptD5tYV#wADPcjmYZ$&A zZ(jXib9*2E5RY;lp%YklJ%2qZQFb(i?dhV7yNTP-SQfmyrlyniIE_%J(|$5%xWDrnnzw?u(^*M* z@Bx~JaI_|y>;ps5JmkfIbI_TmDQLp;z55HdBg4F?k%_kuc15$Oz|}Q)0zEU}d%E8W z6UTn`{`KFV1Y+-juTO^fjTsi`(JET`dQZhGtRUY@^b^DjSz z%e#w7G$KCwX8GepS%26Wzp3@rA$3V)bVr1T?|DQl2qcT@0T4*Mwz2*_K)}@6JgQN* z#$~chaK3ye*8zp!*}_rBqdQwL0OuT~Xwmh2{?pOlUxquqJo=l@)M@MF8D;2Y$}}CP zPrA9yCuR-?Vxl+n91O+h$;@f8f!idstL|K^yzono%(b@gI|cB|VsS3$fW}#E%3CDp zH@YeJRVfi<92|9FbOddoSy!e2_z4XTPU~EC2CVuYbmTW#!#{@pV95ffGKX5;}|M^a@Ur+pATUmVjQ7h7{4=2=VQ>ZMF&g?Gqp;8PwDnWWI^G_-9;l z<=wx8)3DqB*L}hNOWx~LVgE#6;TT10Ni{f%URFT*`g&KjVakXPb2;>VV z6ZFp4(Xr?EGBg!A*R-d?Y3&27zwiB75uj6e=swx+>rVeQC~SQ^dqHkNzcF!L&W5S& z`T(HiH4)4AZBR(jJtcOUTjsCm)am6Cog#paCa+hnI3x5?ueT%vgy_p=2}j(s9G@5~pL)8R@C1jZ4J8y!*XHPK;KfsO)L|gt?Q|hcwI& z`UD#VHBAu3I#4;LeOv5cOBiy#l+>b&u=hN z!88TMK%r@Z#e~?e6pL^7IW(EW^}XfuCiOBVFfy#oasQ3<>&91P#jBW0sV=n~+$an` zP|ReuT8F}NgSaW~b;kNEZKq9xFnMe(Ur}6RhsvU))&Kz}BQobYIc86>cDi6#acIHP z9?ID;EL;Ifznyqr$N7X2eX^~&r@^DG?2qAvHQt| z3DXL*+g>}myjFo_)g^Zms;-Kf7#sKMM4jgN#a>&-zybv+dM?vWHYB5mNc#HfcB4w- zf7;V!AMb8vQRs!1XiJ;zAQA#St|3C)j?8wqB?*?+F|`1|UQpOtJIM-}>OZRbVH1R` zL#y?%ep;Ba&FUUoJqLo+^FajlnN?Az8((QMYd=8qeG#v{u@i?b#cz$)|GBQ+!s~GT z{Ep6JAyjp@W+0)%w_o@MhdeywexmDIQK+k$`BSo=yXsTQuLU>H%NWvS(fV`Ff$>n~ zdZYdbQ8=ctIn94-JlalQ*48O5X+9x`(F zH;T+O{NtvvbM%2S$ICf;`K!8tx~>LGoMk4nPv~;zI@0a$Fp}SAUm{C}H(6S@joF9k zcT0vNbw2%*oVc1$|9lzyaBL-QZFD|#UWetM+}`c?zN_&{YT)k#{m6ostO*5sm z|I=Z{=QBqyu*JZK^Ifd$B=)Co+ZR%d9=;Dc{60QK5W}!;KbfwU@8<^-j}M=`7GmR` zi$A1Jd#uObPG_8_Vet+tl_)1)FEyVJ(C_|3HlEW{gx~5k828yjWgsdljxCj4xaKljjFu>rFEKb_t`31$kFMS}Md+ zluP-q$izQn7^_L|jhydZ`|DFuq<4v@99fLJPXuUmwJ+Q{>Lj?{8y8P`e`A~rHqrO&VqNr+slK)dilYxTQr>e~J(dP5ot?q2c z8kW}2U$6MI=%mNHPRv^+^_4`z3;`naxQ}<+TE{_b%V9|mPkT$hM8a9S=0pyi_GxR6 zl%=(6s==0L)={;!rw&5Ai~M!^lb_ZRg(j_8wf`70s(p)`5S{2VOr(%nYf{<8BVZP2 zaLYU?WbF$Za_E^ELdg$udEdfK>PO*C9w5|;x~A2pW=e0jLOwu|HI5#1A3bX@l8nSd^Ig}8aT}^vz!S=Gw6nl{L#X-bRvg6p$cAw2COcw(mcpy- zUacg)lj2{T^v3deEgn z#Z2pK1t;RTne$0KZ-I~1KvY#~Y=5VpyV=&Uf@*)wy@bd*$??;06^u62iSw2yQW-0fl z)Ptn~fxT67^NT2b-Ur!h`+^za>`!>H^hTtHfBbrJquKhNq4bc{tqN8x0dJ;%1U#`P z`yAbExa%P-kV@Yi?sH*M`BBM-phuiyd$;hzAfP~wpZT5GtK(14H3{8XABd_u>zKbL zmdE-Ee}9r)PocU>feOqU&9uN{ZEoqjE~)!|P}9+T?c4?+nArSl9(O~ z?EI0w3w_krnDle19HHxB<4oXl`gz$n*F+Y<_w$6{VzvP$xYTXI+_v(zHvhK%D~Ev~ zA1H%IkUp?F{Giy-luy7Faq~{oFHSwxL*{DXyUh+IPmz0HtOA`L9Q)9{`oY_mti~HUry%_ZrTH#yRJ7Gnq3q>vy(HZdpla z2Q%Og*50YMZG`0Hv59HP-8tb;o!rXJ$jwo)Ob25t5yqT|2<7kofUIWUtbD)THzNN~ zJas>zEFrPONX6x#lex`PQG$HX{QRnAdaHreoUx#uNFQ+G_2X~nA7DSEP zw!b0@rDV%Rq4#pQ*{>lG@)3v&*=wdKI&V&fb}SW>z+Uai&TWg`0tlAo8I#iNK=7z7km^J!VUvzciv3cS=p1fIFD`aYCvDuFhLoMtlo-+ezB zCG?GY7I{DnH83D0KI_O3tyPP_PrlSFk#K|sdC#?hUC;eLgmu4BO-3p_y`=;_P7Eu! z?k+`j{rPk4ceOK}9Hh|>BU?@*M}XHSBH=Cbk(U(w4OsW7UB{b#%Kh)_69L@DB~wls zHhmGD2eltpcRd};9~*1fYKTem1#Ea)dXDl-et5@`_Gbr0aTNU!px-Pju{6gE?7&c& zs5ySLEZlM$x?+>W1?YmG6`mcZ11L|o1WMu)f-ccoiFoFRuk|*D^ZdfYOK(;*ad4oe zhX$F`DS~xZKBxhX?Zm2G7iii=pLD7pUio9GC*0*w+rh@d7n^4P)R$0i45__x(;Sz1 z)&{5OzB;Z4qb+5M^sGwR?SD4+Vkr9`?Ogji(~lmPF7(tF*$HWGGf7gp)G$pkx18pn z+@dW)7t5t2ZA>O9mrbaYONEGir#Z}Jhb6M2D2vH3EX^g%TxMId^ZB0hU!3Rs`2Okr zJn#4Oyr1{$^}JrM%z2mWEV@?;z9WaEmqaizi=+D*6pz|T*!8ffK0BXo9<#tJxoEQf zpeJy+Yok#$BAt|3*_Y!12^Hcz6Mt0PsCJdCkxmHydbmhlhWEC1ZP#l}#)NPkACW%u z%q#NaSggJe@0tGR@z>^UB+@ zE$axMvBiIS{lR&ccdl(>f4n#)#P%gzFfR1KCT>0V)8l!;oEm_b8{NLqjNLhfIvzEj zg|GF4H;tEHJ@_(@9!i)&{IVT0kQddeDrpRssf%td5G}47_}GixihSpg$b0T!yM+kn zrUK$B8fvsqD2QDoQ>Qg_(=l#6)YBG&h~@)C?)xx3h(`R%e$=I&8lh0`hBTV}X2t>e zZ~D;3E~!hO7~X5#!yxBGjid-S4!LgN_Ror_3t~Z@X)M&?Zx#(xR2x#~IIfgMG20w_ zYtR9zJ-8~yxbTdU$aU|>pbe2pnl0+F(qHjQjiK8nr7O@Vv-*U@KOKV-OJVd@it6Cn zuL84Ak+74-?MmZilve3;+1eS(@S_KpDqjh#uq|tyx!<7W<#ei*<>_FB(aKN^Q0MD@}NF8=;{McHtlkU+36SN ztMws4XyP1^134K@zGSD)BXFr1J)TZ=HElEf#DLOi8`UrE!#Km2AP}u`#cZNHykrF-Nl3xfD*Qy1qg<~cXs(RqWjc)09KOC~5p?Sz}a zfFQB*adyBz%~b3>=E(5!DEysb+WhWxRPpi~#XknB5d@YW^y-d}rj|K1>Mi%OS{ZsBiR z?958=4`W_O*IMlT2nQ!IEX$T+xKmF=-Vl^+UuASpmy|T-6sI8MqrHN)TX+&fC&jWB zf;%~)xZ>RV0{KaCv6%fmTy2nPsRr^tGw;la1OV8CdqBy9rex|XaW;~fTqzvTG^9Rz z_4Kcf*X%OH4cuxW)aOxarU}(l_r`R3vRpjDFhKd?_nkX7NNCv^_!zF9#TH0zT0(Yq z=>Kc03gWhQO@EQ=k^JEpNc^6Ne8PS&9s%k)!qu-ClW3YXqu`+z>@_1S+|I+aO9wPF z+mn1~;encJD`LD5{VZe6mi)8nN*P7@>QN0b?_tg!MR5A@UINp`K=!!xuH=>msi|dc z?BhmfH?P*hde?Rpxbg6=Y`29mj9N=rQHQ_#I9ex-4E#XvRc{JpgDabQVPJFnGN zorFPfUmc)uZ0Ya%@F#g%scpbRp*C5w#6J=ihJCkVKn1nsM@OCC>2}ZW34FAeQG&av zcueBYWx#~98rr89DkMY9+xm!e4eEBA+Eu-=Z(LVcLWbLgn2Ukj;<@`Nzd)tX$r$e= zP8gyERC#lkLn;neAlG9dPw=jkELXb4L>mailTTEqSF1s()2LzolOt2v6DVRX7{tau zew0a0!3>=-w_jmw73b(?REf4H#J$sZg$cVp1I*{;aB7!l?M40=X=Adb&O@e2 zIH!B3Fz;SdljucMT?G_;FAQEk`(T0q&b~nF1wooI@cU_`h%k>Jgp)GmM8LrX+{!iN zwIsbo_&(MhcG~f?bP%BQqBftawYYAsl`Jwj7OrfxDd%HEdUj`VN2vLs#1)}@^NEc+ z@$2{rtMVUPjFFot^U`su%#DFRG(PmRwvyi)m}f~jJLS@H$}3b}^gZDAhi!&hUZ13y z5s>HM?jLu$x~H%^k2xPe2hE)7&2d>5K0|`rbh5}wESy0COlr?O?A4~?FKaN5zfp`j77*8gA&I!+3Rg?%(eM zuE`(1YZNc!w`_T!1o#;42NWPQh=CFiz(Ps#-<_fGLOKc+RY8Fs_jg+>a%TXRDK~om zXE%{{sd2)(JBM#sDLTu?}=6DIZFX?SDM literal 0 HcmV?d00001 diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index b46e84485e8c0af4be979f8132b7d18da75df7e4..91bc8dc52a64a6aa7ff560c5d2855a5b03af8a9e 100644 GIT binary patch delta 20 acmaE$|3II6IWI340}w1vYu(6wRU809bOtW~ delta 20 acmaE$|3II6IWI340}#YcZ`sIwRU808j|LS0 diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 64ce50c8d3c332709d51cb3930e3fdf71f192cfb..1a273baeab92b7be9142e3e619a7e6929e740b84 100644 GIT binary patch delta 20 acmcb`b&HF8IWI340}w1vYu(80&k6uLJ_SJl delta 20 acmcb`b&HF8IWI340}w2k-m;O~pA`T+N(F8J diff --git a/config/__pycache__/wsgi.cpython-311.pyc b/config/__pycache__/wsgi.cpython-311.pyc index 9c49e09df194d2dbcad4868349c9177db4b15571..1bdd3b490d991714d16877965e5e982282b0f675 100644 GIT binary patch delta 20 acmZ3^x}24JIWI340}w1vYu(5_hY0{Pj|Ce5 delta 20 acmZ3^x}24JIWI340}xbw%iqX7hY0{RMg?d9 diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 6f485b3b3739fc2506d1ec0c61459afa803927b4..2c596167445a7c0c67ee0bd953b2003a8e2a2fc0 100644 GIT binary patch delta 22 ccmZqO%+$J>iF-LOFBbz4EKh6Q$XzuP082s!tN;K2 delta 22 ccmZqO%+$J>iF-LOFBbz4+@9RBk-KUp08O_C3;+NC diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index ee499aeeb0e76d75d84a76662177727a992b9a52..512e2690dfb32c6f512f52db72fc1cb3431d4dae 100644 GIT binary patch delta 2186 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 diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index ee430b67022aae2fa81da7bbe63881f4cfdc176f..b1fa1f81e7f0971fbce5195ad8e87bd7d2da4ff7 100644 GIT binary patch delta 6897 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 + + + + + {% trans "Customer Display" %} | {{ settings.business_name }} + + + + + + + + + +
+
+ {% if settings.logo %} + Logo + {% else %} + + {% endif %} +

{{ settings.business_name }}

+

{% trans "Welcome! We are ready to serve you." %}

+
+
+ + +
+ +
+

{% trans "Your Order" %}

+
+ +
+
+ + +
+
+ {% if settings.logo %} + Logo + {% endif %} +
{{ settings.business_name }}
+
+ + +
+
+ {% trans "Total" %} +
+
{{ settings.currency_symbol }} 0.000
+ +
+ {% trans "Items" %}: 0 + {% trans "Tax" %}: 0.000 +
+
+
+
+ + +
Init (v3)...
+ + + + \ No newline at end of file diff --git a/core/templates/core/pos.html b/core/templates/core/pos.html index 02cde53..dcd3346 100644 --- a/core/templates/core/pos.html +++ b/core/templates/core/pos.html @@ -128,6 +128,14 @@

{% trans "Point of Sale" %}

+
+ + +
@@ -571,6 +579,7 @@ cart = []; document.getElementById('discountInput').value = 0; renderCart(); + broadcastClear(); } } @@ -583,6 +592,7 @@ document.getElementById('subtotalAmount').innerText = `${currency} ${formatAmount(subtotal)}`; document.getElementById('taxAmount').innerText = `${currency} ${formatAmount(totalVat)}`; document.getElementById('totalAmount').innerText = `${currency} ${formatAmount(total)}`; + broadcastCartUpdate(); } function renderCart() { @@ -826,6 +836,7 @@ customerLoyalty = null; document.getElementById('loyaltyInfo').classList.add('d-none'); renderCart(); + broadcastClear(); // Show receipt modal const receiptModal = new bootstrap.Modal(document.getElementById('receiptModal')); @@ -1046,6 +1057,7 @@ document.getElementById('customerSearchInput').value = data.customer_name || ""; document.getElementById('clearCustomerBtn').style.display = data.customer_id ? 'block' : 'none'; renderCart(); + broadcastClear(); onCustomerChange(); updateHeldCount(); @@ -1182,6 +1194,68 @@ document.addEventListener('click', function(e) { container.classList.add('d-none'); } }); + + // Customer Display Logic + let customerDisplayWindow = null; + const displayChannel = new BroadcastChannel('pos_channel'); + + function openCustomerDisplay() { + if (customerDisplayWindow && !customerDisplayWindow.closed) { + customerDisplayWindow.focus(); + } else { + customerDisplayWindow = window.open('{% url "customer_display" %}', 'CustomerDisplay', 'width=800,height=600,menubar=no,toolbar=no,location=no,status=no'); + setTimeout(broadcastCartUpdate, 1000); + } + } + + // NEW: Listen for new clients requesting state + displayChannel.onmessage = (event) => { + if (event.data && event.data.type === 'new_client') { + console.log('[POS] New Client Handshake Received'); + broadcastCartUpdate(); + } + }; + + function broadcastCartUpdate() { + const subtotal = cart.reduce((acc, item) => acc + item.line_total, 0); + const totalVat = cart.reduce((acc, item) => acc + (item.line_total * (item.vat_rate / 100)), 0); + const discount = parseFloat(document.getElementById('discountInput').value) || 0; + const total = Math.max(0, subtotal + totalVat - discount); + + const msg = { + type: 'update_cart', + timestamp: Date.now(), + cart: cart, + totals: { + subtotal: subtotal, + tax: totalVat, + discount: discount, + total: total + } + }; + + // 1. BroadcastChannel + try { displayChannel.postMessage(msg); } catch(e) { console.error('BC Error:', e); } + + // 2. Direct Window + if (customerDisplayWindow && !customerDisplayWindow.closed) { + customerDisplayWindow.postMessage(msg, '*'); + } + + // 3. LocalStorage Fallback (triggers 'storage' event in other tabs) + localStorage.setItem('pos_cart_update', JSON.stringify(msg)); + console.log('[POS] Cart Broadcast Sent'); + } + + function broadcastClear() { + const msg = { type: 'clear' }; + displayChannel.postMessage(msg); + if (customerDisplayWindow && !customerDisplayWindow.closed) { + customerDisplayWindow.postMessage(msg, '*'); + } + localStorage.setItem('pos_cart_update', JSON.stringify(msg)); + } + {% endlocalize %} {% endblock %} \ No newline at end of file diff --git a/core/urls.py b/core/urls.py index 06d1e02..d37296f 100644 --- a/core/urls.py +++ b/core/urls.py @@ -5,6 +5,7 @@ urlpatterns = [ path('', views.index, name='index'), path('inventory/', views.inventory, name='inventory'), path('pos/', views.pos, name='pos'), + path('pos/display/', views.customer_display, name='customer_display'), path('customers/', views.customers, name='customers'), path('suppliers/', views.suppliers, name='suppliers'), path('purchases/', views.purchases, name='purchases'), diff --git a/core/views.py b/core/views.py index 75e987f..a0dcf28 100644 --- a/core/views.py +++ b/core/views.py @@ -484,6 +484,166 @@ def create_sale_api(request): sale.status = 'unpaid' sale.save() + # Record initial payment if any + if float(paid_amount) > 0: + pm = None + if payment_method_id: + pm = PaymentMethod.objects.filter(id=payment_method_id).first() + + SalePayment.objects.create( + sale=sale, + amount=paid_amount, + payment_method=pm, + payment_method_name=pm.name_en if pm else payment_type.capitalize(), + notes="Initial payment", + created_by=request.user + ) + + for item in items: + product = Product.objects.get(id=item['id']) + SaleItem.objects.create( + sale=sale, + product=product, + quantity=item['quantity'], + unit_price=item['price'], + line_total=item['line_total'] + ) + product.stock_quantity -= int(item['quantity']) + product.save() + + # Handle Loyalty Points + if settings.loyalty_enabled and customer: + # Earn Points + points_earned = float(total_amount) * float(settings.points_per_currency) + if customer.loyalty_tier: + points_earned *= float(customer.loyalty_tier.point_multiplier) + + if points_earned > 0: + customer.loyalty_points += decimal.Decimal(str(points_earned)) + LoyaltyTransaction.objects.create( + customer=customer, + sale=sale, + transaction_type='earned', + points=points_earned, + notes=f"Points earned from Sale #{sale.id}" + ) + + # Redeem Points + if points_to_redeem > 0: + customer.loyalty_points -= decimal.Decimal(str(points_to_redeem)) + LoyaltyTransaction.objects.create( + customer=customer, + sale=sale, + transaction_type='redeemed', + points=-points_to_redeem, + notes=f"Points redeemed for Sale #{sale.id}" + ) + + customer.update_tier() + customer.save() + + return JsonResponse({ + 'success': True, + 'sale_id': sale.id, + 'business': { + 'name': settings.business_name, + 'address': settings.address, + 'phone': settings.phone, + 'email': settings.email, + 'currency': settings.currency_symbol, + 'vat_number': settings.vat_number, + 'registration_number': settings.registration_number, + 'logo_url': settings.logo.url if settings.logo else None + }, + 'sale': { + 'id': sale.id, + 'invoice_number': sale.invoice_number, + 'created_at': sale.created_at.strftime("%Y-%m-%d %H:%M"), + 'subtotal': float(sale.subtotal), + 'vat_amount': float(sale.vat_amount), + 'total': float(sale.total_amount), + 'discount': float(sale.discount), + 'paid': float(sale.paid_amount), + 'balance': float(sale.balance_due), + 'customer_name': sale.customer.name if sale.customer else 'Guest', + 'items': [ + { + 'name_en': si.product.name_en, + 'name_ar': si.product.name_ar, + 'qty': si.quantity, + 'price': float(si.unit_price), + 'total': float(si.line_total) + } for si in sale.items.all() + ] + } + }) + except Exception as e: + return JsonResponse({'success': False, 'error': str(e)}, status=400) +def create_sale_api(request): + if request.method == 'POST': + try: + data = json.loads(request.body) + customer_id = data.get('customer_id') + invoice_number = data.get('invoice_number', '') + items = data.get('items', []) + + # Retrieve amounts + subtotal = data.get('subtotal', 0) + vat_amount = data.get('vat_amount', 0) + total_amount = data.get('total_amount', 0) + + paid_amount = data.get('paid_amount', 0) + discount = data.get('discount', 0) + payment_type = data.get('payment_type', 'cash') + payment_method_id = data.get('payment_method_id') + due_date = data.get('due_date') + notes = data.get('notes', '') + + # Loyalty data + points_to_redeem = data.get('loyalty_points_redeemed', 0) + + customer = None + if customer_id: + customer = Customer.objects.get(id=customer_id) + + if not customer and payment_type != 'cash': + return JsonResponse({'success': False, 'error': _('Credit or Partial payments are not allowed for Guest customers.')}, status=400) + + settings = SystemSetting.objects.first() + if not settings: + settings = SystemSetting.objects.create() + + loyalty_discount = 0 + if settings.loyalty_enabled and customer and points_to_redeem > 0: + if customer.loyalty_points >= points_to_redeem: + loyalty_discount = float(points_to_redeem) * float(settings.currency_per_point) + + sale = Sale.objects.create( + customer=customer, + invoice_number=invoice_number, + subtotal=subtotal, + vat_amount=vat_amount, + total_amount=total_amount, + paid_amount=paid_amount, + balance_due=float(total_amount) - float(paid_amount), + discount=discount, + loyalty_points_redeemed=points_to_redeem, + loyalty_discount_amount=loyalty_discount, + payment_type=payment_type, + due_date=due_date if due_date else None, + notes=notes, + created_by=request.user + ) + + # Set status based on payments + if float(paid_amount) >= float(total_amount): + sale.status = 'paid' + elif float(paid_amount) > 0: + sale.status = 'partial' + else: + sale.status = 'unpaid' + sale.save() + # Record initial payment if any if float(paid_amount) > 0: pm = None @@ -2423,4 +2583,12 @@ def search_customers_api(request): ).values('id', 'name', 'phone')[:20] else: customers = [] - return JsonResponse({'results': list(customers)}) \ No newline at end of file + return JsonResponse({'results': list(customers)}) + +@login_required +def customer_display(request): + """ + Render the Customer Facing Display screen. + """ + settings = SystemSetting.objects.first() + return render(request, "core/customer_display.html", {"settings": settings}) \ No newline at end of file diff --git a/hr/__pycache__/admin.cpython-311.pyc b/hr/__pycache__/admin.cpython-311.pyc index abc19b191f643571638ec7aadcdfeaeffccf9c75..e1705ac4f7a7179e9c0a6980be165d6dafcc20b7 100644 GIT binary patch delta 20 acmca3dPkIdIWI340}w1vYu(6wkqZDm9|ht7 delta 20 acmca3dPkIdIWI340}$Mu)v}TMA{PKa%mzyU diff --git a/hr/__pycache__/views.cpython-311.pyc b/hr/__pycache__/views.cpython-311.pyc index 756eef392232592d77d2ce869717d00fdffa9d46..ac0a16cd71fb7624c479490b89cedb61cda9254b 100644 GIT binary patch delta 20 acmbQ}Khd9iIWI340}w1vYu(7*rVao)tOb$) delta 20 acmbQ}Khd9iIWI340}wo(-LjFpO&tI|i3S1y