Skip to content

Commit

Permalink
[ADD] product_catalog_stock: New module
Browse files Browse the repository at this point in the history
Use the product catalgo with pickings

TT50477
  • Loading branch information
chienandalu committed Sep 9, 2024
1 parent 0d8909e commit be28ffd
Show file tree
Hide file tree
Showing 15 changed files with 787 additions and 0 deletions.
94 changes: 94 additions & 0 deletions product_catalog_stock/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
=====================
Stock Product Catalog
=====================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:e15b8a712eb3399c22281379449b50e2b307fe8076a721c03159ab634d3164a1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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%2Fproduct--attribute-lightgray.png?logo=github
:target: https://github.com/OCA/product-attribute/tree/16.0/product_catalog_stock
:alt: OCA/product-attribute
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/product-attribute-16-0/product-attribute-16-0-product_catalog_stock
: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/product-attribute&target_branch=16.0
:alt: Try me on Runboat

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

Implementation of the product catalog for stock pickings.

**Table of contents**

.. contents::
:local:

Usage
=====

To access the catalog from a stock picking.

1. Create a new draft picking.
2. Click on the product catalog smart button.
3. Click it and start adding products to the picking.

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

- In v17 the product catalog has the price key as mandatory. So maybe
further adaptations will be needed to support more models.

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

Bugs are tracked on `GitHub Issues <https://github.com/OCA/product-attribute/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/product-attribute/issues/new?body=module:%20product_catalog_stock%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
-------

* Odoo SA
* Tecnativa

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

- `Tecnativa <https://tecnativa.com>`__

- David Vidal

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.

This module is part of the `OCA/product-attribute <https://github.com/OCA/product-attribute/tree/16.0/product_catalog_stock>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions product_catalog_stock/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
16 changes: 16 additions & 0 deletions product_catalog_stock/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2024 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Stock Product Catalog",
"summary": "Use the product catalog on stock pickings",
"version": "16.0.1.0.0",
"author": "Odoo SA, Tecnativa, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/product-attribute",
"license": "AGPL-3",
"category": "Product",
"depends": ["stock", "product_catalog"],
"data": [
"views/stock_picking_views.xml",
"views/stock_picking_type_views.xml",
],
}
2 changes: 2 additions & 0 deletions product_catalog_stock/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import stock_picking
from . import stock_picking_type
152 changes: 152 additions & 0 deletions product_catalog_stock/models/stock_picking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Copyright 2024 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from collections import defaultdict

from odoo import _, api, models
from odoo.osv import expression


class StockPicking(models.Model):
_name = "stock.picking"
_inherit = ["stock.picking", "product.catalog.mixin"]

def _compute_catalog_button_text(self):
self.catalog_button_text = _("Back to picking")

def _get_action_add_from_catalog_extra_context(self):
return {
**super()._get_action_add_from_catalog_extra_context(),
"order_id": self.id,
}

def _default_order_line_values(self):
default_data = super()._default_order_line_values()
new_default_data = self.env["stock.move"]._get_product_catalog_lines_data()
return {**default_data, **new_default_data}

def _get_product_catalog_domain(self):
return expression.AND(
[
super()._get_product_catalog_domain(),
[("type", "in", ["consu", "product"])],
]
)

def _get_product_catalog_record_lines(self, product_ids):
grouped_moves = defaultdict(lambda: self.env["stock.move"])
for move in self.move_ids:
if move.product_id.id not in product_ids:
continue
grouped_moves[move.product_id] |= move
return grouped_moves

@api.model
def _prepare_stock_move_vals_from_catalog(self, product_id, quantity):
self.ensure_one()
product_id = self.env["product.product"].browse(product_id)
return {
"name": product_id.display_name,
"product_id": product_id.id,
"product_uom_qty": quantity,
"product_uom": product_id.uom_id.id,
"location_id": self.location_id.id,
"location_dest_id": self.location_dest_id.id,
"picking_id": self.id,
"state": self.state,
"picking_type_id": self.picking_type_id.id,
"restrict_partner_id": self.owner_id.id,
"company_id": self.company_id.id,
"partner_id": self.partner_id.id,
# Put it at the end of the order
"sequence": ((self.move_ids and self.move_ids[-1].sequence + 1) or 10),
}

def _update_order_line_info(self, product_id, quantity, **kwargs):
"""Update stock move information for a given product or create a
new one if none exists yet.
:param int product_id: The product, as a `product.product` id.
:return: There's no price unit so we return always None show nothing is shown
:rtype: None
"""
move = self.move_ids.filtered(lambda move: move.product_id.id == product_id)
if move:
if quantity != 0:
move.product_uom_qty = quantity
elif self.state == "draft":
move.unlink()
return None
else:
move.product_uom_qty = 0
elif quantity > 0:
move = self.env["stock.move"].create(
self._prepare_stock_move_vals_from_catalog(product_id, quantity)
)
return None

def _is_readonly(self):
"""Return Whether the sale order is read-only or not based on the state or the
lock status.
A sale order is considered read-only if its state is 'cancel' or if the sale
order is locked.
:return: Whether the sale order is read-only or not.
:rtype: bool
"""
self.ensure_one()
return self.state in ["cancel", "done"] or self.is_locked


class StockMove(models.Model):
_inherit = "stock.move"

def _get_product_catalog_lines_data(self, **kwargs):
"""Return information about sale order lines in `self`.
If `self` is empty, this method returns only the default value(s) needed for
the product catalog. In this case, the quantity that equals 0.
Otherwise, it returns a quantity and a price based on the product of the SOL(s)
and whether the product is read-only or not.
A product is considered read-only if the picking is cancelled or done.
Note: This method cannot be called with multiple records that have different
products linked.
:raise odoo.exceptions.ValueError: ``len(self.product_id) != 1``
:rtype: dict
:return: A dict with the following structure:
{
'quantity': float,
'readOnly': bool,
}
"""
if len(self) == 1:
res = {
"quantity": self.product_uom_qty,
"readOnly": self.picking_id.state in ["cancel", "done"],
}
return res
elif self:
self.product_id.ensure_one()
res = {
"readOnly": True,
"quantity": sum(
self.mapped(
lambda move: move.product_uom._compute_quantity(
qty=move.product_uom_qty,
to_unit=move.product_id.uom_id,
)
)
),
}
return res
else:
return {
"quantity": 0,
}

def action_add_from_catalog(self):
picking = self.env["stock.picking"].browse(self.env.context.get("order_id"))
return picking.action_add_from_catalog()
24 changes: 24 additions & 0 deletions product_catalog_stock/models/stock_picking_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2024 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models
from odoo.tests import Form


class StockPickingType(models.Model):
_inherit = "stock.picking.type"

def action_new_draft_picking_from_catalog(self):
"""Create a new draft picking from the catalog view"""
picking_form = Form(
self.env["stock.picking"].with_context(
search_default_picking_type_id=self.ids,
default_picking_type_id=self.id,
contact_display="partner_address",
)
)
picking = picking_form.save()
action = picking.action_add_from_catalog()
# So we can go back safely to the new picking instead of returning to the
# previous screen
action["target"] = "main"
return action
2 changes: 2 additions & 0 deletions product_catalog_stock/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- [Tecnativa](https://tecnativa.com)
- David Vidal
1 change: 1 addition & 0 deletions product_catalog_stock/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implementation of the product catalog for stock pickings.
2 changes: 2 additions & 0 deletions product_catalog_stock/readme/ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- In v17 the product catalog has the price key as mandatory. So maybe further
adaptations will be needed to support more models.
5 changes: 5 additions & 0 deletions product_catalog_stock/readme/USAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
To access the catalog from a stock picking.

1. Create a new draft picking.
2. Click on the product catalog smart button.
3. Click it and start adding products to the picking.
Loading

0 comments on commit be28ffd

Please sign in to comment.