diff --git a/README.md b/README.md index 99cddc8..5717f80 100644 --- a/README.md +++ b/README.md @@ -135,8 +135,9 @@ SECRET_KEY=your-secure-random-string # Database location (optional, defaults to SQLite in the app's data folder) # Note the slashes: sqlite:///path is relative, sqlite:////path is absolute. DATABASE_URL=sqlite:////srv/may/data/may.db -# PostgreSQL is also supported: +# PostgreSQL, MySQL, and MariaDB are also supported: # DATABASE_URL=postgresql://user:password@host:5432/may +# DATABASE_URL=mysql+pymysql://user:password@host:3306/may # Upload folder for attachments (optional) UPLOAD_FOLDER=/srv/may/data/uploads diff --git a/app/routes/fuel.py b/app/routes/fuel.py index 18a390b..e2ba640 100644 --- a/app/routes/fuel.py +++ b/app/routes/fuel.py @@ -130,6 +130,18 @@ def new(): flash(err, 'error') return redirect(url_for('fuel.new', vehicle_id=vehicle_id)) + # Derive the unit price from the amount paid when it was omitted. + # Add the discount back because total_cost represents the amount paid + # after the per-unit discount has been applied (#209). + if price_per_unit is None and volume and total_cost is not None: + price_per_unit = round(total_cost / volume + (discount_per_unit or 0), 3) + price_per_unit, err = validate_positive_number( + price_per_unit, 'Price per unit', max_value=1000 + ) + if err: + flash(err, 'error') + return redirect(url_for('fuel.new')) + log = FuelLog( vehicle_id=vehicle_id, user_id=current_user.id, diff --git a/app/security.py b/app/security.py index 3d68f68..257d26c 100644 --- a/app/security.py +++ b/app/security.py @@ -7,6 +7,7 @@ from functools import wraps from flask import request, redirect, url_for, flash from flask_login import current_user +from app.utils import parse_decimal # File signature (magic bytes) mappings FILE_SIGNATURES = { @@ -180,9 +181,14 @@ def validate_positive_number(value, field_name, max_value=None, allow_zero=True) return None, None # Empty is OK try: - num = float(value) + num = parse_decimal(value) except (ValueError, TypeError): return None, f"{field_name} must be a valid number" + if num is None: + # parse_decimal returned its default/None for inputs like the + # literal string "None" or other absent-value markers. Treat this + # as an invalid number rather than silently accepting it. + return None, f"{field_name} must be a valid number" if not allow_zero and num == 0: return None, f"{field_name} cannot be zero" diff --git a/app/templates/fuel/form.html b/app/templates/fuel/form.html index f8abff5..20156fe 100644 --- a/app/templates/fuel/form.html +++ b/app/templates/fuel/form.html @@ -68,7 +68,7 @@
{{ _('Optional loyalty discount, subtracted from the price per unit.') }}
@@ -94,6 +94,7 @@