From afa8edb9949a0f0258a18cf67db2056e54b41dc5 Mon Sep 17 00:00:00 2001 From: ismail Date: Wed, 2 Jul 2025 15:19:05 +0300 Subject: [PATCH 1/2] fix the group user count qs --- .gitignore | 2 +- inventory/models.py | 2 +- inventory/signals.py | 11 +++++++++++ inventory/views.py | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 195cc59e..450418e5 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,7 @@ Makefile .idea/**/dynamic.xml .idea/**/uiDesigner.xml .idea/**/dbnavigator.xml -**/migrations/ +**/migrations/** # Gradle .idea/**/gradle.xml diff --git a/inventory/models.py b/inventory/models.py index e8da8f43..c9bd3525 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -2518,7 +2518,7 @@ class CustomGroup(models.Model): @property def users(self): - return self.group.user_set.all() + return self.group.user_set.exclude(email=self.dealer.user.email).all() @property def permissions(self): diff --git a/inventory/signals.py b/inventory/signals.py index a2fd44e8..ac0da1a3 100644 --- a/inventory/signals.py +++ b/inventory/signals.py @@ -984,6 +984,17 @@ def lead_created_notification(sender, instance, created, **kwargs): 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 + """, + ) + # @receiver(post_save, sender=models.Lead) # def lead_created_notification(sender, instance, created, **kwargs): # if created: diff --git a/inventory/views.py b/inventory/views.py index 3275f7a5..c8abb885 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -2610,7 +2610,7 @@ class GroupListView(LoginRequiredMixin, ListView): template_name = "groups/group_list.html" def get_queryset(self): - dealer = get_user_type(self.request) + dealer = get_object_or_404(models.Dealer,slug=self.kwargs["dealer_slug"]) return dealer.groups.all() From bea6894f0a3de001fbc301387ed7db9bbbd70815 Mon Sep 17 00:00:00 2001 From: ismail Date: Wed, 2 Jul 2025 16:32:37 +0300 Subject: [PATCH 2/2] fix the lead assigned and lead tracking qs --- inventory/models.py | 57 +++++++++++++++++++++++++++++++++++++++++++- inventory/signals.py | 55 ++++++++++++++++++++++++++++-------------- inventory/views.py | 3 ++- 3 files changed, 95 insertions(+), 20 deletions(-) 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