From 7d1c8df2b25ca3aa98df46257f491deb3d1ffc47 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Mon, 2 Feb 2026 07:39:49 +0000 Subject: [PATCH] Autosave: 20260202-073948 --- config/__pycache__/settings.cpython-311.pyc | Bin 5552 -> 5813 bytes config/__pycache__/urls.cpython-311.pyc | Bin 1557 -> 1092 bytes config/settings.py | 12 +- config/urls.py | 18 +- core/__pycache__/admin.cpython-311.pyc | Bin 212 -> 2968 bytes .../context_processors.cpython-311.pyc | Bin 763 -> 1404 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 7688 bytes core/__pycache__/urls.cpython-311.pyc | Bin 347 -> 1442 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 14812 bytes core/admin.py | 35 +- core/context_processors.py | 18 +- core/migrations/0001_initial.py | 91 ++++ core/migrations/0002_systemsetting.py | 26 ++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 5148 bytes .../0002_systemsetting.cpython-311.pyc | Bin 0 -> 1730 bytes core/models.py | 76 +++- core/templates/base.html | 165 ++++++- core/templates/core/customers.html | 103 +++++ core/templates/core/index.html | 355 +++++++++------ core/templates/core/inventory.html | 162 +++++++ core/templates/core/pos.html | 428 ++++++++++++++++++ core/templates/core/purchases.html | 98 ++++ core/templates/core/reports.html | 70 +++ core/templates/core/settings.html | 102 +++++ core/templates/core/suppliers.html | 95 ++++ core/urls.py | 21 +- core/views.py | 251 +++++++++- static/css/custom.css | 161 ++++++- staticfiles/css/custom.css | 172 ++++++- 29 files changed, 2231 insertions(+), 228 deletions(-) create mode 100644 core/migrations/0001_initial.py create mode 100644 core/migrations/0002_systemsetting.py create mode 100644 core/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 core/migrations/__pycache__/0002_systemsetting.cpython-311.pyc create mode 100644 core/templates/core/customers.html create mode 100644 core/templates/core/inventory.html create mode 100644 core/templates/core/pos.html create mode 100644 core/templates/core/purchases.html create mode 100644 core/templates/core/reports.html create mode 100644 core/templates/core/settings.html create mode 100644 core/templates/core/suppliers.html diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 96bce5584823cd4ebfccfc40c2b36df8beaee7db..88d5360607371f6a7e63876638bb3ed2f2d137ee 100644 GIT binary patch delta 860 zcmZWnOK%cU6rKl<%)kH>AXXboE7V#mP+I$f(00nJB%>G}n=vV&+!4o&w3)#TF)1eQ z4Y@IP>B7{78x@T!U36<=?2e2(|9}%0jZ5zUH9FqpeBU|W{mwnPH~012`>^XJ!_XL7 zKZ_kH=kL14@Y6RlABh7HX%NCikpj`S1H&4)FahR;0APhl6jLB3Tta&b#-0!ai$Vxh z*9X-!%9e}_@$!gQ3~rFZWdak)dxLq#Ot1>pjtC5Ug<`mbnUP~+B!D=eO_nRj0;eof z;0Q;pC`PSUO@}7|W9pnUIoAJkTr)W~x~EBR*d%TOuKO!djhN&ukTT7Sg7jm|y-f_X*koR_La#a;uEvea1dk-8x@WL#i5n@xbXPOOJQtujNP0?(eQrng4 znr(QdMpnwHwq0%2T2ei#Ifls{Nfy<%?Y;=4T2!+RxOc!j#qoF0?|y_Y_MW*P;^%no zX0F2JG9}H)7g8Lbsovts+a<`dD?8MUOghh1D@9(ThiS1;C~KZlnJed0**u>qRnz%m zNm)a$p~Mkrq||IF38PFJux`MH0hx^(Ohkd%+sDVNozV+N2OhUidw2)4b);}(D4;?u3NsJ-H|g#>eI2UL_z&$TOrS&eZu=_uZ~h3wfdBvi delta 617 zcmdn0yFr_8IWI340}xbw%g=NXnaC%>cx9vdUZ(me*%ZMjIUtr#(Th?@@qp2`W;X+fP0#u<2 z#P-MrnWdPcDqF?~G!}@V#;TziYmve`*@szP*)oL}RbP|_no6sQ-)tv0GAmAIW7Lh; zLX)&ju|w0Yonqg@fTqeJRU1{+0v(vckm(f1$sbtcg>_T4ikMQIqBK*Sqx4dkgBdhk zHY>53vM{nuj^JD}S)J=KBg_wzS0>Th-ws9~IZ zP0)0*l8}(8G0^-X6CiPmIWw=M$P~mi2N4z^!V*MSfe0HQaf`LMASbh=$YFA(kRf*( zPy`fw#rK#uFBOVo4CLfv`oI7q8n`})F$l{x@IT;}Y2f+5!64$wctb$whKR%i9)%AK sY|4B{1T%*S*9T5sR<;ieAcC2nm#KmCgVN*>kwcS>MCCUph=wu(04TY4X#fBK diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 0b85e94ece283a83ff1af1d71f1b265c943eb37a..1b7a2c8ac28ebf995bef8653843bf171445911a8 100644 GIT binary patch delta 564 zcmbQrbA+RQIWI340}vQ_He~8DF)%y^abSQ0%J`hb$iOh2A%!7@F^3_SF^Z89#AeE2 z%4LpX&Si;W0rQ!2SaaE;*uZR-9QIs}C=NyjCWcg&6xLM6EKZoASz!A>yk$%b6IXNd zfR(TTN#+#xiL+!Nd=4<5bK)%7dgdtZRJJT0nEoQaRBoUoM+z5ElouwN!d=D9z_5k~ zXePsIAclY{pgd4FSUpfRA50v`=7+Hf=n*i1DFkW~gt4(}O5qJ=0AWqO$vc>B<*HaS z4K4EYt3*?>67$mY^^)`R()3D;a*Fjp;*-BJ8!-w^He{JEbc@s1)y2~>J~YVZ78jT~ z`812Ws5H2>6(OUGEXG$@jBl`T zG`MsKb%b|>Pl&$At9XT1@gj@T6&9rr>@56D4cs4i7+82(>^?9sGX_rH&+2G$gN1*B t*#xs08ds!rc6eN|@xLG(a8Wqm3Xo(8Xz&KX59~n2j9@K{MUp_L0050|apwR4 literal 1557 zcmb7Ezi-<{6h2a`&9y)mR5TN}FQWWXXv428G3D6*L?bJ<0fDW1Zjz3VjNPzapJ3Kyq?|a{ScjS+a zhJj#=|DxWehS2Zwp%|6icw;CCeUDt!MXutiz7nWiRgredF9ljx3-qp@K5KqCsB|l- zt^3uW)~zW>MMQVYL>;A>B`1#ou`388`7g zU*<*qmTaNZY_LhC)QVZCNgLxap4Ua6pT64h<|4TG!2MmY|X6a7%(M zNY5=}_qiPa7jGN);?PMIr)g8tPfWb+y4Vh}7ethaHpYEM101~Q*-?}`Gnpy=T8@_$ z$O4usgit7UxY2BG=5-BeKsIq`2jo^$+Rc`6*S9&pdIW{JORVoxLB)_TDa1?_7jo_c z*Z)x?@utmtl4PUxFGYKy&UD1oMtq34|o|rLr0PMiA4N-Li?SEIsG{iSDQA%}g4T|C&VOo*;=Po0rs=4pgG= z?B03wSyH{TeX!fx+3O_6!QuAd-rXMTP*TtB&cla?KcP23gx;E#JZ4sW6o(?V$aCVv zf->tFWnc5ic8HaIxao&sMlar0ZwAzjeR7*!gmC%W;eW!iC@G4vP*)Xgf#iabvOYn0 z`JSVXC-1uFXJHUBM^`3i??oBuwd0+W3#Zp#wqJfa)h^Gp%X6&?u8&S0pFBSOYT8(z zHP)xvrI~hVp_f+G?C;%I?i&uYrGP|`uS?f&KIx|?c&hZ0zEp*A0@v#d~_1}Ku$8i7v diff --git a/config/settings.py b/config/settings.py index 291d043..443b50a 100644 --- a/config/settings.py +++ b/config/settings.py @@ -62,6 +62,7 @@ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', + 'django.middleware.locale.LocaleMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', @@ -85,6 +86,7 @@ TEMPLATES = [ 'django.contrib.messages.context_processors.messages', # IMPORTANT: do not remove – injects PROJECT_DESCRIPTION/PROJECT_IMAGE_URL and cache-busting timestamp 'core.context_processors.project_context', + 'core.context_processors.global_settings', ], }, }, @@ -134,6 +136,12 @@ AUTH_PASSWORD_VALIDATORS = [ # https://docs.djangoproject.com/en/5.2/topics/i18n/ LANGUAGE_CODE = 'en-us' +LANGUAGES = [ + ('en', 'English'), + ('ar', 'Arabic'), +] + +LOCALE_PATHS = [BASE_DIR / 'locale'] TIME_ZONE = 'UTC' @@ -148,6 +156,8 @@ USE_TZ = True STATIC_URL = 'static/' # Collect static into a separate folder; avoid overlapping with STATICFILES_DIRS. STATIC_ROOT = BASE_DIR / 'staticfiles' +MEDIA_URL = 'media/' +MEDIA_ROOT = BASE_DIR / 'media' STATICFILES_DIRS = [ BASE_DIR / 'static', @@ -179,4 +189,4 @@ if EMAIL_USE_SSL: # 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/config/urls.py b/config/urls.py index bcfc074..5d88023 100644 --- a/config/urls.py +++ b/config/urls.py @@ -1,19 +1,3 @@ -""" -URL configuration for config project. - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/5.2/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" from django.contrib import admin from django.urls import include, path from django.conf import settings @@ -21,9 +5,11 @@ from django.conf.urls.static import static urlpatterns = [ path("admin/", admin.site.urls), + path("i18n/", include("django.conf.urls.i18n")), path("", include("core.urls")), ] if settings.DEBUG: urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets") urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ No newline at end of file diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392d6714413db63120e4233d2e96cbadb5de..5a870f576c826e1df62d5a613df08e6ffc9766eb 100644 GIT binary patch literal 2968 zcmb7G%Wm676rCX{iIOGxAvtlJCU%xT1&Y8(gCs@(wphThp#(l&OLKyq(5r43W4qK zt)BgtLdZY(kZ#4~=KM#AkoUwQ7IlbAHA;ykS+XO!vL?HVrnm*I;1;!_ThdCds;O>S zD^ns7M&Cs2$iw6#O2`K|<4qz@iKV(zi!4#K0MEM{xO&J`k;%VN`M$i@;dA zHe)TrSjb^ifw6pT#(IXan8R2B#;I#FPDf5vp-m0i%%pZqI;G8K`Yq-3TL+HmYxg^s zVJzn`&H&@=wHX`M+%{=7K4J+MSPB5v`I?pBMq#_4t7(z2cq~ngP5D{lIe> z7wUG{?K(ExDcgp_;2H2)z+9oe3c0yw_{>a=!7J2jw4E=)V)Y5K$Krt;@lsbmXbk<334CvB#!d;HWwj{w z8X8XWrRvyzpj)=zb&Lbi=yKNex}gJkTKa37IhOw?IY*tJR@-}!XFJ>pJ3-iHZF*_i7ScqD6u#HVU9D6vh&$Ok?Rq(b)hLs95*+hn2+<7Mun2c5tU4uonZg9^^w zh2WNa*^u9c7hA0&pG9eN2n~cLfS8J`du=-bjCsvx1`KlI8NY#1Q9cWJheI4e8E*VL z0OMx-0%puD^_~x!>%Et_$1Sl@z7xovtr&CyszrfnNh&g}76peIvfuMMaAB@tJ1vRd z2M+!K04gOfJ-&Q0Iz*VCE) ztmD`n#ucE+DH{Bl5e1ls%zhZRdYib%dNDL#FA_}J z%aq+q#bs0+8>|S)wqO#Z%UCt=0>jY_*MoU3Dkf*qT3`e@8KI+*UQx26)ctHmYZ!s> z8Js@Org8J1K*3DkIj-OBJ;gmv3ZwIrnjD09p}Z{nbdgQc;%(p&s-G;%d>tP7Ljb7# z$Lall)&3F&Wa{V#bo0b9;x&@Lm+7 zGVpl;9ytDo;UxqW0oMqQ#lrC~hfq1&g*6)1n9576ohZL}d5xBpXij3~irP=c4lLa~ zDZ{9mq5+7cPp0!p-H3k?zULdz78hB6MIvML;KK!ey=1}AqD1T1brueP z?$3XPHq^1}&SrZc24q%h_%Kp_CtpCA(e diff --git a/core/__pycache__/context_processors.cpython-311.pyc b/core/__pycache__/context_processors.cpython-311.pyc index 75bf2234fb21a6b62efc5cec11af9512dd0c9616..7392a4c4d1efb57dc540755192a10398047eaaaf 100644 GIT binary patch literal 1404 zcmZ`&&ube;6rR~#tt4Zi*h;G$>U!D;+6}D~8j?dWHmYkHmsBy9bFeOAwL4bU-Q7`V zMzI}QFr^1ydomOsTu5Dt|AEp|`yWU~U@_oRFU?J03MQw_ti6(5lefEX-n?J)z2V#6 zGMOAy6 zNXlZkjvdZWixOoZ7c+-?E$)#J*`bRVaXi~cUSKyddb<1=tx*yn96t9b2?HE*^xUSN z-S9ChMh(k8BgnhxYRi5tpKL{m>OL8_gBDsN6gjr@41d~aGj-|br6RYq{N$^J`IY(? z3)T7M#ife(AOmE7T>R7fU)i(HV9H0;PwmR1AUs`v1zBfI8 zGBv%o+WF|=AD?%p=6X|eC+POCk6u3hrSh_JT$nj3%ybL0y~1o4&GpdSAZd)718}Yq z=Bexnu5edzDB|wV(%1!Qz*WkHjM%$BWNjQ%>s3yD55I%#{kPPsGp@=1>s{HwgH>=F zK;QvKTLo3Hsjq?!XlWIZVIIeIcK%B;%b=>KNRmdxR*_iqDC5F(D7HDaG&-rmsW_jh z2@s+=<;^yI(y;wuGy0zN-jE+#k!l+ZG&3=Il0&`R$H%$iQLfm{-R?xgzJ`~bl8 zgOhxrm;dBAfA1)NubaQ$%irI5)W0#kf2)(d(@EVq8)z^w+0Rbwq}6kFcE-kK;~&bf zY=FNFqdcZtNnr-W#XgJXpcxq#z1IFV1nUIxgU&XB^8!kEJl1)&+E7*m*97^0X`7=sx! znO}l5_$4!fC@5e9(#$~odD_Ied5p}H4H$KU!nqWHz%eDISfQXOKPxr4M7OvgH90da zGg%=uuPn1DKQA{muSB6Nu_!Y!DJQj9p(J0SBqLR!BsI4nC$S_|Avr&YLJ5{zO!>vP*wRx=fQH;+&de*h#Zr=)n>x9XDPB+j=mr)bE_MMD4Gdqo zCVym7sDG-Uywqih=R)r#-WL@Nt|%CM;AG`t`@jGpSlK=U6$AZM1PX~FUJwB?XC*_C zAc)NmBz|$&kWCWTIB?J&m HHn5QZy*6Rq diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640edbdcec3e5c1744466c916e7acdd2763b..783a3e3739cccdd5efb729071976f00cf08c4c90 100644 GIT binary patch literal 7688 zcmcgxO>7iL7Ve%O&tK29$A1uT@PL2tWWkQX7-z#0%-AM?nHbv;)&Yk0bYlj_Gp4$S zV2dboh$0_2aEKJMaiobhVuP?&)+z_I+5<<9-K#!WeO+lKUsfRd#A)BFp5LCaLA$H1 zo_?;bdawF*)q7vPdj6B&?`5F;c_N#*?q`^P;6tG}^Oemg%P`+FA|tX%W{#a^S*+WV zwmJK>gJo>Y8Ah~!!-x)vyuA^K|;Huk!%SE|dz~$b7%T2jFz~$Y6 z%R{+*z{Tyr<)vJH;0o-(<)d6YaMka?#Zj&xa5e0}gLj-l$4>y z%}RQbgff1gZBKriE>KWW-5pApX zCpKt-+bp;cRZ@<(O2NW_l)EsB=v=L^* z2}FfCDbziZnoTC;Tj326Mt{m0-Z|lZEGeaCm0NH8Cd&{JW)ku66i!zrmAIRcDyFAk zWt$x^Lgn;WCuG_o+CUBa8-GEKo(qy97~cG2LXx9lr{RvpQlMNcW_V*USfET2>s%~$ zHzOqTJ#5TqyeE;Fv@Ds-^T`Yml24gUoTWECy|>bHQg3D^lTtFh(tRnOQPQOM%QU$o z&kJ#>H=ZU^ueta=^9zOp^&kNd^}sFf1ClLX>-*Z4g&g-dy^>bld(9td0T!|wNW8e- z@PLzncYZP+Ft_2sEI)t)!*h}Q2j)jROolDGXb<&|4622lg%BUB0XC@6+0j=xs-y%W5E^1tNMNl0CCt#*u5&+WPdizUOf@a9RtT)&r-3 z!MAs5K=vb@VJ zdRDy_9RWE(4)!0jP&uDP&a=u{bPP}_zCy}xkqU_XYQ5!c^;8axj~4p2phd1>wbAmn z1}cSyS(0k9NO|Dfnk{c@qH<`av;ap-rPOqbxC;Psm$)08@jb&eP5^M?is7C&EAmsD z;Yp`ruuVvcWN<`E0)&bbbchQE-FOLvAZ!pH5W_xs{?f(~s7-}!1h;pBo@w}oB{@zK z^GYI}0>^gFB!$!+!#Pe8acKkDHgK1Kmr(>36SE0LHUgp)Ps|C)*nAQ|OI{32D(U#0 z(8Y|9QWDAnK@osumnhv7GD&68pVvNgc21a;p4!M^e6=H$NhaZ)oB$vgOQpYz38Gj5 zTj;J7wz{D5J+m`xiMAgdh~m*jTd4aD8-~wBtT62IoeXJ(S{YtZlvw2RYW3uy3fblN zffS+Yu*x6Kb^P27fAT-~;XGRHu8CIOQ2_A7Z0fwUKvBnVMTRCLL&GD6JD%U-NE^Jt zf@S1mXfr%hu+f`<<`YZHVsOLebemnyd0ZQ#X*?|_l*B#hYznqc$%IHFAmd8ljzm|& za9^4j%ZtH+%}R!U7}S_b%t>aeH%=sKH-b_VIonZJBojz|e3?YdEDhoXVbG=h~J=b*?SP!gcT`@6X;f@^Zh*jcMGN z&W&Y9)|)?kbXjlya4onNRF6iqzG1y@_@$sWk8922dh>WTy3Xxg8h!ZL@(^5Ut+hvQ z?O79FG^yOE#=+2|Fh;QRQHvhzT?E=M?K!T^2~H-V&UmyAqT@%3}dQi0}ZU>2U$ShU(~jtCUZK5PX^wIdE7%M1L7D z+c}9C4h-!`Hw;9P3vlRGIwfs1LBkZl28At(9nO(CA(149pu=zti6W6?xdJ*cHnGFK zi7`bbbWB1(8O0z51Do2&P+!of01dceoA`Qw2EOs(g6iI##{qvW94PbgDG)N8^Y|Tx zmuj8&M~QyHC)n)*;KMJd>4N8ggCIdD$Ut^@ zoohu0XkESt*O!l{SEkoaKNnRlqHz(Oi-7TR?<2$e%K}7_uE)1mZm&61?wH0M)45~N zT^{+o_xQoe1F-VIpcWX^1B2N!Xyxx==wcN$a)D0#=X(7_g(BV5I5D0%~N&BWt6WKL4ScANN^{X zmw>#x5jJ-s$adz0oS=3OYF!`cT_3%Os~0b+&6l-i=(>zJ`xZ-mi>;w*6}DCgemDOD zJ=@uuHB6>~GT6qmqJ2zTP*Jqk2yjgdES-aarv|=4QUQ<>V=-FbT^4i&JVYDw=WWa} zDI}$-u$|zPlK~_MeH$3Ikq?pdA)(=!onT}~jw0ztavVs7vEdhiMKhabC`HeF@Msn| z1KKQSzikuRYZ|*A4d{(sYX@FjR2$D|jc4@6 zGug3q{s4wT2Y#7(5qvqM@==YC>UhBE;Dm^Dqm7wTmOe*+$)VSalWXyBPC|W)!t+xCB>+XThj;$5G6>^yW}j8GPCiuVh*5ndFq$TtJhy1RDBbgZ$kG? zz%CqU!wf@P&b2o1>&f!G0sjG7%?BEPNaqisv2lIrNLCdT2)5CVkQ7;mV5xD_*}5WZo@sEA@N&+43K6kgR~of+Q^p zsnAfIZZ*IL28~ApbLSn0+7vyQl)^qU3j7Ru7Wqhq5GfU32u&``&7_kA(d`Y}vB*sc z_d^qK77ulIhBpxMO}D`Pod_uE9!t-rLvWxc$KbJIcL%fD{ zmCY63U)aJiew8tDp{F06->WpB2Ifn#s7XwfF1o{V#&*tb+&LUu(#?m-*Vw*Q>TGqf zaCWUG=D5(lRqAZ0L*8m)@av7r-85vTTf*CZK zUxE~9GTvg#%}+_qDfZK3y2Y82m6(^Fua}Zk#0-?29K>vH^^3y>sGu|_)vkyGD8>lH X#j-%+12ZEd;|&Ix3)oN*8&CxR(>5cr diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659f6c6e0ae848e54157af197c543a09315f..4ecbf2306b758c1e2f3812ec68fc6e6a199b94bc 100644 GIT binary patch literal 1442 zcmbu8zfaph6vxl;1!9N%ApB@Upmal#082$3BHBubPDNs9#R94#<2!*Nv8}Vs4=-h8 z=#T-ajGbDlc3|#bVM`v6*G_CmNFA8^j^Gni9xC;0KfU|D&z+zB-hC~VR0QMa+aq&V zM(7uxq+|Hbx&AF7^a&9}qz>vz>ym^>j>w%{S6-JTltWY^n94giT}bjj2EM><-{I+x zTV@cLe5#N_CZhl|AQ&~1DFQPnn4wIj1WZ9N(=q$9@B`KHnX#?Al+(fw3XD27^FSQD^8&@Co@ZKHpcPU#sOpZX8I0;4 zopbdL)sjko*5z|a;uWa*LFkVZ> z4=k&3Gs4X%n4}2%L+L!qEcY9_1_|BFYTHl(&ENDb&)4VyHGHUkoL5AO>!5&H+=_53#;v|O-Wxlqe;)fMHhYI`b)vU+^8TzI;)Mt=#CW0q zwnmS}Me#MkU1c^yu{p8KTXzK+$mX!dFlCjrA0Z# zMIgg&v6f|~mKPVXPQJ$+5W@!)0hv(j1tdN&Gcq#XV34_hiXJeCUqD44*cezj8(cbs fIznc!U0{*F$RdA*Mg9Xb6F*Y}HwYH-0F46x>1H}@ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2a36fd69370b38a98d8b01bf8eb9817c42f16ed6..f1c90d18ec910bf75b7502f0e086640fad0ddcc4 100644 GIT binary patch literal 14812 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 Z80UFMi91|=@1ef4?~Tsw|Ds}``46e6MnV7p literal 0 HcmV?d00001 diff --git a/core/migrations/__pycache__/0002_systemsetting.cpython-311.pyc b/core/migrations/__pycache__/0002_systemsetting.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c9f1b7efa2b75af67474d5db10ce5be3ee98d11 GIT binary patch literal 1730 zcmZuxO-vg{6y9C`U>h53;>4+g6UTK>Orn@j(yD4yiI7mW0z@!Ds`**1J%d?T?>e*V z#I{1kp@$xGD~BF9QC0DQBS(%L$I>3qo+|a^nVMpF`bKE~n=nYR7oIVBcJBK*LD_oh+^JO6~@SMQ?z#-vR4!JPD>FRCT2lU}w z%Da#|$7MWirp^dfpe&b&WXPJTTi&vUu%Z`xJK2A@E1bUL*^!vb^N7m}h%fPZm%w57 zX3r@&8nHLt&Ay%iU&!Q%{Ig)dlhqX-&mUb|#1YV+&_v%TQmb#&tjUhIOso9GJ^zrwp)Hm|?y2#1DI z0^LS;n#oJ?-nE&*b0*77s`=$b4@vvsmaM=QLC!#g!VDS(+EB5(vowqE90{I z5MGz6iUG|f)kFoWC1ZmO0@do15F%jE>YH=`1mYm0n>N;B$E6)a-GIT-@h?q zqlfO}G|h`tB{ZhDV!9dAY1jY`O^xr3n5l94-5gzBqvdxrwcSc>o2hLY{^cYRr^63- zr_JGq2NOp!9iDFu&zr;ZH2m@;a+AhKcSp?l=t1--MRR!?Uv9;h&G<46uh`lLO#9#< zee@N5wL;^ot@x@LU!~!-lSqoDC-$bz^u%HAc!92IG+k+>D`vVv!>>;ww`gK)cgakQ z9r4GH>Cbs8zom& - - +{% load static i18n %}{% get_current_language as LANGUAGE_CODE %} + - - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} - {% load static %} - - {% block head %}{% endblock %} + + + {% block title %}{{ site_settings.business_name }}{% endblock %} + + {% if project_description %} + + + {% endif %} + + + + + + {% if LANGUAGE_CODE == 'ar' %} + + {% else %} + + {% endif %} + + + + + {% block head %}{% endblock %} - - {% block content %}{% endblock %} - - +
+ + + + +
+ + +
+ {% block content %}{% endblock %} +
+
+
+ + + + {% block scripts %}{% endblock %} + + \ No newline at end of file diff --git a/core/templates/core/customers.html b/core/templates/core/customers.html new file mode 100644 index 0000000..5a0219e --- /dev/null +++ b/core/templates/core/customers.html @@ -0,0 +1,103 @@ +{% extends 'base.html' %} +{% load i18n %} + +{% block title %}{% trans "Customers" %} | Meezan Accounting{% endblock %} + +{% block content %} +
+
+

{% trans "Customers" %}

+ +
+ + {% if messages %} +
+ {% for message in messages %} + + {% endfor %} +
+ {% endif %} + +
+
+
+ + + + + + + + + + + + + {% for customer in customers %} + + + + + + + + + {% empty %} + + + + {% endfor %} + +
{% trans "Name" %}{% trans "Phone" %}{% trans "Email" %}{% trans "Address" %}{% trans "Total Sales" %}{% trans "Actions" %}
{{ customer.name }}{{ customer.phone }}{{ customer.email }}{{ customer.address|truncatechars:30 }}{{ site_settings.currency_symbol }}{{ customer.total_sales|default:"0.00" }} + + +
+ {% trans "No customers found." %} +
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..74ff132 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,220 @@ -{% extends "base.html" %} +{% extends 'base.html' %} +{% load static i18n %} -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}{% trans "Smart Dashboard" %} - {{ site_settings.business_name }}{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+ +
+
+

{% trans "Overview" %}

+

{% trans "Welcome back! Here's what's happening with your business today." %}

+
+
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
-
-
- Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC) -
+ + +
+
+
+
+
+ +
+
+
{% trans "Total Revenue" %}
+

{{ site_settings.currency_symbol }}{{ total_sales_amount|floatformat:2 }}

+
+
+
+
+
+
+
+
+ +
+
+
{% trans "Total Sales" %}
+

{{ total_sales_count }}

+
+
+
+
+
+
+
+
+ +
+
+
{% trans "Total Products" %}
+

{{ total_products }}

+
+
+
+
+
+
+
+
+ +
+
+
{% trans "Total Customers" %}
+

{{ total_customers }}

+
+
+
+
+
+ +
+ +
+
+
+
{% trans "Sales Revenue" %}
+ {% trans "Last 7 Days" %} +
+ +
+
+ + +
+
+
{% trans "Low Stock Alerts" %}
+ {% if low_stock_products %} +
    + {% for product in low_stock_products %} +
  • +
    +
    + +
    +
    +

    + {% if LANGUAGE_CODE == 'ar' %}{{ product.name_ar }}{% else %}{{ product.name_en }}{% endif %} +

    + + {% if LANGUAGE_CODE == 'ar' %}{{ product.category.name_ar }}{% else %}{{ product.category.name_en }}{% endif %} + +
    +
    + {{ product.stock_quantity }} +
  • + {% endfor %} +
+ {% else %} +
+ +

{% trans "All stock levels are healthy!" %}

+
+ {% endif %} + +
+
+
+ + +
+
+
+
{% trans "Recent Sales" %}
+
+ + + + + + + + + + + + + {% for sale in recent_sales %} + + + + + + + + + {% empty %} + + + + {% endfor %} + +
{% trans "Sale ID" %}{% trans "Customer" %}{% trans "Date" %}{% trans "Total Amount" %}{% trans "Status" %}{% trans "Action" %}
#{{ sale.id }}{{ sale.customer.name|default:"Guest" }}{{ sale.created_at|date:"M d, Y H:i" }}{{ site_settings.currency_symbol }}{{ sale.total_amount }}{% trans "Completed" %} + +
{% trans "No recent sales found." %}
+
+
+
+
+ +{% endblock %} + +{% block scripts %} + + {% endblock %} \ No newline at end of file diff --git a/core/templates/core/inventory.html b/core/templates/core/inventory.html new file mode 100644 index 0000000..22398e6 --- /dev/null +++ b/core/templates/core/inventory.html @@ -0,0 +1,162 @@ +{% extends 'base.html' %} +{% load i18n static %} + +{% block title %}{% trans "Inventory Management" %} | Meezan Accounting{% endblock %} + +{% block content %} +
+
+
+

{% trans "Inventory Management" %}

+ +
+ +
+ + {% if messages %} +
+ {% for message in messages %} + + {% endfor %} +
+ {% endif %} + + +
+
+
+
+
+ + +
+
+
+ +
+
+ +
+
+
+
+ + +
+ {% for product in products %} +
+
+
+ {% if product.image %} + {{ product.name_en }} + {% else %} +
+ +
+ {% endif %} + + {% trans "In Stock" %}: {{ product.stock_quantity }} + +
+
+
+ {% if LANGUAGE_CODE == 'ar' %}{{ product.category.name_ar }}{% else %}{{ product.category.name_en }}{% endif %} +
+
+ {% if LANGUAGE_CODE == 'ar' %}{{ product.name_ar }}{% else %}{{ product.name_en }}{% endif %} +
+
+

{{ site_settings.currency_symbol }}{{ product.price }}

+
+ + +
+
+
+
+
+ {% empty %} +
+
+ +

{% trans "Your inventory is empty" %}

+

{% trans "Start by adding your first product to the system." %}

+ +
+
+ {% endfor %} +
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/pos.html b/core/templates/core/pos.html new file mode 100644 index 0000000..10c3e64 --- /dev/null +++ b/core/templates/core/pos.html @@ -0,0 +1,428 @@ +{% extends 'base.html' %} +{% load i18n static %} + +{% block title %}{% trans "POS" %} | {{ site_settings.business_name }}{% endblock %} + +{% block head %} + +{% endblock %} + +{% block content %} +
+
+ +
+
+

{% trans "Point of Sale" %}

+
+ + +
+
+ +
+
{% trans "All" %}
+ {% for category in categories %} +
+ {% if LANGUAGE_CODE == 'ar' %}{{ category.name_ar }}{% else %}{{ category.name_en }}{% endif %} +
+ {% endfor %} +
+ +
+ {% for product in products %} +
+
+ {% if product.image %} + {{ product.name_en }} + {% else %} +
+ +
+ {% endif %} +
+
+ {% if LANGUAGE_CODE == 'ar' %}{{ product.name_ar }}{% else %}{{ product.name_en }}{% endif %} +
+

{{ site_settings.currency_symbol }}{{ product.price }}

+ {% trans "Stock" %}: {{ product.stock_quantity }} +
+
+
+ {% endfor %} +
+
+ + +
+
+
+
{% trans "Current Order" %}
+ +
+ +
+
+ +
+
+ + {% trans "Your cart is empty" %} +
+
+ + +
+
+
+
+ + +
+
+
+
TAX INVOICEفاتورة ضريبية
+
+
+
+
+
+ Inv #: + رقم الفاتورة: +
+
+ Date: + التاريخ: +
+
+ + + + + + + + + + + +
Item / الصنفQtyTotal
+
+
+ TOTAL / المجموع + +
+
+
+ THANK YOU / شكراً لزيارتكم +
+
+ + + +{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/core/templates/core/purchases.html b/core/templates/core/purchases.html new file mode 100644 index 0000000..603cdd3 --- /dev/null +++ b/core/templates/core/purchases.html @@ -0,0 +1,98 @@ +{% extends 'base.html' %} +{% load i18n %} + +{% block title %}{% trans "Purchases" %} | Meezan Accounting{% endblock %} + +{% block content %} +
+
+

{% trans "Purchase History" %}

+ +
+ + {% if messages %} +
+ {% for message in messages %} + + {% endfor %} +
+ {% endif %} + +
+
+
+ + + + + + + + + + + {% for purchase in purchases %} + + + + + + + {% empty %} + + + + {% endfor %} + +
{% trans "Date" %}{% trans "Supplier" %}{% trans "Total Amount" %}{% trans "Actions" %}
{{ purchase.created_at|date:"Y-m-d H:i" }}{{ purchase.supplier.name|default:"-" }}{{ site_settings.currency_symbol }}{{ purchase.total_amount }} + +
+ {% trans "No purchases found." %} +
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/reports.html b/core/templates/core/reports.html new file mode 100644 index 0000000..34f83b1 --- /dev/null +++ b/core/templates/core/reports.html @@ -0,0 +1,70 @@ +{% extends 'base.html' %} +{% load i18n %} + +{% block title %}{% trans "Smart Reports" %} | Meezan Accounting{% endblock %} + +{% block content %} +
+
+
+

{% trans "Analytics & Reports" %}

+

{% trans "Deep dive into your business performance." %}

+
+
+ +
+ +
+
+
{% trans "Monthly Revenue" %}
+
+ + + + + + + + + {% for sale in monthly_sales %} + + + + + {% empty %} + + + + {% endfor %} + +
{% trans "Month" %}{% trans "Revenue" %}
{{ sale.month|date:"F Y" }}{{ site_settings.currency_symbol }}{{ sale.total|floatformat:2 }}
{% trans "No data available." %}
+
+
+
+ + +
+
+
{% trans "Top Selling Products" %}
+
    + {% for item in top_products %} +
  • +
    +

    + {% if LANGUAGE_CODE == 'ar' %}{{ item.product__name_ar }}{% else %}{{ item.product__name_en }}{% endif %} +

    + {{ item.total_qty }} {% trans "units sold" %} +
    +
    + {{ site_settings.currency_symbol }}{{ item.revenue|floatformat:2 }} +
    +
  • + {% empty %} +
  • {% trans "No sales data." %}
  • + {% endfor %} +
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/settings.html b/core/templates/core/settings.html new file mode 100644 index 0000000..7b85eb6 --- /dev/null +++ b/core/templates/core/settings.html @@ -0,0 +1,102 @@ +{% extends 'base.html' %} +{% load i18n %} + +{% block content %} +
+
+
+

{% trans "System Settings" %}

+

{% trans "Manage your business profile and preferences." %}

+
+
+ + {% if messages %} +
+
+ {% for message in messages %} + + {% endfor %} +
+
+ {% endif %} + +
+
+
+
+
{% trans "Business Profile" %}
+
+
+
+ {% csrf_token %} +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
{% trans "Financial Preferences" %}
+
+ + +
{% trans "e.g., $, £, SAR, AED" %}
+
+
+ + +
+
+ +
+ +
+
+
+
+
+ +
+
+
+
{% trans "Help & Support" %}
+
+
+

+ {% trans "Need help configuring your smart admin? Check our documentation or contact support." %} +

+ + {% trans "Documentation" %} + +
+
+ +
+
+ +
{% trans "Smart Admin Version" %}
+

v2.1.0-Meezan

+
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/suppliers.html b/core/templates/core/suppliers.html new file mode 100644 index 0000000..b0f699a --- /dev/null +++ b/core/templates/core/suppliers.html @@ -0,0 +1,95 @@ +{% extends 'base.html' %} +{% load i18n %} + +{% block title %}{% trans "Suppliers" %} | Meezan Accounting{% endblock %} + +{% block content %} +
+
+

{% trans "Suppliers" %}

+ +
+ + {% if messages %} +
+ {% for message in messages %} + + {% endfor %} +
+ {% endif %} + +
+
+
+ + + + + + + + + + + {% for supplier in suppliers %} + + + + + + + {% empty %} + + + + {% endfor %} + +
{% trans "Name" %}{% trans "Contact Person" %}{% trans "Phone" %}{% trans "Actions" %}
{{ supplier.name }}{{ supplier.contact_person }}{{ supplier.phone }} + + +
+ {% trans "No suppliers found." %} +
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/core/urls.py b/core/urls.py index 6299e3d..5fbb881 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,20 @@ from django.urls import path - -from .views import home +from . import views urlpatterns = [ - path("", home, name="home"), -] + path('', views.index, name='index'), + path('inventory/', views.inventory, name='inventory'), + path('pos/', views.pos, name='pos'), + path('customers/', views.customers, name='customers'), + path('suppliers/', views.suppliers, name='suppliers'), + path('purchases/', views.purchases, name='purchases'), + path('reports/', views.reports, name='reports'), + path('settings/', views.settings_view, name='settings'), + + # API / Actions + path('api/create-sale/', views.create_sale_api, name='create_sale_api'), + path('customers/add/', views.add_customer, name='add_customer'), + path('suppliers/add/', views.add_supplier, name='add_supplier'), + path('purchases/add/', views.add_purchase, name='add_purchase'), + path('inventory/add/', views.add_product, name='add_product'), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..78babbc 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,236 @@ -import os -import platform - -from django import get_version as django_version -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404, redirect +from django.db.models import Sum, Count, F +from django.db.models.functions import TruncDate, TruncMonth +from django.http import JsonResponse +from django.views.decorators.csrf import csrf_exempt +from .models import Product, Sale, Category, Customer, Supplier, Purchase, SaleItem, SystemSetting +import json +from datetime import timedelta from django.utils import timezone +from django.contrib import messages - -def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() +def index(request): + """ + Enhanced Meezan Dashboard View + """ + # Summary Stats + total_products = Product.objects.count() + total_sales_count = Sale.objects.count() + total_sales_amount = Sale.objects.aggregate(total=Sum('total_amount'))['total'] or 0 + total_customers = Customer.objects.count() + + # Stock Alert (Low stock < 5) + low_stock_products = Product.objects.filter(stock_quantity__lt=5) + + # Recent Transactions + recent_sales = Sale.objects.order_by('-created_at')[:5] + + # Chart Data: Sales for the last 7 days + seven_days_ago = timezone.now().date() - timedelta(days=6) + sales_over_time = Sale.objects.filter(created_at__date__gte=seven_days_ago) \ + .annotate(date=TruncDate('created_at')) \ + .values('date') \ + .annotate(total=Sum('total_amount')) \ + .order_by('date') + + # Prepare data for Chart.js + chart_labels = [] + chart_data = [] + + date_dict = {s['date']: float(s['total']) for s in sales_over_time} + for i in range(7): + date = seven_days_ago + timedelta(days=i) + chart_labels.append(date.strftime('%b %d')) + chart_data.append(date_dict.get(date, 0)) context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), + 'total_products': total_products, + 'total_sales_count': total_sales_count, + 'total_sales_amount': total_sales_amount, + 'total_customers': total_customers, + 'low_stock_products': low_stock_products, + 'recent_sales': recent_sales, + 'chart_labels': json.dumps(chart_labels), + 'chart_data': json.dumps(chart_data), } - return render(request, "core/index.html", context) + return render(request, 'core/index.html', context) + +def inventory(request): + products = Product.objects.all().select_related('category') + categories = Category.objects.all() + context = {'products': products, 'categories': categories} + return render(request, 'core/inventory.html', context) + +def pos(request): + products = Product.objects.all().filter(stock_quantity__gt=0) + customers = Customer.objects.all() + categories = Category.objects.all() + context = {'products': products, 'customers': customers, 'categories': categories} + return render(request, 'core/pos.html', context) + +def customers(request): + customers_list = Customer.objects.all().annotate(total_sales=Sum('sale__total_amount')) + context = {'customers': customers_list} + return render(request, 'core/customers.html', context) + +def suppliers(request): + suppliers_list = Supplier.objects.all() + context = {'suppliers': suppliers_list} + return render(request, 'core/suppliers.html', context) + +def purchases(request): + purchases_list = Purchase.objects.all().select_related('supplier') + suppliers_list = Supplier.objects.all() + context = {'purchases': purchases_list, 'suppliers': suppliers_list} + return render(request, 'core/purchases.html', context) + +def reports(request): + """ + Smart Reports View + """ + # Monthly Revenue + monthly_sales = Sale.objects.annotate(month=TruncMonth('created_at')) \ + .values('month') \ + .annotate(total=Sum('total_amount')) \ + .order_by('-month')[:12] + + # Top Selling Products + top_products = SaleItem.objects.values('product__name_en', 'product__name_ar') \ + .annotate(total_qty=Sum('quantity'), revenue=Sum('line_total')) \ + .order_by('-total_qty')[:5] + + context = { + 'monthly_sales': monthly_sales, + 'top_products': top_products, + } + return render(request, 'core/reports.html', context) + +def settings_view(request): + """ + Smart Admin Settings View + """ + settings = SystemSetting.objects.first() + if not settings: + settings = SystemSetting.objects.create() + + if request.method == 'POST': + settings.business_name = request.POST.get('business_name') + settings.address = request.POST.get('address') + settings.phone = request.POST.get('phone') + settings.email = request.POST.get('email') + settings.currency_symbol = request.POST.get('currency_symbol') + settings.tax_rate = request.POST.get('tax_rate') + settings.save() + messages.success(request, "Settings updated successfully!") + return redirect('settings') + + return render(request, 'core/settings.html', {'settings': settings}) + +@csrf_exempt +def create_sale_api(request): + if request.method == 'POST': + try: + data = json.loads(request.body) + customer_id = data.get('customer_id') + items = data.get('items', []) + total_amount = data.get('total_amount', 0) + discount = data.get('discount', 0) + + customer = None + if customer_id: + customer = Customer.objects.get(id=customer_id) + + sale = Sale.objects.create( + customer=customer, + total_amount=total_amount, + discount=discount + ) + + 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 -= item['quantity'] + product.save() + + settings = SystemSetting.objects.first() + return JsonResponse({ + 'success': True, + 'sale_id': sale.id, + 'business': { + 'name': settings.business_name, + 'address': settings.address, + 'phone': settings.phone, + 'currency': settings.currency_symbol + }, + 'sale': { + 'id': sale.id, + 'created_at': sale.created_at.strftime("%Y-%m-%d %H:%M"), + 'total': float(sale.total_amount), + 'items': [ + { + 'name_en': item.product.name_en, + 'name_ar': item.product.name_ar, + 'qty': item.quantity, + 'price': float(item.unit_price), + 'total': float(item.line_total) + } for item in sale.items.all() + ] + } + }) + except Exception as e: + return JsonResponse({'success': False, 'error': str(e)}, status=400) + return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405) + +def add_customer(request): + if request.method == 'POST': + name = request.POST.get('name') + phone = request.POST.get('phone') + email = request.POST.get('email') + address = request.POST.get('address') + Customer.objects.create(name=name, phone=phone, email=email, address=address) + messages.success(request, "Customer added successfully!") + return redirect('customers') + +def add_supplier(request): + if request.method == 'POST': + name = request.POST.get('name') + contact_person = request.POST.get('contact_person') + phone = request.POST.get('phone') + Supplier.objects.create(name=name, contact_person=contact_person, phone=phone) + messages.success(request, "Supplier added successfully!") + return redirect('suppliers') + +def add_purchase(request): + if request.method == 'POST': + supplier_id = request.POST.get('supplier') + total_amount = request.POST.get('total_amount') + supplier = get_object_or_404(Supplier, id=supplier_id) + Purchase.objects.create(supplier=supplier, total_amount=total_amount) + messages.success(request, "Purchase recorded successfully!") + return redirect('purchases') + +def add_product(request): + if request.method == 'POST': + name_en = request.POST.get('name_en') + name_ar = request.POST.get('name_ar') + category_id = request.POST.get('category') + sku = request.POST.get('sku') + price = request.POST.get('price') + stock = request.POST.get('stock') + category = get_object_or_404(Category, id=category_id) + Product.objects.create( + name_en=name_en, + name_ar=name_ar, + category=category, + sku=sku, + price=price, + stock_quantity=stock + ) + messages.success(request, "Product added successfully!") + return redirect('inventory') diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..a3ebcdc 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,159 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +/* Meezan Accounting Custom Styles */ +:root { + --meezan-primary: #2E5BFF; + --meezan-secondary: #8C9EFF; + --meezan-accent: #FFAB40; + --meezan-bg: #F8FAFF; + --meezan-sidebar-bg: #FFFFFF; + --meezan-text: #1A202C; + --meezan-glass: rgba(255, 255, 255, 0.7); + --sidebar-width: 260px; +} + +body { + font-family: 'Plus Jakarta Sans', 'Cairo', sans-serif; + background-color: var(--meezan-bg); + color: var(--meezan-text); + overflow-x: hidden; +} + +/* RTL Specific Tweaks */ +[dir="rtl"] { + font-family: 'Cairo', 'Plus Jakarta Sans', sans-serif; +} + +.bg-primary { + background-color: var(--meezan-primary) !important; +} + +.text-primary { + color: var(--meezan-primary) !important; +} + +/* Glassmorphism Effect */ +.glass-card { + background: var(--meezan-glass); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 16px; + box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07); +} + +/* Sidebar Styling */ +#wrapper { + display: flex; + width: 100%; + align-items: stretch; +} + +#sidebar { + min-width: var(--sidebar-width); + max-width: var(--sidebar-width); + background: var(--meezan-sidebar-bg); + color: var(--meezan-text); + transition: all 0.3s; + border-inline-end: 1px solid rgba(0,0,0,0.05); + z-index: 1000; + position: sticky; + top: 0; + height: 100vh; +} + +#sidebar.active { + margin-inline-start: calc(-1 * var(--sidebar-width)); +} + +#sidebar .sidebar-header { + padding: 20px; + background: var(--meezan-sidebar-bg); +} + +#sidebar ul.components { + padding: 20px 0; +} + +#sidebar ul li a { + padding: 12px 25px; + font-size: 1rem; + display: flex; + align-items: center; + color: var(--meezan-text); + text-decoration: none; + transition: all 0.3s; + border-radius: 0 50px 50px 0; + margin-inline-end: 15px; +} + +[dir="rtl"] #sidebar ul li a { + border-radius: 50px 0 0 50px; + margin-inline-start: 15px; + margin-inline-end: 0; +} + +#sidebar ul li a:hover, #sidebar ul li a.active { + background: rgba(46, 91, 255, 0.1); + color: var(--meezan-primary); + font-weight: 600; +} + +#sidebar ul li a i { + margin-inline-end: 15px; + font-size: 1.2rem; +} + +/* Main Content Styling */ +#content { + width: 100%; + padding: 0; + min-height: 100vh; + transition: all 0.3s; +} + +.top-navbar { + padding: 15px 30px; + background: #fff; + border-bottom: 1px solid rgba(0,0,0,0.05); +} + +/* Hero Section */ +.hero-gradient { + background: linear-gradient(135deg, var(--meezan-primary) 0%, var(--meezan-secondary) 100%); + border-radius: 24px; + padding: 3rem; + color: white; + position: relative; + overflow: hidden; +} + +/* Buttons */ +.btn-primary { + background-color: var(--meezan-primary); + border: none; + padding: 0.6rem 1.5rem; + border-radius: 10px; + font-weight: 600; + transition: all 0.3s ease; +} + +/* Dashboard Stats */ +.stat-card { + transition: transform 0.3s ease; +} + +.stat-card:hover { + transform: translateY(-5px); +} + +/* Mobile Tweaks */ +@media (max-width: 992px) { + #sidebar { + margin-inline-start: calc(-1 * var(--sidebar-width)); + position: fixed; + } + #sidebar.active { + margin-inline-start: 0; + } + #content { + width: 100%; + } } diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css index 108056f..a3ebcdc 100644 --- a/staticfiles/css/custom.css +++ b/staticfiles/css/custom.css @@ -1,21 +1,159 @@ - +/* Meezan Accounting Custom Styles */ :root { - --bg-color-start: #6a11cb; - --bg-color-end: #2575fc; - --text-color: #ffffff; - --card-bg-color: rgba(255, 255, 255, 0.01); - --card-border-color: rgba(255, 255, 255, 0.1); + --meezan-primary: #2E5BFF; + --meezan-secondary: #8C9EFF; + --meezan-accent: #FFAB40; + --meezan-bg: #F8FAFF; + --meezan-sidebar-bg: #FFFFFF; + --meezan-text: #1A202C; + --meezan-glass: rgba(255, 255, 255, 0.7); + --sidebar-width: 260px; } + body { - margin: 0; - font-family: 'Inter', sans-serif; - background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); - color: var(--text-color); - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - text-align: center; - overflow: hidden; - position: relative; + font-family: 'Plus Jakarta Sans', 'Cairo', sans-serif; + background-color: var(--meezan-bg); + color: var(--meezan-text); + overflow-x: hidden; +} + +/* RTL Specific Tweaks */ +[dir="rtl"] { + font-family: 'Cairo', 'Plus Jakarta Sans', sans-serif; +} + +.bg-primary { + background-color: var(--meezan-primary) !important; +} + +.text-primary { + color: var(--meezan-primary) !important; +} + +/* Glassmorphism Effect */ +.glass-card { + background: var(--meezan-glass); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 16px; + box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07); +} + +/* Sidebar Styling */ +#wrapper { + display: flex; + width: 100%; + align-items: stretch; +} + +#sidebar { + min-width: var(--sidebar-width); + max-width: var(--sidebar-width); + background: var(--meezan-sidebar-bg); + color: var(--meezan-text); + transition: all 0.3s; + border-inline-end: 1px solid rgba(0,0,0,0.05); + z-index: 1000; + position: sticky; + top: 0; + height: 100vh; +} + +#sidebar.active { + margin-inline-start: calc(-1 * var(--sidebar-width)); +} + +#sidebar .sidebar-header { + padding: 20px; + background: var(--meezan-sidebar-bg); +} + +#sidebar ul.components { + padding: 20px 0; +} + +#sidebar ul li a { + padding: 12px 25px; + font-size: 1rem; + display: flex; + align-items: center; + color: var(--meezan-text); + text-decoration: none; + transition: all 0.3s; + border-radius: 0 50px 50px 0; + margin-inline-end: 15px; +} + +[dir="rtl"] #sidebar ul li a { + border-radius: 50px 0 0 50px; + margin-inline-start: 15px; + margin-inline-end: 0; +} + +#sidebar ul li a:hover, #sidebar ul li a.active { + background: rgba(46, 91, 255, 0.1); + color: var(--meezan-primary); + font-weight: 600; +} + +#sidebar ul li a i { + margin-inline-end: 15px; + font-size: 1.2rem; +} + +/* Main Content Styling */ +#content { + width: 100%; + padding: 0; + min-height: 100vh; + transition: all 0.3s; +} + +.top-navbar { + padding: 15px 30px; + background: #fff; + border-bottom: 1px solid rgba(0,0,0,0.05); +} + +/* Hero Section */ +.hero-gradient { + background: linear-gradient(135deg, var(--meezan-primary) 0%, var(--meezan-secondary) 100%); + border-radius: 24px; + padding: 3rem; + color: white; + position: relative; + overflow: hidden; +} + +/* Buttons */ +.btn-primary { + background-color: var(--meezan-primary); + border: none; + padding: 0.6rem 1.5rem; + border-radius: 10px; + font-weight: 600; + transition: all 0.3s ease; +} + +/* Dashboard Stats */ +.stat-card { + transition: transform 0.3s ease; +} + +.stat-card:hover { + transform: translateY(-5px); +} + +/* Mobile Tweaks */ +@media (max-width: 992px) { + #sidebar { + margin-inline-start: calc(-1 * var(--sidebar-width)); + position: fixed; + } + #sidebar.active { + margin-inline-start: 0; + } + #content { + width: 100%; + } }