.. image:: https://odoo-community.org/readme-banner-image
   :target: https://odoo-community.org/get-involved?utm_source=readme
   :alt: Odoo Community Association

===========================
2D matrix for x2many fields
===========================

.. 
   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   !! This file is generated by oca-gen-addon-readme !!
   !! changes will be overwritten.                   !!
   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   !! source digest: sha256:e422b074c4b533bda09b6422c878ae711365bf51d0a784706df06696acc6a3d3
   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
    :target: https://odoo-community.org/page/development-status
    :alt: Production/Stable
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
    :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
    :alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github
    :target: https://github.com/OCA/web/tree/18.0/web_widget_x2many_2d_matrix
    :alt: OCA/web
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
    :target: https://translation.odoo-community.org/projects/web-18-0/web-18-0-web_widget_x2many_2d_matrix
    :alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
    :target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=18.0
    :alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module allows to show an x2many field with 3-tuples ($x_value,
$y_value, $value) in a table

========= =========== ===========
\         $x_value1   $x_value2
========= =========== ===========
$y_value1 $value(1/1) $value(2/1)
$y_value2 $value(1/2) $value(2/2)
========= =========== ===========

where value(n/n) is editable.

An example use case would be: Select some projects and some employees so
that a manager can easily fill in the planned_hours for one task per
employee. The result could look like this:

|Screenshot|

The beauty of this is that you have an arbitrary amount of columns with
this widget, trying to get this in standard x2many lists involves some
quite ugly hacks.

.. |Screenshot| image:: https://raw.githubusercontent.com/OCA/web/12.0/web_widget_x2many_2d_matrix/static/description/screenshot.png

**Table of contents**

.. contents::
   :local:

Usage
=====

Use this widget by saying:

::

   <field name="my_field" widget="x2many_2d_matrix" />

This assumes that my_field refers to a model with the fields x, y and
value. If your fields are named differently, pass the correct names as
attributes:

.. code:: xml

   <field name="my_field" widget="x2many_2d_matrix" field_x_axis="my_field1" field_y_axis="my_field2" field_value="my_field3">
       <list>
           <field name="my_field"/>
           <field name="my_field1"/>
           <field name="my_field2"/>
           <field name="my_field3"/>
       </list>
   </field>

You can pass the following parameters:

field_x_axis The field that indicates the x value of a point

field_y_axis The field that indicates the y value of a point

field_value Show this field as value

show_row_totals If field_value is a numeric field, it indicates if you
want to calculate row totals. True by default

show_column_totals If field_value is a numeric field, it indicates if
you want to calculate column totals. True by default

x_axis_clickable If the x axis field is a many2one field, render the
values as links to the record in question

y_axis_clickable If the y axis field is a many2one field, render the
values as links to the record in question

For the value field, you can set any attributes you'd set in a normal
list view, ie if your value field is a many2one field and you want to
disable creating records via this field, you'd write

.. code:: xml

   <field name="my_field3" options="{'no_create': true}"/>

or if you want to have a custom domain or context

.. code:: xml

   <field name="my_field3" domain="[('some_field', '=', my_field1)]" context="{'default_some_field': my_field1}" />

Note that to be able to refer to other fields than the ones used as
coordinates or value, you have to add them inside the ``list`` node.

Example
-------

You need a data structure already filled with values. Let's assume we
want to use this widget in a wizard that lets the user fill in planned
hours for one task per project per user. In this case, we can use
``project.task`` as our data model and point to it from our wizard. The
crucial part is that we fill the field in the default function:

.. code:: python

   from odoo import fields, models

   class MyWizard(models.TransientModel):
       _name = 'my.wizard'

       def _default_task_ids(self):
           # your list of project should come from the context, some selection
           # in a previous wizard or wherever else
           projects = self.env['project.project'].browse([1, 2, 3])
           # same with users
           users = self.env['res.users'].browse([1, 2, 3])
           return [
               (0, 0, {
                   'name': 'Sample task name',
                   'project_id': p.id,
                   'user_id': u.id,
                   'planned_hours': 0,
                   'message_needaction': False,
                   'date_deadline': fields.Date.today(),
               })
               # if the project doesn't have a task for the user,
               # create a new one
               if not p.task_ids.filtered(lambda x: x.user_id == u) else
               # otherwise, return the task
               (4, p.task_ids.filtered(lambda x: x.user_id == u)[0].id)
               for p in projects
               for u in users
           ]

       task_ids = fields.Many2many('project.task', default=_default_task_ids)

Now in our wizard, we can use:

.. code:: xml

   <field name="task_ids" widget="x2many_2d_matrix" field_x_axis="project_id" field_y_axis="user_id" field_value="planned_hours">
       <list>
           <field name="task_ids"/>
           <field name="project_id"/>
           <field name="user_id"/>
           <field name="planned_hours"/>
       </list>
   </field>

Known issues / Roadmap
======================

- Support limit total records in the matrix. Ref:
  https://github.com/OCA/web/issues/901
- Support cell traversal through keyboard arrows.
- Entering the widget from behind by pressing ``Shift+TAB`` in your
  keyboard will enter into the 1st cell until
  https://github.com/odoo/odoo/pull/26490 is merged.
- Support kanban mode. Current behaviour forces list mode.

Changelog
=========

12.0.1.0.1 (2018-12-07)
-----------------------

- [FIX] Cells are unable to render property.
  (`#1126 <https://github.com/OCA/web/issues/1126>`__)

12.0.1.0.0 (2018-11-20)
-----------------------

- [12.0][MIG] web_widget_x2many_2d_matrix
  (`#1101 <https://github.com/OCA/web/issues/1101>`__)

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_widget_x2many_2d_matrix%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Hunki Enterprises BV
* Therp BV
* Tecnativa
* Camptocamp
* CorporateHub
* Onestein

Contributors
------------

- Holger Brunn <mail@hunki-enterprises.com>
- Pedro M. Baeza <pedro.baeza@tecnativa.com>
- Artem Kostyuk <a.kostyuk@mobilunity.com>
- Simone Orsi <simone.orsi@camptocamp.com>
- Timon Tschanz <timon.tschanz@camptocamp.com>
- Jairo Llopis <jairo.llopis@tecnativa.com>
- Dennis Sluijk <d.sluijk@onestein.nl>
- `CorporateHub <https://corporatehub.eu/>`__

  - Alexey Pelykh <alexey.pelykh@corphub.eu>

- Adrià Gil Sorribes <adria.gil@forgeflow.com>
- Christopher Ormaza <chris.ormaza@forgeflow.com>
- SodexisTeam <dev@sodexis.com>
- Jasmin Solanki jasmin.solanki@forgeflow.com
- David Jiménez david.jimenez@forgeflow.com

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
   :alt: Odoo Community Association
   :target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

.. |maintainer-JasminSForgeFlow| image:: https://github.com/JasminSForgeFlow.png?size=40px
    :target: https://github.com/JasminSForgeFlow
    :alt: JasminSForgeFlow
.. |maintainer-DavidJForgeFlow| image:: https://github.com/DavidJForgeFlow.png?size=40px
    :target: https://github.com/DavidJForgeFlow
    :alt: DavidJForgeFlow
.. |maintainer-hbrunn| image:: https://github.com/hbrunn.png?size=40px
    :target: https://github.com/hbrunn
    :alt: hbrunn

Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-JasminSForgeFlow| |maintainer-DavidJForgeFlow| |maintainer-hbrunn| 

This module is part of the `OCA/web <https://github.com/OCA/web/tree/18.0/web_widget_x2many_2d_matrix>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
