haikal/inventory/forms.py
Marwan Alwali 43df77dc7b update
2025-02-06 11:42:53 +03:00

741 lines
22 KiB
Python

from django_countries.widgets import CountrySelectWidget
from phonenumber_field.formfields import PhoneNumberField
from django.core.validators import MinLengthValidator
from django.core.validators import RegexValidator
from django import forms
from django.contrib.auth import get_user_model
from phonenumber_field.phonenumber import PhoneNumber
from .mixins import AddClassMixin
from django.forms.models import inlineformset_factory
from django_ledger.forms.invoice import InvoiceModelCreateForm as InvoiceModelCreateFormBase
from django_ledger.forms.estimate import EstimateModelCreateForm as EstimateModelCreateFormBase
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
from django_ledger.forms.vendor import VendorModelForm
from .models import (
Dealer,
# Branch,
Vendor,
Schedule,
Customer,
Car,
CarTransfer,
CarFinance,
CustomCard,
CarRegistration,
CarColors,
ExteriorColors,
InteriorColors,
# SaleQuotation,
CarLocation,
Organization,
Representative,
Payment,
# SaleQuotationCar,
AdditionalServices,
Staff,
Opportunity, Priority, Sources, Lead, Activity, Notes, CarModel,
SaleOrder
)
from django_ledger.models import ItemModel, InvoiceModel, BillModel,VendorModel
from django.forms import ModelMultipleChoiceField, ValidationError, DateInput,DateTimeInput
from django.utils.translation import gettext_lazy as _
import django_tables2 as tables
from django.forms import formset_factory
User = get_user_model()
class AdditionalServiceForm(forms.ModelForm):
class Meta:
model = AdditionalServices
fields = ["name", "price", "description", "taxable", "uom"]
# class PaymentForm(forms.ModelForm):
# invoice = forms.ModelChoiceField(queryset=InvoiceModel.objects.all(),label="Invoice", required=True)
# class Meta:
# model = Payment
# fields = ['amount','payment_method', 'reference_number']
class StaffForm(forms.ModelForm):
email = forms.EmailField(
required=True,
label="Email",
widget=forms.EmailInput(attrs={"class": "form-control"}),
)
class Meta:
model = Staff
fields = ["name", "arabic_name", "phone_number", "staff_type"]
# def __init__(self, *args, **kwargs):
# user_instance = kwargs.get("instance")
# if user_instance and user_instance.user:
# initial = kwargs.setdefault("initial", {})
# initial["email"] = user_instance.user.email
# super().__init__(*args, **kwargs)
#
# def save(self, commit=True):
# user_instance = super().save(commit=False)
# user = user_instance.user
# user.email = self.cleaned_data["email"]
# if commit:
# user.save()
# user_instance.save()
# return user_instance
# Dealer Form
class DealerForm(forms.ModelForm):
class Meta:
model = Dealer
fields = [
"name",
"arabic_name",
"crn",
"vrn",
"phone_number",
"address",
"logo",
]
class CustomerForm(forms.Form):
first_name = forms.CharField()
middle_name = forms.CharField()
last_name = forms.CharField()
national_id = forms.CharField(max_length=10)
email = forms.EmailField()
phone_number = PhoneNumberField(
min_length=10,
max_length=10,
region="SA",
)
address = forms.CharField()
class OrganizationForm(forms.Form):
name = forms.CharField()
arabic_name = forms.CharField()
email = forms.EmailField()
phone_number = PhoneNumberField(
min_length=10,
max_length=10,
region="SA",
)
crn = forms.CharField()
vrn = forms.CharField()
address = forms.CharField()
contact_person = forms.CharField(required=False)
logo = forms.ImageField(required=False)
# class CustomerForm(forms.ModelForm, AddClassMixin):
# class Meta:
# model = Customer
# fields = [
# "title",
# "first_name",
# "middle_name",
# "last_name",
# "gender",
# "dob",
# "email",
# "national_id",
# "phone_number",
# "address",
# ]
# widgets = {
# "phone_number": forms.TextInput(attrs={"class": "phone"}),
# "dob": forms.DateInput(attrs={"type": "date"}),
# }
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:
self.fields["vendor"].queryset = VendorModel.objects.filter(active=True)
# 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(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",
"profit_margin",
"vat_amount",
"total",
"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"}),
}
class CarTransferForm(forms.ModelForm):
class Meta:
model = CarTransfer
fields = ["car", "to_dealer", "remarks"]
widgets = {
"remarks": 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 = ["plate_number", "text1", "text2", "text3", "registration_date"]
widgets = {
'registration_date': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
}
# class VendorForm(VendorModelForm):
# pass
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(
label=_("Email Address"),
widget=forms.EmailInput(
attrs={
"class": "form-control form-control-sm email",
"placeholder": _("Email address"),
"name": _("email"),
"required": "required",
}
),
error_messages={
"required": _("You must add an email."),
},
)
password = forms.CharField(
label=_("Password"),
widget=forms.PasswordInput(
attrs={
"class": "form-control form-control-sm",
"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 form-control-sm",
"placeholder": _("Confirm Password"),
"required": "required",
}
),
error_messages={
"required": _("This field is required."),
},
)
terms = forms.BooleanField(
label=_("I accept the Terms and Privacy Policy"),
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(
label=_("Name"),
widget=forms.TextInput(
attrs={
"class": "form-control form-control-sm",
"placeholder": _("English Name"),
"required": "required",
}
),
error_messages={
"required": _("Please enter an English Name."),
},
)
arabic_name = forms.CharField(
label=_("Arabic Name"),
widget=forms.TextInput(
attrs={
"class": "form-control form-control-sm",
"placeholder": _("Arabic Name"),
"required": "required",
}
),
error_messages={
"required": _("Please enter an Arabic name."),
},
)
phone_number = PhoneNumberField(
label=_("Phone Number"),
min_length=10,
max_length=10,
widget=forms.TextInput(
attrs={
"class": "form-control form-control-sm",
"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(
label=_("CRN"),
widget=forms.TextInput(
attrs={
"class": "form-control form-control-sm",
"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(
label=_("VRN"),
widget=forms.TextInput(
attrs={
"class": "form-control form-control-sm",
"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(
label=_("Address"),
widget=forms.Textarea(
attrs={
"class": "form-control form-control-sm",
"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 != confirm_password:
raise forms.ValidationError("Passwords do not match.")
else:
return cleaned_data
class ItemForm(forms.Form):
item = forms.ModelChoiceField(
queryset=ItemModel.objects.all(), label="Item", required=True,
validators=[MinLengthValidator(5)],
)
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)
class PaymentForm(forms.Form):
invoice = forms.ModelChoiceField(
queryset=InvoiceModel.objects.all(), label="Invoice", required=False
)
bill = forms.ModelChoiceField(
queryset=BillModel.objects.all(), label="Bill", required=False
)
amount = forms.DecimalField(label="Amount", required=True)
payment_method = forms.ChoiceField(
choices=[
("cash", _("cash")),
("credit", _("credit")),
("transfer", _("transfer")),
("debit", _("debit")),
("SADAD", _("SADAD")),
],
label="Payment Method",
required=True,
)
payment_date = forms.DateField(label="Payment Date", widget=DateInput(attrs={'type': 'date'}), required=True)
def clean_amount(self):
invoice = self.cleaned_data['invoice']
bill = self.cleaned_data['bill']
model = invoice if invoice else bill
amount = self.cleaned_data['amount']
if amount + model.amount_paid > model.amount_due:
raise forms.ValidationError("Payment amount is greater than amount due")
if amount <= 0:
raise forms.ValidationError("Payment amount must be greater than 0")
if model.is_paid():
raise forms.ValidationError("Invoice is already paid")
if amount > model.amount_due:
raise forms.ValidationError("Payment amount is greater than amount due")
return amount
class EmailForm(forms.Form):
subject = forms.CharField(max_length=255)
message = forms.CharField(widget=forms.Textarea)
from_email = forms.EmailField()
to_email = forms.EmailField(label="To")
class LeadForm(forms.ModelForm):
class Meta:
model = Lead
fields = [
'first_name',
'last_name',
'email',
'phone_number',
'address',
'car',
'source',
'channel',
'staff',
'priority',
]
def __init__(self, *args, **kwargs):
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
]
class ScheduleForm(forms.ModelForm):
scheduled_at = forms.DateTimeField(widget=DateTimeInput(attrs={'type': 'datetime-local'}))
class Meta:
model = Schedule
fields = ['purpose','scheduled_type', 'scheduled_at', 'notes']
class NoteForm(forms.ModelForm):
class Meta:
model = Notes
fields = ['note']
class ActivityForm(forms.ModelForm):
class Meta:
model = Activity
fields = ['activity_type', 'notes']
class OpportunityForm(forms.ModelForm):
class Meta:
model = Opportunity
fields = ['customer', 'car', 'stage', 'probability', 'staff', 'closing_date']
class InvoiceModelCreateForm(InvoiceModelCreateFormBase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['cash_account'].widget = forms.HiddenInput()
self.fields['prepaid_account'].widget = forms.HiddenInput()
self.fields['unearned_account'].widget = forms.HiddenInput()
self.fields['date_draft'] = forms.DateField(widget=DateInput(attrs={'type': 'date'}))
def get_customer_queryset(self):
if 'customer' in self.fields:
self.fields['customer'].queryset = self.USER_MODEL.dealer.entity.get_customers()
class BillModelCreateForm(BillModelCreateFormBase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['cash_account'].widget = forms.HiddenInput()
self.fields['prepaid_account'].widget = forms.HiddenInput()
self.fields['unearned_account'].widget = forms.HiddenInput()
self.fields['date_draft'] = forms.DateField(widget=DateInput(attrs={'type': 'date'}))
class SaleOrderForm(forms.ModelForm):
class Meta:
model = SaleOrder
fields = ['estimate','payment_method', 'comments']
widgets = {
'comments': forms.Textarea(attrs={'rows': 3}),
}
class EstimateModelCreateForm(EstimateModelCreateFormBase):
def __init__(self, *args, entity_slug, user_model, **kwargs):
super(EstimateModelCreateForm, self).__init__(*args, entity_slug=entity_slug, user_model=user_model, **kwargs)
self.ENTITY_SLUG = entity_slug
self.USER_MODEL = user_model
self.fields['customer'].queryset = self.get_customer_queryset()
def get_customer_queryset(self):
return self.USER_MODEL.dealer.entity.get_customers()