You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

82 lines
3.6 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

user: when both tare and gross are filled out, net should be calculated and saved (at backend). doc_number should be generated and assigned to the vehicle record. how will be the document number generated, what is better, use the vehicle id or a generator?
Claudes Plan
Plan: Auto-calculate net + assign doc_number when both tare and gross are set
Context
One vehicle record = one weighing trip. When both tare and gross are recorded, the backend should
automatically compute net = gross - tare, stamp net_date/net_user, and assign a unique
document number formatted as YYYY-NNNNNN (year + 6-digit sequential counter, resetting per year).
No frontend change is needed — the net and doc_number come back in the existing SSE broadcast.
Files to Modify
File Change
backend/api/models.py Add DocumentCounter model
backend/vehicles/models.py Add doc_number field to Vehicle
backend/api/serializers.py Add net, net_date, net_user_name, doc_number to VehicleSerializer
backend/api/views.py Update set_tare and set_gross to compute net + doc_number
new migration in api For DocumentCounter
new migration in vehicles For doc_number on Vehicle
Step 1 — Add DocumentCounter model (backend/api/models.py)
class DocumentCounter(models.Model):
year = models.IntegerField(unique=True)
last_number = models.IntegerField(default=0)
Add a helper function in the same file (or in views.py, but models.py keeps it reusable):
from django.db import transaction
def generate_doc_number(year):
with transaction.atomic():
counter, _ = DocumentCounter.objects.select_for_update().get_or_create(
year=year, defaults={'last_number': 0}
)
counter.last_number += 1
counter.save()
return f"{year}-{counter.last_number:06d}"
Step 2 — Add doc_number to Vehicle (backend/vehicles/models.py)
doc_number = models.CharField(max_length=20, null=True, blank=True, unique=True)
Place after the net_user field.
Step 3 — Update VehicleSerializer (backend/api/serializers.py)
Add to the VehicleSerializer:
net_user_name = serializers.CharField(source='net_user.username', read_only=True, default=None)
Add to fields list:
'net', 'net_date', 'net_user', 'net_user_name', 'doc_number'
Add to read_only_fields:
'net', 'net_date', 'net_user', 'net_user_name', 'doc_number'
Step 4 — Update set_tare and set_gross (backend/api/views.py)
Extract a helper to avoid duplication:
def _maybe_finalize(vehicle, user):
"""If both tare and gross are now set, compute net and assign doc_number."""
if vehicle.tare is not None and vehicle.gross is not None and vehicle.net is None:
vehicle.net = vehicle.gross - vehicle.tare
vehicle.net_date = timezone.now()
vehicle.net_user = user
vehicle.doc_number = generate_doc_number(timezone.now().year)
vehicle.save()
Call _maybe_finalize(vehicle, request.user) at the end of both set_tare and set_gross,
before the SSE broadcast and serializer response (so the response already contains net + doc_number).
Import generate_doc_number from api.models.
Step 5 — Migrations
python manage.py makemigrations api # DocumentCounter
python manage.py makemigrations vehicles # doc_number on Vehicle
python manage.py migrate
Verification
Create a vehicle with no tare/gross → net and doc_number are null
Set tare → net still null (only one weight set)
Set gross → net is calculated, net_date and net_user are set, doc_number is "2026-000001"
Second vehicle completes → doc_number is "2026-000002"
Race condition test (optional): two simultaneous requests → both get unique sequential numbers
Frontend SSE update reflects net and doc_number automatically (no frontend change needed)