there’s something wrong within my code, because the end_date validation don’t work, but the other’s are working,
I just want to have a validation error if a user pick a date that not within the project’s duration
here is my models.py:
class Project(models.Model): # WORKING
class Status(models.TextChoices):
On_Hold = "On Hold", "On Hold"
Ongoing = "Ongoing", "Ongoing"
Cancelled = "Cancelled", "Cancelled"
Completed = "Completed", "Completed"
name = models.CharField(_("Project's Name"), max_length=250)
address = models.CharField(_("Project Location"), max_length=250)
budget = models.DecimalField(_("Budget"), max_digits=10, decimal_places=2, default=0)
status = models.CharField(max_length=50, choices=Status.choices, default=Status.On_Hold)
owner = models.ForeignKey(Client, on_delete=models.SET_NULL, related_name="projects", null=True, blank=True)
# Projects Duration
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
duration = models.CharField(max_length=3, blank=True)
class Boq(models.Model):
project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True)
description = models.CharField(max_length=250, null=True, blank=True)
quantity = models.DecimalField(max_digits=10, decimal_places=2, default=1)
unit = models.CharField(max_length=10, choices=Units.choices, default=Units.LOT)
rate_material = models.DecimalField(_("Unit Cost for Material"), max_digits=10, decimal_places=2, default=0)
material_cost = models.DecimalField(_("Material Cost"), max_digits=10, decimal_places=2, default=0)
rate_labor = models.DecimalField(_("Unit Cost for Labor"), max_digits=10, decimal_places=2, default=0)
labor_cost = models.DecimalField(_("Labor Cost"), max_digits=10, decimal_places=2, default=0)
line_total = models.DecimalField(_("Line Total"), max_digits=10, decimal_places=2, default=0)
# Task Duration (item, description = task)
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
duration = models.CharField(max_length=3, blank=True)
forms.py
class BoqForm(forms.ModelForm):
start_date = forms.DateField(required=False, widget=forms.DateInput(attrs={'type': 'date'}))
end_date = forms.DateField(required=False, widget=forms.DateInput(attrs={'type': 'date'}))
class Meta:
model = Boq
fields = ['item', 'description', 'quantity', 'unit', 'rate_material', 'rate_labor', 'start_date', 'end_date']
def clean(self):
cleaned_data = super().clean()
start_date = cleaned_data.get('start_date')
end_date = cleaned_data.get('end_date')
today = date.today()
project = self.instance.project
# Check if start_date and end_date are within the project's duration
if project is not None and start_date and project.start_date and start_date < project.start_date:
print("Start date cannot be earlier than the project's start date.")
raise forms.ValidationError("Start date cannot be earlier than the project's start date.")
elif project is not None and end_date and project.end_date and end_date > project.end_date:
print("End date cannot exceed the project's end date.")
raise forms.ValidationError("End date cannot exceed the project's end date.")
if start_date and end_date and start_date >= end_date:
print("Selected dates are incorrect, please select again.")
raise forms.ValidationError("Selected dates are incorrect, please select again.")
if start_date and start_date < today:
print("Start date cannot be in the past.")
raise forms.ValidationError("Start date cannot be in the past.")
if end_date and end_date < today:
print("End date cannot be in the past.")
raise forms.ValidationError("End date cannot be in the past.")
return cleaned_data
views.py:
def add_project_boq(request, pk):
project = get_object_or_404(Project, pk=pk)
if request.method == 'POST':
form = BoqForm(request.POST)
if form.is_valid():
boq = form.save(commit=False)
boq.project = project
boq.save()
project.boq_set.add(boq)
form = BoqForm()
else:
form = BoqForm()
boqs = project.boq_set.all()
context = {'boqs': boqs, 'form': form}
return render(request, 'pms/boq/boq-list-copy.html', context)