Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for multiple vehicles #425

Merged
merged 19 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/bocken/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from bocken.models import (
Admin, Agreement, JournalEntry, Report, JournalEntryGroup
Admin, Agreement, JournalEntry, Report, JournalEntryGroup, Vehicle
)
from .agreement_admin import AgreementAdmin
from .journal_entry_admin import JournalEntryAdmin
from .journal_entry_group_admin import JournalEntryGroupAdmin
from .report_admin import ReportAdmin
from .vehicle_admin import VehicleAdmin
from .user_admin import UserAdmin
from django.utils.translation import gettext_lazy as _
from django.contrib import admin
Expand All @@ -13,6 +14,7 @@

admin.site.register(Admin, UserAdmin)
admin.site.register(Agreement, AgreementAdmin)
admin.site.register(Vehicle, VehicleAdmin)
admin.site.register(JournalEntry, JournalEntryAdmin)
admin.site.register(Report, ReportAdmin)
admin.site.register(JournalEntryGroup, JournalEntryGroupAdmin)
Expand Down
1 change: 1 addition & 0 deletions src/bocken/admin/agreement_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class AgreementAdmin(ImportExportModelAdmin):
form = AgreementForm
list_display = (
'name', 'personnummer', 'phonenumber',
'bike_agreement', 'car_agreement',
'email', 'expires_colored'
)
search_fields = ['name', 'personnummer']
4 changes: 2 additions & 2 deletions src/bocken/admin/journal_entry_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ class JournalEntryAdmin(ModelAdmin):
"""Custom class for the admin pages for journal entry."""

list_display = (
'agreement', 'created', 'group',
'agreement', 'created', 'group', 'vehicle',
'meter_start_gap_marker', 'meter_stop_gap_marker', 'get_total_distance'
)
ordering = ('-meter_stop', )
ordering = ('vehicle', '-meter_stop', )
search_fields = [
'agreement__name', 'agreement__personnummer', 'group__name'
]
Expand Down
15 changes: 15 additions & 0 deletions src/bocken/admin/vehicle_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

from django.contrib.admin import ModelAdmin


class VehicleAdmin(ModelAdmin):
"""Custom class for the admin pages for Vehicle."""

list_display = (
"vehicle_name",
"car",
"bike",
"vehicle_meter_start",
"vehicle_meter_stop"
)
list_filter = ['vehicle_name']
3 changes: 2 additions & 1 deletion src/bocken/forms/agreement_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ class Meta:
model = Agreement
fields = [
'name', 'personnummer', 'phonenumber',
'email', 'agreement_file', 'expires'
'email', 'bike_agreement', 'car_agreement',
'agreement_file', 'expires'
]
80 changes: 66 additions & 14 deletions src/bocken/forms/journal_entry_form.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from bocken.models.agreement import Agreement
from bocken.models.journal_entry import JournalEntry
from bocken.models.vehicle import Vehicle
from ..validators import validate_personnummer
from ..utils import format_personnummer
from ..widgets import TwoLevelSelect
Expand All @@ -26,7 +27,7 @@ class JournalEntryForm(ModelForm):

confirm = BooleanField(
required=True,
label=_("I confirm that Bocken is clean and in good shape"),
label=_("I confirm that the vehicle is clean and in good shape"),
widget=CheckboxInput(attrs={'class': 'h-8 w-8'})
)

Expand All @@ -35,7 +36,7 @@ class JournalEntryForm(ModelForm):
class Meta:
model = JournalEntry
fields = [
'personnummer', 'group', 'meter_start', 'meter_stop'
'personnummer', 'vehicle', 'group', 'meter_start', 'meter_stop'
]
widgets = {
"meter_start": TextInput(
Expand All @@ -57,6 +58,7 @@ class Meta:
'group': 'users',
'meter_start': 'play-circle',
'meter_stop': 'stop-circle',
'vehicle': 'truck'
}
help_texts = {
'group': _(
Expand All @@ -68,20 +70,43 @@ class Meta:
"latest entry. If the number is not correct, enter the value "
"that the meter had when you started driving. Also inform the "
"head of the pub crew about this."
),
'vehicle': _(
"Choose the type of vehicle you have driven."
)
}

def __init__(self, *args, **kwargs):
super(JournalEntryForm, self).__init__(*args, **kwargs)
# Set the initial value for the meter start to the stop value of the
# last entry since it most likely is the value of the meter when a
# person starts driving.
latest_entry = JournalEntry.get_latest_entry()
if latest_entry:
# last entry based on the current vehicle choice since it most
# likely is the value of the meter when a person starts driving.
all_vehicles = Vehicle.objects.all()
latest_entries = [
JournalEntry.get_latest_entry(x)
for x in all_vehicles
if JournalEntry.get_latest_entry(x) is not None
]
if latest_entries:
latest_entry = latest_entries[0]
self.initial = {
'meter_start': latest_entry.meter_stop
'meter_start': latest_entry.meter_stop,
}

# This stores all of the latest registered trips for vehicle.
# By doing this we can hence "support" any amount of vehicle
# and fetch their latest trip to automatically set as
# a value for when a user is registering a new journal entry
for item in latest_entries:
self.initial[
f'meter_start_{str(item.vehicle.id)}'
] = item.meter_stop
else:
# if there is not a latest entry, then fetch from vehicle objects
# ideally it should always be fetched from here but..?
for vehicle in all_vehicles:
self.initial[
f'meter_start_{str(vehicle.id)}'
] = vehicle.vehicle_meter_stop
# If there is data from the previous form (a.k.a. invalid data
# was passed) we need to add some of that data to the TwoLevelSelect
# widget so that it can automatically choose a default option.
Expand All @@ -103,7 +128,8 @@ def clean_personnummer(self):

def clean_meter_start(self):
"""Meter start must be larger than the meter stop in the last entry."""
latest_entry = JournalEntry.get_latest_entry()
form_vehicle = self.cleaned_data['vehicle']
latest_entry = JournalEntry.get_latest_entry(form_vehicle)
if latest_entry:
if latest_entry.meter_stop > self.cleaned_data['meter_start']:
raise ValidationError(_(
Expand All @@ -121,26 +147,52 @@ def clean(self): # noqa
# we don't need to add an error message that a user does not
# have a written agreement.
person_nummer = self.cleaned_data.get('personnummer')
veh = self.cleaned_data.get('vehicle')
if person_nummer:
try:
agreement = Agreement.objects.get(
personnummer=person_nummer
)
can_use_car = agreement.car_agreement
can_use_bike = agreement.bike_agreement
if veh.car:
if not can_use_car:
self.add_error('vehicle', _(
"You don't have a written agreement which you "
"must have to drive a car. Contact the head of "
"the pub crew and send a copy of the details "
"you wrote inte the fields below."
))
else:
if not can_use_bike:
self.add_error('vehicle', _(
"You don't have a written agreement which you "
"must have to drive a bike. Contact the head of "
"the pub crew and send a copy of the details "
"you wrote inte the fields below."
))

self.instance.agreement = agreement
except Agreement.DoesNotExist:
self.add_error('personnummer', _(
"You don't have a written agreement which you must have "
"to drive bocken. Contact the head of the pub crew and "
"send a copy of the details you wrote into the fields "
"below."
"You don't have a written agreement which you "
"must have to drive a vehicle. Contact the head of "
"the pub crew and send a copy of the details "
"you wrote inte the fields below."
))

# Make sure meter stop is larger than meter start
meter_start = cleaned_data.get('meter_start', 0)
meter_stop = cleaned_data['meter_stop']
if cleaned_data['meter_stop'] <= meter_start:
self.add_error('meter_stop', _(
"Trip meter at stop must be larger than the trip meter at "
"start"
))

else:
if veh:
Vehicle.objects.filter(id=veh.id).update(
vehicle_meter_start=meter_start,
vehicle_meter_stop=meter_stop
)
return cleaned_data
Loading
Loading