[FIX] Update average price creates incorrect entries
[odoo/odoo.git] / addons / account_anglo_saxon / product.py
1 ##############################################################################
2 #    
3 #    OpenERP, Open Source Management Solution
4 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
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
8 #    published by the Free Software Foundation, either version 3 of the
9 #    License, or (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 from osv import fields, osv
22 from tools.translate import _
23
24 class product_category(osv.osv):
25     _inherit = "product.category"
26     _columns = {
27         'property_account_creditor_price_difference_categ': fields.property(
28             'account.account',
29             type='many2one',
30             relation='account.account',
31             string="Price Difference Account",
32             method=True,
33             view_load=True,
34             help="This account will be used to value price difference between purchase price and cost price."),
35
36         #Redefine fields to change help text for anglo saxon methodology.            
37         'property_account_income_categ': fields.property(
38             'account.account',
39             type='many2one',
40             relation='account.account',
41             string="Income Account",
42             method=True,
43             view_load=True,
44             help="This account will be used to value outgoing stock for the current product category using sale price"),
45         'property_account_expense_categ': fields.property(
46             'account.account',
47             type='many2one',
48             relation='account.account',
49             string="Expense Account",
50             method=True,
51             view_load=True,
52             help="This account will be used to value outgoing stock for the current product category using cost price"),                
53
54     }
55 product_category()
56
57 class product_template(osv.osv):
58     _inherit = "product.template"
59     _columns = {
60         'property_account_creditor_price_difference': fields.property(
61             'account.account',
62             type='many2one',
63             relation='account.account',
64             string="Price Difference Account",
65             method=True,
66             view_load=True,
67             help="This account will be used to value price difference between purchase price and cost price."),
68             
69         #Redefine fields to change help text for anglo saxon methodology.
70         'property_account_income': fields.property(
71             'account.account',
72             type='many2one',
73             relation='account.account',
74             string="Income Account",
75             method=True,
76             view_load=True,
77             help="This account will be used to value outgoing stock for the current product category using sale price"),
78         'property_account_expense': fields.property(
79             'account.account',
80             type='many2one',
81             relation='account.account',
82             string="Expense Account",
83             method=True,
84             view_load=True,
85             help="This account will be used to value outgoing stock for the current product category using cost price"),                
86
87     }
88 product_template()
89
90 class product_product(osv.osv):
91     _inherit = "product.product"
92     
93     def do_change_standard_price(self, cr, uid, ids, datas, context=None):
94         """ Changes the Standard Price of Product and creates an account move accordingly.
95         @param datas : dict. contain default datas like new_price, stock_output_account, stock_input_account, stock_journal
96         @param context: A standard dictionary
97         @return:
98
99         """
100         location_obj = self.pool.get('stock.location')
101         move_obj = self.pool.get('account.move')
102         move_line_obj = self.pool.get('account.move.line')
103         if context is None:
104             context = {}
105
106         new_price = datas.get('new_price', 0.0)
107         journal_id = datas.get('stock_journal', False)
108         product_obj=self.browse(cr, uid, ids, context=context)[0]
109         account_variation = product_obj.categ_id.property_stock_variation
110         account_variation_id = account_variation and account_variation.id or False
111         stock_price_diff_account = datas.get('stock_price_diff_account',False)
112         
113         if not account_variation_id: raise osv.except_osv(_('Error!'), _('Variation Account is not specified for Product Category: %s') % (product_obj.categ_id.name))
114         if not stock_price_diff_account:
115             stock_price_diff_account = product_obj.categ_id.property_account_creditor_price_difference_categ and product_obj.categ_id.property_account_creditor_price_difference_categ.id or False
116         if not stock_price_diff_account:
117             raise osv.except_osv(_('Error!'),_('There is no price diffrent account defined ' \
118                                                'for this product: "%s" (id: %d)') % (product_obj.name, product_obj.id,))
119         move_ids = []
120         loc_ids = location_obj.search(cr, uid,[('usage','=','internal')])
121         for rec_id in ids:
122             for location in location_obj.browse(cr, uid, loc_ids, context=context):
123                 c = context.copy()
124                 c.update({
125                     'location': location.id,
126                     'compute_child': False
127                 })
128
129                 product = self.browse(cr, uid, rec_id, context=c)
130                 qty = product.qty_available
131                 diff = product.standard_price - new_price
132                 if not diff: raise osv.except_osv(_('Error!'), _("Could not find any difference between standard price and new price!"))
133                 if qty:
134                     company_id = location.company_id and location.company_id.id or False
135                     if not company_id: raise osv.except_osv(_('Error!'), _('Company is not specified in Location'))
136                     #
137                     # Accounting Entries
138                     #
139                     if not journal_id:
140                         journal_id = product.categ_id.property_stock_journal and product.categ_id.property_stock_journal.id or False
141                     if not journal_id:
142                         raise osv.except_osv(_('Error!'),
143                             _('There is no journal defined '\
144                                 'on the product category: "%s" (id: %d)') % \
145                                 (product.categ_id.name,
146                                     product.categ_id.id,))
147                     move_id = move_obj.create(cr, uid, {
148                                 'journal_id': journal_id,
149                                 'company_id': company_id
150                                 })
151
152                     move_ids.append(move_id)
153
154
155                     if diff > 0:
156                         amount_diff = qty * diff
157                         move_line_obj.create(cr, uid, {
158                                     'name': product.name,
159                                     'account_id': stock_price_diff_account,
160                                     'debit': amount_diff,
161                                     'move_id': move_id,
162                                     })
163                         move_line_obj.create(cr, uid, {
164                                     'name': product.categ_id.name,
165                                     'account_id': account_variation_id,
166                                     'credit': amount_diff,
167                                     'move_id': move_id
168                                     })
169                     elif diff < 0:
170                         amount_diff = qty * -diff
171                         move_line_obj.create(cr, uid, {
172                                         'name': product.name,
173                                         'account_id': stock_price_diff_account,
174                                         'credit': amount_diff,
175                                         'move_id': move_id
176                                     })
177                         move_line_obj.create(cr, uid, {
178                                         'name': product.categ_id.name,
179                                         'account_id': account_variation_id,
180                                         'debit': amount_diff,
181                                         'move_id': move_id
182                                     })
183
184             self.write(cr, uid, rec_id, {'standard_price': new_price})
185
186         return move_ids
187     
188 product_product()
189
190
191 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
192