From fa0a7355489ba24d70865b523f360de05d3379ad Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 11 Feb 2026 17:23:51 +0000 Subject: [PATCH] permission add --- accounting/__pycache__/views.cpython-311.pyc | Bin 17870 -> 18239 bytes accounting/views.py | 3 +++ core/__pycache__/models.cpython-311.pyc | Bin 46648 -> 46802 bytes core/__pycache__/views.cpython-311.pyc | Bin 127296 -> 128968 bytes .../0038_alter_systemsetting_options.py | 17 +++++++++++++++++ .../0039_alter_systemsetting_options.py | 17 +++++++++++++++++ core/models.py | 3 +++ core/templates/base.html | 10 +++++++++- core/views.py | 18 +++++++++++++++++- 9 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 core/migrations/0038_alter_systemsetting_options.py create mode 100644 core/migrations/0039_alter_systemsetting_options.py diff --git a/accounting/__pycache__/views.cpython-311.pyc b/accounting/__pycache__/views.cpython-311.pyc index 30c15097e8e923e3292b5abbdc2a70ed89593955..d6190442a5c3223eb9e09d3b35563a90de30d28f 100644 GIT binary patch delta 3163 zcmb7GYitzP6`s3~*;4wZjO7ED{*6NAQk2H z?I3ZltV^;kXSiMOHauuG zSnE7aYM{$)owjg?iC@5K~Z&Qy+Ap#+xkyGqV- z6usJNq!$j7f=kV&LQ9{eaD3jlK&0B^?(e2qv2@!VY4|FQw8Wdp_oVTFM_!n|lB=KF z|HSbcko_ZAYE*OCpA$g)t{?59x>KecLNtEHIyP3oKS0+_Sns(V>^zm7}luVd03H;h*U0U z)X z8Pdk$-XHSKa1u?jLGRmLO{S};%hdELx(K!-Bc^vWtBXiYyZSwM=qGF6wA5tN0+D!$v zz3xeJi2c6qa=H!mc(>7BgiQ$8M>K=bgAhRIV{gaW-8qkYnt2eKheT zDh2>_WE18G9c0Z73HM1*Zm;w<3^^c(SMK?;-8ya?Zu%Jl-jQhswGMb1!u2RTkjTB{7+E71nqoKAe-Satw_~uPLx%HD$t|nKzoV}2__k;bfsop z{3#?l!vd{6eicOxfwIBYD?HjBTgl!}#wNza5sl_MM~!?A5{SW4Okg^(ysVZ>&*M7Y z?eq+Q={YDHIYl?<3#e*D6`wViJlemC@EQxWCwee4lgK(chE-Y^);nO<<+ExL zQnff`+x0T8TFtZ-Br{Bls;a05#RJ(~Rvnh(_^)hO&3 zLfPSAt*9DeASX));rhA?Cf6(bIs*inuqzd>ob1}*c)%(;wwoP89wn>r1(XgUSaCUR zf9ycn*WKL{c0R!%U9+h4^RJj0tY**ZZ@aJikS~JpE&{$KY2Tu9T|@0WG2MrcRtk7Y zKA;%7>48>|K+t{c{Mul05Dd&9^fMHznw$?n_Zdw6LBc+Ww^ZiVCLrR9|3_atMXO>W zvK~N?5EOtkp<^gpkz>5nO2jWv!jRJr(=kjsh<$k0|~L;bVkP0Cc3RHXZ)jjTij35TZUR%Lcs(M&DE}^n8Owc)eF7 zeoQ#EilE;)2P2#BB}w+&=DW%P82bhIJ4^qHM+~w4E%HPOMf|6k_AF}CO{o2@@ZEO! zv$*~#!ru@~03H5;+u_=A`U_MWQ4BGs={o&8tR>)NeF}sV+?TQDpHIxjI&Q{Td*2&8 zej4c>_LsgEvcB@KzLn%B_}Ql?5%60>t?vU~veqSIy{Z)Z*vg(oei7n91$O*@ybtCz qshE>D(SKGR-?o{=HTu=V{s?j5&i?|L7{Ac~ delta 2720 zcma)8ZERCz6u$56`n7)StD|n+M$5ujaoyZtFxN50m^xuBnGgknl+xafj;2;(OA>3N^` zyyrcicRT$uyD-6=M;wk^0iTBWMC?M~g!50)HJl>|lR`@9CtiCFF<_O&u&Tbmc{^Px z9%h1Y3}5{j6;n)ZR*chYLFhL?TiG1g5SRm}>Wknx{Eau{xkgz^l&kKbxHI4;1;?nU z*fUn(y1@tIMx)tuSj6i@*yx>GVLooT<#L1Ky6X{Z<_KIVoLg+Y<#_ z#*Prpy;<$J?dEmVUXoEBWKqYcaoUWicz{)vR?T|CH1kAjfhRcI6=uA~g0D4|(;+;$ zeKZ$k8@~2bE^IM+!D}uq@nyUcQjY$D=~aIreA?tLa4I+N7ZGdDOXa1U(R?^y?qNRo z$?U5sh!!5q9W7M+)8_?jj%ZP;@UQ_3fv^6o75uJlc-n&Tg44RlRE{*SfJdzFvtp>q zJyx$1$f`y;9G7I(Iyl55+rqLW^M#~*KS2#afS?vcThO)wMb)5$hj|@z+IsWX;5rXq zS;00K7p|u5_Jd~D1xJgPvQ_Y7QGj(ro@+x{51Dw3U>#|rvf%adE+U?Q&f*%j8cw)K z`3KjU*_FFss5nsCji*(Uv|}iyjBqQNBC~!Yp9>!sKf|^|)0`9QtB9wW;!6pd2<{_T zOwdR`UCo08g#u7r`&`PLkKc zFSS*umS5MfEZf#v{2OUMlR6A`5SufqyKd24f0I97-smxD@TflzfC5XVPEQ*%?+&eV|8d)G9{PY(Y>>QE6*T zkyUeqOHmYLE95VBlyuRa1Dg`-vNaqJCn6I61iA0iOBO#wF{T=?8$w!1Hju4N1e*yW z2!6(+Bx~_flw1q{Rg$!65>+w6RWZu>Y2vgrogs(6fA&N2Hc3+W1yuSi?Oyf=)gW(qh}kILT&uyr>?xRP zt7K*HciTPX0F`a!46R?JE4tys71G#KB$guh%`XQoO31tY2Ib6 z-&uZ5R-`J&K1WGSjibctm1NnOs#=?05tozKw$}!vI*+W!)Z5C$paTU*LU72Eq6C6| z`J~eXvG$DAT8Un)mL*S6tdeLZth5vyKEj$e{C^g$wzey=%z`%_O@$915wmoZnn$^6?W$8zc(Dt%pd1y4o5_%1<{k=T@wvwz28RS6jknBbig% z+fBp_Yy}iCsYdRl@C4K+9m|AhaKH078HaD3#pY2ALBzq;H9}*P%S4#>~HJ@^B-`(udXmlfDUkLTp4e k7#gvYC3SXWx6!qq>|NuwqU~7t#5(F5o6br#CF&yo03Wdm2LJ#7 delta 759 zcmZXRe@IhN6vy9r^F86=Qz~p}jKKV(ku8F(xo9Iq0llwZhA&0kdO!uWRKh5nlTL736BWR**`-TyGDI;-TnP z=;4v*#fmjGibyWTJZZ&pqJeL?t|{=2Z@XCuS`5TtgfZT7t4f9#_x8^Le8L^^{i1z1 z?$$C?LYT&Ed<-)D%ALbdov%7;u(s}y;p_5u8uL4z=W-#>XV6N7xGr%R{N9p*B;SEril|RP>Su9;l#>Qq1v8Y9|zNGMJ!qJ|Zst4548LiJ z$I0T~^e*M2sQZPxhyS>zsn0{Qsbw3>2_awE?hpA*lUZpN6YWInEY-g!e8BUWMrB5X z3p|ktL%lVu^~bE|u_mO0*bMF)alkA$MrxHN7c>;4#fa{`c3__LVmaBy2cI;-KUp{5 AmjD0& diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 43fa783b3f598dca9dd7b460a1f7568a69a57b15..f515055ac4383bce8d1adef3d325dad018e24a8a 100644 GIT binary patch delta 11134 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 X+LDB6OSOF=uFA(3oLhc?wZ8uYNp%S2 delta 10026 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 diff --git a/core/migrations/0038_alter_systemsetting_options.py b/core/migrations/0038_alter_systemsetting_options.py new file mode 100644 index 0000000..c63568c --- /dev/null +++ b/core/migrations/0038_alter_systemsetting_options.py @@ -0,0 +1,17 @@ +# Generated by Django 5.2.7 on 2026-02-11 17:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0037_alter_systemsetting_options'), + ] + + operations = [ + migrations.AlterModelOptions( + name='systemsetting', + options={'permissions': [('view_dashboard', 'Can view dashboard'), ('view_pos', 'Can access POS'), ('view_reports', 'Can view reports'), ('view_accounting', 'Can view accounting'), ('view_hr', 'Can view HR'), ('view_inventory', 'Can view inventory'), ('view_sales', 'Can view sales'), ('view_purchases', 'Can view purchases'), ('view_customers', 'Can view customers'), ('view_suppliers', 'Can view suppliers'), ('view_expenses', 'Can view expenses'), ('view_lpo', 'Can view LPO'), ('view_quotations', 'Can view quotations'), ('view_system', 'Can view system settings')]}, + ), + ] diff --git a/core/migrations/0039_alter_systemsetting_options.py b/core/migrations/0039_alter_systemsetting_options.py new file mode 100644 index 0000000..1670ce2 --- /dev/null +++ b/core/migrations/0039_alter_systemsetting_options.py @@ -0,0 +1,17 @@ +# Generated by Django 5.2.7 on 2026-02-11 17:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0038_alter_systemsetting_options'), + ] + + operations = [ + migrations.AlterModelOptions( + name='systemsetting', + options={'permissions': [('view_dashboard', 'Can view dashboard'), ('view_pos', 'Can access POS'), ('view_reports', 'Can view reports'), ('view_accounting', 'Can view accounting'), ('view_hr', 'Can view HR'), ('view_inventory', 'Can view inventory'), ('view_sales', 'Can view sales'), ('view_purchases', 'Can view purchases'), ('view_customers', 'Can view customers'), ('view_suppliers', 'Can view suppliers'), ('view_expenses', 'Can view expenses'), ('view_lpo', 'Can view LPO'), ('view_quotations', 'Can view quotations'), ('view_system', 'Can view system settings')], 'verbose_name': 'System & App Access', 'verbose_name_plural': 'System & App Access'}, + ), + ] diff --git a/core/models.py b/core/models.py index f8a7dc0..aaa7dde 100644 --- a/core/models.py +++ b/core/models.py @@ -415,6 +415,8 @@ class SystemSetting(models.Model): allow_zero_stock_sales = models.BooleanField(_("Allow selling items with 0 stock"), default=False) class Meta: + verbose_name = _("System & App Access") + verbose_name_plural = _("System & App Access") permissions = [ ("view_dashboard", "Can view dashboard"), ("view_pos", "Can access POS"), @@ -429,6 +431,7 @@ class SystemSetting(models.Model): ("view_expenses", "Can view expenses"), ("view_lpo", "Can view LPO"), ("view_quotations", "Can view quotations"), + ("view_system", "Can view system settings"), ] def __str__(self): diff --git a/core/templates/base.html b/core/templates/base.html index 245a880..c60e529 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -328,7 +328,7 @@ {% endif %} - {% if user.is_staff %} + {% if user.is_staff or perms.core.view_system %} {% endif %} diff --git a/core/views.py b/core/views.py index a641c24..4bfb7ba 100644 --- a/core/views.py +++ b/core/views.py @@ -1031,7 +1031,11 @@ def expense_category_delete_view(request, pk): @login_required def expense_report(request): - return render(request, 'core/expense_report.html') + if not (request.user.is_staff or request.user.has_perm('core.view_reports')): + messages.error(request, _("You do not have permission to view reports.")) + return redirect('index') + start_date = request.GET.get('start_date') + end_date = request.GET.get('end_date') @login_required def export_expenses_excel(request): @@ -1041,10 +1045,16 @@ def export_expenses_excel(request): @login_required def reports(request): + if not (request.user.is_staff or request.user.has_perm('core.view_reports')): + messages.error(request, _("You do not have permission to view reports.")) + return redirect('index') return render(request, 'core/reports.html') @login_required def customer_statement(request): + if not (request.user.is_staff or request.user.has_perm('core.view_reports')): + messages.error(request, _("You do not have permission to view reports.")) + return redirect('index') customers = Customer.objects.all().order_by('name') selected_customer = None sales = [] @@ -1090,6 +1100,9 @@ def customer_statement(request): @login_required def supplier_statement(request): + if not (request.user.is_staff or request.user.has_perm('core.view_reports')): + messages.error(request, _("You do not have permission to view reports.")) + return redirect('index') suppliers = Supplier.objects.all().order_by('name') selected_supplier = None purchases = [] @@ -1135,6 +1148,9 @@ def supplier_statement(request): @login_required def cashflow_report(request): + if not (request.user.is_staff or request.user.has_perm('core.view_reports')): + messages.error(request, _("You do not have permission to view reports.")) + return redirect('index') start_date = request.GET.get('start_date') end_date = request.GET.get('end_date')