diff --git a/inventory/models.py b/inventory/models.py
index c9bd3525..e22a31d2 100644
--- a/inventory/models.py
+++ b/inventory/models.py
@@ -38,6 +38,7 @@ from django_ledger.models import (
)
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
+from django.core.serializers.json import DjangoJSONEncoder
from appointment.models import StaffMember
from plans.quota import get_user_quota
from plans.models import UserPlan
@@ -2859,4 +2860,58 @@ class PoItemsUploaded(models.Model):
)
status = models.CharField(max_length=100, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
- updated_at = models.DateTimeField(auto_now=True)
\ No newline at end of file
+ updated_at = models.DateTimeField(auto_now=True)
+
+class ExtraInfo(models.Model):
+ """
+ Stores additional information for any model with:
+ - Multiple generic relationships
+ - JSON data storage
+ - Tracking fields
+ """
+ # Primary GenericForeignKey (main linked object)
+ content_type = models.ForeignKey(
+ ContentType,
+ on_delete=models.CASCADE,
+ related_name="extra_info_primary"
+ )
+ object_id = models.PositiveIntegerField()
+ content_object = GenericForeignKey('content_type', 'object_id')
+
+ # Secondary GenericForeignKey (optional additional link)
+ related_content_type = models.ForeignKey(
+ ContentType,
+ on_delete=models.SET_NULL,
+ null=True,
+ blank=True,
+ related_name="extra_info_secondary"
+ )
+ related_object_id = models.PositiveIntegerField(null=True, blank=True)
+ related_object = GenericForeignKey('related_content_type', 'related_object_id')
+
+ # JSON Data Storage
+ data = models.JSONField(
+ encoder=DjangoJSONEncoder,
+ default=dict,
+ blank=True
+ )
+
+ # Metadata
+ created_at = models.DateTimeField(auto_now_add=True)
+ updated_at = models.DateTimeField(auto_now=True)
+ created_by = models.ForeignKey(
+ User,
+ on_delete=models.SET_NULL,
+ null=True,
+ related_name="created_extra_info"
+ )
+
+ class Meta:
+ indexes = [
+ models.Index(fields=['content_type', 'object_id']),
+ models.Index(fields=['related_content_type', 'related_object_id']),
+ ]
+ verbose_name_plural = "Extra Info"
+
+ def __str__(self):
+ return f"ExtraInfo for {self.content_object} ({self.content_type})"
\ No newline at end of file
diff --git a/inventory/signals.py b/inventory/signals.py
index ac0da1a3..ef1eb3cf 100644
--- a/inventory/signals.py
+++ b/inventory/signals.py
@@ -15,7 +15,8 @@ from django_ledger.models import (
TransactionModel,
LedgerModel,
AccountModel,
- PurchaseOrderModel
+ PurchaseOrderModel,
+ EstimateModel
)
from . import models
from django.utils.timezone import now
@@ -977,23 +978,41 @@ def sale_order_created_notification(sender, instance, created, **kwargs):
@receiver(post_save, sender=models.Lead)
def lead_created_notification(sender, instance, created, **kwargs):
if created:
- models.Notification.objects.create(
- user=instance.staff.user,
- message=f"""
- New Lead has been added.
- View
- """,
- )
-@receiver(post_save, sender=models.Lead)
-def estimate__notification(sender, instance, created, **kwargs):
- if created:
- models.Notification.objects.create(
- user=instance.staff.user,
- message=f"""
- New Lead has been added.
- View
- """,
- )
+ if instance.staff:
+ models.Notification.objects.create(
+ user=instance.staff.user,
+ message=f"""
+ New Lead has been added.
+ View
+ """,
+ )
+@receiver(post_save, sender=EstimateModel)
+def estimate_in_review_notification(sender, instance, created, **kwargs):
+ if instance.is_review():
+ recipients = models.CustomGroup.objects.filter(dealer=instance.dealer,name="Manager").first().group.user_set.exclude(email=instance.dealer.user.email)
+ dealer = models.Dealer.objects.get(entity=instance.entity)
+ for recipient in recipients:
+ models.Notification.objects.create(
+ user=recipient,
+ message=f"""
+ Estimate {instance.estimate_number} is in review.
+ Please review and approve it at your earliest convenience.
+ View
+ """)
+
+@receiver(post_save, sender=EstimateModel)
+def estimate_in_approve_notification(sender, instance, created, **kwargs):
+ if instance.is_approved():
+ recipients = models.CustomGroup.objects.filter(dealer=instance.dealer,name="Manager").first().group.user_set.exclude(email=instance.dealer.user.email)
+ dealer = models.Dealer.objects.get(entity=instance.entity)
+ for recipient in recipients:
+ models.Notification.objects.create(
+ user=recipient,
+ message=f"""
+ Estimate {instance.estimate_number} is in review.
+ Please review and approve it at your earliest convenience.
+ View
+ """)
# @receiver(post_save, sender=models.Lead)
# def lead_created_notification(sender, instance, created, **kwargs):
diff --git a/inventory/views.py b/inventory/views.py
index c8abb885..a9f772f4 100644
--- a/inventory/views.py
+++ b/inventory/views.py
@@ -5531,10 +5531,11 @@ def lead_create(request,dealer_slug):
is_sa_import=True, pk__in=dealer_make_list
)
form.fields["staff"].queryset = form.fields["staff"].queryset.filter(
- dealer=dealer,staff_member__user__groups__name__contains="Sales")
+ dealer=dealer,staff_member__user__groups__permissions__codename__contains="add_lead")
# form.fields["staff"].queryset = form.fields["staff"].queryset.filter(
# dealer=dealer
# )
+ print(form.fields["staff"].queryset)
if hasattr(request.user.staffmember, "staff"):
form.initial["staff"] = request.user.staffmember.staff