You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ofbiz.apache.org by "Pranay Pandey (Jira)" <ji...@apache.org> on 2026/08/25 06:15:00 UTC

[jira] [Updated] (OFBIZ-13503) Auto-generated indicator (Y/N) fields silently default to "Y" and overwrite a NULL value on unrelated form saves

     [ https://issues.apache.org/jira/browse/OFBIZ-13503?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Pranay Pandey updated OFBIZ-13503:
----------------------------------
    Description: 
*Problem*

{{ModelFormFieldBuilder.induceFieldInfoFromEntityField()}} builds the auto-generated {{<drop-down>}} control for an {{{}indicator{}}}-type entity field differently depending on context:
 * For {{find}} forms, the option list includes a blank option:

{quote}^{{{{List<OptionSource> optionSources = UtilMisc.toList(}}}}^
^{{{{new ModelFormField.SingleOption("", null, null),}}}}^
^{{{{new ModelFormField.SingleOption("Y", null, null),}}}}^
^{{{{new ModelFormField.SingleOption("N", null, null));}}}}^ 
{quote} * For {{{}create{}}}/{{{}update{}}} forms, it does not:

{quote}~{{List<OptionSource> optionSources = UtilMisc.toList(}}~

{{~new ModelFormField.SingleOption("Y", null, null),~}}
{{~new ModelFormField.SingleOption("N", null, null));~}}
{quote}
When the underlying column is nullable and its current value is {{NULL}} (no default-value, never set by demo/seed data), the rendered {{<select>}} has no option matching the current value, so the browser falls back to highlighting the first {{<option>}} — "Y". Submitting the form for _any_ reason, including editing a completely unrelated field, then silently persists {{"Y"}} into a column that was previously unset.

*Concrete reproduction*

{{ProductStore.allocateInventory}} is a nullable {{indicator}} field with no default value, left {{NULL}} by demo data. {{EditProductStore}} ({{{}applications/product/widget/catalog/StoreForms.xml{}}}) picks it up via {{<auto-fields-service service-name="updateProductStore"/>}} with no explicit {{<field>}} override. Editing any other Product Store field and saving flips {{allocateInventory}} from {{NULL}} to {{{}Y{}}}, which quietly disables inventory reservation for sales order items unless they carry {{autoReserve=true}} ({{{}OrderServices.reserveInventory(){}}}).

Note: {{allocateInventory}} itself already has a narrower, pre-existing fix (OFBIZ-12001 / PR #1237) that forces the field's _display_ default to "N" via {{no-current-selected-key="N"}} on an explicit {{<field>}} override. That addresses the symptom for this one field (and changes which value gets silently written from Y to N), but does not address the general framework-level gap: any other nullable {{indicator}} field picked up through entity/service auto-fields with no explicit override is equally exposed to a null-to-non-null value being silently written on an unrelated save.

*Proposed Improvement (framework-level)*
 * In {{{}ModelFormFieldBuilder.induceFieldInfoFromEntityField(){}}}, add the blank {{SingleOption}} to the create/update branch as well, gated on {{!modelField.getIsNotNull()}} — so a genuinely {{NOT NULL}} column without an explicit override still gets a forced real default, while nullable columns preserve {{NULL}} when untouched.
 * In {{{}GenericEntity.set(){}}}, normalize a blank string submitted for an {{{}indicator{}}}-typed field to {{null}} before it reaches the datastore, so the blank option round-trips as {{NULL}} rather than being persisted as {{{}""{}}}.
 * Add unit test coverage in {{ModelFormFieldBuilderTest}} for: nullable indicator → blank/Y/N options on update forms; {{NOT NULL}} indicator → Y/N only; find forms → always blank/Y/N (unchanged).

*Discussion*

Raised on [dev@ofbiz.apache.org|mailto:dev@ofbiz.apache.org] ("[DISCUSS] Auto-generated indicator fields silently default to first <option> (Y/N) when unset - framework-level fix?", 2026-08-24). Community feedback (Divesh Dutta) favored the framework-level fix over a per-field patch, since the per-field approach doesn't prevent recurrence for other entities' nullable indicator fields.

*Related:* OFBIZ-12001 (PR #1237) — prior narrower fix for {{ProductStore.allocateInventory}} display default.

  was:
*Problem*

{{ModelFormFieldBuilder.induceFieldInfoFromEntityField()}} builds the auto-generated {{<drop-down>}} control for an {{{}indicator{}}}-type entity field differently depending on context:
 * For {{find}} forms, the option list includes a blank option:

{quote}{{List<OptionSource> optionSources = UtilMisc.toList(}}
{{new ModelFormField.SingleOption("", null, null),}}
{{new ModelFormField.SingleOption("Y", null, null),}}
{{new ModelFormField.SingleOption("N", null, null)); }}
{quote}
* For {{{}create{}}}/{{{}update{}}} forms, it does not:
{quote}{{~List<OptionSource> optionSources = UtilMisc.toList(~}}
{{~new ModelFormField.SingleOption("Y", null, null),~}}
{{~new ModelFormField.SingleOption("N", null, null));~}}
{quote}
When the underlying column is nullable and its current value is {{NULL}} (no default-value, never set by demo/seed data), the rendered {{<select>}} has no option matching the current value, so the browser falls back to highlighting the first {{<option>}} — "Y". Submitting the form for _any_ reason, including editing a completely unrelated field, then silently persists {{"Y"}} into a column that was previously unset.

*Concrete reproduction*

{{ProductStore.allocateInventory}} is a nullable {{indicator}} field with no default value, left {{NULL}} by demo data. {{EditProductStore}} ({{{}applications/product/widget/catalog/StoreForms.xml{}}}) picks it up via {{<auto-fields-service service-name="updateProductStore"/>}} with no explicit {{<field>}} override. Editing any other Product Store field and saving flips {{allocateInventory}} from {{NULL}} to {{{}Y{}}}, which quietly disables inventory reservation for sales order items unless they carry {{autoReserve=true}} ({{{}OrderServices.reserveInventory(){}}}).

Note: {{allocateInventory}} itself already has a narrower, pre-existing fix (OFBIZ-12001 / PR #1237) that forces the field's _display_ default to "N" via {{no-current-selected-key="N"}} on an explicit {{<field>}} override. That addresses the symptom for this one field (and changes which value gets silently written from Y to N), but does not address the general framework-level gap: any other nullable {{indicator}} field picked up through entity/service auto-fields with no explicit override is equally exposed to a null-to-non-null value being silently written on an unrelated save.

*Proposed Improvement (framework-level)*
 * In {{{}ModelFormFieldBuilder.induceFieldInfoFromEntityField(){}}}, add the blank {{SingleOption}} to the create/update branch as well, gated on {{!modelField.getIsNotNull()}} — so a genuinely {{NOT NULL}} column without an explicit override still gets a forced real default, while nullable columns preserve {{NULL}} when untouched.
 * In {{{}GenericEntity.set(){}}}, normalize a blank string submitted for an {{{}indicator{}}}-typed field to {{null}} before it reaches the datastore, so the blank option round-trips as {{NULL}} rather than being persisted as {{{}""{}}}.
 * Add unit test coverage in {{ModelFormFieldBuilderTest}} for: nullable indicator → blank/Y/N options on update forms; {{NOT NULL}} indicator → Y/N only; find forms → always blank/Y/N (unchanged).

*Discussion*

Raised on [dev@ofbiz.apache.org|mailto:dev@ofbiz.apache.org] ("[DISCUSS] Auto-generated indicator fields silently default to first <option> (Y/N) when unset - framework-level fix?", 2026-08-24). Community feedback (Divesh Dutta) favored the framework-level fix over a per-field patch, since the per-field approach doesn't prevent recurrence for other entities' nullable indicator fields.

*Related:* OFBIZ-12001 (PR #1237) — prior narrower fix for {{ProductStore.allocateInventory}} display default.


> Auto-generated indicator (Y/N) fields silently default to "Y" and overwrite a NULL value on unrelated form saves
> ----------------------------------------------------------------------------------------------------------------
>
>                 Key: OFBIZ-13503
>                 URL: https://issues.apache.org/jira/browse/OFBIZ-13503
>             Project: OFBiz
>          Issue Type: Improvement
>          Components: framework/widget
>    Affects Versions: Upcoming Branch
>            Reporter: Pranay Pandey
>            Assignee: Pranay Pandey
>            Priority: Major
>             Fix For: Upcoming Branch
>
>
> *Problem*
> {{ModelFormFieldBuilder.induceFieldInfoFromEntityField()}} builds the auto-generated {{<drop-down>}} control for an {{{}indicator{}}}-type entity field differently depending on context:
>  * For {{find}} forms, the option list includes a blank option:
> {quote}^{{{{List<OptionSource> optionSources = UtilMisc.toList(}}}}^
> ^{{{{new ModelFormField.SingleOption("", null, null),}}}}^
> ^{{{{new ModelFormField.SingleOption("Y", null, null),}}}}^
> ^{{{{new ModelFormField.SingleOption("N", null, null));}}}}^ 
> {quote} * For {{{}create{}}}/{{{}update{}}} forms, it does not:
> {quote}~{{List<OptionSource> optionSources = UtilMisc.toList(}}~
> {{~new ModelFormField.SingleOption("Y", null, null),~}}
> {{~new ModelFormField.SingleOption("N", null, null));~}}
> {quote}
> When the underlying column is nullable and its current value is {{NULL}} (no default-value, never set by demo/seed data), the rendered {{<select>}} has no option matching the current value, so the browser falls back to highlighting the first {{<option>}} — "Y". Submitting the form for _any_ reason, including editing a completely unrelated field, then silently persists {{"Y"}} into a column that was previously unset.
> *Concrete reproduction*
> {{ProductStore.allocateInventory}} is a nullable {{indicator}} field with no default value, left {{NULL}} by demo data. {{EditProductStore}} ({{{}applications/product/widget/catalog/StoreForms.xml{}}}) picks it up via {{<auto-fields-service service-name="updateProductStore"/>}} with no explicit {{<field>}} override. Editing any other Product Store field and saving flips {{allocateInventory}} from {{NULL}} to {{{}Y{}}}, which quietly disables inventory reservation for sales order items unless they carry {{autoReserve=true}} ({{{}OrderServices.reserveInventory(){}}}).
> Note: {{allocateInventory}} itself already has a narrower, pre-existing fix (OFBIZ-12001 / PR #1237) that forces the field's _display_ default to "N" via {{no-current-selected-key="N"}} on an explicit {{<field>}} override. That addresses the symptom for this one field (and changes which value gets silently written from Y to N), but does not address the general framework-level gap: any other nullable {{indicator}} field picked up through entity/service auto-fields with no explicit override is equally exposed to a null-to-non-null value being silently written on an unrelated save.
> *Proposed Improvement (framework-level)*
>  * In {{{}ModelFormFieldBuilder.induceFieldInfoFromEntityField(){}}}, add the blank {{SingleOption}} to the create/update branch as well, gated on {{!modelField.getIsNotNull()}} — so a genuinely {{NOT NULL}} column without an explicit override still gets a forced real default, while nullable columns preserve {{NULL}} when untouched.
>  * In {{{}GenericEntity.set(){}}}, normalize a blank string submitted for an {{{}indicator{}}}-typed field to {{null}} before it reaches the datastore, so the blank option round-trips as {{NULL}} rather than being persisted as {{{}""{}}}.
>  * Add unit test coverage in {{ModelFormFieldBuilderTest}} for: nullable indicator → blank/Y/N options on update forms; {{NOT NULL}} indicator → Y/N only; find forms → always blank/Y/N (unchanged).
> *Discussion*
> Raised on [dev@ofbiz.apache.org|mailto:dev@ofbiz.apache.org] ("[DISCUSS] Auto-generated indicator fields silently default to first <option> (Y/N) when unset - framework-level fix?", 2026-08-24). Community feedback (Divesh Dutta) favored the framework-level fix over a per-field patch, since the per-field approach doesn't prevent recurrence for other entities' nullable indicator fields.
> *Related:* OFBIZ-12001 (PR #1237) — prior narrower fix for {{ProductStore.allocateInventory}} display default.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)