Arthur 2 روز پیش
والد
کامیت
0d14cd8cd8

+ 32 - 7
netbox/circuits/migrations/0061_generated_fields.py

@@ -1,8 +1,9 @@
-# Generated by Django 6.1.2 on 2026-10-13 23:27
+# Generated by Django 6.1.2 on 2026-10-14 00:11
 
 from decimal import Decimal
 
 import django.db.models.expressions
+import django.db.models.functions.comparison
 from django.db import migrations, models
 
 
@@ -28,37 +29,61 @@ class Migration(migrations.Migration):
                     models.When(
                         distance_unit="km",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("1000"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1000")),
                         ),
                     ),
                     models.When(
                         distance_unit="m",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         distance_unit="cm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("0.01"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("0.01")),
                         ),
                     ),
                     models.When(
                         distance_unit="mi",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("1609.344"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1609.344")),
                         ),
                     ),
                     models.When(
                         distance_unit="ft",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("0.3048"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("0.3048")),
                         ),
                     ),
                     models.When(
                         distance_unit="in",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("0.0254"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("0.0254")),
                         ),
                     ),
                 ),

+ 228 - 52
netbox/dcim/migrations/0252_generated_fields.py

@@ -1,4 +1,4 @@
-# Generated by Django 6.1.2 on 2026-10-13 23:27
+# Generated by Django 6.1.2 on 2026-10-14 00:11
 
 from decimal import Decimal
 
@@ -30,37 +30,61 @@ class Migration(migrations.Migration):
                     models.When(
                         length_unit="km",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("length"), "*", models.Value(Decimal("1000"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("length"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1000")),
                         ),
                     ),
                     models.When(
                         length_unit="m",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("length"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("length"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         length_unit="cm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("length"), "*", models.Value(Decimal("0.01"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("length"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("0.01")),
                         ),
                     ),
                     models.When(
                         length_unit="mi",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("length"), "*", models.Value(Decimal("1609.344"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("length"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1609.344")),
                         ),
                     ),
                     models.When(
                         length_unit="ft",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("length"), "*", models.Value(Decimal("0.3048"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("length"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("0.3048")),
                         ),
                     ),
                     models.When(
                         length_unit="in",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("length"), "*", models.Value(Decimal("0.0254"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("length"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("0.0254")),
                         ),
                     ),
                 ),
@@ -83,13 +107,19 @@ class Migration(migrations.Migration):
                     models.When(
                         max_flow_unit="lpm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("max_flow"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("max_flow"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         max_flow_unit="m3ph",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("max_flow"),
+                            django.db.models.functions.comparison.Cast(
+                                models.F("max_flow"), output_field=models.DecimalField()
+                            ),
                             "*",
                             models.Value(Decimal("16.66666666666666666666666667")),
                         ),
@@ -97,7 +127,9 @@ class Migration(migrations.Migration):
                     models.When(
                         max_flow_unit="gpm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("max_flow"),
+                            django.db.models.functions.comparison.Cast(
+                                models.F("max_flow"), output_field=models.DecimalField()
+                            ),
                             "*",
                             models.Value(Decimal("3.785411784")),
                         ),
@@ -122,19 +154,31 @@ class Migration(migrations.Migration):
                     models.When(
                         diameter_unit="mm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         diameter_unit="cm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("10"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("10")),
                         ),
                     ),
                     models.When(
                         diameter_unit="in",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("25.4"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("25.4")),
                         ),
                     ),
                 ),
@@ -157,13 +201,19 @@ class Migration(migrations.Migration):
                     models.When(
                         max_flow_unit="lpm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("max_flow"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("max_flow"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         max_flow_unit="m3ph",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("max_flow"),
+                            django.db.models.functions.comparison.Cast(
+                                models.F("max_flow"), output_field=models.DecimalField()
+                            ),
                             "*",
                             models.Value(Decimal("16.66666666666666666666666667")),
                         ),
@@ -171,7 +221,9 @@ class Migration(migrations.Migration):
                     models.When(
                         max_flow_unit="gpm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("max_flow"),
+                            django.db.models.functions.comparison.Cast(
+                                models.F("max_flow"), output_field=models.DecimalField()
+                            ),
                             "*",
                             models.Value(Decimal("3.785411784")),
                         ),
@@ -196,19 +248,31 @@ class Migration(migrations.Migration):
                     models.When(
                         diameter_unit="mm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         diameter_unit="cm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("10"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("10")),
                         ),
                     ),
                     models.When(
                         diameter_unit="in",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("25.4"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("25.4")),
                         ),
                     ),
                 ),
@@ -231,13 +295,19 @@ class Migration(migrations.Migration):
                     models.When(
                         max_flow_unit="lpm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("max_flow"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("max_flow"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         max_flow_unit="m3ph",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("max_flow"),
+                            django.db.models.functions.comparison.Cast(
+                                models.F("max_flow"), output_field=models.DecimalField()
+                            ),
                             "*",
                             models.Value(Decimal("16.66666666666666666666666667")),
                         ),
@@ -245,7 +315,9 @@ class Migration(migrations.Migration):
                     models.When(
                         max_flow_unit="gpm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("max_flow"),
+                            django.db.models.functions.comparison.Cast(
+                                models.F("max_flow"), output_field=models.DecimalField()
+                            ),
                             "*",
                             models.Value(Decimal("3.785411784")),
                         ),
@@ -270,19 +342,31 @@ class Migration(migrations.Migration):
                     models.When(
                         diameter_unit="mm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         diameter_unit="cm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("10"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("10")),
                         ),
                     ),
                     models.When(
                         diameter_unit="in",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("25.4"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("25.4")),
                         ),
                     ),
                 ),
@@ -305,19 +389,31 @@ class Migration(migrations.Migration):
                     models.When(
                         diameter_unit="mm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         diameter_unit="cm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("10"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("10")),
                         ),
                     ),
                     models.When(
                         diameter_unit="in",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("diameter"), "*", models.Value(Decimal("25.4"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("diameter"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("25.4")),
                         ),
                     ),
                 ),
@@ -341,7 +437,10 @@ class Migration(migrations.Migration):
                         models.Case(
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("1000")),
                                 ),
@@ -349,13 +448,21 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"), "*", models.Value(Decimal("1"))
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
+                                    "*",
+                                    models.Value(Decimal("1")),
                                 ),
                                 weight_unit="g",
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("453.592")),
                                 ),
@@ -363,7 +470,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("28.3495")),
                                 ),
@@ -391,7 +501,10 @@ class Migration(migrations.Migration):
                         models.Case(
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("1000")),
                                 ),
@@ -399,13 +512,21 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"), "*", models.Value(Decimal("1"))
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
+                                    "*",
+                                    models.Value(Decimal("1")),
                                 ),
                                 weight_unit="g",
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("453.592")),
                                 ),
@@ -413,7 +534,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("28.3495")),
                                 ),
@@ -441,7 +565,10 @@ class Migration(migrations.Migration):
                         models.Case(
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("max_weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("max_weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("1000")),
                                 ),
@@ -449,7 +576,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("max_weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("max_weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("1")),
                                 ),
@@ -457,7 +587,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("max_weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("max_weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("453.592")),
                                 ),
@@ -465,7 +598,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("max_weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("max_weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("28.3495")),
                                 ),
@@ -493,7 +629,10 @@ class Migration(migrations.Migration):
                         models.Case(
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("1000")),
                                 ),
@@ -501,13 +640,21 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"), "*", models.Value(Decimal("1"))
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
+                                    "*",
+                                    models.Value(Decimal("1")),
                                 ),
                                 weight_unit="g",
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("453.592")),
                                 ),
@@ -515,7 +662,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("28.3495")),
                                 ),
@@ -543,7 +693,10 @@ class Migration(migrations.Migration):
                         models.Case(
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("max_weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("max_weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("1000")),
                                 ),
@@ -551,7 +704,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("max_weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("max_weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("1")),
                                 ),
@@ -559,7 +715,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("max_weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("max_weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("453.592")),
                                 ),
@@ -567,7 +726,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("max_weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("max_weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("28.3495")),
                                 ),
@@ -595,7 +757,10 @@ class Migration(migrations.Migration):
                         models.Case(
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("1000")),
                                 ),
@@ -603,13 +768,21 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"), "*", models.Value(Decimal("1"))
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
+                                    "*",
+                                    models.Value(Decimal("1")),
                                 ),
                                 weight_unit="g",
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("453.592")),
                                 ),
@@ -617,7 +790,10 @@ class Migration(migrations.Migration):
                             ),
                             models.When(
                                 then=django.db.models.expressions.CombinedExpression(
-                                    models.F("weight"),
+                                    django.db.models.functions.comparison.Cast(
+                                        models.F("weight"),
+                                        output_field=models.DecimalField(),
+                                    ),
                                     "*",
                                     models.Value(Decimal("28.3495")),
                                 ),

+ 14 - 9
netbox/utilities/conversion.py

@@ -1,6 +1,6 @@
-from decimal import Decimal, InvalidOperation
+from decimal import ROUND_HALF_UP, Decimal, InvalidOperation
 
-from django.db.models import BigIntegerField, Case, F, Value, When
+from django.db.models import BigIntegerField, Case, DecimalField, F, Value, When
 from django.db.models.functions import Cast, Floor
 from django.utils.translation import gettext as _
 
@@ -28,9 +28,9 @@ __all__ = (
 # Conversion factors
 #
 
-# Each mapping gives the exact multiplier from a unit to its base unit. The to_*() helpers and the GeneratedField
-# expressions built by normalized_unit_expression() both read these, so changing a factor (or adding a unit) requires
-# a migration to drop and re-add the affected generated columns.
+# Each mapping gives the multiplier from a unit to its base unit as a Decimal literal. The to_*() helpers and the
+# GeneratedField expressions built by normalized_unit_expression() both read these, so changing a factor (or adding
+# a unit) requires a migration to drop and re-add the affected generated columns.
 WEIGHT_TO_GRAMS = {
     WeightUnitChoices.UNIT_KILOGRAM: Decimal('1000'),
     WeightUnitChoices.UNIT_GRAM: Decimal('1'),
@@ -56,7 +56,7 @@ DIAMETER_TO_MILLIMETERS = {
 
 FLOW_RATE_TO_LITERS_PER_MINUTE = {
     FlowRateUnitChoices.UNIT_LITERS_PER_MINUTE: Decimal('1'),
-    FlowRateUnitChoices.UNIT_CUBIC_METERS_PER_HOUR: Decimal('1000') / Decimal('60'),
+    FlowRateUnitChoices.UNIT_CUBIC_METERS_PER_HOUR: Decimal('16.66666666666666666666666667'),  # 1000 / 60
     FlowRateUnitChoices.UNIT_GALLONS_PER_MINUTE: Decimal('3.785411784'),
 }
 
@@ -71,8 +71,10 @@ def normalized_unit_expression(value_field, unit_field, factors, integer=False):
     per the given mapping of unit to factor. Evaluates to NULL if either field is NULL or the unit is unrecognized.
     With `integer=True`, the result is truncated to a whole number (as to_grams() does) and cast to a bigint.
     """
+    # Cast to numeric so that an integer source column cannot overflow integer arithmetic
+    value = Cast(F(value_field), output_field=DecimalField())
     expression = Case(*[
-        When(**{unit_field: unit}, then=F(value_field) * Value(factor))
+        When(**{unit_field: unit}, then=value * Value(factor))
         for unit, factor in factors.items()
     ])
     if integer:
@@ -89,7 +91,8 @@ def _normalized_measurement(value, unit, factors, quantity, precision=4) -> Deci
     Shared implementation for the unit-normalization helpers below. Coerce `value` to a non-negative
     Decimal, multiply by the factor for `unit`, and round the result to `precision` decimal places.
     `factors` maps each valid unit to its multiplier; `quantity` labels the value in error messages.
-    Pass `precision=None` to return the unrounded result.
+    Pass `precision=None` to return the unrounded result. Rounding is half away from zero, matching how
+    PostgreSQL stores the same result in a generated numeric column.
     """
     try:
         value = Decimal(value)
@@ -107,7 +110,9 @@ def _normalized_measurement(value, unit, factors, quantity, precision=4) -> Deci
             )
         )
     result = value * factors[unit]
-    return result if precision is None else round(result, precision)
+    if precision is None:
+        return result
+    return result.quantize(Decimal(1).scaleb(-precision), rounding=ROUND_HALF_UP)
 
 
 def to_grams(weight, unit) -> int:

+ 12 - 0
netbox/utilities/testing/mixins.py

@@ -106,6 +106,18 @@ class NormalizedMeasurementTestMixin:
                 self.assertEqual(getattr(instance, self.normalized_field), self.converter(self.value, unit))
                 self.assertNormalized(instance, self.value, unit)
 
+    def test_save_existing(self):
+        instance = self.create_instance()
+        instance.save()
+        for unit in self.units:
+            with self.subTest(unit=unit):
+                setattr(instance, self.value_field, self.value)
+                setattr(instance, self.unit_field, unit)
+                instance.save()
+                # An UPDATE also returns the computed value, so change logging sees the current value
+                self.assertEqual(getattr(instance, self.normalized_field), self.converter(self.value, unit))
+                self.assertNormalized(instance, self.value, unit)
+
     def test_update(self):
         instance = self.create_instance()
         instance.save()

+ 5 - 0
netbox/utilities/tests/test_conversions.py

@@ -110,6 +110,11 @@ class ConversionsTestCase(TestCase):
             to_meters(1, CableLengthUnitChoices.UNIT_INCH),
             Decimal('0.0254')
         )
+        # Ties round half away from zero, matching the generated database columns
+        self.assertEqual(
+            to_meters(Decimal('0.75'), CableLengthUnitChoices.UNIT_INCH),
+            Decimal('0.0191')
+        )
 
     def test_to_millimeters(self):
         self.assertEqual(

+ 32 - 7
netbox/wireless/migrations/0025_generated_fields.py

@@ -1,8 +1,9 @@
-# Generated by Django 6.1.2 on 2026-10-13 23:27
+# Generated by Django 6.1.2 on 2026-10-14 00:11
 
 from decimal import Decimal
 
 import django.db.models.expressions
+import django.db.models.functions.comparison
 from django.db import migrations, models
 
 
@@ -28,37 +29,61 @@ class Migration(migrations.Migration):
                     models.When(
                         distance_unit="km",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("1000"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1000")),
                         ),
                     ),
                     models.When(
                         distance_unit="m",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("1"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1")),
                         ),
                     ),
                     models.When(
                         distance_unit="cm",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("0.01"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("0.01")),
                         ),
                     ),
                     models.When(
                         distance_unit="mi",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("1609.344"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("1609.344")),
                         ),
                     ),
                     models.When(
                         distance_unit="ft",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("0.3048"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("0.3048")),
                         ),
                     ),
                     models.When(
                         distance_unit="in",
                         then=django.db.models.expressions.CombinedExpression(
-                            models.F("distance"), "*", models.Value(Decimal("0.0254"))
+                            django.db.models.functions.comparison.Cast(
+                                models.F("distance"), output_field=models.DecimalField()
+                            ),
+                            "*",
+                            models.Value(Decimal("0.0254")),
                         ),
                     ),
                 ),