Merge lp:~elbati/stock-logistic-warehouse/adding_stock_lot_costing into lp:stock-logistic-warehouse

Proposed by Lorenzo Battistini
Status: Merged
Merged at revision: 32
Proposed branch: lp:~elbati/stock-logistic-warehouse/adding_stock_lot_costing
Merge into: lp:stock-logistic-warehouse
Diff against target: 1166 lines (+1103/-0)
12 files modified
stock_lot_valuation/AUTHORS.txt (+1/-0)
stock_lot_valuation/__init__.py (+23/-0)
stock_lot_valuation/__openerp__.py (+52/-0)
stock_lot_valuation/i18n/stock_lot_valuation.pot (+205/-0)
stock_lot_valuation/product.py (+32/-0)
stock_lot_valuation/product_view.xml (+15/-0)
stock_lot_valuation/stock.py (+358/-0)
stock_lot_valuation/stock_view.xml (+22/-0)
stock_lot_valuation/test/stock.yml (+230/-0)
stock_lot_valuation/wizard/__init__.py (+21/-0)
stock_lot_valuation/wizard/stock_change_standard_price.py (+110/-0)
stock_lot_valuation/wizard/stock_change_standard_price_view.xml (+34/-0)
To merge this branch: bzr merge lp:~elbati/stock-logistic-warehouse/adding_stock_lot_costing
Reviewer Review Type Date Requested Status
Joao Alfredo Gama Batista code review. no test Approve
Maxime Chambreuil (http://www.savoirfairelinux.com) code review Needs Fixing
Joël Grand-Guillaume @ camptocamp code review, no tests Approve
Guewen Baconnier @ Camptocamp code review, nitpicking, no test Needs Fixing
Review via email: mp+164766@code.launchpad.net

Description of the change

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

To post a comment you must log in.
Revision history for this message
Eric Caudal - www.elico-corp.com (elicoidal) wrote :

I think this is a first step to start getting FIFO cost calculation on
product
Eric CAUDAL

Eric Caudal
/CEO/
--
*Elico Corporation, Shanghai branch
/OpenERP Premium Certified Training Partner/ *
Cell: + 86 186 2136 1670
Office: + 86 21 6211 8017/27/37
Skype: elico.corp
<email address hidden> <mailto:<email address hidden>>
http://www.elico-corp.com

Elico Corp
On 05/21/2013 12:35 AM, Lorenzo Battistini - Agile BG wrote:
> Lorenzo Battistini - Agile BG has proposed merging lp:~elbati/stock-logistic-warehouse/adding_stock_lot_costing into lp:stock-logistic-warehouse.
>
> Requested reviews:
> Stock and Logistic Core Editors (stock-logistic-core-editors)
>
> For more details, see:
> https://code.launchpad.net/~elbati/stock-logistic-warehouse/adding_stock_lot_costing/+merge/164766
>
> 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

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Well done!

Seems good to me, some nitpickings:

Most are styling and pep8 issues, but the most annoying ones are the missing propagations of the context in some calls.

l.183
Could be worse to cut the long help:

            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."),

l.195-196 (applies for other places in the code too)
pep8: indentation, see http://www.python.org/dev/peps/pep-0008/#indentation

l.199-202
The expression is hard to read.
I think I would prefer a version with if / elif (or maybe an inline ... if ... else ... expression but it would probably be too complex here)

l.224 pep8: missing spaces around =

l.227,241 pep8: should not be on the same line and the line is too long

l.229 propagation of the context is missing, space after commas

l.250 prefer the form `... if ... else ...` than `... and ... or ...`

l.253-256 (and some other places) the \ is useless here as it is enclosed in ()

l.257-260, l.279-290, l.305-318: propagation of context is missing (+ pep8 indentation)

l.360 and lot of calls under: propagation of the context is missing

l. 554,560,561, ... : s/incomming/incoming/

pep8: in some places, a space is missing after comma or colon.

I will be pleased to merge your proposal once fixed.

Congrats for the tests ;-)

review: Needs Fixing (code review, nitpicking, no test)
Revision history for this message
Lorenzo Battistini (elbati) wrote :

On 06/18/2013 09:53 AM, Guewen Baconnier @ Camptocamp wrote:
> Review: Needs Fixing code review, nitpicking, no test

Thank you Guewen, I did the changes.

52. By Lorenzo Battistini

[fix] lines lenght, indentation, style

53. By Lorenzo Battistini

[fix] The expression is hard to read

54. By Lorenzo Battistini

[fix] propagation of the context is missing, space after commas

55. By Lorenzo Battistini

[fix] prefer the form `... if ... else ...` than `... and ... or ...`

56. By Lorenzo Battistini

[fix] propagation of context is missing

57. By Lorenzo Battistini

[fix] propagation of the context is missing

58. By Lorenzo Battistini

[fix] incomming/incoming

59. By Lorenzo Battistini

[fix] space after comma

Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote :

LGTM

review: Approve (code review, no tests)
Revision history for this message
Joao Alfredo Gama Batista (joao-gama) wrote :

Hi Lorenzo,

Just a small comment:

l.746: You forgot to change the copyright owner.

The rest is ok. Thanks for your contribution!

review: Needs Fixing (code review, no tests)
Revision history for this message
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903) wrote :

Thanks Lorenzo.

Can you please add the translation file and run flake8 on your code ?

review: Needs Fixing (code review)
60. By Lorenzo Battistini

[FIX] copyright

Revision history for this message
Lorenzo Battistini (elbati) wrote :

On 10/17/2013 04:09 PM, Joao Alfredo Gama Batista wrote:
> Review: Needs Fixing code review, no tests
>
> Hi Lorenzo,
>
> Just a small comment:
>
> l.746: You forgot to change the copyright owner.

Added our copyright.
I keep the Tiny one because I copied that file from stock module.

61. By Lorenzo Battistini

[IMP] PEP8

62. By Lorenzo Battistini

[FIX] osv.except_osv

63. By Lorenzo Battistini

[IMP] PEP8

64. By Lorenzo Battistini

[ADD] pot file

Revision history for this message
Lorenzo Battistini (elbati) wrote :

On 10/17/2013 04:56 PM, Maxime Chambreuil
(http://www.savoirfairelinux.com) wrote:
> Can you please add the translation file and run flake8 on your code ?

Added stock_lot_valuation.pot and improved PEP8.
Thanks

Revision history for this message
Joao Alfredo Gama Batista (joao-gama) wrote :

LGTM.

review: Approve (code review. no test)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'stock_lot_valuation'
=== added file 'stock_lot_valuation/AUTHORS.txt'
--- stock_lot_valuation/AUTHORS.txt 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/AUTHORS.txt 2013-10-18 16:18:27 +0000
@@ -0,0 +1,1 @@
1Lorenzo Battistini <lorenzo.battistini@agilebg.com>
02
=== added file 'stock_lot_valuation/__init__.py'
--- stock_lot_valuation/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/__init__.py 2013-10-18 16:18:27 +0000
@@ -0,0 +1,23 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU Affero General Public License as published
8# by the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU Affero General Public License for more details.
15#
16# You should have received a copy of the GNU Affero General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18#
19##############################################################################
20
21import product
22import stock
23import wizard
024
=== added file 'stock_lot_valuation/__openerp__.py'
--- stock_lot_valuation/__openerp__.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/__openerp__.py 2013-10-18 16:18:27 +0000
@@ -0,0 +1,52 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU Affero General Public License as published
8# by the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU Affero General Public License for more details.
15#
16# You should have received a copy of the GNU Affero General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18#
19##############################################################################
20
21{
22 'name': "Lot Valuation",
23 'version': '0.1',
24 'category': 'Warehouse Management',
25 'description': """
26Stock valuation (standard or average price, ...) based on lots.
27This module extends standard stock valuation (based on products).
28Valuing lots allows to have different costs for different lots of the same
29product.
30
31Usage
32-----
33Set the 'Lot valuation' flag on product form (used for real time valuation).
34As for products, lots have 'cost' and 'costing method' fields. Also, a
35'Change Standard Price' wizard is available.
36""",
37 'author': 'Agile Business Group',
38 'website': 'http://www.agilebg.com',
39 'license': 'AGPL-3',
40 "depends": ['stock'],
41 "data": [
42 "wizard/stock_change_standard_price_view.xml",
43 "product_view.xml",
44 "stock_view.xml",
45 ],
46 "demo": [],
47 'test': [
48 'test/stock.yml', # TODO cover user interface operations
49 ],
50 "active": False,
51 "installable": True
52}
053
=== added directory 'stock_lot_valuation/i18n'
=== added file 'stock_lot_valuation/i18n/stock_lot_valuation.pot'
--- stock_lot_valuation/i18n/stock_lot_valuation.pot 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/i18n/stock_lot_valuation.pot 2013-10-18 16:18:27 +0000
@@ -0,0 +1,205 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * stock_lot_valuation
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 7.0\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2013-10-18 16:17+0000\n"
10"PO-Revision-Date: 2013-10-18 16:17+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: stock_lot_valuation
19#: selection:stock.production.lot,cost_method:0
20msgid "Average Price"
21msgstr ""
22
23#. module: stock_lot_valuation
24#: field:lot.change.standard.price,stock_journal:0
25msgid "Stock journal"
26msgstr ""
27
28#. module: stock_lot_valuation
29#: field:lot.change.standard.price,enable_stock_in_out_acc:0
30msgid "Enable Related Account"
31msgstr ""
32
33#. module: stock_lot_valuation
34#: model:ir.model,name:stock_lot_valuation.model_stock_picking
35msgid "Picking List"
36msgstr ""
37
38#. module: stock_lot_valuation
39#: code:addons/stock_lot_valuation/stock.py:132
40#, python-format
41msgid "Please specify company in Location."
42msgstr ""
43
44#. module: stock_lot_valuation
45#: code:addons/stock_lot_valuation/stock.py:145
46#, python-format
47msgid "Please define journal on the product category: '%s' (id: %d)."
48msgstr ""
49
50#. module: stock_lot_valuation
51#: model:ir.model,name:stock_lot_valuation.model_product_product
52msgid "Product"
53msgstr ""
54
55#. module: stock_lot_valuation
56#: help:stock.production.lot,standard_price:0
57msgid "Cost price (in company currency) of the lot used for standard stock valuation in accounting."
58msgstr ""
59
60#. module: stock_lot_valuation
61#: field:lot.change.standard.price,new_price:0
62msgid "Price"
63msgstr ""
64
65#. module: stock_lot_valuation
66#: model:ir.model,name:stock_lot_valuation.model_stock_production_lot
67msgid "Serial Number"
68msgstr ""
69
70#. module: stock_lot_valuation
71#: code:addons/stock_lot_valuation/stock.py:123
72#, python-format
73msgid "No difference between standard price! and new price"
74msgstr ""
75
76#. module: stock_lot_valuation
77#: selection:stock.production.lot,cost_method:0
78msgid "Standard Price"
79msgstr ""
80
81#. module: stock_lot_valuation
82#: model:ir.model,name:stock_lot_valuation.model_stock_partial_picking
83msgid "Partial Picking Processing Wizard"
84msgstr ""
85
86#. module: stock_lot_valuation
87#: view:lot.change.standard.price:0
88#: view:stock.production.lot:0
89msgid "Cost Price"
90msgstr ""
91
92#. module: stock_lot_valuation
93#: help:lot.change.standard.price,new_price:0
94msgid "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"
95"If cost price is decreased, stock variation account will be creadited and stock input account will be debited."
96msgstr ""
97
98#. module: stock_lot_valuation
99#: field:product.product,lot_valuation:0
100msgid "Lot valuation"
101msgstr ""
102
103#. module: stock_lot_valuation
104#: help:stock.production.lot,cost_method:0
105msgid "Standard Price: The cost price is manually updated at the end of a specific period. \n"
106"Average Price: The cost price is recomputed at each incoming shipment."
107msgstr ""
108
109#. module: stock_lot_valuation
110#: view:stock.production.lot:0
111msgid "update"
112msgstr ""
113
114#. module: stock_lot_valuation
115#: code:addons/stock_lot_valuation/stock.py:100
116#: code:addons/stock_lot_valuation/stock.py:122
117#: code:addons/stock_lot_valuation/stock.py:131
118#: code:addons/stock_lot_valuation/stock.py:144
119#: code:addons/stock_lot_valuation/stock.py:167
120#: code:addons/stock_lot_valuation/stock.py:196
121#, python-format
122msgid "Error!"
123msgstr ""
124
125#. module: stock_lot_valuation
126#: field:stock.production.lot,cost_method:0
127msgid "Costing Method"
128msgstr ""
129
130#. module: stock_lot_valuation
131#: code:addons/stock_lot_valuation/wizard/stock_change_standard_price.py:100
132#, python-format
133msgid "Active ID is not set in Context."
134msgstr ""
135
136#. module: stock_lot_valuation
137#: view:lot.change.standard.price:0
138msgid "_Apply"
139msgstr ""
140
141#. module: stock_lot_valuation
142#: view:lot.change.standard.price:0
143msgid "Change Price"
144msgstr ""
145
146#. module: stock_lot_valuation
147#: field:lot.change.standard.price,stock_account_output:0
148msgid "Stock Output Account"
149msgstr ""
150
151#. module: stock_lot_valuation
152#: help:product.product,lot_valuation:0
153msgid "Use lot valuation instead of product valuation"
154msgstr ""
155
156#. module: stock_lot_valuation
157#: code:addons/stock_lot_valuation/stock.py:197
158#, python-format
159msgid "Please define stock output account for this product: '%s' (id: %d)."
160msgstr ""
161
162#. module: stock_lot_valuation
163#: model:ir.model,name:stock_lot_valuation.model_stock_move
164msgid "Stock Move"
165msgstr ""
166
167#. module: stock_lot_valuation
168#: view:lot.change.standard.price:0
169msgid "or"
170msgstr ""
171
172#. module: stock_lot_valuation
173#: field:stock.production.lot,standard_price:0
174msgid "Cost"
175msgstr ""
176
177#. module: stock_lot_valuation
178#: field:lot.change.standard.price,stock_account_input:0
179msgid "Stock Input Account"
180msgstr ""
181
182#. module: stock_lot_valuation
183#: model:ir.actions.act_window,name:stock_lot_valuation.action_view_change_standard_price
184#: model:ir.model,name:stock_lot_valuation.model_lot_change_standard_price
185#: view:lot.change.standard.price:0
186msgid "Change Standard Price"
187msgstr ""
188
189#. module: stock_lot_valuation
190#: code:addons/stock_lot_valuation/stock.py:168
191#, python-format
192msgid "Please define stock input account for this product: '%s' (id: %d)."
193msgstr ""
194
195#. module: stock_lot_valuation
196#: view:lot.change.standard.price:0
197msgid "Cancel"
198msgstr ""
199
200#. module: stock_lot_valuation
201#: code:addons/stock_lot_valuation/stock.py:101
202#, python-format
203msgid "Specify valuation Account for Product Category: %s."
204msgstr ""
205
0206
=== added file 'stock_lot_valuation/product.py'
--- stock_lot_valuation/product.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/product.py 2013-10-18 16:18:27 +0000
@@ -0,0 +1,32 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU Affero General Public License as published
8# by the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU Affero General Public License for more details.
15#
16# You should have received a copy of the GNU Affero General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18#
19##############################################################################
20
21from openerp.osv import fields, orm
22from openerp.tools.translate import _
23
24
25class product_product(orm.Model):
26 _inherit = "product.product"
27
28 _columns = {
29 'lot_valuation': fields.boolean(
30 'Lot valuation',
31 help="Use lot valuation instead of product valuation"),
32 }
033
=== added file 'stock_lot_valuation/product_view.xml'
--- stock_lot_valuation/product_view.xml 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/product_view.xml 2013-10-18 16:18:27 +0000
@@ -0,0 +1,15 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3<data>
4 <record id="product_normal_form_view" model="ir.ui.view">
5 <field name="name">product_normal_form_view</field>
6 <field name="model">product.product</field>
7 <field name="inherit_id" ref="stock.view_normal_property_acc_form"></field>
8 <field name="arch" type="xml">
9 <field name="valuation" position="after">
10 <field name="lot_valuation"></field>
11 </field>
12 </field>
13 </record>
14</data>
15</openerp>
016
=== added file 'stock_lot_valuation/stock.py'
--- stock_lot_valuation/stock.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/stock.py 2013-10-18 16:18:27 +0000
@@ -0,0 +1,358 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU Affero General Public License as published
8# by the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU Affero General Public License for more details.
15#
16# You should have received a copy of the GNU Affero General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18#
19##############################################################################
20
21from openerp.osv import fields, orm
22from openerp.tools.translate import _
23import openerp.addons.decimal_precision as dp
24
25
26class stock_production_lot(orm.Model):
27 _inherit = "stock.production.lot"
28
29 _columns = {
30 'standard_price': fields.float(
31 'Cost', digits_compute=dp.get_precision('Lot Price'),
32 help="Cost price (in company currency) of the lot used for "
33 "standard stock valuation in accounting.",
34 groups="base.group_user"
35 ),
36 'cost_method': fields.selection(
37 [
38 ('standard', 'Standard Price'),
39 ('average', 'Average Price')
40 ], 'Costing Method',
41 help="Standard Price: The cost price is manually updated at the "
42 "end of a specific period. \nAverage Price: The cost price is "
43 "recomputed at each incoming shipment."
44 ),
45 }
46
47 def price_get(self, cr, uid, ids, context=None):
48 if context is None:
49 context = {}
50 res = {}
51 product_uom_obj = self.pool.get('product.uom')
52 for lot in self.browse(cr, uid, ids, context=context):
53 res[lot.id] = lot['standard_price'] or 0.0
54 if 'uom' in context:
55 uom = lot.product_id.uom_id or lot.product_id.uos_id
56 res[lot.id] = product_uom_obj._compute_price(
57 cr, uid,
58 uom.id, res[lot.id], context['uom'])
59 # Convert from price_type currency to asked one
60 if 'currency_id' in context:
61 currency_id = False
62 if lot.company_id and lot.company_id.currency_id:
63 currency_id = lot.company_id.currency_id.id
64 elif (
65 lot.product_id.company_id
66 and lot.product_id.company_id.currency_id
67 ):
68 currency_id = lot.product_id.company_id.currency_id.id
69 if currency_id:
70 res[lot.id] = self.pool.get('res.currency').compute(
71 cr, uid,
72 currency_id,
73 context['currency_id'], res[lot.id], context=context)
74 return res
75
76 def do_change_standard_price(self, cr, uid, ids, datas, context=None):
77 """ Changes the Standard Price of Lot and creates an account move
78 accordingly.
79 @param datas : dict. contain default datas like new_price,
80 stock_output_account, stock_input_account, stock_journal
81 @param context: A standard dictionary
82 """
83 location_obj = self.pool.get('stock.location')
84 move_obj = self.pool.get('account.move')
85 move_line_obj = self.pool.get('account.move.line')
86 if context is None:
87 context = {}
88
89 new_price = datas.get('new_price', 0.0)
90 stock_output_acc = datas.get('stock_output_account', False)
91 stock_input_acc = datas.get('stock_input_account', False)
92 journal_id = datas.get('stock_journal', False)
93 lot_obj = self.browse(cr, uid, ids, context=context)[0]
94 account_valuation = (
95 lot_obj.product_id.categ_id.property_stock_valuation_account_id)
96 account_valuation_id = (
97 account_valuation and account_valuation.id or False)
98 if not account_valuation_id:
99 raise orm.except_orm(
100 _('Error!'),
101 _('Specify valuation Account for Product Category: %s.')
102 % (lot_obj.product_id.categ_id.name))
103 move_ids = []
104 loc_ids = location_obj.search(
105 cr, uid, [('usage', '=', 'internal')],
106 context=context)
107 for rec_id in ids:
108 for location in location_obj.browse(
109 cr, uid, loc_ids, context=context
110 ):
111 c = context.copy()
112 c.update({
113 'location_id': location.id,
114 'compute_child': False
115 })
116
117 lot = self.browse(cr, uid, rec_id, context=c)
118 qty = lot.stock_available
119 diff = lot.standard_price - new_price
120 if not diff:
121 raise orm.except_orm(
122 _('Error!'),
123 _("No difference between standard price!"
124 " and new price"))
125 if qty:
126 company_id = (
127 location.company_id and location.company_id.id or False
128 )
129 if not company_id:
130 raise orm.except_orm(
131 _('Error!'),
132 _('Please specify company in Location.'))
133 #
134 # Accounting Entries
135 #
136 product = lot.product_id
137 if (
138 not journal_id
139 and product.categ_id.property_stock_journal
140 ):
141 journal_id = product.categ_id.property_stock_journal.id
142 if not journal_id:
143 raise orm.except_orm(
144 _('Error!'),
145 _("Please define journal "
146 "on the product category: '%s' (id: %d).") %
147 (product.categ_id.name, product.categ_id.id,))
148 move_id = move_obj.create(cr, uid, {
149 'journal_id': journal_id,
150 'company_id': company_id
151 }, context=context)
152
153 move_ids.append(move_id)
154
155 if diff > 0:
156 if not stock_input_acc:
157 stock_input_acc = (
158 product.property_stock_account_input.id
159 )
160 if not stock_input_acc:
161 stock_input_acc = (
162 product.categ_id.
163 property_stock_account_input_categ.id
164 )
165 if not stock_input_acc:
166 raise orm.except_orm(
167 _('Error!'),
168 _("Please define stock input account "
169 "for this product: '%s' (id: %d).") %
170 (product.name, product.id,))
171 amount_diff = qty * diff
172 move_line_obj.create(cr, uid, {
173 'name': product.name,
174 'account_id': stock_input_acc,
175 'debit': amount_diff,
176 'move_id': move_id,
177 }, context=context)
178 move_line_obj.create(cr, uid, {
179 'name': product.categ_id.name,
180 'account_id': account_valuation_id,
181 'credit': amount_diff,
182 'move_id': move_id
183 }, context=context)
184 elif diff < 0:
185 if not stock_output_acc:
186 stock_output_acc = (
187 product.property_stock_account_output.id
188 )
189 if not stock_output_acc:
190 stock_output_acc = (
191 product.categ_id.
192 property_stock_account_output_categ.id
193 )
194 if not stock_output_acc:
195 raise orm.except_orm(
196 _('Error!'),
197 _("Please define stock output account "
198 "for this product: '%s' (id: %d).") %
199 (product.name, product.id,))
200 amount_diff = qty * -diff
201 move_line_obj.create(cr, uid, {
202 'name': product.name,
203 'account_id': stock_output_acc,
204 'credit': amount_diff,
205 'move_id': move_id
206 }, context=context)
207 move_line_obj.create(cr, uid, {
208 'name': product.categ_id.name,
209 'account_id': account_valuation_id,
210 'debit': amount_diff,
211 'move_id': move_id
212 }, context=context)
213
214 self.write(cr, uid, rec_id, {'standard_price': new_price})
215
216 return move_ids
217
218
219class stock_move(orm.Model):
220 _inherit = "stock.move"
221
222 def _get_reference_accounting_values_for_valuation(
223 self, cr, uid, move, context=None
224 ):
225 res = super(
226 stock_move, self)._get_reference_accounting_values_for_valuation(
227 cr, uid, move, context=context)
228 if move.product_id.lot_valuation and move.prodlot_id:
229 product_uom_obj = self.pool.get('product.uom')
230 qty = product_uom_obj._compute_qty(
231 cr, uid, move.product_uom.id,
232 move.product_qty, move.product_id.uom_id.id)
233 if context is None:
234 context = {}
235 currency_ctx = dict(
236 context, currency_id=move.company_id.currency_id.id)
237 amount_unit = move.prodlot_id.price_get(
238 context=currency_ctx)[move.prodlot_id.id]
239 reference_amount = amount_unit * qty
240 new_res = (reference_amount, move.company_id.currency_id.id)
241 res = new_res
242 return res
243
244 def do_partial(self, cr, uid, ids, partial_datas, context=None):
245 if context is None:
246 context = {}
247 pick_obj = self.pool.get('stock.picking')
248 for move in self.browse(cr, uid, ids, context=context):
249 pick_obj.write_lot(cr, uid, move, partial_datas, context=context)
250 res = super(stock_move, self).do_partial(
251 cr, uid, ids, partial_datas, context=context)
252 return res
253
254
255class stock_picking(orm.Model):
256 _inherit = "stock.picking"
257
258 def compute_price(self, cr, uid, partial_datas, move, context=None):
259 if context is None:
260 context = {}
261 lot_obj = self.pool.get('stock.production.lot')
262 uom_obj = self.pool.get('product.uom')
263 move_obj = self.pool.get('stock.move')
264 currency_obj = self.pool.get('res.currency')
265 partial_data = partial_datas.get('move%s' % (move.id), {})
266 product_uom = partial_data.get('product_uom', False)
267 product_qty = partial_data.get('product_qty', 0.0)
268 product_currency = partial_data.get('product_currency', False)
269 product_price = partial_data.get('product_price', 0.0)
270
271 lot = lot_obj.browse(cr, uid, move.prodlot_id.id, context=context)
272 product = lot.product_id
273 move_currency_id = move.company_id.currency_id.id
274 context['currency_id'] = move_currency_id
275 qty = uom_obj._compute_qty(
276 cr, uid, product_uom, product_qty, product.uom_id.id)
277 if qty > 0:
278 new_price = currency_obj.compute(
279 cr, uid, product_currency,
280 move_currency_id, product_price)
281 new_price = uom_obj._compute_price(
282 cr, uid, product_uom, new_price,
283 product.uom_id.id)
284 if lot.stock_available <= 0:
285 new_std_price = new_price
286 else:
287 # Get the standard price
288 amount_unit = lot.price_get(context=context)[lot.id]
289 new_std_price = (
290 ((amount_unit * lot.stock_available)
291 + (new_price * qty)) / (lot.stock_available + qty)
292 )
293
294 lot_obj.write(
295 cr, uid, [lot.id], {'standard_price': new_std_price},
296 context=context
297 )
298
299 # Record the values that were chosen in the wizard, so they can be
300 # used for inventory valuation if real-time valuation is enabled.
301 move_obj.write(cr, uid, [move.id], {
302 'price_unit': product_price,
303 'price_currency_id': product_currency
304 }, context=context)
305
306 def write_lot(self, cr, uid, move, partial_datas, context=None):
307 lot_obj = self.pool.get('stock.production.lot')
308 currency_obj = self.pool.get('res.currency')
309 uom_obj = self.pool.get('product.uom')
310 if partial_datas.get('move%s' % (move.id)):
311 partial_data = partial_datas.get('move%s' % (move.id), {})
312 product_price = partial_data.get('product_price', 0.0)
313 product_currency = partial_data.get('product_currency', False)
314 product_uom = partial_data.get('product_uom', False)
315 if partial_data.get('prodlot_id'):
316 lot = lot_obj.browse(
317 cr, uid, partial_data['prodlot_id'], context)
318 product = lot.product_id
319 if (
320 move.product_id.lot_valuation and (
321 move.picking_id.type == 'in'
322 ) and (lot.cost_method == 'average')
323 ):
324 self.compute_price(
325 cr, uid, partial_datas, move, context=context)
326 if (
327 move.product_id.lot_valuation and product_price
328 and not lot.standard_price
329 ):
330 new_price = currency_obj.compute(
331 cr, uid, product_currency,
332 move.company_id.currency_id.id, product_price)
333 new_price = uom_obj._compute_price(
334 cr, uid, product_uom, new_price,
335 product.uom_id.id)
336 lot.write({'standard_price': new_price})
337
338 def do_partial(self, cr, uid, ids, partial_datas, context=None):
339 if context is None:
340 context = {}
341 for pick in self.browse(cr, uid, ids, context=context):
342 for move in pick.move_lines:
343 self.write_lot(cr, uid, move, partial_datas, context=context)
344 res = super(stock_picking, self).do_partial(
345 cr, uid, ids, partial_datas, context=context)
346 return res
347
348
349class stock_partial_picking(orm.TransientModel):
350 _inherit = "stock.partial.picking"
351
352 def _product_cost_for_average_update(self, cr, uid, move):
353 res = super(
354 stock_partial_picking, self
355 )._product_cost_for_average_update(cr, uid, move)
356 if move.prodlot_id and move.product_id.lot_valuation:
357 res['cost'] = move.prodlot_id.standard_price
358 return res
0359
=== added file 'stock_lot_valuation/stock_view.xml'
--- stock_lot_valuation/stock_view.xml 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/stock_view.xml 2013-10-18 16:18:27 +0000
@@ -0,0 +1,22 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3<data>
4 <record id="view_production_lot_form" model="ir.ui.view">
5 <field name="name">view_production_lot_form</field>
6 <field name="model">stock.production.lot</field>
7 <field name="inherit_id" ref="stock.view_production_lot_form"></field>
8 <field name="arch" type="xml">
9 <field name="stock_available" position="after" version="7.0">
10 <field name="cost_method"></field>
11 <label string="Cost Price" for="standard_price" align="1.0" groups="base.group_user"/>
12 <div groups="base.group_user">
13 <field name="standard_price" attrs="{'readonly':[('cost_method','=','average')]}" nolabel="1"/>
14 <button name="%(action_view_change_standard_price)d" string="update"
15 type="action" attrs="{'invisible':[('cost_method','&lt;&gt;','average')]}"
16 class="oe_link" groups="product.group_costing_method"/>
17 </div>
18 </field>
19 </field>
20 </record>
21</data>
22</openerp>
023
=== added directory 'stock_lot_valuation/test'
=== added file 'stock_lot_valuation/test/stock.yml'
--- stock_lot_valuation/test/stock.yml 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/test/stock.yml 2013-10-18 16:18:27 +0000
@@ -0,0 +1,230 @@
1-
2 !record {model: stock.location, id: location_refrigerator}:
3 name: Refrigerator
4 usage: internal
5-
6 !record {model: stock.location, id: location_delivery_counter}:
7 name: Delivery Counter
8 usage: internal
9-
10 !record {model: stock.location, id: location_refrigerator_small}:
11 name: Small Refrigerator
12 usage: internal
13 location_id: location_refrigerator
14-
15 !record {model: stock.location, id: location_opening}:
16 name: opening
17 usage: inventory
18-
19 !record {model: stock.location, id: location_convenience_shop}:
20 name: Convenient Store
21 usage: supplier
22-
23 !record {model: stock.warehouse, id: warehouse_icecream}:
24 name: Ice Cream Shop
25 lot_input_id: location_refrigerator
26 lot_stock_id: location_refrigerator
27 lot_output_id: location_delivery_counter
28-
29 !record {model: product.product, id: product_icecream}:
30 default_code: 001
31 name: Ice Cream
32 type: product
33 categ_id: product.product_category_1
34 list_price: 100.0
35 standard_price: 70.0
36 uom_id: product.product_uom_kgm
37 uom_po_id: product.product_uom_kgm
38 procure_method: make_to_stock
39 property_stock_inventory: location_opening
40 valuation: real_time
41 cost_method: average
42 property_stock_account_input: account.o_expense
43 property_stock_account_output: account.o_income
44 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.
45 lot_valuation: True
46
47-
48 !record {model: stock.production.lot, id: lot_icecream_0}:
49 name: Lot0 for Ice cream
50 product_id: product_icecream
51 cost_method: average
52 standard_price: 70.0
53-
54 !record {model: stock.production.lot, id: lot_icecream_1}:
55 name: Lot1 for Ice cream
56 product_id: product_icecream
57-
58 !record {model: stock.inventory, id: stock_inventory_icecream}:
59 name: Inventory for icecream
60-
61 !record {model: stock.inventory.line, id: stock_inventory_line_icecream_lot0}:
62 product_id: product_icecream
63 product_uom: product.product_uom_kgm
64 inventory_id: stock_inventory_icecream
65 product_qty: 50.0
66 prod_lot_id: lot_icecream_0
67 location_id: location_refrigerator
68-
69 !record {model: stock.inventory.line, id: stock_inventory_line_icecream_lot1}:
70 product_id: product_icecream
71 product_uom: product.product_uom_kgm
72 inventory_id: stock_inventory_icecream
73 product_qty: 40.0
74 prod_lot_id: lot_icecream_1
75 location_id: location_refrigerator
76
77-
78 !record {model: stock.picking, id: outgoing_shipment}:
79 type: out
80 location_dest_id: location_delivery_counter
81-
82 !record {model: stock.move, id: outgoing_shipment_icecream}:
83 picking_id: outgoing_shipment
84 product_id: product_icecream
85 product_uom: product.product_uom_kgm
86 product_qty: 130.0
87 location_id: location_refrigerator
88 location_dest_id: location_delivery_counter
89 prodlot_id: lot_icecream_0
90-
91 !record {model: stock.picking, id: incoming_shipment}:
92 type: in
93 invoice_state: 2binvoiced
94 partner_id: base.res_partner_address_9
95 location_dest_id: location_refrigerator
96-
97 !record {model: stock.move, id: incoming_shipment_icecream}:
98 picking_id: incoming_shipment
99 product_id: product_icecream
100 product_uom: product.product_uom_kgm
101 product_qty: 50.0
102 location_id: location_convenience_shop
103 location_dest_id: location_refrigerator
104 prodlot_id: lot_icecream_0
105
106-
107 I update the price of the Ice-cream.
108-
109 !python {model: stock.change.standard.price}: |
110 context.update({'active_model':'product.product', 'active_id': ref('product_icecream'), 'active_ids':[ref('product_icecream')]})
111-
112 !record {model: stock.change.standard.price, id: change_price}:
113 new_price: 120
114-
115 !python {model: stock.change.standard.price}: |
116 self.change_price(cr, uid, [ref('change_price')], context=context)
117-
118 I check price of Ice-cream after update price.
119-
120 !python {model: product.product}: |
121 product = self.browse(cr, uid, ref('product_icecream'), context=context)
122 assert product.standard_price == 120, "Price is not updated."
123
124-
125 I confirm physical inventory of Ice-cream which are came in different lots.
126-
127 !python {model: stock.inventory}: |
128 self.action_confirm(cr, uid, [ref('stock_inventory_icecream')], context=context)
129-
130 I check move details after confirmed physical inventory.
131-
132 !python {model: stock.inventory}: |
133 inventory = self.browse(cr, uid, ref('stock_inventory_icecream'), context=context)
134 assert len(inventory.move_ids) == len(inventory.inventory_line_id), "moves are not correspond."
135 for move_line in inventory.move_ids:
136 for line in inventory.inventory_line_id:
137 if move_line.product_id.id == line.product_id.id and move_line.prodlot_id.id == line.prod_lot_id.id:
138 location_id = line.product_id.property_stock_inventory.id
139 assert move_line.product_qty == line.product_qty, "Qty is not correspond."
140 assert move_line.product_uom.id == line.product_uom.id, "UOM is not correspond."
141 assert move_line.date == inventory.date, "Date is not correspond."
142 assert move_line.location_id.id == location_id, "Source location is not correspond."
143 assert move_line.location_dest_id.id == line.location_id.id, "Destination location is not correspond."
144 assert move_line.state == 'confirmed', "Move is not confirmed."
145
146-
147 Now I check vitual stock of Ice-cream after confirmed physical inventory.
148-
149 !python {model: product.product}: |
150 product = self.browse(cr, uid, ref('product_icecream'), context=context)
151 assert product.virtual_available == 90, "Vitual stock is not updated."
152
153-
154 I complete physical inventory of Ice-cream.
155-
156 !python {model: stock.inventory}: |
157 self.action_done(cr, uid, [ref('stock_inventory_icecream')], context=context)
158 balance = self.pool.get('account.account').browse(cr, uid, ref('account.stk')).balance
159 assert balance == 3500.0, "Purchased Stocks balance is %s, not 3500 (50*70)" % balance
160-
161 I update the price of the Ice-cream lot.
162-
163 !python {model: lot.change.standard.price}: |
164 context.update({'active_model':'stock.production.lot', 'active_id': ref('lot_icecream_0'), 'active_ids':[ref('lot_icecream_0')]})
165-
166 !record {model: lot.change.standard.price, id: change_price}:
167 new_price: 120
168-
169 !python {model: lot.change.standard.price}: |
170 self.change_price(cr, uid, [ref('change_price')], context=context)
171-
172 I check price of Ice-cream lot after update price.
173-
174 !python {model: stock.production.lot}: |
175 lot = self.browse(cr, uid, ref('lot_icecream_0'), context=context)
176 assert lot.standard_price == 120, "Price is not updated."
177 balance = self.pool.get('account.account').browse(cr, uid, ref('account.stk')).balance
178 assert balance == 6000.0, "Purchased Stocks balance is %s, not 6000 (old balance + (lot.standard_price - new_price) * lot.stock_available)" % balance
179
180-
181 I confirm outgoing shipment of 130 kgm Ice-cream.
182-
183 !workflow {model: stock.picking, action: button_confirm, ref: outgoing_shipment}
184-
185 I check shipment details after confirmed.
186-
187 !python {model: stock.picking}: |
188 shipment = self.browse(cr, uid, ref("outgoing_shipment"))
189 assert shipment.state == "confirmed", "Shipment should be confirmed."
190 for move_line in shipment.move_lines:
191 assert move_line.state == "confirmed", "Move should be confirmed."
192
193-
194 I confirm incoming shipment of 50 kgm Ice-cream.
195-
196 !workflow {model: stock.picking, action: button_confirm, ref: incoming_shipment}
197-
198 I receive 40kgm Ice-cream so I make backorder of incoming shipment for 40 kgm.
199-
200 !python {model: stock.partial.picking}: |
201 context.update({'active_model': 'stock.picking', 'active_id': ref('incoming_shipment'), 'active_ids': [ref('incoming_shipment')]})
202-
203 !record {model: stock.partial.picking, id: partial_incoming}:
204 move_ids:
205 - quantity: 40
206 product_id: product_icecream
207 product_uom: product.product_uom_kgm
208 move_id: incoming_shipment_icecream
209 location_id: location_convenience_shop
210 location_dest_id: location_refrigerator
211 prodlot_id: lot_icecream_0
212 cost: 100
213-
214 !python {model: stock.partial.picking }: |
215 self.do_partial(cr, uid, [ref('partial_incoming')], context=context)
216-
217 I check backorder shipment after received partial shipment.
218-
219 !python {model: stock.picking}: |
220 lot = self.pool.get('stock.production.lot').browse(cr, uid, ref('lot_icecream_0'), context=context)
221 assert lot.standard_price == 111.11, "Price is not updated to 111.11 (((120*50)+(100*40))/(50+40))"
222 shipment = self.browse(cr, uid, ref("incoming_shipment"))
223 backorder = shipment.backorder_id
224 assert backorder, "Backorder should be created after partial shipment."
225 assert backorder.state == 'done', "Backorder should be close after received."
226 for move_line in backorder.move_lines:
227 assert move_line.product_qty == 40, "Qty in backorder does not correspond."
228 assert move_line.state == 'done', "Move line of backorder should be closed."
229 balance = self.pool.get('account.account').browse(cr, uid, ref('account.stk')).balance
230 assert balance == 10444.4, "Purchased Stocks balance is %s, not 10444.4 (old balance + 111.11×40)" % balance
0231
=== added directory 'stock_lot_valuation/wizard'
=== added file 'stock_lot_valuation/wizard/__init__.py'
--- stock_lot_valuation/wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/wizard/__init__.py 2013-10-18 16:18:27 +0000
@@ -0,0 +1,21 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU Affero General Public License as published
8# by the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU Affero General Public License for more details.
15#
16# You should have received a copy of the GNU Affero General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18#
19##############################################################################
20
21import stock_change_standard_price
022
=== added file 'stock_lot_valuation/wizard/stock_change_standard_price.py'
--- stock_lot_valuation/wizard/stock_change_standard_price.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/wizard/stock_change_standard_price.py 2013-10-18 16:18:27 +0000
@@ -0,0 +1,110 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# OpenERP, Open Source Management Solution
5# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6# Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>)
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from openerp.osv import fields, orm
24from openerp.tools.translate import _
25import openerp.addons.decimal_precision as dp
26
27
28class change_standard_price(orm.TransientModel):
29 _name = "lot.change.standard.price"
30 _description = "Change Standard Price"
31 _columns = {
32 'new_price': fields.float(
33 'Price', required=True,
34 digits_compute=dp.get_precision('Account'),
35 help="If cost price is increased, stock variation account will be "
36 "debited and stock output account will be credited with the "
37 "value = (difference of amount * quantity available).\n"
38 "If cost price is decreased, stock variation account will be "
39 "creadited and stock input account will be debited."
40 ),
41 'stock_account_input': fields.many2one(
42 'account.account', 'Stock Input Account'),
43 'stock_account_output': fields.many2one(
44 'account.account', 'Stock Output Account'),
45 'stock_journal': fields.many2one(
46 'account.journal', 'Stock journal', required=True),
47 'enable_stock_in_out_acc': fields.boolean('Enable Related Account',),
48 }
49
50 def default_get(self, cr, uid, fields, context=None):
51 """ To get default values for the object.
52 @param self: The object pointer.
53 @param cr: A database cursor
54 @param uid: ID of the user currently logged in
55 @param fields: List of fields for which we want default values
56 @param context: A standard dictionary
57 @return: A dictionary which of fields with values.
58 """
59 if context is None:
60 context = {}
61 lot_pool = self.pool.get('stock.production.lot')
62 product_pool = self.pool.get('product.product')
63 lot_obj = lot_pool.browse(cr, uid, context.get('active_id', False))
64 res = super(change_standard_price, self).default_get(
65 cr, uid, fields, context=context)
66
67 accounts = product_pool.get_product_accounts(
68 cr, uid, lot_obj.product_id.id, context={})
69
70 price = lot_obj.standard_price
71
72 if 'new_price' in fields:
73 res.update({'new_price': price})
74 if 'stock_account_input' in fields:
75 res.update(
76 {'stock_account_input': accounts['stock_account_input']})
77 if 'stock_account_output' in fields:
78 res.update(
79 {'stock_account_output': accounts['stock_account_output']})
80 if 'stock_journal' in fields:
81 res.update({'stock_journal': accounts['stock_journal']})
82 if 'enable_stock_in_out_acc' in fields:
83 res.update({'enable_stock_in_out_acc': True})
84
85 return res
86
87 def change_price(self, cr, uid, ids, context=None):
88 """ Changes the Standard Price of Product.
89 And creates an account move accordingly.
90 @param self: The object pointer.
91 @param cr: A database cursor
92 @param uid: ID of the user currently logged in
93 @param ids: List of IDs selected
94 @param context: A standard dictionary
95 @return:
96 """
97 if context is None:
98 context = {}
99 rec_id = context and context.get('active_id', False)
100 assert rec_id, _('Active ID is not set in Context.')
101 lot_pool = self.pool.get('stock.production.lot')
102 res = self.browse(cr, uid, ids, context=context)
103 datas = {
104 'new_price': res[0].new_price,
105 'stock_output_account': res[0].stock_account_output.id,
106 'stock_input_account': res[0].stock_account_input.id,
107 'stock_journal': res[0].stock_journal.id
108 }
109 lot_pool.do_change_standard_price(cr, uid, [rec_id], datas, context)
110 return {'type': 'ir.actions.act_window_close'}
0111
=== added file 'stock_lot_valuation/wizard/stock_change_standard_price_view.xml'
--- stock_lot_valuation/wizard/stock_change_standard_price_view.xml 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/wizard/stock_change_standard_price_view.xml 2013-10-18 16:18:27 +0000
@@ -0,0 +1,34 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4 <record id="view_change_standard_price" model="ir.ui.view">
5 <field name="name">Change Standard Price</field>
6 <field name="model">lot.change.standard.price</field>
7 <field name="arch" type="xml">
8 <form string="Change Standard Price" version="7.0">
9 <separator string="Change Price"/>
10 <group>
11 <field name="new_price" string="Cost Price"/>
12 </group>
13 <footer>
14 <button name="change_price" string="_Apply" type="object" class="oe_highlight"/>
15 or
16 <button string="Cancel" class="oe_link" special="cancel" />
17 </footer>
18 </form>
19 </field>
20 </record>
21
22 <record id="action_view_change_standard_price" model="ir.actions.act_window">
23 <field name="name">Change Standard Price</field>
24 <field name="type">ir.actions.act_window</field>
25 <field name="res_model">lot.change.standard.price</field>
26 <field name="view_type">form</field>
27 <field name="view_mode">form</field>
28 <field name="view_id" ref="view_change_standard_price"/>
29 <field name="target">new</field>
30 </record>
31
32 </data>
33</openerp>
34

Subscribers

People subscribed via source and target branches