mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge pull request #7758 from jibees/7710-manage-comma-as-decimal-separator-in-unit-value-field
[UnitPrice] Manage comma as decimal separator in unit value field
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
angular.module("admin.products")
|
||||
.controller "unitsCtrl", ($scope, VariantUnitManager, OptionValueNamer, UnitPrices) ->
|
||||
.controller "unitsCtrl", ($scope, VariantUnitManager, OptionValueNamer, UnitPrices, PriceParser) ->
|
||||
$scope.product = { master: {} }
|
||||
$scope.product.master.product = $scope.product
|
||||
$scope.placeholder_text = ""
|
||||
@@ -26,9 +26,9 @@ angular.module("admin.products")
|
||||
|
||||
$scope.processUnitValueWithDescription = ->
|
||||
if $scope.product.master.hasOwnProperty("unit_value_with_description")
|
||||
match = $scope.product.master.unit_value_with_description.match(/^([\d\.]+(?= *|$)|)( *)(.*)$/)
|
||||
match = $scope.product.master.unit_value_with_description.match(/^([\d\.,]+(?= *|$)|)( *)(.*)$/)
|
||||
if match
|
||||
$scope.product.master.unit_value = parseFloat(match[1])
|
||||
$scope.product.master.unit_value = PriceParser.parse(match[1])
|
||||
$scope.product.master.unit_value = null if isNaN($scope.product.master.unit_value)
|
||||
$scope.product.master.unit_value *= $scope.product.variant_unit_scale if $scope.product.master.unit_value && $scope.product.variant_unit_scale
|
||||
$scope.product.master.unit_description = match[3]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.products").controller "variantUnitsCtrl", ($scope, VariantUnitManager, $timeout, UnitPrices) ->
|
||||
angular.module("admin.products").controller "variantUnitsCtrl", ($scope, VariantUnitManager, $timeout, UnitPrices, PriceParser) ->
|
||||
|
||||
$scope.unitName = (scale, type) ->
|
||||
VariantUnitManager.getUnitName(scale, type)
|
||||
@@ -23,7 +23,7 @@ angular.module("admin.products").controller "variantUnitsCtrl", ($scope, Variant
|
||||
|
||||
$scope.updateValue = ->
|
||||
unit_value_human = angular.element('#unit_value_human').val()
|
||||
$scope.unit_value = unit_value_human * $scope.scale
|
||||
$scope.unit_value = PriceParser.parse(unit_value_human) * $scope.scale
|
||||
|
||||
variant_unit_value = angular.element('#variant_unit_value').val()
|
||||
$scope.unit_value_human = variant_unit_value / $scope.scale
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
angular.module("admin.products").factory "UnitPrices", (VariantUnitManager, localizeCurrencyFilter, unlocalizeCurrencyFilter) ->
|
||||
angular.module("admin.products").factory "UnitPrices", (VariantUnitManager, localizeCurrencyFilter, PriceParser) ->
|
||||
class UnitPrices
|
||||
@displayableUnitPrice: (price, scale, unit_type, unit_value, variant_unit_name) ->
|
||||
price = unlocalizeCurrencyFilter(price)
|
||||
price = PriceParser.parse(price)
|
||||
if price && !isNaN(price) && unit_type && unit_value
|
||||
value = localizeCurrencyFilter(UnitPrices.price(price, scale, unit_type, unit_value, variant_unit_name))
|
||||
unit = UnitPrices.unit(scale, unit_type, variant_unit_name)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
angular.module("admin.utils").filter "unlocalizeCurrency", ()->
|
||||
# Convert string to number using injected currency configuration.
|
||||
(price) ->
|
||||
# used decimal and thousands separators from currency configuration
|
||||
decimal_separator = I18n.toCurrency(.1, {precision: 1, unit: ''}).substring(1,2)
|
||||
thousands_separator = I18n.toCurrency(1000, {precision: 1, unit: ''}).substring(1,2)
|
||||
|
||||
if (price.length > 4)
|
||||
# remove configured thousands separator if price is greater than 999
|
||||
price = price.replaceAll(thousands_separator, '')
|
||||
|
||||
if (decimal_separator == ",")
|
||||
price = price.replace(",", ".")
|
||||
|
||||
return parseFloat(price)
|
||||
@@ -0,0 +1,31 @@
|
||||
angular.module("admin.utils").factory "PriceParser", ->
|
||||
new class PriceParser
|
||||
parse: (price) =>
|
||||
return null unless price
|
||||
# used decimal and thousands separators from currency configuration
|
||||
decimal_separator = I18n.toCurrency(.1, {precision: 1, unit: ''}).substring(1,2)
|
||||
thousands_separator = I18n.toCurrency(1000, {precision: 1, unit: ''}).substring(1,2)
|
||||
|
||||
# Replace comma used as a decimal separator and remplace by "."
|
||||
price = this.replaceCommaByFinalPoint(price)
|
||||
|
||||
# Remove configured thousands separator if it is actually a thousands separator
|
||||
price = this.removeThousandsSeparator(price, thousands_separator)
|
||||
|
||||
if (decimal_separator == ",")
|
||||
price = price.replace(",", ".")
|
||||
|
||||
price = parseFloat(price)
|
||||
|
||||
return null if isNaN(price)
|
||||
|
||||
return price
|
||||
|
||||
replaceCommaByFinalPoint : (price) =>
|
||||
if price.match(/^[0-9]*(,{1})[0-9]{1,2}$/g) then price.replace(",", ".") else price
|
||||
|
||||
removeThousandsSeparator : (price, thousands_separator) =>
|
||||
if (new RegExp("^([0-9]*(" + thousands_separator + "{1})[0-9]{3}[0-9\.,]*)*$", "g").test(price))
|
||||
price.replaceAll(thousands_separator, '')
|
||||
else
|
||||
price
|
||||
@@ -1,91 +0,0 @@
|
||||
describe 'convert string to number with configurated currency', ->
|
||||
filter = null
|
||||
|
||||
beforeEach ->
|
||||
module 'ofn.admin'
|
||||
inject ($filter) ->
|
||||
filter = $filter('unlocalizeCurrency')
|
||||
|
||||
describe "with point as decimal separator and comma as thousands separator for I18n service", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(I18n,'toCurrency').and.callFake (arg) ->
|
||||
if (arg == 0.1)
|
||||
return "0.1"
|
||||
else if (arg == 1000)
|
||||
return "1,000"
|
||||
|
||||
it "handle point as decimal separator", ->
|
||||
expect(filter("1.00")).toEqual 1.0
|
||||
|
||||
it "handle point as decimal separator", ->
|
||||
expect(filter("1.000")).toEqual 1.0
|
||||
|
||||
it "also handle comma as decimal separator", ->
|
||||
expect(filter("1,00")).toEqual 1.0
|
||||
|
||||
it "handle point as decimal separator and comma as thousands separator", ->
|
||||
expect(filter("1,000,000.00")).toEqual 1000000
|
||||
|
||||
it "handle integer number", ->
|
||||
expect(filter("10")).toEqual 10
|
||||
|
||||
it "handle integer number with comma as thousands separator", ->
|
||||
expect(filter("1,000")).toEqual 1000
|
||||
|
||||
it "handle integer number with no thousands separator", ->
|
||||
expect(filter("1000")).toEqual 1000
|
||||
|
||||
describe "with comma as decimal separator and final point as thousands separator for I18n service", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(I18n,'toCurrency').and.callFake (arg) ->
|
||||
if (arg == 0.1)
|
||||
return "0,1"
|
||||
else if (arg == 1000)
|
||||
return "1.000"
|
||||
|
||||
it "handle comma as decimal separator", ->
|
||||
expect(filter("1,00")).toEqual 1.0
|
||||
|
||||
it "also handle point as decimal separator", ->
|
||||
expect(filter("1.00")).toEqual 1.0
|
||||
|
||||
it "handle point as decimal separator and final point as thousands separator", ->
|
||||
expect(filter("1.000.000,00")).toEqual 1000000
|
||||
|
||||
it "handle integer number", ->
|
||||
expect(filter("10")).toEqual 10
|
||||
|
||||
it "handle integer number with final point as thousands separator", ->
|
||||
expect(filter("1.000")).toEqual 1000
|
||||
|
||||
it "handle integer number with no thousands separator", ->
|
||||
expect(filter("1000")).toEqual 1000
|
||||
|
||||
describe "with comma as decimal separator and space as thousands separator for I18n service", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(I18n,'toCurrency').and.callFake (arg) ->
|
||||
if (arg == 0.1)
|
||||
return "0,1"
|
||||
else if (arg == 1000)
|
||||
return "1 000"
|
||||
|
||||
it "handle comma as decimal separator", ->
|
||||
expect(filter("1,00")).toEqual 1.0
|
||||
|
||||
it "also handle final point as decimal separator", ->
|
||||
expect(filter("1.00")).toEqual 1.0
|
||||
|
||||
it "handle point as decimal separator and space as thousands separator", ->
|
||||
expect(filter("1 000 000,00")).toEqual 1000000
|
||||
|
||||
it "handle integer number", ->
|
||||
expect(filter("10")).toEqual 10
|
||||
|
||||
it "handle integer number with space as thousands separator", ->
|
||||
expect(filter("1 000")).toEqual 1000
|
||||
|
||||
it "handle integer number with no thousands separator", ->
|
||||
expect(filter("1000")).toEqual 1000
|
||||
@@ -75,3 +75,21 @@ describe "unitsCtrl", ->
|
||||
scope.processUnitValueWithDescription()
|
||||
expect(scope.product.master.unit_value).toEqual 123
|
||||
expect(scope.product.master.unit_description).toEqual "54 boxes"
|
||||
|
||||
it "handle final point as decimal separator", ->
|
||||
scope.product.master.unit_value_with_description = "22.22"
|
||||
scope.processUnitValueWithDescription()
|
||||
expect(scope.product.master.unit_value).toEqual 22.22
|
||||
expect(scope.product.master.unit_description).toEqual ""
|
||||
|
||||
it "handle comma as decimal separator", ->
|
||||
scope.product.master.unit_value_with_description = "22,22"
|
||||
scope.processUnitValueWithDescription()
|
||||
expect(scope.product.master.unit_value).toEqual 22.22
|
||||
expect(scope.product.master.unit_description).toEqual ""
|
||||
|
||||
it "handle comma as decimal separator with description", ->
|
||||
scope.product.master.unit_value_with_description = "22,22 things"
|
||||
scope.processUnitValueWithDescription()
|
||||
expect(scope.product.master.unit_value).toEqual 22.22
|
||||
expect(scope.product.master.unit_description).toEqual "things"
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
describe "PriceParser service", ->
|
||||
priceParser = null
|
||||
|
||||
beforeEach ->
|
||||
module('admin.utils')
|
||||
inject (PriceParser) ->
|
||||
priceParser = PriceParser
|
||||
|
||||
describe "test internal method with Regexp", ->
|
||||
describe "test replaceCommaByFinalPoint() method", ->
|
||||
it "handle the default case (with two numbers after comma)", ->
|
||||
expect(priceParser.replaceCommaByFinalPoint("1,00")).toEqual "1.00"
|
||||
it "doesn't confuse with thousands separator", ->
|
||||
expect(priceParser.replaceCommaByFinalPoint("1,000")).toEqual "1,000"
|
||||
it "handle also when there is only one number after the decimal separator", ->
|
||||
expect(priceParser.replaceCommaByFinalPoint("1,0")).toEqual "1.0"
|
||||
describe "test removeThousandsSeparator() method", ->
|
||||
it "handle the default case", ->
|
||||
expect(priceParser.removeThousandsSeparator("1,000", ",")).toEqual "1000"
|
||||
expect(priceParser.removeThousandsSeparator("1,000,000", ",")).toEqual "1000000"
|
||||
it "handle the case with decimal separator", ->
|
||||
expect(priceParser.removeThousandsSeparator("1,000,000.00", ",")).toEqual "1000000.00"
|
||||
it "handle the case when it is actually a decimal separator (and not a thousands one)", ->
|
||||
expect(priceParser.removeThousandsSeparator("1,00", ",")).toEqual "1,00"
|
||||
|
||||
describe "with point as decimal separator and comma as thousands separator for I18n service", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(I18n,'toCurrency').and.callFake (arg) ->
|
||||
if (arg == 0.1)
|
||||
return "0.1"
|
||||
else if (arg == 1000)
|
||||
return "1,000"
|
||||
|
||||
it "handle point as decimal separator", ->
|
||||
expect(priceParser.parse("1.00")).toEqual 1.0
|
||||
|
||||
it "handle point as decimal separator", ->
|
||||
expect(priceParser.parse("1.000")).toEqual 1.0
|
||||
|
||||
it "also handle comma as decimal separator", ->
|
||||
expect(priceParser.parse("1,0")).toEqual 1.0
|
||||
|
||||
it "also handle comma as decimal separator", ->
|
||||
expect(priceParser.parse("1,00")).toEqual 1.0
|
||||
|
||||
it "also handle comma as decimal separator", ->
|
||||
expect(priceParser.parse("11,00")).toEqual 11.0
|
||||
|
||||
it "handle comma as decimal separator but not confusing with thousands separator", ->
|
||||
expect(priceParser.parse("11,000")).toEqual 11000
|
||||
|
||||
it "handle point as decimal separator and comma as thousands separator", ->
|
||||
expect(priceParser.parse("1,000,000.00")).toEqual 1000000
|
||||
|
||||
it "handle integer number", ->
|
||||
expect(priceParser.parse("10")).toEqual 10
|
||||
|
||||
it "handle integer number with comma as thousands separator", ->
|
||||
expect(priceParser.parse("1,000")).toEqual 1000
|
||||
|
||||
it "handle integer number with no thousands separator", ->
|
||||
expect(priceParser.parse("1000")).toEqual 1000
|
||||
|
||||
describe "with comma as decimal separator and final point as thousands separator for I18n service", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(I18n,'toCurrency').and.callFake (arg) ->
|
||||
if (arg == 0.1)
|
||||
return "0,1"
|
||||
else if (arg == 1000)
|
||||
return "1.000"
|
||||
|
||||
it "handle comma as decimal separator", ->
|
||||
expect(priceParser.parse("1,00")).toEqual 1.0
|
||||
|
||||
it "handle comma as decimal separator with one digit after the comma", ->
|
||||
expect(priceParser.parse("11,0")).toEqual 11.0
|
||||
|
||||
it "handle comma as decimal separator with two digit after the comma", ->
|
||||
expect(priceParser.parse("11,00")).toEqual 11.0
|
||||
|
||||
it "handle comma as decimal separator with three digit after the comma", ->
|
||||
expect(priceParser.parse("11,000")).toEqual 11.0
|
||||
|
||||
it "also handle point as decimal separator", ->
|
||||
expect(priceParser.parse("1.00")).toEqual 1.0
|
||||
|
||||
it "also handle point as decimal separator with integer part with two digits", ->
|
||||
expect(priceParser.parse("11.00")).toEqual 11.0
|
||||
|
||||
it "handle point as decimal separator and final point as thousands separator", ->
|
||||
expect(priceParser.parse("1.000.000,00")).toEqual 1000000
|
||||
|
||||
it "handle integer number", ->
|
||||
expect(priceParser.parse("10")).toEqual 10
|
||||
|
||||
it "handle integer number with final point as thousands separator", ->
|
||||
expect(priceParser.parse("1.000")).toEqual 1000
|
||||
|
||||
it "handle integer number with no thousands separator", ->
|
||||
expect(priceParser.parse("1000")).toEqual 1000
|
||||
|
||||
describe "with comma as decimal separator and space as thousands separator for I18n service", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(I18n,'toCurrency').and.callFake (arg) ->
|
||||
if (arg == 0.1)
|
||||
return "0,1"
|
||||
else if (arg == 1000)
|
||||
return "1 000"
|
||||
|
||||
it "handle comma as decimal separator", ->
|
||||
expect(priceParser.parse("1,00")).toEqual 1.0
|
||||
|
||||
it "handle comma as decimal separator with one digit after the comma", ->
|
||||
expect(priceParser.parse("11,0")).toEqual 11.0
|
||||
|
||||
it "handle comma as decimal separator with two digit after the comma", ->
|
||||
expect(priceParser.parse("11,00")).toEqual 11.0
|
||||
|
||||
it "handle comma as decimal separator with three digit after the comma", ->
|
||||
expect(priceParser.parse("11,000")).toEqual 11.0
|
||||
|
||||
it "also handle final point as decimal separator", ->
|
||||
expect(priceParser.parse("1.00")).toEqual 1.0
|
||||
|
||||
it "also handle final point as decimal separator with integer part with two digits", ->
|
||||
expect(priceParser.parse("11.00")).toEqual 11.0
|
||||
|
||||
it "handle point as decimal separator and space as thousands separator", ->
|
||||
expect(priceParser.parse("1 000 000,00")).toEqual 1000000
|
||||
|
||||
it "handle integer number", ->
|
||||
expect(priceParser.parse("10")).toEqual 10
|
||||
|
||||
it "handle integer number with space as thousands separator", ->
|
||||
expect(priceParser.parse("1 000")).toEqual 1000
|
||||
|
||||
it "handle integer number with no thousands separator", ->
|
||||
expect(priceParser.parse("1000")).toEqual 1000
|
||||
|
||||
describe "handle null/undefined case", ->
|
||||
it "null case", ->
|
||||
expect(priceParser.parse(null)).toEqual null
|
||||
|
||||
it "undefined case ", ->
|
||||
expect(priceParser.parse(undefined)).toEqual null
|
||||
|
||||
it "wtf case", ->
|
||||
expect(priceParser.parse("wtf")).toEqual null
|
||||
|
||||
Reference in New Issue
Block a user