diff --git a/README.md b/README.md index 18d1c5d..50333c9 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,11 @@ To install with pip, simply: pip install odooshow ``` -## Known issues / Roadmap +## Known issues -- Make an Odoo module so we can plug the funcionality directly into the model abstract. -- Subfield values (AKA dynamic related values) -- Congigurable column totals. Now we're getting them from the field info. - Better support for OdooRPC. + +## Roadmap + +- Make an Odoo module so we can plug the funcionality directly into the model abstract. +- Configurable column totals. Now we're getting them from the field info. diff --git a/odooshow/__init__.py b/odooshow/__init__.py index 1af7290..12bc210 100644 --- a/odooshow/__init__.py +++ b/odooshow/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.5.1" +__version__ = "0.6.0" __author__ = "David Vidal" __email__ = "chienandalu@gmail.com" __doc__ = """A library to give goggles when diving into the Odoo Shell""" diff --git a/odooshow/odooshow.py b/odooshow/odooshow.py index fe0e903..9fb8c2e 100644 --- a/odooshow/odooshow.py +++ b/odooshow/odooshow.py @@ -20,6 +20,23 @@ __all__ = ["show", "show_read"] +def unpack_values(method): + """Decorator to unpack related field values""" + + def _unpack_value(*args): + if isinstance(args[1], list): + return " / ".join([method(args[0], x, *args[2:]) for x in args[1]]) + + def wrapper(*args, **kwargs): + res = _unpack_value(*args) + if res: + return res + res = method(*args, **kwargs) + return res + + return wrapper + + class OdooShow(object): """Trying to make Odoo devs' life easier!""" @@ -73,6 +90,11 @@ def _many2many_format(cls): def _one2many_format(cls): return cls._relation_format() + @unpack_values + def _char_value(self, field, attrs=None, record=None): + return field + + @unpack_values def _monetary_value(self, field, attrs=None, record=None): """Format a monetary value with its currency symbol @@ -92,18 +114,22 @@ def _monetary_value(self, field, attrs=None, record=None): or "" ) + @unpack_values def _float_value(self, field, attrs=None, record=None): prec = attrs.get("digits", (0, 2)) return f"{field:.{prec[1]}f}" + @unpack_values def _date_value(self, field, attrs=None, record=None): return field and field.strftime("%Y-%m-%d") or "" + @unpack_values def _datetime_value(self, field, attrs=None, record=None): return field and field.strftime("%Y-%m-%d %H:%M:%S") or "" + @unpack_values def _boolean_value(self, field, attrs=None, record=None): - return ":heavy_check_mark:" if field else "" + return ":heavy_check_mark:" if field else ":heavy_multiplication_x:" def _record_url(self, record): """Return a formatted link for relational records. Only supported terminals @@ -174,12 +200,12 @@ def _cell_value(self, record, field, attrs): :return any: formatted value """ method_name = f"_{attrs.get('type', '')}_value" - value = record[field] + value = record.mapped(field) if "." in field else record[field] try: value = ( method_name in self - and getattr(self, method_name)(record[field], attrs, record) - or record[field] + and getattr(self, method_name)(value, attrs, record) + or value ) # OdooRPC is not always as flexible as the regular Odoo shell so we try to # format the record values. Otherwise we throw it as it is. @@ -256,6 +282,29 @@ def _render_record_rows(self, table, records, fields, groupby=None): end_section=(groupby or empty_group_by_cell) and record == last_row, ) + def _get_field_attributes(self, fields, records_obj): + """Gather fields info. Relations supported. + + :param list fields: List of str: field names + :return dict: Dictionary of fields attributes + """ + model_fields = records_obj.fields_get() + fields_attrs_dict = {} + for field in fields: + if "." in field: + relation_route = field.split(".") + relation_path = ".".join(relation_route[1:]) + related_field_attrs = self._get_field_attributes( + [relation_path], records_obj[relation_route[0]] + ) + fields_attrs_dict.update( + {field: related_field_attrs.get(relation_path, {})} + ) + continue + if field in model_fields: + fields_attrs_dict.update({field: model_fields[field]}) + return fields_attrs_dict + def _show( self, records, @@ -294,11 +343,7 @@ def _show( # Compatibility with OdooRPC to access the object fields properties records_obj = records.env[records._name] if fields: - fields = { - key: value - for key, value in records_obj.fields_get().items() - if key in fields - } + fields = self._get_field_attributes(fields, records_obj) else: # Get fields from default tree view # Since v16 the method is deprecated. For the moment just silence warnings diff --git a/pyproject.toml b/pyproject.toml index 238c2cf..ce2743a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "odooshow" -version = "0.5.1" +version = "0.6.0" description = "Make use of rich power tools to have nice formatted data in Odoo shells" authors = ["David Vidal "] diff --git a/tests/test_odooshow.py b/tests/test_odooshow.py index 42ce32f..36879ba 100644 --- a/tests/test_odooshow.py +++ b/tests/test_odooshow.py @@ -3,4 +3,4 @@ def test_version(): # TODO: Add tests. Not easy though as we need to setup a minimum Odoo instance. - assert __version__ == "0.5.1" + assert __version__ == "0.6.0"