From 53c4f491ab19b6ca9f9c85c1d920e895c9c75cc7 Mon Sep 17 00:00:00 2001 From: ismail <=> Date: Tue, 29 Apr 2025 14:06:02 +0300 Subject: [PATCH] fix the customer note --- inventory/management/commands/setplan.py | 124 +++++++++++++++++++ inventory/management/commands/tenhal_plan.py | 47 +++++++ inventory/models.py | 12 +- inventory/services.py | 2 +- inventory/urls.py | 2 +- inventory/views.py | 2 - scripts/set_plans.py | 63 ++++++++++ templates/customers/view_customer.html | 19 +-- 8 files changed, 257 insertions(+), 14 deletions(-) create mode 100644 inventory/management/commands/setplan.py create mode 100644 inventory/management/commands/tenhal_plan.py create mode 100644 scripts/set_plans.py diff --git a/inventory/management/commands/setplan.py b/inventory/management/commands/setplan.py new file mode 100644 index 00000000..9b6cb860 --- /dev/null +++ b/inventory/management/commands/setplan.py @@ -0,0 +1,124 @@ +# management/commands/create_plans.py +from django.core.management.base import BaseCommand +from plans.models import Plan, Quota, PlanQuota, Pricing, PlanPricing +from decimal import Decimal +from django.db.models import Q + +class Command(BaseCommand): + 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' + ) + + def handle(self, *args, **options): + if options['reset']: + self.stdout.write(self.style.WARNING('Resetting existing plans data...')) + Plan.objects.all().delete() + Quota.objects.filter( + Q(codename='basic') | + Q(codename='pro') | + Q(codename='premium') + ).delete() + + # Ensure no existing plans are marked as default + + Plan.objects.all().delete() + Quota.objects.all().delete() + Pricing.objects.all().delete() + + # Create core quotas + basic_quota, _ = Quota.objects.update_or_create( + codename='basic', + defaults={ + 'name': 'Basic Features', + 'description': 'Essential platform access', + 'is_boolean': True + } + ) + + pro_quota, _ = Quota.objects.update_or_create( + codename='pro', + defaults={ + 'name': 'Pro Features', + 'description': 'Advanced functionality', + 'is_boolean': True + } + ) + + premium_quota, _ = Quota.objects.update_or_create( + codename='premium', + defaults={ + 'name': 'Premium Features', + 'description': 'Full platform access', + 'is_boolean': True + } + ) + + # Create pricing period + monthly_pricing, _ = Pricing.objects.update_or_create( + name='Monthly', + defaults={'period': 30} + ) + + # Define plan structure + plans = [ + { + 'name': 'Basic', + 'description': 'Entry-level plan', + 'price': Decimal('0.00'), + 'period': None, + 'quotas': [basic_quota], + 'default': True + }, + { + 'name': 'Pro', + 'description': 'Professional plan', + 'price': Decimal('29.00'), + 'period': 30, + 'quotas': [basic_quota, pro_quota], + 'default': False + }, + { + 'name': 'Premium', + 'description': 'Full access plan', + 'price': Decimal('99.00'), + 'period': 30, + 'quotas': [basic_quota, pro_quota, premium_quota], + 'default': None + } + ] + + # Create plans and associations + for plan_data in plans: + plan, created = Plan.objects.update_or_create( + name=plan_data['name'], + defaults={ + 'description': plan_data['description'], + 'default': plan_data.get('default', False), + 'available': True, + 'visible': True + } + ) + + # Set quotas + plan.quotas.set(plan_data['quotas']) + + # Create pricing if applicable + if plan_data['price'] > 0: + PlanPricing.objects.update_or_create( + plan=plan, + pricing=monthly_pricing, + defaults={ + 'price': plan_data['price'], + 'visible': True + } + ) + + status = 'Created' if created else 'Updated' + self.stdout.write(self.style.SUCCESS(f'{status} {plan.name} plan')) + + self.stdout.write(self.style.SUCCESS('Successfully created plans structure')) \ No newline at end of file diff --git a/inventory/management/commands/tenhal_plan.py b/inventory/management/commands/tenhal_plan.py new file mode 100644 index 00000000..e28c3139 --- /dev/null +++ b/inventory/management/commands/tenhal_plan.py @@ -0,0 +1,47 @@ +# management/commands/create_plans.py +from decimal import Decimal +from django.db.models import Q +from django.core.management.base import BaseCommand +from plans.models import Plan, Quota, PlanQuota, Pricing, PlanPricing + +class Command(BaseCommand): + 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' + ) + + def handle(self, *args, **options): + Plan.objects.all().delete() + Quota.objects.all().delete() + PlanQuota.objects.all().delete() + Pricing.objects.all().delete() + + three_users_quota = Quota.objects.create(name='3 users', codename='3 users', unit='number') + five_users_quota = Quota.objects.create(name='5 users', codename='5 users', unit='number') + ten_users_quota = Quota.objects.create(name='10 users', codename='10 users', unit='number') + + # 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) + enterprise_plan = Plan.objects.create(name='Enterprise', description='Enterprise plan', available=True, visible=True) + + # Assign quotas to plans + PlanQuota.objects.create(plan=basic_plan, quota=three_users_quota, value=3) + PlanQuota.objects.create(plan=pro_plan, quota=five_users_quota, value=5) + PlanQuota.objects.create(plan=enterprise_plan, quota=ten_users_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 = Pricing.objects.create(plan=basic_plan, name='Monthly', period=30) + pro_pricing = Pricing.objects.create(plan=pro_plan, name='Monthly', period=30) + enterprise_pricing = Pricing.objects.create(plan=enterprise_plan, name='Monthly', period=30) + + PlanPricing.objects.create(plan=basic_plan, pricing=basic_pricing, price=Decimal('9.99')) + PlanPricing.objects.create(plan=pro_plan, pricing=pro_pricing, price=Decimal('19.99')) + PlanPricing.objects.create(plan=enterprise_plan, pricing=enterprise_pricing, price=Decimal('29.99')) \ No newline at end of file diff --git a/inventory/models.py b/inventory/models.py index af152bce..ea1eb17e 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -24,6 +24,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from appointment.models import StaffMember from plans.quota import get_user_quota +# from plans.models import AbstractPlan # from simple_history.models import HistoricalRecords @@ -1963,4 +1964,13 @@ class DealerSettings(models.Model): additional_info = models.JSONField(default=dict,null=True,blank=True) def __str__(self): - return f"Settings for {self.dealer}" \ No newline at end of file + return f"Settings for {self.dealer}" + +# class customPlan(AbstractPlan): +# default = models.BooleanField( +# help_text=_('Both "Unknown" and "No" means that the plan is not default'), +# default=None, +# db_index=True, +# unique=False, +# null=True, +# ) \ No newline at end of file diff --git a/inventory/services.py b/inventory/services.py index b5f9c22c..ea9691b8 100644 --- a/inventory/services.py +++ b/inventory/services.py @@ -160,5 +160,5 @@ def elm(vin): "model": response["data"]["model"] if response["data"]["model"] else " ", "modelYear": response["data"]["modelYear"], } - print(data) + print([x for x in data.values()]) return data if all([x for x in data.values()]) else None diff --git a/inventory/urls.py b/inventory/urls.py index 5e626732..c994084e 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -87,7 +87,7 @@ urlpatterns = [ name="create_opportunity", ), path( - "customers//add-note/", + "customers//add-note/", views.add_note_to_customer, name="add_note_to_customer", ), diff --git a/inventory/views.py b/inventory/views.py index a6c8eb64..ceab2652 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -679,7 +679,6 @@ class AjaxHandlerView(LoginRequiredMixin, View): vin_no = vin_no.strip() vin_data = {} decoding_method = "" - # manufacturer_name = model_name = year_model = None if not (result := decodevin(vin_no)): return JsonResponse( @@ -1940,7 +1939,6 @@ class CustomerDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView context["customer_notes"] = models.Notes.objects.filter( object_id=self.object.pk ) - estimates = entity.get_estimates().filter(customer=self.object) invoices = entity.get_invoices().filter(customer=self.object) # txs = entity. transactions(customer=self.object) diff --git a/scripts/set_plans.py b/scripts/set_plans.py new file mode 100644 index 00000000..8a3bc95d --- /dev/null +++ b/scripts/set_plans.py @@ -0,0 +1,63 @@ +from plans.models import Plan, Quota +from decimal import Decimal + +def run(): + # Create quotas first + basic_quota = Quota.objects.create( + codename='basic_quota', + name='Basic Features', + description='Basic plan features', + is_boolean=True, + url='pricing' + ) + + pro_quota = Quota.objects.create( + codename='pro_quota', + name='Pro Features', + description='Pro plan features', + is_boolean=True, + url='pricing' + ) + + premium_quota = Quota.objects.create( + codename='premium_quota', + name='Premium Features', + description='Premium plan features', + is_boolean=True, + url='pricing' + ) + + # Create the plans + basic_plan = Plan.objects.create( + name="Basic", + description="Basic plan with limited features", + price=Decimal("49.00"), # 49 SAR + period=30, # 30 days + default=True, + available=True, + visible=True, + order=1 + ) + basic_plan.quotas.add(basic_quota) + + pro_plan = Plan.objects.create( + name="Professional", + description="Professional plan with advanced features", + price=Decimal("149.00"), # 149 SAR + # period=30, + available=True, + visible=True, + # order=2 + ) + pro_plan.quotas.add(basic_quota, pro_quota) + + premium_plan = Plan.objects.create( + name="Premium", + description="Premium plan with all features", + price=Decimal("299.00"), # 299 SAR + period=30, + available=True, + visible=True, + order=3 + ) + premium_plan.quotas.add(basic_quota, pro_quota, premium_quota) \ No newline at end of file diff --git a/templates/customers/view_customer.html b/templates/customers/view_customer.html index f7bb21db..a86c133d 100644 --- a/templates/customers/view_customer.html +++ b/templates/customers/view_customer.html @@ -88,16 +88,17 @@ - + + - {% for note in notes %} - - - - - - {% endfor %} + + {% for note in customer_notes %} + + + + + {% endfor %} +
- {{ _("Notes")|upper }}{{ _("Note") }}{{ _("Date") }}
{{note.note}}{{ note.created }}
{{note.note}}{{ note.created }}