diff --git a/backend/src/baserow/contrib/database/api/fields/serializers.py b/backend/src/baserow/contrib/database/api/fields/serializers.py index 1e30991cc..3a2280264 100644 --- a/backend/src/baserow/contrib/database/api/fields/serializers.py +++ b/backend/src/baserow/contrib/database/api/fields/serializers.py @@ -1,4 +1,5 @@ from django.utils.functional import lazy +from django.core.exceptions import ValidationError from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import extend_schema_field from rest_framework import serializers @@ -168,3 +169,17 @@ class FileFieldResponseSerializer( def get_instance_attr(self, instance, name): return instance[name] + + +class MustBeEmptyField(serializers.Field): + def __init__(self, error_message, *args, **kwargs): + def validator(value): + raise ValidationError(error_message, code="invalid") + + kwargs["write_only"] = True + kwargs["required"] = False + kwargs["validators"] = [validator] + super().__init__(*args, **kwargs) + + def to_internal_value(self, data): + return None diff --git a/backend/src/baserow/contrib/database/fields/field_helpers.py b/backend/src/baserow/contrib/database/fields/field_helpers.py index 1694823ab..0438e8157 100644 --- a/backend/src/baserow/contrib/database/fields/field_helpers.py +++ b/backend/src/baserow/contrib/database/fields/field_helpers.py @@ -18,21 +18,25 @@ def construct_all_possible_field_kwargs( "url": [{"name": "url"}], "email": [{"name": "email"}], "number": [ - {"name": "negative_int", "number_type": "INTEGER", "number_negative": True}, + { + "name": "negative_int", + "number_negative": True, + "number_decimal_places": 0, + }, { "name": "positive_int", - "number_type": "INTEGER", "number_negative": False, + "number_decimal_places": 0, }, { "name": "negative_decimal", - "number_type": "DECIMAL", "number_negative": "True", + "number_decimal_places": 1, }, { "name": "positive_decimal", - "number_type": "DECIMAL", "number_negative": False, + "number_decimal_places": 1, }, ], "rating": [ diff --git a/backend/src/baserow/contrib/database/fields/field_types.py b/backend/src/baserow/contrib/database/fields/field_types.py index d2ebabc38..e58258179 100644 --- a/backend/src/baserow/contrib/database/fields/field_types.py +++ b/backend/src/baserow/contrib/database/fields/field_types.py @@ -37,6 +37,7 @@ from baserow.contrib.database.api.fields.serializers import ( FileFieldRequestSerializer, SelectOptionSerializer, FileFieldResponseSerializer, + MustBeEmptyField, ) from baserow.contrib.database.formula import ( BaserowExpression, @@ -82,8 +83,6 @@ from .fields import ( ) from .handler import FieldHandler from .models import ( - NUMBER_TYPE_INTEGER, - NUMBER_TYPE_DECIMAL, TextField, LongTextField, URLField, @@ -315,8 +314,15 @@ class NumberFieldType(FieldType): type = "number" model_class = NumberField - allowed_fields = ["number_type", "number_decimal_places", "number_negative"] - serializer_field_names = ["number_type", "number_decimal_places", "number_negative"] + allowed_fields = ["number_decimal_places", "number_negative"] + serializer_field_names = ["number_decimal_places", "number_negative", "number_type"] + serializer_field_overrides = { + "number_type": MustBeEmptyField( + "The number_type option has been removed and can no longer be provided. " + "Instead set number_decimal_places to 0 for an integer or 1-5 for a " + "decimal." + ) + } def prepare_value_for_db(self, instance, value): if value is not None: @@ -331,11 +337,7 @@ class NumberFieldType(FieldType): def get_serializer_field(self, instance, **kwargs): required = kwargs.get("required", False) - kwargs["decimal_places"] = ( - 0 - if instance.number_type == NUMBER_TYPE_INTEGER - else instance.number_decimal_places - ) + kwargs["decimal_places"] = instance.number_decimal_places if not instance.number_negative: kwargs["min_value"] = 0 @@ -357,7 +359,7 @@ class NumberFieldType(FieldType): # don't convert it to a string. However if a decimal to preserve any precision # we keep it as a string. instance = field_object["field"] - if instance.number_type == NUMBER_TYPE_INTEGER: + if instance.number_decimal_places == 0: return int(value) # DRF's Decimal Serializer knows how to quantize and format the decimal @@ -365,11 +367,7 @@ class NumberFieldType(FieldType): return self.get_serializer_field(instance).to_representation(value) def get_model_field(self, instance, **kwargs): - kwargs["decimal_places"] = ( - 0 - if instance.number_type == NUMBER_TYPE_INTEGER - else instance.number_decimal_places - ) + kwargs["decimal_places"] = instance.number_decimal_places return models.DecimalField( max_digits=self.MAX_DIGITS + kwargs["decimal_places"], @@ -379,13 +377,13 @@ class NumberFieldType(FieldType): ) def random_value(self, instance, fake, cache): - if instance.number_type == NUMBER_TYPE_INTEGER: + if instance.number_decimal_places == 0: return fake.pyint( min_value=-10000 if instance.number_negative else 1, max_value=10000, step=1, ) - elif instance.number_type == NUMBER_TYPE_DECIMAL: + elif instance.number_decimal_places > 0: return fake.pydecimal( min_value=-10000 if instance.number_negative else 1, max_value=10000, @@ -394,9 +392,7 @@ class NumberFieldType(FieldType): def get_alter_column_prepare_new_value(self, connection, from_field, to_field): if connection.vendor == "postgresql": - decimal_places = 0 - if to_field.number_type == NUMBER_TYPE_DECIMAL: - decimal_places = to_field.number_decimal_places + decimal_places = to_field.number_decimal_places function = f"round(p_in::numeric, {decimal_places})" @@ -420,21 +416,14 @@ class NumberFieldType(FieldType): return value if value is None else str(value) def to_baserow_formula_type(self, field: NumberField) -> BaserowFormulaType: - if field.number_type == NUMBER_TYPE_INTEGER: - number_decimal_places = 0 - else: - number_decimal_places = field.number_decimal_places - return BaserowFormulaNumberType(number_decimal_places=number_decimal_places) + return BaserowFormulaNumberType( + number_decimal_places=field.number_decimal_places + ) def from_baserow_formula_type( self, formula_type: BaserowFormulaNumberType ) -> NumberField: - if formula_type.number_decimal_places == 0: - number_type = NUMBER_TYPE_INTEGER - else: - number_type = NUMBER_TYPE_DECIMAL return NumberField( - number_type=number_type, number_decimal_places=formula_type.number_decimal_places, number_negative=True, ) diff --git a/backend/src/baserow/contrib/database/fields/models.py b/backend/src/baserow/contrib/database/fields/models.py index eeb17b3c9..fd4c92fb2 100644 --- a/backend/src/baserow/contrib/database/fields/models.py +++ b/backend/src/baserow/contrib/database/fields/models.py @@ -2,7 +2,6 @@ from django.contrib.contenttypes.models import ContentType from django.db import models from django.utils.functional import cached_property from django.core.validators import MinValueValidator, MaxValueValidator - from baserow.contrib.database.fields.mixins import ( BaseDateMixin, TimezoneMixin, @@ -26,16 +25,11 @@ from baserow.core.mixins import ( ) from baserow.core.utils import to_snake_case, remove_special_characters -NUMBER_TYPE_INTEGER = "INTEGER" -NUMBER_TYPE_DECIMAL = "DECIMAL" -NUMBER_TYPE_CHOICES = ( - ("INTEGER", "Integer"), - ("DECIMAL", "Decimal"), -) NUMBER_MAX_DECIMAL_PLACES = 5 NUMBER_DECIMAL_PLACES_CHOICES = [ + (0, "1"), (1, "1.0"), (2, "1.00"), (3, "1.000"), @@ -206,12 +200,9 @@ class URLField(Field): class NumberField(Field): - number_type = models.CharField( - max_length=32, choices=NUMBER_TYPE_CHOICES, default=NUMBER_TYPE_INTEGER - ) number_decimal_places = models.IntegerField( choices=NUMBER_DECIMAL_PLACES_CHOICES, - default=1, + default=0, help_text="The amount of digits allowed after the point.", ) number_negative = models.BooleanField( @@ -219,10 +210,8 @@ class NumberField(Field): ) def save(self, *args, **kwargs): - """Check if the number_type and number_decimal_places has a valid choice.""" + """Check if the number_decimal_places has a valid choice.""" - if not any(self.number_type in _tuple for _tuple in NUMBER_TYPE_CHOICES): - raise ValueError(f"{self.number_type} is not a valid choice.") if not any( self.number_decimal_places in _tuple for _tuple in NUMBER_DECIMAL_PLACES_CHOICES @@ -396,7 +385,7 @@ class FormulaField(Field): null=True, ) number_decimal_places = models.IntegerField( - choices=[(0, "1")] + NUMBER_DECIMAL_PLACES_CHOICES, + choices=NUMBER_DECIMAL_PLACES_CHOICES, default=None, null=True, help_text="The amount of digits allowed after the point.", diff --git a/backend/src/baserow/contrib/database/migrations/0023_convert_int_to_bigint.py b/backend/src/baserow/contrib/database/migrations/0023_convert_int_to_bigint.py index 6b1f39647..2871ea2fd 100644 --- a/backend/src/baserow/contrib/database/migrations/0023_convert_int_to_bigint.py +++ b/backend/src/baserow/contrib/database/migrations/0023_convert_int_to_bigint.py @@ -1,7 +1,6 @@ # We need to change all NumberFields that are Integers to use DecimalField in Django # and NUMERIC(50, 0) in Postgres. This migration converts all the existing Integer data # types in fields to Decimal. -from baserow.contrib.database.fields.models import NUMBER_TYPE_INTEGER from django.db import migrations, connection from baserow.contrib.database.fields.models import Field as FieldModel @@ -25,7 +24,7 @@ def forward(apps, schema_editor): # which could result in an out of memory exception. tables_schema_editor.atomic.__exit__(None, None, None) - for field in NumberField.objects.filter(number_type=NUMBER_TYPE_INTEGER): + for field in NumberField.objects.filter(number_type="INTEGER"): table_name = f"database_table_{field.table.id}" column_name = FieldModel.db_column.__get__(field, FieldModel) sql = alter_sql(tables_schema_editor, table_name, column_name) diff --git a/backend/src/baserow/contrib/database/migrations/0061_change_decimal_places.py b/backend/src/baserow/contrib/database/migrations/0061_change_decimal_places.py new file mode 100644 index 000000000..6ddc0ab84 --- /dev/null +++ b/backend/src/baserow/contrib/database/migrations/0061_change_decimal_places.py @@ -0,0 +1,29 @@ +# Generated by Django 3.2.6 on 2022-02-14 13:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("database", "0060_set_ordering_on_tablewebhook_models"), + ] + + operations = [ + migrations.AlterField( + model_name="numberfield", + name="number_decimal_places", + field=models.IntegerField( + choices=[ + (0, "1"), + (1, "1.0"), + (2, "1.00"), + (3, "1.000"), + (4, "1.0000"), + (5, "1.00000"), + ], + default=0, + help_text="The amount of digits allowed after the point.", + ), + ), + ] diff --git a/backend/src/baserow/contrib/database/migrations/0062_migrate_number_type.py b/backend/src/baserow/contrib/database/migrations/0062_migrate_number_type.py new file mode 100644 index 000000000..a56df5692 --- /dev/null +++ b/backend/src/baserow/contrib/database/migrations/0062_migrate_number_type.py @@ -0,0 +1,29 @@ +from django.db import migrations + + +def forward(apps, schema_editor): + """ + If the NumberField.number_type was decimal we keep the decimal places + intact. + + If the NumberField.number_type was integer we set the decimal places to + 0 as the number field could have any number of decimal places set before. + """ + + NumberField = apps.get_model("database", "NumberField") + NumberField.objects.filter(number_type="INTEGER").update(number_decimal_places=0) + + +def reverse(apps, schema_editor): + ... + + +class Migration(migrations.Migration): + + dependencies = [ + ("database", "0061_change_decimal_places"), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/backend/src/baserow/contrib/database/migrations/0063_drop_number_type.py b/backend/src/baserow/contrib/database/migrations/0063_drop_number_type.py new file mode 100644 index 000000000..8735580ad --- /dev/null +++ b/backend/src/baserow/contrib/database/migrations/0063_drop_number_type.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.6 on 2022-02-14 13:28 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("database", "0062_migrate_number_type"), + ] + + operations = [ + migrations.RemoveField( + model_name="numberfield", + name="number_type", + ), + ] diff --git a/backend/src/baserow/test_utils/helpers.py b/backend/src/baserow/test_utils/helpers.py index 9deb8bcd0..931252501 100644 --- a/backend/src/baserow/test_utils/helpers.py +++ b/backend/src/baserow/test_utils/helpers.py @@ -59,7 +59,6 @@ def setup_interesting_test_table(data_fixture, user_kwargs=None): table=decimal_link_table, name="text_field", primary=True, - number_type="DECIMAL", number_decimal_places=3, number_negative=True, ) diff --git a/backend/templates/apartment-hunt.json b/backend/templates/apartment-hunt.json index b071e195a..0b7911827 100644 --- a/backend/templates/apartment-hunt.json +++ b/backend/templates/apartment-hunt.json @@ -71,8 +71,7 @@ "name": "Walkability", "order": 6, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -81,8 +80,7 @@ "name": "Transit", "order": 7, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -98,8 +96,7 @@ "name": "Built", "order": 9, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1044,8 +1041,7 @@ "name": "Bathrooms", "order": 5, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1054,8 +1050,7 @@ "name": "Bedrooms", "order": 6, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1064,8 +1059,7 @@ "name": "Rent", "order": 7, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1179,8 +1173,7 @@ "name": "Size (m\u00b2)", "order": 14, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -2480,8 +2473,7 @@ "name": "Zip Code", "order": 4, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/app-pitch-planner.json b/backend/templates/app-pitch-planner.json index 7401acec3..d5ba27e37 100644 --- a/backend/templates/app-pitch-planner.json +++ b/backend/templates/app-pitch-planner.json @@ -64,8 +64,7 @@ "name": "Duration (minutes)", "order": 3, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/blog-post-management.json b/backend/templates/blog-post-management.json index dfed5505b..4dec9cbd6 100644 --- a/backend/templates/blog-post-management.json +++ b/backend/templates/blog-post-management.json @@ -1310,8 +1310,7 @@ "name": "Channel Rating (1-5)", "order": 4, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/book-catalog.json b/backend/templates/book-catalog.json index 9f5b72dec..3c90d926f 100644 --- a/backend/templates/book-catalog.json +++ b/backend/templates/book-catalog.json @@ -148,8 +148,7 @@ "name": "Pages", "order": 10, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false } ], diff --git a/backend/templates/book-writing-guide.json b/backend/templates/book-writing-guide.json index e1d7cdc63..49ae07a08 100644 --- a/backend/templates/book-writing-guide.json +++ b/backend/templates/book-writing-guide.json @@ -86,8 +86,7 @@ "name": "Word Count", "order": 11, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/business-conference-event.json b/backend/templates/business-conference-event.json index 2cb085c41..a3ae126af 100644 --- a/backend/templates/business-conference-event.json +++ b/backend/templates/business-conference-event.json @@ -261,8 +261,7 @@ "name": "Duration (min)", "order": 2, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1327,8 +1326,7 @@ "name": "Years of experience", "order": 5, "primary": false, - "number_type": "DECIMAL", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1992,8 +1990,7 @@ "name": "Room capacity", "order": 3, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false } ], diff --git a/backend/templates/car-maintenance-log.json b/backend/templates/car-maintenance-log.json index 8354f92a2..9d2471717 100644 --- a/backend/templates/car-maintenance-log.json +++ b/backend/templates/car-maintenance-log.json @@ -78,7 +78,6 @@ "name": "Total cost", "order": 7, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -486,8 +485,7 @@ "name": "Avg duration (min)", "order": 1, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -523,7 +521,6 @@ "name": "Avg cost", "order": 3, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -1813,7 +1810,6 @@ "name": "Cost", "order": 2, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, diff --git a/backend/templates/commercial-property-management.json b/backend/templates/commercial-property-management.json index d9cb602f1..4f7dc32c9 100644 --- a/backend/templates/commercial-property-management.json +++ b/backend/templates/commercial-property-management.json @@ -63,8 +63,7 @@ "name": "Zip Code", "order": 4, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -742,8 +741,7 @@ "name": "Floor", "order": 2, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/company-asset-tracker.json b/backend/templates/company-asset-tracker.json index afbe13546..7139674f6 100644 --- a/backend/templates/company-asset-tracker.json +++ b/backend/templates/company-asset-tracker.json @@ -102,7 +102,6 @@ "name": "Cost", "order": 5, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, diff --git a/backend/templates/email-marketing-campaigns.json b/backend/templates/email-marketing-campaigns.json index fd25722d9..c23371656 100644 --- a/backend/templates/email-marketing-campaigns.json +++ b/backend/templates/email-marketing-campaigns.json @@ -1503,8 +1503,7 @@ "name":"Value (1-10)", "order":5, "primary":false, - "number_type":"INTEGER", - "number_decimal_places":1, + "number_decimal_places": 0, "number_negative":false } ], diff --git a/backend/templates/healthcare-facility-management.json b/backend/templates/healthcare-facility-management.json index 5e0e99573..989311a3a 100644 --- a/backend/templates/healthcare-facility-management.json +++ b/backend/templates/healthcare-facility-management.json @@ -174,8 +174,7 @@ "name": "SSN/TIN", "order": 24, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -4484,8 +4483,7 @@ "name": "Avg per Week", "order": 5, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/holiday-shopping.json b/backend/templates/holiday-shopping.json index 639f26341..5c3ed84d2 100644 --- a/backend/templates/holiday-shopping.json +++ b/backend/templates/holiday-shopping.json @@ -47,7 +47,6 @@ "name":"Price", "order":2, "primary":false, - "number_type":"DECIMAL", "number_decimal_places":2, "number_negative":false }, diff --git a/backend/templates/home-inventory.json b/backend/templates/home-inventory.json index 77b282226..b16540f1d 100644 --- a/backend/templates/home-inventory.json +++ b/backend/templates/home-inventory.json @@ -131,8 +131,7 @@ "name": "Quantity", "order": 6, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -188,8 +187,7 @@ "name": "Price", "order": 9, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1056,8 +1054,7 @@ "name": "Age", "order": 5, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1464,8 +1461,7 @@ "name": "Coverage", "order": 8, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false } ], diff --git a/backend/templates/house-search.json b/backend/templates/house-search.json index bb5e3e128..d2b14f54a 100644 --- a/backend/templates/house-search.json +++ b/backend/templates/house-search.json @@ -69,8 +69,7 @@ "name": "Asking price", "order": 5, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -79,8 +78,7 @@ "name": "# of Bedrooms", "order": 6, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -89,7 +87,6 @@ "name": "# of Bathrooms", "order": 7, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 1, "number_negative": false }, @@ -161,8 +158,7 @@ "name": "Size", "order": 14, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -171,7 +167,6 @@ "name": "HOA fee", "order": 15, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -195,7 +190,6 @@ "name": "Interest (%)", "order": 17, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -205,7 +199,6 @@ "name": "Property taxes", "order": 18, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -215,7 +208,6 @@ "name": "Insurance", "order": 19, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -2862,8 +2854,7 @@ "name": "Noise level (1-10)", "order": 4, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -2924,7 +2915,6 @@ "name": "Public transport (km)", "order": 7, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 1, "number_negative": false }, @@ -2934,7 +2924,6 @@ "name": "Highway (km)", "order": 9, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 1, "number_negative": false }, diff --git a/backend/templates/job-search.json b/backend/templates/job-search.json index 16f6dba35..12577d7d5 100644 --- a/backend/templates/job-search.json +++ b/backend/templates/job-search.json @@ -124,8 +124,7 @@ "name": "Salary", "order": 6, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/lightweight-crm.json b/backend/templates/lightweight-crm.json index 0804c13f1..18173c205 100644 --- a/backend/templates/lightweight-crm.json +++ b/backend/templates/lightweight-crm.json @@ -692,7 +692,6 @@ "name": "Contract Value", "order": 5, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, diff --git a/backend/templates/personal-health-log.json b/backend/templates/personal-health-log.json index 1f02ba40d..e7e75e34a 100644 --- a/backend/templates/personal-health-log.json +++ b/backend/templates/personal-health-log.json @@ -49,8 +49,7 @@ "name": "Resting HR", "order": 5, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -99,8 +98,7 @@ "name": "Weight (kg)", "order": 8, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -109,7 +107,6 @@ "name": "Hours of Sleep", "order": 9, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 1, "number_negative": false }, @@ -1204,8 +1201,7 @@ "name": "Calories", "order": 2, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1777,8 +1773,7 @@ "name": "Difficulty (1-10)", "order": 4, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/political-campaign-contributions.json b/backend/templates/political-campaign-contributions.json index 330ff1347..a6373f50a 100644 --- a/backend/templates/political-campaign-contributions.json +++ b/backend/templates/political-campaign-contributions.json @@ -94,8 +94,7 @@ "name": "Lifetime", "order": 8, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -120,8 +119,7 @@ "name": "Zip Code", "order": 11, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1016,8 +1014,7 @@ "name": "Amount", "order": 4, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/project-tracker.json b/backend/templates/project-tracker.json index a43587aa1..d4ffe1c64 100644 --- a/backend/templates/project-tracker.json +++ b/backend/templates/project-tracker.json @@ -622,7 +622,6 @@ "name": "Est. Days", "order": 4, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 1, "number_negative": false }, diff --git a/backend/templates/recipe-book.json b/backend/templates/recipe-book.json index c37b660ee..99c83777c 100644 --- a/backend/templates/recipe-book.json +++ b/backend/templates/recipe-book.json @@ -106,8 +106,7 @@ "name": "Cook Time (min)", "order": 9, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -116,8 +115,7 @@ "name": "Prep Time (min)", "order": 10, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { diff --git a/backend/templates/restaurant-management.json b/backend/templates/restaurant-management.json index c3c8b3b8c..02d5b5626 100644 --- a/backend/templates/restaurant-management.json +++ b/backend/templates/restaurant-management.json @@ -107,7 +107,6 @@ "name": "Hourly rate", "order": 9, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -1780,7 +1779,6 @@ "name": "In stock", "order": 5, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 1, "number_negative": false }, @@ -1790,7 +1788,6 @@ "name": "Ideal quantity", "order": 6, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 1, "number_negative": false }, @@ -2702,7 +2699,6 @@ "name": "Cost to make", "order": 3, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -3443,7 +3439,6 @@ "name": "Price", "order": 2, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -4015,7 +4010,6 @@ "name": "Shift duration", "order": 5, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 1, "number_negative": false } diff --git a/backend/templates/single-trip-planner.json b/backend/templates/single-trip-planner.json index 42ba90af2..79260f330 100644 --- a/backend/templates/single-trip-planner.json +++ b/backend/templates/single-trip-planner.json @@ -461,7 +461,6 @@ "name": "Duration", "order": 7, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -503,7 +502,6 @@ "name": "Cost", "order": 13, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -1388,7 +1386,6 @@ "name": "Cost", "order": 4, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -1927,7 +1924,6 @@ "name": "Cost", "order": 5, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -3130,7 +3126,6 @@ "name": "Cost", "order": 5, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -3731,7 +3726,6 @@ "name": "Cost", "order": 2, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, @@ -3741,7 +3735,6 @@ "name": "Budget", "order": 3, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, diff --git a/backend/templates/teacher-lesson-plans.json b/backend/templates/teacher-lesson-plans.json index 5e505d5df..8f2136bba 100644 --- a/backend/templates/teacher-lesson-plans.json +++ b/backend/templates/teacher-lesson-plans.json @@ -998,8 +998,7 @@ "name": "Est time (min)", "order": 6, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -1829,7 +1828,6 @@ "name": "Price", "order": 8, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false } @@ -2338,8 +2336,7 @@ "name": "Time to read (min)", "order": 4, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false } ], @@ -2656,7 +2653,6 @@ "name": "Admission", "order": 3, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false }, diff --git a/backend/templates/wedding-planning.json b/backend/templates/wedding-planning.json index 324c6f86a..5436795ff 100644 --- a/backend/templates/wedding-planning.json +++ b/backend/templates/wedding-planning.json @@ -72,8 +72,7 @@ "name": "Capacity", "order": 6, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": false }, { @@ -82,8 +81,7 @@ "name": "Rental Cost", "order": 7, "primary": false, - "number_type": "INTEGER", - "number_decimal_places": 2, + "number_decimal_places": 0, "number_negative": false }, { @@ -1328,7 +1326,6 @@ "name": "Cost", "order": 6, "primary": false, - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": false } diff --git a/backend/tests/baserow/contrib/database/api/fields/test_field_views.py b/backend/tests/baserow/contrib/database/api/fields/test_field_views.py index e45510095..33e4f572f 100644 --- a/backend/tests/baserow/contrib/database/api/fields/test_field_views.py +++ b/backend/tests/baserow/contrib/database/api/fields/test_field_views.py @@ -51,7 +51,6 @@ def test_list_fields(api_client, data_fixture): assert response_json[1]["id"] == field_3.id assert response_json[1]["type"] == "number" assert not response_json[1]["primary"] - assert response_json[1]["number_type"] == field_3.number_type assert response_json[1]["number_decimal_places"] == field_3.number_decimal_places assert response_json[1]["number_negative"] == field_3.number_negative @@ -390,15 +389,13 @@ def test_update_field(api_client, data_fixture): assert response.status_code == HTTP_200_OK assert response_json["name"] == "Test 1" assert response_json["type"] == "number" - assert response_json["number_type"] == "INTEGER" - assert response_json["number_decimal_places"] == 1 + assert response_json["number_decimal_places"] == 0 assert response_json["number_negative"] url = reverse("api:database:fields:item", kwargs={"field_id": text.id}) response = api_client.patch( url, { - "number_type": "DECIMAL", "number_decimal_places": 2, "number_negative": False, }, @@ -409,7 +406,6 @@ def test_update_field(api_client, data_fixture): assert response.status_code == HTTP_200_OK assert response_json["name"] == "Test 1" assert response_json["type"] == "number" - assert response_json["number_type"] == "DECIMAL" assert response_json["number_decimal_places"] == 2 assert not response_json["number_negative"] @@ -424,7 +420,6 @@ def test_update_field(api_client, data_fixture): assert response.status_code == HTTP_200_OK assert response_json["name"] == "Test 2" assert response_json["type"] == "boolean" - assert "number_type" not in response_json assert "number_decimal_places" not in response_json assert "number_negative" not in response_json @@ -457,6 +452,31 @@ def test_update_field(api_client, data_fixture): assert response.json()["error"] == "ERROR_REQUEST_BODY_VALIDATION" +@pytest.mark.django_db +def test_update_field_number_type_deprecation_error(api_client, data_fixture): + user, token = data_fixture.create_user_and_token() + table = data_fixture.create_database_table(user=user) + number_field = data_fixture.create_number_field( + table=table, number_decimal_places=1 + ) + + url = reverse("api:database:fields:item", kwargs={"field_id": number_field.id}) + response = api_client.patch( + url, + {"number_type": "INTEGER"}, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + + assert response.status_code == HTTP_400_BAD_REQUEST + assert response.json()["error"] == "ERROR_REQUEST_BODY_VALIDATION" + assert response.json()["detail"]["number_type"][0]["error"] == ( + "The number_type option has been removed and can no longer be provided. " + "Instead set number_decimal_places to 0 for an integer or 1-5 for a " + "decimal." + ) + + @pytest.mark.django_db def test_delete_field(api_client, data_fixture): user, token = data_fixture.create_user_and_token() diff --git a/backend/tests/baserow/contrib/database/api/fields/test_field_views_types.py b/backend/tests/baserow/contrib/database/api/fields/test_field_views_types.py index 8a3cfb457..066f6e0ff 100644 --- a/backend/tests/baserow/contrib/database/api/fields/test_field_views_types.py +++ b/backend/tests/baserow/contrib/database/api/fields/test_field_views_types.py @@ -633,7 +633,7 @@ def test_number_field_type(api_client, data_fixture): { "name": "PositiveInt", "type": "number", - "number_type": "INTEGER", + "number_decimal_places": 0, "number_negative": False, }, format="json", @@ -653,7 +653,7 @@ def test_number_field_type(api_client, data_fixture): { "name": "NegativeInt", "type": "number", - "number_type": "INTEGER", + "number_decimal_places": 0, "number_negative": True, }, format="json", @@ -673,7 +673,6 @@ def test_number_field_type(api_client, data_fixture): { "name": "PositiveDecimal", "type": "number", - "number_type": "DECIMAL", "number_negative": False, "number_decimal_places": 2, }, @@ -694,7 +693,6 @@ def test_number_field_type(api_client, data_fixture): { "name": "NegativeDecimal", "type": "number", - "number_type": "DECIMAL", "number_negative": True, "number_decimal_places": 2, }, diff --git a/backend/tests/baserow/contrib/database/api/fields/test_formula_views.py b/backend/tests/baserow/contrib/database/api/fields/test_formula_views.py index 86eb64d8d..9ff3d74f7 100644 --- a/backend/tests/baserow/contrib/database/api/fields/test_formula_views.py +++ b/backend/tests/baserow/contrib/database/api/fields/test_formula_views.py @@ -19,7 +19,7 @@ def test_altering_value_of_referenced_field( table = data_fixture.create_database_table(user=user) response = api_client.post( reverse("api:database:fields:list", kwargs={"table_id": table.id}), - {"name": "number", "type": "number", "number_type": "INTEGER"}, + {"name": "number", "type": "number", "number_decimal_places": 0}, format="json", HTTP_AUTHORIZATION=f"JWT {token}", ) @@ -702,7 +702,6 @@ def test_altering_type_of_underlying_causes_type_update(api_client, data_fixture { "name": "text", "type": "number", - "number_type": "DECIMAL", "number_decimal_places": 2, }, format="json", @@ -897,7 +896,7 @@ def test_can_type_an_invalid_formula_field( table = data_fixture.create_database_table(user=user) response = api_client.post( reverse("api:database:fields:list", kwargs={"table_id": table.id}), - {"name": "number", "type": "number", "number_type": "INTEGER"}, + {"name": "number", "type": "number", "number_decimal_places": 0}, format="json", HTTP_AUTHORIZATION=f"JWT {token}", ) @@ -935,7 +934,7 @@ def test_can_type_a_valid_formula_field( table = data_fixture.create_database_table(user=user) response = api_client.post( reverse("api:database:fields:list", kwargs={"table_id": table.id}), - {"name": "number", "type": "number", "number_type": "INTEGER"}, + {"name": "number", "type": "number", "number_decimal_places": 0}, format="json", HTTP_AUTHORIZATION=f"JWT {token}", ) @@ -981,7 +980,7 @@ def test_type_endpoint_returns_error_for_bad_syntax( table = data_fixture.create_database_table(user=user) response = api_client.post( reverse("api:database:fields:list", kwargs={"table_id": table.id}), - {"name": "number", "type": "number", "number_type": "INTEGER"}, + {"name": "number", "type": "number", "number_decimal_places": 0}, format="json", HTTP_AUTHORIZATION=f"JWT {token}", ) @@ -1018,7 +1017,7 @@ def test_type_endpoint_returns_error_for_missing_parameters( table = data_fixture.create_database_table(user=user) response = api_client.post( reverse("api:database:fields:list", kwargs={"table_id": table.id}), - {"name": "number", "type": "number", "number_type": "INTEGER"}, + {"name": "number", "type": "number", "number_decimal_places": 0}, format="json", HTTP_AUTHORIZATION=f"JWT {token}", ) @@ -1055,7 +1054,7 @@ def test_type_endpoint_returns_error_for_missing_field( table = data_fixture.create_database_table(user=user) response = api_client.post( reverse("api:database:fields:list", kwargs={"table_id": table.id}), - {"name": "number", "type": "number", "number_type": "INTEGER"}, + {"name": "number", "type": "number", "number_decimal_places": 0}, format="json", HTTP_AUTHORIZATION=f"JWT {token}", ) @@ -1080,7 +1079,7 @@ def test_type_endpoint_returns_error_for_non_formula_field( table = data_fixture.create_database_table(user=user) response = api_client.post( reverse("api:database:fields:list", kwargs={"table_id": table.id}), - {"name": "number", "type": "number", "number_type": "INTEGER"}, + {"name": "number", "type": "number", "number_decimal_places": 0}, format="json", HTTP_AUTHORIZATION=f"JWT {token}", ) @@ -1164,7 +1163,7 @@ def test_type_endpoint_returns_error_if_not_permissioned_for_field( table = data_fixture.create_database_table(user=user) response = api_client.post( reverse("api:database:fields:list", kwargs={"table_id": table.id}), - {"name": "number", "type": "number", "number_type": "INTEGER"}, + {"name": "number", "type": "number", "number_decimal_places": 0}, format="json", HTTP_AUTHORIZATION=f"JWT {token}", ) @@ -1249,7 +1248,6 @@ def test_altering_type_of_underlying_causes_type_update_nested( { "name": "text", "type": "number", - "number_type": "DECIMAL", "number_decimal_places": 2, }, format="json", diff --git a/backend/tests/baserow/contrib/database/api/rows/test_row_serializers.py b/backend/tests/baserow/contrib/database/api/rows/test_row_serializers.py index fe77320d1..0cb6956c6 100644 --- a/backend/tests/baserow/contrib/database/api/rows/test_row_serializers.py +++ b/backend/tests/baserow/contrib/database/api/rows/test_row_serializers.py @@ -25,7 +25,6 @@ def test_get_table_serializer(data_fixture): table=table, order=4, name="Price", - number_type="DECIMAL", number_negative=True, number_decimal_places=2, ) @@ -148,7 +147,6 @@ def test_get_table_serializer(data_fixture): table=table, order=0, name="Sale price", - number_type="DECIMAL", number_decimal_places=3, number_negative=True, ) diff --git a/backend/tests/baserow/contrib/database/api/rows/test_row_views.py b/backend/tests/baserow/contrib/database/api/rows/test_row_views.py index ef531dd75..543cf93a5 100644 --- a/backend/tests/baserow/contrib/database/api/rows/test_row_views.py +++ b/backend/tests/baserow/contrib/database/api/rows/test_row_views.py @@ -11,7 +11,6 @@ from rest_framework.status import ( from baserow.contrib.database.fields.handler import FieldHandler from baserow.contrib.database.fields.registries import field_type_registry -from baserow.contrib.database.fields.models import NUMBER_TYPE_DECIMAL from baserow.contrib.database.rows.handler import RowHandler from baserow.contrib.database.table.cache import ( invalidate_table_model_cache_and_related_models, @@ -653,7 +652,7 @@ def test_create_row_with_blank_decimal_field(api_client, data_fixture): user, jwt_token = data_fixture.create_user_and_token() table = data_fixture.create_database_table(user=user) decimal_field = data_fixture.create_number_field( - table=table, order=1, name="TestDecimal", number_type=NUMBER_TYPE_DECIMAL + table=table, order=1, name="TestDecimal", number_decimal_places=1 ) response = api_client.post( @@ -981,7 +980,6 @@ def test_update_row(api_client, data_fixture): table=table_3, order=0, name="Price", - number_type="DECIMAL", number_decimal_places=2, ) model_3 = table_3.get_model() diff --git a/backend/tests/baserow/contrib/database/api/views/form/test_form_view_views.py b/backend/tests/baserow/contrib/database/api/views/form/test_form_view_views.py index 399651668..36836ceac 100644 --- a/backend/tests/baserow/contrib/database/api/views/form/test_form_view_views.py +++ b/backend/tests/baserow/contrib/database/api/views/form/test_form_view_views.py @@ -280,8 +280,7 @@ def test_meta_submit_form_view(api_client, data_fixture): "field": { "id": number_field.id, "type": "number", - "number_type": "INTEGER", - "number_decimal_places": 1, + "number_decimal_places": 0, "number_negative": False, }, } diff --git a/backend/tests/baserow/contrib/database/export/test_export_handler.py b/backend/tests/baserow/contrib/database/export/test_export_handler.py index 49dc4783b..3db89837a 100644 --- a/backend/tests/baserow/contrib/database/export/test_export_handler.py +++ b/backend/tests/baserow/contrib/database/export/test_export_handler.py @@ -710,7 +710,6 @@ def setup_testing_table(data_fixture): price_field = data_fixture.create_number_field( table=table, name="Price", - number_type="DECIMAL", number_decimal_places=2, number_negative=True, order=4, diff --git a/backend/tests/baserow/contrib/database/field/test_field_handler.py b/backend/tests/baserow/contrib/database/field/test_field_handler.py index 95a396f2c..ed66dc8b8 100644 --- a/backend/tests/baserow/contrib/database/field/test_field_handler.py +++ b/backend/tests/baserow/contrib/database/field/test_field_handler.py @@ -207,17 +207,7 @@ def test_create_field(send_mock, data_fixture): user=user, table=table, type_name="number", - name="Test number field", - number_type="NOT_EXISTING", - ) - - with pytest.raises(ValueError): - handler.create_field( - user=user, - table=table, - type_name="number", - name="Test number field", - number_type="DECIMAL", + name="Test decimal with oversized decimal places value", number_decimal_places=9999, ) @@ -226,8 +216,7 @@ def test_create_field(send_mock, data_fixture): table=table, type_name="number", name="Test number field", - number_type="INTEGER", - number_decimal_places=2, + number_decimal_places=0, number_negative=True, ) @@ -235,8 +224,7 @@ def test_create_field(send_mock, data_fixture): assert number_field.name == "Test number field" assert number_field.order == 2 assert number_field.table == table - assert number_field.number_type == "INTEGER" - assert number_field.number_decimal_places == 2 + assert number_field.number_decimal_places == 0 assert number_field.number_negative handler.create_field( @@ -395,12 +383,12 @@ def test_update_field(send_mock, data_fixture): field=field, new_type_name="number", name="Number field", - number_type="INTEGER", + number_decimal_places=0, number_negative=False, ) assert field.name == "Number field" - assert field.number_type == "INTEGER" + assert field.number_decimal_places == 0 assert field.number_negative is False assert not hasattr(field, "text_default") @@ -416,13 +404,11 @@ def test_update_field(send_mock, data_fixture): field=field, new_type_name="number", name="Price field", - number_type="DECIMAL", number_decimal_places=2, number_negative=True, ) assert field.name == "Price field" - assert field.number_type == "DECIMAL" assert field.number_decimal_places == 2 assert field.number_negative is True @@ -439,7 +425,6 @@ def test_update_field(send_mock, data_fixture): field.refresh_from_db() assert field.name == "Active" - assert not hasattr(field, "number_type") assert not hasattr(field, "number_decimal_places") assert not hasattr(field, "number_negative") @@ -1077,7 +1062,7 @@ def test_can_convert_formula_to_numeric_field(data_fixture): field=existing_formula_field, new_type_name="number", name="Price field", - number_type="INTEGER", + number_decimal_places=0, number_negative=True, ) diff --git a/backend/tests/baserow/contrib/database/field/test_number_field_type.py b/backend/tests/baserow/contrib/database/field/test_number_field_type.py index 9f773ec1c..41f1e1334 100644 --- a/backend/tests/baserow/contrib/database/field/test_number_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_number_field_type.py @@ -5,7 +5,7 @@ from decimal import Decimal from django.contrib.contenttypes.models import ContentType from baserow.contrib.database.fields.handler import FieldHandler -from baserow.contrib.database.fields.models import NumberField, NUMBER_TYPE_DECIMAL +from baserow.contrib.database.fields.models import NumberField from baserow.contrib.database.fields.registries import field_type_registry @@ -29,7 +29,7 @@ from baserow.contrib.database.fields.registries import field_type_registry None, None, ], - {"number_type": "INTEGER", "number_negative": False}, + {"number_decimal_places": 0, "number_negative": False}, ), ( [ @@ -47,7 +47,7 @@ from baserow.contrib.database.fields.registries import field_type_registry None, None, ], - {"number_type": "INTEGER", "number_negative": True}, + {"number_decimal_places": 0, "number_negative": True}, ), ( [ @@ -66,7 +66,6 @@ from baserow.contrib.database.fields.registries import field_type_registry None, ], { - "number_type": "DECIMAL", "number_negative": False, "number_decimal_places": 1, }, @@ -88,7 +87,6 @@ from baserow.contrib.database.fields.registries import field_type_registry None, ], { - "number_type": "DECIMAL", "number_negative": True, "number_decimal_places": 3, }, @@ -139,7 +137,6 @@ def test_alter_number_field_column_type_negative(data_fixture): decimal_field = data_fixture.create_number_field( table=table, order=2, - number_type="DECIMAL", number_negative=True, number_decimal_places=2, ) @@ -170,7 +167,6 @@ def test_alter_number_field_column_type_negative(data_fixture): def test_import_export_number_field(data_fixture): number_field = data_fixture.create_number_field( name="Number field", - number_type="DECIMAL", number_negative=True, number_decimal_places=2, ) @@ -179,7 +175,6 @@ def test_import_export_number_field(data_fixture): number_field_imported = number_field_type.import_serialized( number_field.table, number_serialized, {} ) - assert number_field.number_type == number_field_imported.number_type assert number_field.number_negative == number_field_imported.number_negative assert number_field.number_decimal_places == ( number_field_imported.number_decimal_places @@ -192,7 +187,6 @@ def test_content_type_still_set_when_save_overridden(data_fixture): field = NumberField( number_negative=False, number_decimal_places=1, - number_type=NUMBER_TYPE_DECIMAL, order=1, table=table, ) diff --git a/backend/tests/baserow/contrib/database/field/test_rating_field_type.py b/backend/tests/baserow/contrib/database/field/test_rating_field_type.py index f4f9f8342..7f549e056 100644 --- a/backend/tests/baserow/contrib/database/field/test_rating_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_rating_field_type.py @@ -137,14 +137,14 @@ def test_rating_field_modification(data_fixture): integer_field = data_fixture.create_number_field( table=table, name="integer", - number_type="INTEGER", + number_decimal_places=0, number_negative=True, ) decimal_field = data_fixture.create_number_field( table=table, name="decimal", - number_type="DECIMAL", + number_decimal_places=1, number_negative=True, ) @@ -267,14 +267,13 @@ def test_rating_field_modification(data_fixture): user=user, field=integer_field, new_type_name="number", - number_type="INTEGER", + number_decimal_places=0, number_negative=True, ) field_handler.update_field( user=user, field=decimal_field, new_type_name="number", - number_type="DECIMAL", number_negative=True, number_decimal_places=2, ) diff --git a/backend/tests/baserow/contrib/database/rows/test_rows_handler.py b/backend/tests/baserow/contrib/database/rows/test_rows_handler.py index 170263765..462be52b3 100644 --- a/backend/tests/baserow/contrib/database/rows/test_rows_handler.py +++ b/backend/tests/baserow/contrib/database/rows/test_rows_handler.py @@ -121,7 +121,6 @@ def test_create_row(send_mock, data_fixture): price_field = data_fixture.create_number_field( table=table, name="Price", - number_type="DECIMAL", number_decimal_places=2, number_negative=False, ) @@ -258,7 +257,6 @@ def test_get_row(data_fixture): price_field = data_fixture.create_number_field( table=table, name="Price", - number_type="DECIMAL", number_decimal_places=2, number_negative=False, ) @@ -303,7 +301,6 @@ def test_update_row(send_mock, data_fixture): price_field = data_fixture.create_number_field( table=table, name="Price", - number_type="DECIMAL", number_decimal_places=2, number_negative=False, ) @@ -465,7 +462,6 @@ def test_restore_row(send_mock, data_fixture): price_field = data_fixture.create_number_field( table=table, name="Price", - number_type="DECIMAL", number_decimal_places=2, number_negative=False, ) @@ -565,7 +561,6 @@ def test_has_row(data_fixture): price_field = data_fixture.create_number_field( table=table, name="Price", - number_type="DECIMAL", number_decimal_places=2, number_negative=False, ) diff --git a/backend/tests/baserow/contrib/database/table/test_table_models.py b/backend/tests/baserow/contrib/database/table/test_table_models.py index c5b8ccda3..56c0282fb 100644 --- a/backend/tests/baserow/contrib/database/table/test_table_models.py +++ b/backend/tests/baserow/contrib/database/table/test_table_models.py @@ -75,7 +75,6 @@ def test_get_table_model(data_fixture): table=table_2, order=0, name="Sale price", - number_type="DECIMAL", number_decimal_places=3, number_negative=True, ) diff --git a/backend/tests/baserow/contrib/database/view/test_view_filters.py b/backend/tests/baserow/contrib/database/view/test_view_filters.py index 6b984b0b4..38b46e2bb 100644 --- a/backend/tests/baserow/contrib/database/view/test_view_filters.py +++ b/backend/tests/baserow/contrib/database/view/test_view_filters.py @@ -68,7 +68,7 @@ def test_equal_filter_type(data_fixture): long_text_field = data_fixture.create_long_text_field(table=table) integer_field = data_fixture.create_number_field(table=table) decimal_field = data_fixture.create_number_field( - table=table, number_type="DECIMAL", number_decimal_places=2 + table=table, number_decimal_places=2 ) boolean_field = data_fixture.create_boolean_field(table=table) formula_field = data_fixture.create_formula_field(table=table, formula="'test'") @@ -204,7 +204,7 @@ def test_not_equal_filter_type(data_fixture): long_text_field = data_fixture.create_long_text_field(table=table) integer_field = data_fixture.create_number_field(table=table) decimal_field = data_fixture.create_number_field( - table=table, number_type="DECIMAL", number_decimal_places=2 + table=table, number_decimal_places=2 ) boolean_field = data_fixture.create_boolean_field(table=table) formula_field = data_fixture.create_formula_field(table=table, formula="'test'") @@ -347,7 +347,6 @@ def test_contains_filter_type(data_fixture): ) number_field = data_fixture.create_number_field( table=table, - number_type="DECIMAL", number_negative=True, number_decimal_places=2, ) @@ -567,7 +566,6 @@ def test_contains_not_filter_type(data_fixture): ) number_field = data_fixture.create_number_field( table=table, - number_type="DECIMAL", number_negative=True, number_decimal_places=2, ) @@ -967,7 +965,6 @@ def test_higher_than_filter_type(data_fixture): integer_field = data_fixture.create_number_field(table=table, number_negative=True) decimal_field = data_fixture.create_number_field( table=table, - number_type="DECIMAL", number_decimal_places=2, number_negative=True, ) @@ -1118,7 +1115,6 @@ def test_lower_than_filter_type(data_fixture): integer_field = data_fixture.create_number_field(table=table, number_negative=True) decimal_field = data_fixture.create_number_field( table=table, - number_type="DECIMAL", number_decimal_places=2, number_negative=True, ) @@ -2214,7 +2210,7 @@ def test_empty_filter_type(data_fixture): long_text_field = data_fixture.create_long_text_field(table=table) integer_field = data_fixture.create_number_field(table=table) decimal_field = data_fixture.create_number_field( - table=table, number_type="DECIMAL", number_decimal_places=2 + table=table, number_decimal_places=2 ) date_field = data_fixture.create_date_field(table=table) date_time_field = data_fixture.create_date_field( @@ -2369,7 +2365,7 @@ def test_not_empty_filter_type(data_fixture): long_text_field = data_fixture.create_long_text_field(table=table) integer_field = data_fixture.create_number_field(table=table) decimal_field = data_fixture.create_number_field( - table=table, number_type="DECIMAL", number_decimal_places=2 + table=table, number_decimal_places=2 ) date_field = data_fixture.create_date_field(table=table) date_time_field = data_fixture.create_date_field( diff --git a/changelog.md b/changelog.md index f70aafa40..072ee40a0 100644 --- a/changelog.md +++ b/changelog.md @@ -16,6 +16,9 @@ tools, e.g. to various REST clients. * Added search to gallery views. * Views supporting search are properly updated when a column with a matching default value is added. +* **breaking change** Number field has been changed and doesn't use `number_type` property + anymore. The property `number_decimal_places` can be now set to `0` to indicate integers + instead. ## Released (2022-01-13 1.8.2) diff --git a/web-frontend/modules/database/components/field/FieldFormulaNumberSubForm.vue b/web-frontend/modules/database/components/field/FieldFormulaNumberSubForm.vue deleted file mode 100644 index d0177c7a3..000000000 --- a/web-frontend/modules/database/components/field/FieldFormulaNumberSubForm.vue +++ /dev/null @@ -1,87 +0,0 @@ -<template> - <div> - <div class="control"> - <label class="control__label control__label--small">{{ - $t('fieldFormulaNumberSubForm.typeLabel') - }}</label> - <div class="control__elements"> - <Dropdown - :class="{ 'dropdown--error': $v.numberType.$error }" - :value="numberType" - @input="changeNumberType($event)" - @hide="$v.numberType.$touch()" - > - <DropdownItem - :name="$t('fieldFormulaNumberSubForm.integer') + ' (1)'" - value="INTEGER" - ></DropdownItem> - <DropdownItem - :name="$t('fieldFormulaNumberSubForm.decimal') + ' (1.0)'" - value="DECIMAL" - ></DropdownItem> - </Dropdown> - </div> - </div> - <div v-show="numberType === 'DECIMAL'" class="control"> - <label class="control__label control__label--small">{{ - $t('fieldFormulaNumberSubForm.decimalPlacesLabel') - }}</label> - <div class="control__elements"> - <Dropdown - v-model="values.number_decimal_places" - :class="{ 'dropdown--error': $v.values.number_decimal_places.$error }" - @hide="$v.values.number_decimal_places.$touch()" - > - <DropdownItem name="1.0" :value="1"></DropdownItem> - <DropdownItem name="1.00" :value="2"></DropdownItem> - <DropdownItem name="1.000" :value="3"></DropdownItem> - <DropdownItem name="1.0000" :value="4"></DropdownItem> - <DropdownItem name="1.00000" :value="5"></DropdownItem> - </Dropdown> - </div> - </div> - </div> -</template> - -<script> -import { required } from 'vuelidate/lib/validators' - -import form from '@baserow/modules/core/mixins/form' - -import fieldSubForm from '@baserow/modules/database/mixins/fieldSubForm' - -export default { - name: 'FieldNumberSubForm', - mixins: [form, fieldSubForm], - data() { - return { - allowedValues: ['number_decimal_places'], - values: { - number_decimal_places: 0, - }, - } - }, - computed: { - numberType() { - return this.values.number_decimal_places === 0 ? 'INTEGER' : 'DECIMAL' - }, - }, - methods: { - changeNumberType(newValue) { - if (newValue === 'INTEGER') { - this.values.number_decimal_places = 0 - } else { - this.values.number_decimal_places = 1 - } - }, - }, - validations: { - values: { - number_decimal_places: { required }, - }, - numberType: { - required, - }, - }, -} -</script> diff --git a/web-frontend/modules/database/components/field/FieldNumberSubForm.vue b/web-frontend/modules/database/components/field/FieldNumberSubForm.vue index 1f797bb2b..4fca2d687 100644 --- a/web-frontend/modules/database/components/field/FieldNumberSubForm.vue +++ b/web-frontend/modules/database/components/field/FieldNumberSubForm.vue @@ -1,27 +1,6 @@ <template> <div> <div class="control"> - <label class="control__label control__label--small">{{ - $t('fieldNumberSubForm.typeLabel') - }}</label> - <div class="control__elements"> - <Dropdown - v-model="values.number_type" - :class="{ 'dropdown--error': $v.values.number_type.$error }" - @hide="$v.values.number_type.$touch()" - > - <DropdownItem - :name="$t('fieldNumberSubForm.integer') + ' (1)'" - value="INTEGER" - ></DropdownItem> - <DropdownItem - :name="$t('fieldNumberSubForm.decimal') + ' (1.0)'" - value="DECIMAL" - ></DropdownItem> - </Dropdown> - </div> - </div> - <div v-show="values.number_type === 'DECIMAL'" class="control"> <label class="control__label control__label--small">{{ $t('fieldNumberSubForm.decimalPlacesLabel') }}</label> @@ -31,15 +10,16 @@ :class="{ 'dropdown--error': $v.values.number_decimal_places.$error }" @hide="$v.values.number_decimal_places.$touch()" > - <DropdownItem name="1.0" :value="1"></DropdownItem> - <DropdownItem name="1.00" :value="2"></DropdownItem> - <DropdownItem name="1.000" :value="3"></DropdownItem> - <DropdownItem name="1.0000" :value="4"></DropdownItem> - <DropdownItem name="1.00000" :value="5"></DropdownItem> + <DropdownItem name="0 (1)" :value="0"></DropdownItem> + <DropdownItem name="1 (1.0)" :value="1"></DropdownItem> + <DropdownItem name="2 (1.00)" :value="2"></DropdownItem> + <DropdownItem name="3 (1.000)" :value="3"></DropdownItem> + <DropdownItem name="4 (1.0000)" :value="4"></DropdownItem> + <DropdownItem name="5 (1.00000)" :value="5"></DropdownItem> </Dropdown> </div> </div> - <div class="control"> + <div v-if="allowSetNumberNegative" class="control"> <div class="control__elements"> <Checkbox v-model="values.number_negative">{{ $t('fieldNumberSubForm.allowNegative') @@ -58,23 +38,29 @@ import fieldSubForm from '@baserow/modules/database/mixins/fieldSubForm' export default { name: 'FieldNumberSubForm', mixins: [form, fieldSubForm], + props: { + allowSetNumberNegative: { + type: Boolean, + required: false, + default: true, + }, + }, data() { + let allowedValues = ['number_decimal_places'] + let values = { number_decimal_places: 0 } + + if (this.allowSetNumberNegative) { + allowedValues = [...allowedValues, 'number_negative'] + values = { ...values, number_negative: false } + } + return { - allowedValues: [ - 'number_type', - 'number_decimal_places', - 'number_negative', - ], - values: { - number_type: 'INTEGER', - number_decimal_places: 1, - number_negative: false, - }, + allowedValues, + values, } }, validations: { values: { - number_type: { required }, number_decimal_places: { required }, }, }, diff --git a/web-frontend/modules/database/components/formula/FormulaTypeSubForms.vue b/web-frontend/modules/database/components/formula/FormulaTypeSubForms.vue index 38a0b991c..0db9d4bd3 100644 --- a/web-frontend/modules/database/components/formula/FormulaTypeSubForms.vue +++ b/web-frontend/modules/database/components/formula/FormulaTypeSubForms.vue @@ -1,11 +1,12 @@ <template> <div> - <FieldFormulaNumberSubForm + <FieldNumberSubForm v-if="formulaType === 'number'" :default-values="defaultValues" :table="table" + :allow-set-number-negative="false" > - </FieldFormulaNumberSubForm> + </FieldNumberSubForm> <FieldDateSubForm v-else-if="['date', 'last_modified', 'created_on'].includes(formulaType)" :default-values="defaultValues" @@ -15,14 +16,14 @@ </div> </template> <script> -import FieldFormulaNumberSubForm from '@baserow/modules/database/components/field/FieldFormulaNumberSubForm' +import FieldNumberSubForm from '@baserow/modules/database/components/field/FieldNumberSubForm' import FieldDateSubForm from '@baserow/modules/database/components/field/FieldDateSubForm' import form from '@baserow/modules/core/mixins/form' import fieldSubForm from '@baserow/modules/database/mixins/fieldSubForm' export default { name: 'FormulaTypeSubForms', - components: { FieldFormulaNumberSubForm, FieldDateSubForm }, + components: { FieldNumberSubForm, FieldDateSubForm }, mixins: [form, fieldSubForm], props: { table: { diff --git a/web-frontend/modules/database/fieldTypes.js b/web-frontend/modules/database/fieldTypes.js index b175257ae..ade983c85 100644 --- a/web-frontend/modules/database/fieldTypes.js +++ b/web-frontend/modules/database/fieldTypes.js @@ -865,21 +865,19 @@ export class NumberFieldType extends FieldType { if (value === '' || isNaN(value) || value === undefined || value === null) { return null } - const decimalPlaces = - field.number_type === 'DECIMAL' ? field.number_decimal_places : 0 let number = new BigNumber(value) if (!field.number_negative && number.isLessThan(0)) { number = 0 } - return number.toFixed(decimalPlaces) + return number.toFixed(field.number_decimal_places) } getDocsDataType(field) { - return field.number_type === 'DECIMAL' ? 'decimal' : 'number' + return field.number_decimal_places > 0 ? 'decimal' : 'number' } getDocsDescription(field) { - let t = field.number_type === 'INTEGER' ? 'number' : 'decimal' + let t = field.number_decimal_places === 0 ? 'number' : 'decimal' if (!field.number_negative) { t += 'Positive' } @@ -889,7 +887,7 @@ export class NumberFieldType extends FieldType { } getDocsRequestExample(field) { - if (field.number_type === 'DECIMAL') { + if (field.number_decimal_places > 0) { let number = '0.' for (let i = 1; i <= field.number_decimal_places; i++) { number += '0' diff --git a/web-frontend/test/unit/database/fieldTypes.spec.js b/web-frontend/test/unit/database/fieldTypes.spec.js index 3f1316ebe..9c5947e0b 100644 --- a/web-frontend/test/unit/database/fieldTypes.spec.js +++ b/web-frontend/test/unit/database/fieldTypes.spec.js @@ -35,9 +35,8 @@ const mockedFields = { primary: false, table_id: 42, type: 'number', - number_decimal_places: 1, + number_decimal_places: 0, number_negative: false, - number_type: 'INTEGER', }, rating: { id: 16,