Compare commits
No commits in common. "2d20e0e0bface0548619417036cde08de1d866ea" and "d7ba36b7733ed269cd36e96b0bf84268fadfff5f" have entirely different histories.
2d20e0e0bf
...
d7ba36b773
3
.gitignore
vendored
3
.gitignore
vendored
@ -45,9 +45,6 @@ Makefile
|
|||||||
.idea/**/dbnavigator.xml
|
.idea/**/dbnavigator.xml
|
||||||
**/migrations/**
|
**/migrations/**
|
||||||
|
|
||||||
**haikalbot/migrations/**
|
|
||||||
|
|
||||||
|
|
||||||
# Gradle
|
# Gradle
|
||||||
.idea/**/gradle.xml
|
.idea/**/gradle.xml
|
||||||
.idea/**/libraries
|
.idea/**/libraries
|
||||||
|
|||||||
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -14,7 +14,7 @@
|
|||||||
],
|
],
|
||||||
"django": true,
|
"django": true,
|
||||||
"autoStartBrowser": false,
|
"autoStartBrowser": false,
|
||||||
"program": "C:\\Users\\user\\Desktop\\haikal_projects\\venv\\bin\\activate & ${workspaceFolder}/manage.py"
|
"program": "${workspaceFolder}/manage.py"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -4,8 +4,6 @@ from django.conf.urls.static import static
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.i18n import i18n_patterns
|
from django.conf.urls.i18n import i18n_patterns
|
||||||
from inventory import views
|
from inventory import views
|
||||||
# from debug_toolbar.toolbar import debug_toolbar_urls
|
|
||||||
|
|
||||||
|
|
||||||
# import debug_toolbar
|
# import debug_toolbar
|
||||||
from schema_graph.views import Schema
|
from schema_graph.views import Schema
|
||||||
@ -17,7 +15,7 @@ urlpatterns = [
|
|||||||
path("api-auth/", include("rest_framework.urls")),
|
path("api-auth/", include("rest_framework.urls")),
|
||||||
path("api/", include("api.urls")),
|
path("api/", include("api.urls")),
|
||||||
# path('dj-rest-auth/', include('dj_rest_auth.urls')),
|
# path('dj-rest-auth/', include('dj_rest_auth.urls')),
|
||||||
]# + debug_toolbar_urls()
|
]
|
||||||
urlpatterns += i18n_patterns(
|
urlpatterns += i18n_patterns(
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
path("switch_language/", views.switch_language, name="switch_language"),
|
path("switch_language/", views.switch_language, name="switch_language"),
|
||||||
@ -34,5 +32,3 @@ urlpatterns += i18n_patterns(
|
|||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -70,7 +70,6 @@ admin.site.register(models.Schedule)
|
|||||||
admin.site.register(models.Notes)
|
admin.site.register(models.Notes)
|
||||||
admin.site.register(models.UserActivityLog)
|
admin.site.register(models.UserActivityLog)
|
||||||
admin.site.register(models.DealersMake)
|
admin.site.register(models.DealersMake)
|
||||||
admin.site.register(models.ExtraInfo)
|
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.Car)
|
@admin.register(models.Car)
|
||||||
|
|||||||
@ -40,46 +40,3 @@ def breadcrumbs(request):
|
|||||||
url = "/" + "/".join(path[: i + 1]) + "/"
|
url = "/" + "/".join(path[: i + 1]) + "/"
|
||||||
breadcrumbs.append({"name": path[i].capitalize(), "url": url})
|
breadcrumbs.append({"name": path[i].capitalize(), "url": url})
|
||||||
return {"breadcrumbs": breadcrumbs}
|
return {"breadcrumbs": breadcrumbs}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def user_types(request):
|
|
||||||
"""
|
|
||||||
Sets various flags indicating the user's role types.
|
|
||||||
|
|
||||||
The flags are:
|
|
||||||
|
|
||||||
- request.is_dealer
|
|
||||||
- request.is_staff
|
|
||||||
- request.is_manager
|
|
||||||
- request.is_accountant
|
|
||||||
- request.is_sales
|
|
||||||
- request.is_inventory
|
|
||||||
|
|
||||||
:param request: The request object to set the flags upon.
|
|
||||||
:type request: HttpRequest
|
|
||||||
"""
|
|
||||||
request.is_dealer = False
|
|
||||||
request.is_staff = False
|
|
||||||
request.is_manager = False
|
|
||||||
request.is_accountant = False
|
|
||||||
request.is_sales = False
|
|
||||||
request.is_inventory = False
|
|
||||||
if hasattr(request.user, "dealer"):
|
|
||||||
request.is_dealer = True
|
|
||||||
elif hasattr(request.user, "staffmember"):
|
|
||||||
request.is_staff = True
|
|
||||||
staff = getattr(request.user.staffmember, "staff")
|
|
||||||
if "Accountant" in staff.groups.values_list("name", flat=True):
|
|
||||||
request.is_accountant = True
|
|
||||||
return {"is_accountant": True}
|
|
||||||
elif "Manager" in staff.groups.values_list("name", flat=True):
|
|
||||||
request.is_manager = True
|
|
||||||
return {"is_manager": True}
|
|
||||||
elif "Sales" in staff.groups.values_list("name", flat=True):
|
|
||||||
request.is_sales = True
|
|
||||||
return {"is_sales": True}
|
|
||||||
elif "Inventory" in staff.groups.values_list("name", flat=True):
|
|
||||||
request.is_inventory = True
|
|
||||||
return {"is_inventory": True}
|
|
||||||
return {}
|
|
||||||
|
|||||||
@ -30,7 +30,6 @@ from .models import (
|
|||||||
Vendor,
|
Vendor,
|
||||||
Schedule,
|
Schedule,
|
||||||
Car,
|
Car,
|
||||||
VatRate,
|
|
||||||
CarTransfer,
|
CarTransfer,
|
||||||
CarFinance,
|
CarFinance,
|
||||||
CustomCard,
|
CustomCard,
|
||||||
@ -144,7 +143,7 @@ class StaffForm(forms.ModelForm):
|
|||||||
)
|
)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Staff
|
model = Staff
|
||||||
fields = ["name", "arabic_name", "phone_number", "address","image","group"]
|
fields = ["name", "arabic_name", "phone_number", "group"]
|
||||||
|
|
||||||
|
|
||||||
# Dealer Form
|
# Dealer Form
|
||||||
@ -2092,16 +2091,3 @@ class CSVUploadForm(forms.Form):
|
|||||||
# Reset file pointer for later processing
|
# Reset file pointer for later processing
|
||||||
csv_file.file.seek(0)
|
csv_file.file.seek(0)
|
||||||
return csv_file
|
return csv_file
|
||||||
|
|
||||||
|
|
||||||
class AdditionalFinancesForm(forms.Form):
|
|
||||||
additional_finances = forms.ModelMultipleChoiceField(
|
|
||||||
queryset=AdditionalServices.objects.all(),
|
|
||||||
widget=forms.CheckboxSelectMultiple(attrs={"class": "form-check-input"}),
|
|
||||||
required=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
class VatRateForm(forms.ModelForm):
|
|
||||||
class Meta:
|
|
||||||
model = VatRate
|
|
||||||
fields = ['rate']
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
# from django.http import Http404, HttpResponseForbidden
|
from django.http import Http404, HttpResponseForbidden
|
||||||
# from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
# from inventory import models
|
from inventory import models
|
||||||
# from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from inventory.utils import get_user_type
|
from inventory.utils import get_user_type
|
||||||
|
|
||||||
@ -102,24 +102,17 @@ class InjectDealerMiddleware:
|
|||||||
request.is_inventory = False
|
request.is_inventory = False
|
||||||
if hasattr(request.user, "dealer"):
|
if hasattr(request.user, "dealer"):
|
||||||
request.is_dealer = True
|
request.is_dealer = True
|
||||||
request.dealer = request.user.dealer
|
|
||||||
elif hasattr(request.user, "staffmember"):
|
elif hasattr(request.user, "staffmember"):
|
||||||
request.is_staff = True
|
request.is_staff = True
|
||||||
request.staff = request.user.staffmember.staff
|
|
||||||
request.dealer = request.staff.dealer
|
|
||||||
|
|
||||||
staff = getattr(request.user.staffmember, "staff")
|
staff = getattr(request.user.staffmember, "staff")
|
||||||
staff_groups = staff.groups.values_list("name", flat=True)
|
if "Accountant" in staff.groups.values_list("name", flat=True):
|
||||||
if "Accountant" in staff_groups:
|
|
||||||
request.is_accountant = True
|
request.is_accountant = True
|
||||||
elif "Manager" in staff_groups:
|
if "Manager" in staff.groups.values_list("name", flat=True):
|
||||||
request.is_manager = True
|
request.is_manager = True
|
||||||
elif "Sales" in staff_groups:
|
if "Sales" in staff.groups.values_list("name", flat=True):
|
||||||
request.is_sales = True
|
request.is_sales = True
|
||||||
elif "Inventory" in staff_groups:
|
if "Inventory" in staff.groups.values_list("name", flat=True):
|
||||||
request.is_inventory = True
|
request.is_inventory = True
|
||||||
request.entity = request.dealer.entity
|
|
||||||
request.admin = request.dealer.entity.admin
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
response = self.get_response(request)
|
response = self.get_response(request)
|
||||||
|
|||||||
@ -19,7 +19,7 @@ class Migration(migrations.Migration):
|
|||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('appointment', '__first__'),
|
('appointment', '0001_initial'),
|
||||||
('auth', '0012_alter_user_first_name_max_length'),
|
('auth', '0012_alter_user_first_name_max_length'),
|
||||||
('contenttypes', '0002_remove_content_type_name'),
|
('contenttypes', '0002_remove_content_type_name'),
|
||||||
('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'),
|
('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'),
|
||||||
|
|||||||
@ -43,7 +43,6 @@ from django.core.serializers.json import DjangoJSONEncoder
|
|||||||
from appointment.models import StaffMember
|
from appointment.models import StaffMember
|
||||||
from plans.quota import get_user_quota
|
from plans.quota import get_user_quota
|
||||||
from plans.models import UserPlan
|
from plans.models import UserPlan
|
||||||
from django.db.models import Q
|
|
||||||
# from plans.models import AbstractPlan
|
# from plans.models import AbstractPlan
|
||||||
# from simple_history.models import HistoricalRecords
|
# from simple_history.models import HistoricalRecords
|
||||||
|
|
||||||
@ -191,7 +190,6 @@ class UnitOfMeasure(models.TextChoices):
|
|||||||
|
|
||||||
|
|
||||||
class VatRate(models.Model):
|
class VatRate(models.Model):
|
||||||
dealer = models.ForeignKey("Dealer", on_delete=models.CASCADE)
|
|
||||||
rate = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.15"))
|
rate = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.15"))
|
||||||
is_active = models.BooleanField(default=True)
|
is_active = models.BooleanField(default=True)
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
@ -245,11 +243,6 @@ class CarMake(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Make")
|
verbose_name = _("Make")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['name'], name='car_make_name_idx'),
|
|
||||||
models.Index(fields=['is_sa_import'], name='car_make_sa_import_idx'),
|
|
||||||
models.Index(fields=['car_type'], name='car_make_type_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CarModel(models.Model, LocalizedNameMixin):
|
class CarModel(models.Model, LocalizedNameMixin):
|
||||||
@ -279,11 +272,6 @@ class CarModel(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Model")
|
verbose_name = _("Model")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['id_car_make'], name='car_model_make_idx'),
|
|
||||||
models.Index(fields=['name'], name='car_model_name_idx'),
|
|
||||||
models.Index(fields=['id_car_make', 'name'], name='car_model_make_name_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CarSerie(models.Model, LocalizedNameMixin):
|
class CarSerie(models.Model, LocalizedNameMixin):
|
||||||
@ -318,12 +306,6 @@ class CarSerie(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Series")
|
verbose_name = _("Series")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['id_car_model'], name='car_serie_model_idx'),
|
|
||||||
models.Index(fields=['year_begin', 'year_end'], name='car_serie_years_idx'),
|
|
||||||
models.Index(fields=['name'], name='car_serie_name_idx'),
|
|
||||||
models.Index(fields=['generation_name'], name='car_serie_generation_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CarTrim(models.Model, LocalizedNameMixin):
|
class CarTrim(models.Model, LocalizedNameMixin):
|
||||||
@ -357,11 +339,6 @@ class CarTrim(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Trim")
|
verbose_name = _("Trim")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['id_car_serie'], name='car_trim_serie_idx'),
|
|
||||||
models.Index(fields=['start_production_year', 'end_production_year'], name='car_trim_prod_years_idx'),
|
|
||||||
models.Index(fields=['name'], name='car_trim_name_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CarEquipment(models.Model, LocalizedNameMixin):
|
class CarEquipment(models.Model, LocalizedNameMixin):
|
||||||
@ -382,11 +359,6 @@ class CarEquipment(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Equipment")
|
verbose_name = _("Equipment")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['id_car_trim'], name='car_equipment_trim_idx'),
|
|
||||||
models.Index(fields=['year_begin'], name='car_equipment_year_idx'),
|
|
||||||
models.Index(fields=['name'], name='car_equipment_name_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CarSpecification(models.Model, LocalizedNameMixin):
|
class CarSpecification(models.Model, LocalizedNameMixin):
|
||||||
@ -418,10 +390,6 @@ class CarSpecification(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Specification")
|
verbose_name = _("Specification")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['id_parent'], name='car_spec_parent_idx'),
|
|
||||||
models.Index(fields=['name'], name='car_spec_name_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CarSpecificationValue(models.Model):
|
class CarSpecificationValue(models.Model):
|
||||||
@ -438,11 +406,6 @@ class CarSpecificationValue(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Specification Value")
|
verbose_name = _("Specification Value")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['id_car_trim'], name='car_spec_val_trim_idx'),
|
|
||||||
models.Index(fields=['id_car_specification'], name='car_spec_val_spec_idx'),
|
|
||||||
models.Index(fields=['id_car_trim', 'id_car_specification'], name='car_spec_val_trim_spec_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CarOption(models.Model, LocalizedNameMixin):
|
class CarOption(models.Model, LocalizedNameMixin):
|
||||||
@ -474,10 +437,6 @@ class CarOption(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Option")
|
verbose_name = _("Option")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['id_parent'], name='car_option_parent_idx'),
|
|
||||||
models.Index(fields=['name'], name='car_option_name_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CarOptionValue(models.Model):
|
class CarOptionValue(models.Model):
|
||||||
@ -497,12 +456,6 @@ class CarOptionValue(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Option Value")
|
verbose_name = _("Option Value")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['id_car_option'], name='car_opt_val_option_idx'),
|
|
||||||
models.Index(fields=['id_car_equipment'], name='car_opt_val_equipment_idx'),
|
|
||||||
models.Index(fields=['is_base'], name='car_opt_val_is_base_idx'),
|
|
||||||
models.Index(fields=['id_car_option', 'id_car_equipment'], name='cov_option_equipment_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class CarTransferStatusChoices(models.TextChoices):
|
class CarTransferStatusChoices(models.TextChoices):
|
||||||
@ -564,7 +517,7 @@ class AdditionalServices(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def price_(self):
|
def price_(self):
|
||||||
vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first()
|
vat = VatRate.objects.filter(is_active=True).first()
|
||||||
return (
|
return (
|
||||||
Decimal(self.price + (self.price * vat.rate))
|
Decimal(self.price + (self.price * vat.rate))
|
||||||
if self.taxable
|
if self.taxable
|
||||||
@ -661,26 +614,6 @@ class Car(Base):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Car")
|
verbose_name = _("Car")
|
||||||
verbose_name_plural = _("Cars")
|
verbose_name_plural = _("Cars")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['vin'], name='car_vin_idx'),
|
|
||||||
models.Index(fields=['year'], name='car_year_idx'),
|
|
||||||
models.Index(fields=['status'], name='car_status_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['dealer'], name='car_dealer_idx'),
|
|
||||||
models.Index(fields=['vendor'], name='car_vendor_idx'),
|
|
||||||
models.Index(fields=['id_car_make'], name='car_make_idx'),
|
|
||||||
models.Index(fields=['id_car_model'], name='car_model_idx'),
|
|
||||||
models.Index(fields=['id_car_serie'], name='car_serie_idx'),
|
|
||||||
models.Index(fields=['id_car_trim'], name='car_trim_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['id_car_make', 'id_car_model'], name='car_make_model_idx'),
|
|
||||||
models.Index(fields=['id_car_make', 'year'], name='car_make_year_idx'),
|
|
||||||
models.Index(fields=['dealer', 'status'], name='car_dealer_status_idx'),
|
|
||||||
models.Index(fields=['vendor', 'status'], name='car_vendor_status_idx'),
|
|
||||||
models.Index(fields=['year', 'status'], name='car_year_status_idx'),
|
|
||||||
models.Index(fields=['status'], name='car_active_status_idx',
|
|
||||||
condition=Q(status=CarStatusChoices.AVAILABLE)),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
make = self.id_car_make.name if self.id_car_make else "Unknown Make"
|
make = self.id_car_make.name if self.id_car_make else "Unknown Make"
|
||||||
@ -890,9 +823,6 @@ class CarFinance(models.Model):
|
|||||||
selling_price = models.DecimalField(
|
selling_price = models.DecimalField(
|
||||||
max_digits=14, decimal_places=2, verbose_name=_("Selling Price")
|
max_digits=14, decimal_places=2, verbose_name=_("Selling Price")
|
||||||
)
|
)
|
||||||
marked_price = models.DecimalField(
|
|
||||||
max_digits=14, decimal_places=2, verbose_name=_("Marked Price")
|
|
||||||
)
|
|
||||||
discount_amount = models.DecimalField(
|
discount_amount = models.DecimalField(
|
||||||
max_digits=14,
|
max_digits=14,
|
||||||
decimal_places=2,
|
decimal_places=2,
|
||||||
@ -925,7 +855,7 @@ class CarFinance(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def vat_amount(self):
|
def vat_amount(self):
|
||||||
vat = VatRate.objects.filter(dealer=self.car.dealer, is_active=True).first()
|
vat = VatRate.objects.filter(is_active=True).first()
|
||||||
if vat:
|
if vat:
|
||||||
return (self.total_discount * Decimal(vat.rate)).quantize(Decimal("0.01"))
|
return (self.total_discount * Decimal(vat.rate)).quantize(Decimal("0.01"))
|
||||||
return Decimal("0.00")
|
return Decimal("0.00")
|
||||||
@ -961,12 +891,6 @@ class CarFinance(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Car Financial Details")
|
verbose_name = _("Car Financial Details")
|
||||||
verbose_name_plural = _("Car Financial Details")
|
verbose_name_plural = _("Car Financial Details")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['car'], name='car_finance_car_idx'),
|
|
||||||
models.Index(fields=['cost_price'], name='car_finance_cost_price_idx'),
|
|
||||||
models.Index(fields=['selling_price'], name='car_finance_selling_price_idx'),
|
|
||||||
models.Index(fields=['discount_amount'], name='car_finance_discount_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class ExteriorColors(models.Model, LocalizedNameMixin):
|
class ExteriorColors(models.Model, LocalizedNameMixin):
|
||||||
@ -977,10 +901,6 @@ class ExteriorColors(models.Model, LocalizedNameMixin):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Exterior Colors")
|
verbose_name = _("Exterior Colors")
|
||||||
verbose_name_plural = _("Exterior Colors")
|
verbose_name_plural = _("Exterior Colors")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['name'], name='exterior_color_name_idx'),
|
|
||||||
models.Index(fields=['arabic_name'], name='exterior_color_arabic_name_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name} ({self.rgb})"
|
return f"{self.name} ({self.rgb})"
|
||||||
@ -994,10 +914,6 @@ class InteriorColors(models.Model, LocalizedNameMixin):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Interior Colors")
|
verbose_name = _("Interior Colors")
|
||||||
verbose_name_plural = _("Interior Colors")
|
verbose_name_plural = _("Interior Colors")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['name'], name='interior_color_name_idx'),
|
|
||||||
models.Index(fields=['arabic_name'], name='interior_color_arabic_name_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name} ({self.rgb})"
|
return f"{self.name} ({self.rgb})"
|
||||||
@ -1016,11 +932,6 @@ class CarColors(models.Model):
|
|||||||
verbose_name = _("Color")
|
verbose_name = _("Color")
|
||||||
verbose_name_plural = _("Colors")
|
verbose_name_plural = _("Colors")
|
||||||
unique_together = ("car", "exterior", "interior")
|
unique_together = ("car", "exterior", "interior")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['exterior'], name='car_colors_exterior_idx'),
|
|
||||||
models.Index(fields=['interior'], name='car_colors_interior_idx'),
|
|
||||||
models.Index(fields=['exterior', 'interior'], name='car_colors_ext_int_combo_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.car} ({self.exterior.name}) ({self.interior.name})"
|
return f"{self.car} ({self.exterior.name}) ({self.interior.name})"
|
||||||
@ -1194,13 +1105,9 @@ class Dealer(models.Model, LocalizedNameMixin):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@property
|
|
||||||
def vat_rate(self):
|
|
||||||
return VatRate.objects.get(dealer=self,is_active=True).rate
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Dealer")
|
verbose_name = _("Dealer")
|
||||||
verbose_name_plural = _("Dealers")
|
verbose_name_plural = _("Dealers")
|
||||||
indexes = [models.Index(fields=["name"])]
|
|
||||||
# permissions = [
|
# permissions = [
|
||||||
# ('change_dealer_type', 'Can change dealer type'),
|
# ('change_dealer_type', 'Can change dealer type'),
|
||||||
# ]
|
# ]
|
||||||
@ -1230,12 +1137,6 @@ class Staff(models.Model, LocalizedNameMixin):
|
|||||||
staff_type = models.CharField(
|
staff_type = models.CharField(
|
||||||
choices=StaffTypes.choices, max_length=255, verbose_name=_("Staff Type")
|
choices=StaffTypes.choices, max_length=255, verbose_name=_("Staff Type")
|
||||||
)
|
)
|
||||||
address = models.CharField(
|
|
||||||
max_length=200, blank=True, null=True, verbose_name=_("Address")
|
|
||||||
)
|
|
||||||
image = models.ImageField(
|
|
||||||
upload_to="staff/", blank=True, null=True, verbose_name=_("Image")
|
|
||||||
)
|
|
||||||
active = models.BooleanField(default=True, verbose_name=_("Active"))
|
active = models.BooleanField(default=True, verbose_name=_("Active"))
|
||||||
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
|
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
|
||||||
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
|
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
|
||||||
@ -1287,7 +1188,7 @@ class Staff(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def groups(self):
|
def groups(self):
|
||||||
return CustomGroup.objects.select_related("group").filter(pk__in=[x.customgroup.pk for x in self.user.groups.all()])
|
return CustomGroup.objects.filter(pk__in=[x.customgroup.pk for x in self.user.groups.all()])
|
||||||
|
|
||||||
def clear_groups(self):
|
def clear_groups(self):
|
||||||
self.remove_superuser_permission()
|
self.remove_superuser_permission()
|
||||||
@ -1298,28 +1199,21 @@ class Staff(models.Model, LocalizedNameMixin):
|
|||||||
self.clear_groups()
|
self.clear_groups()
|
||||||
try:
|
try:
|
||||||
self.user.groups.add(group)
|
self.user.groups.add(group)
|
||||||
if "accountant" in group.name.lower():
|
if "accountant" in group.name.lower() or "manager" in group.name.lower():
|
||||||
self.add_superuser_permission()
|
self.add_superuser_permission()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
def add_superuser_permission(self):
|
def add_superuser_permission(self):
|
||||||
entity = self.dealer.entity
|
pass
|
||||||
if entity.managers.count() == 0:
|
# self.dealer.entity.managers.add(self.user)
|
||||||
entity.managers.add(self.user)
|
|
||||||
def remove_superuser_permission(self):
|
def remove_superuser_permission(self):
|
||||||
entity = self.dealer.entity
|
pass
|
||||||
if self.user in entity.managers.all():
|
# self.dealer.entity.managers.remove(self.user)
|
||||||
entity.managers.remove(self.user)
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Staff")
|
verbose_name = _("Staff")
|
||||||
verbose_name_plural = _("Staff")
|
verbose_name_plural = _("Staff")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=["name"]),
|
|
||||||
models.Index(fields=["staff_type"]),
|
|
||||||
]
|
|
||||||
permissions = []
|
permissions = []
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -1475,13 +1369,6 @@ class Customer(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Customer")
|
verbose_name = _("Customer")
|
||||||
verbose_name_plural = _("Customers")
|
verbose_name_plural = _("Customers")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=["title"]),
|
|
||||||
models.Index(fields=["first_name"]),
|
|
||||||
models.Index(fields=["last_name"]),
|
|
||||||
models.Index(fields=["email"]),
|
|
||||||
models.Index(fields=["phone_number"]),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# middle = f" {self.middle_name}" if self.middle_name else ""
|
# middle = f" {self.middle_name}" if self.middle_name else ""
|
||||||
@ -1620,11 +1507,6 @@ class Organization(models.Model, LocalizedNameMixin):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Organization")
|
verbose_name = _("Organization")
|
||||||
verbose_name_plural = _("Organizations")
|
verbose_name_plural = _("Organizations")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=["name"]),
|
|
||||||
models.Index(fields=["email"]),
|
|
||||||
models.Index(fields=["phone_number"]),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@ -1814,17 +1696,6 @@ class Lead(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Lead")
|
verbose_name = _("Lead")
|
||||||
verbose_name_plural = _("Leads")
|
verbose_name_plural = _("Leads")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=["dealer"]),
|
|
||||||
models.Index(fields=["customer"]),
|
|
||||||
models.Index(fields=["organization"]),
|
|
||||||
models.Index(fields=["staff"]),
|
|
||||||
models.Index(fields=["first_name"]),
|
|
||||||
models.Index(fields=["last_name"]),
|
|
||||||
models.Index(fields=["email"]),
|
|
||||||
models.Index(fields=["phone_number"]),
|
|
||||||
models.Index(fields=["created"]),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.first_name} {self.last_name}"
|
return f"{self.first_name} {self.last_name}"
|
||||||
@ -1999,14 +1870,6 @@ class Schedule(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["-scheduled_at"]
|
ordering = ["-scheduled_at"]
|
||||||
verbose_name = _("Schedule")
|
|
||||||
verbose_name_plural = _("Schedules")
|
|
||||||
indexes = [
|
|
||||||
models.Index(fields=["dealer"]),
|
|
||||||
models.Index(fields=["customer"]),
|
|
||||||
models.Index(fields=["content_type", "object_id"]),
|
|
||||||
models.Index(fields=["scheduled_at"]),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class LeadStatusHistory(models.Model):
|
class LeadStatusHistory(models.Model):
|
||||||
@ -2179,14 +2042,6 @@ class Opportunity(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Opportunity")
|
verbose_name = _("Opportunity")
|
||||||
verbose_name_plural = _("Opportunities")
|
verbose_name_plural = _("Opportunities")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=["dealer"]),
|
|
||||||
models.Index(fields=["customer"]),
|
|
||||||
models.Index(fields=["car"]),
|
|
||||||
models.Index(fields=["lead"]),
|
|
||||||
models.Index(fields=["organization"]),
|
|
||||||
models.Index(fields=["created"]),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.customer:
|
if self.customer:
|
||||||
@ -2211,19 +2066,6 @@ class Notes(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Note")
|
verbose_name = _("Note")
|
||||||
verbose_name_plural = _("Notes")
|
verbose_name_plural = _("Notes")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['dealer'], name='note_dealer_idx'),
|
|
||||||
models.Index(fields=['created_by'], name='note_created_by_idx'),
|
|
||||||
models.Index(fields=['content_type'], name='note_content_type_idx'),
|
|
||||||
models.Index(fields=['content_type', 'object_id'], name='note_content_object_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['created'], name='note_created_date_idx'),
|
|
||||||
models.Index(fields=['updated'], name='note_updated_date_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['dealer', 'created'], name='note_dealer_created_idx'),
|
|
||||||
models.Index(fields=['content_type', 'object_id', 'created'],
|
|
||||||
name='note_content_obj_created_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Note by {self.created_by.first_name} on {self.content_object}"
|
return f"Note by {self.created_by.first_name} on {self.content_object}"
|
||||||
@ -2254,19 +2096,6 @@ class Tasks(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Task")
|
verbose_name = _("Task")
|
||||||
verbose_name_plural = _("Tasks")
|
verbose_name_plural = _("Tasks")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['dealer'], name='task_dealer_idx'),
|
|
||||||
models.Index(fields=['created_by'], name='task_created_by_idx'),
|
|
||||||
models.Index(fields=['content_type'], name='task_content_type_idx'),
|
|
||||||
models.Index(fields=['content_type', 'object_id'], name='task_content_object_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['created'], name='task_created_date_idx'),
|
|
||||||
models.Index(fields=['updated'], name='task_updated_date_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['dealer', 'created'], name='task_dealer_created_idx'),
|
|
||||||
models.Index(fields=['content_type', 'object_id', 'created'],
|
|
||||||
name='task_content_obj_created_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Task by {self.created_by.email} on {self.content_object}"
|
return f"Task by {self.created_by.email} on {self.content_object}"
|
||||||
@ -2295,17 +2124,6 @@ class Email(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Email")
|
verbose_name = _("Email")
|
||||||
verbose_name_plural = _("Emails")
|
verbose_name_plural = _("Emails")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['created_by'], name='email_created_by_idx'),
|
|
||||||
models.Index(fields=['content_type'], name='email_content_type_idx'),
|
|
||||||
models.Index(fields=['content_type', 'object_id'], name='email_content_object_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['created'], name='email_created_date_idx'),
|
|
||||||
models.Index(fields=['updated'], name='email_updated_date_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['content_type', 'object_id', 'created'],
|
|
||||||
name='email_content_obj_created_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Email by {self.created_by.first_name} on {self.content_object}"
|
return f"Email by {self.created_by.first_name} on {self.content_object}"
|
||||||
@ -2331,17 +2149,6 @@ class Activity(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Activity")
|
verbose_name = _("Activity")
|
||||||
verbose_name_plural = _("Activities")
|
verbose_name_plural = _("Activities")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['created_by'], name='activity_created_by_idx'),
|
|
||||||
models.Index(fields=['content_type'], name='activity_content_type_idx'),
|
|
||||||
models.Index(fields=['content_type', 'object_id'], name='activity_content_object_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['created'], name='activity_created_date_idx'),
|
|
||||||
models.Index(fields=['updated'], name='activity_updated_date_idx'),
|
|
||||||
|
|
||||||
models.Index(fields=['content_type', 'object_id', 'created'],
|
|
||||||
name='a_content_obj_created_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.get_activity_type_display()} by {self.created_by.get_full_name} on {self.content_object}"
|
return f"{self.get_activity_type_display()} by {self.created_by.get_full_name} on {self.content_object}"
|
||||||
@ -2360,12 +2167,6 @@ class Notification(models.Model):
|
|||||||
verbose_name_plural = _("Notifications")
|
verbose_name_plural = _("Notifications")
|
||||||
ordering = ["-created"]
|
ordering = ["-created"]
|
||||||
|
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['user'], name='notification_user_idx'),
|
|
||||||
models.Index(fields=['is_read'], name='notification_is_read_idx'),
|
|
||||||
models.Index(fields=['created'], name='notification_created_date_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.message
|
return self.message
|
||||||
|
|
||||||
@ -2429,12 +2230,6 @@ class Vendor(models.Model, LocalizedNameMixin):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Vendor")
|
verbose_name = _("Vendor")
|
||||||
verbose_name_plural = _("Vendors")
|
verbose_name_plural = _("Vendors")
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['slug'], name='vendor_slug_idx'),
|
|
||||||
models.Index(fields=['active'], name='vendor_active_idx'),
|
|
||||||
models.Index(fields=['crn'], name='vendor_crn_idx'),
|
|
||||||
models.Index(fields=['vrn'], name='vendor_vrn_idx'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@ -2627,7 +2422,7 @@ class SaleOrder(models.Model):
|
|||||||
blank=True,
|
blank=True,
|
||||||
)
|
)
|
||||||
comments = models.TextField(blank=True, null=True)
|
comments = models.TextField(blank=True, null=True)
|
||||||
formatted_order_id = models.CharField(max_length=20, unique=True, editable=False)
|
formatted_order_id = models.CharField(max_length=10, unique=True, editable=False)
|
||||||
|
|
||||||
# Status and Dates
|
# Status and Dates
|
||||||
status = models.CharField(
|
status = models.CharField(
|
||||||
@ -2676,21 +2471,9 @@ class SaleOrder(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Sales Order")
|
verbose_name = "Sales Order"
|
||||||
verbose_name_plural = _("Sales Orders")
|
verbose_name_plural = "Sales Orders"
|
||||||
ordering = ["-order_date"] # Order by most recent first
|
ordering = ["-order_date"] # Order by most recent first
|
||||||
indexes = [
|
|
||||||
models.Index(fields=["dealer"]),
|
|
||||||
models.Index(fields=["estimate"]),
|
|
||||||
models.Index(fields=["invoice"]),
|
|
||||||
models.Index(fields=["opportunity"]),
|
|
||||||
models.Index(fields=["customer"]),
|
|
||||||
models.Index(fields=["status"]),
|
|
||||||
models.Index(fields=["order_date"]),
|
|
||||||
models.Index(fields=["expected_delivery_date"]),
|
|
||||||
models.Index(fields=["actual_delivery_date"]),
|
|
||||||
models.Index(fields=["cancelled_date"]),
|
|
||||||
]
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.formatted_order_id:
|
if not self.formatted_order_id:
|
||||||
@ -2748,14 +2531,6 @@ class CustomGroup(models.Model):
|
|||||||
group = models.OneToOneField(
|
group = models.OneToOneField(
|
||||||
"auth.Group", verbose_name=_("Group"), on_delete=models.CASCADE
|
"auth.Group", verbose_name=_("Group"), on_delete=models.CASCADE
|
||||||
)
|
)
|
||||||
class Meta:
|
|
||||||
verbose_name = _("Custom Group")
|
|
||||||
verbose_name_plural = _("Custom Groups")
|
|
||||||
indexes = [
|
|
||||||
models.Index(fields=["name"]),
|
|
||||||
models.Index(fields=["dealer"]),
|
|
||||||
models.Index(fields=["group"]),
|
|
||||||
]
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def entity(self):
|
def entity(self):
|
||||||
@ -2891,7 +2666,7 @@ class CustomGroup(models.Model):
|
|||||||
app="inventory",
|
app="inventory",
|
||||||
allowed_models=[
|
allowed_models=[
|
||||||
"saleorder",
|
"saleorder",
|
||||||
# "payment",
|
"payment",
|
||||||
"staff",
|
"staff",
|
||||||
"schedule",
|
"schedule",
|
||||||
"activity",
|
"activity",
|
||||||
@ -2933,8 +2708,7 @@ class CustomGroup(models.Model):
|
|||||||
"tasks",
|
"tasks",
|
||||||
"activity",
|
"activity",
|
||||||
"payment",
|
"payment",
|
||||||
"vendor",
|
'vendor'],
|
||||||
],
|
|
||||||
other_perms=[
|
other_perms=[
|
||||||
"view_car",
|
"view_car",
|
||||||
"view_carlocation",
|
"view_carlocation",
|
||||||
@ -2957,6 +2731,7 @@ class CustomGroup(models.Model):
|
|||||||
"itemmodel",
|
"itemmodel",
|
||||||
"invoicemodel",
|
"invoicemodel",
|
||||||
"vendormodel",
|
"vendormodel",
|
||||||
|
|
||||||
"journalentrymodel",
|
"journalentrymodel",
|
||||||
"purchaseordermodel",
|
"purchaseordermodel",
|
||||||
"estimatemodel",
|
"estimatemodel",
|
||||||
@ -3160,13 +2935,6 @@ class PoItemsUploaded(models.Model):
|
|||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _("PO Items")
|
|
||||||
verbose_name_plural = _("PO Items")
|
|
||||||
indexes = [
|
|
||||||
models.Index(fields=["po"]),
|
|
||||||
models.Index(fields=["item"]),
|
|
||||||
]
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
return self.item.item.name.split('||')
|
return self.item.item.name.split('||')
|
||||||
class ExtraInfo(models.Model):
|
class ExtraInfo(models.Model):
|
||||||
@ -3176,13 +2944,7 @@ class ExtraInfo(models.Model):
|
|||||||
- JSON data storage
|
- JSON data storage
|
||||||
- Tracking fields
|
- Tracking fields
|
||||||
"""
|
"""
|
||||||
dealer = models.ForeignKey(
|
# Primary GenericForeignKey (main linked object)
|
||||||
Dealer,
|
|
||||||
on_delete=models.SET_NULL,
|
|
||||||
null=True,
|
|
||||||
blank=True,
|
|
||||||
related_name="extra_info"
|
|
||||||
)
|
|
||||||
content_type = models.ForeignKey(
|
content_type = models.ForeignKey(
|
||||||
ContentType,
|
ContentType,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
@ -3224,9 +2986,7 @@ class ExtraInfo(models.Model):
|
|||||||
models.Index(fields=['content_type', 'object_id']),
|
models.Index(fields=['content_type', 'object_id']),
|
||||||
models.Index(fields=['related_content_type', 'related_object_id']),
|
models.Index(fields=['related_content_type', 'related_object_id']),
|
||||||
]
|
]
|
||||||
verbose_name_plural = _("Extra Info")
|
verbose_name_plural = "Extra Info"
|
||||||
verbose_name = _("Extra Info")
|
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"ExtraInfo for {self.content_object} ({self.content_type})"
|
return f"ExtraInfo for {self.content_object} ({self.content_type})"
|
||||||
@ -3252,8 +3012,8 @@ class ExtraInfo(models.Model):
|
|||||||
related_content_type=related_content_type,
|
related_content_type=related_content_type,
|
||||||
related_object_id=staff.pk
|
related_object_id=staff.pk
|
||||||
)
|
)
|
||||||
# qs = qs.select_related("customer","estimate","invoice")
|
|
||||||
return [x.content_object.sale_orders.select_related("customer","estimate","invoice").first() for x in qs if x.content_object.sale_orders.first()]
|
return [x.content_object.sale_orders.first() for x in qs if x.content_object.sale_orders.first()]
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_invoices(cls, staff=None, is_dealer=False):
|
def get_invoices(cls, staff=None, is_dealer=False):
|
||||||
if not staff and not is_dealer:
|
if not staff and not is_dealer:
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import logging
|
import logging
|
||||||
from .models import Dealer
|
|
||||||
from django.core.exceptions import ImproperlyConfigured,ValidationError
|
from django.core.exceptions import ImproperlyConfigured,ValidationError
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin,PermissionRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin,PermissionRequiredMixin
|
||||||
from django_ledger.forms.bill import (
|
from django_ledger.forms.bill import (
|
||||||
@ -31,8 +30,7 @@ from django_ledger.models import PurchaseOrderModel,EstimateModel,BillModel
|
|||||||
from django.views.generic.detail import SingleObjectMixin
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
from django.views.generic.edit import UpdateView
|
from django.views.generic.edit import UpdateView
|
||||||
from django.views.generic.base import RedirectView
|
from django.views.generic.base import RedirectView
|
||||||
from django.views.generic.list import ListView
|
from .models import Dealer
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -215,7 +213,7 @@ class PurchaseOrderModelUpdateView(LoginRequiredMixin,
|
|||||||
if form.has_changed():
|
if form.has_changed():
|
||||||
po_items_qs = ItemTransactionModel.objects.for_po(
|
po_items_qs = ItemTransactionModel.objects.for_po(
|
||||||
entity_slug=self.kwargs['entity_slug'],
|
entity_slug=self.kwargs['entity_slug'],
|
||||||
user_model=self.request.admin,
|
user_model=dealer.entity.admin,
|
||||||
po_pk=po_model.uuid,
|
po_pk=po_model.uuid,
|
||||||
).select_related('bill_model')
|
).select_related('bill_model')
|
||||||
|
|
||||||
@ -316,23 +314,12 @@ class BasePurchaseOrderActionActionView(LoginRequiredMixin,
|
|||||||
)
|
)
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
# --- Single-line log for ValidationError ---
|
# --- Single-line log for ValidationError ---
|
||||||
print(f"User {user_username} encountered a validation error "
|
|
||||||
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
|
|
||||||
f"Error: {e}")
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"User {user_username} encountered a validation error "
|
f"User {user_username} encountered a validation error "
|
||||||
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
|
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
|
||||||
f"Error: {e}"
|
f"Error: {e}"
|
||||||
)
|
)
|
||||||
except AttributeError as e:
|
print(e)
|
||||||
print(f"User {user_username} encountered an AttributeError "
|
|
||||||
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
|
|
||||||
f"Error: {e}")
|
|
||||||
logger.warning(
|
|
||||||
f"User {user_username} encountered an AttributeError "
|
|
||||||
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
|
|
||||||
f"Error: {e}"
|
|
||||||
)
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
class BillModelDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
class BillModelDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
||||||
@ -419,23 +406,19 @@ class BillModelUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateVie
|
|||||||
|
|
||||||
def get_form(self, form_class=None):
|
def get_form(self, form_class=None):
|
||||||
form_class = self.get_form_class()
|
form_class = self.get_form_class()
|
||||||
entity_model = self.request.dealer.entity
|
dealer = get_object_or_404(Dealer,slug=self.kwargs['dealer_slug'])
|
||||||
|
entity_model = dealer.entity
|
||||||
if self.request.method == 'POST' and self.action_update_items:
|
if self.request.method == 'POST' and self.action_update_items:
|
||||||
return form_class(
|
return form_class(
|
||||||
entity_model=entity_model,
|
entity_model=entity_model,
|
||||||
user_model=self.request.admin,
|
user_model=dealer.entity.admin,
|
||||||
instance=self.object
|
instance=self.object
|
||||||
)
|
)
|
||||||
form = form_class(
|
return form_class(
|
||||||
entity_model=entity_model,
|
entity_model=entity_model,
|
||||||
user_model=self.request.admin,
|
user_model=dealer.entity.admin,
|
||||||
**self.get_form_kwargs()
|
**self.get_form_kwargs()
|
||||||
)
|
)
|
||||||
try:
|
|
||||||
form.initial['amount_paid'] = self.object.get_itemtxs_data()[1]["total_amount__sum"]
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
return form
|
|
||||||
|
|
||||||
def get_form_class(self):
|
def get_form_class(self):
|
||||||
bill_model: BillModel = self.object
|
bill_model: BillModel = self.object
|
||||||
@ -659,41 +642,3 @@ class BaseBillActionView(LoginRequiredMixin,PermissionRequiredMixin, RedirectVie
|
|||||||
level=messages.ERROR,
|
level=messages.ERROR,
|
||||||
extra_tags='is-danger')
|
extra_tags='is-danger')
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class InventoryListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|
||||||
template_name = 'django_ledger/inventory/inventory_list.html'
|
|
||||||
context_object_name = 'inventory_list'
|
|
||||||
http_method_names = ['get']
|
|
||||||
|
|
||||||
def get_context_data(self, *, object_list=None, **kwargs):
|
|
||||||
context = super(InventoryListView, self).get_context_data(**kwargs)
|
|
||||||
qs = self.get_queryset()
|
|
||||||
|
|
||||||
# evaluates the queryset...
|
|
||||||
context['qs_count'] = qs.count()
|
|
||||||
|
|
||||||
# ordered inventory...
|
|
||||||
ordered_qs = qs.is_ordered()
|
|
||||||
context['inventory_ordered'] = ordered_qs
|
|
||||||
|
|
||||||
# in transit inventory...
|
|
||||||
in_transit_qs = qs.in_transit()
|
|
||||||
context['inventory_in_transit'] = in_transit_qs
|
|
||||||
|
|
||||||
# on hand inventory...
|
|
||||||
received_qs = qs.is_received()
|
|
||||||
context['inventory_received'] = received_qs
|
|
||||||
|
|
||||||
context['page_title'] = _('Inventory')
|
|
||||||
context['header_title'] = _('Inventory Status')
|
|
||||||
context['header_subtitle'] = _('Ordered/In Transit/On Hand')
|
|
||||||
context['header_subtitle_icon'] = 'ic:round-inventory'
|
|
||||||
return context
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
if self.queryset is None:
|
|
||||||
self.queryset = ItemTransactionModel.objects.inventory_pipeline_aggregate(
|
|
||||||
entity_slug=self.kwargs['entity_slug'],
|
|
||||||
)
|
|
||||||
return super().get_queryset()
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from inventory.tasks import create_coa_accounts, create_make_accounts
|
from inventory.tasks import create_coa_accounts, create_make_accounts
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django.db.models.signals import post_save, post_delete
|
from django.db.models.signals import post_save, post_delete
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from appointment.models import Service
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
@ -672,7 +672,6 @@ def create_dealer_settings(sender, instance, created, **kwargs):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if created:
|
if created:
|
||||||
models.VatRate.objects.create(dealer=instance)
|
|
||||||
models.DealerSettings.objects.create(
|
models.DealerSettings.objects.create(
|
||||||
dealer=instance,
|
dealer=instance,
|
||||||
invoice_cash_account=instance.entity.get_all_accounts()
|
invoice_cash_account=instance.entity.get_all_accounts()
|
||||||
@ -942,11 +941,6 @@ def create_po_item_upload(sender,instance,created,**kwargs):
|
|||||||
dealer = models.Dealer.objects.get(entity=instance.entity)
|
dealer = models.Dealer.objects.get(entity=instance.entity)
|
||||||
models.PoItemsUploaded.objects.create(dealer=dealer,po=instance, item=item, status="fulfilled")
|
models.PoItemsUploaded.objects.create(dealer=dealer,po=instance, item=item, status="fulfilled")
|
||||||
|
|
||||||
@receiver(post_save, sender=models.Staff)
|
|
||||||
def add_service_to_staff(sender,instance,created,**kwargs):
|
|
||||||
if created:
|
|
||||||
for service in Service.objects.all():
|
|
||||||
instance.staff_member.services_offered.add(service)
|
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
######################Notification########################
|
######################Notification########################
|
||||||
@ -1098,6 +1092,6 @@ def bill_model_after_approve_notification(sender, instance, created, **kwargs):
|
|||||||
message=f"""
|
message=f"""
|
||||||
Bill {instance.bill_number} has been approved.
|
Bill {instance.bill_number} has been approved.
|
||||||
<a href="{reverse('bill-detail', kwargs={'dealer_slug': dealer.slug, 'entity_slug':dealer.entity.slug, 'bill_pk': instance.pk})}" target="_blank">View</a>.
|
<a href="{reverse('bill-detail', kwargs={'dealer_slug': dealer.slug, 'entity_slug':dealer.entity.slug, 'bill_pk': instance.pk})}" target="_blank">View</a>.
|
||||||
please complete the bill payment.
|
please comlete the bill payment.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
1137
inventory/tasks.py
1137
inventory/tasks.py
File diff suppressed because it is too large
Load Diff
@ -51,11 +51,6 @@ urlpatterns = [
|
|||||||
views.DealerUpdateView.as_view(),
|
views.DealerUpdateView.as_view(),
|
||||||
name="dealer_update",
|
name="dealer_update",
|
||||||
),
|
),
|
||||||
path(
|
|
||||||
"dealers/<slug:slug>/dealer_vat_rate_update/",
|
|
||||||
views.dealer_vat_rate_update,
|
|
||||||
name="dealer_vat_rate_update",
|
|
||||||
),
|
|
||||||
# path('dealers/<int:pk>/delete/', views.DealerDeleteView.as_view(), name='dealer_delete'),
|
# path('dealers/<int:pk>/delete/', views.DealerDeleteView.as_view(), name='dealer_delete'),
|
||||||
# CRM URLs
|
# CRM URLs
|
||||||
path(
|
path(
|
||||||
@ -688,17 +683,6 @@ urlpatterns = [
|
|||||||
views.preview_sale_order,
|
views.preview_sale_order,
|
||||||
name="preview_sale_order",
|
name="preview_sale_order",
|
||||||
),
|
),
|
||||||
path(
|
|
||||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/update_estimate_discount/",
|
|
||||||
views.update_estimate_discount,
|
|
||||||
name="update_estimate_discount",
|
|
||||||
),
|
|
||||||
path(
|
|
||||||
"<slug:dealer_slug>/sales/estimates/<uuid:pk>/update_estimate_additionals/",
|
|
||||||
views.update_estimate_additionals,
|
|
||||||
name="update_estimate_additionals",
|
|
||||||
),
|
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
# Invoice
|
# Invoice
|
||||||
###############################################
|
###############################################
|
||||||
|
|||||||
@ -22,7 +22,6 @@ from django_ledger.models.items import ItemModel
|
|||||||
from django.utils.translation import get_language
|
from django.utils.translation import get_language
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
from django_ledger.models.transactions import TransactionModel
|
from django_ledger.models.transactions import TransactionModel
|
||||||
from django_ledger.models.journal_entry import JournalEntryModel
|
from django_ledger.models.journal_entry import JournalEntryModel
|
||||||
|
|
||||||
@ -474,7 +473,7 @@ def set_invoice_payment(dealer, entity, invoice, amount, payment_method):
|
|||||||
calculator = CarFinanceCalculator(invoice)
|
calculator = CarFinanceCalculator(invoice)
|
||||||
finance_data = calculator.get_finance_data()
|
finance_data = calculator.get_finance_data()
|
||||||
|
|
||||||
handle_account_process(invoice, amount, finance_data)
|
# handle_account_process(invoice, amount, finance_data)
|
||||||
invoice.make_payment(amount)
|
invoice.make_payment(amount)
|
||||||
invoice.save()
|
invoice.save()
|
||||||
|
|
||||||
@ -997,15 +996,13 @@ class CarFinanceCalculator:
|
|||||||
ADDITIONAL_SERVICES_KEY = "additional_services"
|
ADDITIONAL_SERVICES_KEY = "additional_services"
|
||||||
|
|
||||||
def __init__(self, model):
|
def __init__(self, model):
|
||||||
self.dealer = models.Dealer.objects.get(entity=model.entity)
|
|
||||||
self.model = model
|
self.model = model
|
||||||
self.vat_rate = self._get_vat_rate()
|
self.vat_rate = self._get_vat_rate()
|
||||||
self.item_transactions = self._get_item_transactions()
|
self.item_transactions = self._get_item_transactions()
|
||||||
self.additional_services = self._get_additional_services()
|
self.additional_services = self._get_additional_services()
|
||||||
self.extra_info = models.ExtraInfo.objects.get(dealer=self.dealer,content_type=ContentType.objects.get_for_model(model),object_id=model.pk)
|
|
||||||
|
|
||||||
def _get_vat_rate(self):
|
def _get_vat_rate(self):
|
||||||
vat = models.VatRate.objects.filter(dealer=self.dealer,is_active=True).first()
|
vat = models.VatRate.objects.filter(is_active=True).first()
|
||||||
if not vat:
|
if not vat:
|
||||||
raise ObjectDoesNotExist("No active VAT rate found")
|
raise ObjectDoesNotExist("No active VAT rate found")
|
||||||
return vat.rate
|
return vat.rate
|
||||||
@ -1028,6 +1025,7 @@ class CarFinanceCalculator:
|
|||||||
car_finance = self._get_nested_value(item, self.CAR_FINANCE_KEY)
|
car_finance = self._get_nested_value(item, self.CAR_FINANCE_KEY)
|
||||||
car_info = self._get_nested_value(item, self.CAR_INFO_KEY)
|
car_info = self._get_nested_value(item, self.CAR_INFO_KEY)
|
||||||
unit_price = Decimal(car_finance.get("selling_price", 0))
|
unit_price = Decimal(car_finance.get("selling_price", 0))
|
||||||
|
print(item.item_model.car.finances)
|
||||||
return {
|
return {
|
||||||
"item_number": item.item_model.item_number,
|
"item_number": item.item_model.item_number,
|
||||||
"vin": car_info.get("vin"),
|
"vin": car_info.get("vin"),
|
||||||
@ -1039,7 +1037,6 @@ class CarFinanceCalculator:
|
|||||||
"mileage": car_info.get("mileage"),
|
"mileage": car_info.get("mileage"),
|
||||||
"cost_price": car_finance.get("cost_price"),
|
"cost_price": car_finance.get("cost_price"),
|
||||||
"selling_price": car_finance.get("selling_price"),
|
"selling_price": car_finance.get("selling_price"),
|
||||||
"marked_price": car_finance.get("marked_price"),
|
|
||||||
"discount": car_finance.get("discount_amount"),
|
"discount": car_finance.get("discount_amount"),
|
||||||
"quantity": quantity,
|
"quantity": quantity,
|
||||||
"unit_price": unit_price,
|
"unit_price": unit_price,
|
||||||
@ -1073,15 +1070,13 @@ class CarFinanceCalculator:
|
|||||||
Decimal(x.get("price_")) for x in self._get_additional_services()
|
Decimal(x.get("price_")) for x in self._get_additional_services()
|
||||||
)
|
)
|
||||||
|
|
||||||
total_discount = self.extra_info.data.get("discount")
|
total_discount = sum(
|
||||||
|
Decimal(
|
||||||
# total_discount = sum(
|
self._get_nested_value(item, self.CAR_FINANCE_KEY, "discount_amount")
|
||||||
# Decimal(
|
)
|
||||||
# self._get_nested_value(item, self.CAR_FINANCE_KEY, "discount_amount")
|
for item in self.item_transactions
|
||||||
# )
|
)
|
||||||
# for item in self.item_transactions
|
total_price_discounted = total_price - total_discount
|
||||||
# )
|
|
||||||
total_price_discounted = total_price - Decimal(total_discount)
|
|
||||||
total_vat_amount = total_price_discounted * self.vat_rate
|
total_vat_amount = total_price_discounted * self.vat_rate
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -1090,7 +1085,7 @@ class CarFinanceCalculator:
|
|||||||
), # total_price_before_discount,
|
), # total_price_before_discount,
|
||||||
"total_price": round(total_price_discounted, 2), # total_price_discounted,
|
"total_price": round(total_price_discounted, 2), # total_price_discounted,
|
||||||
"total_vat_amount": round(total_vat_amount, 2), # total_vat_amount,
|
"total_vat_amount": round(total_vat_amount, 2), # total_vat_amount,
|
||||||
"total_discount": round(Decimal(total_discount)),
|
"total_discount": round(total_discount, 2),
|
||||||
"total_additionals": round(total_additionals, 2), # total_additionals,
|
"total_additionals": round(total_additionals, 2), # total_additionals,
|
||||||
"grand_total": round(
|
"grand_total": round(
|
||||||
total_price_discounted + total_vat_amount + total_additionals, 2
|
total_price_discounted + total_vat_amount + total_additionals, 2
|
||||||
@ -1144,6 +1139,7 @@ def get_item_transactions(txs):
|
|||||||
data["customer"] = tx.invoice_model.customer
|
data["customer"] = tx.invoice_model.customer
|
||||||
if bool(data):
|
if bool(data):
|
||||||
transactions.append(data)
|
transactions.append(data)
|
||||||
|
print(data)
|
||||||
return transactions
|
return transactions
|
||||||
|
|
||||||
|
|
||||||
@ -1295,7 +1291,7 @@ def handle_account_process(invoice, amount, finance_data):
|
|||||||
exc_info=True
|
exc_info=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print(e)
|
||||||
car.finances.is_sold = True
|
car.finances.is_sold = True
|
||||||
car.finances.save()
|
car.finances.save()
|
||||||
car.item_model.save()
|
car.item_model.save()
|
||||||
@ -1432,7 +1428,7 @@ def handle_payment(request, order):
|
|||||||
print("Failed to process payment:", data)
|
print("Failed to process payment:", data)
|
||||||
#
|
#
|
||||||
data = response.json()
|
data = response.json()
|
||||||
|
print(data)
|
||||||
# order.status = AbstractOrder.STATUS.NEW
|
# order.status = AbstractOrder.STATUS.NEW
|
||||||
order.save()
|
order.save()
|
||||||
#
|
#
|
||||||
|
|||||||
@ -88,6 +88,7 @@ from django_ledger.views import (
|
|||||||
LedgerModelCreateView as LedgerModelCreateViewBase,
|
LedgerModelCreateView as LedgerModelCreateViewBase,
|
||||||
)
|
)
|
||||||
from django_ledger.forms.account import AccountModelCreateForm, AccountModelUpdateForm
|
from django_ledger.forms.account import AccountModelCreateForm, AccountModelUpdateForm
|
||||||
|
from django_ledger.views.inventory import InventoryListView as InventoryListViewBase
|
||||||
from django_ledger.views.entity import (
|
from django_ledger.views.entity import (
|
||||||
EntityModelDetailBaseView,
|
EntityModelDetailBaseView,
|
||||||
EntityModelDetailHandlerView,
|
EntityModelDetailHandlerView,
|
||||||
@ -142,7 +143,6 @@ from .override import (
|
|||||||
BillModelDetailView as BillModelDetailViewBase,
|
BillModelDetailView as BillModelDetailViewBase,
|
||||||
BillModelUpdateView as BillModelUpdateViewBase,
|
BillModelUpdateView as BillModelUpdateViewBase,
|
||||||
BaseBillActionView as BaseBillActionViewBase,
|
BaseBillActionView as BaseBillActionViewBase,
|
||||||
InventoryListView as InventoryListViewBase,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from django_ledger.models import (
|
from django_ledger.models import (
|
||||||
@ -440,16 +440,8 @@ class ManagerDashboard(LoginRequiredMixin, TemplateView):
|
|||||||
transfer_cars = models.Car.objects.filter(
|
transfer_cars = models.Car.objects.filter(
|
||||||
dealer=dealer, status=models.CarStatusChoices.TRANSFER
|
dealer=dealer, status=models.CarStatusChoices.TRANSFER
|
||||||
).count()
|
).count()
|
||||||
try:
|
reserved_percentage = reserved_cars / total_cars * 100
|
||||||
reserved_percentage = reserved_cars / total_cars * 100
|
sold_percentage = sold_cars / total_cars * 100
|
||||||
except ZeroDivisionError as e:
|
|
||||||
print(f"error: {e}")
|
|
||||||
try:
|
|
||||||
sold_percentage = sold_cars / total_cars * 100
|
|
||||||
except ZeroDivisionError as e:
|
|
||||||
print(f"error: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
qs = (
|
qs = (
|
||||||
models.Car.objects.values("id_car_make__name")
|
models.Car.objects.values("id_car_make__name")
|
||||||
.annotate(count=Count("id"))
|
.annotate(count=Count("id"))
|
||||||
@ -1593,6 +1585,7 @@ class CarUpdateView(
|
|||||||
def get_form(self, form_class=None):
|
def get_form(self, form_class=None):
|
||||||
form = super().get_form(form_class)
|
form = super().get_form(form_class)
|
||||||
dealer = get_user_type(self.request)
|
dealer = get_user_type(self.request)
|
||||||
|
print(dealer.get_vendors())
|
||||||
form.fields["vendor"].queryset = dealer.vendors.all()
|
form.fields["vendor"].queryset = dealer.vendors.all()
|
||||||
return form
|
return form
|
||||||
|
|
||||||
@ -2131,16 +2124,12 @@ class DealerDetailView(LoginRequiredMixin, PermissionRequiredMixin,DetailView):
|
|||||||
context["cars_count"] = cars_count
|
context["cars_count"] = cars_count
|
||||||
context["allowed_users"] = dealer.user_quota
|
context["allowed_users"] = dealer.user_quota
|
||||||
context["allowed_cars"] = dealer.car_quota
|
context["allowed_cars"] = dealer.car_quota
|
||||||
context["vatform"] = forms.VatRateForm(initial={"rate": dealer.vat_rate})
|
|
||||||
context["quota_display"] = (
|
context["quota_display"] = (
|
||||||
f"{staff_count}/{dealer.user_quota}" if dealer.user_quota else "0"
|
f"{staff_count}/{dealer.user_quota}" if dealer.user_quota else "0"
|
||||||
)
|
)
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def dealer_vat_rate_update(request,slug):
|
|
||||||
dealer = get_object_or_404(models.Dealer,slug=slug)
|
|
||||||
models.VatRate.objects.filter(dealer=dealer).update(rate=request.POST.get("rate"))
|
|
||||||
return redirect("dealer_detail", slug=slug)
|
|
||||||
|
|
||||||
class DealerUpdateView(LoginRequiredMixin,PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
|
class DealerUpdateView(LoginRequiredMixin,PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
|
||||||
"""
|
"""
|
||||||
@ -2529,8 +2518,6 @@ def vendorDetailView(request, dealer_slug,slug):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class VendorCreateView(
|
class VendorCreateView(
|
||||||
LoginRequiredMixin,
|
LoginRequiredMixin,
|
||||||
PermissionRequiredMixin,
|
PermissionRequiredMixin,
|
||||||
@ -4311,14 +4298,11 @@ class EstimateListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|||||||
|
|
||||||
if any([self.request.is_dealer ,self.request.is_manager ,self.request.is_accountant]):
|
if any([self.request.is_dealer ,self.request.is_manager ,self.request.is_accountant]):
|
||||||
qs = models.ExtraInfo.objects.filter(
|
qs = models.ExtraInfo.objects.filter(
|
||||||
dealer=dealer,
|
|
||||||
content_type=ContentType.objects.get_for_model(EstimateModel),
|
content_type=ContentType.objects.get_for_model(EstimateModel),
|
||||||
related_content_type=ContentType.objects.get_for_model(models.Staff),
|
related_content_type=ContentType.objects.get_for_model(models.Staff),
|
||||||
)
|
)
|
||||||
print(qs)
|
|
||||||
elif self.request.is_staff and self.request.is_sales:
|
elif self.request.is_staff and self.request.is_sales:
|
||||||
qs = models.ExtraInfo.objects.filter(
|
qs = models.ExtraInfo.objects.filter(
|
||||||
dealer=dealer,
|
|
||||||
content_type=ContentType.objects.get_for_model(EstimateModel),
|
content_type=ContentType.objects.get_for_model(EstimateModel),
|
||||||
related_content_type=ContentType.objects.get_for_model(models.Staff),
|
related_content_type=ContentType.objects.get_for_model(models.Staff),
|
||||||
related_object_id=staff.pk,
|
related_object_id=staff.pk,
|
||||||
@ -4515,18 +4499,15 @@ def create_estimate(request, dealer_slug, slug=None):
|
|||||||
|
|
||||||
if staff:=getattr(request.user.staffmember,'staff',None):
|
if staff:=getattr(request.user.staffmember,'staff',None):
|
||||||
models.ExtraInfo.objects.create(
|
models.ExtraInfo.objects.create(
|
||||||
dealer=dealer,
|
|
||||||
content_object=estimate,
|
content_object=estimate,
|
||||||
related_object=staff,
|
related_object=staff,
|
||||||
created_by=request.user,
|
created_by=request.user,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
models.ExtraInfo.objects.create(
|
models.ExtraInfo.objects.create(
|
||||||
dealer=dealer,
|
|
||||||
content_object=estimate,
|
content_object=estimate,
|
||||||
related_object=request.user,
|
related_object=request.user,
|
||||||
created_by=request.user,
|
created_by=request.user,
|
||||||
data={"vat_rate": 0.15,"discount": 0},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
url = reverse(
|
url = reverse(
|
||||||
@ -4631,22 +4612,14 @@ class EstimateDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
|
|||||||
permission_required = ["django_ledger.view_estimatemodel"]
|
permission_required = ["django_ledger.view_estimatemodel"]
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
|
|
||||||
estimate = kwargs.get("object")
|
estimate = kwargs.get("object")
|
||||||
if estimate.get_itemtxs_data():
|
if estimate.get_itemtxs_data():
|
||||||
calculator = CarFinanceCalculator(estimate)
|
calculator = CarFinanceCalculator(estimate)
|
||||||
finance_data = calculator.get_finance_data()
|
finance_data = calculator.get_finance_data()
|
||||||
|
print(finance_data)
|
||||||
invoice_obj = InvoiceModel.objects.all().filter(ce_model=estimate).first()
|
invoice_obj = InvoiceModel.objects.all().filter(ce_model=estimate).first()
|
||||||
kwargs["data"] = finance_data
|
kwargs["data"] = finance_data
|
||||||
kwargs["invoice"] = invoice_obj
|
kwargs["invoice"] = invoice_obj
|
||||||
try:
|
|
||||||
cf = estimate.get_itemtxs_data()[0].first().item_model.car.finances
|
|
||||||
selected_items = cf.additional_services.filter(dealer=dealer)
|
|
||||||
form = forms.AdditionalFinancesForm()
|
|
||||||
form.initial["additional_finances"] = selected_items
|
|
||||||
kwargs["additionals_form"] = form
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(e)
|
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
@ -4726,31 +4699,6 @@ def create_sale_order(request, dealer_slug, pk):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@require_POST
|
|
||||||
def update_estimate_discount(request,dealer_slug,pk):
|
|
||||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
|
||||||
estimate = get_object_or_404(EstimateModel, pk=pk)
|
|
||||||
extra_info = models.ExtraInfo.objects.get(dealer=dealer,content_type=ContentType.objects.get_for_model(EstimateModel),object_id=estimate.pk)
|
|
||||||
discount_amount = request.POST.get("discount_amount",0)
|
|
||||||
|
|
||||||
extra_info.data.update({"discount":Decimal(discount_amount)})
|
|
||||||
extra_info.save()
|
|
||||||
return redirect("estimate_detail", dealer_slug=dealer_slug, pk=pk)
|
|
||||||
@login_required
|
|
||||||
@require_POST
|
|
||||||
def update_estimate_additionals(request,dealer_slug,pk):
|
|
||||||
dealer = get_object_or_404(models.Dealer, slug=dealer_slug)
|
|
||||||
form = forms.AdditionalFinancesForm(request.POST)
|
|
||||||
if request.method == "POST":
|
|
||||||
if form.is_valid():
|
|
||||||
estimate = get_object_or_404(EstimateModel, pk=pk)
|
|
||||||
car = estimate.get_itemtxs_data()[0].first().item_model.car
|
|
||||||
car.finances.additional_services.set(form.cleaned_data["additional_finances"])
|
|
||||||
car.finances.save()
|
|
||||||
|
|
||||||
return redirect("estimate_detail", dealer_slug=dealer_slug, pk=pk)
|
|
||||||
|
|
||||||
class SaleOrderDetail(LoginRequiredMixin,PermissionRequiredMixin,DetailView):
|
class SaleOrderDetail(LoginRequiredMixin,PermissionRequiredMixin,DetailView):
|
||||||
model = models.SaleOrder
|
model = models.SaleOrder
|
||||||
template_name = "sales/orders/order_details.html"
|
template_name = "sales/orders/order_details.html"
|
||||||
@ -5383,7 +5331,6 @@ def PaymentCreateView(request, dealer_slug, pk):
|
|||||||
model = invoice if invoice else bill
|
model = invoice if invoice else bill
|
||||||
entity = dealer.entity
|
entity = dealer.entity
|
||||||
form = forms.PaymentForm()
|
form = forms.PaymentForm()
|
||||||
breakpoint()
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = forms.PaymentForm(request.POST)
|
form = forms.PaymentForm(request.POST)
|
||||||
|
|
||||||
@ -5643,18 +5590,19 @@ class LeadListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|||||||
qs = models.Lead.objects.filter(dealer=dealer).exclude(status="converted")
|
qs = models.Lead.objects.filter(dealer=dealer).exclude(status="converted")
|
||||||
if query:
|
if query:
|
||||||
qs = qs.filter(Q(first_name__icontains=query)
|
qs = qs.filter(Q(first_name__icontains=query)
|
||||||
| Q(last_name__icontains=query)
|
| Q(last_name__icontains=query)
|
||||||
| Q(id_car_make__name__icontains=query)
|
| Q(id_car_make__name__icontains=query)
|
||||||
| Q(id_car_model__name__icontains=query)
|
| Q(id_car_model__name__icontains=query)
|
||||||
| Q(email__icontains=query)
|
| Q(email__icontains=query)
|
||||||
| Q(phone_number__icontains=query)
|
| Q(phone_number__icontains=query)
|
||||||
| Q(next_action__icontains=query)
|
| Q(next_action__icontains=query)
|
||||||
| Q(staff__name__icontains=query))
|
| Q(staff__name__icontains=query))
|
||||||
|
|
||||||
if self.request.is_dealer :#or self.request.is_manager:
|
if self.request.is_dealer:
|
||||||
return qs
|
return qs
|
||||||
if self.request.is_staff:
|
if self.request.user.is_staff:
|
||||||
return qs.filter(staff=self.request.staff)
|
staff = getattr(self.request.user.staffmember, "staff", None)
|
||||||
|
return qs.filter(staff=staff)
|
||||||
return models.Lead.objects.none()
|
return models.Lead.objects.none()
|
||||||
|
|
||||||
|
|
||||||
@ -5711,7 +5659,7 @@ class LeadDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
|||||||
context["transfer_form"] = forms.LeadTransferForm()
|
context["transfer_form"] = forms.LeadTransferForm()
|
||||||
context["transfer_form"].fields[
|
context["transfer_form"].fields[
|
||||||
"transfer_to"
|
"transfer_to"
|
||||||
].queryset = models.Staff.objects.select_related("staff_member","staff_member__user").filter(
|
].queryset = models.Staff.objects.filter(
|
||||||
dealer=dealer,staff_member__user__groups__permissions__codename__contains="can_reassign_lead").exclude(staff_member__user=self.request.user).distinct()
|
dealer=dealer,staff_member__user__groups__permissions__codename__contains="can_reassign_lead").exclude(staff_member__user=self.request.user).distinct()
|
||||||
|
|
||||||
context["activity_form"] = forms.ActivityForm()
|
context["activity_form"] = forms.ActivityForm()
|
||||||
@ -5831,12 +5779,15 @@ def lead_create(request,dealer_slug):
|
|||||||
qs = form.fields["id_car_make"].queryset.filter(
|
qs = form.fields["id_car_make"].queryset.filter(
|
||||||
is_sa_import=True, pk__in=dealer_make_list
|
is_sa_import=True, pk__in=dealer_make_list
|
||||||
)
|
)
|
||||||
form.fields["staff"].queryset = form.fields["staff"].queryset.select_related("staff_member","staff_member__user").filter(dealer=dealer,staff_member__user__groups__permissions__codename__contains="add_lead").distinct()
|
form.fields["staff"].queryset = form.fields["staff"].queryset.filter(
|
||||||
|
dealer=dealer,staff_member__user__groups__permissions__codename__contains="add_lead").distinct()
|
||||||
|
|
||||||
if request.is_staff:
|
|
||||||
form.initial["staff"] = request.staff
|
if hasattr(request.user.staffmember, "staff"):
|
||||||
|
staff = request.user.staffmember.staff
|
||||||
|
form.initial["staff"] = staff
|
||||||
form.fields["staff"].widget.attrs.update({"readonly":"true","required":"true"})
|
form.fields["staff"].widget.attrs.update({"readonly":"true","required":"true"})
|
||||||
form.fields["staff"].queryset = models.Staff.objects.filter(dealer=dealer,pk=request.staff.pk)
|
form.fields["staff"].queryset = models.Staff.objects.filter(dealer=dealer,pk=staff.pk)
|
||||||
form.fields["id_car_make"].queryset = qs
|
form.fields["id_car_make"].queryset = qs
|
||||||
form.fields["id_car_make"].choices = [
|
form.fields["id_car_make"].choices = [
|
||||||
(obj.id_car_make, obj.get_local_name()) for obj in qs
|
(obj.id_car_make, obj.get_local_name()) for obj in qs
|
||||||
@ -5850,7 +5801,7 @@ def lead_create(request,dealer_slug):
|
|||||||
@permission_required("inventory.view_lead", raise_exception=True)
|
@permission_required("inventory.view_lead", raise_exception=True)
|
||||||
def lead_tracking(request,dealer_slug):
|
def lead_tracking(request,dealer_slug):
|
||||||
dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
|
dealer = get_object_or_404(models.Dealer,slug=dealer_slug)
|
||||||
staff = models.Staff.objects.select_related("staff_member","staff_member__user").filter(dealer=dealer, staff_member__user=request.user).first()
|
staff = models.Staff.objects.filter(dealer=dealer, staff_member__user=request.user).first()
|
||||||
|
|
||||||
if staff:
|
if staff:
|
||||||
qs = models.Lead.objects.filter(dealer=dealer,staff=staff)
|
qs = models.Lead.objects.filter(dealer=dealer,staff=staff)
|
||||||
@ -5994,7 +5945,7 @@ class LeadUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
|
|||||||
form.fields[
|
form.fields[
|
||||||
"id_car_model"
|
"id_car_model"
|
||||||
].queryset = form.instance.id_car_make.carmodel_set.all()
|
].queryset = form.instance.id_car_make.carmodel_set.all()
|
||||||
form.fields["staff"].queryset = form.fields["staff"].queryset.select_related("staff_member","staff_member__user").filter(
|
form.fields["staff"].queryset = form.fields["staff"].queryset.filter(
|
||||||
dealer=dealer,staff_member__user__groups__permissions__codename__contains="add_lead").distinct()
|
dealer=dealer,staff_member__user__groups__permissions__codename__contains="add_lead").distinct()
|
||||||
|
|
||||||
return form
|
return form
|
||||||
@ -6929,8 +6880,8 @@ class ItemServiceCreateView(
|
|||||||
permission_required = ["inventory.add_additionalservices"]
|
permission_required = ["inventory.add_additionalservices"]
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
vat = models.VatRate.objects.get(is_active=True)
|
||||||
dealer = get_user_type(self.request)
|
dealer = get_user_type(self.request)
|
||||||
vat = models.VatRate.objects.get(dealer=dealer,is_active=True)
|
|
||||||
form.instance.dealer = dealer
|
form.instance.dealer = dealer
|
||||||
if form.instance.taxable:
|
if form.instance.taxable:
|
||||||
form.instance.price = (form.instance.price * vat.rate) + form.instance.price
|
form.instance.price = (form.instance.price * vat.rate) + form.instance.price
|
||||||
@ -6976,8 +6927,8 @@ class ItemServiceUpdateView(
|
|||||||
|
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
vat = models.VatRate.objects.get(is_active=True)
|
||||||
dealer = get_user_type(self.request)
|
dealer = get_user_type(self.request)
|
||||||
vat = models.VatRate.objects.get(dealer=dealer,is_active=True)
|
|
||||||
form.instance.dealer = dealer
|
form.instance.dealer = dealer
|
||||||
if form.instance.taxable:
|
if form.instance.taxable:
|
||||||
form.instance.price = (form.instance.price * vat.rate) + form.instance.price
|
form.instance.price = (form.instance.price * vat.rate) + form.instance.price
|
||||||
@ -7624,7 +7575,7 @@ class OrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
|||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
dealer = get_user_type(self.request)
|
dealer = get_user_type(self.request)
|
||||||
qs = super().get_queryset().select_related("customer","estimate","invoice")
|
qs = super().get_queryset()
|
||||||
return qs.filter(estimate__entity=dealer.entity)
|
return qs.filter(estimate__entity=dealer.entity)
|
||||||
|
|
||||||
|
|
||||||
@ -8725,13 +8676,12 @@ class LedgerModelListView(LoginRequiredMixin,PermissionRequiredMixin, ListView,
|
|||||||
show_visible = False
|
show_visible = False
|
||||||
allow_empty = True
|
allow_empty = True
|
||||||
paginate_by = 30
|
paginate_by = 30
|
||||||
|
permission_required = "django_ledger.view_ledgermodel"
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = super().get_queryset()
|
qs = super().get_queryset()
|
||||||
# dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
|
dealer = get_user_type(self.request)
|
||||||
# dealer = get_user_type(self.request)
|
qs = qs.filter(entity=dealer.entity)
|
||||||
qs = qs.filter(entity=self.request.entity)
|
|
||||||
qs = qs.select_related("billmodel", "invoicemodel")
|
qs = qs.select_related("billmodel", "invoicemodel")
|
||||||
qs = qs.order_by("-created")
|
qs = qs.order_by("-created")
|
||||||
if self.show_all:
|
if self.show_all:
|
||||||
@ -8744,7 +8694,8 @@ class LedgerModelListView(LoginRequiredMixin,PermissionRequiredMixin, ListView,
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context["entity_slug"] = self.request.dealer.entity.slug
|
dealer = get_user_type(self.request)
|
||||||
|
context["entity_slug"] = dealer.entity.slug
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@ -8791,14 +8742,16 @@ class LedgerModelCreateView(LedgerModelCreateViewBase):
|
|||||||
permission_required = ["django_ledger.add_ledgermodel"]
|
permission_required = ["django_ledger.add_ledgermodel"]
|
||||||
|
|
||||||
def get_form(self, form_class=None):
|
def get_form(self, form_class=None):
|
||||||
|
dealer = get_user_type(self.request)
|
||||||
return LedgerModelCreateForm(
|
return LedgerModelCreateForm(
|
||||||
entity_slug=self.request.dealer.entity.slug,
|
entity_slug=dealer.entity.slug,
|
||||||
user_model=self.request.entity.admin,
|
user_model=dealer.entity.admin,
|
||||||
**self.get_form_kwargs(),
|
**self.get_form_kwargs(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
form.field["entity"] = self.request.dealer.entity
|
dealer = get_user_type(self.request)
|
||||||
|
form.field["entity"] = dealer.entity
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
@ -10300,11 +10253,9 @@ def upload_cars(request, dealer_slug, pk=None):
|
|||||||
car_make = get_make(manufacturer_name)
|
car_make = get_make(manufacturer_name)
|
||||||
car_model = get_model(model_name, car_make)
|
car_model = get_model(model_name, car_make)
|
||||||
if (
|
if (
|
||||||
not all([car_make])
|
not all([car_make, car_model])
|
||||||
or (make.pk != car_make.pk)
|
or (make.pk != car_make.pk)
|
||||||
# not all([car_make, car_model])
|
or (model.pk != car_model.pk)
|
||||||
# or (make.pk != car_make.pk)
|
|
||||||
# or (model.pk != car_model.pk)
|
|
||||||
):
|
):
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"User {user_username} uploaded CSV with VIN '{row['vin']}' "
|
f"User {user_username} uploaded CSV with VIN '{row['vin']}' "
|
||||||
@ -10332,20 +10283,12 @@ def upload_cars(request, dealer_slug, pk=None):
|
|||||||
vendor=vendor,
|
vendor=vendor,
|
||||||
receiving_date=receiving_date,
|
receiving_date=receiving_date,
|
||||||
)
|
)
|
||||||
if po_item:
|
|
||||||
models.CarFinance.objects.create(
|
|
||||||
car=car,
|
|
||||||
cost_price=po_item.item.unit_cost,
|
|
||||||
marked_price=0,
|
|
||||||
selling_price=0
|
|
||||||
)
|
|
||||||
car.add_colors(exterior=exterior, interior=interior)
|
car.add_colors(exterior=exterior, interior=interior)
|
||||||
cars_created += 1
|
cars_created += 1
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"User {user_username} created Car ID: {car.pk} (VIN: {car.vin}). "
|
f"User {user_username} created Car ID: {car.pk} (VIN: {car.vin}). "
|
||||||
f"Count: {cars_created}."
|
f"Count: {cars_created}."
|
||||||
)
|
)
|
||||||
|
|
||||||
if po_item:
|
if po_item:
|
||||||
po_item.status = "uploaded"
|
po_item.status = "uploaded"
|
||||||
po_item.save()
|
po_item.save()
|
||||||
@ -10425,3 +10368,12 @@ def bulk_update_car_price(request):
|
|||||||
class InventoryListView(InventoryListViewBase):
|
class InventoryListView(InventoryListViewBase):
|
||||||
template_name = "inventory/list.html"
|
template_name = "inventory/list.html"
|
||||||
permission_required = ["django_ledger.view_purchaseordermodel"]
|
permission_required = ["django_ledger.view_purchaseordermodel"]
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
dealer = get_user_type(self.request)
|
||||||
|
|
||||||
|
if self.queryset is None:
|
||||||
|
self.queryset = ItemTransactionModel.objects.inventory_pipeline_aggregate(
|
||||||
|
entity_slug=dealer.entity.slug,
|
||||||
|
)
|
||||||
|
return super().get_queryset()
|
||||||
|
|||||||
@ -1,126 +1,126 @@
|
|||||||
annotated-types
|
annotated-types==0.7.0
|
||||||
anyio
|
anyio==4.9.0
|
||||||
arrow
|
arrow==1.3.0
|
||||||
asgiref
|
asgiref==3.8.1
|
||||||
attrs
|
attrs==25.3.0
|
||||||
Babel
|
Babel==2.15.0
|
||||||
beautifulsoup4
|
beautifulsoup4==4.13.4
|
||||||
blessed
|
blessed==1.21.0
|
||||||
cattrs
|
cattrs==24.1.3
|
||||||
certifi
|
certifi==2025.1.31
|
||||||
cffi
|
cffi==1.17.1
|
||||||
charset-normalizer
|
charset-normalizer==3.4.1
|
||||||
click
|
click==8.2.1
|
||||||
colorama
|
colorama==0.4.6
|
||||||
crispy-bootstrap5
|
crispy-bootstrap5==2024.10
|
||||||
cryptography
|
cryptography==44.0.2
|
||||||
cssbeautifier
|
cssbeautifier==1.15.4
|
||||||
defusedxml
|
defusedxml==0.7.1
|
||||||
diff-match-patch
|
diff-match-patch==20241021
|
||||||
distro
|
distro==1.9.0
|
||||||
Django
|
Django==5.2.3
|
||||||
django-allauth
|
django-allauth==65.6.0
|
||||||
django-appointment
|
django-appointment==3.8.0
|
||||||
django-background-tasks
|
django-background-tasks==1.2.8
|
||||||
django-bootstrap5
|
django-bootstrap5==25.1
|
||||||
django-ckeditor
|
django-ckeditor==6.7.2
|
||||||
django-cors-headers
|
django-cors-headers==4.7.0
|
||||||
django-countries
|
django-countries==7.6.1
|
||||||
django-crispy-forms
|
django-crispy-forms==2.3
|
||||||
django-easy-audit
|
django-easy-audit==1.3.7
|
||||||
django-extensions
|
django-extensions==3.2.3
|
||||||
django-filter
|
django-filter==25.1
|
||||||
django-import-export
|
django-import-export==4.3.7
|
||||||
django-js-asset
|
django-js-asset==3.1.2
|
||||||
django-ledger
|
django-ledger==0.7.7
|
||||||
django-manager-utils
|
django-manager-utils==3.1.5
|
||||||
django-next-url-mixin
|
django-next-url-mixin==0.4.0
|
||||||
django-ordered-model
|
django-ordered-model==3.7.4
|
||||||
django-phonenumber-field
|
django-phonenumber-field==8.0.0
|
||||||
django-picklefield
|
django-picklefield==3.3
|
||||||
django-plans
|
django-plans==2.0.0
|
||||||
django-q2
|
django-q2==1.8.0
|
||||||
django-query-builder
|
django-query-builder==3.2.0
|
||||||
django-schema-graph
|
django-schema-graph==3.1.0
|
||||||
django-sequences
|
django-sequences==3.0
|
||||||
django-tables2
|
django-tables2==2.7.5
|
||||||
django-treebeard
|
django-treebeard==4.7.1
|
||||||
django-widget-tweaks
|
django-widget-tweaks==1.5.0
|
||||||
djangorestframework
|
djangorestframework==3.15.2
|
||||||
djhtml
|
djhtml==3.0.7
|
||||||
djlint
|
djlint==1.36.4
|
||||||
docopt
|
docopt==0.6.2
|
||||||
EditorConfig
|
EditorConfig==0.17.0
|
||||||
Faker
|
Faker==37.3.0
|
||||||
fleming
|
fleming==0.7.0
|
||||||
fonttools
|
fonttools==4.57.0
|
||||||
fpdf
|
fpdf==1.7.2
|
||||||
fpdf2
|
fpdf2==2.8.3
|
||||||
greenlet
|
greenlet==3.2.2
|
||||||
h11
|
h11==0.14.0
|
||||||
httpcore
|
httpcore==1.0.7
|
||||||
httpx
|
httpx==0.28.1
|
||||||
icalendar
|
icalendar==6.1.2
|
||||||
idna
|
idna==3.10
|
||||||
jiter
|
jiter==0.9.0
|
||||||
jsbeautifier
|
jsbeautifier==1.15.4
|
||||||
json5
|
json5==0.12.0
|
||||||
jsonpatch
|
jsonpatch==1.33
|
||||||
jsonpointer
|
jsonpointer==3.0.0
|
||||||
jwt
|
jwt==1.3.1
|
||||||
langchain
|
langchain==0.3.25
|
||||||
langchain-core
|
langchain-core==0.3.61
|
||||||
langchain-ollama
|
langchain-ollama==0.3.3
|
||||||
langchain-text-splitters
|
langchain-text-splitters==0.3.8
|
||||||
langsmith
|
langsmith==0.3.42
|
||||||
luhnchecker
|
luhnchecker==0.0.12
|
||||||
Markdown
|
Markdown==3.8
|
||||||
markdown-it-py
|
markdown-it-py==3.0.0
|
||||||
mdurl
|
mdurl==0.1.2
|
||||||
num2words
|
num2words==0.5.14
|
||||||
numpy
|
numpy==2.2.4
|
||||||
ofxtools
|
ofxtools==0.9.5
|
||||||
ollama
|
ollama==0.4.8
|
||||||
openai
|
openai==1.68.2
|
||||||
opencv-python
|
opencv-python==4.11.0.86
|
||||||
orjson
|
orjson==3.10.18
|
||||||
packaging
|
packaging==24.2
|
||||||
pandas
|
pandas==2.2.3
|
||||||
pathspec
|
pathspec==0.12.1
|
||||||
phonenumbers
|
phonenumbers==8.13.42
|
||||||
pillow
|
pillow==11.2.1
|
||||||
pycparser
|
pycparser==2.22
|
||||||
pydantic
|
pydantic==2.10.6
|
||||||
pydantic_core
|
pydantic_core==2.27.2
|
||||||
Pygments
|
Pygments==2.19.1
|
||||||
python-dateutil
|
python-dateutil==2.9.0.post0
|
||||||
python-slugify
|
python-slugify==8.0.4
|
||||||
python-stdnum
|
python-stdnum==1.20
|
||||||
pytz
|
pytz==2025.2
|
||||||
pyvin
|
pyvin==0.0.2
|
||||||
PyYAML
|
PyYAML==6.0.2
|
||||||
pyzbar
|
pyzbar==0.1.9
|
||||||
redis
|
redis==3.5.3
|
||||||
regex
|
regex==2024.11.6
|
||||||
requests
|
requests==2.32.3
|
||||||
requests-toolbelt
|
requests-toolbelt==1.0.0
|
||||||
rich
|
rich==14.0.0
|
||||||
ruff
|
ruff==0.11.10
|
||||||
setuptools
|
setuptools==80.3.0
|
||||||
six
|
six==1.17.0
|
||||||
sniffio
|
sniffio==1.3.1
|
||||||
soupsieve
|
soupsieve==2.7
|
||||||
SQLAlchemy
|
SQLAlchemy==2.0.41
|
||||||
sqlparse
|
sqlparse==0.5.3
|
||||||
suds
|
suds==1.2.0
|
||||||
swapper
|
swapper==1.3.0
|
||||||
tablib
|
tablib==3.8.0
|
||||||
tenacity
|
tenacity==9.1.2
|
||||||
text-unidecode
|
text-unidecode==1.3
|
||||||
tqdm
|
tqdm==4.67.1
|
||||||
types-python-dateutil
|
types-python-dateutil==2.9.0.20250516
|
||||||
typing_extensions
|
typing_extensions==4.13.0
|
||||||
tzdata
|
tzdata==2025.2
|
||||||
urllib3
|
urllib3==2.3.0
|
||||||
wcwidth
|
wcwidth==0.2.13
|
||||||
zstandard
|
zstandard==0.23.0
|
||||||
|
|||||||
9
static/css/all.min.css
vendored
9
static/css/all.min.css
vendored
File diff suppressed because one or more lines are too long
@ -45,7 +45,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.form-control, .form-select {
|
.form-control, .form-select {
|
||||||
/* text-align: center; */
|
text-align: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -131,4 +131,3 @@ html[dir="rtl"] .form-icon-container .form-control {
|
|||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
to { transform: rotate(360deg); }
|
to { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
static/js/fontawesome.min.js
vendored
6
static/js/fontawesome.min.js
vendored
File diff suppressed because one or more lines are too long
@ -26,19 +26,19 @@
|
|||||||
<meta name="msapplication-TileImage" content="{% static 'images/logos/logo-d.png' %}">
|
<meta name="msapplication-TileImage" content="{% static 'images/logos/logo-d.png' %}">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
{% comment %} <script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script> {% endcomment %}
|
<script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script>
|
||||||
<script src="{% static 'js/config.js' %}"></script>
|
<script src="{% static 'js/config.js' %}"></script>
|
||||||
<script src="{% static 'js/sweetalert2.all.min.js' %}"></script>
|
<script src="{% static 'js/sweetalert2.all.min.js' %}"></script>
|
||||||
{% comment %} <link href="{% static 'vendors/mapbox-gl/mapbox-gl.css' %}" rel="stylesheet"> {% endcomment %}
|
<link href="{% static 'vendors/mapbox-gl/mapbox-gl.css' %}" rel="stylesheet">
|
||||||
{% comment %} <link href="{% static 'vendors/swiper/swiper-bundle.min.css' %}" rel="stylesheet"> {% endcomment %}
|
<link href="{% static 'vendors/swiper/swiper-bundle.min.css' %}" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&display=swap" rel="stylesheet">
|
||||||
{% comment %} <link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet"> {% endcomment %}
|
<link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@emran-alhaddad/saudi-riyal-font/index.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@emran-alhaddad/saudi-riyal-font/index.css">
|
||||||
{% comment %} <link href="{% static 'vendors/flatpickr/flatpickr.min.css' %}" rel="stylesheet"> {% endcomment %}
|
<link href="{% static 'vendors/flatpickr/flatpickr.min.css' %}" rel="stylesheet">
|
||||||
<link href="{% static 'css/custom.css' %}" rel="stylesheet">
|
<link href="{% static 'css/custom.css' %}" rel="stylesheet">
|
||||||
{% comment %} <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css"> {% endcomment %}
|
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css">
|
||||||
{% if LANGUAGE_CODE == 'ar' %}
|
{% if LANGUAGE_CODE == 'ar' %}
|
||||||
<link href="{% static 'css/theme-rtl.min.css' %}" type="text/css" rel="stylesheet" id="style-rtl">
|
<link href="{% static 'css/theme-rtl.min.css' %}" type="text/css" rel="stylesheet" id="style-rtl">
|
||||||
<link href="{% static 'css/user-rtl.min.css' %}" type="text/css" rel="stylesheet" id="user-style-rtl">
|
<link href="{% static 'css/user-rtl.min.css' %}" type="text/css" rel="stylesheet" id="user-style-rtl">
|
||||||
@ -46,9 +46,9 @@
|
|||||||
<link href="{% static 'css/theme.min.css' %}" type="text/css" rel="stylesheet" id="style-default">
|
<link href="{% static 'css/theme.min.css' %}" type="text/css" rel="stylesheet" id="style-default">
|
||||||
<link href="{% static 'css/user.min.css' %}" type="text/css" rel="stylesheet" id="user-style-default">
|
<link href="{% static 'css/user.min.css' %}" type="text/css" rel="stylesheet" id="user-style-default">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% comment %} <script src="{% static 'js/main.js' %}"></script> {% endcomment %}
|
<script src="{% static 'js/main.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'js/jquery.min.js' %}"></script> {% endcomment %}
|
<script src="{% static 'js/jquery.min.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'js/echarts.js' %}"></script> {% endcomment %}
|
<script src="{% static 'js/echarts.js' %}"></script>
|
||||||
|
|
||||||
{% block customCSS %}
|
{% block customCSS %}
|
||||||
|
|
||||||
@ -79,9 +79,9 @@
|
|||||||
{% include 'footer.html' %}
|
{% include 'footer.html' %}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
{% comment %} <script src="{% static 'js/djetler.bundle.js' %}"></script>
|
<script src="{% static 'js/djetler.bundle.js' %}"></script>
|
||||||
<script src="{% static 'js/js-utils.js' %}"></script> {% endcomment %}
|
<script src="{% static 'js/js-utils.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'js/modal/show_modal.js' %}"></script> {% endcomment %}
|
<script src="{% static 'js/modal/show_modal.js' %}"></script>
|
||||||
|
|
||||||
<!-- ===============================================-->
|
<!-- ===============================================-->
|
||||||
<!-- JavaScripts-->
|
<!-- JavaScripts-->
|
||||||
@ -90,30 +90,31 @@
|
|||||||
<!--1-->
|
<!--1-->
|
||||||
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
|
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
|
||||||
|
|
||||||
{% comment %} <script src="{% static 'vendors/anchorjs/anchor.min.js' %}"></script>
|
<script src="{% static 'vendors/anchorjs/anchor.min.js' %}"></script>
|
||||||
<script src="{% static 'vendors/is/is.min.js' %}"></script> {% endcomment %}
|
<script src="{% static 'vendors/is/is.min.js' %}"></script>
|
||||||
<!--2-->
|
<!--2-->
|
||||||
<script src="{% static 'vendors/fontawesome/all.min.js' %}"></script>
|
<script src="{% static 'vendors/fontawesome/all.min.js' %}"></script>
|
||||||
|
|
||||||
<script src="{% static 'vendors/lodash/lodash.min.js' %}"></script>
|
<script src="{% static 'vendors/lodash/lodash.min.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'vendors/list.js/list.min.js' %}"></script> {% endcomment %}
|
<script src="{% static 'vendors/list.js/list.min.js' %}"></script>
|
||||||
<script src="{% static 'vendors/feather-icons/feather.min.js' %}"></script>
|
<script src="{% static 'vendors/feather-icons/feather.min.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'vendors/dayjs/dayjs.min.js' %}"></script> {% endcomment %}
|
<script src="{% static 'vendors/dayjs/dayjs.min.js' %}"></script>
|
||||||
<script src="{% static 'js/phoenix.js' %}"></script>
|
<script src="{% static 'js/phoenix.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'js/apexcharts.js' %}"></script> {% endcomment %}
|
<script src="{% static 'js/apexcharts.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'vendors/echarts/echarts.min.js' %}"></script> {% endcomment %}
|
<script src="{% static 'vendors/echarts/echarts.min.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'js/crm-analytics.js' %}"></script> {% endcomment %}
|
<script src="{% static 'js/crm-analytics.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'js/travel-agency-dashboard.js' %}"></script>
|
<script src="{% static 'js/travel-agency-dashboard.js' %}"></script>
|
||||||
<script src="{% static 'js/crm-dashboard.js' %}"></script>
|
<script src="{% static 'js/crm-dashboard.js' %}"></script>
|
||||||
<script src="{% static 'js/projectmanagement-dashboard.js' %}"></script> {% endcomment %}
|
<script src="{% static 'js/projectmanagement-dashboard.js' %}"></script>
|
||||||
|
|
||||||
{% comment %} <script src="{% static 'vendors/mapbox-gl/mapbox-gl.js' %}"></script> {% endcomment %}
|
<script src="{% static 'vendors/mapbox-gl/mapbox-gl.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'vendors/turf.min.js' %}"></script> {% endcomment %}
|
<script src="{% static 'vendors/turf.min.js' %}"></script>
|
||||||
<script src="{% static 'vendors/htmx.min.js' %}"></script>
|
<script src="{% static 'vendors/htmx.min.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script>
|
<script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script>
|
||||||
<script src="{% static 'vendors/flatpickr/flatpickr.min.js' %}"></script> {% endcomment %}
|
<script src="{% static 'vendors/flatpickr/flatpickr.min.js' %}"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
{% if entity_slug %}
|
{% if entity_slug %}
|
||||||
let entitySlug = "{{ view.kwargs.entity_slug }}"
|
let entitySlug = "{{ view.kwargs.entity_slug }}"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
{% load crispy_forms_filters %}
|
{% load crispy_forms_filters %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment %} <div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card shadow-sm">
|
<div class="card shadow-sm">
|
||||||
<div class="card-header bg-light py-3">
|
<div class="card-header bg-light py-3">
|
||||||
@ -46,63 +46,5 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> {% endcomment %}
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{% trans 'Create Bill' %}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
<form action="{{ form_action_url }}" method="post" id="djl-bill-model-create-form-id">
|
|
||||||
<div class="card-body">
|
|
||||||
|
|
||||||
{% csrf_token %}
|
|
||||||
{% if po_model %}
|
|
||||||
<div class="text-center mb-4">
|
|
||||||
<h3 class="h5">{% trans 'Bill for' %} {{ po_model.po_number }}</h3>
|
|
||||||
<p class="text-muted mb-3">{% trans 'Bill for' %} {{ po_model.po_title }}</p>
|
|
||||||
<div class="d-flex flex-column gap-2">
|
|
||||||
{% for itemtxs in po_itemtxs_qs %}
|
|
||||||
<span class="badge bg-secondary">{{ itemtxs }}</span>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="mb-4">
|
|
||||||
{{ form|crispy }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-footer bg-transparent">
|
|
||||||
<div class="d-grid gap-2">
|
|
||||||
<button type="submit"
|
|
||||||
id="djl-bill-create-button"
|
|
||||||
class="btn btn-phoenix-primary btn-lg">{% trans 'Create' %}
|
|
||||||
</button>
|
|
||||||
<a href="{{request.META.HTTP_REFERER}}"
|
|
||||||
id="djl-bill-create-back-button"
|
|
||||||
class="btn btn-phoenix-secondary">{% trans 'Cancel' %}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!---->
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -45,6 +45,11 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill entity_slug=view.kwargs.entity_slug style='bill-detail' %}
|
{% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill entity_slug=view.kwargs.entity_slug style='bill-detail' %}
|
||||||
|
|
||||||
|
<div class="d-grid mt-4">
|
||||||
|
<a href="{% url 'bill_list' request.dealer.slug %}" class="btn btn-phoenix-primary">
|
||||||
|
<i class="fas fa-arrow-left me-1"></i> {% trans 'Bill List' %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
<div class="container py-4">
|
<div class="container py-4">
|
||||||
<div class="row g-2">
|
<div class="row g-2">
|
||||||
|
|
||||||
|
|
||||||
<!-- Bill Form -->
|
<!-- Bill Form -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
|
||||||
@ -17,6 +18,10 @@
|
|||||||
<div class="card mb-2">
|
<div class="card mb-2">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill_model style='bill-detail' entity_slug=view.kwargs.entity_slug %}
|
{% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill_model style='bill-detail' entity_slug=view.kwargs.entity_slug %}
|
||||||
|
<a href="{% url 'bill-detail' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}"
|
||||||
|
class="btn btn-phoenix-secondary w-100 mb-2">
|
||||||
|
<i class="fas fa-arrow-left me-2"></i>{% trans 'Back to Bill Detail' %}
|
||||||
|
</a>
|
||||||
|
|
||||||
<form action="{% url 'bill-update' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}" method="post">
|
<form action="{% url 'bill-update' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@ -25,21 +30,20 @@
|
|||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-phoenix-primary mb-2 me-2">
|
<button type="submit" class="btn btn-phoenix-primary w-100 mb-2">
|
||||||
<i class="fas fa-save me-2"></i>{% trans 'Save Bill' %}
|
<i class="fas fa-save me-2"></i>{% trans 'Save Bill' %}
|
||||||
</button>
|
</button>
|
||||||
<a href="{% url 'bill-detail' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}"
|
|
||||||
class="btn btn-phoenix-secondary mb-2">
|
|
||||||
<i class="fas fa-arrow-left me-2"></i>{% trans 'Back to Bill Detail' %}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<a href="{% url 'bill_list' request.dealer.slug %}"
|
||||||
|
class="btn btn-phoenix-info w-100 mb-2">
|
||||||
|
<i class="fas fa-list me-2"></i>{% trans 'Bill List' %}
|
||||||
|
</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -47,6 +51,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Bill Item Formset -->
|
<!-- Bill Item Formset -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
{% bill_item_formset_table itemtxs_formset %}
|
{% bill_item_formset_table itemtxs_formset %}
|
||||||
|
|||||||
@ -1,15 +1,13 @@
|
|||||||
{% load django_ledger %}
|
{% load django_ledger %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div id="djl-bill-card-widget" class="">
|
<div id="djl-bill-card-widget" class="">
|
||||||
|
|
||||||
{% if not create_bill %}
|
{% if not create_bill %}
|
||||||
{% if style == 'dashboard' %}
|
{% if style == 'dashboard' %}
|
||||||
<!-- Dashboard Style Card -->
|
<!-- Dashboard Style Card -->
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="card-body">
|
<div class="card-body ">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3 text-primary">
|
<h6 class="text-uppercase text-secondary mb-0">
|
||||||
<h6 class="text-uppercase text-primary mb-0">
|
|
||||||
<i class="fas fa-file-invoice me-2"></i>{% trans 'Bill' %}
|
<i class="fas fa-file-invoice me-2"></i>{% trans 'Bill' %}
|
||||||
</h6>
|
</h6>
|
||||||
<span class="badge bg-{{ bill.get_status_badge_color }}">{{ bill.get_bill_status_display }}</span>
|
<span class="badge bg-{{ bill.get_status_badge_color }}">{{ bill.get_bill_status_display }}</span>
|
||||||
@ -93,20 +91,12 @@
|
|||||||
<!-- Detail Style Card -->
|
<!-- Detail Style Card -->
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="card-header p-2 bg-{{ bill.get_status_badge_color }}">
|
<div class="card-header p-2 bg-{{ bill.get_status_badge_color }}">
|
||||||
<div class="d-flex align-items-center justify-content-center mb-2 text-primary">
|
<div class="d-flex align-items-center">
|
||||||
<i class="fas fa-file-invoice me-3 "></i>
|
<i class="fas fa-file-invoice me-3 text-white"></i>
|
||||||
<h4 class="mb-0 text-primary me-2">
|
<h2 class="mb-0 text-white">
|
||||||
{% trans 'Bill' %} {{ bill.bill_number }}
|
{% trans 'Bill' %} {{ bill.bill_number }}
|
||||||
</h4>
|
</h2>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<a href="{% url 'bill_list' request.dealer.slug %}"
|
|
||||||
class="btn btn-phoenix-primary mb-2">
|
|
||||||
<i class="fas fa-long-arrow-alt-left me-2"></i>{% trans 'Back to Bill List' %}
|
|
||||||
</a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-2 text-center">
|
<div class="card-body p-2 text-center">
|
||||||
{% if bill.is_draft %}
|
{% if bill.is_draft %}
|
||||||
@ -231,15 +221,12 @@
|
|||||||
<div class="d-flex flex-wrap gap-2 mt-2">
|
<div class="d-flex flex-wrap gap-2 mt-2">
|
||||||
<!-- Update Button -->
|
<!-- Update Button -->
|
||||||
{% if perms.django_ledger.change_billmodel%}
|
{% if perms.django_ledger.change_billmodel%}
|
||||||
<button class="btn btn-phoenix-primary" {% if not request.is_accountant %} disabled {% endif %}>
|
<a href="{% url 'bill-update' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=bill.uuid %}" class="btn btn-phoenix-primary">
|
||||||
<a href="{% url 'bill-update' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=bill.uuid %}">
|
<i class="fas fa-edit me-2"></i>{% trans 'Update' %}
|
||||||
<i class="fas fa-edit me-2"></i>{% trans 'Update' %}
|
</a>
|
||||||
</a>
|
|
||||||
</button>
|
|
||||||
<!-- Mark as Draft -->
|
<!-- Mark as Draft -->
|
||||||
{% if bill.can_draft %}
|
{% if bill.can_draft %}
|
||||||
<button class="btn btn-phoenix-success"
|
<button class="btn btn-phoenix-success"
|
||||||
{% if not request.is_accountant %} disabled {% endif %}
|
|
||||||
onclick="showPOModal('Mark as Draft', '{% url 'bill-action-mark-as-draft' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Draft')">
|
onclick="showPOModal('Mark as Draft', '{% url 'bill-action-mark-as-draft' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Draft')">
|
||||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Draft' %}
|
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Draft' %}
|
||||||
</button>
|
</button>
|
||||||
@ -247,7 +234,6 @@
|
|||||||
<!-- Mark as Review -->
|
<!-- Mark as Review -->
|
||||||
{% if bill.can_review %}
|
{% if bill.can_review %}
|
||||||
<button class="btn btn-phoenix-warning"
|
<button class="btn btn-phoenix-warning"
|
||||||
{% if not request.is_accountant %} disabled {% endif %}
|
|
||||||
onclick="showPOModal('Mark as Review', '{% url 'bill-action-mark-as-review' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Review')">
|
onclick="showPOModal('Mark as Review', '{% url 'bill-action-mark-as-review' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Review')">
|
||||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Review' %}
|
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Review' %}
|
||||||
</button>
|
</button>
|
||||||
@ -259,11 +245,6 @@
|
|||||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Approved' %}
|
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Approved' %}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if bill.can_approve and not request.is_manager %}
|
|
||||||
<button class="btn btn-phoenix-warning" disabled>
|
|
||||||
<i class="fas fa-hourglass-start me-2"></i><span class="text-warning">{% trans 'Waiting for Manager Approval' %}</span>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
<!-- Mark as Paid -->
|
<!-- Mark as Paid -->
|
||||||
{% if bill.can_pay %}
|
{% if bill.can_pay %}
|
||||||
<button class="btn btn-phoenix-success"
|
<button class="btn btn-phoenix-success"
|
||||||
@ -281,7 +262,6 @@
|
|||||||
<!-- Cancel Button -->
|
<!-- Cancel Button -->
|
||||||
{% if bill.can_cancel %}
|
{% if bill.can_cancel %}
|
||||||
<button class="btn btn-phoenix-danger"
|
<button class="btn btn-phoenix-danger"
|
||||||
{% if not request.is_accountant %} disabled {% endif %}
|
|
||||||
onclick="showPOModal('Mark as Canceled', '{% url 'bill-action-mark-as-canceled' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Canceled')">
|
onclick="showPOModal('Mark as Canceled', '{% url 'bill-action-mark-as-canceled' dealer_slug=request.dealer.slug entity_slug=entity_slug bill_pk=bill.pk %}', 'Mark as Canceled')">
|
||||||
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Canceled' %}
|
<i class="fas fa-check-circle me-2"></i>{% trans 'Mark as Canceled' %}
|
||||||
</button>
|
</button>
|
||||||
@ -297,7 +277,6 @@
|
|||||||
<!-- Create Bill Card -->
|
<!-- Create Bill Card -->
|
||||||
{% if perms.django_ledger.add_billmodel%}
|
{% if perms.django_ledger.add_billmodel%}
|
||||||
<div class=" bg-light">
|
<div class=" bg-light">
|
||||||
|
|
||||||
<div class="card-body text-center p-5">
|
<div class="card-body text-center p-5">
|
||||||
<a href="{% url 'django_ledger:bill-create' entity_slug=entity_slug %}"
|
<a href="{% url 'django_ledger:bill-create' entity_slug=entity_slug %}"
|
||||||
class="text-primary">
|
class="text-primary">
|
||||||
|
|||||||
@ -3,7 +3,15 @@
|
|||||||
|
|
||||||
{% if style == 'card_1' %}
|
{% if style == 'card_1' %}
|
||||||
<div class="card h-100" style="height: 25rem;">
|
<div class="card h-100" style="height: 25rem;">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5 class="card-title fs-3 fw-light mb-0">
|
||||||
|
{% if title %}
|
||||||
|
{{ title }}
|
||||||
|
{% else %}
|
||||||
|
{% trans 'Notes' %}
|
||||||
|
{% endif %}
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
{% if notes_html %}
|
{% if notes_html %}
|
||||||
{{ notes_html|safe }}
|
{{ notes_html|safe }}
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
<tr class="align-middle">
|
<tr class="align-middle">
|
||||||
<!-- Item Column -->
|
<!-- Item Column -->
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex flex-column ms-2">
|
<div class="d-flex flex-column">
|
||||||
{% for hidden_field in f.hidden_fields %}
|
{% for hidden_field in f.hidden_fields %}
|
||||||
{{ hidden_field }}
|
{{ hidden_field }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -137,29 +137,6 @@
|
|||||||
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-file-check-alt"></span>
|
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-file-check-alt"></span>
|
||||||
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Source")}}</h5>
|
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Source")}}</h5>
|
||||||
</div>
|
</div>
|
||||||
{% if lead.source == 'REFERRALS' %}
|
|
||||||
<span class="ms-2 fa fa-users"></span>
|
|
||||||
{% elif lead.source == 'WHATSAPP' %}
|
|
||||||
<span class="ms-2 fa fa-whatsapp"></span>
|
|
||||||
{% elif lead.source == 'SHOWROOM' %}
|
|
||||||
<span class="ms-2 fa fa-building"></span>
|
|
||||||
{% elif lead.source == 'TIKTOK' %}
|
|
||||||
<span class="ms-2 fa fa-tiktok"></span>
|
|
||||||
{% elif lead.source == 'INSTAGRAM' %}
|
|
||||||
<span class="ms-2 fa fa-instagram"></span>
|
|
||||||
{% elif lead.source == 'X' %}
|
|
||||||
<span class="ms-2 fa fa-times-circle"></span>
|
|
||||||
{% elif lead.source == 'FACEBOOK' %}
|
|
||||||
<span class="ms-2 fa fa-facebook-f"></span>
|
|
||||||
{% elif lead.source == 'MOTORY' %}
|
|
||||||
<span class="ms-2 fa fa-car-side"></span>
|
|
||||||
{% elif lead.source == 'INFLUENCERS' %}
|
|
||||||
<span class="ms-2 fa fa-user-check"></span>
|
|
||||||
{% elif lead.source == 'YOUTUBE' %}
|
|
||||||
<span class="ms-2 fa fa-youtube"></span>
|
|
||||||
{% elif lead.source == 'CAMPAIGN' %}
|
|
||||||
<span class="ms-2 fa fa-bullhorn"></span>
|
|
||||||
{% endif %}
|
|
||||||
<span class="text-body-secondary">{{ lead.source|upper }}</span>
|
<span class="text-body-secondary">{{ lead.source|upper }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
@ -513,7 +490,6 @@
|
|||||||
<th class="sort align-middle pe-3 text-uppercase" scope="col" data-sort="sent" style="width:15%; min-width:130px">Assigned to</th>
|
<th class="sort align-middle pe-3 text-uppercase" scope="col" data-sort="sent" style="width:15%; min-width:130px">Assigned to</th>
|
||||||
<th class="sort align-middle text-start text-uppercase" scope="col" data-sort="date" style="min-width:165px">Due Date</th>
|
<th class="sort align-middle text-start text-uppercase" scope="col" data-sort="date" style="min-width:165px">Due Date</th>
|
||||||
<th class="sort align-middle text-start text-uppercase" scope="col" data-sort="date" style="min-width:165px">Completed</th>
|
<th class="sort align-middle text-start text-uppercase" scope="col" data-sort="date" style="min-width:165px">Completed</th>
|
||||||
<th class="sort align-middle text-start text-uppercase" scope="col" data-sort="date" style="min-width:165px"></th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="list" id="all-tasks-table-body">
|
<tbody class="list" id="all-tasks-table-body">
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n static crispy_forms_filters %}
|
{% load i18n static crispy_forms_filters %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
|
{# Check if an 'object' exists in the context #}
|
||||||
{% if object %}
|
{% if object %}
|
||||||
{% trans 'Update Lead' %}
|
{% trans 'Update Lead'%}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% trans 'Add New Lead' %}
|
{% trans 'Add New Lead'%}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block customcss %}
|
{% block customcss %}
|
||||||
<style>
|
<style>
|
||||||
.htmx-indicator{
|
.htmx-indicator{
|
||||||
@ -18,68 +17,49 @@
|
|||||||
.htmx-request .htmx-indicator{
|
.htmx-request .htmx-indicator{
|
||||||
opacity:1;
|
opacity:1;
|
||||||
}
|
}
|
||||||
.htmx-request.htmx-indicator{ /* For elements with htmx-indicator itself becoming the target */
|
.htmx-request.htmx-indicator{
|
||||||
opacity:1;
|
opacity:1;
|
||||||
}
|
}
|
||||||
/* Style for the inline spinner if needed */
|
|
||||||
.inline-spinner {
|
|
||||||
width: 1.5rem; /* Adjust size */
|
|
||||||
height: 1.5rem; /* Adjust size */
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-left: 0.5rem; /* Space from the field */
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
{% endblock customcss %}
|
{% endblock customcss %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
<div class="container-fluid">
|
||||||
<div class="col-lg-8 col-md-10">
|
<h1>{% if object %}{{ _("Update Lead") }}{% else %}{{ _("Create New Lead") }}{% endif %}</h1>
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
<div class="row mb-3">
|
||||||
<div class="card-header bg-gray-300 py-3 border-0 rounded-top-3">
|
<div class="col-sm-6 col-md-8">
|
||||||
<h3 class="mb-0 fs-4 text-center">
|
|
||||||
{% if object %}
|
|
||||||
{{ _("Update Lead") }}
|
|
||||||
{% else %}
|
|
||||||
{{ _("Create New Lead") }}
|
|
||||||
{% endif %}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
<form class="form" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form|crispy }}
|
|
||||||
|
|
||||||
<hr class="my-2">
|
|
||||||
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
|
|
||||||
<button class="btn btn-phoenix-success btn-lg me-md-2" type="submit">
|
|
||||||
<i class="fa-solid fa-floppy-disk me-1"></i>
|
|
||||||
{{ _("Save") }}
|
|
||||||
</button>
|
|
||||||
<a href="{{ request.META.HTTP_REFERER }}" class="btn btn-phoenix-danger btn-lg">
|
|
||||||
<i class="fa-solid fa-ban me-1"></i>
|
|
||||||
{% trans "Cancel" %}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<form class="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form|crispy }}
|
||||||
|
<div class="d-flex justify-content-start">
|
||||||
|
<button class="btn btn-sm btn-phoenix-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-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// First, create the spinner div (or use the existing one)
|
||||||
const spinner = document.createElement('div');
|
const spinner = document.createElement('div');
|
||||||
spinner.id = 'spinner';
|
spinner.id = 'spinner';
|
||||||
spinner.className = 'htmx-indicator spinner-border text-primary inline-spinner';
|
spinner.className = 'htmx-indicator spinner-border inline-spinner';
|
||||||
|
spinner.setAttribute('role', 'status');
|
||||||
spinner.innerHTML = '<span class="visually-hidden">Loading...</span>';
|
spinner.innerHTML = '<span class="visually-hidden">Loading...</span>';
|
||||||
const targetFieldDiv = document.getElementById('div_id_id_car_model');
|
|
||||||
|
|
||||||
if (targetFieldDiv) {
|
// Find the form field you want to place it next to
|
||||||
targetFieldDiv.parentNode.insertBefore(spinner, targetFieldDiv.nextSibling);
|
// Replace 'id_your_field_name' with the actual ID of your form field
|
||||||
|
const targetField = document.getElementById('div_id_id_car_model');
|
||||||
|
|
||||||
|
if (targetField) {
|
||||||
|
// Insert the spinner right after the target field
|
||||||
|
targetField.parentNode.insertBefore(spinner, targetField.nextSibling);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row g-3 mt-4 mb-4">
|
<div class="row g-3 mt-4 mb-4">
|
||||||
<h2 class="mb-2">{{ _("Leads")|capfirst }}<li class="fas fa-bullhorn text-primary ms-2"></li></h2>
|
<h2 class="mb-2">{{ _("Leads")|capfirst }}</h2>
|
||||||
<!-- Action Tracking Modal -->
|
<!-- Action Tracking Modal -->
|
||||||
{% include "crm/leads/partials/update_action.html" %}
|
{% include "crm/leads/partials/update_action.html" %}
|
||||||
|
|
||||||
|
|||||||
@ -68,7 +68,7 @@
|
|||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="d-flex justify-content-between mb-3">
|
<div class="d-flex justify-content-between mb-3">
|
||||||
<h3>{{ _("Lead Tracking")}}<li class="fas fa-bullhorn text-primary ms-2"></li></h3>
|
<h3>{{ _("Lead Tracking")}}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row g-3 mt-4">
|
<div class="row g-3 mt-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h2 class="mb-3">{{ _("Opportunities") }} <li class="fas fas fa-rocket text-primary ms-2"></li></h2>
|
<h2 class="mb-3">{{ _("Opportunities") }}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3 mb-4">
|
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3 mb-4">
|
||||||
|
|||||||
@ -9,38 +9,38 @@
|
|||||||
{% trans 'Add New Customer'%}
|
{% trans 'Add New Customer'%}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
<link rel="stylesheet" href="{% static 'flags/sprite.css' %}">
|
||||||
|
<div class="row">
|
||||||
<div class="col-lg-8 col-md-10">
|
<div class="row mb-3">
|
||||||
<div class="card shadow-sm border-o rounded-3">
|
<div class="col-sm-6 col-md-8">
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
<div class="d-sm-flex justify-content-between">
|
||||||
<h3 class="mb-0 fs-4 text-center">
|
<h3 class="mb-3">
|
||||||
{% if customer.created %}
|
{% if customer.created %}
|
||||||
<i class="fa-solid fa-user"></i> {{ _("Edit Customer") }}
|
<i class="fa-solid fa-user"></i> {{ _("Edit Customer") }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fa-solid fa-user"></i> {{ _("Add Customer") }}
|
<i class="fa-solid fa-user"></i> {{ _("Add Customer") }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h3>
|
</h3>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body bg-light-subtle">
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-sm-6 col-md-8">
|
||||||
<form method="post" class="form row g-3 needs-validation" enctype="multipart/form-data" novalidate>
|
<form method="post" class="form row g-3 needs-validation" enctype="multipart/form-data" novalidate>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<hr class="my-2">
|
<div class="col-12">
|
||||||
|
<button class="btn btn-sm btn-phoenix-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
<!--<i class="bi bi-save"></i> -->
|
||||||
<button class="btn btn-phoenix-success btn-lg me-md-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
{{ _("Save") }}
|
||||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
</button>
|
||||||
</div>
|
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
</div>
|
|
||||||
{%endblock %}
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row g-3 mt-4">
|
<div class="row g-3 mt-4">
|
||||||
<h2 class="mb-2">{{ _("Customers")|capfirst }} <li class="fas fa-people-group text-primary ms-2"></li></h2>
|
<h2 class="mb-2">{{ _("Customers")|capfirst }}</h2>
|
||||||
<div class="row g-3 justify-content-between mb-4">
|
<div class="row g-3 justify-content-between mb-4">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<div class="d-md-flex justify-content-between">
|
<div class="d-md-flex justify-content-between">
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n static custom_filters crispy_forms_filters %}
|
{% load i18n static custom_filters%}
|
||||||
{%block title%}{%trans 'Profile'%} {%endblock%}
|
{%block title%}{%trans 'Profile'%} {%endblock%}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
@ -180,26 +180,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-lg-6">
|
|
||||||
<div class="card h-100">
|
|
||||||
<div class="bg-holder" style="background-image:url({% static 'images/bg/bg-left-20.png' %});background-position:left bottom;background-size:auto;"></div>
|
|
||||||
<div class="card-body d-flex flex-column justify-content-center position-relative">
|
|
||||||
<h4 class="mb-3">{{ _("VAT") }}</h4>
|
|
||||||
<div class="d-flex justify-content-center ">
|
|
||||||
<div class="text-center me-3">
|
|
||||||
<div class="row">
|
|
||||||
<form action="{% url 'dealer_vat_rate_update' request.dealer.slug %}" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{vatform|crispy}}
|
|
||||||
<button class="btn btn-sm btn-phoenix-primary" type="submit">{% trans 'Update' %}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -64,13 +64,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{% url 'inventort_list' request.dealer.slug request.dealer.entity.slug %}">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<span class="nav-link-icon"><span class="fas fa-boxes"></span></span><span class="nav-link-text">{% trans "Inventory List"|capfirst %}</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@ -28,27 +28,16 @@
|
|||||||
aria-label="Close"></button>
|
aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="container-fluid m-0 {% if not vendor_exists %}disabled{% endif %}">
|
||||||
<!---->
|
<form method="post" id="carForm" class="form needs-validation" novalidate>
|
||||||
<div class="row justify-content-center mt-5 mb-3 {% if not vendor_exists %}disabled{% endif %}">
|
{% csrf_token %}
|
||||||
|
{% include 'partials/form_errors.html' %}
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
<h3 class="mb-3">{% trans 'Add Car' %} <li class="fas fa-car-on text-primary ms-2"></li></h3>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
<form method="post" id="carForm" class="form needs-validation" novalidate>
|
|
||||||
{% csrf_token %}
|
|
||||||
{% include 'partials/form_errors.html' %}
|
|
||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<div class="d-flex flex-column flex-sm-grow-1 p-0">
|
<div class="d-flex flex-column flex-sm-grow-1 p-0">
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
|
<h3 class="mb-3">{% trans 'Add Car' %}</h3>
|
||||||
<!-- VIN Section -->
|
<!-- VIN Section -->
|
||||||
<div class="col-lg-12 ">
|
<div class="col-lg-12 col-xl-6">
|
||||||
<div class="card bg-body mb-3 shadow-sm">
|
<div class="card bg-body mb-3 shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<!-- Improved VIN input with integrated buttons -->
|
<!-- Improved VIN input with integrated buttons -->
|
||||||
@ -155,7 +144,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-lg-12">
|
<div class="col-xl-6">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!--Vendor Field-->
|
<!--Vendor Field-->
|
||||||
<div class="col-lg-4 col-xl-4">
|
<div class="col-lg-4 col-xl-4">
|
||||||
@ -213,39 +202,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!--Save Buttons-->
|
||||||
|
<div class="btn-group mt-3">
|
||||||
<hr class="my-2">
|
<button type="submit"
|
||||||
<!--Save Buttons-->
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
|
|
||||||
<button type="submit"
|
|
||||||
name="add_another"
|
name="add_another"
|
||||||
value="true"
|
value="true"
|
||||||
class="btn btn-lg btn-phoenix-success md-me-2">
|
class="btn btn-phoenix-success me-1">
|
||||||
{% trans "Save and Add Another" %}
|
{% trans "Save and Add Another" %}
|
||||||
</button>
|
</button>
|
||||||
<button type="submit"
|
<button type="submit"
|
||||||
name="go_to_stats"
|
name="go_to_stats"
|
||||||
value="true"
|
value="true"
|
||||||
class="btn btn-lg btn-phoenix-primary">
|
class="btn btn-phoenix-primary">
|
||||||
{% trans "Save and Go to Inventory" %}
|
{% trans "Save and Go to Inventory" %}
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Modal sections remain largely unchanged -->
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Modal sections remain largely unchanged -->
|
|
||||||
<!--Specification Modal-->
|
<!--Specification Modal-->
|
||||||
<div class="modal fade"
|
<div class="modal fade"
|
||||||
id="specificationsModal"
|
id="specificationsModal"
|
||||||
@ -334,11 +312,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
<script>
|
<script>
|
||||||
function getCookie(name) {
|
function getCookie(name) {
|
||||||
let cookieValue = null;
|
let cookieValue = null;
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
<div class="container-fluid" id="projectSummary">
|
<div class="container-fluid" id="projectSummary">
|
||||||
<div class="row g-3 justify-content-between align-items-end mb-4">
|
<div class="row g-3 justify-content-between align-items-end mb-4">
|
||||||
<div class="col-12 col-sm-auto">
|
<div class="col-12 col-sm-auto">
|
||||||
<h2 class="text-body-emphasis fw-bold mb-0">{{ _("Inventory") }}<li class="fas fa-store text-primary ms-2"></li></h2>
|
<h2 class="text-body-emphasis fw-bold mb-0">{{ _("Inventory") }}</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3 justify-content-between align-items-end mb-2">
|
<div class="row g-3 justify-content-between align-items-end mb-2">
|
||||||
|
|||||||
@ -14,11 +14,12 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
{% for i in inventory_list %}
|
{% for i in inventory_list %}
|
||||||
<tr class="hover-actions-trigger">
|
|
||||||
<td class="ps-2 fw-medium">{{ i.item_model__name }}</td>
|
<tr class="hover-actions-trigger">
|
||||||
<td class="text-center">{{ i.item_model__uom__name }}</td>
|
<td class="ps-2 fw-medium">{{ i.item_model__name }}</td>
|
||||||
<td class="text-end pe-3">{{ i.total_quantity | floatformat:3 }}</td>
|
<td class="text-center">{{ i.item_model__uom__name }}</td>
|
||||||
<td class="text-end pe-3 fw-bold text-primary">
|
<td class="text-end pe-3">{{ i.total_quantity | floatformat:3 }}</td>
|
||||||
|
<td class="text-end pe-3 fw-bold text-primary">
|
||||||
<span class="currency">{{CURRENCY}}</span>{{ i.total_value | currency_format }}
|
<span class="currency">{{CURRENCY}}</span>{{ i.total_value | currency_format }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -29,7 +30,7 @@
|
|||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
<td class="text-end pe-3 fw-bold">{% trans "Total Value" %}</td>
|
<td class="text-end pe-3 fw-bold">{% trans "Total Value" %}</td>
|
||||||
<td class="text-end pe-3 fw-bold text-success">
|
<td class="text-end pe-3 fw-bold text-success">
|
||||||
<span class="currency">{{CURRENCY}}</span>{{ inventory_total_value | currency_format }}
|
<span class="currency">{{CURRENCY}}</span>{{ inventory_total_value | currency_format }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block title %}{{ _("Add New Expense") }}{% endblock title %}
|
{% block title %}{{ _("Add New Expense") }}{% endblock title %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment %} <div class="row">
|
<div class="row">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@ -13,6 +13,8 @@
|
|||||||
<form method="post" action="">
|
<form method="post" action="">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
|
<!--<button type="submit" class="btn btn-primary">{% trans 'Save' %}</button> -->
|
||||||
|
{% comment %} <button class="btn btn-sm btn-success me-1" type="submit"><i class="fa-solid fa-floppy-disk"></i>{{ _("Save") }}</button> {% endcomment %}
|
||||||
|
|
||||||
<div class="d-flex justify-content-start">
|
<div class="d-flex justify-content-start">
|
||||||
<button class="btn btn-sm btn-phoenix-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
<button class="btn btn-sm btn-phoenix-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||||
@ -24,43 +26,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> {% endcomment %}
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{{ _("Add Expense") }}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
<form method="post" action="">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form|crispy }}
|
|
||||||
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block title %}{{ _("Update Expense") }}{% endblock title %}
|
{% block title %}{{ _("Update Expense") }}{% endblock title %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment %} <div class="row">
|
<div class="row">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@ -19,40 +19,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> {% endcomment %}
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{{ _("Update Expense") }}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
<form method="post" action="">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form|crispy }}
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment %} <div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<div class="card bg-body">
|
<div class="card bg-body">
|
||||||
@ -38,45 +38,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> {% endcomment %}
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{% if service.pk %}
|
|
||||||
{{ _("Update Service") }}
|
|
||||||
{% else %}
|
|
||||||
{{ _("Add Service") }}
|
|
||||||
{% endif %}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
<form method="post" action="">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form|crispy }}
|
|
||||||
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
|||||||
@ -12,8 +12,7 @@
|
|||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment %} <div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
<div class="card shadow rounded bg-body">
|
<div class="card shadow rounded bg-body">
|
||||||
@ -47,48 +46,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> {% endcomment %}
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{% if customer.created %}
|
|
||||||
{{ _("Edit Bank Account") }}
|
|
||||||
{% else %}
|
|
||||||
{{ _("Add Bank Account") }}
|
|
||||||
{% endif %}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
<form method="post" class="form" novalidate>
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form|crispy }}
|
|
||||||
{% for error in form.errors %}
|
|
||||||
<div class="text-danger">{{ error }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -12,7 +12,6 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment %}
|
|
||||||
<div class="row my-5">
|
<div class="row my-5">
|
||||||
<!-- Display Form Errors -->
|
<!-- Display Form Errors -->
|
||||||
<div class="card shadow rounded bg-body">
|
<div class="card shadow rounded bg-body">
|
||||||
@ -47,46 +46,5 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> {% endcomment %}
|
</div>
|
||||||
|
|
||||||
<!---->
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{% if account.created %}
|
|
||||||
|
|
||||||
<i class="fa-solid fa-book"></i> {{ _("Edit Account") }}
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
<i class="fa-solid fa-book"></i> {{ _("Add Account") }}
|
|
||||||
{% endif %}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
<form method="post" class="form" novalidate>
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form|crispy }}
|
|
||||||
{% for error in form.errors %}
|
|
||||||
<div class="text-danger">{{ error }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!---->
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -5,7 +5,7 @@
|
|||||||
{% block title %}{{ _("Create Journal Entry") }}{% endblock title %}
|
{% block title %}{{ _("Create Journal Entry") }}{% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment %} <div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<h3 class="text-center">{% trans "Create Journal Entry" %}</h3>
|
<h3 class="text-center">{% trans "Create Journal Entry" %}</h3>
|
||||||
<form id="mainForm" method="post" class="needs-validation">
|
<form id="mainForm" method="post" class="needs-validation">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@ -17,40 +17,5 @@
|
|||||||
<a href="{% url 'journalentry_list' request.dealer.slug ledger.pk %}" class="btn btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i> {% trans "Cancel" %}</a>
|
<a href="{% url 'journalentry_list' request.dealer.slug ledger.pk %}" class="btn btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i> {% trans "Cancel" %}</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div> {% endcomment %}
|
</div>
|
||||||
|
|
||||||
<!---->
|
|
||||||
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{% trans "Create Journal Entry" %}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
<form id="mainForm" method="post" class="needs-validation">
|
|
||||||
{% csrf_token %}
|
|
||||||
<div class="row g-3">
|
|
||||||
{{ form|crispy }}
|
|
||||||
</div>
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
|
||||||
<a href="{% url 'journalentry_list' request.dealer.slug ledger.pk %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i> {% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!---->
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
@ -5,13 +5,17 @@
|
|||||||
{% block title %}{{ _("Create Ledger") }}{% endblock title %}
|
{% block title %}{{ _("Create Ledger") }}{% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment %} <div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<h3 class="text-center">{% trans "Create Ledger" %}</h3>
|
<h3 class="text-center">{% trans "Create Ledger" %}</h3>
|
||||||
<form id="mainForm" method="post" class="needs-validation">
|
<form id="mainForm" method="post" class="needs-validation">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
</div>
|
</div>
|
||||||
|
{% comment %} <div class="mt-5 text-center">
|
||||||
|
<button type="submit" class="btn btn-success me-2"><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button>
|
||||||
|
<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-phoenix-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
<button class="btn btn-sm btn-phoenix-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||||
@ -20,44 +24,5 @@
|
|||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div> {% endcomment %}
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{% trans "Create Ledger" %}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
<form id="mainForm" method="post" class="needs-validation">
|
|
||||||
{% csrf_token %}
|
|
||||||
<div class="row g-3">
|
|
||||||
{{ form|crispy }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!---->
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
@ -87,7 +87,7 @@
|
|||||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||||
{% if perms.django_ledger.change_ledgermodel %}
|
{% if perms.django_ledger.change_ledgermodel%}
|
||||||
{% if ledger.can_lock %}
|
{% if ledger.can_lock %}
|
||||||
<a href="{% url 'ledger-action-lock' dealer_slug=request.dealer.slug entity_slug=entity_slug ledger_pk=ledger.uuid %}"
|
<a href="{% url 'ledger-action-lock' dealer_slug=request.dealer.slug entity_slug=entity_slug ledger_pk=ledger.uuid %}"
|
||||||
class="dropdown-item has-text-info has-text-weight-bold">{% trans 'Lock' %}</a>
|
class="dropdown-item has-text-info has-text-weight-bold">{% trans 'Lock' %}</a>
|
||||||
|
|||||||
@ -1,19 +1,3 @@
|
|||||||
<style>
|
|
||||||
.fade-out {
|
|
||||||
animation: fadeOut 1s ease-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeOut {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<!-- Notification counter -->
|
<!-- Notification counter -->
|
||||||
<div class="notification-count">
|
<div class="notification-count">
|
||||||
@ -252,10 +236,6 @@
|
|||||||
notificationCard.classList.remove('unread');
|
notificationCard.classList.remove('unread');
|
||||||
notificationCard.classList.add('read');
|
notificationCard.classList.add('read');
|
||||||
updateCounter('decrement');
|
updateCounter('decrement');
|
||||||
notificationCard.closest('.notification-card').classList.add('fade-out');
|
|
||||||
setTimeout(() => {
|
|
||||||
notificationCard.closest('.notification-card').remove();
|
|
||||||
}, 200);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,45 +9,29 @@
|
|||||||
{% trans 'Add New Organization'%}
|
{% trans 'Add New Organization'%}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
<div class="container-fluid mt-4">
|
||||||
|
<!--Heading-->
|
||||||
|
<h3 class="mb-3">
|
||||||
|
{% if object %}
|
||||||
|
{% trans 'Update Organization'%}
|
||||||
|
{% else %}
|
||||||
|
{% trans 'Add New Organization'%}
|
||||||
|
{% endif %}
|
||||||
|
</h3>
|
||||||
|
<!--form body-->
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
<div class="row mb-3">
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
<div class="col-sm-6 col-md-8">
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
<form class="form" method="post" enctype="multipart/form-data">
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{% if object %}
|
|
||||||
{% trans 'Update Organization'%}
|
|
||||||
{% else %}
|
|
||||||
{% trans 'Add New Organization'%}
|
|
||||||
{% endif %}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
<form class="form" method="post" enctype="multipart/form-data">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ redirect_field }}
|
{{ redirect_field }}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
|
<button class="btn btn-sm btn-phoenix-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
|
||||||
<hr class="my-2">
|
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
{% endblock %}
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock%}
|
|
||||||
@ -11,7 +11,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="pt-5 pb-9 ">
|
<section class="pt-5 pb-9 ">
|
||||||
<div class="row overflow-x-auto whitespace-nowrap -mx-2 sm:mx-0">
|
<div class="row overflow-x-auto whitespace-nowrap -mx-2 sm:mx-0">
|
||||||
<h2 class="mb-4">{% trans 'Organizations' %} <li class="fas fa-city text-primary ms-2"></li></h2>
|
<h2 class="mb-4">{% trans 'Organizations' %}</h2>
|
||||||
|
|
||||||
<div class="row g-3 justify-content-between mb-4">
|
<div class="row g-3 justify-content-between mb-4">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<div class="search-box me-2">
|
<div class="search-box me-2">
|
||||||
<form class="position-relative show" id="search-form">
|
<form class="position-relative show" id="search-form">
|
||||||
<input name="q" id="search-input" class="form-control form-control-sm search-input search" type="search"
|
<input name="q" id="search-input" class="form-control form-control-sm search-input search" type="search"
|
||||||
aria-label="Search" placeholder="{{ _('Search...') }}" value="{{ request.GET.q }}" />
|
aria-label="Search" placeholder="{{ _('Search') }}" value="{{ request.GET.q }}" />
|
||||||
<span class="fa fa-magnifying-glass search-box-icon"></span>
|
<span class="fa fa-magnifying-glass search-box-icon"></span>
|
||||||
{% if request.GET.q %}
|
{% if request.GET.q %}
|
||||||
<button type="button" class="btn-close position-absolute end-0 top-50 translate-middle cursor-pointer shadow-none"
|
<button type="button" class="btn-close position-absolute end-0 top-50 translate-middle cursor-pointer shadow-none"
|
||||||
|
|||||||
@ -12,13 +12,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pricing-card .card.selected {
|
.pricing-card .card.selected {
|
||||||
border-color:rgb(20, 108, 241);
|
border-color: #0d6efd;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.4);
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-check:checked + .btn .card {
|
.btn-check:checked + .btn .card {
|
||||||
/* fallback if JS fails */
|
/* fallback if JS fails */
|
||||||
border-color:rgb(13, 91, 207);
|
border-color: #0d6efd;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,37 +50,29 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container py-5">
|
<div class="container py-5">
|
||||||
<h1 class="text-center mb-5 text-primary">{{ _("Choose Your Plan")}}</h1>
|
<h1 class="text-center mb-5">{{ _("Choose Your Plan")}}</h1>
|
||||||
<form method="POST" action="{% url 'submit_plan' request.dealer.slug %}" id="wizardForm">
|
<form method="POST" action="{% url 'submit_plan' request.dealer.slug %}" id="wizardForm">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
<!-- Step 1: Plan Selection -->
|
||||||
<!--step1: Choose Plans-->
|
<div class="step" id="step1">
|
||||||
<div class="step row justify-content-center mt-5 mb-3" id="step1">
|
<h4 class="mb-4">1. {{ _("Select a Plan")}}</h4>
|
||||||
|
<div class="row g-4">
|
||||||
<div class="col-lg-8 col-md-10">
|
{% for pp in plan_list %}
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
<div class="col-md-6 col-lg-3">
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h4 class="mb-0 fs-4 text-center text-white">
|
|
||||||
1. {{ _("Select a Plan")}}
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
{% for pp in plan_list %}
|
|
||||||
<div class="col-md-12 mb-3">
|
|
||||||
<input type="radio" class="btn-check" name="selected_plan" id="plan_{{ forloop.counter }}" value="{{ pp.id }}"
|
<input type="radio" class="btn-check" name="selected_plan" id="plan_{{ forloop.counter }}" value="{{ pp.id }}"
|
||||||
data-name="{{ pp.plan.name }}" data-price="{{ pp.price }}" autocomplete="off" {% if forloop.first %}checked{% endif %}>
|
data-name="{{ pp.plan.name }}" data-price="{{ pp.price }}" autocomplete="off" {% if forloop.first %}checked{% endif %}>
|
||||||
<label class="btn w-100 p-0 pricing-card" for="plan_{{ forloop.counter }}">
|
<label class="btn w-100 p-0 pricing-card" for="plan_{{ forloop.counter }}">
|
||||||
<div class="card h-100 border border-2 rounded-4">
|
<div class="card h-100 border border-2 rounded-4">
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<h4 class="mb-3">{{ pp.plan.name|capfirst }}</h4>
|
<h4 class="mb-3">{{ pp.plan.name }}</h4>
|
||||||
<h5 class="mb-4">{{ pp.price }} <span class="icon-saudi_riyal"></span><span class="fs-6 fw-normal">/ {{ pp.pricing.period }}</span> {% trans "days" %}</h5>
|
<h5 class="mb-4">{{ pp.price }} <span class="icon-saudi_riyal"></span><span class="fs-6 fw-normal">/ {{ pp.pricing.period }}</span> {% trans "days" %}</h5>
|
||||||
<h5>{{_("Include Haikal's")}}</h5>
|
<h6>{{ _("Included") }}</h6>
|
||||||
<ul class="fa-ul ps-3">
|
<ul class="fa-ul ps-3">
|
||||||
{% if pp.plan.description %}
|
{% if pp.plan.description %}
|
||||||
{% for line in pp.plan.description|splitlines %}
|
{% for line in pp.plan.description|splitlines %}
|
||||||
<li class="mb-2">
|
<li class="mb-2">
|
||||||
<span class="fa-li"><i class="fas fa-check text-primary"></i></span>
|
<span class="fa-li"><i class="fas fa-check text-primary"></i></span>
|
||||||
{{ line|capfirst}}
|
{{ line }}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -90,156 +82,124 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
<!-- Step 2: User Info -->
|
||||||
|
<div class="step d-none" id="step2">
|
||||||
</div>
|
<h4 class="mb-4">2. {{ _("Enter Your Information")}}</h4>
|
||||||
|
<div class="row g-3">
|
||||||
<!--step2: Information-->
|
<div class="col-md-6">
|
||||||
|
<label class="form-label" for="first_name">{{ _("First Name")}}</label>
|
||||||
<div class="step d-none row justify-content-center mt-5 mb-3" id="step2">
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="fas fa-user"></i></span>
|
||||||
<div class="col-lg-8 col-md-10">
|
<input type="text" name="first_name" id="first_name" class="form-control form-control-sm" required placeholder="{{ _("First Name")}}" value="{{ request.user.first_name }}">
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
2. {{ _("Enter Your Information")}}
|
|
||||||
</h3>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body bg-light-subtle">
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
<label class="form-label" for="first_name">{{ _("First Name")}}</label>
|
<label class="form-label" for="last_name">{{ _("Last Name")}}</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-text"><i class="fas fa-user"></i></span>
|
<span class="input-group-text"><i class="fas fa-user"></i></span>
|
||||||
<input type="text" name="first_name" id="first_name" class="form-control form-control-sm" required placeholder="{{ _("First Name")}}" value="{{ request.user.first_name }}">
|
<input type="text" name="last_name" id="last_name" class="form-control form-control-sm" required placeholder="{{ _("Last Name")}}" value="{{ request.user.last_name }}">
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="form-label" for="last_name">{{ _("Last Name")}}</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text"><i class="fas fa-user"></i></span>
|
|
||||||
<input type="text" name="last_name" id="last_name" class="form-control form-control-sm" required placeholder="{{ _("Last Name")}}" value="{{ request.user.last_name }}">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="form-label" for="email">{{ _("Email Address")}}</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text"><i class="fas fa-envelope"></i></span>
|
|
||||||
<input type="email" name="email" id="email" class="form-control form-control-sm" required placeholder="email@example.com" value="{{ request.user.email }}">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="form-label" for="phone">{{ _("Phone Number")}}</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text"><i class="fas fa-phone"></i></span>
|
|
||||||
<input type="text" name="phone" id="phone" class="form-control form-control-sm" dir="ltr" placeholder="{{ _("Phone Number")}}" value="{{ request.dealer.phone_number.raw_input }}" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="form-label" for="company">{{ _("Company") }}</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text"><i class="fas fa-building"></i></span>
|
|
||||||
<input type="text" name="company" id="company" class="form-control form-control-sm" placeholder="{{ _("Company") }}" value="{{ request.dealer.get_local_name }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label" for="email">{{ _("Email Address")}}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="fas fa-envelope"></i></span>
|
||||||
|
<input type="email" name="email" id="email" class="form-control form-control-sm" required placeholder="email@example.com" value="{{ request.user.email }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label" for="phone">{{ _("Phone Number")}}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="fas fa-phone"></i></span>
|
||||||
|
<input type="text" name="phone" id="phone" class="form-control form-control-sm" dir="ltr" placeholder="{{ _("Phone Number")}}" value="{{ request.dealer.phone_number.raw_input }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label" for="company">{{ _("Company") }}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="fas fa-building"></i></span>
|
||||||
|
<input type="text" name="company" id="company" class="form-control form-control-sm" placeholder="{{ _("Company") }}" value="{{ request.dealer.get_local_name }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
<!-- Step 3: Payment -->
|
||||||
|
<div class="step d-none" id="step3">
|
||||||
</div>
|
<h4 class="mb-4">3. {{ _("Payment Information")}}</h4>
|
||||||
<!--step3: Payment-->
|
<div class="row g-3">
|
||||||
<div class="step d-none row justify-content-center mt-5 mb-3" id="step3">
|
<div class="col-md-6">
|
||||||
|
<label class="form-label" for="card_name">{{ _("Cardholder Name")}}</label>
|
||||||
<div class="col-lg-8 col-md-10">
|
<div class="input-group">
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
<span class="input-group-text"><i class="fas fa-user"></i></span>
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
<input type="text" name="card_name" id="card_name" class="form-control form-control-sm" placeholder="{{ _("Cardholder Name")}}" required>
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
3. {{ _("Payment Information")}}
|
|
||||||
</h3>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body bg-light-subtle">
|
</div>
|
||||||
<label class="form-label" for="card_name">{{ _("Cardholder Name")}}</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text"><i class="fas fa-user"></i></span>
|
|
||||||
<input type="text" name="card_name" id="card_name" class="form-control form-control-sm" placeholder="{{ _("Cardholder Name")}}" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="form-label" for="card_number">{{ _("Card Number")}}</label>
|
<div class="col-md-6">
|
||||||
<div class="input-group">
|
<label class="form-label" for="card_number">{{ _("Card Number")}}</label>
|
||||||
<span class="input-group-text"><i class="fas fa-credit-card"></i></span>
|
<div class="input-group">
|
||||||
<input type="text" name="card_number" id="card_number" class="form-control form-control-sm" placeholder="{{ _("Card Number")}}"
|
<span class="input-group-text"><i class="fas fa-credit-card"></i></span>
|
||||||
maxlength="19" pattern="^\d{4}\s\d{4}\s\d{4}\s\d{4}$"
|
<input type="text" name="card_number" id="card_number" class="form-control form-control-sm" placeholder="{{ _("Card Number")}}"
|
||||||
inputmode="numeric" required title="Enter a 16-digit card number">
|
maxlength="19" pattern="^\d{4}\s\d{4}\s\d{4}\s\d{4}$"
|
||||||
</div>
|
inputmode="numeric" required title="Enter a 16-digit card number">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
<label class="form-label" for="card_expiry">{{ _("Expiry Date")}} (MM/YY)</label>
|
<label class="form-label" for="card_expiry">{{ _("Expiry Date")}} (MM/YY)</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-text"><i class="far fa-calendar-alt"></i></span>
|
<span class="input-group-text"><i class="far fa-calendar-alt"></i></span>
|
||||||
<input type="text" name="card_expiry" id="card_expiry" class="form-control form-control-sm" placeholder="{{ _("Expiry Date")}}"
|
<input type="text" name="card_expiry" id="card_expiry" class="form-control form-control-sm" placeholder="{{ _("Expiry Date")}}"
|
||||||
maxlength="5" pattern="^(0[1-9]|1[0-2])\/\d{2}$"
|
maxlength="5" pattern="^(0[1-9]|1[0-2])\/\d{2}$"
|
||||||
inputmode="numeric" required title="Enter expiry in MM/YY format">
|
inputmode="numeric" required title="Enter expiry in MM/YY format">
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="form-label" for="card_cvv">{{ _("CVV") }}</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text"><i class="fas fa-lock"></i></span>
|
|
||||||
<input type="text" name="card_cvv" id="card_cvv" class="form-control form-control-sm" placeholder="{{ _("CVV") }}"
|
|
||||||
maxlength="3" pattern="^\d{3}$"
|
|
||||||
inputmode="numeric" required title="Enter 3-digit CVV">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-2">
|
||||||
|
<label class="form-label" for="card_cvv">{{ _("CVV") }}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="fas fa-lock"></i></span>
|
||||||
|
<input type="text" name="card_cvv" id="card_cvv" class="form-control form-control-sm" placeholder="{{ _("CVV") }}"
|
||||||
|
maxlength="3" pattern="^\d{3}$"
|
||||||
|
inputmode="numeric" required title="Enter 3-digit CVV">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
<!-- Step 4: Confirmation -->
|
||||||
|
<div class="step d-none" id="step4">
|
||||||
</div>
|
<h4 class="mb-4">4. {{ _("Confirm Your Information")}}</h4>
|
||||||
<!--Step4 confirmation-->
|
<div class="summary-box">
|
||||||
|
<h5><i class="fas fa-file-invoice-dollar me-2"></i>{{ _("Order Summary")}}</h5>
|
||||||
<div class="step d-none row justify-content-center mt-5 mb-3" id="step4">
|
<div class="summary-item"><i class="fas fa-box"></i><strong>{{ _("Plan") }}:</strong> <span id="summary_plan"></span></div>
|
||||||
|
<div class="summary-item"><i class="fas fa-tag"></i><strong>{{ _("Price") }}:</strong> <span id="summary_price"></span></div>
|
||||||
<div class="col-lg-8 col-md-10">
|
<div class="summary-item"><i class="fas fa-receipt"></i><strong>{{ _("VAT") }} (15%):</strong> <span id="summary-tax">0.00</span> <span class="icon-saudi_riyal"></span></div>
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
4. {{ _("Confirm Your Information")}}
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle me-2">
|
|
||||||
<h5 class="text-center"><i class="fas fa-file-invoice-dollar me-2"></i>{{ _("Order Summary")}}</h5>
|
|
||||||
<div class="summary-item"><i class="fas fa-box me-2"></i><strong>{{ _("Plan") }}:</strong> <span id="summary_plan"></span></div>
|
|
||||||
<div class="summary-item"><i class="fas fa-tag me-2"></i><strong>{{ _("Price") }}:</strong> <span id="summary_price"></span></div>
|
|
||||||
<div class="summary-item"><i class="fas fa-receipt me-2"></i><strong>{{ _("VAT") }} (15%):</strong> <span id="summary-tax">0.00</span> <span class="icon-saudi_riyal"></span></div>
|
|
||||||
<div class="summary-item"><i class="fas fa-hand-holding-usd me-2"></i><strong>{{ _("Total") }}:</strong> <span id="summary-total">0.00</span> <span class="icon-saudi_riyal"></span></div>
|
|
||||||
<hr>
|
<hr>
|
||||||
|
<div class="summary-item"><i class="fas fa-hand-holding-usd"></i><strong>{{ _("Total") }}:</strong> <span id="summary-total">0.00</span> <span class="icon-saudi_riyal"></span></div>
|
||||||
|
|
||||||
|
<h5 class="mt-4"><i class="fas fa-user me-2"></i>{{ _("User Information")}}</h5>
|
||||||
|
<div class="summary-item"><i class="fas fa-signature"></i><strong>{{ _("Name") }}:</strong> <span id="summary_name"></span></div>
|
||||||
|
<div class="summary-item"><i class="fas fa-envelope"></i><strong>{{ _("Email") }}:</strong> <span id="summary_email"></span></div>
|
||||||
|
<div class="summary-item"><i class="fas fa-building"></i><strong>{{ _("Company") }}:</strong> <span id="summary_company"></span></div>
|
||||||
|
<div class="summary-item"><i class="fas fa-phone"></i><strong>{{ _("Phone") }}:</strong> <span id="summary_phone"></span></div>
|
||||||
|
|
||||||
<h5 class="mt-4 text-center"><i class="fas fa-user me-2"></i>{{ _("User Information")}}</h5>
|
<h5 class="mt-4"><i class="fas fa-credit-card me-2"></i>{{ _("Payment") }}</h5>
|
||||||
<div class="summary-item"><i class="fas fa-signature me-2"></i><strong>{{ _("Name") }}:</strong> <span id="summary_name"></span></div>
|
<div class="summary-item"><i class="fas fa-user"></i><strong>{{ _("Cardholder") }}:</strong> <span id="summary_card_name"></span></div>
|
||||||
<div class="summary-item"><i class="fas fa-envelope me-2"></i><strong>{{ _("Email") }}:</strong> <span id="summary_email"></span></div>
|
<div class="summary-item"><i class="fas fa-credit-card"></i><strong>{{ _("Card Number")}}:</strong> <span id="summary_card_number"></span></div>
|
||||||
<div class="summary-item"><i class="fas fa-building me-2"></i><strong>{{ _("Company") }}:</strong> <span id="summary_company"></span></div>
|
<div class="summary-item"><i class="far fa-calendar-alt"></i><strong>{{ _("Expiry") }}:</strong> <span id="summary_card_expiry"></span></div>
|
||||||
<div class="summary-item"><i class="fas fa-phone me-2"></i><strong>{{ _("Phone") }}:</strong> <span id="summary_phone"></span></div>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h5 class="mt-4 text-center"><i class="fas fa-credit-card me-2"></i>{{ _("Payment") }}</h5>
|
|
||||||
<div class="summary-item"><i class="fas fa-user me-2"></i><strong>{{ _("Cardholder") }}:</strong> <span id="summary_card_name"></span></div>
|
|
||||||
<div class="summary-item"><i class="fas fa-credit-card me-2"></i><strong>{{ _("Card Number")}}:</strong> <span id="summary_card_number"></span></div>
|
|
||||||
<div class="summary-item"><i class="far fa-calendar-alt me-2"></i><strong>{{ _("Expiry") }}:</strong> <span id="summary_card_expiry"></span></div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
|
|
||||||
<!-- Navigation -->
|
<!-- Navigation -->
|
||||||
<div class="d-flex justify-content-between mt-4">
|
<div class="d-flex justify-content-between mt-4">
|
||||||
<button type="button" class="btn btn-lg btn-phoenix-secondary" id="prevBtn" disabled>{{ _("Previous") }}</button>
|
<button type="button" class="btn btn-phoenix-secondary" id="prevBtn" disabled>{{ _("Previous") }}</button>
|
||||||
<button type="button" class="btn btn-lg btn-phoenix-primary" id="nextBtn">{{ _("Next") }}</button>
|
<button type="button" class="btn btn-phoenix-primary" id="nextBtn">{{ _("Next") }}</button>
|
||||||
<button type="submit" class="btn btn-lg btn-phoenix-primary d-none" id="submitBtn">{{ _("Confirm") }}</button>
|
<button type="submit" class="btn btn-phoenix-success d-none" id="submitBtn">{{ _("Confirm") }}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -32,26 +32,15 @@
|
|||||||
{% if not create_po %}
|
{% if not create_po %}
|
||||||
{% if style == 'po-detail' %}
|
{% if style == 'po-detail' %}
|
||||||
<div class="card shadow-sm border-0 mb-2">
|
<div class="card shadow-sm border-0 mb-2">
|
||||||
<div class="card-header bg-light ">
|
<div class="card-header bg-light">
|
||||||
<div class="d-flex align-items-center mb-2 ">
|
<div class="d-flex align-items-center">
|
||||||
<span class="me-3 text-primary">
|
<span class="me-3 text-primary">
|
||||||
{% icon 'uil:bill' 36 %}
|
{% icon 'uil:bill' 36 %}
|
||||||
</span>
|
</span>
|
||||||
<h2 class="h3 mb-0 text-primary me-4">
|
<h2 class="h3 mb-0">
|
||||||
{{ po_model.po_number }}
|
{{ po_model.po_number }}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p>
|
|
||||||
<a class="btn btn-phoenix-primary"
|
|
||||||
href="{% url 'purchase_order_list' request.dealer.slug request.dealer.entity.slug %}"
|
|
||||||
title="Click to view the complete list of Purchase Orders"
|
|
||||||
role="button">
|
|
||||||
<i class="fas fa-list me-2"></i>{% trans 'PO List' %}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -63,7 +52,6 @@
|
|||||||
{{ po_model.get_po_status_display }}
|
{{ po_model.get_po_status_display }}
|
||||||
</span>
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@ -111,7 +99,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class='col-12 col-md-12 col-lg-2 d-grid align-content-end'>
|
||||||
|
<a class="btn btn-phoenix-primary py-2"
|
||||||
|
href="{% url 'purchase_order_list' request.dealer.slug request.dealer.entity.slug %}"
|
||||||
|
title="Click to view the complete list of Purchase Orders"
|
||||||
|
role="button">
|
||||||
|
<i class="fas fa-list me-2"></i>{% trans 'PO List' %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -10,42 +10,44 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-9">
|
||||||
|
<div class="d-sm-flex justify-content-between">
|
||||||
|
|
||||||
<!---->
|
<h3 class="mb-3">
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
{% if vendor.created %}
|
||||||
|
<!--<i class="bi bi-pencil-square"></i>-->
|
||||||
<div class="col-lg-8 col-md-10 ">
|
{{ _("Edit Purchase Order") }}
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
{% else %}
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
<!--<i class="bi bi-person-plus"></i> -->
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
{{ _("Add New Purchase Order") }}
|
||||||
{{ _("Add New Purchase Order") }}
|
{% endif %}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
<form class="row g-3 mb-9" method="post" class="form" enctype="multipart/form-data" novalidate >
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ redirect_field }}
|
|
||||||
{{ form|crispy }}
|
|
||||||
{% for error in form.errors %}
|
|
||||||
<div class="text-danger">{{ error }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
<div class="row">
|
||||||
|
<div class="col-xl-9">
|
||||||
|
|
||||||
</div>
|
<form class="row g-3 mb-9" method="post" class="form" enctype="multipart/form-data" novalidate >
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ redirect_field }}
|
||||||
|
{{ 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-phoenix-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-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!---->
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -13,26 +13,21 @@
|
|||||||
<div class="alert alert-success">{{ message }}</div>
|
<div class="alert alert-success">{{ message }}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<!-- Add New PO Button -->
|
||||||
<h2 class="">
|
<div class="d-flex justify-content-between mb-2">
|
||||||
{{ _("Purchase Orders") |capfirst }} <li class="fas fa-file-invoice text-primary ms-2"></li>
|
<h3 class="">
|
||||||
|
{{ _("Purchase Orders") |capfirst }}
|
||||||
</h2>
|
</h2>
|
||||||
|
{% if perms.django_ledger.add_purchaseordermodel%}
|
||||||
<div class="row g-3 justify-content-between mb-4">
|
<div>
|
||||||
<div class="col-auto">
|
{% if perms.django_ledger.add_purchaseordermodel %}
|
||||||
<div class="d-md-flex justify-content-between">
|
|
||||||
{% if perms.django_ledger.add_purchaseordermodel %}
|
|
||||||
<a href="{% url 'purchase_order_create' request.dealer.slug request.dealer.entity.slug %}"
|
<a href="{% url 'purchase_order_create' request.dealer.slug request.dealer.entity.slug %}"
|
||||||
class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{{ _("Create New PO") }}</a>
|
class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{{ _("Create New PO") }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
{% include "partials/search_box.html" %}
|
||||||
<div class="d-flex">
|
|
||||||
{% include 'partials/search_box.html' %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-responsive px-1 scrollbar mt-3">
|
<div class="table-responsive px-1 scrollbar mt-3">
|
||||||
<table class= "table align-items-center table-flush table-hover">
|
<table class= "table align-items-center table-flush table-hover">
|
||||||
@ -79,7 +74,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if po.po_status == 'fulfilled' %}
|
{% if po.po_status == 'fulfilled' %}
|
||||||
{% if perms.inventory.add_car %}
|
{% if perms.inventory.add_car %}
|
||||||
<a href="{% url 'view_items_inventory' dealer_slug=request.dealer.slug entity_slug=entity_slug po_pk=po.pk %}" class="dropdown-item text-success-dark">{% trans 'Inventory Items' %}</a>
|
<a href="{% url 'view_items_inventory' dealer_slug=request.dealer.slug entity_slug=entity_slug po_pk=po.pk %}" class="dropdown-item text-success-dark">{% trans 'Add Inventory Items' %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<button class="dropdown-item text-warning-dark" disabled><span class="fas fa-exclamation-triangle me-1"></span> Fulfill the PO Before Viewing Inventory</button>
|
<button class="dropdown-item text-warning-dark" disabled><span class="fas fa-exclamation-triangle me-1"></span> Fulfill the PO Before Viewing Inventory</button>
|
||||||
|
|||||||
@ -24,11 +24,13 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<button type="submit"
|
<button type="submit"
|
||||||
class="btn btn-phoenix-success my-2 me-2">{% trans 'Save PO' %}
|
class="btn btn-phoenix-success w-100 my-2">{% trans 'Save PO' %}
|
||||||
</button>
|
</button>
|
||||||
<a href="{% url 'purchase_order_detail' request.dealer.slug request.dealer.entity.slug po_model.uuid %}"
|
<a href="{% url 'purchase_order_detail' request.dealer.slug request.dealer.entity.slug po_model.uuid %}"
|
||||||
class="btn btn-phoenix-secondary my-2">{% trans 'Back to PO Detail' %}</a>
|
class="btn btn-phoenix-secondary w-100 my-2">{% trans 'Back to PO Detail' %}</a>
|
||||||
|
<a href="{% url 'purchase_order_list' request.dealer.slug request.dealer.entity.slug %}"
|
||||||
|
class="btn btn-phoenix-info
|
||||||
|
info w-100 my-2">{% trans 'PO List' %}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n custom_filters%}
|
{% load i18n custom_filters%}
|
||||||
{% load crispy_forms_filters %}
|
|
||||||
|
|
||||||
{% block title %}{{ _("View Quotation") }}{% endblock title %}
|
{% block title %}{{ _("View Quotation") }}{% endblock title %}
|
||||||
|
|
||||||
@ -84,11 +83,6 @@
|
|||||||
{% if perms.django_ledger.can_approve_estimatemodel %}
|
{% if perms.django_ledger.can_approve_estimatemodel %}
|
||||||
<button id="accept_estimate" onclick="setFormAction('approved')" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Approved' %}</span></button>
|
<button id="accept_estimate" onclick="setFormAction('approved')" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Approved' %}</span></button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if estimate.can_approve and not request.is_manager %}
|
|
||||||
<button class="btn btn-phoenix-warning" disabled>
|
|
||||||
<i class="fas fa-hourglass-start me-2"></i><span class="text-warning">{% trans 'Waiting for Manager Approval' %}</span>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% elif estimate.status == 'approved' %}
|
{% elif estimate.status == 'approved' %}
|
||||||
{% if perms.django_ledger.change_estimatemodel %}
|
{% if perms.django_ledger.change_estimatemodel %}
|
||||||
<a href="{% url 'send_email' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary me-2"><span class="fa-regular fa-paper-plane me-sm-2"></span><span class="d-none d-sm-inline-block">{% trans 'Send Quotation' %}</span></a>
|
<a href="{% url 'send_email' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary me-2"><span class="fa-regular fa-paper-plane me-sm-2"></span><span class="d-none d-sm-inline-block">{% trans 'Send Quotation' %}</span></a>
|
||||||
@ -192,22 +186,15 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Vat" %} ({{data.vat}})</td>
|
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Vat" %} ({{data.vat|percentage}})</td>
|
||||||
<td class="align-middle text-start fw-semibold">
|
<td class="align-middle text-start fw-semibold">
|
||||||
<span id="grand-total">+ {{data.total_vat_amount|floatformat}}<span class="icon-saudi_riyal"></span></span>
|
<span id="grand-total">+ {{data.total_vat_amount|floatformat}}<span class="icon-saudi_riyal"></span></span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Discount Amount" %}</td>
|
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Discount Amount" %}</td>
|
||||||
<td class="align-middle text-start text-danger fw-semibold">
|
<td class="align-middle text-start text-danger fw-semibold ">
|
||||||
<form action="{% url 'update_estimate_discount' request.dealer.slug estimate.pk %}" method="post">
|
<span id="grand-total">- {{data.total_discount|floatformat}}<span class="icon-saudi_riyal"></span></span>
|
||||||
{% csrf_token %}
|
|
||||||
<div class="input-group input-group-sm">
|
|
||||||
<input type="number" class="form-control" name="discount_amount" value="{{data.total_discount}}" step="0.01" style="width: 1px;">
|
|
||||||
<span class="input-group-text"><span class="icon-saudi_riyal"></span></span>
|
|
||||||
<button type="submit" class="btn btn-sm btn-phoenix-primary ms-n2">{% trans "Update" %}</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
@ -216,7 +203,6 @@
|
|||||||
{% for service in data.additionals %}
|
{% for service in data.additionals %}
|
||||||
<small><span class="fw-semibold">+ {{service.name}} - {{service.price_|floatformat}}<span class="icon-saudi_riyal"></span></span></small><br>
|
<small><span class="fw-semibold">+ {{service.name}} - {{service.price_|floatformat}}<span class="icon-saudi_riyal"></span></span></small><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<button class="btn btn-phoenix-primary btn-xs ms-auto" type="button" data-bs-toggle="modal" data-bs-target="#additionalModal"><span class="fas fa-plus me-1"></span>{{ _("Add") }}</button>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="bg-body-secondary total-sum">
|
<tr class="bg-body-secondary total-sum">
|
||||||
@ -235,27 +221,6 @@
|
|||||||
</section>
|
</section>
|
||||||
<!-- <section> close ============================-->
|
<!-- <section> close ============================-->
|
||||||
<!-- ============================================-->
|
<!-- ============================================-->
|
||||||
<!-- add update Modal -->
|
|
||||||
<div class="modal fade" id="additionalModal" tabindex="-1" aria-labelledby="additionalModalLabel" 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">
|
|
||||||
<h4 class="modal-title" id="additionalModalLabel">{% trans 'Additional Services' %}</h4>
|
|
||||||
<button class="btn p-0 text-body-quaternary fs-6" data-bs-dismiss="modal" aria-label="Close">
|
|
||||||
<span class="fas fa-times"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<form action="{% url 'update_estimate_additionals' request.dealer.slug estimate.pk %}" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{additionals_form|crispy}}
|
|
||||||
<button type="submit" class="btn btn-phoenix-primary">{% trans 'Update' %}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block customJS %}
|
{% block customJS %}
|
||||||
|
|||||||
@ -120,89 +120,8 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock customCSS %}
|
{% endblock customCSS %}
|
||||||
<!---->
|
|
||||||
{% block content%}
|
|
||||||
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
{% if not items %}
|
|
||||||
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
|
||||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
|
||||||
<p class="mb-0 flex-1">{{ _("Please add at least one car before creating a quotation.") }}<a class="ms-3 text-body-primary fs-9" href="{% url 'car_add' request.dealer.slug %}"> {{ _("Add Car") }} </a></p>
|
|
||||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if not customer_count %}
|
|
||||||
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
|
||||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
|
||||||
<p class="mb-0 flex-1"> {{ _("Please add at least one customer before creating a quotation.") }}<a class="ms-3 text-body-primary fs-9" href="{% url 'customer_create' request.dealer.slug %}"> {{ _("Add Customer") }} </a></p>
|
|
||||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
<i class="fa-regular fa-file-lines"></i> {% trans "Create Quotation" %}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
|
|
||||||
<form id="mainForm" method="post" class="needs-validation {% if not items or not customer_count %}disabled{% endif %}">
|
|
||||||
|
|
||||||
{% csrf_token %}
|
|
||||||
<div class="row g-3 col-12">
|
|
||||||
{{ form|crispy }}
|
|
||||||
<div class="custom-select">
|
|
||||||
<!-- Hidden native select for form submission -->
|
|
||||||
<select class="native-select" name="item" required tabindex="-1">
|
|
||||||
<option value="">Select a car</option>
|
|
||||||
{% for item in items %}
|
|
||||||
<option value="{{ item.hash }}"></option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<!-- Custom select UI -->
|
|
||||||
<div class="select-trigger">
|
|
||||||
<div class="selected-value">
|
|
||||||
<span>Select a car</span>
|
|
||||||
</div>
|
|
||||||
<i class="fas fa-chevron-down dropdown-icon"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="options-container">
|
|
||||||
{% for item in items %}
|
|
||||||
<div class="option" data-value="{{ item.hash }}" data-image="{{item.logo}}">
|
|
||||||
<img src="{{item.logo}}" alt="{{item.model}}">
|
|
||||||
<span>{{item.make}} {{item.model}} {{item.serie}} {{item.trim}} {{item.color_name}}</span>
|
|
||||||
<div class="color-box" style="background-color: rgb({{ item.exterior_color }});"></div>
|
|
||||||
<div class="color-box" style="background-color: rgb({{ item.interior_color }});"></div>
|
|
||||||
<span style="color:gray;">({{item.hash_count}} in stock)</span>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
<!---->
|
|
||||||
|
|
||||||
{% comment %} {% block content %}
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
{% if not items %}
|
{% if not items %}
|
||||||
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
||||||
@ -265,7 +184,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %} {% endcomment %}
|
{% endblock content %}
|
||||||
|
|
||||||
{% block customJS %}
|
{% block customJS %}
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block title %}{{ _("Invoice") }}{% endblock title %}
|
{% block title %}{{ _("Invoice") }}{% endblock title %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment %} <div class="row paid">
|
<div class="row paid">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@ -19,42 +19,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> {% endcomment %}
|
</div>
|
||||||
|
|
||||||
<!---->
|
|
||||||
<div class="row paid justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
<i class="fa-solid fa-receipt"></i> {{ _("Add Invoice") }}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
|
|
||||||
|
|
||||||
<form method="post" action="">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ form|crispy }}
|
|
||||||
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
|||||||
@ -82,7 +82,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="d-flex align-items-center gap-2">
|
||||||
{% if perms.inventory.add_payment%}
|
{% if perms.django_ledger.add_payment%}
|
||||||
{% if invoice.invoice_status == 'in_review' %}
|
{% if invoice.invoice_status == 'in_review' %}
|
||||||
<button id="accept_invoice" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Accept' %}</span></button>
|
<button id="accept_invoice" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Accept' %}</span></button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@ -39,8 +39,6 @@
|
|||||||
{{ form.arabic_name|as_crispy_field }}
|
{{ form.arabic_name|as_crispy_field }}
|
||||||
{{ form.email|as_crispy_field }}
|
{{ form.email|as_crispy_field }}
|
||||||
{{ form.phone_number|as_crispy_field }}
|
{{ form.phone_number|as_crispy_field }}
|
||||||
{{ form.address|as_crispy_field }}
|
|
||||||
{{ form.image|as_crispy_field }}
|
|
||||||
{{ form.group|as_crispy_field }}
|
{{ form.group|as_crispy_field }}
|
||||||
{% for error in form.errors %}
|
{% for error in form.errors %}
|
||||||
<div class="text-danger">{{ error }}</div>
|
<div class="text-danger">{{ error }}</div>
|
||||||
|
|||||||
41
templates/vendors/vendor_form.html
vendored
41
templates/vendors/vendor_form.html
vendored
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% comment %}
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-9">
|
<div class="col-xl-9">
|
||||||
@ -54,43 +54,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endcomment %}
|
|
||||||
|
|
||||||
<!---->
|
|
||||||
<div class="row justify-content-center mt-5 mb-3">
|
|
||||||
|
|
||||||
<div class="col-lg-8 col-md-10">
|
|
||||||
<div class="card shadow-sm border-0 rounded-3">
|
|
||||||
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
|
|
||||||
<h3 class="mb-0 fs-4 text-center text-white">
|
|
||||||
{% if vendor.created %}
|
|
||||||
{{ _("Edit Vendor") }}
|
|
||||||
{% else %}
|
|
||||||
{{ _("Add Vendor") }}
|
|
||||||
{% endif %}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body bg-light-subtle">
|
|
||||||
<form class="row g-3 mb-9" method="post" class="form" enctype="multipart/form-data" novalidate >
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ redirect_field }}
|
|
||||||
{{ form|crispy }}
|
|
||||||
{% for error in form.errors %}
|
|
||||||
<div class="text-danger">{{ error }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<hr class="my-2">
|
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
|
|
||||||
<button class="btn btn-lg btn-phoenix-success md-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-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!---->
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -28,21 +28,21 @@
|
|||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&display=swap" rel="stylesheet">
|
||||||
{% comment %} <link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet"> {% endcomment %}
|
<link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet">
|
||||||
{% comment %} <link href="{% static 'css/sweetalert2.min.css' %}" rel="stylesheet"> {% endcomment %}
|
<link href="{% static 'css/sweetalert2.min.css' %}" rel="stylesheet">
|
||||||
{% comment %} <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css"> {% endcomment %}
|
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css">
|
||||||
|
|
||||||
{% if LANGUAGE_CODE == 'ar' %}
|
{% if LANGUAGE_CODE == 'en' %}
|
||||||
<link href="{% static 'css/theme-rtl.min.css' %}" type="text/css" rel="stylesheet" id="style-rtl">
|
<link href="{% static 'css/theme.min.css' %}" type="text/css" rel="stylesheet" id="style-default">
|
||||||
<link href="{% static 'css/user-rtl.min.css' %}" type="text/css" rel="stylesheet" id="user-style-rtl">
|
<link href="{% static 'css/user.min.css' %}" type="text/css" rel="stylesheet" id="user-style-default">
|
||||||
{% else %}
|
{% else %}
|
||||||
<link href="{% static 'css/theme.min.css' %}" type="text/css" rel="stylesheet" id="style-default">
|
<link href="{% static 'css/theme-rtl.min.css' %}" type="text/css" rel="stylesheet" id="style-rtl">
|
||||||
<link href="{% static 'css/user.min.css' %}" type="text/css" rel="stylesheet" id="user-style-default">
|
<link href="{% static 'css/user-rtl.min.css' %}" type="text/css" rel="stylesheet" id="user-style-rtl">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script>
|
<script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script>
|
||||||
<script src="{% static 'js/config.js' %}"></script>
|
<script src="{% static 'js/config.js' %}"></script>
|
||||||
{% comment %} <script src="{% static 'js/sweetalert2.all.min.js' %}"></script> {% endcomment %}
|
<script src="{% static 'js/sweetalert2.all.min.js' %}"></script>
|
||||||
<link href="{% static 'css/custom.css' %}" rel="stylesheet">
|
<link href="{% static 'css/custom.css' %}" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@ -52,27 +52,9 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
{% comment %}
|
|
||||||
<script src="{% static 'vendors/anchorjs/anchor.min.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/is/is.min.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/list.js/list.min.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/dayjs/dayjs.min.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/echarts/echarts.min.js' %}"></script>
|
|
||||||
<script src="{% static 'js/travel-agency-dashboard.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/mapbox-gl/mapbox-gl.js' %}"></script>
|
|
||||||
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
|
|
||||||
<script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script> {% endcomment %}
|
|
||||||
|
|
||||||
<script src="{% static 'vendors/popper/popper.min.js' %}"></script>
|
<script src="{% static 'vendors/popper/popper.min.js' %}"></script>
|
||||||
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
|
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
|
||||||
<script src="{% static 'vendors/fontawesome/all.min.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/lodash/lodash.min.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/feather-icons/feather.min.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/typed.js/typed.umd.js' %}"></script>
|
|
||||||
<script src="{% static 'js/phoenix.js' %}"></script>
|
|
||||||
|
|
||||||
{% comment %} <script src="{% static 'vendors/popper/popper.min.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
|
|
||||||
<script src="{% static 'vendors/anchorjs/anchor.min.js' %}"></script>
|
<script src="{% static 'vendors/anchorjs/anchor.min.js' %}"></script>
|
||||||
<script src="{% static 'vendors/is/is.min.js' %}"></script>
|
<script src="{% static 'vendors/is/is.min.js' %}"></script>
|
||||||
<script src="{% static 'vendors/fontawesome/all.min.js' %}"></script>
|
<script src="{% static 'vendors/fontawesome/all.min.js' %}"></script>
|
||||||
@ -86,7 +68,7 @@
|
|||||||
<script src="{% static 'vendors/mapbox-gl/mapbox-gl.js' %}"></script>
|
<script src="{% static 'vendors/mapbox-gl/mapbox-gl.js' %}"></script>
|
||||||
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
|
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
|
||||||
<script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script>
|
<script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script>
|
||||||
<script src="{% static 'vendors/typed.js/typed.umd.js' %}"></script> {% endcomment %}
|
<script src="{% static 'vendors/typed.js/typed.umd.js' %}"></script>
|
||||||
|
|
||||||
{% block customJS %}
|
{% block customJS %}
|
||||||
{% endblock customJS %}
|
{% endblock customJS %}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user