diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..499c1f07 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "printWidth": 80, + "tabWidth": 4, + "useTabs": false, + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "bracketSpacing": true, + "arrowParens": "always" +} \ No newline at end of file diff --git a/inventory/forms.py b/inventory/forms.py index 8b5c12c8..2b36887c 100644 --- a/inventory/forms.py +++ b/inventory/forms.py @@ -50,7 +50,8 @@ from .models import ( CarMake, Customer, Organization, - DealerSettings + DealerSettings, + Tasks ) from django_ledger import models as ledger_models from django.forms import ( @@ -1120,6 +1121,7 @@ class ActivityForm(forms.ModelForm): associated with the form and the fields it comprises. :type Meta: type """ + activity_type = forms.ChoiceField(choices=[("call", "Call"), ("email", "Email"), ("meeting", "Meeting")]) class Meta: model = Activity fields = ["activity_type", "notes"] @@ -1140,9 +1142,34 @@ class OpportunityForm(forms.ModelForm): :ivar Meta.fields: List of fields from the model included in the form. :type Meta.fields: list """ + closing_date = forms.DateField( + label=_("Expected Closing Date"), + widget=forms.DateInput(attrs={"type": "date"}) + ) + + probability = forms.IntegerField( + label=_("Probability (%)"), + widget=forms.NumberInput(attrs={ + 'type': 'range', + 'min': '0', + 'max': '100', + 'step': '1', + 'class': 'form-range', + 'oninput': 'this.nextElementSibling.value = this.value' + }), + initial=50 # Default value + ) + class Meta: model = Opportunity - fields = ["customer", "car", "stage", "probability", "staff", "closing_date"] + fields = ["lead", "car", "stage", "probability", "expected_revenue", "closing_date"] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Add a visible number input to display the current value + self.fields['probability'].widget.attrs['class'] = 'd-none' # Hide the default input + if self.instance and self.instance.pk: + self.fields['probability'].initial = self.instance.probability class InvoiceModelCreateForm(InvoiceModelCreateFormBase): @@ -1684,3 +1711,33 @@ class PaymentPlanForm(forms.Form): self.fields['first_name'].initial = user.first_name self.fields['last_name'].initial = user.last_name self.fields['email'].initial = user.email + + +# class ActivityHistoryForm(forms.Form): +# activity_type = forms.ChoiceField( +# choices=[ +# ('note', 'Note'), +# ('call', 'Call'), +# ('email', 'Email'), +# ('meeting', 'Meeting'),], +# widget=forms.Select(attrs={ +# 'class': 'form-control', +# 'id': 'activity-type' +# }), +# label=_('Activity Type') +# ) +# description = forms.CharField( +# widget=forms.Textarea(attrs={ +# 'class': 'form-control', +# 'id': 'activity-description' +# }), +# label=_('Description') +# ) + +class StaffTaskForm(forms.ModelForm): + class Meta: + model = Tasks + fields = ['title','due_date' ,'description'] + widgets = { + 'due_date': forms.DateTimeInput(attrs={'type': 'date'}), + } \ No newline at end of file diff --git a/inventory/migrations/0018_remove_opportunity_closed_remove_opportunity_status_and_more.py b/inventory/migrations/0018_remove_opportunity_closed_remove_opportunity_status_and_more.py new file mode 100644 index 00000000..d0914faa --- /dev/null +++ b/inventory/migrations/0018_remove_opportunity_closed_remove_opportunity_status_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 5.1.7 on 2025-05-13 15:19 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('inventory', '0017_alter_activity_activity_type'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.RemoveField( + model_name='opportunity', + name='closed', + ), + migrations.RemoveField( + model_name='opportunity', + name='status', + ), + migrations.CreateModel( + name='Tasks', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('object_id', models.UUIDField()), + ('title', models.CharField(max_length=255, verbose_name='Title')), + ('description', models.TextField(blank=True, null=True, verbose_name='Description')), + ('due_date', models.DateField(verbose_name='Due Date')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), + ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), + ('assigned_to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='tasks_assigned', to=settings.AUTH_USER_MODEL)), + ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='tasks_created', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Task', + 'verbose_name_plural': 'Tasks', + }, + ), + ] diff --git a/inventory/migrations/0019_tasks_dealer.py b/inventory/migrations/0019_tasks_dealer.py new file mode 100644 index 00000000..3216f502 --- /dev/null +++ b/inventory/migrations/0019_tasks_dealer.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.7 on 2025-05-13 16:22 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0018_remove_opportunity_closed_remove_opportunity_status_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='tasks', + name='dealer', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to='inventory.dealer'), + preserve_default=False, + ), + ] diff --git a/inventory/migrations/0020_tasks_completed.py b/inventory/migrations/0020_tasks_completed.py new file mode 100644 index 00000000..430f05ae --- /dev/null +++ b/inventory/migrations/0020_tasks_completed.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.7 on 2025-05-13 16:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0019_tasks_dealer'), + ] + + operations = [ + migrations.AddField( + model_name='tasks', + name='completed', + field=models.BooleanField(default=False, verbose_name='Completed'), + ), + ] diff --git a/inventory/migrations/0021_alter_lead_status_alter_leadstatushistory_new_status_and_more.py b/inventory/migrations/0021_alter_lead_status_alter_leadstatushistory_new_status_and_more.py new file mode 100644 index 00000000..dd4ce570 --- /dev/null +++ b/inventory/migrations/0021_alter_lead_status_alter_leadstatushistory_new_status_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.1.7 on 2025-05-14 10:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0020_tasks_completed'), + ] + + operations = [ + migrations.AlterField( + model_name='lead', + name='status', + field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Follow-up'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed')], db_index=True, default='new', max_length=50, verbose_name='Status'), + ), + migrations.AlterField( + model_name='leadstatushistory', + name='new_status', + field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Follow-up'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed')], max_length=50, verbose_name='New Status'), + ), + migrations.AlterField( + model_name='leadstatushistory', + name='old_status', + field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Follow-up'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed')], max_length=50, verbose_name='Old Status'), + ), + ] diff --git a/inventory/migrations/0022_opportunity_expected_revenue.py b/inventory/migrations/0022_opportunity_expected_revenue.py new file mode 100644 index 00000000..28364144 --- /dev/null +++ b/inventory/migrations/0022_opportunity_expected_revenue.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.7 on 2025-05-14 10:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0021_alter_lead_status_alter_leadstatushistory_new_status_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='opportunity', + name='expected_revenue', + field=models.DecimalField(decimal_places=2, default=0, max_digits=10, verbose_name='Expected Revenue'), + preserve_default=False, + ), + ] diff --git a/inventory/migrations/0023_alter_opportunity_stage.py b/inventory/migrations/0023_alter_opportunity_stage.py new file mode 100644 index 00000000..7e64e011 --- /dev/null +++ b/inventory/migrations/0023_alter_opportunity_stage.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.7 on 2025-05-14 10:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0022_opportunity_expected_revenue'), + ] + + operations = [ + migrations.AlterField( + model_name='opportunity', + name='stage', + field=models.CharField(choices=[('discovery', 'Discovery'), ('proposal', 'Proposal'), ('negotiation', 'Negotiation'), ('closed_won', 'Closed Won'), ('closed_lost', 'Closed Lost')], max_length=20, verbose_name='Stage'), + ), + ] diff --git a/inventory/migrations/0024_alter_opportunity_customer.py b/inventory/migrations/0024_alter_opportunity_customer.py new file mode 100644 index 00000000..69c45cfb --- /dev/null +++ b/inventory/migrations/0024_alter_opportunity_customer.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.7 on 2025-05-14 10:59 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'), + ('inventory', '0023_alter_opportunity_stage'), + ] + + operations = [ + migrations.AlterField( + model_name='opportunity', + name='customer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='django_ledger.customermodel'), + ), + ] diff --git a/inventory/models.py b/inventory/models.py index 9ef68e2c..03f37493 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -973,9 +973,9 @@ class Channel(models.TextChoices): class Status(models.TextChoices): NEW = "new", _("New") - FOLLOW_UP = "follow_up", _("Needs Follow-up") - NEGOTIATION = "negotiation", _("Under Negotiation") - WON = "won", _("Converted") + FOLLOW_UP = "follow_up", _("Follow-up") + NEGOTIATION = "negotiation", _("Negotiation") + WON = "won", _("Won") LOST = "lost", _("Lost") CLOSED = "closed", _("Closed") @@ -1020,7 +1020,7 @@ class ActionChoices(models.TextChoices): class Stage(models.TextChoices): - PROSPECT = "prospect", _("Prospect") + DISCOVERY = "discovery", _("Discovery") PROPOSAL = "proposal", _("Proposal") NEGOTIATION = "negotiation", _("Negotiation") CLOSED_WON = "closed_won", _("Closed Won") @@ -1515,7 +1515,7 @@ class Opportunity(models.Model): Dealer, on_delete=models.CASCADE, related_name="opportunities" ) customer = models.ForeignKey( - CustomerModel, on_delete=models.CASCADE, related_name="opportunities" + CustomerModel, on_delete=models.CASCADE, related_name="opportunities",null=True,blank=True ) car = models.ForeignKey( Car, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_("Car") @@ -1523,12 +1523,6 @@ class Opportunity(models.Model): stage = models.CharField( max_length=20, choices=Stage.choices, verbose_name=_("Stage") ) - status = models.CharField( - max_length=20, - choices=Status.choices, - verbose_name=_("Status"), - default=Status.NEW, - ) staff = models.ForeignKey( Staff, on_delete=models.SET_NULL, @@ -1538,10 +1532,12 @@ class Opportunity(models.Model): ) lead = models.OneToOneField("Lead",related_name="opportunity", on_delete=models.CASCADE,null=True,blank=True) probability = models.PositiveIntegerField(validators=[validate_probability]) + expected_revenue = models.DecimalField( + max_digits=10, decimal_places=2, verbose_name=_("Expected Revenue") + ) closing_date = models.DateField(verbose_name=_("Closing Date"),null=True,blank=True) created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created")) updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated")) - closed = models.BooleanField(default=False, verbose_name=_("Closed")) estimate = models.OneToOneField(EstimateModel, related_name="opportunity",on_delete=models.SET_NULL,null=True,blank=True) class Meta: verbose_name = _("Opportunity") @@ -1569,6 +1565,31 @@ class Notes(models.Model): def __str__(self): return f"Note by {self.created_by.first_name} on {self.content_object}" +class Tasks(models.Model): + dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name="tasks") + content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) + object_id = models.UUIDField() + content_object = GenericForeignKey("content_type", "object_id") + title = models.CharField(max_length=255, verbose_name=_("Title")) + description = models.TextField(verbose_name=_("Description"),null=True,blank=True) + due_date = models.DateField(verbose_name=_("Due Date")) + completed = models.BooleanField(default=False, verbose_name=_("Completed")) + assigned_to = models.ForeignKey( + User, on_delete=models.DO_NOTHING, related_name="tasks_assigned",null=True,blank=True + ) + created_by = models.ForeignKey( + User, on_delete=models.DO_NOTHING, related_name="tasks_created" + ) + created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created")) + updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated")) + + class Meta: + verbose_name = _("Task") + verbose_name_plural = _("Tasks") + + def __str__(self): + return f"Task by {self.created_by.email} on {self.content_object}" + class Email(models.Model): content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.UUIDField() diff --git a/inventory/urls.py b/inventory/urls.py index 110dc778..6f94d6e7 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -117,8 +117,18 @@ urlpatterns = [ path('crm/leads//update-note/', views.update_note, name='update_note_to_lead'), path("crm/leads//delete-note/", views.delete_note, name="delete_note_to_lead"), path( - "crm/leads//add-activity/", - views.add_activity_to_lead, + "crm//update-task/", + views.update_task, + name="update_task", + ), + path( + "crm///add-task/", + views.add_task, + name="add_task", + ), + path( + "crm///add-activity/", + views.add_activity, name="add_activity", ), path( diff --git a/inventory/utils.py b/inventory/utils.py index 55104f09..12354c6e 100644 --- a/inventory/utils.py +++ b/inventory/utils.py @@ -1362,6 +1362,6 @@ def handle_payment(request,order): return transaction_url - # def get_user_quota(user): # return user.dealer.quota + diff --git a/inventory/views.py b/inventory/views.py index 16940292..6bb7de9b 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -8,6 +8,7 @@ import numpy as np # from rich import print from random import randint from decimal import Decimal +from django.apps import apps from datetime import timedelta from calendar import month_name from pyzbar.pyzbar import decode @@ -24,7 +25,7 @@ from django.conf import settings from django.db import transaction from django.db.models import Func from django.contrib import messages -from django.http import JsonResponse, HttpResponseForbidden +from django.http import Http404, JsonResponse, HttpResponseForbidden from django.forms import HiddenInput, ValidationError from django.shortcuts import HttpResponse from django.db.models import Sum, F, Count @@ -4580,10 +4581,15 @@ class LeadDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): context["activities"] = models.Activity.objects.filter( content_type__model="lead", object_id=self.object.id ) + context["tasks"] = models.Tasks.objects.filter( + content_type__model="lead", object_id=self.object.id + ) context["status_history"] = models.LeadStatusHistory.objects.filter( lead=self.object ) context["transfer_form"] = forms.LeadTransferForm() + context["activity_form"] = forms.ActivityForm() + context["staff_task_form"] = forms.StaffTaskForm() return context @@ -4673,10 +4679,10 @@ def lead_create(request): def lead_tracking(request): dealer = get_user_type(request) - new = models.Lead.objects.filter(dealer=dealer) + new = models.Lead.objects.filter(dealer=dealer, status="new") follow_up = models.Lead.objects.filter(dealer=dealer, next_action__in=["call", "meeting"]) won = models.Lead.objects.filter(dealer=dealer, status="won") - lose = models.Lead.objects.filter(dealer=dealer, status="lose") + lose = models.Lead.objects.filter(dealer=dealer, status="lost") negotiation = models.Lead.objects.filter(dealer=dealer, status="negotiation") context = {"new": new,"follow_up": follow_up,"won": won,"lose": lose,"negotiation": negotiation} return render(request, "crm/leads/lead_tracking.html", context) @@ -4687,25 +4693,25 @@ def update_lead_actions(request): lead_id = request.POST.get('lead_id') current_action = request.POST.get('current_action') next_action = request.POST.get('next_action') - next_action_date = request.POST.get('next_action_date') + next_action_date = request.POST.get('next_action_date',None) action_notes = request.POST.get('action_notes', '') - # Validate required fields - if not all([lead_id, current_action, next_action, next_action_date]): + if not all([lead_id, current_action, next_action]): return JsonResponse({'success': False, 'message': 'All fields are required'}, status=400) # Get the lead lead = models.Lead.objects.get(id=lead_id) # Update lead fields - lead.action = current_action + lead.status = current_action lead.next_action = next_action - lead.next_action_date = next_action_date # Parse the datetime string try: - next_action_datetime = datetime.strptime(next_action_date, '%Y-%m-%dT%H:%M') - lead.next_action_date = timezone.make_aware(next_action_datetime) + if next_action_date: + lead.next_action_date = next_action_date + next_action_datetime = datetime.strptime(next_action_date, '%Y-%m-%dT%H:%M') + lead.next_action_date = timezone.make_aware(next_action_datetime) except ValueError: return JsonResponse({'success': False, 'message': 'Invalid date format'}, status=400) @@ -5060,10 +5066,6 @@ def send_lead_email(request, pk, email_pk=None): response["HX-Redirect"] = reverse("lead_detail", args=[lead.pk]) return response - lead.status = models.Status.CONTACTED - lead.save() - - if request.method == "POST": email_pk = request.POST.get("email_pk") if email_pk not in [None, "None", ""]: @@ -5138,11 +5140,16 @@ def add_activity_to_lead(request, pk): :return: An HTTP response that either renders the form or redirects to the lead detail page """ lead = get_object_or_404(models.Lead, pk=pk) + dealer = get_user_type(request) if request.method == "POST": form = forms.ActivityForm(request.POST) if form.is_valid(): activity = form.save(commit=False) + print(activity) activity.content_object = lead + activity.dealer = dealer + activity.activity_type = form.cleaned_data["activity_type"] + activity.notes = form.cleaned_data["notes"] activity.created_by = request.user activity.save() return redirect("lead_detail", pk=pk) @@ -5151,7 +5158,7 @@ def add_activity_to_lead(request, pk): return render(request, "crm/add_activity.html", {"form": form, "lead": lead}) -class OpportunityCreateView(CreateView, LoginRequiredMixin): +class OpportunityCreateView(CreateView,SuccessMessageMixin, LoginRequiredMixin): """ Handles the creation of Opportunity instances through a form while enforcing specific user access control and initial data population. This view ensures @@ -5173,30 +5180,33 @@ class OpportunityCreateView(CreateView, LoginRequiredMixin): model = models.Opportunity form_class = forms.OpportunityForm template_name = "crm/opportunities/opportunity_form.html" + success_message = "Opportunity created successfully." def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) dealer = get_user_type(self.request) return context - def get_initial(self): - initial = super().get_initial() - if self.kwargs.get("pk", None): - lead = models.Lead.objects.get(pk=self.kwargs.get("pk")) + # def get_initial(self): + # initial = super().get_initial() + # if self.kwargs.get("pk", None): + # lead = models.Lead.objects.get(pk=self.kwargs.get("pk")) - initial["customer"] = lead.customer - return initial + # initial["customer"] = lead.customer + # return initial def form_valid(self, form): dealer = get_user_type(self.request) form.instance.dealer = dealer + form.instance.customer = form.instance.lead.customer + form.instance.staff = form.instance.lead.staff return super().form_valid(form) def get_success_url(self): return reverse_lazy("opportunity_detail", kwargs={"pk": self.object.pk}) -class OpportunityUpdateView(LoginRequiredMixin, UpdateView): +class OpportunityUpdateView(LoginRequiredMixin,SuccessMessageMixin, UpdateView): """ Handles the update functionality for Opportunity objects. @@ -5221,6 +5231,7 @@ class OpportunityUpdateView(LoginRequiredMixin, UpdateView): model = models.Opportunity form_class = forms.OpportunityForm template_name = "crm/opportunities/opportunity_form.html" + success_message = "Opportunity updated successfully." def get_success_url(self): return reverse_lazy("opportunity_detail", kwargs={"pk": self.object.pk}) @@ -5252,7 +5263,6 @@ class OpportunityDetailView(LoginRequiredMixin, DetailView): url = reverse("opportunity_update_status", args=[self.object.pk]) form.fields["status"].widget.attrs["hx-get"] = url form.fields["stage"].widget.attrs["hx-get"] = url - form.fields["status"].initial = self.object.status form.fields["stage"].initial = self.object.stage context["status_form"] = form context["notes"] = models.Notes.objects.filter( @@ -5272,25 +5282,6 @@ class OpportunityDetailView(LoginRequiredMixin, DetailView): class OpportunityListView(LoginRequiredMixin, ListView): - """ - View for displaying a paginated list of opportunities. - - This class-based view inherits from `LoginRequiredMixin` and `ListView` to - provide a view rendering a list of `Opportunity` objects associated with - the current dealer. It ensures the user is authenticated before providing - access to the opportunity list and adds filtering based on the dealer - associated with the request. - - :ivar model: The model used to retrieve opportunities. - :type model: models.Opportunity - :ivar template_name: The template used to render the opportunities list. - :type template_name: str - :ivar context_object_name: The context variable name for the list of - opportunities in the template. - :type context_object_name: str - :ivar paginate_by: The number of opportunities displayed per page. - :type paginate_by: int - """ model = models.Opportunity template_name = "crm/opportunities/opportunity_list.html" context_object_name = "opportunities" @@ -5298,9 +5289,38 @@ class OpportunityListView(LoginRequiredMixin, ListView): def get_queryset(self): dealer = get_user_type(self.request) - return models.Opportunity.objects.filter(dealer=dealer).all() + queryset = models.Opportunity.objects.filter(dealer=dealer) + # Search filter + search = self.request.GET.get('search') + if search: + queryset = queryset.filter( + Q(customer__customer_name__icontains=search) | + Q(customer__email__icontains=search)) + # Stage filter + stage = self.request.GET.get('stage') + if stage: + queryset = queryset.filter(stage=stage) + + # Sorting + sort = self.request.GET.get('sort', 'newest') + if sort == 'newest': + queryset = queryset.order_by('-created') + elif sort == 'highest': + queryset = queryset.order_by('-expected_revenue') + elif sort == 'closing': + queryset = queryset.order_by('closing_date') + + return queryset + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['stage_choices'] = models.Stage.choices + return context + + def get_template_names(self): + return self.template_name @login_required def delete_opportunity(request, pk): """ @@ -7706,3 +7726,78 @@ def mark_all_notifications_as_read(request): def notifications_history(request): models.Notification.objects.filter(user=request.user, is_read=False).update(read=True) return JsonResponse({'status': 'success'}) + +# def activity_create(request,pk): +# lead = get_object_or_404(models.Lead, pk=pk) +# form = forms.ActivityHistoryForm() +# dealer = get_user_type(request) +# if request.method == "POST": +# form = forms.ActivityHistoryForm(request.POST) +# if form.is_valid(): +# models.Activity.objects.create( +# dealer=dealer, +# activity_type=form.cleaned_data['activity_type'], +# notes=form.cleaned_data['description'], +# created_by=request.user, +# content_object=lead +# ) +# return render(request, 'activity_history.html') + +def add_activity(request,content_type,pk): + try: + model = apps.get_model(f'inventory.{content_type}') + except LookupError: + raise Http404("Model not found") + + obj = get_object_or_404(model, pk=pk) + dealer = get_user_type(request) + if request.method == "POST": + form = forms.ActivityForm(request.POST) + if form.is_valid(): + activity = form.save(commit=False) + activity.dealer = dealer + activity.content_object = obj + activity.created_by = request.user + activity.notes = form.cleaned_data['notes'] + activity.activity_type = form.cleaned_data['activity_type'] + + activity.save() + messages.success(request, _("Activity added successfully")) + else: + messages.error(request, _("Activity form is not valid")) + return redirect(f"{content_type}_detail", pk=pk) +def add_task(request,content_type,pk): + try: + model = apps.get_model(f'inventory.{content_type}') + except LookupError: + raise Http404("Model not found") + + obj = get_object_or_404(model, pk=pk) + dealer = get_user_type(request) + if request.method == "POST": + form = forms.StaffTaskForm(request.POST) + if form.is_valid(): + task = form.save(commit=False) + task.dealer = dealer + task.content_object = obj + task.assigned_to = request.user + task.created_by = request.user + task.due_date = form.cleaned_data['due_date'] + task.save() + messages.success(request, _("Task added successfully")) + else: + print(form.errors) + messages.error(request, _("Task form is not valid")) + return redirect(f"{content_type}_detail", pk=pk) + +def update_task(request,pk): + task = get_object_or_404(models.Tasks, pk=pk) + if request.method == "POST": + task.completed = False if task.completed else True + task.save() + messages.success(request, _("Task updated successfully")) + else: + messages.error(request, _("Task form is not valid")) + response = HttpResponse() + response['HX-Refresh'] = 'true' + return response \ No newline at end of file diff --git a/templates/403.html b/templates/403.html index 73099d1b..505228d0 100644 --- a/templates/403.html +++ b/templates/403.html @@ -40,7 +40,7 @@ } .main { width: 100%; - max-width: 1200px; + max-width: 1200px; margin: auto; } .flex-center { @@ -53,7 +53,7 @@ } - +
diff --git a/templates/404.html b/templates/404.html index a2857741..c948fef7 100644 --- a/templates/404.html +++ b/templates/404.html @@ -40,7 +40,7 @@ } .main { width: 100%; - max-width: 1200px; + max-width: 1200px; margin: auto; } .flex-center { @@ -53,7 +53,7 @@ } - +
@@ -64,7 +64,7 @@
- +

Page Missing!

But no worries! Our ostrich is looking everywhere
while you wait safely.

Go Home
diff --git a/templates/500.html b/templates/500.html index 0b5739e9..d9a6763f 100644 --- a/templates/500.html +++ b/templates/500.html @@ -40,7 +40,7 @@ } .main { width: 100%; - max-width: 1200px; + max-width: 1200px; margin: auto; } .flex-center { @@ -53,7 +53,7 @@ } - +
@@ -64,7 +64,7 @@
- +

Unknow error!

But relax! Our cat is here to play you some music.

Go Home
diff --git a/templates/account/confirm_login_code..html b/templates/account/confirm_login_code..html index d984c2bc..5b2a4f46 100644 --- a/templates/account/confirm_login_code..html +++ b/templates/account/confirm_login_code..html @@ -8,42 +8,42 @@ {% endblock head_title %} {% block content %}
-
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} +
+
+ +
+
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

{% translate "Enter Sign-In Code" %}

+
+ + {% setvar email_link %} + {{ email }} + {% endsetvar %} +

+ {% blocktranslate %}We’ve sent a code to {{ email_link }}. The code expires shortly, so please enter it soon.{% endblocktranslate %} +

+
+ {% csrf_token %} + {{ redirect_field }} + {{ form|crispy }} + +
+ {% element button type="submit" form="logout-from-stage" tags="link" %} + {% translate "Cancel" %} + {% endelement %} +
+ + {% csrf_token %} +
- -
-

{% translate "Enter Sign-In Code" %}

-
- - {% setvar email_link %} - {{ email }} - {% endsetvar %} -

- {% blocktranslate %}We’ve sent a code to {{ email_link }}. The code expires shortly, so please enter it soon.{% endblocktranslate %} -

-
- {% csrf_token %} - {{ redirect_field }} - {{ form|crispy }} - -
- {% element button type="submit" form="logout-from-stage" tags="link" %} - {% translate "Cancel" %} - {% endelement %} -
- - {% csrf_token %} -
-
-
{% endblock content %} diff --git a/templates/account/email.html b/templates/account/email.html index 4d2682e8..7db0aa33 100644 --- a/templates/account/email.html +++ b/templates/account/email.html @@ -5,86 +5,86 @@ {% trans "Email Addresses" %} {% endblock head_title %} {% block content %} -
-
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} +
+
+
+ +
+
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

{% trans "Email Addresses" %}

+
+ + {% if emailaddresses %} +

+ {% trans 'The following email addresses are associated with your account:' %} +

+ {% url 'account_email' as email_url %} + + {% else %} + {% include "account/snippets/warn_no_email.html" %} + {% endif %} + {% if can_add_email %} +

+ {% trans "Add Email Address" %} +

+ + {% url 'account_email' as action_url %} + + {% endif %} + +
- -
-

{% trans "Email Addresses" %}

- - {% if emailaddresses %} -

- {% trans 'The following email addresses are associated with your account:' %} -

- {% url 'account_email' as email_url %} - - {% else %} - {% include "account/snippets/warn_no_email.html" %} - {% endif %} - {% if can_add_email %} -

- {% trans "Add Email Address" %} -

- - {% url 'account_email' as action_url %} - - {% endif %} - - -
-
-
{% endblock content %} diff --git a/templates/account/email_confirm.html b/templates/account/email_confirm.html index 5e2c1d66..f7a2243f 100644 --- a/templates/account/email_confirm.html +++ b/templates/account/email_confirm.html @@ -6,48 +6,48 @@ {% trans "Confirm Email Address" %} {% endblock head_title %} {% block content %} -
-
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} +
+
+
+ +
+
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

{% trans "Confirm Email Address" %}

+
+ + {% if confirmation %} + {% user_display confirmation.email_address.user as user_display %} + {% if can_confirm %} +

+ {% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an email address for user {{ user_display }}.{% endblocktrans %} +

+ {% url 'account_confirm_email' confirmation.key as action_url %} +
+ {% csrf_token %} + {{ redirect_field }} + +
+ + {% else %} +

+ {% blocktrans %}Unable to confirm {{ email }} because it is already confirmed by a different account.{% endblocktrans %} +

+ {% endif %} + {% else %} + {% url 'account_email' as email_url %} +

+ {% blocktrans %}This email confirmation link expired or is invalid. Please issue a new email confirmation request.{% endblocktrans %} +

+ {% endif %}
- -
-

{% trans "Confirm Email Address" %}

- - {% if confirmation %} - {% user_display confirmation.email_address.user as user_display %} - {% if can_confirm %} -

- {% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an email address for user {{ user_display }}.{% endblocktrans %} -

- {% url 'account_confirm_email' confirmation.key as action_url %} -
- {% csrf_token %} - {{ redirect_field }} - -
- - {% else %} -

- {% blocktrans %}Unable to confirm {{ email }} because it is already confirmed by a different account.{% endblocktrans %} -

- {% endif %} - {% else %} - {% url 'account_email' as email_url %} -

- {% blocktrans %}This email confirmation link expired or is invalid. Please issue a new email confirmation request.{% endblocktrans %} -

- {% endif %} -
-
-
{% endblock content %} diff --git a/templates/account/lock-screen.html b/templates/account/lock-screen.html index 00c873ef..bfa017df 100644 --- a/templates/account/lock-screen.html +++ b/templates/account/lock-screen.html @@ -104,14 +104,14 @@
@@ -256,9 +256,9 @@
- - -
+ + +
customize
diff --git a/templates/account/login.html b/templates/account/login.html index feddf23e..1f2a116d 100644 --- a/templates/account/login.html +++ b/templates/account/login.html @@ -8,80 +8,80 @@ {% block content %}
-
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} -
-
-
-
-

{% trans "Sign In" %}

- {% if not SOCIALACCOUNT_ONLY %} +
+
+ +
+
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

{% trans "Sign In" %}

+ {% if not SOCIALACCOUNT_ONLY %} -
-
- {% csrf_token %} -
- -
- - +
+ + {% csrf_token %} +
+ +
+ + +
+
+
+ +
+ + +
+
+
+ + +
+ + + + {% include 'partials/form_errors.html' %} + + +
+ {% trans 'If you have not created an account yet, then please' %} + {% trans 'Sign Up' %} +
+ {% endif %}
-
- -
- - -
-
-
- - -
- - - {% include 'partials/form_errors.html' %} +
+
+ {% include 'footer.html' %} +
- -
- {% trans 'If you have not created an account yet, then please' %} - {% trans 'Sign Up' %} -
- {% endif %} -
-
- - -
- {% include 'footer.html' %} -
- - {% if LOGIN_BY_CODE_ENABLED or PASSKEY_LOGIN_ENABLED %} -
- {% element button_group vertical=True %} - {% if PASSKEY_LOGIN_ENABLED %} - {% element button type="submit" form="mfa_login" id="passkey_login" tags="prominent,login,outline,primary" %} - {% trans "Sign in with a passkey" %} - {% endelement %} - {% endif %} - {% if LOGIN_BY_CODE_ENABLED %} - {% element button href=request_login_code_url tags="prominent,login,outline,primary" %} - {% trans "Mail me a sign-in code" %} - {% endelement %} - {% endif %} - {% endelement %} - {% endif %} - {% if SOCIALACCOUNT_ENABLED %} - {% include "socialaccount/snippets/login.html" with page_layout="entrance" %} - {% endif %} + {% if LOGIN_BY_CODE_ENABLED or PASSKEY_LOGIN_ENABLED %} +
+ {% element button_group vertical=True %} + {% if PASSKEY_LOGIN_ENABLED %} + {% element button type="submit" form="mfa_login" id="passkey_login" tags="prominent,login,outline,primary" %} + {% trans "Sign in with a passkey" %} + {% endelement %} + {% endif %} + {% if LOGIN_BY_CODE_ENABLED %} + {% element button href=request_login_code_url tags="prominent,login,outline,primary" %} + {% trans "Mail me a sign-in code" %} + {% endelement %} + {% endif %} + {% endelement %} + {% endif %} + {% if SOCIALACCOUNT_ENABLED %} + {% include "socialaccount/snippets/login.html" with page_layout="entrance" %} + {% endif %} {% endblock content %} diff --git a/templates/account/logout.html b/templates/account/logout.html index a9a72436..2e56c0a7 100644 --- a/templates/account/logout.html +++ b/templates/account/logout.html @@ -3,28 +3,28 @@ {% block title %}{{ _("Sign Out") }}{% endblock title %} {% block content %} -
-
-
-
-
-

{{ _("Sign Out") }}

-

{{ _("Are you sure you want to sign out?") }}

+
+
+
+
+
+

{{ _("Sign Out") }}

+

{{ _("Are you sure you want to sign out?") }}

+
+
+
+ {% csrf_token %} + {{ redirect_field }} +
+
-
- - {% csrf_token %} - {{ redirect_field }} -
- -
-
-
+
+
{% endblock content %} \ No newline at end of file diff --git a/templates/account/otp_verification.html b/templates/account/otp_verification.html index 3f4f3f7a..923f4e5a 100644 --- a/templates/account/otp_verification.html +++ b/templates/account/otp_verification.html @@ -2,37 +2,37 @@ {% load i18n static %} {% block content %} -
-
-
- -
- {% trans 'home' %} - {% trans 'home' %} -
-
-
-
-

{{ _("Enter the verification code") }}

-

- {{ _("An email containing a 6-digit verification code has been sent to your email.") }} -

+
+
+
+ +
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

{{ _("Enter the verification code") }}

+

+ {{ _("An email containing a 6-digit verification code has been sent to your email.") }} +

-
- {% csrf_token %} -
- -
- - {{ _("Didn’t receive the code") }} -
+
+ {% csrf_token %} +
+ +
+ + {{ _("Didn’t receive the code") }} +
+
-
{% endblock %} \ No newline at end of file diff --git a/templates/account/password_change.html b/templates/account/password_change.html index 30b239b5..6b123eed 100644 --- a/templates/account/password_change.html +++ b/templates/account/password_change.html @@ -5,30 +5,30 @@ {% trans "Change Password" %} {% endblock head_title %} {% block content %} -
-
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} +
+
+
+ +
+
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

{% trans "Change Password" %}

+
+
+ {% csrf_token %} + {{ redirect_field }} + {{ form|crispy }} + + +
- -
-

{% trans "Change Password" %}

-
- {% csrf_token %} - {{ redirect_field }} - {{ form|crispy }} - - -
-
-
-
{% endblock content %} diff --git a/templates/account/password_reset.html b/templates/account/password_reset.html index 50e0badf..a7c3041f 100644 --- a/templates/account/password_reset.html +++ b/templates/account/password_reset.html @@ -5,37 +5,37 @@ {% trans "Password Reset" %} {% endblock head_title %} {% block content %} -
-
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} +
+
+
+ +
+
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

{% trans "Password Reset" %}

+ + {% if user.is_authenticated %} + {% include "account/snippets/already_logged_in.html" %} + {% endif %} +

+ {% trans "Forgotten your password? Enter your email address below, and we'll send you an email allowing you to reset it." %} +

+ +
+ {% csrf_token %} + {{ form|crispy }} + +
+

+ {% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %} +

- -
-

{% trans "Password Reset" %}

- - {% if user.is_authenticated %} - {% include "account/snippets/already_logged_in.html" %} - {% endif %} -

- {% trans "Forgotten your password? Enter your email address below, and we'll send you an email allowing you to reset it." %} -

- -
- {% csrf_token %} - {{ form|crispy }} - -
-

- {% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %} -

-
-
{% endblock content %} diff --git a/templates/account/password_reset_done.html b/templates/account/password_reset_done.html index e56b3f6b..a3d49a9e 100644 --- a/templates/account/password_reset_done.html +++ b/templates/account/password_reset_done.html @@ -7,27 +7,27 @@ {% endblock head_title %} {% block content %}
-
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} +
+
+ +
+
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

{% trans "Password Reset" %}

+
+ + {% if user.is_authenticated %} + {% include "account/snippets/already_logged_in.html" %} + {% endif %} +

+ {% blocktrans %}We have sent you an email. If you have not received it please check your spam folder. Otherwise contact us if you do not receive it in a few minutes.{% endblocktrans %} +

- -
-

{% trans "Password Reset" %}

-
- - {% if user.is_authenticated %} - {% include "account/snippets/already_logged_in.html" %} - {% endif %} -

- {% blocktrans %}We have sent you an email. If you have not received it please check your spam folder. Otherwise contact us if you do not receive it in a few minutes.{% endblocktrans %} -

-
-
{% endblock content %} diff --git a/templates/account/password_reset_from_key.html b/templates/account/password_reset_from_key.html index 86f05953..20870747 100644 --- a/templates/account/password_reset_from_key.html +++ b/templates/account/password_reset_from_key.html @@ -6,41 +6,41 @@ {% trans "Change Password" %} {% endblock head_title %} {% block content %} -
-
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} +
+
+
+ +
+
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

+ {% if token_fail %} + {% trans "Bad Token" %} + {% else %} + {% trans "Change Password" %} + {% endif %} +

+
+ + {% if token_fail %} + {% url 'account_reset_password' as passwd_reset_url %} +

+ {% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset.{% endblocktrans %} +

+ {% else %} +
+ {% csrf_token %} + {{ redirect_field }} + {{ form|crispy }} + +
+ {% endif %}
- -
-

- {% if token_fail %} - {% trans "Bad Token" %} - {% else %} - {% trans "Change Password" %} - {% endif %} -

- - {% if token_fail %} - {% url 'account_reset_password' as passwd_reset_url %} -

- {% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset.{% endblocktrans %} -

- {% else %} -
- {% csrf_token %} - {{ redirect_field }} - {{ form|crispy }} - -
- {% endif %} -
-
-
{% endblock content %} diff --git a/templates/account/password_reset_from_key_done.html b/templates/account/password_reset_from_key_done.html index d6dc8cbb..cd9e05b5 100644 --- a/templates/account/password_reset_from_key_done.html +++ b/templates/account/password_reset_from_key_done.html @@ -6,23 +6,23 @@ {% endblock head_title %} {% block content %}
-
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} +
+
+ +
+
+ {% trans 'home' %} + {% trans 'home' %} +
+
+
+
+

{% trans "Change Password" %}

+

{% trans 'Your password is now changed.' %}

+
+ +
- -
-

{% trans "Change Password" %}

-

{% trans 'Your password is now changed.' %}

-
- - -
-
{% endblock content %} diff --git a/templates/account/signup-wizard.html b/templates/account/signup-wizard.html index db411d17..740d64e4 100644 --- a/templates/account/signup-wizard.html +++ b/templates/account/signup-wizard.html @@ -4,90 +4,90 @@ {% block content %} -
+
-
+
-
+
- {% trans 'home' %} - {% trans 'home' %} + {% trans 'home' %} + {% trans 'home' %}
-

{% trans 'Sign Up' %}

-

{% trans 'Create your account today' %}

-
+

{% trans 'Sign Up' %}

+

{% trans 'Create your account today' %}

+
-
- -
-
-
-
- {{form1|crispy}} -
-
-
-
- {{form2|crispy}} -
-
-
-
- {{form3|crispy}} -
-
-
-
-
-
+
+ -
-
-
{% trans 'You are all set!' %}
-

{% trans 'Now you can access your account' %}
{% trans 'anytime' %} {% trans 'anywhere' %}

+
+
+
+
+ {{form1|crispy}} +
+
+
+
+ {{form2|crispy}} +
+
+
+
+ {{form3|crispy}} +
+
+
+
+
+
+
+
+
+
{% trans 'You are all set!' %}
+

{% trans 'Now you can access your account' %}
{% trans 'anytime' %} {% trans 'anywhere' %}

+
+
+
+
+
+
+
- -
-
-
-
-
-
- {% include 'footer.html' %} -
- - {% endblock content %} +
+
+ {% include 'footer.html' %} +
+ +{% endblock content %} - {% block customJS %} +{% block customJS %} + }); + return formData; + } - {% endblock customJS %} \ No newline at end of file + function showLoading() { + Swal.fire({ + title: "{% trans 'Please Wait' %}", + text: "{% trans 'Loading' %}...", + allowOutsideClick: false, + didOpen: () => { + Swal.showLoading(); + } + }); + } + + function hideLoading() { + Swal.close(); + } + + function notify(tag,msg){ + Swal.fire({ + icon: tag, + titleText: msg + }); + } + function getCookie(name) { + let cookieValue = null; + if (document.cookie && document.cookie !== "") { + const cookies = document.cookie.split(";"); + for (let cookie of cookies) { + cookie = cookie.trim(); + if (cookie.substring(0, name.length + 1) === name + "=") { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; + } + + +{% endblock customJS %} \ No newline at end of file diff --git a/templates/account/signup.html b/templates/account/signup.html index ddb3b041..bffc7f4e 100644 --- a/templates/account/signup.html +++ b/templates/account/signup.html @@ -5,84 +5,84 @@ {% block title %}{{ _("Sign Up") }}{% endblock title %} {% block content %} -
+
-
- -
-
- {% trans 'home' %} - {% trans 'home' %} -
-
-
-
-

Sign Up

-

Create your account today

-
- - {% if PASSKEY_SIGNUP_ENABLED %} -
-
- - {{ _("Sign up using a passkey") }} + - {% endif %} +
+

Sign Up

+

Create your account today

+
+ + {% if PASSKEY_SIGNUP_ENABLED %} +
+ + {% endif %} - {% if SOCIALACCOUNT_ENABLED %} + {% if SOCIALACCOUNT_ENABLED %} - {% include "socialaccount/snippets/login.html" with page_layout="entrance" %} -{% endif %} + {% include "socialaccount/snippets/login.html" with page_layout="entrance" %} + {% endif %} - {% if not SOCIALACCOUNT_ONLY %} -
- {% csrf_token %} - {{ redirect_field }} -
- - - {% if form.email.errors %} -
{{ form.email.errors|striptags }}
- {% endif %} -
+ {% if not SOCIALACCOUNT_ONLY %} + + {% csrf_token %} + {{ redirect_field }} +
+ + + {% if form.email.errors %} +
{{ form.email.errors|striptags }}
+ {% endif %} +
-
- -
- - -
- {% if form.password1.errors %} -
{{ form.password1.errors|striptags }}
- {% endif %} -
+
+ +
+ + +
+ {% if form.password1.errors %} +
{{ form.password1.errors|striptags }}
+ {% endif %} +
-
- -
- - -
- {% if form.password2.errors %} -
{{ form.password2.errors|striptags }}
- {% endif %} -
+
+ +
+ + +
+ {% if form.password2.errors %} +
{{ form.password2.errors|striptags }}
+ {% endif %} +
-
+
- - -
- -
{% trans 'Already have an account?' %} {{ _("Sign In") }}
- - {% endif %} -
+ + +
+ +
{% trans 'Already have an account?' %} {{ _("Sign In") }}
+ + {% endif %} +
-
+
diff --git a/templates/account/snippets/already_logged_in.html b/templates/account/snippets/already_logged_in.html index 92d550a6..320f40f5 100644 --- a/templates/account/snippets/already_logged_in.html +++ b/templates/account/snippets/already_logged_in.html @@ -6,6 +6,6 @@ diff --git a/templates/account/user_settings.html b/templates/account/user_settings.html index bc35be00..7b72fdfe 100644 --- a/templates/account/user_settings.html +++ b/templates/account/user_settings.html @@ -10,7 +10,7 @@ {% csrf_token %}
- +

Default Invoice Accounts

@@ -41,7 +41,7 @@
-
+
diff --git a/templates/account/verfied_email_required.html b/templates/account/verfied_email_required.html index af072af3..644c041d 100644 --- a/templates/account/verfied_email_required.html +++ b/templates/account/verfied_email_required.html @@ -7,23 +7,23 @@ {% block content %}
-
-
- -
- {% trans 'home' %} - {% trans 'home' %} -
-
-

- {% trans "Verify Your Email Address" %} -

+
+
+ +
+ {% trans 'home' %} + {% trans 'home' %} +
+
+

+ {% trans "Verify Your Email Address" %} +

-

- {% blocktrans %}We have sent an email to you for verification. Follow the link provided to finalize the signup process. If you do not see the verification email in your main inbox, check your spam folder. Please contact us if you do not receive the verification email within a few minutes.{% endblocktrans %} -

+

+ {% blocktrans %}We have sent an email to you for verification. Follow the link provided to finalize the signup process. If you do not see the verification email in your main inbox, check your spam folder. Please contact us if you do not receive the verification email within a few minutes.{% endblocktrans %} +

+
-
{% endblock content %} diff --git a/templates/account/verification_sent.html b/templates/account/verification_sent.html index 748e40f6..a0710439 100644 --- a/templates/account/verification_sent.html +++ b/templates/account/verification_sent.html @@ -5,23 +5,23 @@ {% trans "Verify Your Email Address" %} {% endblock head_title %} {% block content %} -
-
-
- -
- {% trans 'home' %} - {% trans 'home' %} -
-
-

- {% trans "Verify Your Email Address" %} -

+
+
+
+ +
+ {% trans 'home' %} + {% trans 'home' %} +
+
+

+ {% trans "Verify Your Email Address" %} +

-

- {% blocktrans %}We have sent an email to you for verification. Follow the link provided to finalize the signup process. If you do not see the verification email in your main inbox, check your spam folder. Please contact us if you do not receive the verification email within a few minutes.{% endblocktrans %} -

+

+ {% blocktrans %}We have sent an email to you for verification. Follow the link provided to finalize the signup process. If you do not see the verification email in your main inbox, check your spam folder. Please contact us if you do not receive the verification email within a few minutes.{% endblocktrans %} +

+
-
{% endblock content %} diff --git a/templates/account/verified_email_required.html b/templates/account/verified_email_required.html index cf2c9548..01e54180 100644 --- a/templates/account/verified_email_required.html +++ b/templates/account/verified_email_required.html @@ -6,33 +6,33 @@ {% endblock head_title %} {% block content %}
-
-
- -
- {% trans 'home' %} - {% trans 'home' %} -
-
-

- {% trans "Verify Your Email Address" %} -

+
+
+ +
+ {% trans 'home' %} + {% trans 'home' %} +
+
+

+ {% trans "Verify Your Email Address" %} +

- {% url 'account_email' as email_url %} -

- {% blocktrans %}This part of the site requires us to verify that -you are who you claim to be. For this purpose, we require that you -verify ownership of your email address. {% endblocktrans %} -

-

- {% blocktrans %}We have sent an email to you for -verification. Please click on the link inside that email. If you do not see the verification email in your main inbox, check your spam folder. Otherwise -contact us if you do not receive it within a few minutes.{% endblocktrans %} -

-

- {% blocktrans %}Note: you can still change your email address.{% endblocktrans %} -

+ {% url 'account_email' as email_url %} +

+ {% blocktrans %}This part of the site requires us to verify that + you are who you claim to be. For this purpose, we require that you + verify ownership of your email address. {% endblocktrans %} +

+

+ {% blocktrans %}We have sent an email to you for + verification. Please click on the link inside that email. If you do not see the verification email in your main inbox, check your spam folder. Otherwise + contact us if you do not receive it within a few minutes.{% endblocktrans %} +

+

+ {% blocktrans %}Note: you can still change your email address.{% endblocktrans %} +

+
-
{% endblock content %} diff --git a/templates/administration/display_appointment.html b/templates/administration/display_appointment.html index 3c06a3b8..954be742 100644 --- a/templates/administration/display_appointment.html +++ b/templates/administration/display_appointment.html @@ -6,89 +6,89 @@ {% block description %}{{ page_description }}{% endblock %} {% block content %} -
-
-
-

{{ page_title }}

-
-
-
-
-
- - {% trans 'Date' %}: {{ appointment.get_date }} +
+
+
+

{{ page_title }}

+
+
+
+
+
+ + {% trans 'Date' %}: {{ appointment.get_date }} +
-
-
-
- - {% trans 'Start time' %}: {{ appointment.get_start_time|time:"g:i A" }} +
+
+ + {% trans 'Start time' %}: {{ appointment.get_start_time|time:"g:i A" }} +
-
-
-
- - {% trans 'End time' %}: {{ appointment.get_end_time|time:"g:i A" }} +
+
+ + {% trans 'End time' %}: {{ appointment.get_end_time|time:"g:i A" }} +
-
-
-
- - {% trans 'Service' %}: {{ appointment.get_service_name }} +
+
+ + {% trans 'Service' %}: {{ appointment.get_service_name }} +
-
-
-
- - {% trans 'Client' %}: {{ appointment.get_client_name }} +
+
+ + {% trans 'Client' %}: {{ appointment.get_client_name }} +
-
-
-
- - {% trans 'Email' %}: {{ appointment.client.email }} +
+
+ + {% trans 'Email' %}: {{ appointment.client.email }} +
-
-
-
- - {% trans 'Phone' %}: {{ appointment.phone }} +
+
+ + {% trans 'Phone' %}: {{ appointment.phone }} +
-
-
-
- - {% trans 'Wants reminder' %}: {{ appointment.want_reminder }} +
+
+ + {% trans 'Wants reminder' %}: {{ appointment.want_reminder }} +
-
-
-
- - {% trans 'Client address' %}: {{ appointment.address }} +
+
+ + {% trans 'Client address' %}: {{ appointment.address }} +
-
-
-
- - {% trans 'Additional Information' %}: {{ appointment.additional_info }} +
+
+ + {% trans 'Additional Information' %}: {{ appointment.additional_info }} +
-
-
-
- - {% trans 'Is paid' %}: {{ appointment.is_paid_text }} +
+
+ + {% trans 'Is paid' %}: {{ appointment.is_paid_text }} +
-
-
-
- - {% trans 'Service price' %}: {{ appointment.get_appointment_amount_to_pay_text }} +
+
+ + {% trans 'Service price' %}: {{ appointment.get_appointment_amount_to_pay_text }} +
-
{% endblock %} {% block extra_js %} diff --git a/templates/administration/manage_service.html b/templates/administration/manage_service.html index 1ec9fc0a..f90017be 100644 --- a/templates/administration/manage_service.html +++ b/templates/administration/manage_service.html @@ -9,126 +9,126 @@ {% block content %} {% translate "Confirm Deletion" as modal_title %} - {% translate "Delete" as delete_btn_modal %} -
-
-

{{ page_title }}

-
- {% csrf_token %} + {% translate "Delete" as delete_btn_modal %} +
+
+

{{ page_title }}

+ + {% csrf_token %} -
- {{ form.name|add_class:"form-control form-control-sm" }} - - {% if form.name.errors %} -
- {{ form.name.errors }} +
+ {{ form.name|add_class:"form-control form-control-sm" }} + + {% if form.name.errors %} +
+ {{ form.name.errors }} +
+ {% endif %}
- {% endif %} -
-
- {{ form.description|add_class:"form-control form-control-sm" }} - - {% if form.description.errors %} -
- {{ form.description.errors }} +
+ {{ form.description|add_class:"form-control form-control-sm" }} + + {% if form.description.errors %} +
+ {{ form.description.errors }} +
+ {% endif %}
- {% endif %} -
-
- {{ form.duration|add_class:"form-control form-control-sm" }} - - {% if form.duration.errors %} -
- {{ form.duration.errors }} +
+ {{ form.duration|add_class:"form-control form-control-sm" }} + + {% if form.duration.errors %} +
+ {{ form.duration.errors }} +
+ {% endif %}
- {% endif %} -
-
- {{ form.price|add_class:"form-control form-control-sm" }} - - {% if form.price.errors %} -
- {{ form.price.errors }} +
+ {{ form.price|add_class:"form-control form-control-sm" }} + + {% if form.price.errors %} +
+ {{ form.price.errors }} +
+ {% endif %}
- {% endif %} -
-
- {{ form.down_payment|add_class:"form-control form-control-sm" }} - - {% if form.down_payment.errors %} -
- {{ form.down_payment.errors }} +
+ {{ form.down_payment|add_class:"form-control form-control-sm" }} + + {% if form.down_payment.errors %} +
+ {{ form.down_payment.errors }} +
+ {% endif %}
- {% endif %} -
-
- - {{ form.image }} - {% if form.image.errors %} -
- {{ form.image.errors }} +
+ + {{ form.image }} + {% if form.image.errors %} +
+ {{ form.image.errors }} +
+ {% endif %}
- {% endif %} -
-
- - - {% if form.currency.errors %} -
- {{ form.currency.errors }} +
+ + + {% if form.currency.errors %} +
+ {{ form.currency.errors }} +
+ {% endif %}
- {% endif %} -
-
- - - {% if form.background_color.errors %} -
- {{ form.background_color.errors }} -
- {% endif %} -
- - - {% if btn_text %} - - {% else %} - {% if request.user.is_superuser and service.id %} -{% translate "Are you sure you want to delete this service?" as d_modal_message %} - - {% endif %} +
+ + + {% if form.background_color.errors %} +
+ {{ form.background_color.errors }} +
{% endif %} - +
+ + + {% if btn_text %} + + {% else %} + {% if request.user.is_superuser and service.id %} + {% translate "Are you sure you want to delete this service?" as d_modal_message %} + + {% endif %} + {% endif %} + -
+
{% include 'modal/confirm_modal.html' %} {% endblock %} diff --git a/templates/administration/manage_staff_member.html b/templates/administration/manage_staff_member.html index eaa4f6c9..2d57373e 100644 --- a/templates/administration/manage_staff_member.html +++ b/templates/administration/manage_staff_member.html @@ -34,7 +34,7 @@
- {{ form.slot_duration.label_tag }} + {{ form.slot_duration.label_tag }} {{ form.slot_duration }} {{ form.slot_duration.help_text }}
diff --git a/templates/administration/manage_staff_personal_info.html b/templates/administration/manage_staff_personal_info.html index 2cdd7257..8438d05a 100644 --- a/templates/administration/manage_staff_personal_info.html +++ b/templates/administration/manage_staff_personal_info.html @@ -8,38 +8,38 @@ {% block content %}
-
-

{% trans 'Staff Personal Information' %}

-
- {% csrf_token %} +
+

{% trans 'Staff Personal Information' %}

+ + {% csrf_token %} -
- {{ form.first_name }} - +
+ {{ form.first_name }} + -
- -
- {{ form.last_name }} - -
- -
- {{ form.email }} - -
- - - -
- {% if messages %} - {% for message in messages %} - - {% endfor %} - {% endif %}
+ +
+ {{ form.last_name }} + +
+ +
+ {{ form.email }} + +
+ + + +
+ {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %}
+
{% endblock %} diff --git a/templates/administration/manage_working_hours.html b/templates/administration/manage_working_hours.html index 671ecece..e06deb0b 100644 --- a/templates/administration/manage_working_hours.html +++ b/templates/administration/manage_working_hours.html @@ -12,66 +12,66 @@
-

{% trans "Manage Working Hours" %}

-
- {% csrf_token %} - - {% if working_hours_form.staff_member %} -
- - {{ working_hours_form.staff_member }} -
- {% endif %} +

{% trans "Manage Working Hours" %}

+ + {% csrf_token %} + {% if working_hours_form.staff_member %}
- - {{ working_hours_form.day_of_week|add_class:"form-select form-select-sm" }} + + {{ working_hours_form.staff_member }}
+ {% endif %} -
- -
- -
-
-
- -
- -
- -
-
-
- - - - - -
- {% include 'modal/error_modal.html' %} -
- {% if messages %} - {% for message in messages %} - - {% endfor %} - {% endif %} +
+ + {{ working_hours_form.day_of_week|add_class:"form-select form-select-sm" }}
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+
+
+ + + + + + + {% include 'modal/error_modal.html' %} +
+ {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %}
+
{% endblock %} {% block customJS %} diff --git a/templates/administration/service_list.html b/templates/administration/service_list.html index 1fc7e713..88af7de5 100644 --- a/templates/administration/service_list.html +++ b/templates/administration/service_list.html @@ -9,61 +9,61 @@ {% trans 'Service List' %}. {% endblock %} {% block body %} -{% translate "Confirm Deletion" as modal_title %} - {% translate "Delete" as delete_btn_modal %} -
-
-

{% trans 'Service List' %}

-
-
- - - - - - - - - - - - {% for service in services %} - - - - - - - - {% empty %} - - - - {% endfor %} - -
{% trans 'Name' %}{% trans 'Duration' %}{% trans 'Price' %}{% trans 'Action' %}
{{ service.name }}{{ service.get_duration }}{{ service.get_price_text }} -
- - - - {% translate "Are you sure you want to delete this service?" as d_modal_message %} - {% if request.user.is_superuser %} - - - - - - - {% endif %} -
-
{% trans 'No service found' %}.
-
-{% include 'modal/confirm_modal.html' %} + {% translate "Confirm Deletion" as modal_title %} + {% translate "Delete" as delete_btn_modal %} +
+
+

{% trans 'Service List' %}

+
+ + + + + + + + + + + + {% for service in services %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
{% trans 'Name' %}{% trans 'Duration' %}{% trans 'Price' %}{% trans 'Action' %}
{{ service.name }}{{ service.get_duration }}{{ service.get_price_text }} +
+ + + + {% translate "Are you sure you want to delete this service?" as d_modal_message %} + {% if request.user.is_superuser %} + + + + + + + {% endif %} +
+
{% trans 'No service found' %}.
+
+ {% include 'modal/confirm_modal.html' %} +
{% endblock %} diff --git a/templates/administration/staff_index.html b/templates/administration/staff_index.html index 779d0c20..ce9d2a5d 100644 --- a/templates/administration/staff_index.html +++ b/templates/administration/staff_index.html @@ -36,7 +36,7 @@ @@ -94,7 +94,7 @@ - diff --git a/templates/auth_base.html b/templates/auth_base.html index e7e7ba2e..9bdba65d 100644 --- a/templates/auth_base.html +++ b/templates/auth_base.html @@ -7,27 +7,27 @@ data-navigation-type="default" data-navbar-horizontal-shape="default"> - - - - - + + + + + - {% block title %}{% trans 'HAIKAL' %}{% endblock %} + {% block title %}{% trans 'HAIKAL' %}{% endblock %} - - - - - - - + + + + + + + - - - + + + @@ -36,71 +36,71 @@ - - - - - - - - - {% if LANGUAGE_CODE == 'en' %} - - - {% else %} - - - {% endif %} + + + + + + + + + {% if LANGUAGE_CODE == 'en' %} + + + {% else %} + + + {% endif %} - + - - {% include 'messages.html' %} -
+ + {% include 'messages.html' %} +
-
+
-{% block content %} + {% block content %} -{% endblock %} + {% endblock %} -
+
-
+
- - {% block customJS %}{% endblock customJS %} + + {% block customJS %}{% endblock customJS %} - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 3cb7e58d..8cb59944 100644 --- a/templates/base.html +++ b/templates/base.html @@ -6,50 +6,50 @@ data-bs-theme="" data-navigation-type="default" data-navbar-horizontal-shape="default"> - - - - - - - {% block title %} + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content="Haikal - The Backbone of Car Qar: An innovative car inventory management system designed to streamline dealership operations. Manage inventory, sales, transfers, and accounting seamlessly with advanced analytics and intuitive tools. Inspired by Arabic origins, Haikal empowers businesses with precision and efficiency."> + <title> + {% block title %} - {% endblock %} - {% block description %} -{% endblock %} - - - - - - - - + {% endblock %} + {% block description %} + {% endblock %} + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - {% if LANGUAGE_CODE == 'ar' %} - - - {% else %} - - - {% endif %} - - - + + + + {% if LANGUAGE_CODE == 'ar' %} + + + {% else %} + + + {% endif %} + + + -{% block customCSS %} + {% block customCSS %} -{% endblock %} - - + {% endblock %} + + - {% include "toast-alert.html" %} -
- {% include 'header.html' %} + {% include "toast-alert.html" %} +
+ {% include 'header.html' %} -
-{% include "plans/expiration_messages.html" %} - {% block period_navigation %} +
+ {% include "plans/expiration_messages.html" %} + {% block period_navigation %} - {% endblock period_navigation %} + {% endblock period_navigation %} - {% block content %} - {% endblock content%} - {% block body %} - {% endblock body%} + {% block content %} + {% endblock content%} + {% block body %} + {% endblock body%} -
-{% include 'footer.html' %} -
-
- - - +
+ {% include 'footer.html' %} +
+
+ + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - + + + + + - - {% block customJS %} - {% endblock %} - + {% if date_navigation_url %} + let dateNavigationUrl = "{{ date_navigation_url }}" + let datePickers = document.querySelectorAll("[id^='djl-datepicker']") + datePickers.forEach(dp => djLedger.getCalendar(dp.attributes.id.value, dateNavigationUrl)) + {% endif %} + + {% block customJS %} + {% endblock %} + \ No newline at end of file diff --git a/templates/chat_support.html b/templates/chat_support.html index d99cc37d..6035e9d6 100644 --- a/templates/chat_support.html +++ b/templates/chat_support.html @@ -1,43 +1,43 @@
-
-
- - - +
+
+ +
+ - -
\ No newline at end of file +
+ +
+
+ +
\ No newline at end of file diff --git a/templates/components/activity_modal.html b/templates/components/activity_modal.html new file mode 100644 index 00000000..fe9fa5f0 --- /dev/null +++ b/templates/components/activity_modal.html @@ -0,0 +1,30 @@ +{% load static i18n crispy_forms_tags %} + + \ No newline at end of file diff --git a/templates/crm/add_activity.html b/templates/crm/add_activity.html index e79d0c90..44de9100 100644 --- a/templates/crm/add_activity.html +++ b/templates/crm/add_activity.html @@ -2,10 +2,10 @@ {% load i18n static crispy_forms_filters %} {% block content %} -

Add Activity to {{ lead.first_name }} {{ lead.last_name }}

-
- {% csrf_token %} - {{ form|crispy }} - -
+

Add Activity to {{ lead.first_name }} {{ lead.last_name }}

+
+ {% csrf_token %} + {{ form|crispy }} + +
{% endblock %} \ No newline at end of file diff --git a/templates/crm/employee_calendar.html b/templates/crm/employee_calendar.html index 3153fee1..b61e2a08 100644 --- a/templates/crm/employee_calendar.html +++ b/templates/crm/employee_calendar.html @@ -1,38 +1,38 @@ {% extends 'base.html' %} {% load static %} {% block content %} -
-
- - - - - - - - - - - - - - - {% for appointment in appointments %} - - - - - - - - - - - {% endfor %} - -
CustomerServiceDateStart TimeEnd TimeStaffStatus
{{ appointment.get_client_name }}{{ appointment.get_service }}{{ appointment.appointment_request.date|date:"Y-m-d" }}{{ appointment.appointment_request.start_time }}{{ appointment.appointment_request.end_time }}{{ appointment.get_staff_member_name }} - view -
-
-
+
+
+ + + + + + + + + + + + + + + {% for appointment in appointments %} + + + + + + + + + + + {% endfor %} + +
CustomerServiceDateStart TimeEnd TimeStaffStatus
{{ appointment.get_client_name }}{{ appointment.get_service }}{{ appointment.appointment_request.date|date:"Y-m-d" }}{{ appointment.appointment_request.start_time }}{{ appointment.appointment_request.end_time }}{{ appointment.get_staff_member_name }} + view +
+
+
{% endblock %} \ No newline at end of file diff --git a/templates/crm/leads/lead_confirm_delete.html b/templates/crm/leads/lead_confirm_delete.html index 566549bd..f20794a6 100644 --- a/templates/crm/leads/lead_confirm_delete.html +++ b/templates/crm/leads/lead_confirm_delete.html @@ -1,10 +1,10 @@ - - - Title - - + + + Title + + - + \ No newline at end of file diff --git a/templates/crm/leads/lead_detail.html b/templates/crm/leads/lead_detail.html index 81e5c73a..20a77319 100644 --- a/templates/crm/leads/lead_detail.html +++ b/templates/crm/leads/lead_detail.html @@ -1,143 +1,232 @@ {% extends 'base.html' %} -{% load i18n static %} -{% block content %} +{% load i18n static humanize %} {% load crispy_forms_tags %} {% block customCSS %} - + {% endblock customCSS %} - -
-
-
-
-

{{ _("Lead Details")}}

-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-

{{ _("Lead Details")}}

- -
-
-
-
-
-

{{ lead.first_name }} {{ lead.last_name }}

- {% if lead.staff %} -

{{ _("Assigned to")}}: {{ lead.staff }}

- {% else %} -

{{ _("Not Assigned")}}

- {% endif %} +{% block content %} +
+
+
diff --git a/templates/ledger/bills/bill_update_form.html b/templates/ledger/bills/bill_update_form.html index e43c596c..a63348d1 100644 --- a/templates/ledger/bills/bill_update_form.html +++ b/templates/ledger/bills/bill_update_form.html @@ -3,19 +3,19 @@ {% load crispy_forms_filters %} {% block title %}{% trans "Bill" %}{% endblock title %} {% block content %} -
-

{% trans "Bill" %}

-
- {% csrf_token %} - {{ form|crispy }} - - {% trans "Cancel" %} -
-
+
+

{% trans "Bill" %}

+
+ {% csrf_token %} + {{ form|crispy }} + + {% trans "Cancel" %} +
+
{% endblock %} \ No newline at end of file diff --git a/templates/ledger/coa_accounts/account_detail.html b/templates/ledger/coa_accounts/account_detail.html index 1e044cae..fc051955 100644 --- a/templates/ledger/coa_accounts/account_detail.html +++ b/templates/ledger/coa_accounts/account_detail.html @@ -44,11 +44,11 @@

- {% if account.balance_type == 'debit' %} - {{ _('Balance Type') }}:

{{ _("Debit") }}
- {% else %} - {{ _('Balance Type') }}:
{{ _("Credit") }}
- {% endif %} + {% if account.balance_type == 'debit' %} + {{ _('Balance Type') }}:
{{ _("Debit") }}
+ {% else %} + {{ _('Balance Type') }}:
{{ _("Credit") }}
+ {% endif %}

@@ -58,7 +58,7 @@

- +
@@ -75,7 +75,7 @@ - + diff --git a/templates/ledger/coa_accounts/account_form.html b/templates/ledger/coa_accounts/account_form.html index ddeb83a2..bc091284 100644 --- a/templates/ledger/coa_accounts/account_form.html +++ b/templates/ledger/coa_accounts/account_form.html @@ -4,35 +4,35 @@ {% block title %}{% trans "account" %}{% endblock title %} {% block content %} -
+
-
-
-

- {% if account.created %} +
+
+

+ {% if account.created %} - {{ _("Edit Account") }} - {% else %} + {{ _("Edit Account") }} + {% else %} - {{ _("Add Account") }} - {% endif %} -

-
-
-
- {% csrf_token %} - {{ form|crispy }} - {% for error in form.errors %} -
{{ error }}
- {% endfor %} -
- - {% trans "Cancel"|capfirst %} -
- + {{ _("Add Account") }} + {% endif %} +

+
+
+
+ {% csrf_token %} + {{ form|crispy }} + {% for error in form.errors %} +
{{ error }}
+ {% endfor %} +
+ + {% trans "Cancel"|capfirst %} +
+ +
-
{% endblock %} \ No newline at end of file diff --git a/templates/ledger/coa_accounts/account_list.html b/templates/ledger/coa_accounts/account_list.html index 10eeefa6..1a26535e 100644 --- a/templates/ledger/coa_accounts/account_list.html +++ b/templates/ledger/coa_accounts/account_list.html @@ -2,147 +2,147 @@ {% load i18n %} {% block title %}{% trans "Accounts" %}{% endblock title %} {% block accounts %} - - {% trans "Accounts"|capfirst %} - (current) - + + {% trans "Accounts"|capfirst %} + (current) + {% endblock %} {% block content %} -
- -

- {% trans "Accounts" %}

-
-
-
- - - {% if request.GET.q %} - - - - {% endif %} -
- +
+ +

+ {% trans "Accounts" %}

+
+
+
+ + + {% if request.GET.q %} + + + + {% endif %}
-
-{% if page_obj.object_list %} -
-
{{ _('JE Number') }} {{ _('Date') }}{{ tx.journal_entry.timestamp }} {% if tx.tx_type == 'debit' %} - {{ tx.amount }} + {{ tx.amount }} {% endif %} @@ -97,7 +97,7 @@ {% endfor %}
{{ _("Total") }}{{ _("Total") }} {{ total_debits }} {{ CURRENCY }} {{ total_credits }} {{ CURRENCY }}
- - - - - - - - - - - - - {% for account in accounts %} - - - - - - - - - + + + {% endfor %} + +
{% trans "Type" %}{% trans "Account Name" %}{% trans "Code" %}{% trans "Balance Type" %}{% trans "Active" %}
{{ account.role_bs|upper }}{{ account.name }}{{ account.code }} + {% if page_obj.object_list %} +
+ + - {% if account.balance_type == 'debit' %} -
{{ _("Debit") }}
- {% else %} -
{{ _("Credit") }}
- {% endif %} - + + + + + + + + + + + {% for account in accounts %} + + + + + + + + + + {% if account.balance_type == 'debit' %} +
{{ _("Debit") }}
+ {% else %} +
{{ _("Credit") }}
+ {% endif %} + + - + - {% empty %} - - - - {% endfor %} - -
{% trans "Type" %}{% trans "Account Name" %}{% trans "Code" %}{% trans "Balance Type" %}{% trans "Active" %}
{{ account.role_bs|upper }}{{ account.name }}{{ account.code }} - {% if account.active %} - - {% else %} - - {% endif %} - + {% if account.active %} + + {% else %} + + {% endif %} +
- - + +
+
- {% trans "No account found." %} -
-
+ {% empty %} +
+ {% trans "No account found." %} +
+
-
{{ page_obj.start_index }} {{ _("to") }} {{ page_obj.end_index }} {{ _("Items of")}} {{ page_obj.paginator.count }} -
+
{{ page_obj.start_index }} {{ _("to") }} {{ page_obj.end_index }} {{ _("Items of")}} {{ page_obj.paginator.count }} +
+ + {% if is_paginated %} + {% include 'partials/pagination.html' %} + {% endif %} + +
+
-{% if is_paginated %} - {% include 'partials/pagination.html' %} {% endif %} -
-
- - {% endif %} - {% endblock %} \ No newline at end of file diff --git a/templates/ledger/journal_entry/includes/card_invoice.html b/templates/ledger/journal_entry/includes/card_invoice.html index 028e7da0..cac95751 100644 --- a/templates/ledger/journal_entry/includes/card_invoice.html +++ b/templates/ledger/journal_entry/includes/card_invoice.html @@ -97,7 +97,7 @@ {% endif %}
+ {% endblock content %} \ No newline at end of file diff --git a/templates/plans/billing_info_create_or_update.html b/templates/plans/billing_info_create_or_update.html index 3ffc404b..2e7e673d 100644 --- a/templates/plans/billing_info_create_or_update.html +++ b/templates/plans/billing_info_create_or_update.html @@ -11,7 +11,7 @@ {% csrf_token %} {{ form|crispy }} {% if object %} - {{ _("Delete") }} + {{ _("Delete") }} {% endif %} - + + + - {% endblock %} diff --git a/templates/plans/create_order.html b/templates/plans/create_order.html index c4430c44..ace45179 100644 --- a/templates/plans/create_order.html +++ b/templates/plans/create_order.html @@ -29,43 +29,43 @@

{% trans "Invoice" %}

{% url "billing_info" as billing_info_url %} {% with billing_info_url|add:"?next="|add:request.get_full_path as billing_info_url %} - {% if billing_info %} -

- {% blocktrans %} - Invoice for this order will be issued for: - {% endblocktrans %} + {% if billing_info %} +

+ {% blocktrans %} + Invoice for this order will be issued for: + {% endblocktrans %} -

- {{ billing_info.name }}
- {{ billing_info.street }}
- {{ billing_info.zipcode }} - {{ billing_info.city }}, - {{ billing_info.country }} -

- {% trans "VAT ID" %} {{ billing_info.tax_number }} -
-

-

- {% blocktrans %} - If this data is not correct please edit billing data before - making an order. - {% endblocktrans %} -

- {% else %} - {% block invoice-alert %} -

- {% blocktrans %} - Invoice will not be issued. If you need an invoice please provide - billing data before making an order. - {% endblocktrans %} -

- {% endblock %} - {% endif %} +

+ {{ billing_info.name }}
+ {{ billing_info.street }}
+ {{ billing_info.zipcode }} + {{ billing_info.city }}, + {{ billing_info.country }} +

+ {% trans "VAT ID" %} {{ billing_info.tax_number }} +
+

+

+ {% blocktrans %} + If this data is not correct please edit billing data before + making an order. + {% endblocktrans %} +

+ {% else %} + {% block invoice-alert %} +

+ {% blocktrans %} + Invoice will not be issued. If you need an invoice please provide + billing data before making an order. + {% endblocktrans %} +

+ {% endblock %} + {% endif %} {% endwith %} - - {{ form|crispy }} - {% csrf_token %} + + {{ form|crispy }} + {% csrf_token %} {% endif %} diff --git a/templates/plans/current.html b/templates/plans/current.html index e796bd06..3d3d9f8e 100644 --- a/templates/plans/current.html +++ b/templates/plans/current.html @@ -2,49 +2,50 @@ {% load i18n custom_filters %} {% block content %} -
+
-
-
-
-
-
{% trans "Your Account" %}
-
-
-
-
-
- {% trans "Account" %} - {{ user.dealer.get_local_name }} +
+
+
+
+
{% trans "Your Account" %}
+
+
+
+
+
+ {% trans "Account" %} + {{ user.dealer.get_local_name }} +
-
-
-
- {% trans "Status" %} - {% if userplan.active %} - {% trans "Active" %} - {% else %} - {% trans "Expired" %} - {% endif %} +
+
+ {% trans "Status" %} + {% if userplan.active %} + {% trans "Active" %} + {% else %} + {% trans "Expired" %} + {% endif %} +
-
-
-
- {% trans "Active until" %} - {{ userplan.expire }} +
+
+ {% trans "Active until" %} + {{ userplan.expire }} +
-
-
-
- {% trans "Plan" %} -
- {{ userplan.plan }} - - {% trans "Upgrade" %} - +
+
+ {% trans "Plan" %} +
+ {{ userplan.plan }} + + {% trans "Upgrade" %} + +
@@ -52,20 +53,19 @@
-
-
-
-
-
-
{% trans "Plan Details" %}
-
-
- {% include "plans/plan_table.html" %} +
+
+
+
+
{% trans "Plan Details" %}
+
+
+ {% include "plans/plan_table.html" %} +
-
{% endblock %} \ No newline at end of file diff --git a/templates/plans/expiration_messages.html b/templates/plans/expiration_messages.html index c0f0c697..cd4206d6 100644 --- a/templates/plans/expiration_messages.html +++ b/templates/plans/expiration_messages.html @@ -1,31 +1,31 @@ {% load i18n %} {% block expiration_messages %} -{% if ACCOUNT_EXPIRED %} + {% if ACCOUNT_EXPIRED %} -
- {% blocktrans with url=EXTEND_URL %}Your account has expired. - Please extend your account.{% endblocktrans %} -
-{% else %} - - {% if ACCOUNT_NOT_ACTIVE %}
- {% blocktrans with url=ACTIVATE_URL %} - Your account is not active. Possibly you are over some limits. - Try to activate your account. - {% endblocktrans %} + {% blocktrans with url=EXTEND_URL %}Your account has expired. + Please extend your account.{% endblocktrans %}
- {% endif %} + {% else %} - {% if EXPIRE_IN_DAYS >= 0 and EXPIRE_IN_DAYS <= 14 %} -
- {% blocktrans with extend_url=EXTEND_URL days_to_expire=EXPIRE_IN_DAYS %} - Your account will expire soon (in {{ days_to_expire }} days). - We recommend to extend your account now. - {% endblocktrans %} -
- {% endif %} + {% if ACCOUNT_NOT_ACTIVE %} +
+ {% blocktrans with url=ACTIVATE_URL %} + Your account is not active. Possibly you are over some limits. + Try to activate your account. + {% endblocktrans %} +
+ {% endif %} -{% endif %} + {% if EXPIRE_IN_DAYS >= 0 and EXPIRE_IN_DAYS <= 14 %} +
+ {% blocktrans with extend_url=EXTEND_URL days_to_expire=EXPIRE_IN_DAYS %} + Your account will expire soon (in {{ days_to_expire }} days). + We recommend to extend your account now. + {% endblocktrans %} +
+ {% endif %} + + {% endif %} {% endblock %} diff --git a/templates/plans/extend.html b/templates/plans/extend.html index 5c21595a..e110b137 100644 --- a/templates/plans/extend.html +++ b/templates/plans/extend.html @@ -3,58 +3,58 @@ {% block seo_title %}user_plan{% endblock %} {% block extra_js %} - + {% endblock %} {% block content %} -
- {% csrf_token %} - {{ form.as_p }} + + {% csrf_token %} + {{ form.as_p }} -{% if userplan.plan.available %} -
    -
  • {% trans "Plan" %}: {{ userplan.plan.name }} -
  • {% trans "Quotas" %}: -
      - {% for quota in quotas %} -
    • {{ quota.quota.name }} ({{ quota.quota.description }}) - + {% if userplan.plan.available %} +
        +
      • {% trans "Plan" %}: {{ userplan.plan.name }} +
      • {% trans "Quotas" %}: +
          + {% for quota in quotas %} +
        • {{ quota.quota.name }} ({{ quota.quota.description }}) - - {% if quota.quota.is_boolean %} + {% if quota.quota.is_boolean %} - {% if quota.value %} {% trans "yes" %} {% else %} {% trans "no" %} {% endif %} + {% if quota.value %} {% trans "yes" %} {% else %} {% trans "no" %} {% endif %} - {% else %} - {{ quota.value }} {{ quota.quota.unit }} - {% endif %} - {% endfor %} -
        + {% else %} + {{ quota.value }} {{ quota.quota.unit }} + {% endif %} + {% endfor %} +
      -
    • {% trans "Pricings" %}: - -
    • -
    -{% else %} +
  • {% trans "Pricings" %}: + +
  • +
+ {% else %} - {% url 'upgrade_plan' as upgrade_url %} - {% blocktrans %} - Unfortunately your current plan is not available any more. You need to upgrade your plan. - {% endblocktrans %} + {% url 'upgrade_plan' as upgrade_url %} + {% blocktrans %} + Unfortunately your current plan is not available any more. You need to upgrade your plan. + {% endblocktrans %} -{% endif %} -
+ {% endif %} + {% endblock %} diff --git a/templates/plans/invoices/PL_EN.html b/templates/plans/invoices/PL_EN.html index 9a3003bd..01f677ef 100644 --- a/templates/plans/invoices/PL_EN.html +++ b/templates/plans/invoices/PL_EN.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} {% block title %}{{ invoice.full_number }}{% endblock %} {% block body %} -{% include 'plans/invoices/layout.html' %} + {% include 'plans/invoices/layout.html' %} {% endblock %} \ No newline at end of file diff --git a/templates/plans/invoices/invoice_base.html b/templates/plans/invoices/invoice_base.html index 172f2c16..47f240ae 100644 --- a/templates/plans/invoices/invoice_base.html +++ b/templates/plans/invoices/invoice_base.html @@ -1,83 +1,83 @@ - - {% block title %}{% endblock %} - - + - {% block head %}{% endblock %} + {% block head %}{% endblock %} - - -{% block body %}{% endblock %} - + + + {% block body %}{% endblock %} + \ No newline at end of file diff --git a/templates/plans/invoices/layout.html b/templates/plans/invoices/layout.html index b07d1752..39e53904 100644 --- a/templates/plans/invoices/layout.html +++ b/templates/plans/invoices/layout.html @@ -17,9 +17,9 @@
{% if copy %} {{ _("COPY") }} -{% else %} + {% else %} {{ _("ORIGINAL") }} -{% endif %} + {% endif %}
{{ _("Issued") }}: {{ invoice.issued|date:"F j, Y" }}
@@ -72,19 +72,19 @@ {% if invoice.shipping_name %} -
-
-
{{ _("Shipping Address")}}
+
+
+
{{ _("Shipping Address")}}
+
+
+
+ {{ invoice.shipping_name }}
+ {{ invoice.shipping_street }}
+ {{ invoice.shipping_zipcode }} {{ invoice.shipping_city }}
+ {{ invoice.buyer_country.name }} +
+
-
-
- {{ invoice.shipping_name }}
- {{ invoice.shipping_street }}
- {{ invoice.shipping_zipcode }} {{ invoice.shipping_city }}
- {{ invoice.buyer_country.name }} -
-
-
{% endif %} @@ -124,7 +124,7 @@ {% endif %} {{ invoice.total_net|floatformat:2 }} {{ CURRENCY }} {% if invoice.tax != None %}{{ invoice.tax|floatformat }}%{% else %}n/a{% endif %} - {% if invoice.tax_total != None %}{{ invoice.tax_total|floatformat:2 }} {{ CURRENCY }}{% else %}{{ _("n/a")}}{% endif %} + {% if invoice.tax_total != None %}{{ invoice.tax_total|floatformat:2 }} {{ CURRENCY }}{% else %}{{ _("n/a")}}{% endif %} {{ invoice.total|floatformat:2 }} {{ CURRENCY }} diff --git a/templates/plans/order_detail_table.html b/templates/plans/order_detail_table.html index 61f64ce0..cdd52d1b 100644 --- a/templates/plans/order_detail_table.html +++ b/templates/plans/order_detail_table.html @@ -1,40 +1,40 @@ {% load i18n %} {% block table %} -
- - - - - - - - - - {% if order.user %} - - - {% endif %} - - - - - - - - - - - - - - -
{% trans "Name" %}{% trans "Net price" %}{% trans "VAT" %}{% trans "VAT total" %}{% trans "Total" %}{% trans "Order completed" %}{% trans "Plan valid from" %}{% trans "Plan valid until" %}
{{ order.name }}{{ order.amount }} {{ order.currency }}{% if order.tax == None %}n/a{% else %}{{ order.tax }} %{% endif %}{% if order.tax_total == None %}n/a{% else %}{{ order.tax_total }} {{ order.currency }}{% endif %}{{ order.total }} {{ order.currency }}{{ order.completed|date|default:"-" }}{{ order.get_plan_extended_from|date|default:"-" }}{{ order.get_plan_extended_until|date|default:"-" }}
-
+
+ + + + + + + + + + {% if order.user %} + + + {% endif %} + + + + + + + + + + + + + + +
{% trans "Name" %}{% trans "Net price" %}{% trans "VAT" %}{% trans "VAT total" %}{% trans "Total" %}{% trans "Order completed" %}{% trans "Plan valid from" %}{% trans "Plan valid until" %}
{{ order.name }}{{ order.amount }} {{ order.currency }}{% if order.tax == None %}n/a{% else %}{{ order.tax }} %{% endif %}{% if order.tax_total == None %}n/a{% else %}{{ order.tax_total }} {{ order.currency }}{% endif %}{{ order.total }} {{ order.currency }}{{ order.completed|date|default:"-" }}{{ order.get_plan_extended_from|date|default:"-" }}{{ order.get_plan_extended_until|date|default:"-" }}
+
{% endblock %} {% if order.tax == None %} -

{% trans "EU VAT" %}

-
- {% blocktrans %} VAT is not applied to order. {% endblocktrans %} -
+

{% trans "EU VAT" %}

+
+ {% blocktrans %} VAT is not applied to order. {% endblocktrans %} +
{% endif %} diff --git a/templates/plans/order_list.html b/templates/plans/order_list.html index 90a81c3b..732d5195 100644 --- a/templates/plans/order_list.html +++ b/templates/plans/order_list.html @@ -4,50 +4,50 @@ {% block body %} {% block order_header %} -

{% trans "List of orders" %}

+

{% trans "List of orders" %}

{% endblock %} {% if object_list %} - {% block pagination_first %} - {% include "plans/pagination.html" %} - {% endblock %} + {% block pagination_first %} + {% include "plans/pagination.html" %} + {% endblock %} - {% block order_table %} -
- - - - - - - - - - - - - - - {% for order in object_list %} - - - - - - - - - - - {% endfor %} - -
ID{% trans 'Name' %}{% trans 'Created' context 'order created' %}{% trans 'Status' context 'order status' %}{% trans 'Completed' context 'order completed' %}{% trans 'Total' context 'total amount, value' %}{% trans 'Plan valid from' %}{% trans 'Plan valid until' %}
{{ order.pk }}{{ order.name }}{{ order.created|date }}{{ order.get_status_display }}{{ order.completed|date|default:"-" }}{{ order.total }} {{ CURRENCY }}{{ order.plan_extended_from|date|default:"-" }}{{ order.plan_extended_until|date|default:"-" }}
-
- {% endblock %} + {% block order_table %} +
+ + + + + + + + + + + + + + + {% for order in object_list %} + + + + + + + + + + + {% endfor %} + +
ID{% trans 'Name' %}{% trans 'Created' context 'order created' %}{% trans 'Status' context 'order status' %}{% trans 'Completed' context 'order completed' %}{% trans 'Total' context 'total amount, value' %}{% trans 'Plan valid from' %}{% trans 'Plan valid until' %}
{{ order.pk }}{{ order.name }}{{ order.created|date }}{{ order.get_status_display }}{{ order.completed|date|default:"-" }}{{ order.total }} {{ CURRENCY }}{{ order.plan_extended_from|date|default:"-" }}{{ order.plan_extended_until|date|default:"-" }}
+
+ {% endblock %} - {% block pagination_second %} - {% include "plans/pagination.html" %} - {% endblock %} + {% block pagination_second %} + {% include "plans/pagination.html" %} + {% endblock %} {% else %} {% blocktrans %}You do not have any orders so far.{% endblocktrans %} diff --git a/templates/plans/plan_table.html b/templates/plans/plan_table.html index 1eeb8444..144fa689 100644 --- a/templates/plans/plan_table.html +++ b/templates/plans/plan_table.html @@ -5,55 +5,55 @@ {% for plan in plan_list %} - - + {% endfor %} {% for quota_row in plan_table %} - - -
- {% if quota_row.0.url %}{% endif %} + + + - - {% for plan_quota in quota_row.1 %} - - {% if plan_quota != None %} - {% if quota_row.0.is_boolean %} - {% if plan_quota.value %} - - {% else %} - - {% endif %} - {% else %} - - {% if plan_quota.value == None %} - {% trans 'No Limit' %} - {% else %} - {{ plan_quota.value }} - {% if quota_row.0.unit %} - {{ quota_row.0.unit }} + {% if quota_row.0.url %}{% endif %} +
+ + {% for plan_quota in quota_row.1 %} + + {% if plan_quota != None %} + {% if quota_row.0.is_boolean %} + {% if plan_quota.value %} + + {% else %} + {% endif %} + {% else %} + + {% if plan_quota.value == None %} + {% trans 'No Limit' %} + {% else %} + {{ plan_quota.value }} + {% if quota_row.0.unit %} + {{ quota_row.0.unit }} + {% endif %} + {% endif %} + {% endif %} - - {% endif %} - {% endif %} - - {% endfor %} - + {% endif %} + + {% endfor %} + {% endfor %} @@ -65,78 +65,78 @@ {% if user.is_authenticated %} - - - {% for plan in plan_list %} - - {% if plan != userplan.plan and not userplan.is_expired and not userplan.plan.is_free %} - - {% trans "Change" %} - - {% endif %} - - {% endfor %} - + + + {% for plan in plan_list %} + + {% if plan != userplan.plan and not userplan.is_expired and not userplan.plan.is_free %} + + {% trans "Change" %} + + {% endif %} + + {% endfor %} + {% endif %} {% for plan in plan_list %} - - {% if plan.available %} -
- {% if not plan.is_free %} - {% for plan_pricing in plan.planpricing_set.all %} - {% if plan_pricing.visible %} -
- {% if plan_pricing.pricing.url %}{% endif %} + + {% if plan.available %} +
+ {% if not plan.is_free %} + {% for plan_pricing in plan.planpricing_set.all %} + {% if plan_pricing.visible %} +
+ {% if plan_pricing.pricing.url %}{% endif %}
{{ plan_pricing.pricing.name }} {{ plan_pricing.pricing.period }} {% trans "days" %}
- {% if plan_pricing.pricing.url %}
{% endif %} -
- {{ plan_pricing.price }} {{ CURRENCY }} - {% if plan_pricing.plan == userplan.plan or userplan.is_expired or userplan.plan.is_free %} - - {% trans "Buy" %} - - {% endif %} + {% if plan_pricing.pricing.url %}{% endif %} +
+ {{ plan_pricing.price }} {{ CURRENCY }} + {% if plan_pricing.plan == userplan.plan or userplan.is_expired or userplan.plan.is_free %} + + {% trans "Buy" %} + + {% endif %} +
-
- {% endif %} - {% endfor %} - {% else %} -
-
- {% trans "Free" %} - {% trans "no expiry" %} -
-
- 0 {{ CURRENCY }} - {% if plan != userplan.plan or userplan.is_expired %} - - {% if userplan.is_expired %} - {% trans "Select" %} - {% else %} - {% trans "Change" %} - {% endif %} - {% endif %} + {% endfor %} + {% else %} +
+
+ {% trans "Free" %} + {% trans "no expiry" %} +
+
+ 0 {{ CURRENCY }} + {% if plan != userplan.plan or userplan.is_expired %} + + {% if userplan.is_expired %} + {% trans "Select" %} + {% else %} + {% trans "Change" %} + {% endif %} + + {% endif %} +
-
- {% endif %} -
- {% else %} -
- {% url 'upgrade_plan' as upgrade_url %} - {% blocktrans %} -

This plan is no longer available.

- Upgrade to current plans → - {% endblocktrans %} -
- {% endif %} - + {% endif %} +
+ {% else %} +
+ {% url 'upgrade_plan' as upgrade_url %} + {% blocktrans %} +

This plan is no longer available.

+ Upgrade to current plans → + {% endblocktrans %} +
+ {% endif %} + {% endfor %} diff --git a/templates/pricing_page.html b/templates/pricing_page.html index 00b64564..49b36525 100644 --- a/templates/pricing_page.html +++ b/templates/pricing_page.html @@ -3,209 +3,209 @@ {% load custom_filters %} {% block customCSS %} - + - + .form-label { + font-weight: 500; + } + {% endblock customCSS %} {% block content %} -
-

{{ _("Choose Your Plan")}}

-
- {% csrf_token %} +
+

{{ _("Choose Your Plan")}}

+ + {% csrf_token %} -
-

1. {{ _("Select a Plan")}}

-
- {% for pp in plan_list %} -
- -