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