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 exclude = ['dealer'] 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): name = forms.CharField( label="Name", widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Name', 'required': 'required', }), error_messages={ 'required': 'Please choose a username.', } ) arabic_name = forms.CharField( label="Arabic Name", widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Arabic Name', 'required': 'required', }), error_messages={ 'required': 'Please choose an Arabic name.', } ) email = forms.EmailField( label="Email*", widget=forms.EmailInput(attrs={ 'class': 'form-control', 'placeholder': 'Email address', 'pattern': '^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$', 'required': 'required', }), error_messages={ 'required': 'You must add an email.', } ) terms = forms.BooleanField( label="I accept the terms and privacy policy", widget=forms.CheckboxInput(attrs={ 'class': 'form-check-input', 'required': 'required', 'checked': 'checked', }), error_messages={ 'required': 'You must accept the terms and privacy policy.', } ) class WizardForm2(forms.Form): # Phone field with SA region validation phone_number = PhoneNumberField( label="Phone", max_length=10, widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'Phone', 'required': 'required', }), region='SA', # Enforces SA region validation error_messages={ 'required': 'This field is required.', 'invalid': 'Phone number must be in the format +966XXXXXXXXX (Saudi Arabia).', } ) # CRN field with max length of 10 crn = forms.CharField( label="CRN", widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'CRN', 'required': 'required', 'maxlength': '10', # HTML maxlength attribute }), max_length=10, # Django max_length validation error_messages={ 'required': 'This field is required.', 'max_length': 'CRN must be at most 10 characters long.', } ) # VRN field with max length of 15 vrn = forms.CharField( label="VRN", widget=forms.TextInput(attrs={ 'class': 'form-control', 'placeholder': 'VRN', 'required': 'required', 'maxlength': '15', # HTML maxlength attribute }), max_length=15, # Django max_length validation error_messages={ 'required': 'This field is required.', 'max_length': 'VRN must be at most 15 characters long.', } ) address = forms.CharField( label="Address", widget=forms.Textarea(attrs={ 'class': 'form-control', 'rows': '4', 'required': 'required', }), error_messages={ 'required': 'This field is required.', } ) class WizardForm3(forms.Form): password = forms.CharField( label="Password*", widget=forms.PasswordInput(attrs={ 'class': 'form-control', 'placeholder': 'Password', 'required': 'required', }), error_messages={ 'required': 'This field is required.', } ) confirm_password = forms.CharField( label="Confirm Password*", widget=forms.PasswordInput(attrs={ 'class': 'form-control', 'placeholder': 'Confirm Password', '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)