Skip to content

Commit

Permalink
Merge PR #1415 into 16.0
Browse files Browse the repository at this point in the history
Signed-off-by lmignon
  • Loading branch information
shopinvader-git-bot committed Dec 19, 2023
2 parents 9993383 + 221a215 commit 1e56c7b
Show file tree
Hide file tree
Showing 20 changed files with 457 additions and 4 deletions.
6 changes: 6 additions & 0 deletions setup/shopinvader_product_sale_packaging/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
13 changes: 9 additions & 4 deletions shopinvader_anonymous_partner/tests/test_anonymous_partner.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import psycopg2

from odoo import SUPERUSER_ID
from odoo.http import Controller, request, route
from odoo.tests.common import HttpCase, TransactionCase
from odoo.tools import mute_logger
Expand All @@ -15,15 +16,19 @@
class TestController(Controller):
@route("/test/anonymous_partner_create", type="http", auth="none")
def anonymous_partner_create(self):
partner = request.env["res.partner"]._create_anonymous_partner__cookie(
request.future_response
partner = (
request.env["res.partner"]
.with_user(SUPERUSER_ID)
._create_anonymous_partner__cookie(request.future_response)
)
return str(partner.id)

@route("/test/anonymous_partner_get", type="http", auth="none")
def anonymous_partner_get(self):
partner = request.env["res.partner"]._get_anonymous_partner__cookie(
request.httprequest.cookies
partner = (
request.env["res.partner"]
.with_user(SUPERUSER_ID)
._get_anonymous_partner__cookie(request.httprequest.cookies)
)
if partner:
return str(partner.id)
Expand Down
67 changes: 67 additions & 0 deletions shopinvader_product_sale_packaging/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
==========================
Shopinvader Sale Packaging
==========================

.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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-shopinvader%2Fodoo--shopinvader-lightgray.png?logo=github
:target: https://github.com/shopinvader/odoo-shopinvader/tree/14.0/shopinvader_sale_packaging
:alt: shopinvader/odoo-shopinvader

|badge1| |badge2| |badge3|

Provide packaging information for products and allow to purchase them by packaging.

Available packaging are taken using `stock_packaging_calculator <https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_packaging_calculator>`_.

**Table of contents**

.. contents::
:local:

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

Bugs are tracked on `GitHub Issues <https://github.com/shopinvader/odoo-shopinvader/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/shopinvader/odoo-shopinvader/issues/new?body=module:%20shopinvader_sale_packaging%0Aversion:%2014.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
~~~~~~~

* Camptocamp SA

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

* Simone Orsi <[email protected]>

Other credits
~~~~~~~~~~~~~

The development of this module has been financially supported by:

* Camptocamp
* Cosanum

Maintainers
~~~~~~~~~~~

This module is part of the `shopinvader/odoo-shopinvader <https://github.com/shopinvader/odoo-shopinvader/tree/14.0/shopinvader_sale_packaging>`_ project on GitHub.

You are welcome to contribute.
2 changes: 2 additions & 0 deletions shopinvader_product_sale_packaging/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import schemas
26 changes: 26 additions & 0 deletions shopinvader_product_sale_packaging/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2020 Camptocamp SA
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Shopinvader Product Sale Packaging",
"Summary": """
Sell products by packaging.
""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Camptocamp SA",
"website": "https://github.com/shopinvader/odoo-shopinvader",
"depends": [
"extendable_fastapi",
"shopinvader_product",
"sale_stock",
"sell_only_by_packaging",
"stock_packaging_calculator_packaging_level",
],
"data": [
"views/product_packaging.xml",
"views/product_packaging_level.xml",
],
"installable": True,
}
2 changes: 2 additions & 0 deletions shopinvader_product_sale_packaging/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import product_packaging
from . import product_packaging_level
22 changes: 22 additions & 0 deletions shopinvader_product_sale_packaging/models/product_packaging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2021 Camptocamp SA (http://www.camptocamp.com).
# @author Simone Orsi <[email protected]>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from odoo import api, fields, models


class ProductPackaging(models.Model):

_inherit = "product.packaging"

shopinvader_display = fields.Boolean(
compute="_compute_shopinvader_display",
readonly=False,
store=True,
help="Include this packaging into Shopinvader product metadata.",
)
can_be_sold = fields.Boolean(related="packaging_level_id.can_be_sold")

@api.depends("packaging_level_id.shopinvader_display")
def _compute_shopinvader_display(self):
for record in self:
record.shopinvader_display = record.packaging_level_id.shopinvader_display
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2021 Camptocamp SA (http://www.camptocamp.com).
# @author Simone Orsi <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import fields, models


class ProductPackagingLevel(models.Model):
_inherit = "product.packaging.level"

shopinvader_display = fields.Boolean(
help="Include this packaging into Shopinvader product metadata.",
default=True,
)
2 changes: 2 additions & 0 deletions shopinvader_product_sale_packaging/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Simone Orsi <[email protected]>
* Marie Lejeune <[email protected]>
5 changes: 5 additions & 0 deletions shopinvader_product_sale_packaging/readme/CREDITS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The development of this module has been financially supported by:

* Camptocamp
* Cosanum
* Acsone
3 changes: 3 additions & 0 deletions shopinvader_product_sale_packaging/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Provide packaging information for products.

Available packaging are taken using `stock_packaging_calculator <https://github.com/OCA/stock-logistics-warehouse/tree/16.0/stock_packaging_calculator>`_.
2 changes: 2 additions & 0 deletions shopinvader_product_sale_packaging/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .product_packaging import SimpleProductPackaging, ProductPackaging
from .product import ProductProduct
31 changes: 31 additions & 0 deletions shopinvader_product_sale_packaging/schemas/product.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo.addons.shopinvader_product.schemas import ProductProduct as BaseProductProduct

from . import ProductPackaging


class ProductProduct(BaseProductProduct, extends=True):
sell_only_by_packaging: bool | None = None
packaging: list[ProductPackaging] = []

@classmethod
def from_product_product(cls, odoo_rec):
obj = super().from_product_product(odoo_rec)
obj.sell_only_by_packaging = odoo_rec.sell_only_by_packaging
context = {"_packaging_filter": lambda x: x.shopinvader_display}
packaging = odoo_rec.with_context(**context)._ordered_packaging()
packaging_contained_mapping = odoo_rec.with_context(
**context
).packaging_contained_mapping
obj.packaging = [
ProductPackaging.from_packaging(
odoo_product=odoo_rec,
packaging=pkg,
packaging_contained_mapping=packaging_contained_mapping,
)
for pkg in packaging
]

return obj
59 changes: 59 additions & 0 deletions shopinvader_product_sale_packaging/schemas/product_packaging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo.addons.extendable_fastapi import StrictExtendableBaseModel
from odoo.addons.stock_packaging_calculator.models.product import Packaging


class SimpleProductPackaging(StrictExtendableBaseModel):
id: int
name: str
qty: float
barcode: str | None = None
is_unit: bool
can_be_sold: bool

@classmethod
def from_packaging(cls, odoo_product, packaging, packaging_contained_mapping=None):
# packaging is a either a namedtuple of type Packaging, or a dict with the same keys
# id key can refer to id of model product.packaging or uom.uom, depending on is_unit
obj = cls.model_construct(
id=packaging.id,
name=packaging.name,
qty=packaging.qty,
barcode=packaging.barcode,
is_unit=packaging.is_unit,
can_be_sold=not odoo_product.sell_only_by_packaging,
)
if not obj.is_unit:
# packaging is of type product.packaging, not uom.uom
# read can_be_sold info on packaging
pkg = odoo_product.packaging_ids.filtered(lambda p: p.id == packaging.id)
obj.can_be_sold = pkg.can_be_sold

return obj


class ProductPackaging(SimpleProductPackaging):
contained: list[SimpleProductPackaging] = []

@classmethod
def from_packaging(cls, odoo_product, packaging, packaging_contained_mapping=None):
obj = super().from_packaging(odoo_product, packaging)
if packaging_contained_mapping and not packaging.is_unit:
contained_packaging = packaging_contained_mapping.get(str(obj.id), [])
if contained_packaging:
obj.contained = [
SimpleProductPackaging.from_packaging(
odoo_product,
Packaging(
pkg["id"],
pkg["name"],
pkg["qty"],
pkg["barcode"] or None,
pkg["is_unit"],
),
)
for pkg in contained_packaging
]
return obj
1 change: 1 addition & 0 deletions shopinvader_product_sale_packaging/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_product_data
31 changes: 31 additions & 0 deletions shopinvader_product_sale_packaging/tests/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright 2023 Acsone SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo.tests.common import TransactionCase


class CommonPackagingCase(TransactionCase):
@classmethod
def setUpClass(cls):
super(CommonPackagingCase, cls).setUpClass()
cls.pkg_level_retail_box = cls.env["product.packaging.level"].create(
{
"name": "Retail Box",
"code": "pack",
"sequence": 3,
}
)
cls.pkg_level_transport_box = cls.env["product.packaging.level"].create(
{
"name": "Transport Box",
"code": "case",
"sequence": 4,
}
)
cls.pkg_level_pallet = cls.env["product.packaging.level"].create(
{
"name": "Pallet",
"code": "pallet",
"sequence": 5,
}
)
Loading

0 comments on commit 1e56c7b

Please sign in to comment.