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

TP2000-1678-Measure-condition-duty-bug #1394

Merged
merged 3 commits into from
Jan 24, 2025
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
3 changes: 2 additions & 1 deletion measures/duty_sentence_parser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import datetime
from decimal import Decimal
from typing import Sequence

from django.core.exceptions import ObjectDoesNotExist
Expand Down Expand Up @@ -460,7 +461,7 @@ def expr_amount_permitted(self, value):

def duty_amount(self, value):
(value,) = value
return ("duty_amount", float(value))
return ("duty_amount", Decimal(value))

def monetary_unit(self, value):
(value,) = value
Expand Down
7 changes: 7 additions & 0 deletions measures/forms/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,13 @@ def conditions_clean(
try:
components = parser.transform(price)
cleaned_data["duty_amount"] = components[0].get("duty_amount")
if (
cleaned_data["duty_amount"]
and len(str(cleaned_data["duty_amount"]).split(".")[-1]) > 3
):
raise ValidationError(
f"The reference price cannot have more than 3 decimal places.",
)
cleaned_data["monetary_unit"] = components[0].get("monetary_unit")
cleaned_data["condition_measurement"] = (
models.Measurement.objects.as_at(date)
Expand Down
35 changes: 33 additions & 2 deletions measures/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,37 @@ def test_measure_forms_conditions_wizard_clears_unneeded_certificate(date_ranges
assert form_expects_no_certificate.cleaned_data["required_certificate"] is None


def test_measure_forms_conditions_wizard_form_invalid_duty(date_ranges):
"""Tests that MeasureConditionsWizardStepForm is invalid when the duty has
more than 3 decimal places."""
condition_code = factories.MeasureConditionCodeFactory.create()
monetary_unit = factories.MonetaryUnitFactory.create()
factories.MeasurementUnitFactory.create()
factories.MeasurementUnitQualifierFactory.create()
factories.MeasureConditionComponentFactory.create()
factories.DutyExpressionFactory.create(sid=99)
action = factories.MeasureActionFactory.create()

data = {
"reference_price": f"1.2345 {monetary_unit.code}",
"action": action.pk,
"condition_code": condition_code.pk,
}
# MeasureConditionsForm.__init__ expects prefix kwarg for instantiating crispy forms `Layout` object
form = forms.MeasureConditionsWizardStepForm(
data,
prefix="",
measure_start_date=date_ranges.normal,
)

with override_current_transaction(action.transaction):
assert not form.is_valid()
assert (
"The reference price cannot have more than 3 decimal places."
in form.errors["reference_price"]
)


def test_measure_form_valid_data(erga_omnes, session_request_with_workbasket):
"""Test that MeasureForm.is_valid returns True when passed required fields
and geographical_area and sid fields in cleaned data."""
Expand Down Expand Up @@ -1970,8 +2001,8 @@ def test_simple_measure_edit_forms_serialize_deserialize(
request,
duty_sentence_parser,
):
"""Test that the EditMeasure simple forms that use the
SerializableFormMixin behave correctly and as expected."""
"""Test that the EditMeasure simple forms that use the SerializableFormMixin
behave correctly and as expected."""

# Create some measures to apply this data to, for the kwargs
quota_order_number = factories.QuotaOrderNumberFactory()
Expand Down
15 changes: 8 additions & 7 deletions measures/tests/test_lark_parser.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from decimal import Decimal
from typing import Dict
from typing import List
from typing import Tuple
Expand Down Expand Up @@ -45,7 +46,7 @@
["1.230", "EUR", "kg"],
[
{
"duty_amount": 1.23,
"duty_amount": Decimal("1.23"),
"duty_expression": PERCENT_OR_AMOUNT_FIXTURE_NAME,
"monetary_unit": EURO_FIXTURE_NAME,
"measurement_unit": KILOGRAM_FIXTURE_NAME,
Expand All @@ -57,16 +58,16 @@
["9.10", "%", "MAX", "1.00", "%", "+", "0.90", "GBP", "100 kg"],
[
{
"duty_amount": 9.1,
"duty_amount": Decimal("9.1"),
"duty_expression": PERCENT_OR_AMOUNT_FIXTURE_NAME,
},
{
"duty_expression_sid": MAXIMUM_CLAUSE_SID[0],
"duty_amount": 1.0,
"duty_amount": Decimal("1.0"),
},
{
"duty_expression_sid": PLUS_PERCENT_OR_AMOUNT_SID[1],
"duty_amount": 0.9,
"duty_amount": Decimal("0.9"),
"monetary_unit": BRITISH_POUND_FIXTURE_NAME,
"measurement_unit": HECTOKILOGRAM_FIXTURE_NAME,
},
Expand All @@ -77,7 +78,7 @@
["0.300", "XEM", "100 kg", "lactic."],
[
{
"duty_amount": 0.3,
"duty_amount": Decimal("0.3"),
"duty_expression": PERCENT_OR_AMOUNT_FIXTURE_NAME,
"measurement_unit": HECTOKILOGRAM_FIXTURE_NAME,
"measurement_unit_qualifier": LACTIC_MATTER_FIXTURE_NAME,
Expand All @@ -91,10 +92,10 @@
[
{
"duty_expression": PERCENT_OR_AMOUNT_FIXTURE_NAME,
"duty_amount": 12.9,
"duty_amount": Decimal("12.9"),
},
{
"duty_amount": 20.0,
"duty_amount": Decimal("20.0"),
"duty_expression_sid": PLUS_PERCENT_OR_AMOUNT_SID[0],
"measurement_unit": KILOGRAM_FIXTURE_NAME,
"monetary_unit": EURO_FIXTURE_NAME,
Expand Down
Loading