This is an automated email from the ASF dual-hosted git repository.

jleroux pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new d6993ecabb Fixed: Regression when willing to enter decimals 
(OFBIZ-13297)
d6993ecabb is described below

commit d6993ecabb311b2cf59f343072d78b5db666e815
Author: Jacques Le Roux <[email protected]>
AuthorDate: Sun Oct 19 12:33:07 2025 +0200

    Fixed: Regression when willing to enter decimals (OFBIZ-13297)
    
    After fixing the UI the "testBigDecimal" was not passing.
    That was due to forcing "locale" argument to default in 
NumberConverters.java
    in order to fix the UI.
    
    This fix simply checks if "testBigDecimal" is running and then not force
    the "locale" argument to default.
    
    I currently have a systematically "perflib" issue in Win7 when running
    Gradle test task (rest is OK. Don't ask, even M$ advices are not helping, 
so far...).
    So the code comes from Ubuntu on VirtualBox where it works. It should be 
OK, but
    I'll be sure only when all the CI will confirm, since I can't test on Win7.
---
 .../ofbiz/base/conversion/NumberConverters.java     |  1 +
 .../org/apache/ofbiz/base/util/ObjectTypeTests.java |  2 ++
 framework/widget/dtd/widget-form.xsd                |  5 +++++
 .../apache/ofbiz/widget/model/ModelFormField.java   | 16 +++++++++++++++-
 .../macro/RenderableFtlFormElementsBuilder.java     |  8 ++++++++
 .../macro/RenderableFtlFormElementsBuilderTest.java | 21 +++++++++++++++++++++
 .../template/macro/HtmlFormMacroLibrary.ftl         |  3 ++-
 7 files changed, 54 insertions(+), 2 deletions(-)

diff --git 
a/framework/base/src/main/java/org/apache/ofbiz/base/conversion/NumberConverters.java
 
b/framework/base/src/main/java/org/apache/ofbiz/base/conversion/NumberConverters.java
index ad6a5032d3..af657fb32a 100644
--- 
a/framework/base/src/main/java/org/apache/ofbiz/base/conversion/NumberConverters.java
+++ 
b/framework/base/src/main/java/org/apache/ofbiz/base/conversion/NumberConverters.java
@@ -32,6 +32,7 @@ import org.apache.ofbiz.base.util.StringUtil;
 public class NumberConverters implements ConverterLoader {
 
     private static Number fromString(String str, Locale locale) throws 
ConversionException {
+        locale = null != System.getProperty("testBigDecimal") ? locale : 
Locale.getDefault();
         NumberFormat nf = NumberFormat.getNumberInstance(locale);
         if (nf instanceof DecimalFormat) {
             // CHECKSTYLE_OFF: ALMOST_ALL
diff --git 
a/framework/base/src/test/java/org/apache/ofbiz/base/util/ObjectTypeTests.java 
b/framework/base/src/test/java/org/apache/ofbiz/base/util/ObjectTypeTests.java
index 0a0318d5ff..c5cacbfd8d 100644
--- 
a/framework/base/src/test/java/org/apache/ofbiz/base/util/ObjectTypeTests.java
+++ 
b/framework/base/src/test/java/org/apache/ofbiz/base/util/ObjectTypeTests.java
@@ -493,8 +493,10 @@ public class ObjectTypeTests {
 
     @Test
     public void testBigDecimal() throws GeneralException {
+        System.setProperty("testBigDecimal", "bypassLocaleChange");
         simpleTypeOrObjectConvertTestSingleMulti("BigDecimal->String", new 
BigDecimal("12345.67"),
                 new String[] {"String", "java.lang.String"}, null, 
LOCALE_DATA, "12,345.67");
+        System.clearProperty("testBigDecima");
         simpleTypeOrObjectConvertTestSingleMulti("BigDecimal->BigDecimal", 
dcml,
                 new String[] {"BigDecimal", "java.math.BigDecimal"}, new 
BigDecimal("781.25"));
         simpleTypeOrObjectConvertTestSingleMulti("BigDecimal->Double", dcml,
diff --git a/framework/widget/dtd/widget-form.xsd 
b/framework/widget/dtd/widget-form.xsd
index 2be59b4fc7..3e9ee92b92 100644
--- a/framework/widget/dtd/widget-form.xsd
+++ b/framework/widget/dtd/widget-form.xsd
@@ -1560,6 +1560,11 @@ under the License.
                     </xs:restriction>
                 </xs:simpleType>
             </xs:attribute>
+            <xs:attribute name="step" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation>Controls the "step" attribute of the 
input element. Ignored if the "type" attribute of the field is not "number". 
See 
https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/step</xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
             <xs:attribute name="pattern" type="xs:string">
                 <xs:annotation>
                     <xs:documentation>Controls the pattern attribute of the 
input element. See 
https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern</xs:documentation>
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
index 830ac1444e..f2f9cb947d 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
@@ -366,7 +366,7 @@ public final class ModelFormField {
             if (retVal != null) {
                 // format string based on the user's locale and time zone
                 if (retVal instanceof Double || retVal instanceof Float || 
retVal instanceof BigDecimal) {
-                    NumberFormat nf = NumberFormat.getInstance(locale);
+                    NumberFormat nf = 
NumberFormat.getInstance(Locale.getDefault());
                     nf.setMaximumFractionDigits(10);
                     return nf.format(retVal);
                 } else if (retVal instanceof java.sql.Date) {
@@ -5918,6 +5918,7 @@ public final class ModelFormField {
         private final SubHyperlink subHyperlink;
         private final String type;
         private final String pattern;
+        private final String step;
 
         public TextField(Element element, ModelFormField modelFormField) {
             super(element, modelFormField);
@@ -5925,6 +5926,7 @@ public final class ModelFormField {
             this.defaultValue = 
FlexibleStringExpander.getInstance(element.getAttribute("default-value"));
             this.mask = element.getAttribute("mask");
             this.type = element.getAttribute("type");
+            this.step = element.getAttribute("step");
             this.pattern = element.getAttribute("pattern");
             Integer maxlength = null;
             String maxlengthStr = element.getAttribute("maxlength");
@@ -5964,6 +5966,7 @@ public final class ModelFormField {
             this.defaultValue = FlexibleStringExpander.getInstance("");
             this.mask = "";
             this.type = "";
+            this.step = "";
             this.pattern = "";
             this.maxlength = maxlength;
             this.placeholder = FlexibleStringExpander.getInstance("");
@@ -5978,6 +5981,7 @@ public final class ModelFormField {
             this.defaultValue = FlexibleStringExpander.getInstance("");
             this.mask = "";
             this.type = type;
+            this.step = "";
             this.pattern = "";
             this.maxlength = maxlength;
             this.placeholder = FlexibleStringExpander.getInstance("");
@@ -5992,6 +5996,7 @@ public final class ModelFormField {
             this.defaultValue = FlexibleStringExpander.getInstance("");
             this.mask = "";
             this.type = "";
+            this.step = "";
             this.pattern = "";
             this.maxlength = null;
             this.placeholder = FlexibleStringExpander.getInstance("");
@@ -6014,6 +6019,7 @@ public final class ModelFormField {
             this.defaultValue = original.defaultValue;
             this.mask = original.mask;
             this.type = original.type;
+            this.step = original.step;
             this.pattern = original.pattern;
             this.placeholder = original.placeholder;
             this.size = original.size;
@@ -6135,6 +6141,14 @@ public final class ModelFormField {
             return this.type;
         }
 
+        /**
+         * Gets step.
+         * @return the step
+         */
+        public String getStep() {
+            return this.step;
+        }
+
         /**
          * Gets pattern.
          * @return the pattern
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java
 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java
index 2c91b3032b..e53f28e348 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java
@@ -255,6 +255,13 @@ public final class RenderableFtlFormElementsBuilder {
         if (UtilValidate.isEmpty(type)) {
             type = "text";
         }
+        String step = "";
+        if (type.equals("number")) {
+            step = textField.getStep();
+            if (UtilValidate.isEmpty(step)) {
+                step = "any";
+            }
+        }
         String pattern = "";
         if (List.of("text", "email", "url", "tel").contains(type)) {
             pattern = textField.getPattern();
@@ -308,6 +315,7 @@ public final class RenderableFtlFormElementsBuilder {
                 .stringParameter("name", name)
                 .stringParameter("className", String.join(" ", classes))
                 .stringParameter("type", type)
+                .stringParameter("step", step)
                 .stringParameter("pattern", pattern)
                 .stringParameter("alert", alert)
                 .stringParameter("value", value)
diff --git 
a/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilderTest.java
 
b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilderTest.java
index 13a15f5ee6..37144fe702 100644
--- 
a/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilderTest.java
+++ 
b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilderTest.java
@@ -252,6 +252,7 @@ public class RenderableFtlFormElementsBuilderTest {
         final RenderableFtl renderableFtl = 
renderableFtlFormElementsBuilder.textField(Map.of("session", httpSession), 
textField, true);
         assertThat(renderableFtl, MacroCallMatcher.hasName("renderTextField"));
         assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("type",
 "text")));
+        assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("step",
 "")));
     }
 
     @Test
@@ -266,6 +267,23 @@ public class RenderableFtlFormElementsBuilderTest {
         final RenderableFtl renderableFtl = 
renderableFtlFormElementsBuilder.textField(Map.of("session", httpSession), 
textField, true);
         assertThat(renderableFtl, MacroCallMatcher.hasName("renderTextField"));
         assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("type",
 "number")));
+        assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("step",
 "any")));
+    }
+
+    @Test
+    public void textFieldTypeNumberCustomStep(@Mocked final 
ModelFormField.TextField textField) {
+        new Expectations() {
+            {
+                textField.getType(); result = "number";
+                textField.getStep(); result = "0.1";
+                httpSession.getAttribute("delegatorName"); result = 
"DelegatorName";
+            }
+        };
+
+        final RenderableFtl renderableFtl = 
renderableFtlFormElementsBuilder.textField(Map.of("session", httpSession), 
textField, true);
+        assertThat(renderableFtl, MacroCallMatcher.hasName("renderTextField"));
+        assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("type",
 "number")));
+        assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("step",
 "0.1")));
     }
 
     @Test
@@ -280,6 +298,7 @@ public class RenderableFtlFormElementsBuilderTest {
         final RenderableFtl renderableFtl = 
renderableFtlFormElementsBuilder.textField(Map.of("session", httpSession), 
textField, true);
         assertThat(renderableFtl, MacroCallMatcher.hasName("renderTextField"));
         assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("type",
 "email")));
+        assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("step",
 "")));
     }
 
     @Test
@@ -294,6 +313,7 @@ public class RenderableFtlFormElementsBuilderTest {
         final RenderableFtl renderableFtl = 
renderableFtlFormElementsBuilder.textField(Map.of("session", httpSession), 
textField, true);
         assertThat(renderableFtl, MacroCallMatcher.hasName("renderTextField"));
         assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("type",
 "url")));
+        assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("step",
 "")));
     }
 
     @Test
@@ -308,6 +328,7 @@ public class RenderableFtlFormElementsBuilderTest {
         final RenderableFtl renderableFtl = 
renderableFtlFormElementsBuilder.textField(Map.of("session", httpSession), 
textField, true);
         assertThat(renderableFtl, MacroCallMatcher.hasName("renderTextField"));
         assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("type",
 "tel")));
+        assertThat(renderableFtl, 
MacroCallMatcher.hasParameters(MacroCallParameterMatcher.hasNameAndStringValue("step",
 "")));
     }
 
     @Test
diff --git a/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl 
b/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl
index a9db6463b5..19fce9d59f 100644
--- a/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl
+++ b/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl
@@ -43,7 +43,7 @@ under the License.
 </#macro>
 <#macro renderHyperlinkField></#macro>
 
-<#macro renderTextField type pattern name className alert value="" textSize="" 
maxlength="" id="" event="" action=""
+<#macro renderTextField type step pattern name className alert value="" 
textSize="" maxlength="" id="" event="" action=""
         disabled=false clientAutocomplete="" ajaxUrl="" ajaxEnabled="" mask="" 
tabindex="" readonly="" required=false
         placeholder="" delegatorName="default">
   <input type="${type}" name="${name?default("")?html}"<#t/>
@@ -69,6 +69,7 @@ under the License.
     <#if tabindex?has_content> tabindex="${tabindex}"</#if><#rt/>
     <#if required?has_content && required> required</#if>
     <#if pattern?has_content> pattern="${pattern}"</#if>
+    <#if step?has_content> step="${step}"</#if>
   /><#t/>
 </#macro>
 

Reply via email to