[FIX] purchase : Quantity and price calculation in journal entry corrected
[odoo/odoo.git] / addons / purchase / stock.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 from osv import osv, fields
23
24 class stock_move(osv.osv):
25     _inherit = 'stock.move'
26     _columns = {
27         'purchase_line_id': fields.many2one('purchase.order.line',
28             'Purchase Order Line', ondelete='set null', select=True,
29             readonly=True),
30     }
31
32     def _get_reference_accounting_values_for_valuation(self, cr, uid, move, context=None):
33         """
34         Overrides the default stock valuation to take into account the currency that was specified
35         on the purchase order in case the valuation data was not directly specified during picking
36         confirmation.
37         """
38         reference_amount, reference_currency_id = super(stock_move, self)._get_reference_accounting_values_for_valuation(cr, uid, move, context=context)
39         if move.product_id.cost_method != 'average' or not move.price_unit:
40             # no average price costing or cost not specified during picking validation, we will
41             # plug the purchase line values if they are found.
42             if move.purchase_line_id and move.picking_id.purchase_id.pricelist_id:
43                 qty = self.pool.get('product.uom')._compute_qty(cr, uid, move.product_uom.id, move.product_qty, move.product_id.uom_id.id)
44                 reference_amount, reference_currency_id = move.purchase_line_id.price_unit * qty, move.picking_id.purchase_id.pricelist_id.currency_id.id
45         return reference_amount, reference_currency_id
46
47 stock_move()
48
49 #
50 # Inherit of picking to add the link to the PO
51 #
52 class stock_picking(osv.osv):
53     _inherit = 'stock.picking'
54     _columns = {
55         'purchase_id': fields.many2one('purchase.order', 'Purchase Order',
56             ondelete='set null', select=True),
57     }
58     _defaults = {
59         'purchase_id': False,
60     }
61
62     def _get_address_invoice(self, cr, uid, picking):
63         """ Gets invoice address of a partner
64         @return {'contact': address, 'invoice': address} for invoice
65         """
66         res = super(stock_picking, self)._get_address_invoice(cr, uid, picking)
67         if picking.purchase_id:
68             partner_obj = self.pool.get('res.partner')
69             partner = picking.purchase_id.partner_id or picking.address_id.partner_id
70             data = partner_obj.address_get(cr, uid, [partner.id],
71                 ['contact', 'invoice'])
72             res.update(data)
73         return res
74
75     def get_currency_id(self, cursor, user, picking):
76         if picking.purchase_id:
77             return picking.purchase_id.pricelist_id.currency_id.id
78         else:
79             return super(stock_picking, self).get_currency_id(cursor, user, picking)
80
81     def _get_comment_invoice(self, cursor, user, picking):
82         if picking.purchase_id and picking.purchase_id.notes:
83             if picking.note:
84                 return picking.note + '\n' + picking.purchase_id.notes
85             else:
86                 return picking.purchase_id.notes
87         return super(stock_picking, self)._get_comment_invoice(cursor, user, picking)
88
89     def _get_price_unit_invoice(self, cursor, user, move_line, type):
90         if move_line.purchase_line_id:
91             return move_line.purchase_line_id.price_unit
92         return super(stock_picking, self)._get_price_unit_invoice(cursor, user, move_line, type)
93
94     def _get_discount_invoice(self, cursor, user, move_line):
95         if move_line.purchase_line_id:
96             return 0.0
97         return super(stock_picking, self)._get_discount_invoice(cursor, user, move_line)
98
99     def _get_taxes_invoice(self, cursor, user, move_line, type):
100         if move_line.purchase_line_id:
101             return [x.id for x in move_line.purchase_line_id.taxes_id]
102         return super(stock_picking, self)._get_taxes_invoice(cursor, user, move_line, type)
103
104     def _get_account_analytic_invoice(self, cursor, user, picking, move_line):
105         if move_line.purchase_line_id:
106             return move_line.purchase_line_id.account_analytic_id.id
107         return super(stock_picking, self)._get_account_analytic_invoice(cursor, user, picking, move_line)
108
109     def _invoice_line_hook(self, cursor, user, move_line, invoice_line_id):
110         if move_line.purchase_line_id:
111             invoice_line_obj = self.pool.get('account.invoice.line')
112             invoice_line_obj.write(cursor, user, [invoice_line_id], {'note':  move_line.purchase_line_id.notes,})
113         return super(stock_picking, self)._invoice_line_hook(cursor, user, move_line, invoice_line_id)
114
115     def _invoice_hook(self, cursor, user, picking, invoice_id):
116         purchase_obj = self.pool.get('purchase.order')
117         if picking.purchase_id:
118             purchase_obj.write(cursor, user, [picking.purchase_id.id], {'invoice_id': invoice_id,})
119         return super(stock_picking, self)._invoice_hook(cursor, user, picking, invoice_id)
120
121 stock_picking()
122
123 class stock_partial_picking(osv.osv_memory):
124     _inherit = 'stock.partial.picking'
125
126     def default_get(self, cr, uid, fields, context=None):
127         """ To get default values for the object.
128         @param self: The object pointer.
129         @param cr: A database cursor
130         @param uid: ID of the user currently logged in
131         @param fields: List of fields for which we want default values
132         @param context: A standard dictionary
133         @return: A dictionary which of fields with values.
134         """
135         if context is None:
136             context = {}
137         pick_obj = self.pool.get('stock.picking')
138         res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context)
139         for pick in pick_obj.browse(cr, uid, context.get('active_ids', []), context=context):
140             has_product_cost = (pick.type == 'in' and pick.purchase_id)
141             for m in pick.move_lines:
142                 if m.state in ('done','cancel') :
143                     continue
144                 if has_product_cost and m.product_id.cost_method == 'average' and m.purchase_line_id:
145                     # We use the original PO unit purchase price as the basis for the cost, expressed
146                     # in the currency of the PO (i.e the PO's pricelist currency)
147                     list_index = 0
148                     for item in res['product_moves_in']:
149                         if item['move_id'] == m.id:
150                             res['product_moves_in'][list_index]['cost'] = m.purchase_line_id.price_unit
151                             res['product_moves_in'][list_index]['currency'] = m.picking_id.purchase_id.pricelist_id.currency_id.id
152                         list_index += 1
153         return res
154 stock_partial_picking()
155
156 class stock_partial_move(osv.osv_memory):
157     _inherit = "stock.partial.move"
158     def default_get(self, cr, uid, fields, context=None):
159         """ To get default values for the object.
160         @param self: The object pointer.
161         @param cr: A database cursor
162         @param uid: ID of the user currently logged in
163         @param fields: List of fields for which we want default values
164         @param context: A standard dictionary
165         @return: A dictionary which of fields with values.
166         """
167         if context is None:
168             context = {}
169         res = super(stock_partial_move, self).default_get(cr, uid, fields, context=context)
170         move_obj = self.pool.get('stock.move')
171         for m in move_obj.browse(cr, uid, context.get('active_ids', []), context=context):
172             if m.picking_id.type == 'in' and m.product_id.cost_method == 'average' \
173                 and m.purchase_line_id and m.picking_id.purchase_id:
174                     # We use the original PO unit purchase price as the basis for the cost, expressed
175                     # in the currency of the PO (i.e the PO's pricelist currency)
176                     list_index = 0
177                     for item in res['product_moves_in']:
178                         if item['move_id'] == m.id:
179                             res['product_moves_in'][list_index]['cost'] = m.purchase_line_id.price_unit
180                             res['product_moves_in'][list_index]['currency'] = m.picking_id.purchase_id.pricelist_id.currency_id.id
181                         list_index += 1
182         return res
183 stock_partial_move()
184 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
185