I am working on a simple appointment scheduling system where customers can bring their vehicle in for service. Customers can have multiple vehicles and have a login with all of their vehicle information saved. Most of the customers track their vehicle by a 'unit' number.
When they fill out the form, they select the branch (service center) where they want the work performed, the date, the timeslot, and they select their vehicle based on the unit number. On the backend, the unit and VIN are tied together. However, currently when they submit a service request, only their unit number comes through. I need the associated VIN to come through automatically.
I have tried to return separate values from the vehicle model (I can't figure that out), I've tried to return them with f' but that returns it as one string with the unit and VIN together. I've spent probably 3-4 hours trying to get this figured out. Any help is appreciated!!
Models.py
class Vehicle(models.Model):
unit = models.CharField(max_length=10, help_text="Unit number for the vehicle")
vin = models.CharField(max_length=17, unique=True, validators=[MinLengthValidator(17)], help_text="VIN of the vehicle")
engine = models.ForeignKey(Engine, on_delete=models.SET_NULL, null=True)
engineMfg = models.ForeignKey(engineMfg, on_delete=models.SET_NULL, null=True)
sold_to = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
mileage = models.IntegerField(default=0, help_text="Mileage of the vehicle")
class Meta:
ordering= ['unit', 'vin']
permissions = (
('view_all_vehicles', "View All Vehicles"), # this is only a permission to do something, it does NOT change a book state
)
def __str__(self):
#return f'{self.unit} - {self.vin}'
#return self.vin
return self.unit
class Appointment(models.Model):
class Meta:
unique_together = ('branch', 'date', 'timeslot')
Timeslot_List = (
(0, '07:00 - 09:00'),
(1, '09:00 - 11:00'),
(2, '13:00 - 15:00'),
(3, '15:00 - 17:00'),
(4, '17:00 - 19:00'),
)
Booking_Status = (
('a', "Available"),
('b', "Booked"),
('r', "Requested")
)
status = models.CharField(
max_length=1,
choices=Booking_Status,
blank=True,
default='a',
help_text="Booking Availability",
)
branch = models.ForeignKey('Branch', on_delete=models.SET_NULL, null=True)
unit = models.ForeignKey(Vehicle, related_name='UNIT', on_delete=models.SET_NULL, null=True)
vin = models.ForeignKey(Vehicle, related_name='VIN', on_delete=models.SET_NULL, null=True)
date = models.DateField(help_text="MM-DD-YY")
timeslot = models.IntegerField(choices=Timeslot_List)
sold_to = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
def __str__(self):
return str(self.sold_to)
@property
def time(self):
return self.Timeslot_List[self.timeslot][1]
Views.py
def new_appointment(request):
if request.method == 'POST':
form = AppointmentForm(user=request.user, data=request.POST)
if form.is_valid():
appt = form.save(commit=False)
appt.sold_to = request.user
appt.status = 'r'
appt.save()
return redirect('/')
else:
form = AppointmentForm(user=request.user)
return render(request, 'catalog/appointment_form.html', {'form':form})
Forms.py
class AppointmentForm(forms.ModelForm):
class Meta:
model = Appointment
timeslot = Appointment.objects.filter(status__exact='b')
#unit = Vehicle.unit
exclude = ('status', 'sold_to', 'vin')
widgets = {
'date': DateTimeWidget(
attrs={'id': 'date'}, usel10n=True, bootstrap_version=5,
options={
'minView': 2, # month view
'maxView': 3, # year view
'weekStart': 1,
'todayHighlight': True,
'format': 'mm-dd-yy',
'daysOfWeekDisabled': [0,6],
'startDate': date.today().strftime('%Y-%m-%d'),
}
),
}
def clean_date(self):
day = self.cleaned_data['date']
if day <= date.today():
raise forms.ValidationError("Date should be in the future", code='invalid')
if day.isoweekday() in (0,6):
raise forms.ValidationError("Must be scheduled on a weekday", code='invalid')
return day
def __init__(self, **kwargs):
sold_to = kwargs.pop('user')
super(AppointmentForm, self).__init__(**kwargs)
self.fields['unit'].queryset = Vehicle.objects.filter(sold_to=sold_to)
Edit: I've also tried the below but python yells at me that this isn't allowed, for some reason...
unit = models.ForeignKey(Vehicle.unit, on_delete=models.SET_NULL, null=True)
vin = models.ForeignKey(Vehicle.vin, on_delete=models.SET_NULL, null=True)
Edit2: If change the following in views, I get really close, but I get the error below.
def new_appointment(request):
if request.method == 'POST':
form = AppointmentForm(user=request.user, data=request.POST)
if form.is_valid():
appt = form.save(commit=False)
appt.sold_to = request.user
appt.vin = appt.unit.vin # <--- addition of this line
appt.status = 'r'
appt.save()
return redirect('/')
Error that I get from addition of line above:
Cannot assign "'1XPTD4EXOCD128815'": "Appointment.vin" must be a "Vehicle" instance.
GOT ITTTTTTTT!!!!!
I had to set a generic CharField in the Appointment class:
class Appointment(models.Model):
...
vin = models.CharField(max_length=17)
...
This, coupled with the change in the views as discussed in edit2 above:
def new_appointment(request):
...
appt.vin = appt.unit.vin # <---- This line here
...
Made everything work as I wanted!
Only took 8 hours today...