From d8650f3b094d1be105c0bfc804cbe727531c0c2d Mon Sep 17 00:00:00 2001 From: Faheed Date: Tue, 9 Sep 2025 18:23:39 +0300 Subject: [PATCH] ui change for plans list and admin management to only show the admin user --- inventory/management/commands/tenhal_plan.py | 201 ++++---- inventory/views.py | 26 +- templates/account/success.html | 5 +- templates/admin_management/management.html | 4 +- templates/crm/leads/lead_list.html | 2 +- templates/crm/leads/lead_tracking.html | 2 +- .../crm/opportunities/opportunity_list.html | 2 +- templates/customers/customer_list.html | 2 +- templates/groups/group_detail.html | 2 +- templates/header.html | 2 +- templates/inventory/inventory_stats.html | 2 +- .../organizations/organization_list.html | 2 +- templates/payment_failed.html | 63 ++- templates/payment_success.html | 74 +-- templates/plans/order_list.html | 2 +- templates/pricing_page.html | 479 +++++++++++------- templates/purchase_orders/po_list.html | 2 +- templates/sales/estimates/estimate_form.html | 4 +- templates/sales/invoices/invoice_list.html | 2 +- templates/users/user_list.html | 2 +- 20 files changed, 531 insertions(+), 349 deletions(-) diff --git a/inventory/management/commands/tenhal_plan.py b/inventory/management/commands/tenhal_plan.py index e91d0b95..8d21a127 100644 --- a/inventory/management/commands/tenhal_plan.py +++ b/inventory/management/commands/tenhal_plan.py @@ -5,119 +5,128 @@ from plans.models import Plan, Quota, PlanQuota, Pricing, PlanPricing class Command(BaseCommand): - help = "Create basic subscription plans structure" + help = "Create basic subscription plans structure." def add_arguments(self, parser): parser.add_argument( "--reset", action="store_true", - help="Delete existing plans and quotas before creating new ones", + help="Delete existing plans and quotas before creating new ones.", ) def handle(self, *args, **options): - # Plan.objects.all().delete() - # Quota.objects.all().delete() - # PlanQuota.objects.all().delete() - # Pricing.objects.all().delete() - # PlanPricing.objects.all().delete() - # UserPlan.objects.all().delete() - # Order.objects.all().delete() - # BillingInfo.objects.all().delete() + if options["reset"]: + self.stdout.write(self.style.WARNING("Resetting all plan-related data...")) + Plan.objects.all().delete() + Quota.objects.all().delete() + Pricing.objects.all().delete() + # Note: Deleting plans and quotas should cascade to related objects like PlanQuota and PlanPricing. + self.stdout.write(self.style.SUCCESS("Data reset complete.")) + else: + self.stdout.write(self.style.NOTICE("Creating or updating default plans and quotas...")) - users_quota = Quota.objects.create( - name="Users", codename="Users", unit="number" + # Create or get quotas + users_quota, created_u = Quota.objects.get_or_create( + codename="Users", + defaults={"name": "Users", "unit": "number"} ) - cars_quota = Quota.objects.create(name="Cars", codename="Cars", unit="number") - # Create plans - basic_plan = Plan.objects.create( - name="Basic", description="basic plan", available=True, visible=True + if created_u: + self.stdout.write(self.style.SUCCESS('Created quota: "Users"')) + + cars_quota, created_c = Quota.objects.get_or_create( + codename="Cars", + defaults={"name": "Cars", "unit": "number"} ) - pro_plan = Plan.objects.create( - name="Pro", description="Pro plan", available=True, visible=True + if created_c: + self.stdout.write(self.style.SUCCESS('Created quota: "Cars"')) + + # Create or get plans + basic_plan, created_bp = Plan.objects.get_or_create( + name="Basic", + defaults={"description": "basic plan", "available": True, "visible": True} ) - enterprise_plan = Plan.objects.create( + if created_bp: + self.stdout.write(self.style.SUCCESS('Created plan: "Basic"')) + + pro_plan, created_pp = Plan.objects.get_or_create( + name="Pro", + defaults={"description": "Pro plan", "available": True, "visible": True} + ) + if created_pp: + self.stdout.write(self.style.SUCCESS('Created plan: "Pro"')) + + enterprise_plan, created_ep = Plan.objects.get_or_create( name="Enterprise", - description="Enterprise plan", - available=True, - visible=True, + defaults={"description": "Enterprise plan", "available": True, "visible": True} + ) + if created_ep: + self.stdout.write(self.style.SUCCESS('Created plan: "Enterprise"')) + + # Assign quotas to plans using get_or_create to prevent duplicates + PlanQuota.objects.get_or_create( + plan=basic_plan, + quota=users_quota, + defaults={"value": 10000000} + ) + PlanQuota.objects.get_or_create( + plan=basic_plan, + quota=cars_quota, + defaults={"value": 10000000} + ) + + # Pro plan quotas + PlanQuota.objects.get_or_create( + plan=pro_plan, + quota=users_quota, + defaults={"value": 10000000} + ) + PlanQuota.objects.get_or_create( + plan=pro_plan, + quota=cars_quota, + defaults={"value": 10000000} ) - # Assign quotas to plans - PlanQuota.objects.create(plan=basic_plan, quota=users_quota, value=10000000) - PlanQuota.objects.create(plan=basic_plan, quota=cars_quota, value=10000000) - - PlanQuota.objects.create(plan=pro_plan, quota=users_quota, value=10000000) - PlanQuota.objects.create(plan=pro_plan, quota=cars_quota, value=10000000) - - PlanQuota.objects.create(plan=enterprise_plan, quota=users_quota, value=10000000) - PlanQuota.objects.create(plan=enterprise_plan, quota=cars_quota, value=10000000) - - # PlanQuota.objects.create(plan=pro_plan, quota=project_quota, value=50) - # PlanQuota.objects.create(plan=pro_plan, quota=storage_quota, value=100) - - # Define pricing - basic_pricing = Pricing.objects.create(name="3 Months", period=90) - pro_pricing = Pricing.objects.create(name="6 Months", period=180) - enterprise_pricing = Pricing.objects.create(name="1 Year", period=365) - - PlanPricing.objects.create( - plan=basic_plan, pricing=basic_pricing, price=Decimal("2997.00") + # Enterprise plan quotas + PlanQuota.objects.get_or_create( + plan=enterprise_plan, + quota=users_quota, + defaults={"value": 10000000} ) - PlanPricing.objects.create( - plan=pro_plan, pricing=pro_pricing, price=Decimal("5395.00") - ) - PlanPricing.objects.create( - plan=enterprise_plan, pricing=enterprise_pricing, price=Decimal("9590.00") + PlanQuota.objects.get_or_create( + plan=enterprise_plan, + quota=cars_quota, + defaults={"value": 10000000} ) - # # Create quotas - # project_quota = Quota.objects.create(name='projects', codename='projects', unit='projects') - # storage_quota = Quota.objects.create(name='storage', codename='storage', unit='GB') + # Create or get pricing + basic_pricing, created_bp_p = Pricing.objects.get_or_create( + name="3 Months", + defaults={"period": 90} + ) + pro_pricing, created_pp_p = Pricing.objects.get_or_create( + name="6 Months", + defaults={"period": 180} + ) + enterprise_pricing, created_ep_p = Pricing.objects.get_or_create( + name="1 Year", + defaults={"period": 365} + ) - # # Create plans - # basic_plan = Plan.objects.create(name='Basic', description='Basic plan', available=True, visible=True) - # pro_plan = Plan.objects.create(name='Pro', description='Pro plan', available=True, visible=True) + # Assign pricing to plans + PlanPricing.objects.get_or_create( + plan=basic_plan, + pricing=basic_pricing, + defaults={"price": Decimal("2997.00")} + ) + PlanPricing.objects.get_or_create( + plan=pro_plan, + pricing=pro_pricing, + defaults={"price": Decimal("5395.00")} + ) + PlanPricing.objects.get_or_create( + plan=enterprise_plan, + pricing=enterprise_pricing, + defaults={"price": Decimal("9590.00")} + ) - # # Assign quotas to plans - # PlanQuota.objects.create(plan=basic_plan, quota=project_quota, value=5) - # PlanQuota.objects.create(plan=basic_plan, quota=storage_quota, value=10) - - # PlanQuota.objects.create(plan=pro_plan, quota=project_quota, value=50) - # PlanQuota.objects.create(plan=pro_plan, quota=storage_quota, value=100) - - # # Define pricing - - # basic = Pricing.objects.create(name='Monthly', period=30) - # pro = Pricing.objects.create(name='Monthly', period=30) - - # basic_pricing = PlanPricing.objects.create(plan=basic_plan, pricing=basic, price=Decimal('19.99')) - # pro_pricing = PlanPricing.objects.create(plan=pro_plan, pricing=pro, price=Decimal('29.99')) - # Create users - - # user = User.objects.first() - - # # Create user plans - # billing_info = BillingInfo.objects.create( - # user=user, - # tax_number='123456789', - # name='John Doe', - # street='123 Main St', - # zipcode='12345', - # city='Anytown', - # country='US', - # ) - - # order = Order.objects.create( - # user=user, - # plan=pro_plan, - # pricing=pro_pricing, - # amount=pro_pricing.price, - # currency="SAR", - # ) - - # UserPlan.objects.create( - # user=user, - # plan=pro_plan, - # expire=timezone.now() + timedelta(days=2), - # active=True, - # ) + self.stdout.write(self.style.SUCCESS("Subscription plans structure successfully created or updated.")) \ No newline at end of file diff --git a/inventory/views.py b/inventory/views.py index c3ef267d..8187c6f4 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -1585,7 +1585,7 @@ def inventory_stats_view(request, dealer_slug): for make_data in inventory.values() ], } - return render(request, "inventory/inventory_stats.html", {"inventory": result}) + return render(request, "inventory/inventory_stats.html", {"inventory": result,"empty_state_value":_("car")}) # @login_required @@ -2450,6 +2450,7 @@ class CustomerListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["query"] = self.request.GET.get("q", "") + context["empty_state_value"] = _("customers") return context @@ -3553,7 +3554,10 @@ class UserListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"]) staff = models.Staff.objects.filter(dealer=dealer, active=True).all() return apply_search_filters(staff, query) - + def get_context_data(self, **kwargs): + context=super().get_context_data(**kwargs) + context['no_staff_message']=_("staff") + return context class UserDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): """ @@ -3800,7 +3804,10 @@ class OrganizationListView(LoginRequiredMixin, PermissionRequiredMixin, ListView organization = dealer.organizations.filter(active=True) return apply_search_filters(organization, query) - + def get_context_data(self, **kwargs): + context=super().get_context_data(**kwargs) + context["empty_state_value"]=_("organization") + return context class OrganizationDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): """ @@ -5020,6 +5027,10 @@ def create_estimate(request, dealer_slug, slug=None): ], "opportunity_id": slug if slug else None, "customer_count": entity.get_customers().count(), + "no_items_message": _("Please add at least one car or complete the car info before creating a quotation."), + "no_items_button": _("Add car"), + "no_customers_message": _("Please add at least one customer before creating a quotation."), + "no_customers_button": _("Add Customer"), } return render(request, "sales/estimates/estimate_form.html", context) @@ -6168,6 +6179,10 @@ class LeadListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): if self.request.is_staff: return qs.filter(staff=self.request.staff) return models.Lead.objects.none() + def get_context_data(self, **kwargs): + context=super().get_context_data(**kwargs) + context['empty_state_value']=_("lead") + return context class LeadDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): @@ -6418,7 +6433,8 @@ def lead_tracking(request, dealer_slug): "won": won, "lose": lose, "negotiation": negotiation, - "leads":leads + "leads":leads, + "empty_state_value": _("lead"), } return render(request, "crm/leads/lead_tracking.html", context) @@ -7471,6 +7487,7 @@ class OpportunityListView(LoginRequiredMixin, PermissionRequiredMixin, ListView) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["stage_choices"] = models.Stage.choices + context["empty_state_value"] = _("opportunity") return context def get_template_names(self): @@ -10720,6 +10737,7 @@ class PurchaseOrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListVie context = super().get_context_data(**kwargs) context["entity_slug"] = dealer.entity.slug context["vendors"] = vendors + context["empty_state_value"] = _("purchase order") return context diff --git a/templates/account/success.html b/templates/account/success.html index 29246884..e9c56f07 100644 --- a/templates/account/success.html +++ b/templates/account/success.html @@ -21,10 +21,11 @@
-

{% trans 'Account Created Successfully' %}

+

{% trans 'Registration Successful!' %}

{% blocktrans %} - Thank you for registering at Haikal. We will contact you soon. + + Thank you for registering at Haikal. We've received your information and a member of our team will contact you shortly to confirm your account details. {% endblocktrans %}

diff --git a/templates/admin_management/management.html b/templates/admin_management/management.html index 600ae9e2..0d155197 100644 --- a/templates/admin_management/management.html +++ b/templates/admin_management/management.html @@ -5,6 +5,7 @@ {% endblock %} {% block content %} +{% if request.user.is_superuser %}

@@ -12,7 +13,7 @@ {% trans "Admin Dashboard" %}

- {% trans "Manage user accounts, review system logs, and control access permissions." %} + {% trans "Manage user accounts and review system logs." %}

@@ -41,4 +42,5 @@
+{% endif %} {% endblock content %} \ No newline at end of file diff --git a/templates/crm/leads/lead_list.html b/templates/crm/leads/lead_list.html index 3c8757c7..9fab2850 100644 --- a/templates/crm/leads/lead_list.html +++ b/templates/crm/leads/lead_list.html @@ -258,6 +258,6 @@ {% else %} {% url 'lead_create' request.dealer.slug as create_lead_url %} - {% include "empty-illustration-page.html" with value="lead" url=create_lead_url %} + {% include "empty-illustration-page.html" with value=empty_state_value url=create_lead_url %} {% endif %} {% endblock %} diff --git a/templates/crm/leads/lead_tracking.html b/templates/crm/leads/lead_tracking.html index b3be0f19..14d0f81c 100644 --- a/templates/crm/leads/lead_tracking.html +++ b/templates/crm/leads/lead_tracking.html @@ -175,6 +175,6 @@ {% else %} {% url 'lead_create' request.dealer.slug as create_lead_url %} - {% include "empty-illustration-page.html" with value="lead" url=create_lead_url %} + {% include "empty-illustration-page.html" with value=empty_state_value url=create_lead_url %} {% endif %} {% endblock %} diff --git a/templates/crm/opportunities/opportunity_list.html b/templates/crm/opportunities/opportunity_list.html index b07b5ba5..97533751 100644 --- a/templates/crm/opportunities/opportunity_list.html +++ b/templates/crm/opportunities/opportunity_list.html @@ -118,7 +118,7 @@ {% endif %} {% else %} {% url 'opportunity_create' request.dealer.slug as create_opportunity_url %} - {% include "empty-illustration-page.html" with value="opportunity" url=create_opportunity_url %} + {% include "empty-illustration-page.html" with value=empty_state_value url=create_opportunity_url %} {% endif %} {% block customJS %}