diff --git a/db.sqlite b/db.sqlite index 9f28510e..0031e560 100644 Binary files a/db.sqlite and b/db.sqlite differ diff --git a/inventory/__pycache__/forms.cpython-311.pyc b/inventory/__pycache__/forms.cpython-311.pyc index 90bf1621..6d223734 100644 Binary files a/inventory/__pycache__/forms.cpython-311.pyc and b/inventory/__pycache__/forms.cpython-311.pyc differ diff --git a/inventory/__pycache__/models.cpython-311.pyc b/inventory/__pycache__/models.cpython-311.pyc index c2489e52..b3f36000 100644 Binary files a/inventory/__pycache__/models.cpython-311.pyc and b/inventory/__pycache__/models.cpython-311.pyc differ diff --git a/inventory/__pycache__/urls.cpython-311.pyc b/inventory/__pycache__/urls.cpython-311.pyc index 8cb69e8c..58331ee1 100644 Binary files a/inventory/__pycache__/urls.cpython-311.pyc and b/inventory/__pycache__/urls.cpython-311.pyc differ diff --git a/inventory/__pycache__/views.cpython-311.pyc b/inventory/__pycache__/views.cpython-311.pyc index 2a1e7928..dd07f4ec 100644 Binary files a/inventory/__pycache__/views.cpython-311.pyc and b/inventory/__pycache__/views.cpython-311.pyc differ diff --git a/inventory/forms.py b/inventory/forms.py index 592dbe81..519154fc 100644 --- a/inventory/forms.py +++ b/inventory/forms.py @@ -24,7 +24,7 @@ from .models import ( SaleQuotationCar, AdditionalServices, Staff, - Opportunity + Opportunity, DealStatus, Priority, DealSource ) from django_ledger.models import ItemModel @@ -445,7 +445,7 @@ class OpportunityForm(forms.ModelForm): 'priority', 'source' ] widgets = { - 'deal_status': forms.Select(choices=Opportunity.DEAL_STATUS_CHOICES), - 'priority': forms.Select(choices=Opportunity.PRIORITY_CHOICES), - 'source': forms.Select(choices=Opportunity.DEAL_SOURCES_CHOICES), - } \ No newline at end of file + 'deal_status': forms.Select(choices=DealStatus.choices), + 'priority': forms.Select(choices=Priority.choices), + 'source': forms.Select(choices=DealSource.choices), + } diff --git a/inventory/migrations/0019_alter_opportunity_deal_status_and_more.py b/inventory/migrations/0019_alter_opportunity_deal_status_and_more.py new file mode 100644 index 00000000..e6e8c676 --- /dev/null +++ b/inventory/migrations/0019_alter_opportunity_deal_status_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.1.4 on 2024-12-31 14:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0018_remove_notification_staff_notification_user'), + ] + + operations = [ + migrations.AlterField( + model_name='opportunity', + name='deal_status', + field=models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('canceled', 'Canceled'), ('completed', 'Completed')], default='new', max_length=50, verbose_name='Deal Status'), + ), + migrations.AlterField( + model_name='opportunity', + name='priority', + field=models.CharField(choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High')], default='low', max_length=50, verbose_name='Priority'), + ), + migrations.AlterField( + model_name='opportunity', + name='source', + field=models.CharField(choices=[('referrals', 'Referrals'), ('walk_in', 'Walk In'), ('toll_free', 'Toll Free'), ('whatsapp', 'Whatsapp'), ('showrooms', 'Showrooms'), ('website', 'Website'), ('other', 'Other')], default='showrooms', max_length=255, verbose_name='Source'), + ), + ] diff --git a/inventory/migrations/0020_notes.py b/inventory/migrations/0020_notes.py new file mode 100644 index 00000000..a36509c5 --- /dev/null +++ b/inventory/migrations/0020_notes.py @@ -0,0 +1,31 @@ +# Generated by Django 5.1.4 on 2024-12-31 15:13 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0019_alter_opportunity_deal_status_and_more'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Notes', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('note', models.TextField(verbose_name='Note')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')), + ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='notes_created', to=settings.AUTH_USER_MODEL)), + ('opportunity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='inventory.opportunity')), + ], + options={ + 'verbose_name': 'Notes', + 'verbose_name_plural': 'Notes', + }, + ), + ] diff --git a/inventory/migrations/0021_log.py b/inventory/migrations/0021_log.py new file mode 100644 index 00000000..35ceefcf --- /dev/null +++ b/inventory/migrations/0021_log.py @@ -0,0 +1,34 @@ +# Generated by Django 5.1.4 on 2024-12-31 15:48 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0020_notes'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Log', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('action', models.CharField(choices=[('create', 'Create'), ('update', 'Update'), ('delete', 'Delete'), ('status_change', 'Status Change')], max_length=50, verbose_name='Action')), + ('old_status', models.CharField(blank=True, choices=[('new', 'New'), ('pending', 'Pending'), ('canceled', 'Canceled'), ('completed', 'Completed')], max_length=50, null=True, verbose_name='Old Status')), + ('new_status', models.CharField(blank=True, choices=[('new', 'New'), ('pending', 'Pending'), ('canceled', 'Canceled'), ('completed', 'Completed')], max_length=50, null=True, verbose_name='New Status')), + ('details', models.TextField(blank=True, null=True, verbose_name='Details')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('opportunity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='logs', to='inventory.opportunity')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='User')), + ], + options={ + 'verbose_name': 'Log', + 'verbose_name_plural': 'Logs', + 'ordering': ['-created_at'], + }, + ), + ] diff --git a/inventory/migrations/0022_rename_log_oportunitylog.py b/inventory/migrations/0022_rename_log_oportunitylog.py new file mode 100644 index 00000000..f7390cd9 --- /dev/null +++ b/inventory/migrations/0022_rename_log_oportunitylog.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.4 on 2024-12-31 15:49 + +from django.conf import settings +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0021_log'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.RenameModel( + old_name='Log', + new_name='OportunityLog', + ), + ] diff --git a/inventory/models.py b/inventory/models.py index 218bfa74..26b8c6d9 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -167,13 +167,6 @@ class CarStockTypeChoices(models.TextChoices): USED = "used", _("Used") -class DEALER_TYPES(models.TextChoices): - OWNER = "Owner", _("Owner") - INVENTORY = "Inventory", _("Inventory") - ACCOUNTANT = "Accountent", _("Accountent") - SALES = "sales", _("Sales") - - class AdditionalServices(models.Model, LocalizedNameMixin): name = models.CharField(max_length=255, verbose_name=_("Name")) arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name")) @@ -633,8 +626,6 @@ class Staff(models.Model, LocalizedNameMixin): return f"{self.name} - {self.dealer}" - - # Vendor Model class Vendor(models.Model, LocalizedNameMixin): dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name="vendors") @@ -701,36 +692,37 @@ class Customer(models.Model): return f"{self.first_name} {self.middle_name} {self.last_name}" -class Opportunity(models.Model): - DEAL_STATUS_CHOICES = [ - ('new', _('New')), - ('in_progress', _('In Progress')), - ('pending', _('Pending')), - ('canceled', _('Canceled')), - ('completed', _('Completed')), - ] - PRIORITY_CHOICES = [ - ('low', _('Low')), - ('medium', _('Medium')), - ('high', _('High')), - ('urgent', _('Urgent')), - ] - DEAL_SOURCES_CHOICES = [ - ('referrals', _('Referrals')), - ('walk_in', _('Walk In')), - ('toll_free', _('Toll Free')), - ('whatsapp', _('Whatsapp')), - ('showroom', _('Showroom')), - ('website', _('Website')), - ] +class DealStatus(models.TextChoices): + NEW = "new", _("New") + PENDING = "pending", _("Pending") + CANCELED = "canceled", _("Canceled") + COMPLETED = "completed", _("Completed") + +class Priority(models.TextChoices): + LOW = "low", _("Low") + MEDIUM = "medium", _("Medium") + HIGH = "high", _("High") + + +class DealSource(models.TextChoices): + REFERRALS = "referrals", _("Referrals") + WALK_IN = "walk_in", _("Walk In") + TOLL_FREE = "toll_free", _("Toll Free") + WHATSAPP = "whatsapp", _("Whatsapp") + SHOWROOMS = "showrooms", _("Showrooms") + WEBSITE = "website", _("Website") + OTHER = "other", _("Other") + + +class Opportunity(models.Model): customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="opportunities") car = models.ForeignKey(Car, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_("Car")) deal_name = models.CharField(max_length=255, verbose_name=_("Deal Name")) deal_value = models.DecimalField(max_digits=10, decimal_places=2, verbose_name=_("Deal Value")) - deal_status = models.CharField(max_length=50, choices=DEAL_STATUS_CHOICES, default='new', verbose_name=_("Deal Status")) - priority = models.CharField(max_length=50, choices=PRIORITY_CHOICES, default='low', verbose_name=_("Priority")) - source = models.CharField(max_length=255, choices=DEAL_SOURCES_CHOICES, default='showroom', verbose_name=_("Source")) + deal_status = models.CharField(max_length=50, choices=DealStatus.choices, default=DealStatus.NEW, verbose_name=_("Deal Status")) + priority = models.CharField(max_length=50, choices=Priority.choices, default=Priority.LOW, verbose_name=_("Priority")) + source = models.CharField(max_length=255, choices=DealSource.choices, default=DealSource.SHOWROOMS, verbose_name=_("Source")) created_by = models.ForeignKey(Staff, on_delete=models.SET_NULL, null=True, related_name="deals_created") created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At")) updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At")) @@ -743,6 +735,42 @@ class Opportunity(models.Model): return f"{self.deal_name} - {self.customer.get_full_name}" +class Notes(models.Model): + opportunity = models.ForeignKey(Opportunity, on_delete=models.CASCADE, related_name="notes") + note = models.TextField(verbose_name=_("Note")) + created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name="notes_created") + created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At")) + updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At")) + class Meta: + verbose_name = _("Notes") + verbose_name_plural = _("Notes") + + +class ActionChoices(models.TextChoices): + CREATE = "create", _("Create") + UPDATE = "update", _("Update") + DELETE = "delete", _("Delete") + STATUS_CHANGE = "status_change", _("Status Change") + + +class OportunityLog(models.Model): + opportunity = models.ForeignKey(Opportunity, on_delete=models.CASCADE, related_name="logs") + action = models.CharField(max_length=50, choices=ActionChoices.choices, verbose_name=_("Action")) + user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name=_("User")) + old_status = models.CharField(max_length=50, choices=DealStatus.choices, null=True, blank=True, verbose_name=_("Old Status")) + new_status = models.CharField(max_length=50, choices=DealStatus.choices, null=True, blank=True, verbose_name=_("New Status")) + details = models.TextField(blank=True, null=True, verbose_name=_("Details")) + created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At")) + + class Meta: + verbose_name = _("Log") + verbose_name_plural = _("Logs") + ordering = ['-created_at'] + + def __str__(self): + return f"{self.get_action_display()} by {self.user} on {self.opportunity.deal_name}" + + class Notification(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="notifications") message = models.CharField(max_length=255, verbose_name=_("Message")) diff --git a/inventory/urls.py b/inventory/urls.py index 1fd494d7..b354a112 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -47,7 +47,7 @@ urlpatterns = [ path('opportunities//', views.OpportunityDetailView.as_view(), name='opportunity_detail'), path('opportunities//edit/', views.OpportunityUpdateView.as_view(), name='update_opportunity'), path('opportunities/', views.OpportunityListView.as_view(), name='opportunity_list'), - path('opportunities//delete/', views.OpportunityDeleteView.as_view(), name='delete_opportunity'), + path('opportunities//delete/', views.delete_opportunity, name='delete_opportunity'), path('notifications/', views.NotificationListView.as_view(), name='notifications_history'), path('notifications//mark_as_read/', views.mark_notification_as_read, name='mark_notification_as_read'), diff --git a/inventory/views.py b/inventory/views.py index 331d2713..3664ac0b 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -1935,10 +1935,12 @@ class OpportunityListView(ListView): context_object_name = 'opportunities' -class OpportunityDeleteView(DeleteView): - model = models.Opportunity - template_name = 'crm/opportunity_confirm_delete.html' - success_url = reverse_lazy('opportunity_list') +@login_required +def delete_opportunity(request, pk): + opportunity = get_object_or_404(models.Opportunity, pk=pk) + opportunity.delete() + messages.success(request, _("Opportunity deleted successfully.")) + return redirect("opportunity_list") def notifications_view(request): diff --git a/templates/crm/opportunity_detail.html b/templates/crm/opportunity_detail.html index 70d85623..42f16529 100644 --- a/templates/crm/opportunity_detail.html +++ b/templates/crm/opportunity_detail.html @@ -1,3 +1,1430 @@ +{% extends 'base.html' %} +{% load i18n static %} + + +{% block content %} + +
+
+
+
+

Deal details

+
+
+ + + +
+
+
+
+
+
+
+
+
+

Start-Up Growth Suite

+
+
USD $12,000.00
+
Financial
+
+
+
+
+
+
Ansolo Lazinatov
+ +
+
+
SuccessLostClose
+
+
+
+
+
+

New

+
Dec 15, 05:00AM
+
+
+
+
+
+
+
+

Others Information

+
+
+
+
+
Category
Add new category +
+ +
+
+
Priority
+ +
+
+
Stage
+ +
+
+
+
Lead Source
Add new +
+ +
+
+
+
Campaign Source
Add new +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Deal Amount

+

$12,000.00

+
+
+
+
+
+
+
+

Deal Code

+

PHO1234

+
+
+
+
+
+
+
+

Deal Type

+

New Business

+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + +
+
+
+

Probability (%)

+
+
: +

12.5

+
+
+
+

Revenue

+
+
: +

$1,500.00

+
+
+
+ + + + + + + + + + + + + + + + +
+
+
+

Phone

+
+
:+11 123 456 789
+
+
+

Email

+
+
:jacksonpol@email.com
+
+
+ + + + + + + + + + + + + + + + +
+
+
+

Contact Name

+
+
: +
Jackson Pollock
+
+
+
+

Modified By

+
+
: +
Ansolo Lazinatov
+
+
+
+ + + + + + + + + + + + + + + + +
+
+
+

Create Date

+
+
: +
Nov 30, 2022
+
+
+
+

Closing Date

+
+
: +
Dec 15, 2022
+
+
+
+
+ +
+
+

Activity

+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
Assigned as a director for Project The Chewing Gum Attack
+

byJackson Pollock

+
+
22 September, 2022, 4:33 PM
+
+

Utilizing best practices to better leverage our assets, we must engage in black sky leadership thinking, not the usual band-aid solution.

+
+
+
+
+
+
+
+
+
+
Onboarding Meeting
+

byJackson Pollock

+
+
20 September, 2022, 5:31pm
+
+
+
+
+
+
+
+
+
+
+
Designing the dungeon
+

byJackson Pollock

+
+
19 September, 2022, 4:39pm
+
+

To get off the runway and paradigm shift, we should take brass tacks with above-the-board actionable analytics, ramp up with viral partnering, not the usual goat rodeo putting socks on an octopus.

+
+
+
+
+
+
+
+
+
+
Purchasing-Related Vendors
+

byAnsolo Lazinatov

+
+
22 September, 2022, 4:30pm
+
+
+
+
+
+
+
+
+
+
+
Quary about purchased soccer socks
+

byAnsolo Lazinatov

+
+
15 September, 2022, 3:33pm
+
+

I’ve come across your posts and found some favorable deals on your page. I’ve added a load of products to the cart and I don’t know the payment options you avail. Also, can you enlighten me about any discount.

+
+
+
+
+
+
+
+
+
+
Added image
+

byAnsolo Lazinatov

+
+
11 September, 2022, 12:15am
+
+
+
+
+
+
+

Notes

+ +
+
+
+

Gave us a nice feedback

+
+
clock 12 Nov, 2018
+

byAnsolo Lazinatov

+
+
+
+

I also want to let you know that I am available to you as your real estate insider from now on. If you have any questions about the market, even if they sound silly, call or text anytime.

+
+
30 Jan, 2019
+

byAnsolo Lazinatov

+
+
+
+

To get off the runway and paradigm shift, we should take brass tacks with above-the-board actionable analytics, ramp up with viral partnering, not the usual goat rodeo putting socks on an octopus.

+
+
19 September, 2022, 4:39pm
+

byJackson Pollock

+
+
+
+

Utilizing best practices to better leverage our assets, we must engage in black sky leadership thinking, not the usual band-aid solution.

+
+
22 September, 2022, 4:30pm
+

byAnsolo Lazinatov

+
+
+
+
+
+
+

Meeting

+
+
+ +
+
+

23 tasks

+ +
+
+ +
+
+
+
+
+
+
+
+

Onboarding Meeting

+
5:30 pm to 7:00pm - 1h 30min
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+1
+
+
+
+
today +
Urgent
+ +
+
+
+
+
+
+
+
+
+

Agile Mindset Meetup

+
4:30 pm to 6:00pm - 1h 30min
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+1
+
+
+
+
tomorrow +
Medium
+ +
+
+
+
+
+
+
+
+
+

Meeting Fundamentals

+
6:00 pm to 7:20pm - 1h 20min
+
+
+
+
R
+
+
+ + +
+
+ + +
+
+ + +
+
+
+2
+
+
+
+
tomorrow +
High
+ +
+
+
+
+
+
+
+
+
+

Design System Meeting

+
7:30 pm to 8:45pm - 1h 45min
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+4
+
+
+
+
tomorrow +
Low
+ +
+
+
+
+
+
+
+

Tasks

+
+
+ +
+
+

23 tasks

+ +
+
+
+
+
+
+ + +
+
+
+
+
+

19 Nov, 2022

+
+
+ + +
+
+
+

11:56 PM

+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+

05 Nov, 2022

+
+
+ + +
+
+
+

09:30 PM

+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+

02 Nov, 2022

+
+
+ + +
+
+
+

05:25 AM

+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+

29 Oct, 2022

+
+
+ + +
+
+
+

08:21 PM

+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+

21 Oct, 2022

+
+
+ + +
+
+
+

03:45 PM

+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+

14 Oct, 2022

+
+
+ + +
+
+
+

10:00 PM

+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+

12 Oct, 2022

+
+
+ + +
+
+
+

02:00 AM

+
+
+
+
Add new task +
+
+
+
+

Call

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
Namedescriptioncreate datecreate byLast Activity
+
+ +
+
+
+
+
Ansolo Lazinatov
+
Purchasing-Related VendorsDec 29, 2021Ansolo Lazinarov +
Active
+
+
+ + +
+
+
+ +
+
+
+
+
Jackson Pollock
+
Based on emails sent rate, the top 10 usersMar 27, 2021Jackson Pollock +
6 hours ago
+
+
+ + +
+
+
+ +
+
+
+
+
Ansolo Lazinatov
+
Based on the percentage of recipientsJun 24, 2021Ansolo Lazinarov +
Active
+
+
+ + +
+
+
+ +
+
+
+
+
Jackson Pollock
+
Obtaining leads todayMay 19, 2024Jackson Pollock +
6 hours ago
+
+
+ + +
+
+
+ +
+
+
+
+
Ansolo Lazinatov
+
Sums up the many phases of new and existing businesses.Aug 19, 2024Ansolo Lazinarov +
Active
+
+
+ + +
+
+
+ +
+
+
+
+
Ansolo Lazinatov
+
Purchasing-Related VendorsAug 19, 2024Ansolo Lazinarov +
Active
+
+
+ + +
+
+
+
+ +
+ +
    + +
    +
    +
    +
    +
    +

    Emails

    +
    + + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    SubjectSent byDateActionStatus
    +
    + +
    +
    Quary about purchased soccer socks +
    jackson@mail.com
    +
    Jackson PollockDec 29, 2021 10:23 amCallsent
    +
    + +
    +
    How to take the headache out of Order +
    ansolo45@mail.com
    +
    Ansolo LazinatovDec 27, 2021 3:27 pmCalldelivered
    +
    + +
    +
    The Arnold Schwarzenegger of Order +
    ansolo45@mail.com
    +
    Ansolo LazinatovDec 24, 2021 10:44 amCallBounce
    +
    + +
    +
    My order is not being taken +
    jackson@mail.com
    +
    Jackson PollockDec 19, 2021 4:55 pmCallSpam
    +
    + +
    +
    Shipment is missing +
    jackson@mail.com
    +
    Jackson PollockDec 19, 2021 2:43 pmCallsent
    +
    + +
    +
    How can I order something urgently? +
    ansolo45@mail.com
    +
    Jackson PollockDec 19, 2021 2:43 pmCallDelivered
    +
    + +
    +
    How the delicacy of the products will be handled? +
    ansolo45@mail.com
    +
    Ansolo LazinatovDec 16, 2021 5:18 pmCallbounced
    +
    +
    + +
    + +
      + +
      +
      +
      +
      +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + +
      +
      SubjectSent byDateActionStatus
      +
      + +
      +
      Quary about purchased soccer socks +
      jackson@mail.com
      +
      Jackson PollockDec 29, 2021 10:23 amCallsent
      +
      + +
      +
      How to take the headache out of Order +
      ansolo45@mail.com
      +
      Ansolo LazinatovDec 27, 2021 3:27 pmCalldelivered
      +
      + +
      +
      The Arnold Schwarzenegger of Order +
      ansolo45@mail.com
      +
      Ansolo LazinatovDec 24, 2021 10:44 amCallBounce
      +
      + +
      +
      My order is not being taken +
      jackson@mail.com
      +
      Jackson PollockDec 19, 2021 4:55 pmCallSpam
      +
      + +
      +
      Shipment is missing +
      jackson@mail.com
      +
      Jackson PollockDec 19, 2021 2:43 pmCallsent
      +
      +
      + +
      + +
        + +
        +
        +
        +
        +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        + +
        +
        SubjectSent byDateActionStatus
        +
        + +
        +
        Quary about purchased soccer socks +
        jackson@mail.com
        +
        Jackson PollockDec 29, 2021 10:23 amCallsent
        +
        + +
        +
        How to take the headache out of Order +
        ansolo45@mail.com
        +
        Ansolo LazinatovDec 27, 2021 3:27 pmCalldelivered
        +
        + +
        +
        The Arnold Schwarzenegger of Order +
        ansolo45@mail.com
        +
        Ansolo LazinatovDec 24, 2021 10:44 amCallBounce
        +
        + +
        +
        My order is not being taken +
        jackson@mail.com
        +
        Jackson PollockDec 19, 2021 4:55 pmCallSpam
        +
        +
        + +
        + +
          + +
          +
          +
          +
          +
          +
          +
          +
          +

          Attachments

          +
          +
          +
          +

          Silly_sight_1.png

          +
          + +
          +

          768kB| Shantinan Mekalan | 21st Dec, 12:56 PM

          +
          +
          +
          +
          +
          +

          All_images.zip

          +
          +

          12.8 mB|Yves Tanguy | 19th Dec, 08:56 PM

          +
          + +
          +
          +
          +
          +
          +
          +

          Project.txt

          +
          +

          123 kB| Shantinan Mekalan | 12th Dec, 12:56 PM

          +
          + +
          +
          +
          +
          +
          +
          +

          {{ opportunity.deal_name }}

          Customer: {{ opportunity.customer.get_full_name }}

          Car: {{ opportunity.car }}

          @@ -8,4 +1435,6 @@

          Created By: {{ opportunity.created_by.name }}

          Created At: {{ opportunity.created_at }}

          Updated At: {{ opportunity.updated_at }}

          -Edit \ No newline at end of file +Edit +
          +{% endblock %} \ No newline at end of file diff --git a/templates/crm/opportunity_list.html b/templates/crm/opportunity_list.html index 9495956d..c205e602 100644 --- a/templates/crm/opportunity_list.html +++ b/templates/crm/opportunity_list.html @@ -1,50 +1,504 @@ -{% extends 'base.html' %} +{% extends 'base.html' %} +{% load i18n static %} {% block content %} -

          Opportunities

          -Create New Opportunity +
          + +
          +
          +
          +

          {{ _("Opportunities") }}

          +
          +
          + +
          +
          +
          +
          +
          + {% for opportunity in opportunities %} +
          +
          +
          +
          +

          {{ _("Revenue") }}:

          +

          {{ opportunity.car.finances.total }}

          +
          +
          + + + +
          +
          +
          +
          +
          +
          +
          +
          +
          +

          {{ opportunity.created_at|date }} . {{ opportunity.created_at|time }}

          +
          +
          +
          {{ opportunity.deal_name }} +

          {{ opportunity.get_source_display }}

          +

          {{ opportunity.car.finances.total }}

          +
          +
          +
          +

          {{ opportunity.customer.get_full_name }}

          +
          +
          +

          {{ opportunity.created_by.name }}

          +
          +
          +
          +
          {{ opportunity.get_deal_status_display }}{{ opportunity.get_priority_display }}
          + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          +

          {{ _("Expected Revenue")}}

          +
          +
          : +

          {{ opportunity.car.finances.total }}

          +
          +
          +

          {{ _("Name") }}

          +
          +
          : +

          {{ opportunity.customer.first_name }}

          +
          +
          +

          {{ _("Closing Date and Time")}}

          +
          +
          : +

          {{ opportunity.created_at }}

          +
          +
          +

          Assigned Agent

          +
          +
          : + +
          +

          {{ _("Probability") }}:

          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          + + +{% endfor %} +
          +
          +
          +
          +
          +{% endblock %} + + - - - - - - - - - - - - - - - - - {% for opportunity in opportunities %} - - - - - - - - - - - - - {% empty %} - - - - {% endfor %} - -
          Deal NameCustomerCarDeal ValueDeal StatusPrioritySourceCreated ByCreated AtActions
          {{ opportunity.deal_name }}{{ opportunity.customer.get_full_name }}{{ opportunity.car }}{{ opportunity.deal_value }}{{ opportunity.get_deal_status_display }}{{ opportunity.get_priority_display }}{{ opportunity.get_source_display }}{{ opportunity.created_by.name }}{{ opportunity.created_at }} - View - Edit -
          - {% csrf_token %} - -
          -
          No opportunities found.
          -{% endblock %} \ No newline at end of file