Merge branch 'main' of http://10.10.1.136:3000/ismail/haikal into frontend
This commit is contained in:
commit
6b56156921
@ -1,5 +1,3 @@
|
||||
import hashlib
|
||||
import json
|
||||
import requests
|
||||
|
||||
|
||||
|
||||
@ -1,3 +1,2 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@ -1,17 +1,15 @@
|
||||
from django.core.paginator import Paginator
|
||||
from django.http import JsonResponse
|
||||
from rest_framework import permissions, status, viewsets, generics
|
||||
from rest_framework import permissions, status, viewsets
|
||||
from inventory.utils import get_user_type
|
||||
from . import models, serializers
|
||||
from .services import get_car_data
|
||||
from inventory import models as inventory_models
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from inventory import models as inventory_models
|
||||
from inventory.services import get_make, get_model, decodevin
|
||||
from inventory.services import decodevin
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -1,3 +1,2 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
|
||||
@ -1,3 +1,2 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
|
||||
@ -7,7 +7,6 @@ from django_ledger import models as ledger_models
|
||||
from import_export.admin import ExportMixin
|
||||
from import_export.resources import ModelResource
|
||||
|
||||
from .models import Car
|
||||
|
||||
# # Define resource class
|
||||
# class CarSerieResource(ModelResource):
|
||||
|
||||
@ -5,7 +5,7 @@ class InventoryConfig(AppConfig):
|
||||
name = 'inventory'
|
||||
|
||||
def ready(self):
|
||||
import inventory.signals
|
||||
pass
|
||||
#from decimal import Decimal
|
||||
#from inventory.models import VatRate
|
||||
#VatRate.objects.get_or_create(rate=Decimal('0.15'), is_active=True)
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
import re
|
||||
from django.core.cache import cache
|
||||
from datetime import datetime
|
||||
from luhnchecker.luhn import Luhn
|
||||
from django.core.validators import RegexValidator
|
||||
from django.contrib.auth.models import Permission
|
||||
from appointment.models import Service
|
||||
from phonenumber_field.formfields import PhoneNumberField
|
||||
from django.core.validators import MinLengthValidator
|
||||
from django import forms
|
||||
from plans.models import PlanPricing
|
||||
@ -17,9 +14,6 @@ from .mixins import AddClassMixin
|
||||
from django_ledger.forms.invoice import (
|
||||
InvoiceModelCreateForm as InvoiceModelCreateFormBase,
|
||||
)
|
||||
from django_ledger.forms.estimate import (
|
||||
EstimateModelCreateForm as EstimateModelCreateFormBase,
|
||||
)
|
||||
|
||||
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
|
||||
from django_ledger.forms.journal_entry import JournalEntryModelCreateForm as JournalEntryModelCreateFormBase
|
||||
@ -1062,6 +1056,7 @@ class LeadForm(forms.ModelForm):
|
||||
"crn",
|
||||
"vrn",
|
||||
"year",
|
||||
"salary",
|
||||
"source",
|
||||
"channel",
|
||||
"staff",
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
import re
|
||||
from itertools import cycle
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
|
||||
def vin_year(vin_char: str) -> int:
|
||||
@ -1830,7 +1827,7 @@ def decode_vin_haikalna(vin):
|
||||
|
||||
pattern = r"^[A-HJ-NPR-Z0-9]{17}$"
|
||||
if not re.match(pattern, vin):
|
||||
raise Exception(f"VIN number must only contain alphanumeric symbols except 'I', 'O', and 'Q' ")
|
||||
raise Exception("VIN number must only contain alphanumeric symbols except 'I', 'O', and 'Q' ")
|
||||
|
||||
vin = vin.upper()
|
||||
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
import os
|
||||
import json
|
||||
import pymysql
|
||||
import pandas as pd
|
||||
from django.core.management.base import BaseCommand
|
||||
from sqlalchemy import create_engine
|
||||
from tqdm import tqdm # Progress bar support
|
||||
from django.conf import settings
|
||||
|
||||
# Database connection details
|
||||
db_config = {
|
||||
|
||||
@ -11,19 +11,19 @@ class Command(BaseCommand):
|
||||
def handle(self, *args, **kwargs):
|
||||
vin,description = self.generate_vin()
|
||||
result = decodevin(vin)
|
||||
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS(f'Generated VIN: {vin}'))
|
||||
self.stdout.write(self.style.SUCCESS(f'Description: {description}'))
|
||||
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS(f'Decoded VIN: {result}'))
|
||||
make,model,year_model = result.values()
|
||||
self.stdout.write(self.style.SUCCESS(f'VIN: {vin} - Make {make} - Model {model} - Model Year {year_model}'))
|
||||
m = get_model(model)
|
||||
self.stdout.write(self.style.SUCCESS(f'Make: {m.id_car_make} - Model: {m}'))
|
||||
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
|
||||
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# management/commands/create_plans.py
|
||||
from django.core.management.base import BaseCommand
|
||||
from plans.models import Plan, Quota, PlanQuota, Pricing, PlanPricing
|
||||
from plans.models import Plan, Quota, Pricing, PlanPricing
|
||||
from decimal import Decimal
|
||||
from django.db.models import Q
|
||||
|
||||
|
||||
@ -1,12 +1,7 @@
|
||||
# management/commands/create_plans.py
|
||||
from decimal import Decimal
|
||||
from datetime import timedelta
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
from plans.quota import get_user_quota
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.management.base import BaseCommand
|
||||
from plans.models import Plan, Quota, PlanQuota, Pricing, PlanPricing,UserPlan,Order,BillingInfo,AbstractOrder
|
||||
from plans.models import Plan, Quota, PlanQuota, Pricing, PlanPricing
|
||||
class Command(BaseCommand):
|
||||
help = 'Create basic subscription plans structure'
|
||||
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.core.mail import send_mail
|
||||
from allauth.account.models import EmailConfirmation
|
||||
from inventory.tasks import send_email
|
||||
from django.contrib.auth import get_user_model
|
||||
import re
|
||||
from inventory.tasks import create_coa_accounts
|
||||
from inventory.models import Dealer
|
||||
|
||||
|
||||
@ -1,12 +1,6 @@
|
||||
import logging
|
||||
from django.conf import settings
|
||||
from inventory import models
|
||||
from django.utils import timezone
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from fpdf import FPDF
|
||||
import os
|
||||
|
||||
from inventory.utils import get_user_type
|
||||
|
||||
@ -67,7 +61,7 @@ class InjectParamsMiddleware:
|
||||
try:
|
||||
# request.entity = request.user.dealer.entity
|
||||
request.dealer = get_user_type(request)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
response = self.get_response(request)
|
||||
return response
|
||||
@ -98,7 +92,7 @@ class InjectDealerMiddleware:
|
||||
request.is_dealer = True
|
||||
if hasattr(request.user, "staffmember"):
|
||||
request.is_staff = True
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
response = self.get_response(request)
|
||||
return response
|
||||
|
||||
18
inventory/migrations/0006_organization_slug.py
Normal file
18
inventory/migrations/0006_organization_slug.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.7 on 2025-05-21 10:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0005_notes_dealer'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='organization',
|
||||
name='slug',
|
||||
field=models.SlugField(blank=True, editable=False, max_length=255, null=True, unique=True),
|
||||
),
|
||||
]
|
||||
23
inventory/migrations/0007_staff_active_staff_slug.py
Normal file
23
inventory/migrations/0007_staff_active_staff_slug.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.1.7 on 2025-05-21 13:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0006_organization_slug'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='staff',
|
||||
name='active',
|
||||
field=models.BooleanField(default=True, verbose_name='Active'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='staff',
|
||||
name='slug',
|
||||
field=models.SlugField(blank=True, editable=False, max_length=255, null=True, unique=True),
|
||||
),
|
||||
]
|
||||
18
inventory/migrations/0008_lead_salary.py
Normal file
18
inventory/migrations/0008_lead_salary.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.7 on 2025-05-21 15:26
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0007_staff_active_staff_slug'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='lead',
|
||||
name='salary',
|
||||
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Salary'),
|
||||
),
|
||||
]
|
||||
@ -1,6 +1,4 @@
|
||||
from django import forms
|
||||
from django.utils.translation import get_language
|
||||
from django.urls import reverse, reverse_lazy
|
||||
|
||||
class AddClassMixin:
|
||||
"""
|
||||
|
||||
@ -3,7 +3,7 @@ from django.contrib.auth.models import Permission
|
||||
from decimal import Decimal
|
||||
from django.utils.text import slugify
|
||||
from django.utils import timezone
|
||||
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||
from django.core.validators import MinValueValidator
|
||||
import hashlib
|
||||
from django.db import models
|
||||
from datetime import timedelta
|
||||
@ -23,12 +23,12 @@ from django.contrib.auth.models import Group
|
||||
|
||||
from inventory.utils import get_user_type, to_dict
|
||||
from .mixins import LocalizedNameMixin
|
||||
from django_ledger.models import EntityModel, ItemModel,EstimateModel,InvoiceModel,AccountModel,EntityManagementModel
|
||||
from django_ledger.models import EstimateModel,InvoiceModel,AccountModel,EntityManagementModel
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from appointment.models import StaffMember
|
||||
from plans.quota import get_user_quota
|
||||
from plans.models import UserPlan,Quota,PlanQuota
|
||||
from plans.models import UserPlan
|
||||
# from plans.models import AbstractPlan
|
||||
# from simple_history.models import HistoricalRecords
|
||||
|
||||
@ -548,7 +548,7 @@ class Car(Base):
|
||||
def ready(self):
|
||||
try:
|
||||
return all([self.colors ,self.finances,])
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
return False
|
||||
def get_transfer(self):
|
||||
return self.transfer_logs.filter(active=True).first()
|
||||
@ -1000,11 +1000,37 @@ class Staff(models.Model, LocalizedNameMixin):
|
||||
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
|
||||
phone_number = PhoneNumberField(region="SA", verbose_name=_("Phone Number"))
|
||||
staff_type = models.CharField(choices=StaffTypes.choices, max_length=255, verbose_name=_("Staff Type"))
|
||||
active = models.BooleanField(default=True, verbose_name=_("Active"))
|
||||
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
|
||||
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
|
||||
slug = models.SlugField(max_length=255, unique=True, editable=False, null=True, blank=True)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.slug:
|
||||
base_slug = slugify(f"{self.name}")
|
||||
self.slug = base_slug
|
||||
counter = 1
|
||||
|
||||
while self.__class__.objects.filter(slug=self.slug).exclude(pk=self.pk).exists():
|
||||
self.slug = f"{base_slug}-{counter}"
|
||||
counter += 1
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
objects = StaffUserManager()
|
||||
|
||||
def deactivate_account(self):
|
||||
self.active = False
|
||||
self.user.is_active = False
|
||||
self.user.save()
|
||||
self.save()
|
||||
def activate_account(self):
|
||||
self.active = True
|
||||
self.user.is_active = True
|
||||
self.user.save()
|
||||
self.save()
|
||||
def permenant_delete(self):
|
||||
# self.user.delete()
|
||||
self.staff_member.delete()
|
||||
self.delete()
|
||||
@property
|
||||
def email(self):
|
||||
return self.staff_member.user.email
|
||||
@ -1256,7 +1282,17 @@ class Customer(models.Model):
|
||||
self.customer_model.save()
|
||||
self.user.save()
|
||||
self.save()
|
||||
|
||||
def activate_account(self):
|
||||
self.active = True
|
||||
self.customer_model.active = True
|
||||
self.user.is_active = True
|
||||
self.customer_model.save()
|
||||
self.user.save()
|
||||
self.save()
|
||||
def permenant_delete(self):
|
||||
self.customer_model.delete()
|
||||
self.user.delete()
|
||||
self.delete()
|
||||
class Organization(models.Model, LocalizedNameMixin):
|
||||
dealer = models.ForeignKey(
|
||||
Dealer, on_delete=models.CASCADE, related_name="organizations"
|
||||
@ -1282,6 +1318,18 @@ class Organization(models.Model, LocalizedNameMixin):
|
||||
active = models.BooleanField(default=True, verbose_name=_("Active"))
|
||||
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
|
||||
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
|
||||
slug = models.SlugField(max_length=255, unique=True, editable=False, null=True, blank=True)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.slug:
|
||||
base_slug = slugify(f"{self.name}")
|
||||
self.slug = base_slug
|
||||
counter = 1
|
||||
|
||||
while self.__class__.objects.filter(slug=self.slug).exclude(pk=self.pk).exists():
|
||||
self.slug = f"{base_slug}-{counter}"
|
||||
counter += 1
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Organization")
|
||||
@ -1348,6 +1396,17 @@ class Organization(models.Model, LocalizedNameMixin):
|
||||
self.user.save()
|
||||
self.customer_model.save()
|
||||
self.save()
|
||||
def activate_account(self):
|
||||
self.active = True
|
||||
self.customer_model.active = True
|
||||
self.user.is_active = True
|
||||
self.customer_model.save()
|
||||
self.user.save()
|
||||
self.save()
|
||||
def permenant_delete(self):
|
||||
self.user.delete()
|
||||
self.customer_model.delete()
|
||||
self.delete()
|
||||
|
||||
class Representative(models.Model, LocalizedNameMixin):
|
||||
dealer = models.ForeignKey(
|
||||
@ -1447,7 +1506,6 @@ class Lead(models.Model):
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
|
||||
next_action_date = models.DateTimeField(
|
||||
verbose_name=_("Next Action Date"),
|
||||
blank=True,
|
||||
@ -1455,6 +1513,7 @@ class Lead(models.Model):
|
||||
)
|
||||
is_converted = models.BooleanField(default=False)
|
||||
converted_at = models.DateTimeField(null=True, blank=True)
|
||||
salary = models.PositiveIntegerField(verbose_name=_("Salary"), blank=True, null=True)
|
||||
created = models.DateTimeField(
|
||||
auto_now_add=True, verbose_name=_("Created"), db_index=True
|
||||
)
|
||||
@ -1548,7 +1607,6 @@ class Lead(models.Model):
|
||||
return Activity.objects.filter(dealer=self.dealer,content_type__model="lead", object_id=self.pk).order_by('-updated').first()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.status = self.get_status()
|
||||
if not self.slug:
|
||||
base_slug = slugify(f"{self.last_name} {self.first_name}")
|
||||
self.slug = base_slug
|
||||
@ -1882,7 +1940,13 @@ class Vendor(models.Model, LocalizedNameMixin):
|
||||
balance_type="credit",
|
||||
active=True
|
||||
)
|
||||
|
||||
def activate_account(self):
|
||||
self.active = True
|
||||
self.vendor_model.active = True
|
||||
self.save()
|
||||
def permenant_delete(self):
|
||||
self.vendor_model.delete()
|
||||
self.delete()
|
||||
class Payment(models.Model):
|
||||
METHOD_CHOICES = [
|
||||
("cash", _("cash")),
|
||||
@ -2034,7 +2098,7 @@ class CustomGroup(models.Model):
|
||||
try:
|
||||
for perm in Permission.objects.filter(content_type__app_label="inventory"):
|
||||
self.add_permission(perm)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def set_default_permissions(self):
|
||||
|
||||
@ -5,14 +5,10 @@ Services module
|
||||
import requests
|
||||
import json
|
||||
|
||||
from django_ledger.models import EntityModel
|
||||
|
||||
from inventory.utils import get_jwt_token, get_user_type
|
||||
from pyvin import VIN
|
||||
from django.conf import settings
|
||||
from openai import OpenAI
|
||||
from .models import Car,CarMake,CarModel
|
||||
from inventory.haikalna import decode_vin_haikalna
|
||||
from .models import CarMake
|
||||
|
||||
|
||||
def get_make(item):
|
||||
|
||||
@ -1,33 +1,20 @@
|
||||
from inventory.tasks import create_coa_accounts,create_accounts_for_make,create_settings
|
||||
from inventory.tasks import create_coa_accounts
|
||||
from django.contrib.auth.models import Group
|
||||
from decimal import Decimal
|
||||
from django.db.models.signals import post_save, post_delete, pre_delete, pre_save
|
||||
from inventory.models import VatRate
|
||||
from plans.quota import get_user_quota
|
||||
from .utils import to_dict
|
||||
from django.db.models.signals import post_save, post_delete
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.contrib.auth import get_user_model
|
||||
from django_ledger.io import roles
|
||||
from django_ledger.models import (
|
||||
EntityModel,
|
||||
AccountModel,
|
||||
ItemModel,
|
||||
ItemModelAbstract,
|
||||
UnitOfMeasureModel,
|
||||
VendorModel,
|
||||
EstimateModel,
|
||||
CustomerModel,
|
||||
JournalEntryModel,
|
||||
TransactionModel,
|
||||
LedgerModel,
|
||||
BillModel,
|
||||
ItemTransactionModel
|
||||
LedgerModel
|
||||
)
|
||||
from . import models
|
||||
from django.utils.timezone import now
|
||||
from django.db import transaction
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@ -2,7 +2,7 @@ from django.conf import settings
|
||||
from django.utils.timesince import timesince
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from .models import Car, CarFinance, ExteriorColors, InteriorColors, CarColors
|
||||
from .models import Car
|
||||
from .utils import get_local_name
|
||||
from django.utils.html import format_html
|
||||
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
from time import sleep
|
||||
from datetime import datetime
|
||||
from django.db import transaction
|
||||
from django_ledger.io import roles
|
||||
from django.core.mail import send_mail
|
||||
from background_task import background
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from inventory.models import DealerSettings,CarMake,Dealer
|
||||
from inventory.models import DealerSettings,Dealer
|
||||
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ from django.urls import reverse
|
||||
from django.utils.formats import number_format
|
||||
from django_ledger.io.io_core import get_localdate,validate_activity
|
||||
from django.conf import settings
|
||||
from django.utils.translation import get_language
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@ -7,19 +7,16 @@
|
||||
# """
|
||||
|
||||
from calendar import month_abbr
|
||||
from random import randint
|
||||
|
||||
from django import template
|
||||
from django.db.models import Sum
|
||||
from django.urls import reverse
|
||||
from django.utils.formats import number_format
|
||||
from decimal import Decimal
|
||||
|
||||
# from django_ledger import __version__
|
||||
# from django_ledger.forms.app_filters import EntityFilterForm, ActivityFilterForm
|
||||
# from django_ledger.forms.feedback import BugReportForm, RequestNewFeatureForm
|
||||
# from django_ledger.io import CREDIT, DEBIT, ROLES_ORDER_ALL
|
||||
from django_ledger.io.io_core import validate_activity, get_localdate
|
||||
from django_ledger.io.io_core import get_localdate
|
||||
# from django_ledger.models import TransactionModel, BillModel, InvoiceModel, EntityUnitModel
|
||||
# from django_ledger.settings import (
|
||||
# DJANGO_LEDGER_FINANCIAL_ANALYSIS, DJANGO_LEDGER_CURRENCY_SYMBOL,
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import json
|
||||
from . import models as m
|
||||
from datetime import datetime
|
||||
from django.urls import reverse
|
||||
from django_ledger import models as lm
|
||||
from django.test import Client, TestCase
|
||||
from django.contrib.auth import get_user_model
|
||||
from django_ledger.io.io_core import get_localdate
|
||||
|
||||
@ -3,7 +3,6 @@ from django.urls import path
|
||||
from django_tables2.export.export import TableExport
|
||||
|
||||
from . import views
|
||||
from allauth.account import views as allauth_views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
@ -395,12 +394,12 @@ path(
|
||||
# ),
|
||||
|
||||
# Users URLs
|
||||
path("user/create/", views.UserCreateView.as_view(), name="user_create"),
|
||||
path("user/<int:pk>/update/", views.UserUpdateView.as_view(), name="user_update"),
|
||||
path("user/<int:pk>/", views.UserDetailView.as_view(), name="user_detail"),
|
||||
path("user/", views.UserListView.as_view(), name="user_list"),
|
||||
path("user/<int:pk>/confirm/", views.UserDeleteview, name="user_delete"),
|
||||
path("user/<int:pk>/groups/", views.UserGroupView, name="user_groups"),
|
||||
path("user/create/", views.UserCreateView.as_view(), name="user_create"),
|
||||
path("user/<slug:slug>/", views.UserDetailView.as_view(), name="user_detail"),
|
||||
path("user/<slug:slug>/groups/", views.UserGroupView, name="user_groups"),
|
||||
path("user/<slug:slug>/update/", views.UserUpdateView.as_view(), name="user_update"),
|
||||
path("user/<slug:slug>/confirm/", views.UserDeleteview, name="user_delete"),
|
||||
# Group URLs
|
||||
path("group/create/", views.GroupCreateView.as_view(), name="group_create"),
|
||||
path("group/<int:pk>/update/", views.GroupUpdateView.as_view(), name="group_update"),
|
||||
@ -409,26 +408,26 @@ path(
|
||||
path("group/<int:pk>/confirm/", views.GroupDeleteview, name="group_delete"),
|
||||
path("group/<int:pk>/permission/", views.GroupPermissionView, name="group_permission"),
|
||||
# Organization URLs
|
||||
path(
|
||||
"organizations/", views.OrganizationListView.as_view(), name="organization_list"
|
||||
),
|
||||
path(
|
||||
"organizations/<int:pk>/",
|
||||
views.OrganizationDetailView.as_view(),
|
||||
name="organization_detail",
|
||||
),
|
||||
path(
|
||||
"organizations/create/",
|
||||
views.OrganizationCreateView.as_view(),
|
||||
name="organization_create",
|
||||
),
|
||||
path(
|
||||
"organizations/<int:pk>/update/",
|
||||
"organizations/", views.OrganizationListView.as_view(), name="organization_list"
|
||||
),
|
||||
path(
|
||||
"organizations/<slug:slug>/",
|
||||
views.OrganizationDetailView.as_view(),
|
||||
name="organization_detail",
|
||||
),
|
||||
path(
|
||||
"organizations/<slug:slug>/update/",
|
||||
views.OrganizationUpdateView.as_view(),
|
||||
name="organization_update",
|
||||
),
|
||||
path(
|
||||
"organizations/<int:pk>/delete/",
|
||||
"organizations/<slug:slug>/delete/",
|
||||
views.OrganizationDeleteView,
|
||||
name="organization_delete",
|
||||
),
|
||||
@ -802,6 +801,11 @@ path(
|
||||
path('entity/<slug:entity_slug>/data/pnl/',
|
||||
views.PnLAPIView.as_view(),
|
||||
name='entity-json-pnl'),
|
||||
# Admin Management...
|
||||
path('management/', views.management_view, name='management'),
|
||||
path('management/user_management/', views.user_management, name='user_management'),
|
||||
path('management/<str:content_type>/<slug:slug>/activate_account/', views.activate_account, name='activate_account'),
|
||||
path('management/<str:content_type>/<slug:slug>/permenant_delete_account/', views.permenant_delete_account, name='permenant_delete_account'),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
|
||||
from decimal import Decimal
|
||||
from django.conf import settings
|
||||
from inventory import models
|
||||
from django_ledger.models.items import ItemModel
|
||||
def calculate_vat(value):
|
||||
"""Helper to calculate VAT dynamically for a given value."""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
||||
import pymysql
|
||||
from sqlalchemy import create_engine
|
||||
import pandas as pd
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
|
||||
from vininfo.utils import merge_wmi
|
||||
from vininfo.dicts import WMI
|
||||
|
||||
|
||||
wmi_manufacturer_mapping = {
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
import json
|
||||
import requests
|
||||
from django.urls import reverse
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from inventory.models import PaymentHistory,Notification
|
||||
from plans.models import Order, PlanPricing,AbstractOrder
|
||||
from inventory.models import Notification
|
||||
|
||||
def run():
|
||||
user = User.objects.first()
|
||||
|
||||
@ -1,41 +1,13 @@
|
||||
from django_ledger.forms.account import AccountModelUpdateForm, AccountModelCreateForm
|
||||
import requests
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import Group
|
||||
from django_ledger.models.invoice import InvoiceModel
|
||||
from django_ledger.utils import accruable_net_summary
|
||||
from decimal import Decimal
|
||||
from django_ledger.models import (
|
||||
EstimateModel,
|
||||
EntityModel,
|
||||
ItemModel,
|
||||
ItemTransactionModel,
|
||||
AccountModel,
|
||||
CustomerModel,
|
||||
EntityManagementModel,
|
||||
)
|
||||
# from rich import print
|
||||
from datetime import date
|
||||
from inventory.models import (
|
||||
Car,
|
||||
Dealer,
|
||||
VatRate,
|
||||
Lead,
|
||||
CarMake,
|
||||
CarModel,
|
||||
Schedule,
|
||||
CustomGroup,
|
||||
)
|
||||
from inventory.utils import CarFinanceCalculator
|
||||
from appointment.models import Appointment, AppointmentRequest, Service, StaffMember
|
||||
from appointment.models import Appointment, AppointmentRequest, Service, StaffMember
|
||||
from django.contrib.auth import get_user_model
|
||||
from django_ledger.io.io_core import get_localdate
|
||||
from datetime import datetime, timedelta
|
||||
from django.utils import timezone
|
||||
import hashlib
|
||||
from django_ledger.io import roles
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@ -1,23 +1,8 @@
|
||||
from django_ledger.forms.account import AccountModelUpdateForm,AccountModelCreateForm
|
||||
import requests
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import Group
|
||||
from django_ledger.models.invoice import InvoiceModel
|
||||
from django_ledger.utils import accruable_net_summary
|
||||
from decimal import Decimal
|
||||
from django_ledger.models import EstimateModel,EntityModel,ItemModel,ItemTransactionModel,AccountModel,CustomerModel,EntityManagementModel
|
||||
from django_ledger.models import EntityModel
|
||||
# from rich import print
|
||||
from datetime import date
|
||||
from inventory.models import Car, Dealer, VatRate,Lead,CarMake,CarModel,Schedule,CustomGroup
|
||||
from inventory.utils import CarFinanceCalculator
|
||||
from appointment.models import Appointment,AppointmentRequest,Service,StaffMember
|
||||
from inventory.models import CarMake
|
||||
from django.contrib.auth import get_user_model
|
||||
from django_ledger.io.io_core import get_localdate
|
||||
from datetime import datetime, timedelta
|
||||
from django.utils import timezone
|
||||
import hashlib
|
||||
from django_ledger.io import roles
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@ -1,24 +1,9 @@
|
||||
from django_ledger.forms.account import AccountModelUpdateForm,AccountModelCreateForm
|
||||
import requests
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import Group
|
||||
from django_ledger.models.invoice import InvoiceModel
|
||||
from django_ledger.utils import accruable_net_summary
|
||||
from decimal import Decimal
|
||||
from django_ledger.models import EstimateModel,EntityModel,ItemModel,ItemTransactionModel,AccountModel,CustomerModel,EntityManagementModel
|
||||
from rich import print
|
||||
from datetime import date
|
||||
from inventory.models import Car, Dealer, VatRate,Lead,CarMake,CarModel,Schedule,CustomGroup
|
||||
from inventory.models import Car
|
||||
from inventory.utils import CarFinanceCalculator
|
||||
from appointment.models import Appointment,AppointmentRequest,Service,StaffMember
|
||||
from django.contrib.auth import get_user_model
|
||||
from django_ledger.io.io_core import get_localdate
|
||||
from datetime import datetime, timedelta
|
||||
from django.utils import timezone
|
||||
import hashlib
|
||||
from django_ledger.io import roles
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
17
templates/admin_management/confirm_activate_account.html
Normal file
17
templates/admin_management/confirm_activate_account.html
Normal file
@ -0,0 +1,17 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="d-flex justify-content-center align-items-center mt-10">
|
||||
<div class="text-center">
|
||||
<h1>Activate Account</h1>
|
||||
<p>Are you sure you want to activate this account "{{ obj.email }}"?</p>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<div class="d-flex justify-content-center">
|
||||
<button class="btn btn-primary mx-2" type="submit">Activate</button>
|
||||
<a class="btn btn-secondary mx-2" href="{% url 'user_management' %}">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
16
templates/admin_management/management.html
Normal file
16
templates/admin_management/management.html
Normal file
@ -0,0 +1,16 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<h1><i class="fas fa-tools me-2"></i>Admin Management</h1>
|
||||
<div class="row row-cols-1 row-cols-md-4 g-4 mt-10">
|
||||
<div class="col">
|
||||
<a href="{% url 'user_management' %}">
|
||||
<div class="card h-100">
|
||||
<div class="card-header text-center">
|
||||
<h5 class="card-title">User Management</h5>
|
||||
<span style="font-size: 2rem; font-weight: 500;" class="me-2"><i class="fas fa-user"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
18
templates/admin_management/permenant_delete_account.html
Normal file
18
templates/admin_management/permenant_delete_account.html
Normal file
@ -0,0 +1,18 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="d-flex justify-content-center align-items-center mt-10">
|
||||
<div class="text-center">
|
||||
<h1 class="display-4">Delete Account</h1>
|
||||
<p class="lead">Are you sure you want to delete this account "{{ obj.email }}"? This will delete all associated information for this user.</p>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<div class="d-flex justify-content-center">
|
||||
<button class="btn btn-danger mx-2" type="submit"><i class="fas fa-trash me-2"></i> Delete Permenantly</button>
|
||||
<a class="btn btn-secondary mx-2" href="{% url 'user_management' %}"><i class="fas fa-ban me-2"></i>Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
243
templates/admin_management/user_management.html
Normal file
243
templates/admin_management/user_management.html
Normal file
@ -0,0 +1,243 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static humanize %}
|
||||
|
||||
{% block title %}
|
||||
{% trans 'User Management' %}
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<section class="pt-5 pb-9">
|
||||
<div class="row">
|
||||
<h2 class="mb-4">{% trans 'User Management' %}</h2>
|
||||
<div class="row g-3 justify-content-between mb-4">
|
||||
<div class="col-12">
|
||||
<h3 class="mb-3">{% trans 'Customers' %}</h3>
|
||||
<div class="table-responsive scrollbar mx-n1 px-1">
|
||||
<table class="table table-hover fs-9 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('First Name') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Last Name') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Email') }}</th>
|
||||
<th class="sort align-middle ps-4 pe-5 text-uppercase border-end border-translucent" scope="col" style="width:15%;">{{ _('Status') }}</th>
|
||||
<th class="sort align-middle ps-4 pe-5 text-uppercase" scope="col" style="width:15%;">{{ _('Created date') }}</th>
|
||||
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _('Actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="leal-tables-body">
|
||||
{% for customer in customers %}
|
||||
<tr>
|
||||
<td class="ps-0">{{ customer.first_name }}</td>
|
||||
<td class="ps-0">{{ customer.last_name }}</td>
|
||||
<td class="ps-0">{{ customer.email }}</td>
|
||||
<td class="ps-0">
|
||||
{% if customer.active %}
|
||||
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }}
|
||||
{% else %}
|
||||
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="ps-0">{{ customer.created|naturalday|capfirst }}</td>
|
||||
<td class="align-middle white-space-nowrap text-end">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button
|
||||
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-boundary="window"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
data-bs-reference="parent">
|
||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a href="{% url 'activate_account' 'customer' customer.slug %}"><button class="dropdown-item">{% trans "Activate" %}</button></a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{% url 'permenant_delete_account' 'customer' customer.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<td colspan="6" class="text-center">{% trans 'No data available in table' %}</td>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-5">
|
||||
<div class="col-12">
|
||||
<h3 class="mb-3">{% trans 'Organizations' %}</h3>
|
||||
<div class="table-responsive scrollbar mx-n1 px-1">
|
||||
<table class="table table-hover fs-9 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Name') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Arabic Name') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Email') }}</th>
|
||||
<th class="sort align-middle ps-4 pe-5 text-uppercase border-end border-translucent" scope="col" style="width:15%;">{{ _('Status') }}</th>
|
||||
<th class="sort align-middle ps-4 pe-5 text-uppercase" scope="col" style="width:15%;">{{ _('Create date') }}</th>
|
||||
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _('Actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="leal-tables-body">
|
||||
{% for organization in organizations %}
|
||||
<tr>
|
||||
<td class="ps-0">{{ organization.name }}</td>
|
||||
<td class="ps-0">{{ organization.arabic_name }}</td>
|
||||
<td class="ps-0">{{ organization.email }}</td>
|
||||
<td class="ps-0">
|
||||
{% if customer.active %}
|
||||
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }}
|
||||
{% else %}
|
||||
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="ps-0">{{ organization.created|naturalday|capfirst }}</td>
|
||||
<td class="align-middle white-space-nowrap text-end">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button
|
||||
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-boundary="window"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
data-bs-reference="parent">
|
||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a href="{% url 'activate_account' 'organization' organization.slug %}"><button class="dropdown-item">{% trans "Activate" %}</button></a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{% url 'permenant_delete_account' 'organization' organization.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<td colspan="6" class="text-center">{% trans 'No data available in table' %}</td>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-5">
|
||||
<div class="col-12">
|
||||
<h3 class="mb-3">{% trans 'Vendors' %}</h3>
|
||||
<div class="table-responsive scrollbar mx-n1 px-1">
|
||||
<table class="table table-hover fs-9 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Name') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Arabic Name') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Email') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:15%;">{{ _('Status') }}</th>
|
||||
<th class="sort align-middle ps-4 pe-5 text-uppercase" scope="col" style="width:15%;">{{ _('Create date') }}</th>
|
||||
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _('Actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="leal-tables-body">
|
||||
{% for vendor in vendors %}
|
||||
<tr>
|
||||
<td class="ps-0">{{ vendor.name }}</td>
|
||||
<td class="ps-0">{{ vendor.arabic_name }}</td>
|
||||
<td class="ps-0">{{ vendor.email }}</td>
|
||||
<td class="ps-0">
|
||||
{% if customer.active %}
|
||||
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }}
|
||||
{% else %}
|
||||
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="ps-0">{{ vendor.created_at|naturalday|capfirst }}</td>
|
||||
<td class="align-middle white-space-nowrap text-end">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button
|
||||
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-boundary="window"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
data-bs-reference="parent">
|
||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a href="{% url 'activate_account' 'vendor' vendor.slug %}"><button class="dropdown-item">{% trans "Activate" %}</button></a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{% url 'permenant_delete_account' 'vendor' vendor.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<td colspan="6" class="text-center">{% trans 'No data available in table' %}</td>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-5">
|
||||
<div class="col-12">
|
||||
<h3 class="mb-3">{% trans 'Staff' %}</h3>
|
||||
<div class="table-responsive scrollbar mx-n1 px-1">
|
||||
<table class="table table-hover fs-9 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Name') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Arabic Name') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Email') }}</th>
|
||||
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:15%;">{{ _('Status') }}</th>
|
||||
<th class="sort align-middle ps-4 pe-5 text-uppercase" scope="col" style="width:15%;">{{ _('Create date') }}</th>
|
||||
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _('Actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="leal-tables-body">
|
||||
{% for obj in staff %}
|
||||
<tr>
|
||||
<td class="ps-0">{{ obj.name }}</td>
|
||||
<td class="ps-0">{{ obj.arabic_name }}</td>
|
||||
<td class="ps-0">{{ obj.email }}</td>
|
||||
<td class="ps-0">
|
||||
{% if obj.active %}
|
||||
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }}
|
||||
{% else %}
|
||||
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="ps-0">{{ obj.created|naturalday|capfirst }}</td>
|
||||
<td class="align-middle white-space-nowrap text-end">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button
|
||||
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-boundary="window"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
data-bs-reference="parent">
|
||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a href="{% url 'activate_account' 'staff' obj.slug %}"><button class="dropdown-item">{% trans "Activate" %}</button></a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{% url 'permenant_delete_account' 'staff' obj.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<td colspan="6" class="text-center">{% trans 'No data available in table' %}</td>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
@ -130,14 +130,16 @@
|
||||
<h5 class="text-body-highlight mb-0 text-end">{{ _("Status")}}
|
||||
{% if lead.status == "new" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-primary"><span class="badge-label">{{_("New")}}</span><span class="fa fa-bell ms-1"></span></span>
|
||||
{% elif lead.status == "pending" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-warning"><span class="badge-label">{{_("Pending")}}</span><span class="fa fa-clock-o ms-1"></span></span>
|
||||
{% elif lead.status == "in_progress" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-info"><span class="badge-label">{{_("In Progress")}}</span><span class="fa fa-wrench ms-1"></span></span>
|
||||
{% elif lead.status == "qualified" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-success"><span class="badge-label">{{_("Qualified")}}</span><span class="fa fa-check ms-1"></span></span>
|
||||
{% elif lead.status == "canceled" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-danger"><span class="badge-label">{{_("Canceled")}}</span><span class="fa fa-times ms-1"></span></span>
|
||||
{% elif lead.status == "follow_up" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-warning"><span class="badge-label">{{_("Follow Up")}}</span><span class="fa fa-clock-o ms-1"></span></span>
|
||||
{% elif lead.status == "negotiation" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-info"><span class="badge-label">{{_("Negotiation")}}</span><span class="fa fa-wrench ms-1"></span></span>
|
||||
{% elif lead.status == "won" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-success"><span class="badge-label">{{_("Won")}}</span><span class="fa fa-check ms-1"></span></span>
|
||||
{% elif lead.status == "lost" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-danger"><span class="badge-label">{{_("Lost")}}</span><span class="fa fa-times ms-1"></span></span>
|
||||
{% elif lead.status == "closed" %}
|
||||
<span class="badge badge-phoenix badge-phoenix-danger"><span class="badge-label">{{_("Closed")}}</span><span class="fa fa-times ms-1"></span></span>
|
||||
{% endif %}
|
||||
</h5>
|
||||
</div>
|
||||
@ -158,51 +160,51 @@
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-envelope-alt"> </span>
|
||||
<h5 class="text-body-highlight mb-0">{{ _("Email") }}</h5>
|
||||
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Email") }}</h5>
|
||||
</div>
|
||||
<a href="{{ lead.email}}">{{ lead.email }}</a>
|
||||
<span class="text-body-secondary">{{ lead.email }}</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-phone"> </span>
|
||||
<h5 class="text-body-highlight mb-0">{{ _("Phone") }}</h5>
|
||||
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Phone") }}</h5>
|
||||
</div>
|
||||
<a href="{{ lead.phone_number}}">{{ lead.phone_number}} </a>
|
||||
<span class="text-body-secondary">{{ lead.phone_number}} </span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-dollar-alt"></span>
|
||||
<h5 class="text-body-highlight mb-0">{{ _("Salary")}}</h5>
|
||||
<div class="d-flex align-items-center mb-1"><span class="currency">{{CURRENCY}}</span>
|
||||
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Salary")}}</h5>
|
||||
</div>
|
||||
<p class="mb-0 text-body-secondary">{{lead.salary}} </p>
|
||||
<p class="mb-0 text-body-secondary"><small><span class="currency">{{CURRENCY}}</span></small> {{lead.salary}} </p>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-clock"></span>
|
||||
<h5 class="text-body-highlight mb-0">{{ _("Created")}}</h5>
|
||||
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Created")}}</h5>
|
||||
</div>
|
||||
<p class="mb-0 text-body-secondary">{{ lead.created|naturalday|capfirst }}</p>
|
||||
<span class="text-body-secondary">{{ lead.created|naturalday|capfirst }}</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-file-check-alt"></span>
|
||||
<h5 class="text-body-highlight mb-0">{{ _("Lead Source")}}</h5>
|
||||
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Source")}}</h5>
|
||||
</div>
|
||||
<p class="mb-0 text-body-secondary">{{ lead.source|upper }}</p>
|
||||
<span class="text-body-secondary">{{ lead.source|upper }}</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-file-check-alt"></span>
|
||||
<h5 class="text-body-highlight mb-0">{{ _("Lead Channel")}}</h5>
|
||||
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Channel")}}</h5>
|
||||
</div>
|
||||
<p class="mb-0 text-body-secondary">{{ lead.channel|upper }}</p>
|
||||
<span class="text-body-secondary">{{ lead.channel|upper }}</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-estate"></span>
|
||||
<h5 class="mb-0">{{ _("Address") }}</h5>
|
||||
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Address") }}</h5>
|
||||
</div>
|
||||
<p class="mb-0 text-body-secondary">{{ lead.address}}</p>
|
||||
<span class="text-body-secondary">{{ lead.address}}</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-map"></span>
|
||||
<h5 class="mb-0 text-body-highlight">{{ _("City") }}</h5>
|
||||
<h5 class="text-body-highlight fw-bold mb-0">{{ _("City") }}</h5>
|
||||
</div>
|
||||
<p class="mb-0 text-body-secondary">{{ lead.city }}</p>
|
||||
<span class="text-body-secondary">{{ lead.city }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -213,7 +215,7 @@
|
||||
<div class="col-md-7 col-lg-7 col-xl-8">
|
||||
<div class="d-flex w-100 gap-5">
|
||||
<div class="kanban-header bg-success w-50 text-white fw-bold"><i class="fa-solid fa-circle-check me-2"></i>{{lead.status|capfirst}} <br> <small>{% trans "Current Stage" %}</small></div>
|
||||
<div class="kanban-header bg-secondary w-50 text-white fw-bold"><i class="fa-solid fa-circle-info me-2"></i>{{lead.next_action|capfirst}} <br> <small>{% trans "Next Action" %}</small></div>
|
||||
<div class="kanban-header bg-secondary w-50 text-white fw-bold"><i class="fa-solid fa-circle-info me-2"></i>{{lead.next_action|capfirst}} <br> <small>{% trans "Next Action" %} :</small> <small>{{lead.next_action_date|naturalday|capfirst}}</small></div>
|
||||
</div>
|
||||
<ul class="nav main-tab nav-underline fs-9 deal-details scrollbar flex-nowrap w-100 pb-1 mb-6 justify-content-end mt-5" id="myTab" role="tablist" style="overflow-y: hidden;">
|
||||
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link active" id="activity-tab" data-bs-toggle="tab" href="#tab-activity" role="tab" aria-controls="tab-activity" aria-selected="false" tabindex="-1"> <span class="fa-solid fa-chart-line me-2 tab-icon-color fs-8"></span>{{ _("Activity") }}</a></li>
|
||||
@ -329,17 +331,17 @@
|
||||
<td class="align-middle text-end white-space-nowrap pe-0 action py-2">
|
||||
{% if note.created_by == request.user %}
|
||||
<a id="updateBtn"
|
||||
href="#"
|
||||
onclick="updateNote(this)"
|
||||
class="btn btn-sm btn-phoenix-primary me-2"
|
||||
data-pk="{{ note.pk }}"
|
||||
data-note="{{ note.note|escapejs }}"
|
||||
data-url="{% url 'update_note' note.pk %}"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#noteModal"
|
||||
data-note-title="{{ _('Update') }}<i class='fas fa-pen-square text-primary ms-2'></i>">
|
||||
{{ _("Update") }}
|
||||
</a>
|
||||
href="#"
|
||||
onclick="updateNote(this)"
|
||||
class="btn btn-sm btn-phoenix-primary me-2"
|
||||
data-pk="{{ note.pk }}"
|
||||
data-note="{{ note.note|escapejs }}"
|
||||
data-url="{% url 'update_note' note.pk %}"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#noteModal"
|
||||
data-note-title="{{ _('Update') }}<i class='fas fa-pen-square text-primary ms-2'></i>">
|
||||
{{ _("Update") }}
|
||||
</a>
|
||||
<button class="btn btn-phoenix-danger btn-sm delete-btn"
|
||||
data-url="{% url 'delete_note_to_lead' note.pk %}"
|
||||
data-message="Are you sure you want to delete this note?"
|
||||
@ -582,7 +584,6 @@
|
||||
</div>
|
||||
<!-- note Modal -->
|
||||
<div class="modal fade" id="noteModal" tabindex="-1" aria-labelledby="noteModalLabel" aria-hidden="true">
|
||||
|
||||
<div class="modal-dialog modal-md">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
|
||||
@ -606,103 +607,120 @@
|
||||
{% block customJS %}
|
||||
<script>
|
||||
function updateNote(e) {
|
||||
let url = e.getAttribute('data-url')
|
||||
let note = e.getAttribute('data-note')
|
||||
document.querySelector('#id_note').value = note
|
||||
let form = document.querySelector('.add_note_form')
|
||||
form.action = url
|
||||
let url = e.getAttribute('data-url')
|
||||
let note = e.getAttribute('data-note')
|
||||
document.querySelector('#id_note').value = note
|
||||
let form = document.querySelector('.add_note_form')
|
||||
form.action = url
|
||||
}
|
||||
function reset_form() {
|
||||
document.querySelector('#id_note').value = ""
|
||||
let form = document.querySelector('.add_note_form')
|
||||
form.action = "{% url 'add_note' 'lead' lead.slug %}"
|
||||
document.querySelector('#id_note').value = ""
|
||||
let form = document.querySelector('.add_note_form')
|
||||
form.action = "{% url 'add_note' 'lead' lead.slug %}"
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
let Toast = Swal.mixin({
|
||||
toast: true,
|
||||
position: "top-end",
|
||||
showConfirmButton: false,
|
||||
timer: 3000,
|
||||
timerProgressBar: true,
|
||||
didOpen: (toast) => {
|
||||
toast.onmouseenter = Swal.stopTimer;
|
||||
toast.onmouseleave = Swal.resumeTimer;
|
||||
}
|
||||
});
|
||||
|
||||
// Display Django messages
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
Toast.fire({
|
||||
icon: "{{ message.tags }}",
|
||||
titleText: "{{ message|safe }}"
|
||||
});
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
function openActionModal(leadId, currentAction, nextAction, nextActionDate) {
|
||||
const modal = new bootstrap.Modal(document.getElementById('actionTrackingModal'));
|
||||
document.getElementById('leadId').value = leadId;
|
||||
document.getElementById('currentAction').value = currentAction;
|
||||
document.getElementById('nextAction').value = nextAction;
|
||||
document.getElementById('nextActionDate').value = nextActionDate;
|
||||
modal.show();
|
||||
}
|
||||
|
||||
document.getElementById('actionTrackingForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(this);
|
||||
|
||||
// Show loading indicator
|
||||
Swal.fire({
|
||||
let Toast = Swal.mixin({
|
||||
toast: true,
|
||||
icon: 'info',
|
||||
text: 'Please wait...',
|
||||
allowOutsideClick: false,
|
||||
position: "top-end",
|
||||
showConfirmButton: false,
|
||||
timer: 2000,
|
||||
timerProgressBar: false,
|
||||
timer: 3000,
|
||||
timerProgressBar: true,
|
||||
didOpen: (toast) => {
|
||||
toast.onmouseenter = Swal.stopTimer;
|
||||
toast.onmouseleave = Swal.resumeTimer;
|
||||
}
|
||||
});
|
||||
|
||||
fetch("{% url 'update_lead_actions' %}", {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-CSRFToken': '{{ csrf_token }}'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
Swal.close();
|
||||
if (data.success) {
|
||||
// Display Django messages
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
Toast.fire({
|
||||
icon: "{{ message.tags }}",
|
||||
titleText: "{{ message|safe }}"
|
||||
});
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
function openActionModal(leadId, currentAction, nextAction, nextActionDate) {
|
||||
const modal = new bootstrap.Modal(document.getElementById('actionTrackingModal'));
|
||||
document.getElementById('leadId').value = leadId;
|
||||
document.getElementById('currentAction').value = currentAction;
|
||||
document.getElementById('nextAction').value = nextAction;
|
||||
document.getElementById('nextActionDate').value = nextActionDate;
|
||||
modal.show();
|
||||
}
|
||||
|
||||
document.getElementById('actionTrackingForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(this);
|
||||
|
||||
// Show loading indicator
|
||||
Swal.fire({
|
||||
toast: true,
|
||||
icon: 'info',
|
||||
text: 'Please wait...',
|
||||
allowOutsideClick: false,
|
||||
position: "top-end",
|
||||
showConfirmButton: false,
|
||||
timer: 2000,
|
||||
timerProgressBar: false,
|
||||
didOpen: (toast) => {
|
||||
toast.onmouseenter = Swal.stopTimer;
|
||||
toast.onmouseleave = Swal.resumeTimer;
|
||||
}
|
||||
});
|
||||
|
||||
fetch("{% url 'update_lead_actions' %}", {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-CSRFToken': '{{ csrf_token }}'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
Swal.close();
|
||||
if (data.success) {
|
||||
// Success notification
|
||||
Swal.fire({
|
||||
toast: true,
|
||||
icon: 'success',
|
||||
position: "top-end",
|
||||
text: data.message || 'Actions updated successfully',
|
||||
showConfirmButton: false,
|
||||
timer: 2000,
|
||||
timerProgressBar: false,
|
||||
didOpen: (toast) => {
|
||||
toast.onmouseenter = Swal.stopTimer;
|
||||
toast.onmouseleave = Swal.resumeTimer;
|
||||
}
|
||||
}).then(() => {
|
||||
location.reload(); // Refresh after user clicks OK
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
toast: true,
|
||||
icon: 'success',
|
||||
position: "top-end",
|
||||
text: data.message || 'Actions updated successfully',
|
||||
showConfirmButton: false,
|
||||
timer: 2000,
|
||||
timerProgressBar: false,
|
||||
didOpen: (toast) => {
|
||||
toast.onmouseenter = Swal.stopTimer;
|
||||
toast.onmouseleave = Swal.resumeTimer;
|
||||
}
|
||||
}).then(() => {
|
||||
location.reload(); // Refresh after user clicks OK
|
||||
});
|
||||
} else {
|
||||
// Error notification
|
||||
Swal.fire({
|
||||
toast: true,
|
||||
icon: 'error',
|
||||
position: "top-end",
|
||||
text: data.message || 'Failed to update actions',
|
||||
showConfirmButton: false,
|
||||
timer: 2000,
|
||||
timerProgressBar: false,
|
||||
didOpen: (toast) => {
|
||||
toast.onmouseenter = Swal.stopTimer;
|
||||
toast.onmouseleave = Swal.resumeTimer;
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Swal.close();
|
||||
console.error('Error:', error);
|
||||
Swal.fire({
|
||||
toast: true,
|
||||
icon: 'error',
|
||||
position: "top-end",
|
||||
text: data.message || 'Failed to update actions',
|
||||
text: 'An unexpected error occurred',
|
||||
showConfirmButton: false,
|
||||
timer: 2000,
|
||||
timerProgressBar: false,
|
||||
@ -711,34 +729,16 @@
|
||||
toast.onmouseleave = Swal.resumeTimer;
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Swal.close();
|
||||
console.error('Error:', error);
|
||||
Swal.fire({
|
||||
toast: true,
|
||||
icon: 'error',
|
||||
position: "top-end",
|
||||
text: 'An unexpected error occurred',
|
||||
showConfirmButton: false,
|
||||
timer: 2000,
|
||||
timerProgressBar: false,
|
||||
didOpen: (toast) => {
|
||||
toast.onmouseenter = Swal.stopTimer;
|
||||
toast.onmouseleave = Swal.resumeTimer;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Helper function for notifications
|
||||
function notify(tag, msg) {
|
||||
Toast.fire({
|
||||
icon: tag,
|
||||
titleText: msg
|
||||
});
|
||||
}
|
||||
});
|
||||
function notify(tag, msg) {
|
||||
Toast.fire({
|
||||
icon: tag,
|
||||
titleText: msg
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
{% endblock customJS %}
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static crispy_forms_filters %}
|
||||
{% block customcss %}
|
||||
<style>
|
||||
.htmx-indicator{
|
||||
opacity:0;
|
||||
transition: opacity 500ms ease-in;
|
||||
}
|
||||
.htmx-request .htmx-indicator{
|
||||
opacity:1;
|
||||
}
|
||||
.htmx-request.htmx-indicator{
|
||||
opacity:1;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.htmx-indicator{
|
||||
opacity:0;
|
||||
transition: opacity 500ms ease-in;
|
||||
}
|
||||
.htmx-request .htmx-indicator{
|
||||
opacity:1;
|
||||
}
|
||||
.htmx-request.htmx-indicator{
|
||||
opacity:1;
|
||||
}
|
||||
</style>
|
||||
{% endblock customcss %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid">
|
||||
<h1>{% if object %}{{ _("Update") }}{% else %}{{ _("Create") }}{% endif %}</h1>
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-6 col-md-8">
|
||||
<div class="col-sm-6 col-md-8">
|
||||
|
||||
<form class="form" method="post">
|
||||
{% csrf_token %}
|
||||
@ -36,7 +36,7 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// First, create the spinner div (or use the existing one)
|
||||
const spinner = document.createElement('div');
|
||||
|
||||
@ -182,6 +182,7 @@
|
||||
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="">{{ lead.email }}</a></td>
|
||||
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="tel:{{ lead.phone_number }}">{{ lead.phone_number }}</a></td>
|
||||
<td class="align-middle white-space-nowrap fw-semibold">
|
||||
{% if request.user.staffmember.staff %}
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingTwo">
|
||||
@ -221,7 +222,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight">{{ lead.get_status|upper }}</td>
|
||||
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight">{{ lead.staff|upper }}</td>
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
{% load i18n static humanize %}
|
||||
{% load custom_filters %}
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
.bg-success-soft {
|
||||
background-color: rgba(25, 135, 84, 0.1) !important;
|
||||
opacity: .8;
|
||||
}
|
||||
.bg-danger-soft {
|
||||
background-color: rgba(220, 53, 69, 0.1) !important;
|
||||
opacity: .8;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.bg-success-soft {
|
||||
background-color: rgba(25, 135, 84, 0.1) !important;
|
||||
opacity: .8;
|
||||
}
|
||||
.bg-danger-soft {
|
||||
background-color: rgba(220, 53, 69, 0.1) !important;
|
||||
opacity: .8;
|
||||
}
|
||||
</style>
|
||||
{% endblock customCSS %}
|
||||
|
||||
{% for opportunity in opportunities %}
|
||||
<div class="col-12 col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="card h-100
|
||||
{% if opportunity.get_stage_display == 'Closed Won' %}bg-success-soft
|
||||
{% elif opportunity.get_stage_display == 'Closed Lost' %}bg-danger-soft{% endif %}">
|
||||
{% if opportunity.get_stage_display == 'Closed Won' %}bg-success-soft
|
||||
{% elif opportunity.get_stage_display == 'Closed Lost' %}bg-danger-soft{% endif %}">
|
||||
<div class="card-body">
|
||||
<h5 class="mb-4">Opportunity for {{ opportunity.customer.customer_name }}</h5>
|
||||
|
||||
@ -35,8 +35,8 @@
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-danger">{{ opportunity.get_stage_display }}</span>
|
||||
{% endif %}
|
||||
<span class="badge badge-phoenix fs-10
|
||||
{% if opportunity.get_stage_display == 'Won' %}badge-phoenix-success
|
||||
{% elif opportunity.get_stage_display == 'Lost' %}badge-phoenix-danger{% endif %}">
|
||||
{% if opportunity.get_stage_display == 'Won' %}badge-phoenix-success
|
||||
{% elif opportunity.get_stage_display == 'Lost' %}badge-phoenix-danger{% endif %}">
|
||||
{{ opportunity.get_status_display }}
|
||||
</span>
|
||||
</div>
|
||||
@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<p class="fw-semibold fs-9 mb-0 text-body-emphasis"><span class="currency">{{ CURRENCY }}</span>{{ opportunity.expected_revenue }}</p>
|
||||
<p class="fw-semibold fs-9 mb-0 text-body-emphasis"><span class="currency">{{ CURRENCY }}</span>{{ opportunity.expected_revenue }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<div class="col-12">
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<!--<i class="bi bi-save"></i> -->
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
|
||||
@ -6,6 +6,12 @@
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="row g-2 g-sm-3">
|
||||
<div class="col-auto">
|
||||
<a href="{% url 'order_list' %}" class="btn btn-phoenix-success"><span class="fas fa-list me-2"></span>{{ _("Orders") }}</a>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<a href="{% url 'billing_info' %}" class="btn btn-phoenix-info"><span class="fas fa-credit-card me-2"></span>{{ _("Billing Information") }}</a>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<a href="{% url 'account_change_password' %}" class="btn btn-phoenix-danger"><span class="fas fa-key me-2"></span>{{ _("Change Password") }}</a>
|
||||
</div>
|
||||
@ -108,7 +114,7 @@
|
||||
<a href="{% url 'pricing_page' %}" class="btn btn-phoenix-secondary ms-2"><span class="fas fa-arrow-right me-2"></span>{{ _("Renew") }}</a>
|
||||
{% endif %}
|
||||
{% if dealer.user.userplan.plan.name != "Enterprise" %}
|
||||
<a href="{% url 'pricing_page' %}" class="btn btn-phoenix-secondary ms-2"><span class="fas fa-arrow-right me-2"></span>{{ _("Upgrade") }}</a>
|
||||
<a href="{% url 'pricing_page' %}" class="btn btn-sm btn-phoenix-primary ms-2"><span class="fas fa-rocket me-2"></span>{{ _("Upgrade") }}</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="text-body-tertiary fw-semibold">You have no active plan.</span> <a href="{% url 'pricing_page' %}" class="btn btn-phoenix-secondary ms-2"><span class="fas fa-arrow-right me-2"></span>{{ _("Subscribe") }}</a>
|
||||
|
||||
@ -435,6 +435,11 @@
|
||||
<a class="nav-link px-3 d-block" href="{% url 'dealer_settings' request.user.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="settings"></span>{{ _("Settings") }}</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
{% if request.is_dealer %}
|
||||
<a class="nav-link px-3 d-block" href="{% url 'management' %}"> <span class="me-2 text-body align-bottom" data-feather="shield"></span>{{ _("Admin Managemnet") }}</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-3 d-block" href=""> <span class="me-2 text-body align-bottom" data-feather="help-circle"></span>Help Center</a>
|
||||
</li>
|
||||
|
||||
@ -58,7 +58,7 @@
|
||||
</div>
|
||||
</div> {% endcomment %}
|
||||
|
||||
|
||||
|
||||
|
||||
{% comment %} <div class="row justify-content-center g-1 mt-4">
|
||||
<div class="col-auto">
|
||||
@ -73,7 +73,7 @@
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -44,15 +44,15 @@
|
||||
</div> {% endcomment %}
|
||||
|
||||
<div class="d-flex justify-content-center">
|
||||
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<!--<i class="bi bi-save"></i> -->
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<!--<i class="bi bi-save"></i> -->
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -106,7 +106,7 @@
|
||||
<button type="submit" class="btn btn-sm btn-success me-1">{% trans "Save" %}</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger me-1">{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i> {{ _("Save") }}</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,39 +4,39 @@
|
||||
{% block title %}{% trans "bank account" %}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-8">
|
||||
<div class="card shadow rounded bg-body">
|
||||
<div class="card-header">
|
||||
<p class="mb-0">
|
||||
{% if customer.created %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-8">
|
||||
<div class="card shadow rounded bg-body">
|
||||
<div class="card-header">
|
||||
<p class="mb-0">
|
||||
{% if customer.created %}
|
||||
<!--<i class="bi bi-pencil-square"></i>-->
|
||||
{{ _("Edit Bank Account") }}
|
||||
{% else %}
|
||||
{{ _("Edit Bank Account") }}
|
||||
{% else %}
|
||||
<!--<i class="bi bi-person-plus"></i> -->
|
||||
{{ _("Add Bank Account") }}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" class="form" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-danger">{{ error }}</div>
|
||||
{% endfor %}
|
||||
<div class="d-flex justify-content-start">
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<!--<i class="bi bi-save"></i> -->
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
{{ _("Add Bank Account") }}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
<div class="card-body">
|
||||
<form method="post" class="form" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-danger">{{ error }}</div>
|
||||
{% endfor %}
|
||||
<div class="d-flex justify-content-start">
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<!--<i class="bi bi-save"></i> -->
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -89,5 +89,5 @@
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@ -42,7 +42,7 @@
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
<div class="text-danger">{{ error }}</div>
|
||||
{% endfor %}
|
||||
<div class="d-flex justify-content-start">
|
||||
|
||||
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<!--<i class="bi bi-save"></i> -->
|
||||
{{ _("Save") }}
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -17,11 +17,11 @@
|
||||
<a href="{% url 'ledger_list' %}" class="btn btn-danger"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</a>
|
||||
</div> {% endcomment %}
|
||||
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="d-flex justify-content-center">
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<div class="d-flex">
|
||||
<a href="{% url 'organization_update' organization.pk %}" class="btn btn-sm btn-warning me-2">{% trans "Edit" %}</a>
|
||||
<button class="btn btn-phoenix-danger btn-sm delete-btn"
|
||||
data-url="{% url 'organization_delete' organization.pk %}"
|
||||
data-url="{% url 'organization_delete' organization.slug %}"
|
||||
data-message="Are you sure you want to delete this organization?"
|
||||
data-bs-toggle="modal" data-bs-target="#deleteModal">
|
||||
{% trans 'Delete' %}<i class="fas fa-trash ms-1"></i>
|
||||
|
||||
@ -93,7 +93,7 @@
|
||||
{% trans 'Are you sure you want to delete this Organization?' %}
|
||||
</p>
|
||||
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">{% trans 'No' %}</button>
|
||||
<a type="button" class="btn btn-danger btn-sm" href="{% url 'organization_delete' org.pk %}">{% trans 'Yes' %}</a>
|
||||
<a type="button" class="btn btn-danger btn-sm" href="{% url 'organization_delete' org.slug %}">{% trans 'Yes' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -102,7 +102,7 @@
|
||||
<td class="name align-middle white-space-nowrap ps-0">
|
||||
<div class="d-flex align-items-center">
|
||||
<div>
|
||||
<a class="fs-8 fw-bold" href="{% url 'organization_detail' org.pk %}">{{ org.name }}</a>
|
||||
<a class="fs-8 fw-bold" href="{% url 'organization_detail' org.slug %}">{{ org.name }}</a>
|
||||
<div class="d-flex align-items-center">
|
||||
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2"></p><span class="badge badge-phoenix badge-phoenix-primary">{{ org.name }}</span>
|
||||
</div>
|
||||
@ -121,7 +121,7 @@
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a href="{% url 'organization_update' org.pk %}" class="dropdown-item text-success-dark">{% trans 'Edit' %}</a>
|
||||
<a href="{% url 'organization_update' org.slug %}" class="dropdown-item text-success-dark">{% trans 'Edit' %}</a>
|
||||
{% if perms.django_ledger.delete_customermodel %}
|
||||
<div class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans 'Delete' %}</button>
|
||||
{% endif %}
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
<div class="container text-center" data-aos="fade-up">
|
||||
<div class="py-5">
|
||||
<i class="bi bi-x-circle-fill text-danger" style="font-size: 5rem;"></i>
|
||||
<h2 class="mt-4">{% trans "Payment Failed"%}</h2>
|
||||
<h2 class="mt-4">{% trans "Payment Failed"%}</h2>
|
||||
{% if message %}
|
||||
<p class="lead">{{message}}.</p>
|
||||
{% else %}
|
||||
|
||||
@ -207,26 +207,26 @@
|
||||
{% block customJS %}
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const form = document.getElementById('wizardForm');
|
||||
const form = document.getElementById('wizardForm');
|
||||
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault(); // Prevent default form submission
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault(); // Prevent default form submission
|
||||
|
||||
// Show loading alert
|
||||
Swal.fire({
|
||||
title: 'Processing...',
|
||||
html: 'Please wait while we submit your form',
|
||||
allowOutsideClick: false,
|
||||
didOpen: () => {
|
||||
Swal.showLoading();
|
||||
}
|
||||
});
|
||||
Swal.fire({
|
||||
title: 'Processing...',
|
||||
html: 'Please wait while we submit your form',
|
||||
allowOutsideClick: false,
|
||||
didOpen: () => {
|
||||
Swal.showLoading();
|
||||
}
|
||||
});
|
||||
|
||||
// Submit the form after a slight delay to ensure Swal is shown
|
||||
setTimeout(() => {
|
||||
form.submit();
|
||||
}, 100);
|
||||
});
|
||||
setTimeout(() => {
|
||||
form.submit();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
const radios = document.querySelectorAll('.btn-check');
|
||||
radios.forEach(radio => {
|
||||
|
||||
@ -68,13 +68,13 @@
|
||||
</div> {% endcomment %}
|
||||
<div class="d-flex justify-content-center">
|
||||
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<!--<i class="bi bi-save"></i> -->
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">{{ invoice.created }}</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
<a href="{% url 'invoice_detail' invoice.pk %}"
|
||||
<a href="{% url 'invoice_detail' invoice.pk %}"
|
||||
class="btn btn-sm btn-phoenix-success">
|
||||
<i class="fa-regular fa-eye me-1"></i>
|
||||
{% trans "View" %}
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
</div>
|
||||
<h4 class="my-4">Groups</h4>
|
||||
<a class="btn btn-sm btn-primary mt-2 mb-4" href="{% url 'user_groups' user_.pk %}"><i class="fa-solid fa-users"></i> Manage Groups</a>
|
||||
<a class="btn btn-sm btn-primary mt-2 mb-4" href="{% url 'user_groups' user_.slug %}"><i class="fa-solid fa-users"></i> Manage Groups</a>
|
||||
<table class="table table-hover table-responsive-sm fs-9 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -48,13 +48,13 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-footer d-flex ">
|
||||
<a class="btn btn-sm btn-phoenix-primary me-1" href="{% url 'user_update' user_.id %}">
|
||||
<a class="btn btn-sm btn-phoenix-primary me-1" href="{% url 'user_update' user_.slug %}">
|
||||
{{ _("Edit") }}
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</a>
|
||||
|
||||
<button class="btn btn-phoenix-danger btn-sm delete-btn me-1"
|
||||
data-url="{% url 'user_delete' user_.id %}"
|
||||
data-url="{% url 'user_delete' user_.slug %}"
|
||||
data-message="{{ _("Are you sure you want to delete this user?")}}"
|
||||
data-bs-toggle="modal" data-bs-target="#deleteModal">
|
||||
{{ _("Delete") }}
|
||||
|
||||
@ -2,10 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% block title %}{% trans "Group" %}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="row">
|
||||
<div class="col-sm-9">
|
||||
@ -16,7 +13,6 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-9">
|
||||
|
||||
<form class="row g-3 mb-9" method="post" class="form" novalidate>
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
|
||||
@ -11,8 +11,16 @@
|
||||
<div class="col-auto">
|
||||
<div class="d-md-flex justify-content-between">
|
||||
<div>
|
||||
<a href="{% url 'user_create' %}" class="btn btn-sm btn-phoenix-primary"><i class="fa-solid fa-user-tie"></i> {% trans "Add New Staff" %}</a>
|
||||
<a href="{% url 'group_list' %}" class="btn btn-sm btn-phoenix-success"><i class="fa-solid fa-user-group"></i> {% trans "Manage Groups & Permissions" %}</a>
|
||||
{% if request.user.userplan %}
|
||||
<a href="{% url 'user_create' %}" class="btn btn-sm btn-phoenix-primary"><i class="fa-solid fa-user-tie"></i> {% trans "Add New Staff" %}</a>
|
||||
<a href="{% url 'group_list' %}" class="btn btn-sm btn-phoenix-success"><i class="fa-solid fa-user-group"></i> {% trans "Manage Groups & Permissions" %}</a>
|
||||
{% else %}
|
||||
<div class="alert alert-outline-info d-flex align-items-center" role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1">{{ _("No Active Subscription,please activate your subscription.") }}<a href="{% url 'pricing_page' %}" class="ms-3 text-body-primary fs-9">Manage Subscription</a></p>
|
||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -33,7 +41,7 @@
|
||||
<tr>
|
||||
<td class="align-middle white-space-nowrap ps-0">
|
||||
<div>
|
||||
<a class="fs-8 fw-bold" href="{% url 'user_detail' user.pk%}">{{ user.arabic_name }}</a>
|
||||
<a class="fs-8 fw-bold" href="{% url 'user_detail' user.slug%}">{{ user.arabic_name }}</a>
|
||||
<div class="d-flex align-items-center">
|
||||
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2">{{ user.name }}</p>
|
||||
</div>
|
||||
@ -47,7 +55,7 @@
|
||||
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<a class="btn btn-phoenix-success"
|
||||
href="{% url 'user_detail' user.id %}">
|
||||
href="{% url 'user_detail' user.slug %}">
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
{% trans 'view'|capfirst %}
|
||||
</a>
|
||||
|
||||
8
templates/vendors/vendor_form.html
vendored
8
templates/vendors/vendor_form.html
vendored
@ -35,11 +35,11 @@
|
||||
<div class="text-danger">{{ error }}</div>
|
||||
{% endfor %}
|
||||
<div class="d-flex justify-content-start">
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||
<!--<i class="bi bi-save"></i> -->
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
{{ _("Save") }}
|
||||
</button>
|
||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user