mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 20:55:42 +00:00 
			
		
		
		
	Format number fix (#10710)
* Improvements for format_number func - Prevent accidental rendering in scientific notation * Add multiplier argument to format_number
This commit is contained in:
		| @@ -607,6 +607,7 @@ def render_html_text(text: str, **kwargs): | |||||||
| def format_number( | def format_number( | ||||||
|     number: Union[int, float, Decimal], |     number: Union[int, float, Decimal], | ||||||
|     decimal_places: Optional[int] = None, |     decimal_places: Optional[int] = None, | ||||||
|  |     multiplier: Optional[Union[int, float, Decimal]] = None, | ||||||
|     integer: bool = False, |     integer: bool = False, | ||||||
|     leading: int = 0, |     leading: int = 0, | ||||||
|     separator: Optional[str] = None, |     separator: Optional[str] = None, | ||||||
| @@ -616,16 +617,20 @@ def format_number( | |||||||
|     Arguments: |     Arguments: | ||||||
|         number: The number to be formatted |         number: The number to be formatted | ||||||
|         decimal_places: Number of decimal places to render |         decimal_places: Number of decimal places to render | ||||||
|  |         multiplier: Optional multiplier to apply to the number before formatting | ||||||
|         integer: Boolean, whether to render the number as an integer |         integer: Boolean, whether to render the number as an integer | ||||||
|         leading: Number of leading zeros (default = 0) |         leading: Number of leading zeros (default = 0) | ||||||
|         separator: Character to use as a thousands separator (default = None) |         separator: Character to use as a thousands separator (default = None) | ||||||
|     """ |     """ | ||||||
|     try: |     try: | ||||||
|         number = Decimal(str(number)) |         number = Decimal(str(number).strip()) | ||||||
|     except Exception: |     except Exception: | ||||||
|         # If the number cannot be converted to a Decimal, just return the original value |         # If the number cannot be converted to a Decimal, just return the original value | ||||||
|         return str(number) |         return str(number) | ||||||
|  |  | ||||||
|  |     if multiplier is not None: | ||||||
|  |         number *= Decimal(str(multiplier).strip()) | ||||||
|  |  | ||||||
|     if integer: |     if integer: | ||||||
|         # Convert to integer |         # Convert to integer | ||||||
|         number = Decimal(int(number)) |         number = Decimal(int(number)) | ||||||
| @@ -641,7 +646,13 @@ def format_number( | |||||||
|             pass |             pass | ||||||
|  |  | ||||||
|     # Re-encode, and normalize again |     # Re-encode, and normalize again | ||||||
|     value = Decimal(number).normalize() |     # Ensure that the output never uses scientific notation | ||||||
|  |     value = Decimal(number) | ||||||
|  |     value = ( | ||||||
|  |         value.quantize(Decimal(1)) | ||||||
|  |         if value == value.to_integral() | ||||||
|  |         else value.normalize() | ||||||
|  |     ) | ||||||
|  |  | ||||||
|     if separator: |     if separator: | ||||||
|         value = f'{value:,}' |         value = f'{value:,}' | ||||||
|   | |||||||
| @@ -270,6 +270,14 @@ class ReportTagTest(PartImageTestMixin, InvenTreeTestCase): | |||||||
|         """Simple tests for number formatting tags.""" |         """Simple tests for number formatting tags.""" | ||||||
|         fn = report_tags.format_number |         fn = report_tags.format_number | ||||||
|  |  | ||||||
|  |         self.assertEqual(fn(None), 'None') | ||||||
|  |  | ||||||
|  |         for i in [1, '1', '1.0000', '  1  ']: | ||||||
|  |             self.assertEqual(fn(i), '1') | ||||||
|  |  | ||||||
|  |         for x in ['10.000000', '  10  ', 10.000000, 10]: | ||||||
|  |             self.assertEqual(fn(x), '10') | ||||||
|  |  | ||||||
|         self.assertEqual(fn(1234), '1234') |         self.assertEqual(fn(1234), '1234') | ||||||
|         self.assertEqual(fn(1234.5678, decimal_places=2), '1234.57') |         self.assertEqual(fn(1234.5678, decimal_places=2), '1234.57') | ||||||
|         self.assertEqual(fn(1234.5678, decimal_places=3), '1234.568') |         self.assertEqual(fn(1234.5678, decimal_places=3), '1234.568') | ||||||
| @@ -278,6 +286,9 @@ class ReportTagTest(PartImageTestMixin, InvenTreeTestCase): | |||||||
|             fn(9988776655.4321, integer=True, separator=' '), '9 988 776 655' |             fn(9988776655.4321, integer=True, separator=' '), '9 988 776 655' | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |         # Test with multiplier | ||||||
|  |         self.assertEqual(fn(1000, multiplier=1.5), '1500') | ||||||
|  |  | ||||||
|         # Failure cases |         # Failure cases | ||||||
|         self.assertEqual(fn('abc'), 'abc') |         self.assertEqual(fn('abc'), 'abc') | ||||||
|         self.assertEqual(fn(1234.456, decimal_places='a'), '1234.456') |         self.assertEqual(fn(1234.456, decimal_places='a'), '1234.456') | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user