From f19ade40ee50b6625c2e44c9fcdb7179b6303abf Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Tue, 3 Feb 2026 05:21:43 +0000 Subject: [PATCH] Autosave: 20260203-052143 --- .../__pycache__/signals.cpython-311.pyc | Bin 6625 -> 6652 bytes accounting/signals.py | 1 + assets/pasted-20260203-040015-70bc78c5.jpg | Bin 0 -> 32132 bytes assets/vm-shot-2026-02-03T03-59-49-172Z.jpg | Bin 0 -> 32132 bytes config/__pycache__/settings.cpython-311.pyc | Bin 5927 -> 6108 bytes config/settings.py | 9 +- core/__pycache__/models.cpython-311.pyc | Bin 35699 -> 36156 bytes core/__pycache__/urls.cpython-311.pyc | Bin 10506 -> 10630 bytes core/__pycache__/utils.cpython-311.pyc | Bin 2648 -> 4394 bytes core/__pycache__/views.cpython-311.pyc | Bin 121929 -> 123752 bytes ...8_systemsetting_wablas_enabled_and_more.py | 28 +++ ...ng_wablas_enabled_and_more.cpython-311.pyc | Bin 0 -> 1337 bytes core/models.py | 5 + core/templates/base.html | 21 +++ core/templates/core/invoice_create.html | 27 +-- core/templates/core/invoice_edit.html | 35 ++-- core/templates/core/pos.html | 13 +- core/templates/core/purchase_create.html | 27 +-- .../core/purchase_return_create.html | 25 ++- core/templates/core/quotation_create.html | 27 +-- core/templates/core/sale_return_create.html | 25 ++- core/templates/core/settings.html | 136 ++++++++++++- core/templates/core/users.html | 178 +++++++++++++++--- core/urls.py | 2 + core/utils.py | 41 ++++ core/views.py | 30 ++- locale/ar/LC_MESSAGES/django.mo | Bin 29006 -> 29048 bytes locale/ar/LC_MESSAGES/django.po | 4 +- 28 files changed, 533 insertions(+), 101 deletions(-) create mode 100644 assets/pasted-20260203-040015-70bc78c5.jpg create mode 100644 assets/vm-shot-2026-02-03T03-59-49-172Z.jpg create mode 100644 core/migrations/0018_systemsetting_wablas_enabled_and_more.py create mode 100644 core/migrations/__pycache__/0018_systemsetting_wablas_enabled_and_more.cpython-311.pyc diff --git a/accounting/__pycache__/signals.cpython-311.pyc b/accounting/__pycache__/signals.cpython-311.pyc index bd9edfecd00725f69993c7795787e74be3536d3c..7f8a8b79ab48d08e81e8fc17a610d5b30b88365f 100644 GIT binary patch delta 1153 zcmZuwO=#3w6waAsGRb7p`RV*P({|dC`ZHAvwTd7jh`c^fo-TYm^rD71iFHcuq}-%d zL=eH9AeLLumCGvFU3PDy58meOTu7g0=T2QcaaW$;xtZ~&>LvO3&Ue3)bM8-G&;CDa zJ~GX$gyWB^x4LIm%=*o#lqB7k9LWJsqCfxyPkAXS6PYSRNn+VcQh(>jy z(=5qSgBUbNa?~Uy9U?>MNjs{Srv*}=MN*_CQcChN-Y_kba>6yQLaU^TyrSQhNX^M2 zZc9n7>dLORZmh&Dqdo}rb%U$WI@B1%*>z(Ldwzm%e>g+8r8T5aJ_`~V8F&rMy$CI1 zbP(q-eg_jb$yg#NqSn@r4RkE}Q~ihH13wn}sUHh&)tw?X%Rj>0wx&}$BejR$imuxb zYhjnV*ZrOwolczv$n(eY1XTDx@~QL)I&?m&gm5ofQB)W|5DtG?t8_zhqN1}~xq`k!EY(-ps9H0xpu;#}y5wrAPYU+RVIAWCeCuNuGO zx852p*cTbOhfo#PWG#s!Rs!2|(f8CmjJ{2?4Rg`t(BB}E@;l&clrOA8JgM2MbZF^cSdoKYufPGS?8THQZ~9ZZF{PjY|4F3OAy2We-k_A#G>A zZYkR>nkxus3z!nH2cfO7LxLX@a9n`csz5=Qz`+_kUv0r%K2tqc9*=X*g58_}iZ`_*n6~7(N7+1vfNx;oFZrJg057H1^Q}*`TKg^a E2@UW2{Qv*} delta 1191 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 B4Wa-5 literal 0 HcmV?d00001 diff --git a/assets/vm-shot-2026-02-03T03-59-49-172Z.jpg b/assets/vm-shot-2026-02-03T03-59-49-172Z.jpg new file mode 100644 index 0000000000000000000000000000000000000000..56c9cdf595e38971633a4c00a2d3775b042bbab6 GIT binary patch literal 32132 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 B4Wa-5 literal 0 HcmV?d00001 diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 80bb7d0e8c0e79736a28aec9079be73ec35f96b1..4c793a102de26e09a0794064c7431f1ebd0d4b8b 100644 GIT binary patch delta 1170 zcmZuvOHWf#5I*O&h0@x0DMf@*N`WG;f;^OGrI&ZC7L0fnHYU@w*MP$9HAY;Z2|oaG zT(U4Mz=Rd)j*W>+SD2_FjT^VDnwS{l$~i?by>XKH=FH4@?tEu*54yf~+Yf9u3qgCo z{z`f7+p+tp{it=28kqwe`~i(pC*P)_O((dvNZJ`E`^Y^M7fQyQ;ASp#H+Yx_-HYdH zjJ^y3?;d3}7^^Y*!N+Q$hFu0fR@_jFczKU16zX=38OrM53cCXJ&>)et;ZaGE7ytpV z?MsC4Icb=$(}v9^u!#H+{oHi?5Hy$fAq*`zrFFMbp{yR-Ac9#Nw3qN|2|E;;F|r2e zWC7@c?u^75(^b&3VI>5W1tH3s@Kqu7=1u5jVQlt^CToFftQE8VQr3p20dc}O_$LmD zm@%-3PUdyEQ7)6U>lnlOhq9~4h<4~`BQRS2p?!+mK|eRv$v+u_eOi zV@&M)81?k%iZQsk^K*DMsw+=Iyj%n81$m3;SX1fVa@LzZ{;kq0!89)#1A%Mls4Bq> z>w#I;4|8k)eGul^5EvFoWFg;WdP{>5so_40Q%FE`uHXf*%b zc0{9g?BGySPE(b&i+PHcUj6^PWB%DOO+CEcd5d1>E6z=S&7wScHz|wvE#FTqE-s{I zvpB1DcN6b#B^O&t^Ign*cU zn*t^U$Ox!)ZAH=4S^nC+5EA-Tj{vckU*?h3C-8J7J*IA8D*mrr4>x!|nn~T*38^U> z`6thdOQ*HYO0^^u4 z6TOK(0uj~@?W_Yju%bg0vGbT%1iFrtB4JVJW}VOjy;Lg5j~crOVd#U<3B^fh;_xM^ z^DJHCHQHD0hvdIKWDmd~Dh?faEyB7W1;d!7Al<-`298>!sIYDrV?8hqnIdJq1wUk; zv`P|g(FYSOhPQ~LB_PN8u{SAtED2L=0JG^vHi%KaDnblq{`gtpi!vK>U11KcG_T20 zF2+0rT#R94q+P59SZreP_p-)|vSwUu{ztg&DE}xY^f8yfa_#$7W876-fz{fNg{_RM zyaww{!z7l4jRVQWx>m?GvtCc|bJe79onI=kSgw${{Y*^$&}Sw>m|rN{d*w=5JbyfHtLSV&Ye148`tA|k z`R3cE#KZ5lzT}g^sFMf=NJ~tRMx0!zgOIGV6+R=mAePeP!c(r;Rw+&G-||+au={`c z4}4VHBswo^cgPI?q*Xc7OU|XPko>$*UqHB!t;ZF6QKU-(mIbT`SQW62fCEcAR>j`r zdE<6cEMe;c#9e;+7I*hxf2Xiy?_)~P%02vzan7HaPq`9V9`q)|b?Gn2elt+_hdnKI UNr0?{=yQL4z}b$Js3KH<0q0A>uK)l5 diff --git a/config/settings.py b/config/settings.py index 0a5b204..560a7a0 100644 --- a/config/settings.py +++ b/config/settings.py @@ -26,6 +26,8 @@ ALLOWED_HOSTS = [ os.getenv("HOST_FQDN", ""), ] +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") + CSRF_TRUSTED_ORIGINS = [ origin for origin in [ os.getenv("HOST_FQDN", ""), @@ -37,11 +39,13 @@ CSRF_TRUSTED_ORIGINS = [ for host in CSRF_TRUSTED_ORIGINS ] -# Cookies must always be HTTPS-only; SameSite=Lax keeps CSRF working behind the proxy. +# Cookies must always be HTTPS-only; SameSite=None is required for iframes. SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SESSION_COOKIE_SAMESITE = "None" CSRF_COOKIE_SAMESITE = "None" +LANGUAGE_COOKIE_SECURE = True +LANGUAGE_COOKIE_SAMESITE = "None" # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ @@ -85,6 +89,7 @@ TEMPLATES = [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', + 'django.template.context_processors.i18n', # IMPORTANT: do not remove – injects PROJECT_DESCRIPTION/PROJECT_IMAGE_URL and cache-busting timestamp 'core.context_processors.project_context', 'core.context_processors.global_settings', @@ -196,4 +201,4 @@ LOGIN_URL = '/accounts/login/' # Default primary key field type # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' \ No newline at end of file diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 48736bbcfb8ba99a5165d3b0cda49227c74fdd6d..5a0a5f0127092040d5a7ae063072fa594dd8a4a5 100644 GIT binary patch delta 790 zcmex7jcLy;Ccfpoyj%=Gz}MQCxg%gBUvU}J3FgTUqofwkEn^m8Vn}7q5(UYF0FcL; zqB{9vg`%o7ScU~64wX?`#>l|18i*kvMSZejxv;AYSfwmX6l{hDno715%{5xfn1Q;1 z7y_c?QnXtbqU2L_f*CY*H?OQLW~{Fgcg;&o%1KoS&qypOb}T4Ra8E2rEl;eh5(o#1 zCl)I>26!rj{^kSTac4#rI1llQc!HAub-Ts zSDc@ds#gv+LN7T#SCgs80;v5KXGUsHL3~MSMM*NqSCcoZXifI6wv{Oa@`|~EA`J{T z_=T_VD_-DGERqKD{WKLOJ7$Vb)>q|X448bR`jPc5K8UgLsbH6<+~R@qOF*u?#Q}7Z zTV`rb$}K^tcrnRXD+DiSyIj(Z0IIO|v zhJ^YIwmJMO7*{Y}(6YU#VRuEt?m)_gu<8pEH5Vmnu1M5eU=iJXzmA!Sv1;<;25-ic z$@-1fTnRuA7lDY9$t8{37!xLIH&x4|0Qs8CVBw-hP;jv&7o`H@LzAT_WAdRUC)RwR zg4)TP&EKsPfvln|kb1UT>=}v0i6tdP2#rPAAZf6g4xl+eGc!N}IUpi$vUQ6JYY~vy zv^k}vj8PNp6p+b9Ai*LjpayWz7s&uwzc_4i^HWN5QtgVWHZ!+vWzmsfRQkYxNlb8? R;`0$C{skdvGWkhYKLDVD=OX|B delta 344 zcmdlpi|O+;Ccfpoyj%=GAeGUWnc=^Yuegj!iFxwFD5=GB%b0mmR9hILq*K&_88p>5 z`&Sh+PF|;?KRLU`Rwjp$fuWcisIh_J2EXtXe#HwMibc{uzMrPdWXDX=$@;2XjDC}! z)I6HZSf|XWy;-$RjA`@A1|}xP(#dO@ycy#r|7f!2iUJx_1S0Y$+cs}wjGFwVxmqR; z$k${B3l}v4jl9K{T$GwvlB&s4lr*`!#fdc&sGwr41Y zB80}GRFE`SO$X2%pqWV^fiw`2F`1=Jg%#wD+ReIcWsKZlr+`c@%9*^bU6!$A^O^Ro dEIPuBN*@?7i3x5~d_IE2zaS*FCa>-32LK#WV1EDr diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 21142d043c9eff5b2e458867ed0c7d69870c7561..1e7cf90349e99464899e57054e13decbef4b5191 100644 GIT binary patch delta 856 zcmY+CPiPZC6vnf=lh(whYDL<{X8$B1-+=yTw+8kC|*4426C_gp@`x&UPJ_oGhds7v&@e-@B7}{H!!zP-yG?D z=5W|8Y(;Ne&)DR}&K|MDQSpE6pb^0usHCN-C|CI!e^G9GDp@QmY;UebAsQR6j#vUO zt6dJ$ao|cw7z?DOAF6qCJEL^ zuug(at3lUYF2SH1V4v)27Y%x~pVvPE-}i6bb#hbB zFx~3ox(gTWSu0N P7x5g6+xa&;#UAiKIN|=H delta 868 zcmZ{jL1@!Z9LC$^RkyBP^`Ms4G;P|Xt!_IgY>R6_p}T0it`1k&RK%^0p$@kZa4M`K zjOjr-pTY!%o^+n14so|#yy(Rj3Fy@w^r8@tdh)%`9=w>4AAjEWegF4=30WDtce?v| zFzEO2ORe3WeXOi?ho!H9R%R#AF)=aS8uMgdZ4L%mP#(!nZko}&L~kl3|7Gs?@@Mfb z{iyVLE$WR$ITg^1DZH-6l)U8)Nv_}H>#P@64>qia%Nvu7m^LvTV!B;W1OHKj7Hy%= zhgh62yt>C0qTI$+U?8sq9URpo4`!r8(KL;X{YFT8*##?dK4EEzK*Lp+=FnhD(gNcoY}a=NX{lXhvZxn^05cWh%{u;eF<@* zez2O*czpwWnn>_^8}$z8(}bDe~Z!g&-N2baJn;C4z(^d+VJ{XQeKM~}*7$)agp#7^o$z5?FIN=t8BFVeCe z>6nr*Ao9DQJGj**g0N)9Qxi#+)jnQun> z;MXNu(IWB^S9;T;PZ^v~xAlTdPw*ErEL-$VS{(W__zSLRMkMkXG0O$;4)_dw2Yv@b US>ZX7)k0#%dY8BtX8AAj2L&Mq^8f$< diff --git a/core/__pycache__/utils.cpython-311.pyc b/core/__pycache__/utils.cpython-311.pyc index f1acd999770252d2f73a04a73ec6bf4ce42a5ae4..fcfe627d18ccbdbf44d9e5b521d6ccb173273354 100644 GIT binary patch delta 1803 zcmZ`(TZ|J`7(R39ZMxlQx7CF%#Jb$JEEKaBzyK!T-ei>!i!t!B8G25;Q`(t&&Xls7 z*49K5BqoFaaib9Xgezdg7vq~odEl|#G@+S@hD|NQs=JO4S; zX6XL#```O~3IZDW;xm1^AECdv(j&1eyoiACHNxm~bOB)jxPV10WyA|2mO+!S6h~3V z&+q)=IZh>rJ(K9A@(ONvx%EXFtWXA$Gbk&RL;)2=ZtGB0y7`+tTrNpPiMonXTJAX* z^ok>}IC_@0-`Uf^FUJvfR9!vG=G6*pXx6}noNn)%>sD~XTDlEDq9;S#e{es;b2MmRDp)=wICGG73n-G z2+`2;VI=|-CkAE_E%NcAX0emGTqH{v(^4dISqGzbF{80aO0&wOpe@DP8FUPQLZv$+hh zNR0AZNXLOK2M%dD{SX6)<%3;Zw(n%#S~RJ?+|G@Pwj;M_8pL*W1L!^uPqJmKS(@!y zBpN1^*)B`Z5;Jf8{RG^$lUbUTXXm2gx#jQ&-5o<8E5h=L1n9|pCbJZqq3>}R;g5{+ zCBrNj5kjd+BS~szyR(U%i4NG#tcgj6(HUOaWnN5^gvD$}Qm4$a`wQ(ME)b(V2D`7T zTjnKV*nzIb2)#_`LY`)9Ic@5O?M&(!3))SzYwBf&^^|VePAEzBob9IMlRRP2M$Vbg zMNTu*u)UpaEhGSsEv1NMd#0}>NRCfA>ZNl~tG%NRQa9@y9kZ29?IplK=i6O#+ET{U zFmG07In#is)7&8t#=lE`eY!;XCuP6JPimpSZ<3bFE%XkAfNu(3wgg{!1-0DBv9~7g z+59xs9SwE&Q+5BEy1%X-Xs8D&bI-lO77`qXSB^G@#>#E6sZQ3^NpLj05pFoX>TZmj zYD-P^SWP|Faw4C4efHYy?U}pdcaHritxo@-JXGqT@kVI8-Z#00T_@>k`na+9NeqdLCk-COhS zU7h&p=>4OQ=IWy-8lxwE53P+(*G8wC!O2>1@_BIE%I@z*z8R^$U5lNrhvysN`Eo5d zU+bHH`OF*Q+ugarnri5FV&%;n$y>>*rJ8%kE6+=ymIN8FvORDLf9yKxpYowUCkKH) z_9;_i(&It@)IsU-K7q>z9l)b9Jq59p9~(UnOr+%IKc29X0-66;v$>nY%E-v;Nbpxw R{%gs51VHs)M&E+)e*t5O&?5i< delta 137 zcmZ3bbVI~$IWI340}yzBYRJsuWMFs<;=lkSl<`>z$e7NM!qCDH#gM`XBpFkff*CZK zH~MVj)brD1DsloUC~^T3D;bImKx{oA@r%PIH$SB`C)KXV4afzVR;)MqmVgEy11F=} J2M_^P3;^{q8UFwP diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 3347185baa345fadf1cd281ba94d900629038239..b5bcced031c470787d2dd7c5365b88c8842adac6 100644 GIT binary patch delta 6417 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 bJ+v>LfOKWyY1klHH6sAJ!TGw6I;H*#x)uR( diff --git a/core/migrations/0018_systemsetting_wablas_enabled_and_more.py b/core/migrations/0018_systemsetting_wablas_enabled_and_more.py new file mode 100644 index 0000000..2e3bb1b --- /dev/null +++ b/core/migrations/0018_systemsetting_wablas_enabled_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.2.7 on 2026-02-03 05:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0017_expensecategory_accounting_account'), + ] + + operations = [ + migrations.AddField( + model_name='systemsetting', + name='wablas_enabled', + field=models.BooleanField(default=False, verbose_name='Enable WhatsApp Gateway'), + ), + migrations.AddField( + model_name='systemsetting', + name='wablas_server_url', + field=models.URLField(blank=True, help_text='Example: https://console.wablas.com', verbose_name='Wablas Server URL'), + ), + migrations.AddField( + model_name='systemsetting', + name='wablas_token', + field=models.CharField(blank=True, max_length=255, verbose_name='Wablas API Token'), + ), + ] diff --git a/core/migrations/__pycache__/0018_systemsetting_wablas_enabled_and_more.cpython-311.pyc b/core/migrations/__pycache__/0018_systemsetting_wablas_enabled_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5542d895964904fc2a61b88152300bafc324322 GIT binary patch literal 1337 zcmah|&2JM&6rcU@#=CK7yhP2Rm2e0Ie96KIgd(I+0ip`1Dzr#$=xDR^u$}A|vuony z(o|}t9#aX4|A3}y{s8`oN=EX*nrkoR<|sLFY2S?3v>^y)ci;ZroB6%Z-QT9B9D-}+ z=O5d@8if2MmGLSS;BX1SbHWJILK0~WEz%phMs#wUF#RXO4A9n*J6bOg{qa_77|gs+ z>ZR9mv#tv#YB#x`x05&%R+KOZv!EcV*JPm_{*B-{0n*SIY3NLAY7IjtV6Kmo!q7}w zto4bp17@<)zV$-K1n?QH{fXlVo$ygsKFZ_s%w`Uo+^-yGebmd8@?!tb%PIEB{`7~v zG>wMCs@NV^*muW$!6unO!a-cPbm{UH3f&aq3<5ugX2Q3q9|TD!&f9Tw48>HomE{m+ zkV~^Twdt>genuh2H?UjVvo{s0J#6`Tww$K5+vsf5-@-@}3?BQPFc+1lz}J!tXzWK& zH*ijJHcAtww29K=HiS%63-1|lq|gozA8gOx?D|m}!nIl}&(rLh=LI<5B!tD$;l&_{ zwyO_STDAL%So`Md6%13tOydn5> z8@wvdI+5R{A;itRrO5Z{lcG#j=9CJDQmmvC0^$m#Pda`mtC1Q5>@0&gXhX*32P?|U zjNOt|a#Lk-Bf%Q{SeZl_Gae!PiNR{%kP2FsRNA-1EB&efRtx^lp6Db5~!vt9^HMIAPk(0YPyj#XF>P z19xtB;hDE*_O3qag+B}lIlZhOD0!shhxum)?pYc1?B2}F`QFO+J(s?6Y2T&q(q^Y! zYv)UO@!Gh)dv#OTY~7EW$s$`*15#rdb>NIVrq0eGdQ)B+P5C;XM^(co`xeE}&@>IZ fqSbrk;>mkxeX3bQa#HL%{poWDa^vVdyDIL#h~{W2 literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index 157d084..016d2a5 100644 --- a/core/models.py +++ b/core/models.py @@ -360,6 +360,11 @@ class SystemSetting(models.Model): points_per_currency = models.DecimalField(_("Points Earned per Currency Unit"), max_digits=10, decimal_places=2, default=1.0) currency_per_point = models.DecimalField(_("Currency Value per Point"), max_digits=10, decimal_places=3, default=0.010) min_points_to_redeem = models.PositiveIntegerField(_("Minimum Points to Redeem"), default=100) + + # WhatsApp (Wablas) Settings + wablas_enabled = models.BooleanField(_("Enable WhatsApp Gateway"), default=False) + wablas_token = models.CharField(_("Wablas API Token"), max_length=255, blank=True) + wablas_server_url = models.URLField(_("Wablas Server URL"), blank=True, help_text="Example: https://console.wablas.com") def __str__(self): return self.business_name diff --git a/core/templates/base.html b/core/templates/base.html index 35c7f35..6ea8a9e 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -386,6 +386,27 @@ } }); {% endif %} + + // Prevent double form submission + document.addEventListener('submit', function (e) { + const form = e.target; + if (form.tagName === 'FORM') { + if (form.getAttribute('data-submitted') === 'true') { + e.preventDefault(); + return; + } + form.setAttribute('data-submitted', 'true'); + const submitButtons = form.querySelectorAll('button[type="submit"], input[type="submit"]'); + submitButtons.forEach(btn => { + btn.disabled = true; + // Add spinner if it is a button and not already there + if (btn.tagName === 'BUTTON' && !btn.querySelector('.spinner-border')) { + const originalText = btn.innerHTML; + btn.innerHTML = `${originalText}`; + } + }); + } + }); {% block scripts %}{% endblock %} diff --git a/core/templates/core/invoice_create.html b/core/templates/core/invoice_create.html index dfefabd..56cb8f2 100644 --- a/core/templates/core/invoice_create.html +++ b/core/templates/core/invoice_create.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% load i18n %} +{% load i18n l10n %} {% block title %}{% trans "New Invoice" %} | {{ site_settings.business_name }}{% endblock %} @@ -77,7 +77,7 @@ - [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(3) ]] + [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(decimalPlaces) ]] @@ -102,7 +102,7 @@
{% trans "Subtotal" %} - [[ currencySymbol ]][[ subtotal.toFixed(3) ]] + [[ currencySymbol ]][[ subtotal.toFixed(decimalPlaces) ]]
@@ -116,7 +116,7 @@

{% trans "Grand Total" %}

-

[[ currencySymbol ]][[ grandTotal.toFixed(3) ]]

+

[[ currencySymbol ]][[ grandTotal.toFixed(decimalPlaces) ]]

@@ -168,6 +168,7 @@ +{% localize off %} +{% endlocalize %} {% endblock %} \ No newline at end of file diff --git a/core/templates/core/invoice_edit.html b/core/templates/core/invoice_edit.html index d9f900c..64b76f3 100644 --- a/core/templates/core/invoice_edit.html +++ b/core/templates/core/invoice_edit.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% load i18n %} +{% load i18n l10n %} {% block title %}{% trans "Edit Invoice" %} | {{ site_settings.business_name }}{% endblock %} @@ -82,7 +82,7 @@ - [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(3) ]] + [[ currencySymbol ]][[ (parseFloat(item.price) * parseFloat(item.quantity)).toFixed(decimalPlaces) ]] @@ -107,7 +107,7 @@
{% trans "Subtotal" %} - [[ currencySymbol ]][[ subtotal.toFixed(3) ]] + [[ currencySymbol ]][[ subtotal.toFixed(decimalPlaces) ]]
@@ -121,7 +121,7 @@

{% trans "Grand Total" %}

-

[[ currencySymbol ]][[ grandTotal.toFixed(3) ]]

+

[[ currencySymbol ]][[ grandTotal.toFixed(decimalPlaces) ]]

@@ -173,6 +173,7 @@ +{% localize off %} +{% endlocalize %} {% endblock %} \ No newline at end of file diff --git a/core/templates/core/pos.html b/core/templates/core/pos.html index be555d4..a017838 100644 --- a/core/templates/core/pos.html +++ b/core/templates/core/pos.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% load i18n static %} +{% load i18n static l10n %} {% block title %}{% trans "POS" %} | {{ site_settings.business_name }}{% endblock %} @@ -146,7 +146,7 @@
{% for product in products %}
-
+
{% if product.image %} {{ product.name_en }} {% else %} @@ -351,7 +351,7 @@
@@ -493,13 +493,14 @@ {% endblock %} {% block scripts %} +{% localize off %} +{% endlocalize %} {% endblock %} \ No newline at end of file diff --git a/core/templates/core/purchase_create.html b/core/templates/core/purchase_create.html index 9892f93..6769ba5 100644 --- a/core/templates/core/purchase_create.html +++ b/core/templates/core/purchase_create.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% load i18n %} +{% load i18n l10n %} {% block title %}{% trans "New Purchase" %} | {{ site_settings.business_name }}{% endblock %} @@ -77,7 +77,7 @@ - [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(3) ]] + [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(decimalPlaces) ]] @@ -102,14 +102,14 @@
{% trans "Subtotal" %} - [[ currencySymbol ]][[ subtotal.toFixed(3) ]] + [[ currencySymbol ]][[ subtotal.toFixed(decimalPlaces) ]]

{% trans "Grand Total" %}

-

[[ currencySymbol ]][[ subtotal.toFixed(3) ]]

+

[[ currencySymbol ]][[ subtotal.toFixed(decimalPlaces) ]]

@@ -161,6 +161,7 @@ +{% localize off %} +{% endlocalize %} {% endblock %} \ No newline at end of file diff --git a/core/templates/core/purchase_return_create.html b/core/templates/core/purchase_return_create.html index 2dd5559..1cbc84f 100644 --- a/core/templates/core/purchase_return_create.html +++ b/core/templates/core/purchase_return_create.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% load i18n %} +{% load i18n l10n %} {% block title %}{% trans "New Purchase Return" %} | {{ site_settings.business_name }}{% endblock %} @@ -86,7 +86,7 @@ - [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(3) ]] + [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(decimalPlaces) ]] @@ -111,7 +111,7 @@
{% trans "Total Amount" %} -

[[ currencySymbol ]][[ subtotal.toFixed(3) ]]

+

[[ currencySymbol ]][[ subtotal.toFixed(decimalPlaces) ]]


@@ -141,6 +141,7 @@ +{% localize off %} +{% endlocalize %} {% endblock %} \ No newline at end of file diff --git a/core/templates/core/quotation_create.html b/core/templates/core/quotation_create.html index 2635ca0..3acd4f0 100644 --- a/core/templates/core/quotation_create.html +++ b/core/templates/core/quotation_create.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% load i18n %} +{% load i18n l10n %} {% block title %}{% trans "New Quotation" %} | {{ site_settings.business_name }}{% endblock %} @@ -77,7 +77,7 @@ - [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(3) ]] + [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(decimalPlaces) ]] @@ -111,7 +111,7 @@
{% trans "Subtotal" %} - [[ currencySymbol ]][[ subtotal.toFixed(3) ]] + [[ currencySymbol ]][[ subtotal.toFixed(decimalPlaces) ]]
@@ -125,7 +125,7 @@

{% trans "Grand Total" %}

-

[[ currencySymbol ]][[ grandTotal.toFixed(3) ]]

+

[[ currencySymbol ]][[ grandTotal.toFixed(decimalPlaces) ]]

@@ -153,6 +153,7 @@ +{% localize off %} +{% endlocalize %} {% endblock %} \ No newline at end of file diff --git a/core/templates/core/sale_return_create.html b/core/templates/core/sale_return_create.html index 132a434..81e9e96 100644 --- a/core/templates/core/sale_return_create.html +++ b/core/templates/core/sale_return_create.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% load i18n %} +{% load i18n l10n %} {% block title %}{% trans "New Sales Return" %} | {{ site_settings.business_name }}{% endblock %} @@ -86,7 +86,7 @@ - [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(3) ]] + [[ currencySymbol ]][[ (item.price * item.quantity).toFixed(decimalPlaces) ]] @@ -111,7 +111,7 @@
{% trans "Total Amount" %} -

[[ currencySymbol ]][[ subtotal.toFixed(3) ]]

+

[[ currencySymbol ]][[ subtotal.toFixed(decimalPlaces) ]]


@@ -141,6 +141,7 @@ +{% localize off %} +{% endlocalize %} {% endblock %} \ No newline at end of file diff --git a/core/templates/core/settings.html b/core/templates/core/settings.html index b0817c7..4e38752 100644 --- a/core/templates/core/settings.html +++ b/core/templates/core/settings.html @@ -40,6 +40,11 @@ {% trans "Loyalty System" %} +
@@ -389,6 +394,82 @@
+ + +
+
+
+
+
+
{% trans "Wablas WhatsApp Integration" %}
+
+
+
+ {% csrf_token %} +
+
+
+ + +
+

{% trans "When enabled, you can send automated messages, invoices, and alerts via WhatsApp using the Wablas gateway." %}

+
+ +
+ + +
{% trans "Get your token from your Wablas dashboard." %}
+
+ +
+ + +
{% trans "Ensure it starts with https://. Example: https://console.wablas.com or your custom domain." %}
+
+
+ +
+ +
+
+
+
+ +
+
+
{% trans "How to use" %}
+
    +
  • {% trans "Register an account at Wablas.com" %}
  • +
  • {% trans "Scan your WhatsApp QR code in the Wablas dashboard." %}
  • +
  • {% trans "Copy the API Token and Server URL into the fields above." %}
  • +
  • {% trans "Test by sending a sample message to your own number." %}
  • +
+
+
+
+ +
+
+
+
{% trans "Test Connection" %}
+
+
+

{% trans "Verify your WhatsApp gateway is working correctly." %}

+
+ + +
+ +
+
+
+
+
+
@@ -508,6 +589,7 @@ method: 'POST', headers: { 'Content-Type': 'application/json', + 'X-CSRFToken': '{{ csrf_token }}' }, body: JSON.stringify({ name_en: nameEn, @@ -556,8 +638,58 @@ } } - document.getElementById('savePm').addEventListener('click', () => savePaymentMethod(false)); - document.getElementById('saveAndAddAnotherPm').addEventListener('click', () => savePaymentMethod(true)); + const savePmBtn = document.getElementById('savePm'); + if (savePmBtn) savePmBtn.addEventListener('click', () => savePaymentMethod(false)); + + const saveAndAddAnotherPmBtn = document.getElementById('saveAndAddAnotherPm'); + if (saveAndAddAnotherPmBtn) saveAndAddAnotherPmBtn.addEventListener('click', () => savePaymentMethod(true)); + + // WhatsApp Test + const btnTestWhatsapp = document.getElementById('btn_test_whatsapp'); + if (btnTestWhatsapp) { + btnTestWhatsapp.addEventListener('click', async function() { + const phone = document.getElementById('test_phone').value; + const resultDiv = document.getElementById('test_result'); + + if (!phone) { + alert('{% trans "Please enter a test phone number" %}'); + return; + } + + btnTestWhatsapp.disabled = true; + btnTestWhatsapp.innerHTML = ' {% trans "Sending..." %}'; + resultDiv.classList.add('d-none'); + + try { + const response = await fetch('{% url "test_whatsapp_connection" %}', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': '{{ csrf_token }}' + }, + body: JSON.stringify({ phone: phone }) + }); + + const data = await response.json(); + resultDiv.classList.remove('d-none'); + if (data.success) { + resultDiv.className = 'mt-3 alert alert-success small py-2'; + resultDiv.innerHTML = '' + data.message; + } else { + resultDiv.className = 'mt-3 alert alert-danger small py-2'; + resultDiv.innerHTML = '' + data.error; + } + } catch (error) { + console.error('Error:', error); + resultDiv.classList.remove('d-none'); + resultDiv.className = 'mt-3 alert alert-danger small py-2'; + resultDiv.innerHTML = ' {% trans "An error occurred." %}'; + } finally { + btnTestWhatsapp.disabled = false; + btnTestWhatsapp.innerHTML = ' {% trans "Send Test Message" %}'; + } + }); + } }); {% endblock %} \ No newline at end of file diff --git a/core/templates/core/users.html b/core/templates/core/users.html index 9bbcc96..d053fe9 100644 --- a/core/templates/core/users.html +++ b/core/templates/core/users.html @@ -3,6 +3,42 @@ {% block title %}{% trans "User & Role Management" %} - {{ site_settings.business_name }}{% endblock %} +{% block head %} + +{% endblock %} + {% block content %}

{% trans "User & Role Management" %}

@@ -138,7 +174,7 @@ data-id="{{ g.id }}" data-name="{{ g.name }}" data-bs-toggle="modal" data-bs-target="#editGroupModal"> - Edit Perms + {% trans "Edit Permissions" %}
{% csrf_token %} @@ -260,17 +296,67 @@
{% trans "Assign Permissions" %}
-
- {% for perm in permissions %} -
-
- - -
+
+
+ + + + + + + + + + + + {% regroup permissions by content_type as perm_list %} + {% for g in perm_list %} + + + + + + + + {% endfor %} + +
{% trans "Module" %}{% trans "View" %}{% trans "Add" %}{% trans "Edit" %}{% trans "Delete" %}
+
{{ g.grouper.name|capfirst }}
+
{{ g.grouper.app_label }}
+
+ {% for perm in g.list %} + {% if "view" in perm.codename %} +
+ +
+ {% endif %} + {% endfor %} +
+ {% for perm in g.list %} + {% if "add" in perm.codename %} +
+ +
+ {% endif %} + {% endfor %} +
+ {% for perm in g.list %} + {% if "change" in perm.codename %} +
+ +
+ {% endif %} + {% endfor %} +
+ {% for perm in g.list %} + {% if "delete" in perm.codename %} +
+ +
+ {% endif %} + {% endfor %} +
- {% endfor %}
{% trans "Permissions" %}
-
- {% for perm in permissions %} -
-
- - -
+
+
+ + + + + + + + + + + + {% regroup permissions by content_type as perm_list %} + {% for g in perm_list %} + + + + + + + + {% endfor %} + +
{% trans "Module" %}{% trans "View" %}{% trans "Add" %}{% trans "Edit" %}{% trans "Delete" %}
+
{{ g.grouper.name|capfirst }}
+
{{ g.grouper.app_label }}
+
+ {% for perm in g.list %} + {% if "view" in perm.codename %} +
+ +
+ {% endif %} + {% endfor %} +
+ {% for perm in g.list %} + {% if "add" in perm.codename %} +
+ +
+ {% endif %} + {% endfor %} +
+ {% for perm in g.list %} + {% if "change" in perm.codename %} +
+ +
+ {% endif %} + {% endfor %} +
+ {% for perm in g.list %} + {% if "delete" in perm.codename %} +
+ +
+ {% endif %} + {% endfor %} +
- {% endfor %}