407 lines
12 KiB
Python
407 lines
12 KiB
Python
from phonenumber_field.formfields import PhoneNumberField
|
|
from django.core.validators import RegexValidator
|
|
from django import forms
|
|
from .mixins import AddClassMixin
|
|
from django.forms.models import inlineformset_factory
|
|
from .models import (
|
|
Dealer,
|
|
# Branch,
|
|
Vendor,
|
|
Customer,
|
|
Car,
|
|
CarFinance,
|
|
CustomCard,
|
|
CarRegistration,
|
|
CarColors,
|
|
ExteriorColors,
|
|
InteriorColors,
|
|
SaleQuotation,
|
|
CarLocation,
|
|
Organization,
|
|
Representative,
|
|
Payment,
|
|
SaleQuotationCar,
|
|
AdditionalServices
|
|
|
|
)
|
|
from django_ledger.models import ItemModel
|
|
from django.forms import ModelMultipleChoiceField, ValidationError
|
|
from django.utils.translation import gettext_lazy as _
|
|
import django_tables2 as tables
|
|
from django.forms import formset_factory
|
|
|
|
|
|
class AdditionalServiceForm(forms.ModelForm):
|
|
class Meta:
|
|
model = AdditionalServices
|
|
fields = ['name', 'price','description','taxable', 'uom']
|
|
|
|
class PaymentForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Payment
|
|
fields = ['amount','payment_method', 'reference_number']
|
|
|
|
class UserForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Dealer
|
|
fields = ['name', 'arabic_name', 'phone_number', 'address','dealer_type']
|
|
|
|
# Dealer Form
|
|
class DealerForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Dealer
|
|
fields = ['name', 'arabic_name', 'crn', 'vrn', 'phone_number', 'address', 'logo']
|
|
|
|
# Customer Form
|
|
class CustomerForm(forms.ModelForm, AddClassMixin):
|
|
class Meta:
|
|
model = Customer
|
|
fields = [
|
|
'first_name', 'middle_name', 'last_name', 'email',
|
|
'national_id', 'phone_number', 'address'
|
|
]
|
|
|
|
|
|
class CarForm(forms.ModelForm, AddClassMixin, ):
|
|
class Meta:
|
|
model = Car
|
|
fields = [
|
|
'vin', 'id_car_make', 'id_car_model',
|
|
'year', 'id_car_serie', 'id_car_trim',
|
|
'stock_type', 'remarks', 'mileage', 'receiving_date', 'vendor'
|
|
]
|
|
widgets = {
|
|
'receiving_date': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
|
|
'remarks': forms.Textarea(attrs={'rows': 2}),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
dealer = kwargs.pop('dealer', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
if 'id_car_make' in self.fields:
|
|
queryset = self.fields['id_car_make'].queryset.filter(is_sa_import=True)
|
|
self.fields['id_car_make'].choices = [
|
|
(obj.id_car_make, obj.get_local_name()) for obj in queryset
|
|
]
|
|
if 'id_car_model' in self.fields:
|
|
queryset = self.fields['id_car_model'].queryset
|
|
self.fields['id_car_model'].choices = [
|
|
(obj.id_car_model, obj.get_local_name()) for obj in queryset
|
|
]
|
|
if 'vendor' in self.fields:
|
|
queryset = self.fields['vendor'].queryset
|
|
self.fields['vendor'].choices = [
|
|
(obj.pk, obj.get_local_name()) for obj in queryset
|
|
]
|
|
|
|
|
|
class CarUpdateForm(forms.ModelForm, AddClassMixin):
|
|
class Meta:
|
|
model = Car
|
|
fields = ['vendor', 'status', 'stock_type', 'mileage', 'receiving_date', 'remarks']
|
|
|
|
widgets = {
|
|
'receiving_date': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
|
|
'remarks': forms.Textarea(attrs={'rows': 2}),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
dealer = kwargs.pop('dealer', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# if dealer and 'branch' in self.fields:
|
|
# self.fields['branch'].queryset = Branch.objects.filter(dealer=dealer)
|
|
# self.fields['branch'].choices = [
|
|
# (branch.id, branch.get_local_name()) for branch in self.fields['branch'].queryset
|
|
# ]
|
|
|
|
if 'vendor' in self.fields:
|
|
queryset = self.fields['vendor'].queryset
|
|
if queryset:
|
|
self.fields['vendor'].choices = [
|
|
(vendor.id, vendor.get_local_name()) for vendor in queryset
|
|
]
|
|
|
|
|
|
class CarFinanceForm(AddClassMixin, forms.ModelForm):
|
|
additional_finances = forms.ModelMultipleChoiceField(
|
|
queryset=AdditionalServices.objects.all(),
|
|
widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}),
|
|
required=False
|
|
)
|
|
class Meta:
|
|
model = CarFinance
|
|
exclude = ['car', 'additional_finances','profit_margin', 'vat_amount', 'total', 'vat_rate','additional_services']
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
if self.instance.pk:
|
|
self.fields['additional_finances'].initial = self.instance.additional_services.all()
|
|
def save(self, commit=True):
|
|
instance = super().save()
|
|
instance.additional_services.set(self.cleaned_data['additional_finances'])
|
|
instance.save()
|
|
return instance
|
|
|
|
class CarLocationForm(forms.ModelForm):
|
|
class Meta:
|
|
model = CarLocation
|
|
fields = ['showroom', 'description']
|
|
widgets = {
|
|
'description': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}),
|
|
}
|
|
|
|
|
|
# Custom Card Form
|
|
class CustomCardForm(forms.ModelForm):
|
|
custom_date = forms.DateTimeField(
|
|
widget=forms.DateInput(attrs={'type': 'date'}),
|
|
label=_("Custom Date"),
|
|
)
|
|
|
|
class Meta:
|
|
model = CustomCard
|
|
fields = ['custom_number', 'custom_date']
|
|
|
|
|
|
# Car Registration Form
|
|
class CarRegistrationForm(forms.ModelForm):
|
|
class Meta:
|
|
model = CarRegistration
|
|
fields = [
|
|
'car', 'plate_number', 'text1', 'text2', 'text3', 'registration_date'
|
|
]
|
|
|
|
|
|
class VendorForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Vendor
|
|
fields = ['name', 'arabic_name', 'crn', 'vrn', 'email', 'phone_number', 'contact_person', 'address', 'logo' ]
|
|
|
|
|
|
|
|
class CarColorsForm(forms.ModelForm):
|
|
class Meta:
|
|
model = CarColors
|
|
fields = ['exterior', 'interior']
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.fields['exterior'].queryset = ExteriorColors.objects.all()
|
|
self.fields['exterior'].widget = forms.RadioSelect(attrs={'class': 'form-check-input'})
|
|
self.fields['exterior'].choices = [
|
|
(color.id, f"{color.get_local_name}") for color in ExteriorColors.objects.all().order_by('-name')
|
|
]
|
|
|
|
self.fields['interior'].queryset = InteriorColors.objects.all()
|
|
self.fields['interior'].widget = forms.RadioSelect(attrs={'class': 'form-check-input'})
|
|
self.fields['interior'].choices = [
|
|
(color.id, f"{color.get_local_name}") for color in InteriorColors.objects.all().order_by('-name')
|
|
]
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
exterior = cleaned_data.get("exterior")
|
|
interior = cleaned_data.get("interior")
|
|
|
|
if not exterior or not interior:
|
|
raise forms.ValidationError(_("Both exterior and interior colors must be selected."))
|
|
|
|
return cleaned_data
|
|
|
|
|
|
class QuotationForm(forms.ModelForm):
|
|
cars = ModelMultipleChoiceField(
|
|
queryset=Car.objects.none(), # Default empty queryset
|
|
widget=forms.CheckboxSelectMultiple,
|
|
label="Select Cars"
|
|
)
|
|
|
|
class Meta:
|
|
model = SaleQuotation
|
|
fields = ['customer', 'cars', 'remarks']
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.fields['cars'].queryset = Car.objects.filter(
|
|
finances__isnull=False
|
|
).distinct()
|
|
|
|
|
|
class OrganizationForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Organization
|
|
fields = [
|
|
'name', 'arabic_name', 'crn', 'vrn',
|
|
'phone_number', 'address', 'logo',
|
|
]
|
|
def __init__(self, *args, **kwargs):
|
|
dealer = kwargs.pop('dealer', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
class RepresentativeForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Representative
|
|
fields = [
|
|
'name', 'arabic_name', 'id_number',
|
|
'phone_number', 'address', 'organization'
|
|
]
|
|
def __init__(self, *args, **kwargs):
|
|
dealer = kwargs.pop('dealer', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
class CarSelectionTable(tables.Table):
|
|
select = tables.CheckBoxColumn(accessor="pk", orderable=False)
|
|
|
|
class Meta:
|
|
model = Car
|
|
fields = ['vin', 'year', 'id_car_make', 'id_car_model']
|
|
template_name = "django_tables2/bootstrap4.html"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WizardForm1(forms.Form):
|
|
|
|
email = forms.EmailField(
|
|
widget=forms.EmailInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': 'Email address',
|
|
'required': 'required',
|
|
}),
|
|
error_messages={
|
|
'required': _('You must add an email.'),
|
|
}
|
|
)
|
|
password = forms.CharField(
|
|
widget=forms.PasswordInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': _('Password'),
|
|
'required': 'required',
|
|
}),
|
|
error_messages={
|
|
'required': _('This field is required.'),
|
|
}
|
|
)
|
|
confirm_password = forms.CharField(
|
|
widget=forms.PasswordInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': _('Confirm Password'),
|
|
'required': 'required',
|
|
}),
|
|
error_messages={
|
|
'required': _('This field is required.'),
|
|
}
|
|
)
|
|
terms = forms.BooleanField(
|
|
|
|
widget=forms.CheckboxInput(attrs={
|
|
'class': 'form-check-input',
|
|
'required': 'required',
|
|
|
|
}),
|
|
error_messages={
|
|
'required': _('You must accept the terms and privacy policy.'),
|
|
}
|
|
)
|
|
|
|
|
|
class WizardForm2(forms.Form):
|
|
name = forms.CharField(
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': _('English Name'),
|
|
'required': 'required',
|
|
}),
|
|
error_messages={
|
|
'required': _('Please enter an English Name.'),
|
|
}
|
|
)
|
|
arabic_name = forms.CharField(
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': _('Arabic Name'),
|
|
'required': 'required',
|
|
}),
|
|
error_messages={
|
|
'required': _('Please enter an Arabic name.'),
|
|
}
|
|
)
|
|
phone_number = PhoneNumberField(
|
|
min_length=10,
|
|
max_length=10,
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': _('Phone'),
|
|
'required': 'required',
|
|
}),
|
|
region='SA',
|
|
error_messages={
|
|
'required': _('This field is required.'),
|
|
'invalid': _('Phone number must be in the format 05xxxxxxxx'),
|
|
}
|
|
)
|
|
|
|
class WizardForm3(forms.Form):
|
|
# CRN field with max length of 10
|
|
crn = forms.CharField(
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': _("Commercial Registration Number"),
|
|
'required': 'required',
|
|
'maxlength': '10',
|
|
}),
|
|
max_length=10,
|
|
error_messages={
|
|
'required': 'This field is required.',
|
|
'max_length': 'Commercial Registration Number must be 10 characters.',
|
|
}
|
|
)
|
|
|
|
# VRN field with max length of 15
|
|
vrn = forms.CharField(
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'form-control',
|
|
'placeholder': _("VAT Registration Number"),
|
|
'required': 'required',
|
|
'maxlength': '15',
|
|
}),
|
|
max_length=15, #
|
|
error_messages={
|
|
'required': _('This field is required.'),
|
|
'max_length': _('VAT Registration Number must be 15 characters.'),
|
|
}
|
|
)
|
|
|
|
address = forms.CharField(
|
|
widget=forms.Textarea(attrs={
|
|
'class': 'form-control',
|
|
'rows': '3',
|
|
'required': 'required',
|
|
}),
|
|
error_messages={
|
|
'required': _('This field is required.'),
|
|
}
|
|
)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
password = cleaned_data.get("password")
|
|
confirm_password = cleaned_data.get("confirm_password")
|
|
|
|
if password and confirm_password and password != confirm_password:
|
|
raise forms.ValidationError("Passwords do not match.")
|
|
|
|
|
|
class ItemForm(forms.Form):
|
|
item = forms.ModelChoiceField(queryset=ItemModel.objects.all(),label="Item", required=True)
|
|
quantity = forms.DecimalField(label="Quantity", required=True)
|
|
unit = forms.DecimalField(label="Unit", required=True)
|
|
unit_cost = forms.DecimalField(label="Unit Cost", required=True)
|
|
unit_sales_price = forms.DecimalField(label="Unit Sales Price", required=True) |