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

13.0 imp rep cost #343

Merged
merged 9 commits into from Dec 31, 2020
6 changes: 5 additions & 1 deletion price_security/__manifest__.py
Expand Up @@ -19,21 +19,25 @@
##############################################################################
{
'name': 'Price Security',
'version': '13.0.1.0.0',
'version': '13.0.1.1.0',
'category': 'Sales Management',
'author': 'ADHOC SA, Odoo Community Association (OCA)',
'website': 'http://www.adhoc.com.ar/',
'license': 'AGPL-3',
'depends': [
'sale',
'purchase',
# stock_account to hide correctly everything related to standard_price (TODO on v14/v15 this could be
# removed as the wizard has been removed)
'stock_account',
],
'data': [
'security/price_security_security.xml',
'security/ir.model.access.csv',
'views/account_move_views.xml',
'views/account_payment_term_views.xml',
'views/product_template_views.xml',
'views/product_product_views.xml',
'views/res_partner_views.xml',
'views/res_users_views.xml',
'views/sale_order_views.xml',
Expand Down
74 changes: 74 additions & 0 deletions price_security/views/product_product_views.xml
@@ -0,0 +1,74 @@
<?xml version="1.0"?>
<odoo>
<!-- Solo ver: oculta precio de compra y hace readonly -->
<record id="product_product_sale_only_sale_form_view" model="ir.ui.view">
<field name="name">price_security.product.form</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_variant_easy_edit_view"/>
<field name="groups_id" eval="[(6, 0, [ref('group_restrict_prices')])]"/>
<field name="arch" type="xml">
<label for="standard_price" position="attributes">
<attribute name="invisible">1</attribute>
</label>
<div name="update_cost_price" position="attributes">
<attribute name="invisible">1</attribute>
</div>
<button name="%(stock_account.action_view_change_standard_price)d" position="attributes">
<attribute name="invisible">1</attribute>
</button>
<field name="standard_price" position="attributes">
<attribute name="invisible">1</attribute>
<attribute name="readonly">1</attribute>
</field>
</field>
</record>

<!-- Solo ver: restaura precio de compra -->
<record id="product_product_sale_sale_purchase_form_view" model="ir.ui.view">
<field name="name">price_security.product.form</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product_product_sale_only_sale_form_view"/>
<field name="groups_id" eval="[(6, 0, [ref('group_only_view')])]"/>
<field name="priority">30</field>
<field name="arch" type="xml">
<label for="standard_price" position="attributes">
<attribute name="invisible">0</attribute>
</label>
<div name="update_cost_price" position="attributes">
<attribute name="invisible">0</attribute>
</div>
<field name="standard_price" position="attributes">
<attribute name="invisible">0</attribute>
</field>
</field>
</record>

<!-- oculta precio de compra en vista lista -->
<record id="product_product_sale_only_tree_view" model="ir.ui.view">
<field name="name">View Only sale price template form</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_product_tree_view"/>
<field name="groups_id" eval="[(6, 0, [ref('group_restrict_prices')])]"/>
<field name="priority">30</field>
<field name="arch" type="xml">
<field name="standard_price" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>

<!-- restaura precio de compra en vista lista -->
<record id="product_product_sale_purchase_view_tree_view" model="ir.ui.view">
<field name="name">View Only sale price template form</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product_product_sale_only_tree_view"/>
<field name="groups_id" eval="[(6, 0, [ref('group_only_view')])]"/>
<field name="priority">30</field>
<field name="arch" type="xml">
<field name="standard_price" position="attributes">
<attribute name="invisible">0</attribute>
</field>
</field>
</record>

</odoo>
9 changes: 9 additions & 0 deletions price_security/views/product_template_views.xml
Expand Up @@ -29,6 +29,12 @@
</field>

<!-- we hide costing -->
<button name="%(stock_account.action_view_change_standard_price)d" position="attributes">
<attribute name="invisible">1</attribute>
</button>
<div name="standard_price_uom" position="attributes">
<attribute name="invisible">1</attribute>
</div>
<label for="standard_price" position="attributes">
<attribute name="invisible">1</attribute>
</label>
Expand Down Expand Up @@ -78,6 +84,9 @@
<field name="arch" type="xml">

<!-- restore cost fields (they remain readonly) -->
<div name="standard_price_uom" position="attributes">
<attribute name="invisible">0</attribute>
</div>
<field name="seller_ids" position="attributes">
<attribute name="invisible">0</attribute>
</field>
Expand Down
4 changes: 2 additions & 2 deletions price_security_planned_price/__manifest__.py
Expand Up @@ -19,7 +19,7 @@
##############################################################################
{
'name': 'Price Security with planned price',
'version': '13.0.1.0.0',
'version': '13.0.1.1.0',
'category': 'Sales Management',
'author': 'ADHOC SA',
'website': 'http://www.adhoc.com.ar/',
Expand All @@ -32,5 +32,5 @@
'views/product_template_views.xml',
],
'installable': True,
'auto_install': False,
'auto_install': True,
}
3 changes: 0 additions & 3 deletions price_security_planned_price/views/product_template_views.xml
Expand Up @@ -56,9 +56,6 @@
<field name="replenishment_cost_rule_id" position="attributes">
<attribute name="readonly">1</attribute>
</field>
<xpath expr="//group[@name='accounting_cost']//field[@name='standard_price']" position="attributes">
<attribute name="readonly">1</attribute>
</xpath>

</field>
</record>
Expand Down
2 changes: 1 addition & 1 deletion product_planned_price/__manifest__.py
Expand Up @@ -19,7 +19,7 @@
##############################################################################
{
'name': 'Product Planned Price',
'version': '13.0.1.0.0',
'version': '13.0.1.1.0',
'category': 'Product',
'sequence': 14,
'author': 'ADHOC SA,Odoo Community Association (OCA)',
Expand Down
9 changes: 4 additions & 5 deletions product_planned_price/models/product_template.py
Expand Up @@ -3,7 +3,7 @@
# directory
##############################################################################
from odoo import models, fields, api
from odoo.tools import float_compare
from odoo.tools import float_is_zero
import logging
_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -80,10 +80,9 @@ def _update_prices_from_planned(self):
cr = self._cr
for rec in self.with_context(
prefetch_fields=False).search(domain).filtered(
lambda x: x.computed_list_price and float_compare(
x.computed_list_price,
x.list_price,
precision_digits=prec) != 0):
lambda x: x.computed_list_price and not float_is_zero(
x.computed_list_price - x.list_price,
precision_digits=prec)):
# es mucho mas rapido hacerlo por sql directo
cr.execute(
"UPDATE product_template SET list_price=%s WHERE id=%s",
Expand Down
2 changes: 1 addition & 1 deletion product_planned_price/views/product_template_views.xml
Expand Up @@ -27,7 +27,7 @@
<field name="computed_list_price" widget="monetary" attrs="{'invisible': [('list_price_type', 'in', ['manual', False])]}" options="{'currency_field': 'currency_id', 'field_digits': True}"/>
</group>
<group name="list_price" string="Sales Price">
<field name="list_price" widget="monetary" options="{'currency_field': 'currency_id', 'field_digits': True}"/>
<field name="list_price" widget="monetary" options="{'currency_field': 'currency_id', 'field_digits': True}" readonly="1"/>
</group>
</group>
</group>
Expand Down
2 changes: 1 addition & 1 deletion product_replenishment_cost/__manifest__.py
Expand Up @@ -19,7 +19,7 @@
##############################################################################
{
'name': 'Replenishment Cost',
'version': '13.0.1.3.0',
'version': '13.0.1.6.0',
'author': "ADHOC SA, Camptocamp,GRAP,Odoo Community Association (OCA)",
'license': 'AGPL-3',
'category': 'Products',
Expand Down
6 changes: 4 additions & 2 deletions product_replenishment_cost/models/product_supplierinfo.py
Expand Up @@ -19,7 +19,7 @@ class ProductSupplierinfo(models.Model):
inverse='_inverse_net_price',
compute='_compute_net_price',
# TODO, activamos store como estaba??
store=False,
store=True,
digits='Product Price',
help="Net Price",
)
Expand All @@ -43,7 +43,9 @@ def _inverse_net_price(self):
'currency_id',
# and this if we change de date (name field)
# rule items
'replenishment_cost_rule_id',
'replenishment_cost_rule_id.item_ids.sequence',
'replenishment_cost_rule_id.item_ids.percentage_amount',
'replenishment_cost_rule_id.item_ids.fixed_amount',
)
def _compute_net_price(self):
""" For now we only implement when product_tmpl_id is set
Expand Down
62 changes: 27 additions & 35 deletions product_replenishment_cost/models/product_template.py
Expand Up @@ -32,6 +32,8 @@ class ProductTemplate(models.Model):
)
replenishment_cost_last_update = fields.Datetime(
tracking=True,
compute='_compute_replenishment_cost_last_update',
store=True,
)
replenishment_base_cost = fields.Float(
digits='Product Price',
Expand Down Expand Up @@ -65,8 +67,8 @@ class ProductTemplate(models.Model):
required=True,
)

@api.depends('seller_ids')
@api.depends_context('force_company')
@api.depends('seller_ids.net_price', 'seller_ids.currency_id', 'seller_ids.company_id')
def _compute_supplier_data(self):
""" Lo ideal seria utilizar campo related para que segun los permisos
del usuario tome el seller_id que corresponda, pero el tema es que el
Expand All @@ -78,17 +80,11 @@ def _compute_supplier_data(self):
no tiene cia o es cia del usuario.
"""
company_id = self._context.get('force_company', self.env.company.id)
products_with_sellers = self.filtered('seller_ids')
(self - products_with_sellers).update({
'supplier_price': 0.0,
'supplier_currency_id': self.env['res.currency'],
})
for rec in products_with_sellers:
seller_ids = rec.seller_ids.filtered(
lambda x: not x.company_id or x.company_id.id == company_id)
for rec in self:
seller_ids = rec.seller_ids.filtered(lambda x: not x.company_id or x.company_id.id == company_id)
rec.update({
'supplier_price': seller_ids and seller_ids[0].net_price,
'supplier_currency_id': seller_ids and seller_ids[0].currency_id.id or self.env['res.currency'],
'supplier_price': seller_ids and seller_ids[0].net_price or 0.0,
'supplier_currency_id': seller_ids and seller_ids[0].currency_id or self.env['res.currency'],
})

@api.model
Expand All @@ -106,7 +102,7 @@ def _update_cost_from_replenishment_cost(self):

# clave hacerlo en product.product por velocidad (relativo a
# campos standard_price)
products = self.env['product.product'].search(
products = self.with_context(tracking_disable=True).env['product.product'].search(
[('product_tmpl_id.id', 'in', self.ids)])
for product in products.filtered('replenishment_cost'):
replenishment_cost = product.replenishment_cost
Expand All @@ -119,11 +115,11 @@ def _update_cost_from_replenishment_cost(self):
product.standard_price,
replenishment_cost,
precision_digits=prec) != 0:
account = product.property_account_creditor_price_difference \
or product.categ_id.property_account_creditor_price_difference_categ\
or product.property_account_expense_id\
or product.categ_id.property_account_expense_categ_id
if product.valuation == 'real_time':
if product._fields.get('valuation') and product.valuation == 'real_time':
account = product.property_account_creditor_price_difference \
or product.categ_id.property_account_creditor_price_difference_categ\
or product.property_account_expense_id\
or product.categ_id.property_account_expense_categ_id
# we force to change company to env when we run with "force_company" in the context, because
# odoo use the env company to in the change price method
if self._context.get('force_company', False):
Expand All @@ -137,38 +133,38 @@ def _update_cost_from_replenishment_cost(self):
product.standard_price = replenishment_cost
return True

@api.constrains(
@api.depends(
'replenishment_base_cost',
'replenishment_base_cost_currency_id',
)
def update_replenishment_cost_last_update(self):
# con el tracking_disable nos ahorramos doble mensaje
self.with_context(tracking_disable=True).write(
{'replenishment_cost_last_update': fields.Datetime.now()})
def _compute_replenishment_cost_last_update(self):
self.replenishment_cost_last_update = fields.Datetime.now()

# TODO ver si necesitamos borrar estos depends o no, por ahora
# no parecen afectar performance y sirvern para que la interfaz haga
# el onchange, pero no son fundamentales porque el campo no lo storeamos
@api.depends(
'currency_id',
# no usamos estos depends porque afetan un poco la performance al actualizar costo de reposicion, al menos
# testeado desde cron de precio planeado usando de reposicion
# 'currency_id',
# 'supplier_price',
# 'supplier_currency_id',
'replenishment_cost_type',
'replenishment_base_cost',
# beccause field is not stored anymore we only keep currency and
# rule
'replenishment_base_cost_currency_id',
# 'replenishment_base_cost_currency_id',
# # because of being stored
# 'replenishment_base_cost_currency_id.rate_ids.rate',
'replenishment_base_cost_currency_id.rate_ids.rate',
# # and this if we change de date (name field)
# 'replenishment_base_cost_currency_id.rate_ids.name',
# rule items
'replenishment_cost_rule_id',
# 'replenishment_cost_rule_id.item_ids.sequence',
# 'replenishment_cost_rule_id.item_ids.percentage_amount',
# 'replenishment_cost_rule_id.item_ids.fixed_amount',
'replenishment_cost_rule_id.item_ids.sequence',
'replenishment_cost_rule_id.item_ids.percentage_amount',
'replenishment_cost_rule_id.item_ids.fixed_amount',
)
def _compute_replenishment_cost(self):
_logger.info(
'Getting replenishment cost for ids %s' % self.ids)
_logger.info('Getting replenishment cost for %s products' % len(self.ids))
company = self.env.company
date = fields.Date.today()
for rec in self:
Expand Down Expand Up @@ -201,7 +197,3 @@ def _compute_replenishment_cost(self):
replenishment_base_cost_on_currency,
'replenishment_cost': replenishment_cost
})

@api.constrains('replenishment_cost_rule_id')
def update_replenishment_cost_last_update_by_rule(self):
self.update_replenishment_cost_last_update()
8 changes: 4 additions & 4 deletions product_replenishment_cost/views/product_template_views.xml
Expand Up @@ -25,10 +25,10 @@
<field name="replenishment_cost" string="Replenishment Cost" widget="monetary" options="{'currency_field': 'currency_id','field_digits': True}"/>
</group>
<group name="accounting_cost" string="Accounting Cost">
<!-- we only change label -->
<label for="standard_price" groups="base.group_user" string="Accounting Cost" attrs="{'invisible': [('product_variant_count', '&gt;', 1), ('is_product_variant', '=', False)]}"/>
<div name="standard_price" groups="base.group_user" attrs="{'invisible': [('product_variant_count', '&gt;', 1), ('is_product_variant', '=', False)]}">
<field name="standard_price" widget="monetary" options="{'currency_field': 'cost_currency_id','field_digits': True}" class="oe_inline" attrs="{'readonly':[('valuation','=','real_time')]}"/>
<label for="standard_price" groups="base.group_user" string="Accounting Cost"/>
<div name="standard_price" groups="base.group_user">
<field name="standard_price" widget="monetary" options="{'currency_field': 'cost_currency_id','field_digits': True}" class="oe_inline" readonly="1" attrs="{'invisible': [('product_variant_count', '&gt;', 1), ('is_product_variant', '=', False)]}"/>
<button name="%(product.product_variant_action)d" icon="fa-arrow-right" type="action" attrs="{'invisible': ['|', ('product_variant_count', '&lt;=', 1), ('is_product_variant', '=', True)]}" groups="product.group_product_variant" string="Variants Costs" class="oe_inline"/>
</div>
</group>
</group>
Expand Down