update
This commit is contained in:
parent
5a76fb4fa2
commit
c3a31d71e1
@ -96,12 +96,12 @@ class StaffForm(forms.ModelForm):
|
||||
"""
|
||||
email = forms.EmailField(
|
||||
required=True,
|
||||
label="Email",
|
||||
label=_("Email"),
|
||||
widget=forms.EmailInput(attrs={"class": "form-control form-control-sm"}),
|
||||
)
|
||||
|
||||
service_offered = forms.ModelMultipleChoiceField(
|
||||
label="Services Offered",
|
||||
label=_("Services Offered"),
|
||||
widget=forms.CheckboxSelectMultiple(attrs={"class": "form-check-input"}),
|
||||
queryset=Service.objects.all(),
|
||||
required=False,)
|
||||
@ -837,7 +837,7 @@ class WizardForm3(forms.Form):
|
||||
max_length=10,
|
||||
error_messages={
|
||||
"required": _("This field is required."),
|
||||
"max_length": "Commercial Registration Number must be 10 characters.",
|
||||
"max_length": _("Commercial Registration Number must be 10 characters"),
|
||||
},
|
||||
)
|
||||
|
||||
@ -890,11 +890,11 @@ class ItemForm(forms.Form):
|
||||
"""
|
||||
item = forms.ModelChoiceField(
|
||||
queryset=ledger_models.ItemModel.objects.all(),
|
||||
label="Item",
|
||||
label=_("Item"),
|
||||
required=True,
|
||||
validators=[MinLengthValidator(5)],
|
||||
)
|
||||
quantity = forms.DecimalField(label="Quantity", required=True)
|
||||
quantity = forms.DecimalField(label=_("Quantity"), required=True)
|
||||
|
||||
|
||||
class PaymentForm(forms.Form):
|
||||
@ -919,13 +919,13 @@ class PaymentForm(forms.Form):
|
||||
"""
|
||||
invoice = forms.ModelChoiceField(
|
||||
queryset=ledger_models.InvoiceModel.objects.all(),
|
||||
label="Invoice",
|
||||
label=_("Invoice"),
|
||||
required=False,
|
||||
)
|
||||
bill = forms.ModelChoiceField(
|
||||
queryset=ledger_models.BillModel.objects.all(), label="Bill", required=False
|
||||
queryset=ledger_models.BillModel.objects.all(), label=_("Bill"), required=False
|
||||
)
|
||||
amount = forms.DecimalField(label="Amount", required=True)
|
||||
amount = forms.DecimalField(label=_("Amount"), required=True)
|
||||
payment_method = forms.ChoiceField(
|
||||
choices=[
|
||||
("cash", _("cash")),
|
||||
@ -934,11 +934,11 @@ class PaymentForm(forms.Form):
|
||||
("debit", _("debit")),
|
||||
("SADAD", _("SADAD")),
|
||||
],
|
||||
label="Payment Method",
|
||||
label=_("Payment Method"),
|
||||
required=True,
|
||||
)
|
||||
payment_date = forms.DateField(
|
||||
label="Payment Date", widget=DateInput(attrs={"type": "date"}), required=True
|
||||
label=_("Payment Date"), widget=DateInput(attrs={"type": "date"}), required=True
|
||||
)
|
||||
|
||||
def clean_amount(self):
|
||||
@ -947,13 +947,13 @@ class PaymentForm(forms.Form):
|
||||
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")
|
||||
raise forms.ValidationError(_("Payment amount is greater than amount due"))
|
||||
if amount <= 0:
|
||||
raise forms.ValidationError("Payment amount must be greater than 0")
|
||||
raise forms.ValidationError(_("Payment amount must be greater than 0"))
|
||||
if model.is_paid():
|
||||
raise forms.ValidationError("Invoice is already paid")
|
||||
raise forms.ValidationError(_("Invoice is already paid"))
|
||||
if amount > model.amount_due:
|
||||
raise forms.ValidationError("Payment amount is greater than amount due")
|
||||
raise forms.ValidationError(_("Payment amount is greater than amount due"))
|
||||
return amount
|
||||
|
||||
|
||||
@ -979,7 +979,7 @@ 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")
|
||||
to_email = forms.EmailField(label=_("To"))
|
||||
|
||||
|
||||
class LeadForm(forms.ModelForm):
|
||||
@ -999,7 +999,7 @@ class LeadForm(forms.ModelForm):
|
||||
:type id_car_model: ModelChoiceField
|
||||
"""
|
||||
id_car_make = forms.ModelChoiceField(
|
||||
label="Make",
|
||||
label=_("Make"),
|
||||
queryset=CarMake.objects.filter(is_sa_import=True),
|
||||
widget=forms.Select(
|
||||
attrs={
|
||||
@ -1016,7 +1016,7 @@ class LeadForm(forms.ModelForm):
|
||||
required=True,
|
||||
)
|
||||
id_car_model = forms.ModelChoiceField(
|
||||
label="Model",
|
||||
label=_("Model"),
|
||||
queryset=CarModel.objects.none(),
|
||||
widget=forms.Select(attrs={"class": "form-control form-control-sm"}),
|
||||
required=True,
|
||||
@ -1291,7 +1291,7 @@ class OpportunityStatusForm(forms.Form):
|
||||
:type stage: ChoiceField
|
||||
"""
|
||||
status = forms.ChoiceField(
|
||||
label="Status",
|
||||
label=_("Status"),
|
||||
choices=Status.choices,
|
||||
widget=forms.Select(
|
||||
attrs={
|
||||
@ -1307,7 +1307,7 @@ class OpportunityStatusForm(forms.Form):
|
||||
required=True,
|
||||
)
|
||||
stage = forms.ChoiceField(
|
||||
label="Stage",
|
||||
label=_("Stage"),
|
||||
choices=Stage.choices,
|
||||
widget=forms.Select(
|
||||
attrs={
|
||||
@ -1496,7 +1496,7 @@ class CreditCardField(forms.CharField):
|
||||
|
||||
# Validate using Luhn algorithm
|
||||
if not Luhn.check_luhn(cleaned_value):
|
||||
raise forms.ValidationError("Please enter a valid credit card number")
|
||||
raise forms.ValidationError(_("Please enter a valid credit card number"))
|
||||
|
||||
# Add basic card type detection (optional)
|
||||
if cleaned_value.startswith('4'):
|
||||
@ -1526,17 +1526,17 @@ class ExpiryDateField(forms.CharField):
|
||||
|
||||
# Validate month
|
||||
if month < 1 or month > 12:
|
||||
raise forms.ValidationError("Please enter a valid month (01-12)")
|
||||
raise forms.ValidationError(_("Please enter a valid month (01-12)"))
|
||||
|
||||
# Validate not expired
|
||||
current_year = datetime.now().year
|
||||
current_month = datetime.now().month
|
||||
|
||||
if year < current_year or (year == current_year and month < current_month):
|
||||
raise forms.ValidationError("This card appears to be expired")
|
||||
raise forms.ValidationError(_("This card appears to be expired"))
|
||||
|
||||
except (ValueError, AttributeError):
|
||||
raise forms.ValidationError("Please enter a valid expiry date in MM/YY format")
|
||||
raise forms.ValidationError(_("Please enter a valid expiry date in MM/YY format"))
|
||||
|
||||
return value
|
||||
|
||||
@ -1545,9 +1545,9 @@ class CVVField(forms.CharField):
|
||||
value = super().clean(value)
|
||||
if value:
|
||||
if not value.isdigit():
|
||||
raise forms.ValidationError("CVV must contain only digits")
|
||||
raise forms.ValidationError(_("CVV must contain only digits"))
|
||||
if len(value) not in (3, 4):
|
||||
raise forms.ValidationError("CVV must be 3 or 4 digits")
|
||||
raise forms.ValidationError(_("CVV must be 3 or 4 digits"))
|
||||
return value
|
||||
|
||||
class PaymentPlanForm(forms.Form):
|
||||
@ -1606,7 +1606,7 @@ class PaymentPlanForm(forms.Form):
|
||||
'id': 'card-number',
|
||||
|
||||
}),
|
||||
label="Card Number"
|
||||
label=_("Card Number")
|
||||
)
|
||||
|
||||
expiry_date = ExpiryDateField(
|
||||
@ -1617,7 +1617,7 @@ class PaymentPlanForm(forms.Form):
|
||||
'id': 'expiry',
|
||||
|
||||
}),
|
||||
label="Expiration Date"
|
||||
label=_("Expiration Date")
|
||||
)
|
||||
|
||||
cvv = CVVField(
|
||||
@ -1628,7 +1628,7 @@ class PaymentPlanForm(forms.Form):
|
||||
'id': 'cvv',
|
||||
|
||||
}),
|
||||
label="Security Code (CVV)"
|
||||
label=_("Security Code (CVV)")
|
||||
)
|
||||
|
||||
card_name = forms.CharField(
|
||||
@ -1640,7 +1640,7 @@ class PaymentPlanForm(forms.Form):
|
||||
'id': 'card-name',
|
||||
|
||||
}),
|
||||
label="Name on Card"
|
||||
label=_("Name on Card")
|
||||
)
|
||||
|
||||
# Terms and conditions
|
||||
|
||||
@ -171,7 +171,7 @@ class CarMake(models.Model, LocalizedNameMixin):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Make"
|
||||
verbose_name = _("Make")
|
||||
|
||||
|
||||
class CarModel(models.Model, LocalizedNameMixin):
|
||||
@ -184,7 +184,7 @@ class CarModel(models.Model, LocalizedNameMixin):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Model"
|
||||
verbose_name = _("Model")
|
||||
|
||||
|
||||
class CarSerie(models.Model, LocalizedNameMixin):
|
||||
@ -202,7 +202,7 @@ class CarSerie(models.Model, LocalizedNameMixin):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Series"
|
||||
verbose_name = _("Series")
|
||||
|
||||
|
||||
class CarTrim(models.Model, LocalizedNameMixin):
|
||||
@ -219,7 +219,7 @@ class CarTrim(models.Model, LocalizedNameMixin):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Trim"
|
||||
verbose_name = _("Trim")
|
||||
|
||||
|
||||
class CarEquipment(models.Model, LocalizedNameMixin):
|
||||
@ -233,7 +233,7 @@ class CarEquipment(models.Model, LocalizedNameMixin):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Equipment"
|
||||
verbose_name = _("Equipment")
|
||||
|
||||
|
||||
class CarSpecification(models.Model, LocalizedNameMixin):
|
||||
@ -248,7 +248,7 @@ class CarSpecification(models.Model, LocalizedNameMixin):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Specification"
|
||||
verbose_name = _("Specification")
|
||||
|
||||
|
||||
class CarSpecificationValue(models.Model):
|
||||
@ -264,7 +264,7 @@ class CarSpecificationValue(models.Model):
|
||||
return f"{self.id_car_specification.name}: {self.value} {self.unit}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Specification Value"
|
||||
verbose_name = _("Specification Value")
|
||||
|
||||
|
||||
class CarOption(models.Model, LocalizedNameMixin):
|
||||
@ -279,7 +279,7 @@ class CarOption(models.Model, LocalizedNameMixin):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Option"
|
||||
verbose_name = _("Option")
|
||||
|
||||
|
||||
class CarOptionValue(models.Model):
|
||||
@ -298,7 +298,7 @@ class CarOptionValue(models.Model):
|
||||
return f"{self.id_car_option.name}: {self.value} {self.unit}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Option Value"
|
||||
verbose_name = _("Option Value")
|
||||
|
||||
|
||||
class CarTransferStatusChoices(models.TextChoices):
|
||||
@ -480,7 +480,7 @@ class Car(models.Model):
|
||||
self.cancel_reservation()
|
||||
self.status = CarStatusChoices.SOLD
|
||||
self.save()
|
||||
Activity.objects.create(dealer=dealer,content_object=self, notes="Car Sold",created_by=request.user,activity_type=ActionChoices.SALE_CAR)
|
||||
Activity.objects.create(dealer=dealer,content_object=self, notes=_("Car Sold"),created_by=request.user,activity_type=ActionChoices.SALE_CAR)
|
||||
|
||||
def cancel_reservation(self):
|
||||
if self.reservations.exists():
|
||||
@ -801,89 +801,6 @@ class TimestampedModel(models.Model):
|
||||
abstract = True
|
||||
|
||||
|
||||
# class Subscription(models.Model):
|
||||
# plan = models.ForeignKey(
|
||||
# "SubscriptionPlan", on_delete=models.CASCADE, related_name="subscriptions"
|
||||
# )
|
||||
# start_date = models.DateField(help_text="Date when the subscription starts")
|
||||
# end_date = models.DateField(help_text="Date when the subscription ends")
|
||||
# users = models.ManyToManyField(
|
||||
# User, through="SubscriptionUser"
|
||||
# ) # many-to-many relationship with User model
|
||||
# is_active = models.BooleanField(default=True)
|
||||
# billing_cycle = models.CharField(
|
||||
# max_length=10,
|
||||
# choices=[("monthly", "Monthly"), ("annual", "Annual")],
|
||||
# default="monthly",
|
||||
# help_text="Billing cycle for the subscription",
|
||||
# )
|
||||
# last_payment_date = models.DateField(
|
||||
# null=True, blank=True, help_text="Date of the last payment made"
|
||||
# )
|
||||
# next_payment_date = models.DateField(
|
||||
# null=True, blank=True, help_text="Date of the next payment due"
|
||||
# )
|
||||
#
|
||||
# class Meta:
|
||||
# verbose_name = _("Subscription")
|
||||
# verbose_name_plural = _("Subscriptions")
|
||||
#
|
||||
# def __str__(self):
|
||||
# return self.plan.name
|
||||
#
|
||||
# @property
|
||||
# def total_subscribers(self):
|
||||
# return self.users.count()
|
||||
#
|
||||
#
|
||||
# class SubscriptionUser(models.Model):
|
||||
# subscription = models.ForeignKey(Subscription, on_delete=models.CASCADE)
|
||||
# user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
#
|
||||
# class Meta:
|
||||
# verbose_name = _("Subscription User")
|
||||
# verbose_name_plural = _("Subscription Users")
|
||||
#
|
||||
# def __str__(self):
|
||||
# return f"{self.subscription} - {self.user}"
|
||||
#
|
||||
#
|
||||
# class SubscriptionPlan(models.Model):
|
||||
# name = models.CharField(
|
||||
# max_length=100, unique=True, help_text=_("Name of the subscription plan")
|
||||
# )
|
||||
# description = models.TextField()
|
||||
# price = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
# max_users = models.PositiveIntegerField(
|
||||
# help_text=_("Maximum number of users allowed"), default=1
|
||||
# )
|
||||
# max_inventory_size = models.PositiveIntegerField(
|
||||
# help_text=_("Maximum number of cars in inventory"), default=50
|
||||
# )
|
||||
# support_level = models.CharField(
|
||||
# max_length=50,
|
||||
# choices=[
|
||||
# ("basic", "Basic Support"),
|
||||
# ("priority", "Priority Support"),
|
||||
# ("dedicated", "Dedicated Support"),
|
||||
# ],
|
||||
# default="basic",
|
||||
# help_text="Level of support provided",
|
||||
# )
|
||||
# custom_features = models.JSONField(
|
||||
# blank=True, null=True, help_text=_("Additional features specific to this plan")
|
||||
# )
|
||||
# created_at = models.DateTimeField(auto_now_add=True)
|
||||
# updated_at = models.DateTimeField(auto_now=True)
|
||||
#
|
||||
# class Meta:
|
||||
# verbose_name = _("Subscription Plan")
|
||||
# verbose_name_plural = _("Subscription Plans")
|
||||
#
|
||||
# def __str__(self):
|
||||
# return f"{self.name} - {self.price}"
|
||||
|
||||
|
||||
class Dealer(models.Model, LocalizedNameMixin):
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="dealer")
|
||||
crn = models.CharField(
|
||||
@ -966,31 +883,6 @@ class Dealer(models.Model, LocalizedNameMixin):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
# @property
|
||||
# def get_sub_dealers(self):
|
||||
# if self.dealer_type == "OWNER":
|
||||
# return self.sub_dealers.all()
|
||||
# return None
|
||||
#
|
||||
# @property
|
||||
# def is_parent(self):
|
||||
# return self.dealer_type == "OWNER"
|
||||
# @property
|
||||
# def get_root_dealer(self):
|
||||
# return self.parent_dealer if self.parent_dealer else self
|
||||
|
||||
|
||||
|
||||
##############################
|
||||
# Additional staff types for later
|
||||
|
||||
# COORDINATOR = "coordinator", _("Coordinator")
|
||||
# RECEPTIONIST = "receptionist", _("Receptionist")
|
||||
# AGENT = "agent", _("Agent")
|
||||
# TECHNICIAN = "technician", _("Technician")
|
||||
# DRIVER = "driver", _("Driver")
|
||||
##############################
|
||||
|
||||
|
||||
class StaffTypes(models.TextChoices):
|
||||
# MANAGER = "manager", _("Manager")
|
||||
@ -1372,22 +1264,22 @@ class Lead(models.Model):
|
||||
|
||||
class Schedule(models.Model):
|
||||
PURPOSE_CHOICES = [
|
||||
('Product Demo', 'Product Demo'),
|
||||
('Follow-Up Call', 'Follow-Up Call'),
|
||||
('Contract Discussion', 'Contract Discussion'),
|
||||
('Sales Meeting', 'Sales Meeting'),
|
||||
('Support Call', 'Support Call'),
|
||||
('Other', 'Other'),
|
||||
('product_demo', _('Product Demo')),
|
||||
('follow_up_call', _('Follow-Up Call')),
|
||||
('contract_discussion', _('Contract Discussion')),
|
||||
('sales_meeting', _('Sales Meeting')),
|
||||
('support_call', _('Support Call')),
|
||||
('other', _('Other')),
|
||||
]
|
||||
ScheduledType = [
|
||||
('Call', 'Call'),
|
||||
('Meeting', 'Meeting'),
|
||||
('Email', 'Email'),
|
||||
('call', _('Call')),
|
||||
('meeting', _('Meeting')),
|
||||
('email', _('Email')),
|
||||
]
|
||||
ScheduleStatusChoices = [
|
||||
('Scheduled', 'Scheduled'),
|
||||
('Completed', 'Completed'),
|
||||
('Canceled', 'Canceled'),
|
||||
('scheduled', _('Scheduled')),
|
||||
('completed', _('Completed')),
|
||||
('canceled', _('Canceled')),
|
||||
]
|
||||
lead = models.ForeignKey(Lead, on_delete=models.CASCADE, related_name='schedules')
|
||||
customer = models.ForeignKey(CustomerModel, on_delete=models.CASCADE, related_name='schedules',null=True,blank=True)
|
||||
@ -1593,198 +1485,15 @@ class Vendor(models.Model, LocalizedNameMixin):
|
||||
return self.name
|
||||
|
||||
|
||||
# class SaleQuotation(models.Model):
|
||||
# quotation_number = models.CharField(max_length=10, unique=True)
|
||||
#
|
||||
# STATUS_CHOICES = [
|
||||
# ("Draft", _("Draft")),
|
||||
# ("Approved", _("Approved")),
|
||||
# ("In Review", _("In Review")),
|
||||
# ("Paid", _("Paid")),
|
||||
# ]
|
||||
# dealer = models.ForeignKey(
|
||||
# Dealer, on_delete=models.CASCADE, related_name="sales", null=True
|
||||
# )
|
||||
# customer = models.ForeignKey(
|
||||
# Customer,
|
||||
# on_delete=models.CASCADE,
|
||||
# related_name="quotations",
|
||||
# verbose_name=_("Customer"),
|
||||
# )
|
||||
# amount = models.DecimalField(
|
||||
# decimal_places=2,
|
||||
# default=Decimal("0.00"),
|
||||
# max_digits=10,
|
||||
# verbose_name=_("Amount"),
|
||||
# )
|
||||
# remarks = models.TextField(blank=True, null=True, verbose_name=_("Remarks"))
|
||||
# is_approved = models.BooleanField(default=False)
|
||||
# status = models.CharField(
|
||||
# max_length=10, choices=STATUS_CHOICES, default="Draft", verbose_name=_("Status")
|
||||
# )
|
||||
# created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
|
||||
# updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))
|
||||
#
|
||||
# posted = models.BooleanField(default=False)
|
||||
# payment_id = models.CharField(
|
||||
# max_length=255, null=True, blank=True, verbose_name=_("Payment ID")
|
||||
# )
|
||||
# is_paid = models.BooleanField(default=False)
|
||||
# date_draft = models.DateTimeField(
|
||||
# null=True, blank=True, verbose_name=_("Draft Date")
|
||||
# )
|
||||
# date_in_review = models.DateTimeField(
|
||||
# null=True, blank=True, verbose_name=_("In Review Date")
|
||||
# )
|
||||
# date_approved = models.DateTimeField(
|
||||
# null=True, blank=True, verbose_name=_("Approved Date")
|
||||
# )
|
||||
# date_paid = models.DateTimeField(null=True, blank=True, verbose_name=_("Paid Date"))
|
||||
# date_void = models.DateTimeField(null=True, blank=True, verbose_name=_("Void Date"))
|
||||
# date_canceled = models.DateTimeField(
|
||||
# null=True, blank=True, verbose_name=_("Canceled Date")
|
||||
# )
|
||||
#
|
||||
# @property
|
||||
# def total_quantity(self):
|
||||
# total_quantity = self.quotation_cars.aggregate(total=Sum("quantity"))["total"]
|
||||
# return total_quantity or 0
|
||||
#
|
||||
# @property
|
||||
# def total(self):
|
||||
# total = self.quotation_cars.aggregate(
|
||||
# total_price=Sum(F("car__finances__selling_price") * F("quantity"))
|
||||
# )
|
||||
# if not total:
|
||||
# return 0
|
||||
# return total["total_price"]
|
||||
#
|
||||
# @property
|
||||
# def total_vat(self):
|
||||
# if self.total:
|
||||
# return float(self.total) * 0.15 + float(self.total)
|
||||
# return 0
|
||||
|
||||
# def confirm(self):
|
||||
# """Confirm the quotation and lock financial details."""
|
||||
# if self.status != "DRAFT":
|
||||
# raise ValueError(_("Only draft quotations can be confirmed."))
|
||||
# self.status = "CONFIRMED"
|
||||
# self.save()
|
||||
|
||||
# def cancel(self):
|
||||
# """Cancel the quotation."""
|
||||
# if self.status == "CONFIRMED":
|
||||
# raise ValueError(_("Cannot cancel a confirmed quotation."))
|
||||
# self.status = "CANCELED"
|
||||
# self.save()
|
||||
|
||||
# def __str__(self):
|
||||
# return f"Quotation #{self.quotation_number} for {self.customer}"
|
||||
#
|
||||
# @property
|
||||
# def display_quotation_number(self):
|
||||
# return f"QN-{self.quotation_number}"
|
||||
#
|
||||
# def save(self, *args, **kwargs):
|
||||
# if not self.quotation_number:
|
||||
# self.quotation_number = str(next(self._get_quotation_number())).zfill(6)
|
||||
# super().save(*args, **kwargs)
|
||||
#
|
||||
# @classmethod
|
||||
# def _get_quotation_number(cls):
|
||||
# last_quotation = cls.objects.all().order_by("id").last()
|
||||
# if last_quotation:
|
||||
# last_quotation_number = int(last_quotation.quotation_number)
|
||||
# else:
|
||||
# last_quotation_number = 0
|
||||
# return itertools.count(last_quotation_number + 1)
|
||||
|
||||
#
|
||||
# class SaleQuotationCar(models.Model):
|
||||
# quotation = models.ForeignKey(
|
||||
# SaleQuotation,
|
||||
# on_delete=models.CASCADE,
|
||||
# related_name="quotation_cars",
|
||||
# verbose_name=_("Quotation"),
|
||||
# )
|
||||
# car = models.ForeignKey(Car, on_delete=models.CASCADE, verbose_name=_("Car"))
|
||||
# quantity = models.PositiveIntegerField(default=1, verbose_name=_("Quantity"))
|
||||
#
|
||||
# @property
|
||||
# def finance(self):
|
||||
# return self.car.finances
|
||||
#
|
||||
# @property
|
||||
# def financial_details(self):
|
||||
# """
|
||||
# Retrieve financial details dynamically from CarFinance.
|
||||
# Returns a dictionary with all financial fields for better access.
|
||||
# """
|
||||
# car_finance = self.car.finances
|
||||
# if not car_finance:
|
||||
# return None
|
||||
#
|
||||
# return {
|
||||
# "selling_price": car_finance.selling_price,
|
||||
# "administration_fee": car_finance.administration_fee,
|
||||
# "transportation_fee": car_finance.transportation_fee,
|
||||
# "custom_card_fee": car_finance.custom_card_fee,
|
||||
# "registration_fee": car_finance.registration_fee,
|
||||
# "vat_amount": car_finance.vat_amount,
|
||||
# # "total_amount": car_finance.total,
|
||||
# }
|
||||
#
|
||||
# @property
|
||||
# def total(self):
|
||||
# """
|
||||
# Calculate total price dynamically based on quantity and selling price.
|
||||
# """
|
||||
# if not self.car.finances:
|
||||
# return Decimal("0.00")
|
||||
# return self.car.finances.selling_price * self.quantity
|
||||
#
|
||||
# @property
|
||||
# def total_vat(self):
|
||||
# """
|
||||
# Calculate total price dynamically based on quantity and selling price.
|
||||
# """
|
||||
# if not self.car.finances:
|
||||
# return Decimal("0.00")
|
||||
# price = float(self.car.finances.selling_price * self.quantity)
|
||||
# return (price * 0.15) + price
|
||||
#
|
||||
# def __str__(self):
|
||||
# return f"{self.car} - Quotation #{self.quotation.id}"
|
||||
#
|
||||
#
|
||||
# class SalesOrder(models.Model):
|
||||
# quotation = models.OneToOneField(
|
||||
# SaleQuotation,
|
||||
# on_delete=models.CASCADE,
|
||||
# related_name="sales_order",
|
||||
# verbose_name=_("Quotation"),
|
||||
# )
|
||||
# created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
|
||||
# total_amount = models.DecimalField(
|
||||
# max_digits=14, decimal_places=2, verbose_name=_("Total Amount")
|
||||
# )
|
||||
#
|
||||
# def __str__(self):
|
||||
# return f"Sales Order #{self.id} from Quotation #{self.quotation.id}"
|
||||
|
||||
|
||||
class Payment(models.Model):
|
||||
METHOD_CHOICES = [
|
||||
("cash", _("cash")),
|
||||
("credit", _("credit")),
|
||||
("transfer", _("transfer")),
|
||||
("debit", _("debit")),
|
||||
("SADAD", _("SADAD")),
|
||||
("sadad", _("SADAD")),
|
||||
]
|
||||
# quotation = models.ForeignKey(
|
||||
# SaleQuotation, on_delete=models.CASCADE, related_name="payments"
|
||||
# )
|
||||
|
||||
amount = models.DecimalField(
|
||||
max_digits=10, decimal_places=2, verbose_name=_("amount")
|
||||
)
|
||||
@ -1796,19 +1505,13 @@ class Payment(models.Model):
|
||||
)
|
||||
payment_date = models.DateField(auto_now_add=True, verbose_name=_("date"))
|
||||
|
||||
# def save(self, *args, **kwargs):
|
||||
# super().save(*args, **kwargs)
|
||||
# self.quotation.remaining_balance -= self.amount
|
||||
# if self.quotation.remaining_balance <= 0:
|
||||
# self.quotation.is_paid = True
|
||||
# self.quotation.save()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("payment")
|
||||
verbose_name_plural = _("payments")
|
||||
|
||||
def __str__(self):
|
||||
return f"Payment of {self.amount} on {self.payment_date} for {self.quotation}"
|
||||
return f"Payment of {self.amount} on {self.payment_date}"
|
||||
|
||||
|
||||
class Refund(models.Model):
|
||||
@ -1835,8 +1538,8 @@ class UserActivityLog(models.Model):
|
||||
timestamp = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "User Activity Log"
|
||||
verbose_name_plural = "User Activity Logs"
|
||||
verbose_name = _("User Activity Log")
|
||||
verbose_name_plural = _("User Activity Logs")
|
||||
ordering = ["-timestamp"]
|
||||
|
||||
def __str__(self):
|
||||
@ -1863,7 +1566,7 @@ class SaleOrder(models.Model):
|
||||
('lease', _('Lease')),
|
||||
("credit_card", _("Credit Card")),
|
||||
("bank_transfer", _("Bank Transfer")),
|
||||
("SADAD", _("SADAD")),
|
||||
("sadad", _("SADAD")),
|
||||
])
|
||||
comments = models.TextField(blank=True, null=True)
|
||||
formatted_order_id = models.CharField(max_length=10, unique=True, editable=False)
|
||||
@ -2073,7 +1776,8 @@ class PaymentHistory(models.Model):
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = "Payment Histories"
|
||||
verbose_name = _("Payment History")
|
||||
verbose_name_plural = _("Payment Histories")
|
||||
ordering = ["-payment_date"]
|
||||
indexes = [
|
||||
models.Index(fields=["transaction_id"]),
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user