fix the customer note
This commit is contained in:
parent
d94c5adef7
commit
53c4f491ab
124
inventory/management/commands/setplan.py
Normal file
124
inventory/management/commands/setplan.py
Normal file
@ -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'))
|
||||||
47
inventory/management/commands/tenhal_plan.py
Normal file
47
inventory/management/commands/tenhal_plan.py
Normal file
@ -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'))
|
||||||
@ -24,6 +24,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from appointment.models import StaffMember
|
from appointment.models import StaffMember
|
||||||
from plans.quota import get_user_quota
|
from plans.quota import get_user_quota
|
||||||
|
# from plans.models import AbstractPlan
|
||||||
# from simple_history.models import HistoricalRecords
|
# from simple_history.models import HistoricalRecords
|
||||||
|
|
||||||
|
|
||||||
@ -1964,3 +1965,12 @@ class DealerSettings(models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Settings for {self.dealer}"
|
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,
|
||||||
|
# )
|
||||||
@ -160,5 +160,5 @@ def elm(vin):
|
|||||||
"model": response["data"]["model"] if response["data"]["model"] else " ",
|
"model": response["data"]["model"] if response["data"]["model"] else " ",
|
||||||
"modelYear": response["data"]["modelYear"],
|
"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
|
return data if all([x for x in data.values()]) else None
|
||||||
|
|||||||
@ -87,7 +87,7 @@ urlpatterns = [
|
|||||||
name="create_opportunity",
|
name="create_opportunity",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"customers/<uuid:customer_id>/add-note/",
|
"customers/<uuid:pk>/add-note/",
|
||||||
views.add_note_to_customer,
|
views.add_note_to_customer,
|
||||||
name="add_note_to_customer",
|
name="add_note_to_customer",
|
||||||
),
|
),
|
||||||
|
|||||||
@ -679,7 +679,6 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
|||||||
vin_no = vin_no.strip()
|
vin_no = vin_no.strip()
|
||||||
vin_data = {}
|
vin_data = {}
|
||||||
decoding_method = ""
|
decoding_method = ""
|
||||||
|
|
||||||
# manufacturer_name = model_name = year_model = None
|
# manufacturer_name = model_name = year_model = None
|
||||||
if not (result := decodevin(vin_no)):
|
if not (result := decodevin(vin_no)):
|
||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
@ -1940,7 +1939,6 @@ class CustomerDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
|
|||||||
context["customer_notes"] = models.Notes.objects.filter(
|
context["customer_notes"] = models.Notes.objects.filter(
|
||||||
object_id=self.object.pk
|
object_id=self.object.pk
|
||||||
)
|
)
|
||||||
|
|
||||||
estimates = entity.get_estimates().filter(customer=self.object)
|
estimates = entity.get_estimates().filter(customer=self.object)
|
||||||
invoices = entity.get_invoices().filter(customer=self.object)
|
invoices = entity.get_invoices().filter(customer=self.object)
|
||||||
# txs = entity. transactions(customer=self.object)
|
# txs = entity. transactions(customer=self.object)
|
||||||
|
|||||||
63
scripts/set_plans.py
Normal file
63
scripts/set_plans.py
Normal file
@ -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)
|
||||||
@ -88,16 +88,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<table class="table fs-9 mb-0 table-responsive">
|
<table class="table fs-9 mb-0 table-responsive">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="align-middle pe-6 text-start" scope="col">
|
<th class="align-middle pe-6 text-start" scope="col">{{ _("Note") }}</th>
|
||||||
{{ _("Notes")|upper }}</th>
|
<th class="align-middle pe-6 text-start" scope="col">{{ _("Date") }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for note in notes %}
|
<tbody>
|
||||||
|
{% for note in customer_notes %}
|
||||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||||
<td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{note.note}}</td>
|
<td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{note.note}}</td>
|
||||||
<td class="align-middle text-body-tertiary text-start white-space-nowrap">{{ note.created }}</td>
|
<td class="align-middle text-body-tertiary text-start white-space-nowrap">{{ note.created }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user