-
Notifications
You must be signed in to change notification settings - Fork 34
MySQL/MariaDB + Auto cost per unit #294
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
base: main
Are you sure you want to change the base?
Changes from all commits
981b940
f4df45e
c6a096a
76328fa
cda4e6b
fa5ce01
fac5369
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -62,23 +62,23 @@ <h1 class="text-2xl font-bold text-gray-900 dark:text-white mt-2">{% if log %}{{ | |
| <label for="volume" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ _('Volume') }} ({{ current_user.volume_unit }})</label> | ||
| <input type="number" name="volume" id="volume" step="0.001" | ||
| value="{{ log.volume if log else '' }}" | ||
| onchange="calculateTotal()" | ||
| onchange="calculateFuelAmounts()" | ||
| class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 px-3 py-2 focus:border-primary-500 focus:outline-none focus:ring-1 focus:ring-primary-500"> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label for="price_per_unit" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ _('Price per') }} {{ current_user.volume_unit }} ({{ current_user.currency }})</label> | ||
| <input type="number" name="price_per_unit" id="price_per_unit" step="0.001" | ||
| value="{{ log.price_per_unit if log else '' }}" | ||
| onchange="calculateTotal()" | ||
| onchange="calculateFuelAmounts()" | ||
| class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 px-3 py-2 focus:border-primary-500 focus:outline-none focus:ring-1 focus:ring-primary-500"> | ||
| </div> | ||
|
|
||
| <div> | ||
| <label for="discount_per_unit" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ _('Discount per') }} {{ current_user.volume_unit }} ({{ current_user.currency }})</label> | ||
| <input type="number" name="discount_per_unit" id="discount_per_unit" step="0.001" min="0" | ||
| value="{{ log.discount_per_unit if log and log.discount_per_unit is not none else '' }}" | ||
| onchange="calculateTotal()" | ||
| onchange="calculateFuelAmounts()" | ||
| placeholder="0.000" | ||
| class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 px-3 py-2 focus:border-primary-500 focus:outline-none focus:ring-1 focus:ring-primary-500"> | ||
| <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">{{ _('Optional loyalty discount, subtracted from the price per unit.') }}</p> | ||
|
|
@@ -88,6 +88,7 @@ <h1 class="text-2xl font-bold text-gray-900 dark:text-white mt-2">{% if log %}{{ | |
| <label for="total_cost" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ _('Total Cost') }} ({{ current_user.currency }})</label> | ||
| <input type="number" name="total_cost" id="total_cost" step="0.01" | ||
| value="{{ log.total_cost if log else '' }}" | ||
| onchange="calculateFuelAmounts()" | ||
| class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 px-3 py-2 focus:border-primary-500 focus:outline-none focus:ring-1 focus:ring-primary-500"> | ||
|
Comment on lines
+91
to
92
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Track whether When After the function fills the field, a later edit to Also applies to: 247-265 🤖 Prompt for AI Agents✅ Addressed in commit 76328fa |
||
| </div> | ||
|
|
||
|
|
@@ -179,6 +180,8 @@ <h1 class="text-2xl font-bold text-gray-900 dark:text-white mt-2">{% if log %}{{ | |
| </div> | ||
|
|
||
| <script> | ||
| let pricePerUnitWasDerived = false; | ||
|
|
||
| function updateVehicleOdometer(vehicleId) { | ||
| const select = document.getElementById('vehicle_id'); | ||
| const selectedOption = select.options[select.selectedIndex]; | ||
|
|
@@ -243,13 +246,32 @@ <h1 class="text-2xl font-bold text-gray-900 dark:text-white mt-2">{% if log %}{{ | |
| } | ||
| } | ||
|
|
||
| function calculateTotal() { | ||
| function calculateFuelAmounts() { | ||
| const volume = parseDecimal(document.getElementById('volume').value) || 0; | ||
| const pricePerUnit = parseDecimal(document.getElementById('price_per_unit').value) || 0; | ||
| const priceInput = document.getElementById('price_per_unit'); | ||
| const totalInput = document.getElementById('total_cost'); | ||
| const discountPerUnit = parseDecimal(document.getElementById('discount_per_unit').value) || 0; | ||
|
|
||
| // Preserve an explicitly entered total cost when the unit price is derived from it. | ||
| // Keep the derived-state flag until the user edits the price manually. | ||
| if ((pricePerUnitWasDerived || !priceInput.value) && volume && totalInput.value) { | ||
| const totalCost = parseDecimal(totalInput.value); | ||
| if (totalCost !== null) { | ||
| const pricePerUnit = (totalCost / volume) + discountPerUnit; | ||
| priceInput.value = pricePerUnit.toFixed(3); | ||
| pricePerUnitWasDerived = true; | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| let pricePerUnit = parseDecimal(priceInput.value) || 0; | ||
| if (pricePerUnitWasDerived && !priceInput.value) { | ||
| pricePerUnitWasDerived = false; | ||
| } | ||
|
|
||
| if (volume && pricePerUnit) { | ||
| const effectivePrice = Math.max(pricePerUnit - discountPerUnit, 0); | ||
| document.getElementById('total_cost').value = (volume * effectivePrice).toFixed(2); | ||
| totalInput.value = (volume * effectivePrice).toFixed(2); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -264,6 +286,19 @@ <h1 class="text-2xl font-bold text-gray-900 dark:text-white mt-2">{% if log %}{{ | |
| // Initialize odometer and fuel type for selected vehicle | ||
| document.addEventListener('DOMContentLoaded', function() { | ||
| const vehicleSelect = document.getElementById('vehicle_id'); | ||
| const priceInput = document.getElementById('price_per_unit'); | ||
| const totalInput = document.getElementById('total_cost'); | ||
|
|
||
| priceInput.addEventListener('change', function() { | ||
| pricePerUnitWasDerived = false; | ||
| }); | ||
|
|
||
| totalInput.addEventListener('change', function() { | ||
| if (!priceInput.value || pricePerUnitWasDerived) { | ||
| calculateFuelAmounts(); | ||
| } | ||
| }); | ||
|
|
||
| updateVehicleOdometer(vehicleSelect.value); | ||
| const selectedOption = vehicleSelect.options[vehicleSelect.selectedIndex]; | ||
| updateFuelTypeSelector(selectedOption); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Revalidate a derived
price_per_unit.The explicit price path applies
max_value=1000before this block. The fallback assigns a new value after that validation and does not apply the same limit. A request withvolume=1andtotal_cost=2000derivesprice_per_unit=2000, which can then be persisted and saved toFuelPriceHistory.Run the derived value through the same validation rule before creating
FuelLog.🤖 Prompt for AI Agents
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: dannymcc/may
Length of output: 34888
🏁 Script executed:
Repository: dannymcc/may
Length of output: 2096
Use
parse_decimal()invalidate_positive_number(). The helper currently callsfloat(value), so locale-formatted inputs such as9,99fail and fuel fields bypass the shared route parser.🤖 Prompt for AI Agents
Source: Path instructions
✅ Addressed in commit c6a096a