You need to sign in or sign up before continuing.
Fix Form.proxifyField creating inconsistent proxy fields
When `Form.proxifyField` is used to make a proxy field from a field which has only a TALES and no value, it creates a proxy field with inconsistent internal data structures where `has_value` method does not work as expected. As a consequence, proxy fields to list fields are often broken in the ods/odt rendering.
Here is a scenario to reproduce the problem:
* add `Base_viewDummyFieldLibrary` ERP5 Form
* add a `LinesField`, with id `your_test_base_field`. Change `size` to 1 (not really required but I did this in screenshots here)
* add another `LinesField`, with id `your_test_field` and in this field:
* set a `default` (`2`) in values, it's only needed to visualise the problem in ods style:

* set `items` in TALES (`python: [('one', '1'), ('two', '2')]`) , this will be the problem

* So far, when this is rendered as ODS, everything is fine:

this is also what we see in html style view: 
* use the proxify action, to make `your_test_field` be a proxy field to `your_test_base_field`

* result of proxify action looks good, both for values:
 and for TALES:

* but after this rendering the form with ODS becomes broken:
 even though it looks fine with html views.
`erp5_ods_style` knows how to render list fields and it uses the "display" (two) and not the "value" (2), this is done [here](https://lab.nexedi.com/nexedi/erp5/blob/451ce4137dc1d006bc2cd155535523d51a928150/bt5/erp5_ods_style/SkinTemplateItem/portal_skins/erp5_ods_style/field_ods_macro.zpt#L60) with a check depending on `field.has_value("items")`.
`has_value` is implemented like [this](https://lab.nexedi.com/nexedi/erp5/blob/451ce4137dc1d006bc2cd155535523d51a928150/product/ERP5Form/ProxyField.py#L598-611) for proxy fields:
```python
def has_value(self, id):
"""
Return true if the field defines such a value.
"""
result = None
if (id in self.widget.property_names) or \
(not self.is_delegated(id)):
result = ZMIField.has_value(self, id)
else:
proxy_field = self.getTemplateField()
if proxy_field is not None:
result = proxy_field.has_value(id)
return result
```
and like [this](https://lab.nexedi.com/nexedi/erp5/blob/451ce4137dc1d006bc2cd155535523d51a928150/product/Formulator/Field.py#L80-86) for traditional fields:
```python
def has_value(self, id):
"""Return true if the field defines such a value.
"""
if self.values.has_key(id) or self.form.has_field(id):
return 1
else:
return 0
```
when the value is defined on the proxy field and not delegated to template field, the condition is `self.values.has_key(id)`.
But `Form.proxifyField` when transforming a traditional field in a proxy field does not keep the `id` in `self.values` if it's only needed in `self.tales`. This is the root cause of this problem, if we inspect the field, it is something like this:
```
(Pdb) self
<ProxyField at /erp5/portal_skins/custom/Base_viewDummyFieldLibrary/your_test_field>
(Pdb) pp self.tales
{'field_id': '',
'form_id': '',
'items': <Products.Formulator.TALESField.TALESMethod object at 0x7ffa705c7450 oid 0x572626 in <Connection at 7ffa42c1a610>>}
(Pdb) pp self.values
{'default': '2',
'field_id': 'your_test_base_field',
'form_id': 'Base_viewDummyFieldLibrary',
'title': 'Test Field'}
(Pdb) self.has_value('items')
0
(Pdb)
```
If we edit the proxy field, it will repair itself, because the proxy field edit method maintain `self.tales` and `self.values` consistent, but this is not the case with`Form.proxifyField`, which mutate directly `.tales` and `.values` and can make them have different keys - which is not supposed to happen.
The problem is that most of the proxy fields we have have been generated by `Form.proxifyField`, so for most of our fields the XML data of business template has this inconsistency. We could have took the easy way and make change `ProxyField.has_value` to understand this case, but it's probably better to fix the data.
`erp5_hal_json` also uses `field.has_value` in some places, so it's better to fix at field level and not to address this in `erp5_ods_style` and `erp5_odt_style`.
These changes:
- add a little more test coverage for `ProxyField.has_value` ( at first I thought the problem was only in `has_value`)
- Fix `Form.proxifyField`
- add a `ProxyField.checkConsistency` to check that `.values` and `.tales` are in sync - or more exactly that all entries from `.tales` are also in `.values`, because this is what cause the problem with `has_value`.
- re-export all proxy fields after cleaning up their `.values` and `.tales`, using `checkConsistency(fixit=True)` on all proxy fields.
See merge request !1352