mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[MRG][ADD] stock_lot_valuation : Stock valuation (standard or average price, ...) based on lots.
This module extends standard stock valuation (based on products). Valuing lots allows to have different costs for different lots of the same product.
This commit is contained in:
1
stock_lot_valuation/AUTHORS.txt
Normal file
1
stock_lot_valuation/AUTHORS.txt
Normal file
@@ -0,0 +1 @@
|
||||
Lorenzo Battistini <lorenzo.battistini@agilebg.com>
|
||||
23
stock_lot_valuation/__init__.py
Normal file
23
stock_lot_valuation/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import product
|
||||
import stock
|
||||
import wizard
|
||||
52
stock_lot_valuation/__openerp__.py
Normal file
52
stock_lot_valuation/__openerp__.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': "Lot Valuation",
|
||||
'version': '0.1',
|
||||
'category': 'Warehouse Management',
|
||||
'description': """
|
||||
Stock valuation (standard or average price, ...) based on lots.
|
||||
This module extends standard stock valuation (based on products).
|
||||
Valuing lots allows to have different costs for different lots of the same
|
||||
product.
|
||||
|
||||
Usage
|
||||
-----
|
||||
Set the 'Lot valuation' flag on product form (used for real time valuation).
|
||||
As for products, lots have 'cost' and 'costing method' fields. Also, a
|
||||
'Change Standard Price' wizard is available.
|
||||
""",
|
||||
'author': 'Agile Business Group',
|
||||
'website': 'http://www.agilebg.com',
|
||||
'license': 'AGPL-3',
|
||||
"depends": ['stock'],
|
||||
"data": [
|
||||
"wizard/stock_change_standard_price_view.xml",
|
||||
"product_view.xml",
|
||||
"stock_view.xml",
|
||||
],
|
||||
"demo": [],
|
||||
'test': [
|
||||
'test/stock.yml', # TODO cover user interface operations
|
||||
],
|
||||
"active": False,
|
||||
"installable": True
|
||||
}
|
||||
205
stock_lot_valuation/i18n/stock_lot_valuation.pot
Normal file
205
stock_lot_valuation/i18n/stock_lot_valuation.pot
Normal file
@@ -0,0 +1,205 @@
|
||||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * stock_lot_valuation
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 7.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-10-18 16:17+0000\n"
|
||||
"PO-Revision-Date: 2013-10-18 16:17+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: selection:stock.production.lot,cost_method:0
|
||||
msgid "Average Price"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: field:lot.change.standard.price,stock_journal:0
|
||||
msgid "Stock journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: field:lot.change.standard.price,enable_stock_in_out_acc:0
|
||||
msgid "Enable Related Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: model:ir.model,name:stock_lot_valuation.model_stock_picking
|
||||
msgid "Picking List"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: code:addons/stock_lot_valuation/stock.py:132
|
||||
#, python-format
|
||||
msgid "Please specify company in Location."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: code:addons/stock_lot_valuation/stock.py:145
|
||||
#, python-format
|
||||
msgid "Please define journal on the product category: '%s' (id: %d)."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: model:ir.model,name:stock_lot_valuation.model_product_product
|
||||
msgid "Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: help:stock.production.lot,standard_price:0
|
||||
msgid "Cost price (in company currency) of the lot used for standard stock valuation in accounting."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: field:lot.change.standard.price,new_price:0
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: model:ir.model,name:stock_lot_valuation.model_stock_production_lot
|
||||
msgid "Serial Number"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: code:addons/stock_lot_valuation/stock.py:123
|
||||
#, python-format
|
||||
msgid "No difference between standard price! and new price"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: selection:stock.production.lot,cost_method:0
|
||||
msgid "Standard Price"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: model:ir.model,name:stock_lot_valuation.model_stock_partial_picking
|
||||
msgid "Partial Picking Processing Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: view:lot.change.standard.price:0
|
||||
#: view:stock.production.lot:0
|
||||
msgid "Cost Price"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: help:lot.change.standard.price,new_price:0
|
||||
msgid "If cost price is increased, stock variation account will be debited and stock output account will be credited with the value = (difference of amount * quantity available).\n"
|
||||
"If cost price is decreased, stock variation account will be creadited and stock input account will be debited."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: field:product.product,lot_valuation:0
|
||||
msgid "Lot valuation"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: help:stock.production.lot,cost_method:0
|
||||
msgid "Standard Price: The cost price is manually updated at the end of a specific period. \n"
|
||||
"Average Price: The cost price is recomputed at each incoming shipment."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: view:stock.production.lot:0
|
||||
msgid "update"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: code:addons/stock_lot_valuation/stock.py:100
|
||||
#: code:addons/stock_lot_valuation/stock.py:122
|
||||
#: code:addons/stock_lot_valuation/stock.py:131
|
||||
#: code:addons/stock_lot_valuation/stock.py:144
|
||||
#: code:addons/stock_lot_valuation/stock.py:167
|
||||
#: code:addons/stock_lot_valuation/stock.py:196
|
||||
#, python-format
|
||||
msgid "Error!"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: field:stock.production.lot,cost_method:0
|
||||
msgid "Costing Method"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: code:addons/stock_lot_valuation/wizard/stock_change_standard_price.py:100
|
||||
#, python-format
|
||||
msgid "Active ID is not set in Context."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: view:lot.change.standard.price:0
|
||||
msgid "_Apply"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: view:lot.change.standard.price:0
|
||||
msgid "Change Price"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: field:lot.change.standard.price,stock_account_output:0
|
||||
msgid "Stock Output Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: help:product.product,lot_valuation:0
|
||||
msgid "Use lot valuation instead of product valuation"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: code:addons/stock_lot_valuation/stock.py:197
|
||||
#, python-format
|
||||
msgid "Please define stock output account for this product: '%s' (id: %d)."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: model:ir.model,name:stock_lot_valuation.model_stock_move
|
||||
msgid "Stock Move"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: view:lot.change.standard.price:0
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: field:stock.production.lot,standard_price:0
|
||||
msgid "Cost"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: field:lot.change.standard.price,stock_account_input:0
|
||||
msgid "Stock Input Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: model:ir.actions.act_window,name:stock_lot_valuation.action_view_change_standard_price
|
||||
#: model:ir.model,name:stock_lot_valuation.model_lot_change_standard_price
|
||||
#: view:lot.change.standard.price:0
|
||||
msgid "Change Standard Price"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: code:addons/stock_lot_valuation/stock.py:168
|
||||
#, python-format
|
||||
msgid "Please define stock input account for this product: '%s' (id: %d)."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: view:lot.change.standard.price:0
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_lot_valuation
|
||||
#: code:addons/stock_lot_valuation/stock.py:101
|
||||
#, python-format
|
||||
msgid "Specify valuation Account for Product Category: %s."
|
||||
msgstr ""
|
||||
|
||||
32
stock_lot_valuation/product.py
Normal file
32
stock_lot_valuation/product.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import fields, orm
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class product_product(orm.Model):
|
||||
_inherit = "product.product"
|
||||
|
||||
_columns = {
|
||||
'lot_valuation': fields.boolean(
|
||||
'Lot valuation',
|
||||
help="Use lot valuation instead of product valuation"),
|
||||
}
|
||||
15
stock_lot_valuation/product_view.xml
Normal file
15
stock_lot_valuation/product_view.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="product_normal_form_view" model="ir.ui.view">
|
||||
<field name="name">product_normal_form_view</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="stock.view_normal_property_acc_form"></field>
|
||||
<field name="arch" type="xml">
|
||||
<field name="valuation" position="after">
|
||||
<field name="lot_valuation"></field>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
358
stock_lot_valuation/stock.py
Normal file
358
stock_lot_valuation/stock.py
Normal file
@@ -0,0 +1,358 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import fields, orm
|
||||
from openerp.tools.translate import _
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class stock_production_lot(orm.Model):
|
||||
_inherit = "stock.production.lot"
|
||||
|
||||
_columns = {
|
||||
'standard_price': fields.float(
|
||||
'Cost', digits_compute=dp.get_precision('Lot Price'),
|
||||
help="Cost price (in company currency) of the lot used for "
|
||||
"standard stock valuation in accounting.",
|
||||
groups="base.group_user"
|
||||
),
|
||||
'cost_method': fields.selection(
|
||||
[
|
||||
('standard', 'Standard Price'),
|
||||
('average', 'Average Price')
|
||||
], 'Costing Method',
|
||||
help="Standard Price: The cost price is manually updated at the "
|
||||
"end of a specific period. \nAverage Price: The cost price is "
|
||||
"recomputed at each incoming shipment."
|
||||
),
|
||||
}
|
||||
|
||||
def price_get(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = {}
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
for lot in self.browse(cr, uid, ids, context=context):
|
||||
res[lot.id] = lot['standard_price'] or 0.0
|
||||
if 'uom' in context:
|
||||
uom = lot.product_id.uom_id or lot.product_id.uos_id
|
||||
res[lot.id] = product_uom_obj._compute_price(
|
||||
cr, uid,
|
||||
uom.id, res[lot.id], context['uom'])
|
||||
# Convert from price_type currency to asked one
|
||||
if 'currency_id' in context:
|
||||
currency_id = False
|
||||
if lot.company_id and lot.company_id.currency_id:
|
||||
currency_id = lot.company_id.currency_id.id
|
||||
elif (
|
||||
lot.product_id.company_id
|
||||
and lot.product_id.company_id.currency_id
|
||||
):
|
||||
currency_id = lot.product_id.company_id.currency_id.id
|
||||
if currency_id:
|
||||
res[lot.id] = self.pool.get('res.currency').compute(
|
||||
cr, uid,
|
||||
currency_id,
|
||||
context['currency_id'], res[lot.id], context=context)
|
||||
return res
|
||||
|
||||
def do_change_standard_price(self, cr, uid, ids, datas, context=None):
|
||||
""" Changes the Standard Price of Lot and creates an account move
|
||||
accordingly.
|
||||
@param datas : dict. contain default datas like new_price,
|
||||
stock_output_account, stock_input_account, stock_journal
|
||||
@param context: A standard dictionary
|
||||
"""
|
||||
location_obj = self.pool.get('stock.location')
|
||||
move_obj = self.pool.get('account.move')
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
new_price = datas.get('new_price', 0.0)
|
||||
stock_output_acc = datas.get('stock_output_account', False)
|
||||
stock_input_acc = datas.get('stock_input_account', False)
|
||||
journal_id = datas.get('stock_journal', False)
|
||||
lot_obj = self.browse(cr, uid, ids, context=context)[0]
|
||||
account_valuation = (
|
||||
lot_obj.product_id.categ_id.property_stock_valuation_account_id)
|
||||
account_valuation_id = (
|
||||
account_valuation and account_valuation.id or False)
|
||||
if not account_valuation_id:
|
||||
raise orm.except_orm(
|
||||
_('Error!'),
|
||||
_('Specify valuation Account for Product Category: %s.')
|
||||
% (lot_obj.product_id.categ_id.name))
|
||||
move_ids = []
|
||||
loc_ids = location_obj.search(
|
||||
cr, uid, [('usage', '=', 'internal')],
|
||||
context=context)
|
||||
for rec_id in ids:
|
||||
for location in location_obj.browse(
|
||||
cr, uid, loc_ids, context=context
|
||||
):
|
||||
c = context.copy()
|
||||
c.update({
|
||||
'location_id': location.id,
|
||||
'compute_child': False
|
||||
})
|
||||
|
||||
lot = self.browse(cr, uid, rec_id, context=c)
|
||||
qty = lot.stock_available
|
||||
diff = lot.standard_price - new_price
|
||||
if not diff:
|
||||
raise orm.except_orm(
|
||||
_('Error!'),
|
||||
_("No difference between standard price!"
|
||||
" and new price"))
|
||||
if qty:
|
||||
company_id = (
|
||||
location.company_id and location.company_id.id or False
|
||||
)
|
||||
if not company_id:
|
||||
raise orm.except_orm(
|
||||
_('Error!'),
|
||||
_('Please specify company in Location.'))
|
||||
#
|
||||
# Accounting Entries
|
||||
#
|
||||
product = lot.product_id
|
||||
if (
|
||||
not journal_id
|
||||
and product.categ_id.property_stock_journal
|
||||
):
|
||||
journal_id = product.categ_id.property_stock_journal.id
|
||||
if not journal_id:
|
||||
raise orm.except_orm(
|
||||
_('Error!'),
|
||||
_("Please define journal "
|
||||
"on the product category: '%s' (id: %d).") %
|
||||
(product.categ_id.name, product.categ_id.id,))
|
||||
move_id = move_obj.create(cr, uid, {
|
||||
'journal_id': journal_id,
|
||||
'company_id': company_id
|
||||
}, context=context)
|
||||
|
||||
move_ids.append(move_id)
|
||||
|
||||
if diff > 0:
|
||||
if not stock_input_acc:
|
||||
stock_input_acc = (
|
||||
product.property_stock_account_input.id
|
||||
)
|
||||
if not stock_input_acc:
|
||||
stock_input_acc = (
|
||||
product.categ_id.
|
||||
property_stock_account_input_categ.id
|
||||
)
|
||||
if not stock_input_acc:
|
||||
raise orm.except_orm(
|
||||
_('Error!'),
|
||||
_("Please define stock input account "
|
||||
"for this product: '%s' (id: %d).") %
|
||||
(product.name, product.id,))
|
||||
amount_diff = qty * diff
|
||||
move_line_obj.create(cr, uid, {
|
||||
'name': product.name,
|
||||
'account_id': stock_input_acc,
|
||||
'debit': amount_diff,
|
||||
'move_id': move_id,
|
||||
}, context=context)
|
||||
move_line_obj.create(cr, uid, {
|
||||
'name': product.categ_id.name,
|
||||
'account_id': account_valuation_id,
|
||||
'credit': amount_diff,
|
||||
'move_id': move_id
|
||||
}, context=context)
|
||||
elif diff < 0:
|
||||
if not stock_output_acc:
|
||||
stock_output_acc = (
|
||||
product.property_stock_account_output.id
|
||||
)
|
||||
if not stock_output_acc:
|
||||
stock_output_acc = (
|
||||
product.categ_id.
|
||||
property_stock_account_output_categ.id
|
||||
)
|
||||
if not stock_output_acc:
|
||||
raise orm.except_orm(
|
||||
_('Error!'),
|
||||
_("Please define stock output account "
|
||||
"for this product: '%s' (id: %d).") %
|
||||
(product.name, product.id,))
|
||||
amount_diff = qty * -diff
|
||||
move_line_obj.create(cr, uid, {
|
||||
'name': product.name,
|
||||
'account_id': stock_output_acc,
|
||||
'credit': amount_diff,
|
||||
'move_id': move_id
|
||||
}, context=context)
|
||||
move_line_obj.create(cr, uid, {
|
||||
'name': product.categ_id.name,
|
||||
'account_id': account_valuation_id,
|
||||
'debit': amount_diff,
|
||||
'move_id': move_id
|
||||
}, context=context)
|
||||
|
||||
self.write(cr, uid, rec_id, {'standard_price': new_price})
|
||||
|
||||
return move_ids
|
||||
|
||||
|
||||
class stock_move(orm.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
def _get_reference_accounting_values_for_valuation(
|
||||
self, cr, uid, move, context=None
|
||||
):
|
||||
res = super(
|
||||
stock_move, self)._get_reference_accounting_values_for_valuation(
|
||||
cr, uid, move, context=context)
|
||||
if move.product_id.lot_valuation and move.prodlot_id:
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
qty = product_uom_obj._compute_qty(
|
||||
cr, uid, move.product_uom.id,
|
||||
move.product_qty, move.product_id.uom_id.id)
|
||||
if context is None:
|
||||
context = {}
|
||||
currency_ctx = dict(
|
||||
context, currency_id=move.company_id.currency_id.id)
|
||||
amount_unit = move.prodlot_id.price_get(
|
||||
context=currency_ctx)[move.prodlot_id.id]
|
||||
reference_amount = amount_unit * qty
|
||||
new_res = (reference_amount, move.company_id.currency_id.id)
|
||||
res = new_res
|
||||
return res
|
||||
|
||||
def do_partial(self, cr, uid, ids, partial_datas, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
for move in self.browse(cr, uid, ids, context=context):
|
||||
pick_obj.write_lot(cr, uid, move, partial_datas, context=context)
|
||||
res = super(stock_move, self).do_partial(
|
||||
cr, uid, ids, partial_datas, context=context)
|
||||
return res
|
||||
|
||||
|
||||
class stock_picking(orm.Model):
|
||||
_inherit = "stock.picking"
|
||||
|
||||
def compute_price(self, cr, uid, partial_datas, move, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
lot_obj = self.pool.get('stock.production.lot')
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
move_obj = self.pool.get('stock.move')
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
partial_data = partial_datas.get('move%s' % (move.id), {})
|
||||
product_uom = partial_data.get('product_uom', False)
|
||||
product_qty = partial_data.get('product_qty', 0.0)
|
||||
product_currency = partial_data.get('product_currency', False)
|
||||
product_price = partial_data.get('product_price', 0.0)
|
||||
|
||||
lot = lot_obj.browse(cr, uid, move.prodlot_id.id, context=context)
|
||||
product = lot.product_id
|
||||
move_currency_id = move.company_id.currency_id.id
|
||||
context['currency_id'] = move_currency_id
|
||||
qty = uom_obj._compute_qty(
|
||||
cr, uid, product_uom, product_qty, product.uom_id.id)
|
||||
if qty > 0:
|
||||
new_price = currency_obj.compute(
|
||||
cr, uid, product_currency,
|
||||
move_currency_id, product_price)
|
||||
new_price = uom_obj._compute_price(
|
||||
cr, uid, product_uom, new_price,
|
||||
product.uom_id.id)
|
||||
if lot.stock_available <= 0:
|
||||
new_std_price = new_price
|
||||
else:
|
||||
# Get the standard price
|
||||
amount_unit = lot.price_get(context=context)[lot.id]
|
||||
new_std_price = (
|
||||
((amount_unit * lot.stock_available)
|
||||
+ (new_price * qty)) / (lot.stock_available + qty)
|
||||
)
|
||||
|
||||
lot_obj.write(
|
||||
cr, uid, [lot.id], {'standard_price': new_std_price},
|
||||
context=context
|
||||
)
|
||||
|
||||
# Record the values that were chosen in the wizard, so they can be
|
||||
# used for inventory valuation if real-time valuation is enabled.
|
||||
move_obj.write(cr, uid, [move.id], {
|
||||
'price_unit': product_price,
|
||||
'price_currency_id': product_currency
|
||||
}, context=context)
|
||||
|
||||
def write_lot(self, cr, uid, move, partial_datas, context=None):
|
||||
lot_obj = self.pool.get('stock.production.lot')
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
if partial_datas.get('move%s' % (move.id)):
|
||||
partial_data = partial_datas.get('move%s' % (move.id), {})
|
||||
product_price = partial_data.get('product_price', 0.0)
|
||||
product_currency = partial_data.get('product_currency', False)
|
||||
product_uom = partial_data.get('product_uom', False)
|
||||
if partial_data.get('prodlot_id'):
|
||||
lot = lot_obj.browse(
|
||||
cr, uid, partial_data['prodlot_id'], context)
|
||||
product = lot.product_id
|
||||
if (
|
||||
move.product_id.lot_valuation and (
|
||||
move.picking_id.type == 'in'
|
||||
) and (lot.cost_method == 'average')
|
||||
):
|
||||
self.compute_price(
|
||||
cr, uid, partial_datas, move, context=context)
|
||||
if (
|
||||
move.product_id.lot_valuation and product_price
|
||||
and not lot.standard_price
|
||||
):
|
||||
new_price = currency_obj.compute(
|
||||
cr, uid, product_currency,
|
||||
move.company_id.currency_id.id, product_price)
|
||||
new_price = uom_obj._compute_price(
|
||||
cr, uid, product_uom, new_price,
|
||||
product.uom_id.id)
|
||||
lot.write({'standard_price': new_price})
|
||||
|
||||
def do_partial(self, cr, uid, ids, partial_datas, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
for pick in self.browse(cr, uid, ids, context=context):
|
||||
for move in pick.move_lines:
|
||||
self.write_lot(cr, uid, move, partial_datas, context=context)
|
||||
res = super(stock_picking, self).do_partial(
|
||||
cr, uid, ids, partial_datas, context=context)
|
||||
return res
|
||||
|
||||
|
||||
class stock_partial_picking(orm.TransientModel):
|
||||
_inherit = "stock.partial.picking"
|
||||
|
||||
def _product_cost_for_average_update(self, cr, uid, move):
|
||||
res = super(
|
||||
stock_partial_picking, self
|
||||
)._product_cost_for_average_update(cr, uid, move)
|
||||
if move.prodlot_id and move.product_id.lot_valuation:
|
||||
res['cost'] = move.prodlot_id.standard_price
|
||||
return res
|
||||
22
stock_lot_valuation/stock_view.xml
Normal file
22
stock_lot_valuation/stock_view.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_production_lot_form" model="ir.ui.view">
|
||||
<field name="name">view_production_lot_form</field>
|
||||
<field name="model">stock.production.lot</field>
|
||||
<field name="inherit_id" ref="stock.view_production_lot_form"></field>
|
||||
<field name="arch" type="xml">
|
||||
<field name="stock_available" position="after" version="7.0">
|
||||
<field name="cost_method"></field>
|
||||
<label string="Cost Price" for="standard_price" align="1.0" groups="base.group_user"/>
|
||||
<div groups="base.group_user">
|
||||
<field name="standard_price" attrs="{'readonly':[('cost_method','=','average')]}" nolabel="1"/>
|
||||
<button name="%(action_view_change_standard_price)d" string="update"
|
||||
type="action" attrs="{'invisible':[('cost_method','<>','average')]}"
|
||||
class="oe_link" groups="product.group_costing_method"/>
|
||||
</div>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
230
stock_lot_valuation/test/stock.yml
Normal file
230
stock_lot_valuation/test/stock.yml
Normal file
@@ -0,0 +1,230 @@
|
||||
-
|
||||
!record {model: stock.location, id: location_refrigerator}:
|
||||
name: Refrigerator
|
||||
usage: internal
|
||||
-
|
||||
!record {model: stock.location, id: location_delivery_counter}:
|
||||
name: Delivery Counter
|
||||
usage: internal
|
||||
-
|
||||
!record {model: stock.location, id: location_refrigerator_small}:
|
||||
name: Small Refrigerator
|
||||
usage: internal
|
||||
location_id: location_refrigerator
|
||||
-
|
||||
!record {model: stock.location, id: location_opening}:
|
||||
name: opening
|
||||
usage: inventory
|
||||
-
|
||||
!record {model: stock.location, id: location_convenience_shop}:
|
||||
name: Convenient Store
|
||||
usage: supplier
|
||||
-
|
||||
!record {model: stock.warehouse, id: warehouse_icecream}:
|
||||
name: Ice Cream Shop
|
||||
lot_input_id: location_refrigerator
|
||||
lot_stock_id: location_refrigerator
|
||||
lot_output_id: location_delivery_counter
|
||||
-
|
||||
!record {model: product.product, id: product_icecream}:
|
||||
default_code: 001
|
||||
name: Ice Cream
|
||||
type: product
|
||||
categ_id: product.product_category_1
|
||||
list_price: 100.0
|
||||
standard_price: 70.0
|
||||
uom_id: product.product_uom_kgm
|
||||
uom_po_id: product.product_uom_kgm
|
||||
procure_method: make_to_stock
|
||||
property_stock_inventory: location_opening
|
||||
valuation: real_time
|
||||
cost_method: average
|
||||
property_stock_account_input: account.o_expense
|
||||
property_stock_account_output: account.o_income
|
||||
description: Ice cream can be mass-produced and thus is widely available in developed parts of the world. Ice cream can be purchased in large cartons (vats and squrounds) from supermarkets and grocery stores, in smaller quantities from ice cream shops, convenience stores, and milk bars, and in individual servings from small carts or vans at public events.
|
||||
lot_valuation: True
|
||||
|
||||
-
|
||||
!record {model: stock.production.lot, id: lot_icecream_0}:
|
||||
name: Lot0 for Ice cream
|
||||
product_id: product_icecream
|
||||
cost_method: average
|
||||
standard_price: 70.0
|
||||
-
|
||||
!record {model: stock.production.lot, id: lot_icecream_1}:
|
||||
name: Lot1 for Ice cream
|
||||
product_id: product_icecream
|
||||
-
|
||||
!record {model: stock.inventory, id: stock_inventory_icecream}:
|
||||
name: Inventory for icecream
|
||||
-
|
||||
!record {model: stock.inventory.line, id: stock_inventory_line_icecream_lot0}:
|
||||
product_id: product_icecream
|
||||
product_uom: product.product_uom_kgm
|
||||
inventory_id: stock_inventory_icecream
|
||||
product_qty: 50.0
|
||||
prod_lot_id: lot_icecream_0
|
||||
location_id: location_refrigerator
|
||||
-
|
||||
!record {model: stock.inventory.line, id: stock_inventory_line_icecream_lot1}:
|
||||
product_id: product_icecream
|
||||
product_uom: product.product_uom_kgm
|
||||
inventory_id: stock_inventory_icecream
|
||||
product_qty: 40.0
|
||||
prod_lot_id: lot_icecream_1
|
||||
location_id: location_refrigerator
|
||||
|
||||
-
|
||||
!record {model: stock.picking, id: outgoing_shipment}:
|
||||
type: out
|
||||
location_dest_id: location_delivery_counter
|
||||
-
|
||||
!record {model: stock.move, id: outgoing_shipment_icecream}:
|
||||
picking_id: outgoing_shipment
|
||||
product_id: product_icecream
|
||||
product_uom: product.product_uom_kgm
|
||||
product_qty: 130.0
|
||||
location_id: location_refrigerator
|
||||
location_dest_id: location_delivery_counter
|
||||
prodlot_id: lot_icecream_0
|
||||
-
|
||||
!record {model: stock.picking, id: incoming_shipment}:
|
||||
type: in
|
||||
invoice_state: 2binvoiced
|
||||
partner_id: base.res_partner_address_9
|
||||
location_dest_id: location_refrigerator
|
||||
-
|
||||
!record {model: stock.move, id: incoming_shipment_icecream}:
|
||||
picking_id: incoming_shipment
|
||||
product_id: product_icecream
|
||||
product_uom: product.product_uom_kgm
|
||||
product_qty: 50.0
|
||||
location_id: location_convenience_shop
|
||||
location_dest_id: location_refrigerator
|
||||
prodlot_id: lot_icecream_0
|
||||
|
||||
-
|
||||
I update the price of the Ice-cream.
|
||||
-
|
||||
!python {model: stock.change.standard.price}: |
|
||||
context.update({'active_model':'product.product', 'active_id': ref('product_icecream'), 'active_ids':[ref('product_icecream')]})
|
||||
-
|
||||
!record {model: stock.change.standard.price, id: change_price}:
|
||||
new_price: 120
|
||||
-
|
||||
!python {model: stock.change.standard.price}: |
|
||||
self.change_price(cr, uid, [ref('change_price')], context=context)
|
||||
-
|
||||
I check price of Ice-cream after update price.
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
product = self.browse(cr, uid, ref('product_icecream'), context=context)
|
||||
assert product.standard_price == 120, "Price is not updated."
|
||||
|
||||
-
|
||||
I confirm physical inventory of Ice-cream which are came in different lots.
|
||||
-
|
||||
!python {model: stock.inventory}: |
|
||||
self.action_confirm(cr, uid, [ref('stock_inventory_icecream')], context=context)
|
||||
-
|
||||
I check move details after confirmed physical inventory.
|
||||
-
|
||||
!python {model: stock.inventory}: |
|
||||
inventory = self.browse(cr, uid, ref('stock_inventory_icecream'), context=context)
|
||||
assert len(inventory.move_ids) == len(inventory.inventory_line_id), "moves are not correspond."
|
||||
for move_line in inventory.move_ids:
|
||||
for line in inventory.inventory_line_id:
|
||||
if move_line.product_id.id == line.product_id.id and move_line.prodlot_id.id == line.prod_lot_id.id:
|
||||
location_id = line.product_id.property_stock_inventory.id
|
||||
assert move_line.product_qty == line.product_qty, "Qty is not correspond."
|
||||
assert move_line.product_uom.id == line.product_uom.id, "UOM is not correspond."
|
||||
assert move_line.date == inventory.date, "Date is not correspond."
|
||||
assert move_line.location_id.id == location_id, "Source location is not correspond."
|
||||
assert move_line.location_dest_id.id == line.location_id.id, "Destination location is not correspond."
|
||||
assert move_line.state == 'confirmed', "Move is not confirmed."
|
||||
|
||||
-
|
||||
Now I check vitual stock of Ice-cream after confirmed physical inventory.
|
||||
-
|
||||
!python {model: product.product}: |
|
||||
product = self.browse(cr, uid, ref('product_icecream'), context=context)
|
||||
assert product.virtual_available == 90, "Vitual stock is not updated."
|
||||
|
||||
-
|
||||
I complete physical inventory of Ice-cream.
|
||||
-
|
||||
!python {model: stock.inventory}: |
|
||||
self.action_done(cr, uid, [ref('stock_inventory_icecream')], context=context)
|
||||
balance = self.pool.get('account.account').browse(cr, uid, ref('account.stk')).balance
|
||||
assert balance == 3500.0, "Purchased Stocks balance is %s, not 3500 (50*70)" % balance
|
||||
-
|
||||
I update the price of the Ice-cream lot.
|
||||
-
|
||||
!python {model: lot.change.standard.price}: |
|
||||
context.update({'active_model':'stock.production.lot', 'active_id': ref('lot_icecream_0'), 'active_ids':[ref('lot_icecream_0')]})
|
||||
-
|
||||
!record {model: lot.change.standard.price, id: change_price}:
|
||||
new_price: 120
|
||||
-
|
||||
!python {model: lot.change.standard.price}: |
|
||||
self.change_price(cr, uid, [ref('change_price')], context=context)
|
||||
-
|
||||
I check price of Ice-cream lot after update price.
|
||||
-
|
||||
!python {model: stock.production.lot}: |
|
||||
lot = self.browse(cr, uid, ref('lot_icecream_0'), context=context)
|
||||
assert lot.standard_price == 120, "Price is not updated."
|
||||
balance = self.pool.get('account.account').browse(cr, uid, ref('account.stk')).balance
|
||||
assert balance == 6000.0, "Purchased Stocks balance is %s, not 6000 (old balance + (lot.standard_price - new_price) * lot.stock_available)" % balance
|
||||
|
||||
-
|
||||
I confirm outgoing shipment of 130 kgm Ice-cream.
|
||||
-
|
||||
!workflow {model: stock.picking, action: button_confirm, ref: outgoing_shipment}
|
||||
-
|
||||
I check shipment details after confirmed.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
shipment = self.browse(cr, uid, ref("outgoing_shipment"))
|
||||
assert shipment.state == "confirmed", "Shipment should be confirmed."
|
||||
for move_line in shipment.move_lines:
|
||||
assert move_line.state == "confirmed", "Move should be confirmed."
|
||||
|
||||
-
|
||||
I confirm incoming shipment of 50 kgm Ice-cream.
|
||||
-
|
||||
!workflow {model: stock.picking, action: button_confirm, ref: incoming_shipment}
|
||||
-
|
||||
I receive 40kgm Ice-cream so I make backorder of incoming shipment for 40 kgm.
|
||||
-
|
||||
!python {model: stock.partial.picking}: |
|
||||
context.update({'active_model': 'stock.picking', 'active_id': ref('incoming_shipment'), 'active_ids': [ref('incoming_shipment')]})
|
||||
-
|
||||
!record {model: stock.partial.picking, id: partial_incoming}:
|
||||
move_ids:
|
||||
- quantity: 40
|
||||
product_id: product_icecream
|
||||
product_uom: product.product_uom_kgm
|
||||
move_id: incoming_shipment_icecream
|
||||
location_id: location_convenience_shop
|
||||
location_dest_id: location_refrigerator
|
||||
prodlot_id: lot_icecream_0
|
||||
cost: 100
|
||||
-
|
||||
!python {model: stock.partial.picking }: |
|
||||
self.do_partial(cr, uid, [ref('partial_incoming')], context=context)
|
||||
-
|
||||
I check backorder shipment after received partial shipment.
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
lot = self.pool.get('stock.production.lot').browse(cr, uid, ref('lot_icecream_0'), context=context)
|
||||
assert lot.standard_price == 111.11, "Price is not updated to 111.11 (((120*50)+(100*40))/(50+40))"
|
||||
shipment = self.browse(cr, uid, ref("incoming_shipment"))
|
||||
backorder = shipment.backorder_id
|
||||
assert backorder, "Backorder should be created after partial shipment."
|
||||
assert backorder.state == 'done', "Backorder should be close after received."
|
||||
for move_line in backorder.move_lines:
|
||||
assert move_line.product_qty == 40, "Qty in backorder does not correspond."
|
||||
assert move_line.state == 'done', "Move line of backorder should be closed."
|
||||
balance = self.pool.get('account.account').browse(cr, uid, ref('account.stk')).balance
|
||||
assert balance == 10444.4, "Purchased Stocks balance is %s, not 10444.4 (old balance + 111.11×40)" % balance
|
||||
21
stock_lot_valuation/wizard/__init__.py
Normal file
21
stock_lot_valuation/wizard/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import stock_change_standard_price
|
||||
110
stock_lot_valuation/wizard/stock_change_standard_price.py
Normal file
110
stock_lot_valuation/wizard/stock_change_standard_price.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import fields, orm
|
||||
from openerp.tools.translate import _
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class change_standard_price(orm.TransientModel):
|
||||
_name = "lot.change.standard.price"
|
||||
_description = "Change Standard Price"
|
||||
_columns = {
|
||||
'new_price': fields.float(
|
||||
'Price', required=True,
|
||||
digits_compute=dp.get_precision('Account'),
|
||||
help="If cost price is increased, stock variation account will be "
|
||||
"debited and stock output account will be credited with the "
|
||||
"value = (difference of amount * quantity available).\n"
|
||||
"If cost price is decreased, stock variation account will be "
|
||||
"creadited and stock input account will be debited."
|
||||
),
|
||||
'stock_account_input': fields.many2one(
|
||||
'account.account', 'Stock Input Account'),
|
||||
'stock_account_output': fields.many2one(
|
||||
'account.account', 'Stock Output Account'),
|
||||
'stock_journal': fields.many2one(
|
||||
'account.journal', 'Stock journal', required=True),
|
||||
'enable_stock_in_out_acc': fields.boolean('Enable Related Account',),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
""" To get default values for the object.
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param fields: List of fields for which we want default values
|
||||
@param context: A standard dictionary
|
||||
@return: A dictionary which of fields with values.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
lot_pool = self.pool.get('stock.production.lot')
|
||||
product_pool = self.pool.get('product.product')
|
||||
lot_obj = lot_pool.browse(cr, uid, context.get('active_id', False))
|
||||
res = super(change_standard_price, self).default_get(
|
||||
cr, uid, fields, context=context)
|
||||
|
||||
accounts = product_pool.get_product_accounts(
|
||||
cr, uid, lot_obj.product_id.id, context={})
|
||||
|
||||
price = lot_obj.standard_price
|
||||
|
||||
if 'new_price' in fields:
|
||||
res.update({'new_price': price})
|
||||
if 'stock_account_input' in fields:
|
||||
res.update(
|
||||
{'stock_account_input': accounts['stock_account_input']})
|
||||
if 'stock_account_output' in fields:
|
||||
res.update(
|
||||
{'stock_account_output': accounts['stock_account_output']})
|
||||
if 'stock_journal' in fields:
|
||||
res.update({'stock_journal': accounts['stock_journal']})
|
||||
if 'enable_stock_in_out_acc' in fields:
|
||||
res.update({'enable_stock_in_out_acc': True})
|
||||
|
||||
return res
|
||||
|
||||
def change_price(self, cr, uid, ids, context=None):
|
||||
""" Changes the Standard Price of Product.
|
||||
And creates an account move accordingly.
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param ids: List of IDs selected
|
||||
@param context: A standard dictionary
|
||||
@return:
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
rec_id = context and context.get('active_id', False)
|
||||
assert rec_id, _('Active ID is not set in Context.')
|
||||
lot_pool = self.pool.get('stock.production.lot')
|
||||
res = self.browse(cr, uid, ids, context=context)
|
||||
datas = {
|
||||
'new_price': res[0].new_price,
|
||||
'stock_output_account': res[0].stock_account_output.id,
|
||||
'stock_input_account': res[0].stock_account_input.id,
|
||||
'stock_journal': res[0].stock_journal.id
|
||||
}
|
||||
lot_pool.do_change_standard_price(cr, uid, [rec_id], datas, context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_change_standard_price" model="ir.ui.view">
|
||||
<field name="name">Change Standard Price</field>
|
||||
<field name="model">lot.change.standard.price</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Change Standard Price" version="7.0">
|
||||
<separator string="Change Price"/>
|
||||
<group>
|
||||
<field name="new_price" string="Cost Price"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="change_price" string="_Apply" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_view_change_standard_price" model="ir.actions.act_window">
|
||||
<field name="name">Change Standard Price</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">lot.change.standard.price</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_change_standard_price"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
Reference in New Issue
Block a user