#15 new module product_update_price_last_purchase based on product_margin_classification to update sell prices on products when purchase price changes.

This commit is contained in:
Luis 2024-01-15 20:25:34 +01:00
parent f9d660c245
commit 1bd3fab4dc
18 changed files with 279 additions and 536 deletions

View file

@ -1,3 +1 @@
from . import models
from . import report

View file

@ -1,32 +1,29 @@
{
'name': 'Product Update Price From Last Purchase',
'version': "16.0.1.0.0",
'category': 'purchase',
'summary' : 'Product Update Price From Last Purchase',
'description' : """
"name": "Product Update Price From Last Purchase",
"version": "16.0.1.0.0",
"category": "purchase",
"summary": """"
Personaliza el comportamiento de Product para supermercados:
* setea los impuestos del proveedor al mismo tipo que el impuesto de venta.
* Actualiza el precio de venta según el precio de coste aplicado a una tarifa.
* Filtro para productos actualizados el precio de coste.
* Campo que guarda el último precio de compra en vez de usar standard_price
y no afectar a la valoración de inventario.
* Actualiza el precio de venta según el último precio de coste aplicado a una tarifa.
* Filtro para productos actualizados el último precio de coste.
* Filtro para productos que necesitan etiqueta nueva.
* Campo que guarda el último precio de compra en vez de usar standard_price y no afectar a la valoración de inventario.
""",
'author': 'Criptomart',
'website': 'https://criptomart.net',
'license': 'AGPL-3',
'depends': [
'base',
'product',
'account',
'stock_account',
"author": "Criptomart",
"website": "https://criptomart.net",
"license": "AGPL-3",
"depends": [
"account",
"stock_account",
"sale",
"product_margin_classification",
"product_print_category",
],
'data': [
'views/actions.xml',
'views/product_view.xml',
'data/report_paperformat.xml',
'report/report_product_shelf_tag.xml',
#'report/report_product_barcode.xml',
#'report/product_barcode.xml'
"data": [
"views/actions.xml",
"views/product_view.xml",
"views/res_config.xml",
],
'installable': True,
"installable": True,
}

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="paperformat_barcode" model="report.paperformat">
<field name="name">Barcodes stickers format</field>
<field name="default" eval="True" />
<field name="format">A4</field>
<field name="page_height">0</field>
<field name="page_width">0</field>
<field name="orientation">Portrait</field>
<field name="margin_top">10</field>
<field name="margin_bottom">5</field>
<field name="margin_left">8</field>
<field name="margin_right">8</field>
<field name="header_line" eval="False" />
<field name="header_spacing">0</field>
<field name="dpi">75</field>
</record>
</odoo>

View file

@ -1,8 +1,4 @@
from . import product_template
from . import product_product
from . import res_company
from . import res_config
from . import ir_actions_report
from . import stock_move
from . import product_pricelist
from . import product_pricelist_item

View file

@ -1,21 +0,0 @@
import logging
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
class IrActionsReport(models.Model):
_inherit = 'ir.actions.report'
def render_qweb_pdf(self, res_ids=None, data=None):
_logger.debug("render_qweb_pdf : %s -- %s" %(res_ids, data))
if res_ids:
Model = self.env[self.model]
record_ids = Model.browse(res_ids)
wk_record_ids = Model
for record_id in record_ids:
if self.report_name == "product.report_producttemplatelabel":
record_id.to_print = False
return super(IrActionsReport, self).render_qweb_pdf(res_ids, data)

View file

@ -1,25 +0,0 @@
# Copyright (C) 2020: Criptomart (https://criptomart.net)
# @author Santi Noreña (<santi@criptomart.net>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, models
class ProductPricelist(models.Model):
_inherit = 'product.pricelist'
def _compute_price_rule(self, products_qty_partner, date=False, uom_id=False):
ProductPricelistItem = self.env['product.pricelist.item']
ProductProduct = self.env['product.product']
res = super()._compute_price_rule(products_qty_partner, date=date, uom_id=uom_id)
new_res = res.copy()
item_id = []
for product_id, values in res.items():
if values[1]:
item_id = values[1]
if item_id:
item = ProductPricelistItem.browse(item_id)
if item.base == 'last_purchase_price':
product = ProductProduct.browse(product_id)
new_res[product_id] = (product.last_purchase_price, item_id)
return new_res

View file

@ -1,12 +0,0 @@
# Copyright (C) 2020: Criptomart (https://criptomart.net)
# @author Santi Noreña (<santi@criptomart.net>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class ProductPricelistItem(models.Model):
_inherit = 'product.pricelist.item'
base = fields.Selection(selection_add=[
('last_purchase_price', 'Last purchase price')])

View file

@ -4,21 +4,54 @@
import logging
from odoo import models, fields, api
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
class ProductProduct(models.Model):
_inherit = "product.product"
def write(self, vals):
if vals.get('last_purchase_price'):
vals['list_price_updated'] = True
return super(ProductProduct, self).write(vals)
@api.depends(
"standard_price",
"last_purchase_price_received",
"lst_price",
"margin_classification_id",
"margin_classification_id.markup",
"margin_classification_id.price_round",
"margin_classification_id.price_surcharge",
"product_tmpl_id.taxes_id",
"product_tmpl_id.list_price",
)
def _compute_theoretical_multi(self):
res = super()._compute_theoretical_multi()
for product in self:
if product.last_purchase_price_received != 0:
(
product.margin_state,
product.theoretical_price,
product.theoretical_difference,
) = self._get_margin_info(
product.margin_classification_id,
product.taxes_id,
product.name,
product.last_purchase_price_received,
product.lst_price,
)
return res
def use_theoretical_price(self):
res = super().use_theoretical_price()
for product in self:
product.to_print_label = True
return res
class ProductPackaging(models.Model):
_inherit = "product.packaging"
qty = fields.Float('Contained Quantity', help="The total number of products you can have per pallet or box.", digits='Product Unit of Measure')
qty = fields.Float(
"Contained Quantity",
help="The total number of products you can have per pallet or box.",
digits="Product Unit of Measure",
)

View file

@ -3,136 +3,88 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
import math
from odoo import exceptions, models, fields, api, _
from odoo.exceptions import UserError
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
MARGIN_STATE_SELECTION = [
("correct", "Correct Margin"),
("too_cheap", "Too Cheap"),
("too_expensive", "Too Expensive"),
]
class ProductTemplate(models.Model):
_inherit = "product.template"
def _compute_theoritical_price(self):
partner = self.env['res.users'].browse(self.env.uid).partner_id
pricelist_obj = self.env['product.pricelist']
pricelist_id = self.env['ir.config_parameter'].sudo().get_param('product_update_price_last_purchase.product_pricelist_automatic') or False
pricelist = pricelist_obj.browse(int(pricelist_id))
_logger.debug("Calculating price with PriceList : %s" %pricelist.name)
if pricelist:
for template in self:
if template.name and template.id and template.product_variant_id and template.last_purchase_price_compute_type != 'manual_update':
partial_price = pricelist.get_product_price(template.product_variant_id, "1", partner)
_logger.debug("partial_price : %s" %partial_price)
# Suma el IVA
for tax in template.taxes_id:
partial_price = partial_price * ( 1 + ( tax.amount / 100) )
_logger.debug("partial_price after taxes : %s" %partial_price)
# Redondea a 0,05 de precisión
template.list_price = round(round(partial_price / 0.05) * 0.05, -int(math.floor(math.log10(0.05))))
_logger.debug("final price : %s" %template.list_price)
template.list_price_updated = False
else:
raise UserError(_('Not found a valid pricelist to compute sale price. Check configuration in General Settings.'))
return False
list_price = fields.Float(
string="Sale price with VAT",
help="Price calculated according to the configured pricelist, including VAT.",
digits='Product Price'
margin_state = fields.Selection(
string="Theoretical Price State",
compute="_compute_theoretical_multi_template",
selection=MARGIN_STATE_SELECTION,
store=True,
)
list_price_updated = fields.Boolean(
string="Last purchase price updated",
help="The last cost price has been updated and you need to update the selling price in the database, shelves and scales.",
default=False,
readonly=True
)
list_price_automatic = fields.Boolean(
string="Automatic Sale Price",
help="Automatic computation of the PVP from the cost price and the rate defined in the configuration.",
default=True
)
to_print = fields.Boolean(
to_print_label = fields.Boolean(
string="To print label",
help="The sale price has been updated on this product and needs to be updated on the shelf.",
help="""The sale price has been updated on this product
and needs to be updated on the shelf.""",
default=False,
readonly=True
readonly=True,
)
last_purchase_price = fields.Float(
last_purchase_price_received = fields.Float(
string="Last purchase price",
help="The last price at which the product was purchased. It is used as the base price field for calculating the product sale price.",
#readonly=True,
digits='Product Price'
help="The last price at which the product was purchased. "
"It is used as the base price field for calculating the product sale price.",
readonly=True,
digits="Product Price",
)
last_purchase_price_compute_type = fields.Selection([
('without_discounts', 'Without discounts'),
('with_discount', 'First discount'),
('with_three_discounts', 'Triple discount'),
('manual_update', 'Manual update')],
string="Last purchase price calculation type",
help='Choose whether discounts should influence the calculation of the last purchase price. Select Never update for manual configuration of cost and sale prices.\n'
'\n* Without discounts: does not take into account discounts when updating the last purchase price.\n'
'* First discount: take into account only first discount when updating the last purchase price.\n'
'* Triple discount: take into account all discounts when updating the last purchase price. Needs "Purchase Triple Discount" OCA module.\n'
'* Manual update: Select this for manual configuration of cost and sale price. The sales price will not be calculated automatically.',
default='without_discounts',
required=True
)
@api.model
def create(self, vals):
# Set supplier tax same than customer tax
if vals.get('taxes_id'):
tax = self.get_supplier_tax(vals.get('taxes_id'))
vals['supplier_taxes_id'] = tax
vals['list_price_updated'] = True
return super(ProductTemplate, self).create(vals)
def write(self, vals):
# Set supplier tax same than customer tax
if vals.get('taxes_id'):
tax = self.get_supplier_tax(vals.get('taxes_id'))
vals['supplier_taxes_id'] = tax
# Mark if product needs list price update
if vals.get('last_purchase_price'):
vals['list_price_updated'] = True
# Mark if product needs update the shelf tag
if vals.get('list_price'):
vals['to_print'] = True
return super(ProductTemplate, self).write(vals)
def get_supplier_tax(self, taxes_id):
tax_obj = self.env['account.tax']
tax_res = []
if taxes_id:
if "6, False, []" not in taxes_id:
for tupla in taxes_id:
a, b, c = tupla
if c:
for i in c:
tax = tax_obj.browse(i)
val = tax.amount
if val == 21:
record_id = self.env.ref('l10n_es.1_account_tax_template_p_iva21_bc').id
elif val == 10:
record_id = self.env.ref('l10n_es.1_account_tax_template_p_iva10_bc').id
elif val == 4:
record_id = self.env.ref('l10n_es.1_account_tax_template_p_iva4_bc').id
else:
record_id = self.env['account.tax'].search([
('amount','=', val),
('active','=', True),
('type_tax_use','=','purchase')
last_purchase_price_received_compute_type = fields.Selection(
[
("without_discounts", "Without discounts"),
("with_discount", "First discount"),
("with_three_discounts", "Triple discount"),
("manual_update", "Manual update"),
],
limit=1).id
tax_res.append(record_id)
return [(6, 0, tax_res)]
string="Last purchase price calculation type",
help="""
Choose whether discounts should influence the calculation of the last purchase price.
Select Never update for manual configuration of cost and sale prices.\n
* Without discounts: does not take into account discounts when updating
the last purchase price.\n
* First discount: take into account only first discount when updating
the last purchase price.\n
* Triple discount: take into account all discounts when updating
the last purchase price.
Needs "Purchase Triple Discount" OCA module.\n
* Manual update: Select this for manual configuration of cost and sale price.
The sales price will not be calculated automatically.
""",
default="without_discounts",
required=True,
)
@api.onchange(
"last_purchase_price_received",
"standard_price",
"taxes_id",
"margin_classification_id",
"list_price",
)
def _onchange_standard_price(self):
res = super()._onchange_standard_price()
if self.last_purchase_price_received != 0:
(
self.margin_state,
self.theoretical_price,
self.theoretical_difference,
) = self.env["product.product"]._get_margin_info(
self.margin_classification_id,
self.taxes_id,
self.name,
self.last_purchase_price_received,
self.list_price,
)
return res

View file

@ -1,17 +0,0 @@
#import logging
from odoo import models, fields, api
#_logger = logging.getLogger(__name__)
class ResCompany(models.Model):
_inherit = "res.company"
product_pricelist_automatic = fields.Many2one(
comodel_name='product.pricelist',
string='Pricelist applied to the automatic selling price',
help='Rate that applies to all products that update the selling price automatically.',
)

View file

@ -1,30 +1,12 @@
from odoo import models, fields, api
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
_inherit = "res.config.settings"
product_pricelist_automatic = fields.Many2one(
related='company_id.product_pricelist_automatic',
comodel_name='product.pricelist',
string='Pricelist applied to automatic calculation of sales price',
readonly=False,
required=False,
comodel_name="product.pricelist",
string="Pricelist applied to automatic calculation of sales price",
config_parameter="product_update_price_last_purchase.product_pricelist_automatic",
)
@api.model
def get_values(self):
res = super(ResConfigSettings, self).get_values()
config_obj = self.env["ir.config_parameter"]
product_pricelist_automatic = config_obj.sudo().get_param(
"product_update_price_last_purchase.product_pricelist_automatic", default=0)
return res
def set_values(self):
super(ResConfigSettings, self).set_values()
config_obj = self.env["ir.config_parameter"]
config_obj.sudo().set_param(
"product_update_price_last_purchase.product_pricelist_automatic",
int(self.product_pricelist_automatic.id)
)

View file

@ -5,28 +5,56 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
import math
from odoo import exceptions, models, fields, api, _
from odoo.tools import float_is_zero, float_round, float_compare
from odoo import models
from odoo.tools import float_compare, float_is_zero, float_round
_logger = logging.getLogger(__name__)
class StockMove(models.Model):
_inherit = 'stock.move'
_inherit = "stock.move"
def product_price_update_before_done(self):
super(StockMove, self).product_price_update_before_done()
for move in self.filtered(lambda move: move.location_id.usage == 'supplier'):
if move.product_id.last_purchase_price_compute_type == 'with_three_discounts':
price_updated = float_round(move.purchase_line_id.price_subtotal / move.purchase_line_id.product_qty, precision_digits=2)
elif move.product_id.last_purchase_price_compute_type == 'with_discount':
price_updated = float_round(move.purchase_line_id.price_unit * (1 - move.purchase_line_id.discount / 100), precision_digits=2)
res = super(StockMove, self).product_price_update_before_done()
for move in self.filtered(lambda move: move.location_id.usage == "supplier"):
if (
move.product_id.last_purchase_price_received_compute_type
== "with_three_discounts"
):
price_updated = float_round(
move.purchase_line_id.price_subtotal
/ move.purchase_line_id.product_qty,
precision_digits=2,
)
elif (
move.product_id.last_purchase_price_received_compute_type
== "with_discount"
):
price_updated = float_round(
move.purchase_line_id.price_unit
* (1 - move.purchase_line_id.discount / 100),
precision_digits=2,
)
else:
price_updated = move.purchase_line_id.price_unit
if float_compare(move.product_id.last_purchase_price, price_updated, precision_digits=2) and not float_is_zero(move.quantity_done, precision_digits=3):
_logger.info("Update last_purchase_price: %s for product %s Previous price: %s" % (price_updated, move.product_id.default_code, move.product_id.last_purchase_price))
# Write the last purchase price, as SUPERUSER_ID because a warehouse manager may not have the right to write on products
move.product_id.with_context(force_company=move.company_id.id).sudo().write({'last_purchase_price': price_updated})
if float_compare(
move.product_id.last_purchase_price_received,
price_updated,
precision_digits=2,
) and not float_is_zero(move.quantity_done, precision_digits=3):
_logger.info(
"Update last_purchase_price_received: %s for product %s Previous price: %s"
% (
price_updated,
move.product_id.default_code,
move.product_id.last_purchase_price_received,
)
)
# Write last purchase price as SUPERUSER_ID
# warehouse manager may not have the right to write on products
move.product_id.with_company(move.company_id.id).sudo().write(
{"last_purchase_price_received": price_updated}
)
return res

View file

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<report
id="report_productbarcode"
string="Barcode"
model="product.product"
report_type="qweb-pdf"
name="product_update_price_last_purchase.report_productbarcode_update"
file="product_update_price_last_purchase.report_productbarcode_update"/>
<record id="report_productbarcode" model="ir.actions.report" >
<field name="paperformat_id" ref="product_update_price_last_purchase.paperformat_barcode"/>
</record>
<report
id="report_product_product_barcode"
string="Product Barcode (PDF)"
model="product.product"
report_type="qweb-pdf"
name="product.report_productbarcode"
file="product.report_productbarcode"
print_report_name="'Products barcode - %s' % (object.name)"
/>
<record id="report_product_product_barcode" model="ir.actions.report" >
<field name="paperformat_id" ref="product_update_price_last_purchase.paperformat_barcode"/>
</record>
<report
id="report_product_template_barcode"
string="Product Barcode (PDF)"
model="product.product"
report_type="qweb-pdf"
name="product.report_productbarcode"
file="product.report_productbarcode"
print_report_name="'Products barcode - %s' % (object.name)"
/>
<record id="report_product_template_barcode" model="ir.actions.report" >
<field name="paperformat_id" ref="product_update_price_last_purchase.paperformat_barcode"/>
</record>
<report
id="report_simple_barcode_update"
string="Product Barcode (PDF)"
model="product.product"
report_type="qweb-pdf"
name="product.report_productbarcode"
file="product.report_productbarcode"
print_report_name="'Products barcode - %s' % (object.name)"
/>
<record id="report_simple_barcode_update" model="ir.actions.report" >
<field name="paperformat_id" ref="product_update_price_last_purchase.paperformat_barcode"/>
</record>
<report
id="report_productbarcode_update"
string="Product Barcode (PDF)"
model="product.product"
report_type="qweb-pdf"
name="product.report_productbarcode"
file="product.report_productbarcode"
print_report_name="'Products barcode - %s' % (object.name)"
/>
<record id="report_productbarcode_update" model="ir.actions.report" >
<field name="paperformat_id" ref="product_update_price_last_purchase.paperformat_barcode"/>
</record>
</data>
</odoo>

View file

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_simple_barcode_update" inherit_id="product.report_simple_barcode" >
<xpath expr="." position="replace">
<t t-name="product.report_simple_barcode">
<div style="height: 1.65cm; width: 3.5cm; margin-top: 0.2mm; padding: 0; text-align: center; position: relative; display: inline-table; border: 2px solid black;">
<t t-if="product.barcode">
<img alt="Barcode" t-if="len(product.barcode) == 13" t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('EAN13', quote_plus(product.barcode or ''), 600, 150)" style="width: 100%; height: 1.165cm;"/>
<img alt="Barcode" t-elif="len(product.barcode) == 8" t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('EAN8', quote_plus(product.barcode or ''), 600, 150)" style="width:100%;height:4rem;"/>
<img alt="Barcode" t-else="" t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('Code128', quote_plus(product.barcode or ''), 600, 150)" style="width:100%;height:4rem"/>
<span t-field="product.barcode" style="font-size: 0.6em;" />
</t>
<t t-else=""><span class="text-muted">No barcode</span></t>
</div>
</t>
</xpath>
</template>
<template id="report_productbarcode_update" inherit_id="product.report_productbarcode">
<xpath expr="." position="replace">
<t t-name="product.report_productbarcode">
<t t-call="web.html_container">
<div class="page" >
<t t-foreach="docs" t-as="product">
<t t-call="product.report_simple_barcode_update">
<t t-set="product" t-value="product"/>
</t>
</t>
</div>
</t>
</t>
</xpath>
</template>
</odoo>

View file

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<template id="report_simple_label_shelf" inherit_id="product.report_simple_label" >
<xpath expr="." position="replace">
<t t-name="product.report_simple_label">
<div style="height: 4cm; width: 6.7cm; border: 2px solid black; text-align: center; margin: 0; padding: 0; position: relative; display: inline-table;">
<div class="text-center" style="margin: 10px; font-size: 1em; text-align: center;">
<strong t-field="product.name"/>
</div>
<div style="font-size: 1.9em; vertical-align:bottom; position: absolute; bottom: 15; left: 10;">
<strong t-field="product.lst_price" t-options="{'widget': 'monetary', 'display_currency': product.company_id.currency_id}"/>
</div>
<t t-if="product.packaging_ids">
<div style="vertical-align: bottom; position: absolute; bottom: 20; right: 10; font-size: 0.7em; text-align: left;" >
<t t-set="unit_price" t-value="round(product.list_price / product.packaging_ids[0].qty, 1)" />
<strong ><t t-esc="unit_price" t-options="{'widget': 'monetary', 'display_currency': product.company_id.currency_id}"/></strong>
<strong >/</strong>
<strong t-field="product.packaging_ids[0].name"/>
</div>
</t>
</div>
</t>
</xpath>
</template>
<template id="report_producttemplatelabel_shelf" inherit_id="product.report_producttemplatelabel" >
<xpath expr="." position="replace">
<t t-name="product.report_producttemplatelabel">
<t t-call="web.html_container">
<div class="page" style="">
<t t-set="page" t-value="0" />
<t t-foreach="docs" t-as="product">
<t t-call="product.report_simple_label">
<t t-set="product" t-value="product"/>
</t>
</t>
</div>
</t>
</t>
</xpath>
</template>
</data>
</odoo>

View file

@ -1,20 +1,19 @@
<?xml version="1.0"?>
<?xml version="1.0" ?>
<!--
Copyright (C) 2020-Today: La Osa (<https://laosa.coop/>)
@author: Criptomart (https://criptomart.net)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<!-- Add action entry in the Action Menu for calculate sale price in Products -->
<record id="action_product_calculate_theoritical_price" model="ir.actions.server">
<field name="name">Update Sales Price</field>
<field name="model_id" ref="product.model_product_template"/>
<field name="binding_model_id" ref="product.model_product_template"/>
<field name="model_id" ref="product.model_product_template" />
<field name="binding_model_id" ref="product.model_product_template" />
<field name="state">code</field>
<field name="code">
records._compute_theoritical_price()
records.use_theoretical_price()
</field>
</record>
@ -35,4 +34,3 @@
</record>
-->
</odoo>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
@ -7,47 +7,33 @@
<field name="name">product.list.price.automatic.form</field>
<field name="model">product.template</field>
<field name="type">form</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="inherit_id" ref="product.product_template_form_view" />
<field name="arch" type="xml">
<field name="list_price" position="replace">
<field name="list_price"
string="Sale price."
widget="monetary"
options="{'currency_field': 'currency_id', 'field_digits': True}"
attrs="{'readonly': [('last_purchase_price_compute_type','!=', 'manual_update')]}"
/>
<field name="last_purchase_price"
string="Last purchase price"
widget="monetary"
options="{'currency_field': 'currency_id', 'field_digits': True}"
attrs="{'readonly': 1}"
/>
<field name="last_purchase_price_compute_type"/>
<field name="list_price_updated"/>
<field name="to_print"/>
</field>
<label for="list_price" position="before">
<field name="last_purchase_price_received" />
<!-- attrs="{'readonly': 1}"-->
<!-- />-->
<field name="last_purchase_price_received_compute_type" />
<field name="to_print_label" />
</label>
<field name="standard_price" position="replace">
<field name="standard_price" attrs="{'readonly': [('last_purchase_price_compute_type','!=', 'manual_update')]}" />
<field
name="standard_price"
attrs="{'readonly': [('last_purchase_price_received_compute_type','!=', 'manual_update')]}"
/>
</field>
</field>
</record>
<!-- Settings Window -->
<record id="res_config_settings_view_form_pricelists" model="ir.ui.view">
<field name="name">product_update_price_last_purchase.res.config.settings.form</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="100"/>
<field name="inherit_id" ref="stock.res_config_settings_view_form"/>
<record id="product_template_tree_view" model="ir.ui.view">
<field name="name">product.template.product.tree</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_tree_view" />
<field name="arch" type="xml">
<xpath expr="//div[@data-key='stock']" position="inside">
<h2>Default pricelists for Coops</h2>
<div class="row mt16 o_settings_container" name="coop_setting_container">
<div class="row mt16 o_settings_container">
<label for="product_pricelist_automatic"/>
<field name="product_pricelist_automatic"/>
</div>
</div>
</xpath>
<field name="standard_price" position="after">
<field name="last_purchase_price_received" />
<field name="margin_state" invisible="1" />
</field>
</field>
</record>
@ -55,34 +41,23 @@
<record id="view_product_search_form_inherit_updated" model="ir.ui.view">
<field name="name">view.product.search.form.inherit.updated</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_search_view"/>
<field name="inherit_id" ref="product.product_template_search_view" />
<field name="arch" type="xml">
<xpath expr="//filter[@name='services']" position="before">
<separator/>
<filter string="To update sales price"
<filter
string="To update sales price"
name="products_updated_filter"
domain="[('list_price_updated', '=', True), ('last_purchase_price_compute_type', '!=', 'manual_update')]"
help="Products that have recently changed their cost price and have not updated their selling price."
icon="terp-project"
domain="[
('last_purchase_price_received_compute_type', '!=', 'manual_update'),
('margin_state','in', ['too_cheap', 'too_expensive'])
]"
/>
</xpath>
</field>
</record>
<!--Filter for products that should print its shelf label -->
<record id="view_product_search_form_inherit_tags" model="ir.ui.view">
<field name="name">product_update_price_last_purchase.product.search.form.inherit.tags</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_search_view"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='products_updated_filter']" position="after">
<filter string="To print"
<filter
string="To print"
name="products_ready_to_print_filter"
domain="[('to_print', '=', True)]"
help="Products that have changed their sales price and no label has been printed."
icon="terp-project"
domain="[('to_print_label', '=', True)]"
/>
<separator/>
<separator />
</xpath>
</field>
</record>

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record
id="res_config_settings_view_form__compute_pvp_pricelist"
model="ir.ui.view"
>
<field
name="name"
>product.update.price.last.purchase.res.config.settings.form</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="120" />
<field name="inherit_id" ref="sale.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//div[@id='pricing_setting_container']" position="inside">
<div
class="col-12 col-lg-6 o_setting_box"
name="update_price_settigs_container"
>
<div class="o_setting_right_pane">
<label
for="product_pricelist_automatic"
string="PVP Pricelist"
/>
<field name="product_pricelist_automatic" />
</div>
</div>
</xpath>
</field>
</record>
</data>
</odoo>