RemiFr82
11 months ago
7 changed files with 253 additions and 0 deletions
-
4product_variant_price_choice/__init__.py
-
15product_variant_price_choice/__manifest__.py
-
22product_variant_price_choice/hooks.py
-
53product_variant_price_choice/i18n/fr.po
-
2product_variant_price_choice/models/__init__.py
-
98product_variant_price_choice/models/product.py
-
59product_variant_price_choice/views/product_views.xml
@ -0,0 +1,4 @@ |
|||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
|
||||
|
from . import models |
||||
|
from .hooks import set_sale_price_on_variant |
@ -0,0 +1,15 @@ |
|||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
|
||||
|
{ |
||||
|
"name": "Product Variant Price Choice", |
||||
|
"summary": "Allows to choose how to manage product variants price : attributes extra price or manually", |
||||
|
"version": "14.0.1.0.0", |
||||
|
"category": "Product Management", |
||||
|
"website": "https://remifr82.me", |
||||
|
"author": "RemiFr82, Tecnativa, Odoo Community Association (OCA)", |
||||
|
"license": "AGPL-3", |
||||
|
"installable": True, |
||||
|
"depends": ["product"], |
||||
|
"data": ["views/product_views.xml"], |
||||
|
"post_init_hook": "set_sale_price_on_variant", |
||||
|
} |
@ -0,0 +1,22 @@ |
|||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
|
||||
|
|
||||
|
def set_sale_price_on_variant(cr, registry, template_id=None): |
||||
|
sql = """ |
||||
|
UPDATE product_product pp |
||||
|
SET fix_price = pt.list_price + ( |
||||
|
SELECT COALESCE(SUM(ptav.price_extra), 0) |
||||
|
FROM product_variant_combination pvc |
||||
|
LEFT JOIN product_template_attribute_value ptav ON |
||||
|
ptav.id = pvc.product_template_attribute_value_id |
||||
|
WHERE pvc.product_product_id = pp.id |
||||
|
AND ptav.product_tmpl_id = pt.id |
||||
|
) |
||||
|
FROM product_template pt |
||||
|
WHERE pt.id = pp.product_tmpl_id |
||||
|
""" |
||||
|
if template_id: |
||||
|
sql += "AND pt.id = %s" |
||||
|
cr.execute(sql, (template_id,)) |
||||
|
else: |
||||
|
cr.execute(sql) |
@ -0,0 +1,53 @@ |
|||||
|
# Translation of Odoo Server. |
||||
|
# This file contains the translation of the following modules: |
||||
|
# * product_variant_price_choice |
||||
|
# |
||||
|
# Translators: |
||||
|
# OCA Transbot <transbot@odoo-community.org>, 2016 |
||||
|
msgid "" |
||||
|
msgstr "" |
||||
|
"Project-Id-Version: Odoo Server 8.0\n" |
||||
|
"Report-Msgid-Bugs-To: \n" |
||||
|
"POT-Creation-Date: 2016-11-11 03:45+0000\n" |
||||
|
"PO-Revision-Date: 2016-11-11 03:45+0000\n" |
||||
|
"Last-Translator: OCA Transbot <transbot@odoo-community.org>, 2016\n" |
||||
|
"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" |
||||
|
"Language: fr\n" |
||||
|
"MIME-Version: 1.0\n" |
||||
|
"Content-Type: text/plain; charset=UTF-8\n" |
||||
|
"Content-Transfer-Encoding: \n" |
||||
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n" |
||||
|
|
||||
|
#. module: product_variant_price_choice |
||||
|
#: model:ir.model.fields,field_description:product_variant_price_choice.field_product_product__fix_price |
||||
|
msgid "Fixed Price" |
||||
|
msgstr "Prix fixé" |
||||
|
|
||||
|
#. module: product_variant_price_choice |
||||
|
#: model:ir.model.fields,field_description:product_variant_price_choice.field_product_product__list_price |
||||
|
msgid "List Price" |
||||
|
msgstr "Prix de vente" |
||||
|
|
||||
|
#. module: product_variant_price_choice |
||||
|
#: model:ir.model,name:product_variant_price_choice.model_product_product |
||||
|
msgid "Product" |
||||
|
msgstr "Article" |
||||
|
|
||||
|
#. module: product_variant_price_choice |
||||
|
#: model:ir.model,name:product_variant_price_choice.model_product_template |
||||
|
msgid "Product Template" |
||||
|
msgstr "Modèle d'article" |
||||
|
|
||||
|
#. module: product_variant_price_choice |
||||
|
#: model:ir.model.fields,field_description:product_variant_price_choice.field_product_product__lst_price |
||||
|
msgid "Sale Price" |
||||
|
msgstr "Prix de vente" |
||||
|
|
||||
|
#. module: product_variant_price_choice |
||||
|
#: model:ir.model.fields,help:product_variant_price_choice.field_product_product__lst_price |
||||
|
msgid "" |
||||
|
"The sale price is managed from the product template. Click on the 'Configure " |
||||
|
"Variants' button to set the extra attribute prices." |
||||
|
msgstr "" |
||||
|
"Le prix de vente de cet articlé est géré sur son modèle. Cliquez sur le bouton " |
||||
|
"'Confirgurer les variantes' pour renseigner les prix des caractéristiques." |
@ -0,0 +1,2 @@ |
|||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
from . import product |
@ -0,0 +1,98 @@ |
|||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class ProductTemplate(models.Model): |
||||
|
_inherit = "product.template" |
||||
|
|
||||
|
fix_variant_prices = fields.Boolean( |
||||
|
"Set variant prices manually", |
||||
|
default=False, |
||||
|
help="If checked, the extra values from attributes will be ignored and you'll have to define each variant price.", |
||||
|
) |
||||
|
|
||||
|
def _update_fix_price(self, vals): |
||||
|
if "list_price" in vals: |
||||
|
self.mapped("product_variant_ids").write({"fix_price": vals["list_price"]}) |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
product_tmpl = super(ProductTemplate, self).create(vals) |
||||
|
if product_tmpl.fix_variant_prices: |
||||
|
product_tmpl._update_fix_price(vals) |
||||
|
return product_tmpl |
||||
|
|
||||
|
def write(self, vals): |
||||
|
res = super(ProductTemplate, self).write(vals) |
||||
|
if self.env.context.get("skip_update_fix_price", False): |
||||
|
return res |
||||
|
for template in self: |
||||
|
if template.fix_variant_prices: |
||||
|
template._update_fix_price(vals) |
||||
|
return res |
||||
|
|
||||
|
|
||||
|
class ProductProduct(models.Model): |
||||
|
_inherit = "product.product" |
||||
|
|
||||
|
list_price = fields.Float( |
||||
|
compute="_compute_list_price", |
||||
|
) |
||||
|
fix_price = fields.Float(string="Fixed price") |
||||
|
|
||||
|
@api.depends("list_price", "price_extra", "fix_variant_prices", "fix_price") |
||||
|
@api.depends_context("uom") |
||||
|
def _compute_product_lst_price(self): |
||||
|
to_uom = None |
||||
|
if "uom" in self._context: |
||||
|
to_uom = self.env["uom.uom"].browse(self._context["uom"]) |
||||
|
|
||||
|
for product in self: |
||||
|
if not product.fix_variant_prices: |
||||
|
super(ProductProduct, product)._compute_product_lst_price() |
||||
|
else: |
||||
|
price = product.fix_price or product.list_price |
||||
|
if to_uom: |
||||
|
price = product.uom_id._compute_price(price, to_uom) |
||||
|
product.lst_price = price |
||||
|
|
||||
|
def _compute_list_price(self): |
||||
|
for product in self: |
||||
|
price = ( |
||||
|
product.fix_variant_prices |
||||
|
and product.fix_price |
||||
|
or product.product_tmpl_id.list_price |
||||
|
) |
||||
|
if self._context.get("uom"): |
||||
|
price = ( |
||||
|
self.env["uom.uom"] |
||||
|
.browse(self._context["uom"]) |
||||
|
._compute_price(price, product.uom_id) |
||||
|
) |
||||
|
product.list_price = price |
||||
|
|
||||
|
def _set_product_lst_price(self): |
||||
|
for product in self: |
||||
|
if not product.fix_variant_prices: |
||||
|
super(ProductProduct, product)._set_product_lst_price() |
||||
|
else: |
||||
|
if self._context.get("uom"): |
||||
|
price = ( |
||||
|
self.env["uom.uom"] |
||||
|
.browse(self._context["uom"]) |
||||
|
._compute_price(product.lst_price, product.uom_id) |
||||
|
) |
||||
|
else: |
||||
|
price = product.lst_price |
||||
|
product.write({"fix_price": price}) |
||||
|
if product.product_variant_count == 1: |
||||
|
product.product_tmpl_id.list_price = price |
||||
|
else: |
||||
|
fix_prices = product.product_tmpl_id.mapped( |
||||
|
"product_variant_ids.fix_price" |
||||
|
) |
||||
|
# for consistency with price shown in the shop |
||||
|
product.product_tmpl_id.with_context( |
||||
|
skip_update_fix_price=True |
||||
|
).list_price = min(fix_prices) |
@ -0,0 +1,59 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<record id="product_template_only_form_view" model="ir.ui.view"> |
||||
|
<field name="name">product.template.form.inherited</field> |
||||
|
<field name="model">product.template</field> |
||||
|
<field name="inherit_id" ref="product.product_template_only_form_view" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<button name="action_open_attribute_values" position="attributes"> |
||||
|
<attribute name="attrs">{'invisible': [ |
||||
|
'|',('parent.fix_variant_prices', '=', True), |
||||
|
'|', ('parent.attribute_line_ids', '<=', 0), ('parent.is_product_variant', '=', True), |
||||
|
]}</attribute> |
||||
|
</button> |
||||
|
<xpath expr="//page/field[@name='attribute_line_ids']" position="before"> |
||||
|
<group class="o_label_nowrap"> |
||||
|
<field name="fix_variant_prices" /> |
||||
|
</group> |
||||
|
</xpath> |
||||
|
<!-- <xpath expr="//field[@name='list_price']" position="attributes"> |
||||
|
<attribute name="attrs">{'invisible': [ |
||||
|
('fix_variant_prices', '=', True), |
||||
|
('product_variant_count', '>', 1) |
||||
|
]}</attribute> |
||||
|
</xpath> --> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="product_normal_form_view_default_check" model="ir.ui.view"> |
||||
|
<field name="model">product.product</field> |
||||
|
<field name="inherit_id" ref="product.product_normal_form_view" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//field[@name='uom_id']" position="after"> |
||||
|
<field name="fix_variant_prices" invisible="1" /> |
||||
|
<field |
||||
|
name="fix_price" |
||||
|
attrs="{'invisible': ['|',('fix_variant_prices','=',False),('product_variant_count', '=', 1)]}" |
||||
|
/> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="product_variant_easy_edit_price_view" model="ir.ui.view"> |
||||
|
<field name="model">product.product</field> |
||||
|
<field name="inherit_id" ref="product.product_variant_easy_edit_view" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//label[@for='standard_price']" position="before"> |
||||
|
<field name="fix_variant_prices" invisible="1" /> |
||||
|
<field |
||||
|
name="fix_price" |
||||
|
attrs="{'invisible': ['|',('fix_variant_prices','=',False),('product_variant_count', '=', 1)]}" |
||||
|
widget='monetary' |
||||
|
options="{'currency_field': 'currency_id', 'field_digits': True}" |
||||
|
/> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue