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][MIG] purchase_variant_configurator_on_confirm: Merged into purchase_variant_configurator and migration to 16.0 #362

Merged
Merged
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
31 changes: 31 additions & 0 deletions purchase_variant_configurator/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,37 @@ selecting a product and its attributes can be created a new product variant.
.. contents::
:local:

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

#. Go to ``Purchase > Configuration > Settings``.
#. Check the "Create variants on confirm" option if you want to delay the creation
of them until the order confirmation.

Usage
=====

#. Go to a purchase order or create a new one.
#. Create a new line
#. Set in Product Template some product with attributes and variants.
#. All product attributes will be displayed in table mode just below.
#. Set a value for all attributes.
#. A product variant (with the selected options) will be auto-set.


Only if the "Create variants on confirm" option in the configuration is set.


#. Go to ``Purchase > Products > Product`` and create a new one.
#. Go to the "Attributes & Variants" tab.
#. Set in "Variant creation" the option "Do not create them automatically".
#. Set some attribute and value(s)
#. Go to a purchase order or create a new one.
#. Create a new line
#. Set in Product Template the one created before and select values for attributes.
#. Confirm orden.
#. A product variant (with the selected options) will have been created for the Product Template.

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

Expand Down
5 changes: 4 additions & 1 deletion purchase_variant_configurator/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
"Odoo Community Association (OCA)",
"category": "Purchase Management",
"website": "https://github.com/OCA/product-variant",
"data": ["views/inherited_purchase_order_views.xml"],
"data": [
"views/inherited_purchase_order_views.xml",
"views/res_config_settings_views.xml",
],
"installable": True,
"post_init_hook": "assign_product_template",
}
7 changes: 6 additions & 1 deletion purchase_variant_configurator/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
from . import purchase_order_line
from . import product_product
from . import product_supplierinfo
from . import product_template
from . import purchase_order
from . import res_company
from . import res_config_settings
24 changes: 24 additions & 0 deletions purchase_variant_configurator/models/product_product.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2016 ACSONE SA/NV
# Copyright 2017 Tecnativa - David Vidal
# Copyright 2017 Tecnativa - Pedro M. Baeza
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo import models


class ProductProduct(models.Model):
_inherit = "product.product"

def _select_seller(
self, partner_id=False, quantity=0.0, date=None, uom_id=False, params=False
):
"""Don't fail on empty products for allowing to copy purchase order lines."""
if not self:
return False

Check warning on line 17 in purchase_variant_configurator/models/product_product.py

View check run for this annotation

Codecov / codecov/patch

purchase_variant_configurator/models/product_product.py#L17

Added line #L17 was not covered by tests
return super()._select_seller(
partner_id=partner_id,
quantity=quantity,
date=date,
uom_id=uom_id,
params=params,
)
36 changes: 36 additions & 0 deletions purchase_variant_configurator/models/product_supplierinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright 2021 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, models


class ProductSupplierinfo(models.Model):
_inherit = "product.supplierinfo"

@api.model
def search(self, args, offset=0, limit=None, order=None, count=False):
"""HACK: With NewId, the linked product_tmpl_id won't be a proper interger
that we can use in a search. As we need it to get the proper pricelists
we'll be passing it by context. The propper solution would be to
use `self.product_tmpl_id._origin.id` in `_prepare_sellers`:
https://github.com/odoo/odoo/blob/13.0/addons/product/models/product.py#L588"""
if self.env.context.get("pvc_product_tmpl"):
args2 = []
for arg in args:
if (
len(arg) == 3
and arg[0] == "product_tmpl_id"
and arg[1] == "="
and not isinstance(arg[2], int)
):
arg = (

Check warning on line 25 in purchase_variant_configurator/models/product_supplierinfo.py

View check run for this annotation

Codecov / codecov/patch

purchase_variant_configurator/models/product_supplierinfo.py#L25

Added line #L25 was not covered by tests
"product_tmpl_id",
"=",
self.env.context.get("pvc_product_tmpl"),
)
args2.append(arg)
return super().search(
args2, offset=offset, limit=limit, order=order, count=count
)
return super().search(
args, offset=offset, limit=limit, order=order, count=count
)
16 changes: 16 additions & 0 deletions purchase_variant_configurator/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2016 ACSONE SA/NV
# Copyright 2017 Tecnativa - David Vidal
# Copyright 2017 Tecnativa - Pedro M. Baeza
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo import models


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

def _product_from_tmpl(self):
"""Creates a product in memory from template to use its methods"""
return self.env["product.product"].new(
{"product_tmpl_id": self.id, "name": self.name}
)
107 changes: 107 additions & 0 deletions purchase_variant_configurator/models/purchase_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Copyright 2016 Oihane Crucelaegui - AvanzOSC
# Copyright 2016-2017 Tecnativa - Pedro M. Baeza
# Copyright 2016 ACSONE SA/NV
# Copyright 2017 Tecnativa - David Vidal
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo import api, fields, models


class PurchaseOrder(models.Model):
_inherit = "purchase.order"

def button_confirm(self):
"""Create possible product variants not yet created."""
lines_without_product = self.order_line.filtered(
lambda x: not x.product_id and x.product_tmpl_id
)
for line in lines_without_product:
line.create_variant_if_needed()
return super().button_confirm()

def copy(self, default=None):
"""Change date_planned for lines without product after calling super"""
new_po = super().copy(default=default)
for line in new_po.order_line.filtered(lambda x: not x.product_id):
product = line.product_tmpl_id._product_from_tmpl()
seller = product._select_seller(
partner_id=line.partner_id,
quantity=line.product_qty,
date=line.order_id.date_order and line.order_id.date_order.date(),
uom_id=line.product_uom,
)
line.date_planned = line._get_date_planned(seller)
return new_po


class PurchaseOrderLine(models.Model):
_inherit = ["purchase.order.line", "product.configurator"]
_name = "purchase.order.line"

product_id = fields.Many2one(required=False)
product_id_is_required = fields.Boolean(compute="_compute_product_id_is_required")

_sql_constraints = [
(
"accountable_required_fields",
"CHECK(display_type IS NOT NULL OR (product_tmpl_id IS NOT NULL OR "
"product_id IS NOT NULL AND product_uom IS NOT NULL AND "
"date_planned IS NOT NULL))",
"Missing required fields on accountable purchase order line.",
),
(
"non_accountable_null_fields",
"CHECK(display_type IS NULL OR (product_tmpl_id IS NULL AND "
"product_id IS NULL AND price_unit = 0 AND product_uom_qty = 0 AND "
"product_uom IS NULL AND date_planned is NULL))",
"Forbidden values on non-accountable purchase order line",
),
]

@api.depends("company_id")
def _compute_product_id_is_required(self):
for item in self:
item.product_id_is_required = not item.company_id.po_confirm_create_variant

@api.onchange("product_tmpl_id")
def _onchange_product_tmpl_id_configurator(self):
"""Make use of PurchaseOrderLine onchange_product_id method with
a virtual product created on the fly.
"""
res = super()._onchange_product_tmpl_id_configurator()
if not self.product_id and self.product_tmpl_id:
self.product_id = self.product_tmpl_id._product_from_tmpl()
# HACK: With NewId, the `search` method that looks for vendor pricelists
# related to the product is unable to find the linked template as the
# id returns something like `NewId origin: <ID>`. So we'll ensure the
# proper link overriding the supplier search by context. If Odoo fixes
# `_prepare_sellers` method to avoid this issue, this won't be necessary
# anymore
self.with_context(
pvc_product_tmpl=self.product_tmpl_id.id
).onchange_product_id()
return res

@api.model
def _get_product_description(self, template, product, product_attributes):
"""Add description_purchase to name field (similar to what purchase does)."""
name = super()._get_product_description(
template=template, product=product, product_attributes=product_attributes
)
if template.description_purchase:
name += "\n" + template.description_purchase
return name

@api.model_create_multi
def create(self, vals_list):
"""Create variant before calling super when the purchase order is
confirmed, as it creates associated stock moves.
"""
for vals in vals_list:
if vals.get("order_id") and not vals.get("product_id"):
order = self.env["purchase.order"].browse(vals["order_id"])
if order.state == "purchase":
line = self.new(vals)
product = line.create_variant_if_needed()
vals["product_id"] = product.id
return super().create(vals_list)
11 changes: 0 additions & 11 deletions purchase_variant_configurator/models/purchase_order_line.py

This file was deleted.

14 changes: 14 additions & 0 deletions purchase_variant_configurator/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2024 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import fields, models


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

po_confirm_create_variant = fields.Boolean(
string="Create variants on confirm",
help="Create product variants when confirming",
default=False,
)
12 changes: 12 additions & 0 deletions purchase_variant_configurator/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright 2024 Tecnativa - Víctor Martínez
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo import fields, models


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

po_confirm_create_variant = fields.Boolean(
related="company_id.po_confirm_create_variant", readonly=False
)
3 changes: 3 additions & 0 deletions purchase_variant_configurator/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#. Go to ``Purchase > Configuration > Settings``.
#. Check the "Create variants on confirm" option if you want to delay the creation
of them until the order confirmation.
20 changes: 20 additions & 0 deletions purchase_variant_configurator/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#. Go to a purchase order or create a new one.
#. Create a new line
#. Set in Product Template some product with attributes and variants.
#. All product attributes will be displayed in table mode just below.
#. Set a value for all attributes.
#. A product variant (with the selected options) will be auto-set.


Only if the "Create variants on confirm" option in the configuration is set.


#. Go to ``Purchase > Products > Product`` and create a new one.
#. Go to the "Attributes & Variants" tab.
#. Set in "Variant creation" the option "Do not create them automatically".
#. Set some attribute and value(s)
#. Go to a purchase order or create a new one.
#. Create a new line
#. Set in Product Template the one created before and select values for attributes.
#. Confirm orden.
#. A product variant (with the selected options) will have been created for the Product Template.
Loading
Loading