Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0] [ADD] product_uom_company_favorite #188

Open
wants to merge 1 commit into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions product_uom_company_favorite/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
======================================
Product Categories - Company Favorites
======================================

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

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-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%2Fmulti--company-lightgray.png?logo=github
:target: https://github.com/OCA/multi-company/tree/16.0/product_category_company_favorite
:alt: OCA/multi-company
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/multi-company-16-0/multi-company-16-0-product_category_company_favorite
: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/multi-company&target_branch=16.0
:alt: Try me on Runboat

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

This module is usefull in a multi-company context if
- the companies doesn't have to use all the same categories
- if you apply companies to your products.

Without that module, when creating products, end user can select categories
that don't make sense for the current company.
With that module, categories manager can set for each company, which category
will be displayed, reducing configuration error. (and so accounting error
if accounts are set at the category level.)

You could be interested by concurrent module named ``product_category_company``,
(same repository), that propose similar features but with alternative implementation.

**Note**

- When creating **new root category**:

- it is favorite for all the other company if it is favorite in the current
context.
- it is not favorite for all the other company if it is not favorite in the current
context.

- When creating **new child category**:

- the category will inherit the configuration
of the parent category in each company.

- when creating a **new company**:

- all the existing categories are favorite in the new created company.

**Table of contents**

.. contents::
:local:

Configuration
=============

* Select a company you want to configure

* Go to "Inventory" > "Configuration" > "Product Categories"

* Uncheck categories you don't want to use for the current company.

.. figure:: https://raw.githubusercontent.com/OCA/multi-company/16.0/product_category_company_favorite/static/description/product_category_tree.png

Usage
=====

* Go in "Inventory" > "Master Data" > "Products"

* Create a new product

.. figure:: https://raw.githubusercontent.com/OCA/multi-company/16.0/product_category_company_favorite/static/description/product_form_view.png

End user doesn't have access to the category "All / Consumable"
that is not favorite in the current company.

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

There is a little UX bug. When user display product categories in the tree view
and click to select which category is favorite
and which category is not, if the category has children, the value of the children
is updated in the database but the display is not updated.

Refresh the page resolve the problem.

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

Bugs are tracked on `GitHub Issues <https://github.com/OCA/multi-company/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/multi-company/issues/new?body=module:%20product_category_company_favorite%0Aversion:%2016.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
~~~~~~~

* GRAP

Contributors
~~~~~~~~~~~~

* Sylvain LE GAL (https://www.twitter.com/legalsylvain)

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-legalsylvain| image:: https://github.com/legalsylvain.png?size=40px
:target: https://github.com/legalsylvain
:alt: legalsylvain

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

|maintainer-legalsylvain|

This module is part of the `OCA/multi-company <https://github.com/OCA/multi-company/tree/16.0/product_category_company_favorite>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
2 changes: 2 additions & 0 deletions product_uom_company_favorite/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from .post_init_hook import initialize_is_favorite_field
22 changes: 22 additions & 0 deletions product_uom_company_favorite/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (C) 2025 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Product UoM - Company Favorites",
"summary": "Possilibity to set favorite product units" " of Measure per company",
"version": "16.0.1.0.1",
"category": "Product",
"author": "GRAP,Odoo Community Association (OCA)",
"maintainers": ["legalsylvain"],
"website": "https://github.com/grap/grap-odoo-incubator",
"license": "AGPL-3",
"depends": ["product"],
"data": [
"views/view_uom_uom.xml",
"views/view_uom_category.xml",
"views/view_product_template.xml",
],
"demo": ["demo/res_company.xml"],
"installable": True,
"post_init_hook": "initialize_is_favorite_field",
}
14 changes: 14 additions & 0 deletions product_uom_company_favorite/demo/res_company.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright (C) 2023-Today: GRAP (<http://www.grap.coop/>)
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>

<record id="demo_company" model="res.company">
<field name="name">Demo Company For Favorite UoM</field>
<field name="user_ids" eval="[(4, ref('base.user_admin'))]" />
</record>

</odoo>
71 changes: 71 additions & 0 deletions product_uom_company_favorite/i18n/fr.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_uom_company_favorite
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-24 15:37+0000\n"
"PO-Revision-Date: 2025-02-24 15:37+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"

#. module: product_uom_company_favorite
#: model:ir.model,name:product_uom_company_favorite.model_res_company
msgid "Companies"
msgstr "Sociétés"

#. module: product_uom_company_favorite
#: model:ir.model.fields,help:product_uom_company_favorite.field_product_product__uom_id
#: model:ir.model.fields,help:product_uom_company_favorite.field_product_template__uom_id
msgid "Default unit of measure used for all stock operations."
msgstr ""
"Unité de mesure par défaut utilisée pour toutes les opérations de stock"

#. module: product_uom_company_favorite
#: model:ir.model.fields,field_description:product_uom_company_favorite.field_uom_uom__is_favorite
msgid "Favorite"
msgstr "Favorite"

#. module: product_uom_company_favorite
#: model_terms:ir.ui.view,arch_db:product_uom_company_favorite.view_uom_uom_search
msgid "Favorites"
msgstr "Favorites"

#. module: product_uom_company_favorite
#: model:ir.model.fields,help:product_uom_company_favorite.field_uom_uom__is_favorite
msgid ""
"If this field is unchecked, the uom will be hidden when searching uom in a "
"drop-down list like in the product form view."
msgstr ""
"Si cette case est décochée, l'unité de mesure sera cachée lors de la recherche"
" d'unité de mesure dans une liste déroulante, comme dans la vue formulaire "
"du produit."

#. module: product_uom_company_favorite
#: model:ir.model,name:product_uom_company_favorite.model_product_template
msgid "Product"
msgstr "Produit"

#. module: product_uom_company_favorite
#: model:ir.model,name:product_uom_company_favorite.model_uom_uom
msgid "Product Unit of Measure"
msgstr "Unité de mesure du produit"

#. module: product_uom_company_favorite
#: model:ir.model.fields,field_description:product_uom_company_favorite.field_product_product__uom_id
#: model:ir.model.fields,field_description:product_uom_company_favorite.field_product_template__uom_id
msgid "Unit of Measure"
msgstr "Unité de mesure"

#. module: product_uom_company_favorite
#. odoo-python
#: code:addons/product_uom_company_favorite/models/product_template.py:0
#, python-format
msgid "You can not set this Unit of Measure."
msgstr "Vous ne pouvez pas utiliser cette unité de mesure."
3 changes: 3 additions & 0 deletions product_uom_company_favorite/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import res_company
from . import uom_uom
from . import product_template
28 changes: 28 additions & 0 deletions product_uom_company_favorite/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright (C) 2023-Today: GRAP (<http://www.grap.coop/>)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import _, api, fields, models
from odoo.exceptions import ValidationError


class ProductTemplate(models.Model):
_inherit = "product.template"

uom_id = fields.Many2one(default=lambda x: x._get_default_uom_id())

def _get_default_uom_id(self):
"""Overwrite the original function that returns 'Units'
In our case, if there are many favorites, force user to decide.
Otherwise, set the unique favorite unit of measure as the default one.
"""
favorite_uoms = self.env["uom.uom"].search([("is_favorite", "=", True)])
if len(favorite_uoms) == 1:
return favorite_uoms[0].id
return False

@api.constrains("uom_id")
def _check_uom(self):
if self.filtered(lambda x: not x.uom_id.is_favorite):
raise ValidationError(_("You can not set this Unit of Measure."))
return super()._check_uom()

Check warning on line 28 in product_uom_company_favorite/models/product_template.py

View check run for this annotation

Codecov / codecov/patch

product_uom_company_favorite/models/product_template.py#L27-L28

Added lines #L27 - L28 were not covered by tests
30 changes: 30 additions & 0 deletions product_uom_company_favorite/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright (C) 2023-Today: GRAP (<http://www.grap.coop/>)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import api, models


class ResCompany(models.Model):
_inherit = "res.company"

def _configure_favorite_uom(self):
for company in self:
result = self.env["product.template"].read_group(
[("company_id", "in", [company.id, False])], ["uom_id"], ["uom_id"]
)
uom_ids = [x["uom_id"][0] for x in result]

uoms = (
self.env["uom.uom"]
.sudo()
.with_company(company)
.search([("id", "in", uom_ids)])
)
uoms.write({"is_favorite": True})

@api.model_create_multi
def create(self, vals_list):
companies = super().create(vals_list)
companies._configure_favorite_uom()
return companies
27 changes: 27 additions & 0 deletions product_uom_company_favorite/models/uom_uom.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright (C) 2023-Today: GRAP (<http://www.grap.coop/>)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import fields, models


class ProductUom(models.Model):
_inherit = "uom.uom"

is_favorite = fields.Boolean(
string="Favorite",
company_dependent=True,
help="If this field is unchecked, the uom will"
" be hidden when searching uom in a drop-down list"
" like in the product form view.",
)

def _name_search(
self, name, args=None, operator="ilike", limit=100, name_get_uid=None
):
args = list(args or [])
if self.env.context.get("display_only_favorite", False):
args += [("is_favorite", "=", True)]
return super()._name_search(
name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid
)
16 changes: 16 additions & 0 deletions product_uom_company_favorite/post_init_hook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright (C) 2025-Today: GRAP (<http://www.grap.coop/>)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

import logging

from odoo import SUPERUSER_ID, api

_logger = logging.getLogger(__name__)


def initialize_is_favorite_field(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
for company in env["res.company"].with_context(active_test=False).search([]):
_logger.info("Configure is_favorite field for the company %s" % (company.name))
company._configure_favorite_uom()
7 changes: 7 additions & 0 deletions product_uom_company_favorite/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
* Select a company you want to configure

* Go to "Units of Measure"

* Uncheck units you don't want to use for the current company.

.. figure:: ../static/description/product_uom_tree.png
1 change: 1 addition & 0 deletions product_uom_company_favorite/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Sylvain LE GAL (https://www.twitter.com/legalsylvain)
18 changes: 18 additions & 0 deletions product_uom_company_favorite/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
This module is usefull in a multi-company context if
- the companies doesn't have to use all the same units
- if you apply companies to your products.

Without that module, when creating products, end user can select units
that don't make sense for the current company.
With that module, units manager can set for each company, which units
will be displayed, reducing configuration error.

This module also change the default unit of measure.
If many units are favorite, default unit is False, so it forces the
user to choose the correct one.

**Note**

When installing the module for all companies, or when creating a new company,
we set as favorite units, all the units set for the products of the company
(or the global products)
Loading
Loading