696c4d708fefcd0e07dcd92e66e2f89d9c12acfd
[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         product_uom_obj = self.pool.get('product.uom')
39
40         reference_amount, reference_currency_id = super(stock_move, self)._get_reference_accounting_values_for_valuation(cr, uid, move, context=context)
41         default_uom = move.product_id.uom_id.id
42         qty = product_uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, default_uom)
43         if move.product_id.cost_method != 'average' or not move.price_unit:
44             # no average price costing or cost not specified during picking validation, we will
45             # plug the purchase line values if they are found.
46             if move.purchase_line_id and move.picking_id.purchase_id.pricelist_id:
47                 reference_amount, reference_currency_id = move.purchase_line_id.price_unit * qty, move.picking_id.purchase_id.pricelist_id.currency_id.id
48         return reference_amount, reference_currency_id
49
50 stock_move()
51
52 #
53 # Inherit of picking to add the link to the PO
54 #
55 class stock_picking(osv.osv):
56     _inherit = 'stock.picking'
57     _columns = {
58         'purchase_id': fields.many2one('purchase.order', 'Purchase Order',
59             ondelete='set null', select=True),
60     }
61     _defaults = {
62         'purchase_id': False,
63     }
64
65     def _get_address_invoice(self, cr, uid, picking):
66         """ Gets invoice address of a partner
67         @return {'contact': address, 'invoice': address} for invoice
68         """
69         res = super(stock_picking, self)._get_address_invoice(cr, uid, picking)
70         if picking.purchase_id:
71             partner_obj = self.pool.get('res.partner')
72             partner = picking.purchase_id.partner_id or picking.address_id.partner_id
73             data = partner_obj.address_get(cr, uid, [partner.id],
74                 ['contact', 'invoice'])
75             res.update(data)
76         return res
77
78     def get_currency_id(self, cursor, user, picking):
79         if picking.purchase_id:
80             return picking.purchase_id.pricelist_id.currency_id.id
81         else:
82             return super(stock_picking, self).get_currency_id(cursor, user, picking)
83
84     def _get_comment_invoice(self, cursor, user, picking):
85         if picking.purchase_id and picking.purchase_id.notes:
86             if picking.note:
87                 return picking.note + '\n' + picking.purchase_id.notes
88             else:
89                 return picking.purchase_id.notes
90         return super(stock_picking, self)._get_comment_invoice(cursor, user, picking)
91
92     def _get_price_unit_invoice(self, cursor, user, move_line, type):
93         if move_line.purchase_line_id:
94             if move_line.purchase_line_id.order_id.invoice_method == 'picking':
95                 return move_line.price_unit
96             else:
97                 return move_line.purchase_line_id.price_unit
98         return super(stock_picking, self)._get_price_unit_invoice(cursor, user, move_line, type)
99
100     def _get_discount_invoice(self, cursor, user, move_line):
101         if move_line.purchase_line_id:
102             return 0.0
103         return super(stock_picking, self)._get_discount_invoice(cursor, user, move_line)
104
105     def _get_taxes_invoice(self, cursor, user, move_line, type):
106         if move_line.purchase_line_id:
107             return [x.id for x in move_line.purchase_line_id.taxes_id]
108         return super(stock_picking, self)._get_taxes_invoice(cursor, user, move_line, type)
109
110     def _get_account_analytic_invoice(self, cursor, user, picking, move_line):
111         if picking.purchase_id and move_line.purchase_line_id:
112             return move_line.purchase_line_id.account_analytic_id.id
113         return super(stock_picking, self)._get_account_analytic_invoice(cursor, user, picking, move_line)
114
115     def _invoice_line_hook(self, cursor, user, move_line, invoice_line_id):
116         if move_line.purchase_line_id:
117             invoice_line_obj = self.pool.get('account.invoice.line')
118             invoice_line_obj.write(cursor, user, [invoice_line_id], {'note':  move_line.purchase_line_id.notes,})
119         return super(stock_picking, self)._invoice_line_hook(cursor, user, move_line, invoice_line_id)
120
121     def _invoice_hook(self, cursor, user, picking, invoice_id):
122         purchase_obj = self.pool.get('purchase.order')
123         if picking.purchase_id:
124             purchase_obj.write(cursor, user, [picking.purchase_id.id], {'invoice_id': invoice_id,})
125         return super(stock_picking, self)._invoice_hook(cursor, user, picking, invoice_id)
126
127 stock_picking()
128
129 class stock_partial_picking(osv.osv_memory):
130     _inherit = 'stock.partial.picking'
131
132     def default_get(self, cr, uid, fields, context=None):
133         """ To get default values for the object.
134         @param self: The object pointer.
135         @param cr: A database cursor
136         @param uid: ID of the user currently logged in
137         @param fields: List of fields for which we want default values
138         @param context: A standard dictionary
139         @return: A dictionary which of fields with values.
140         """
141         if context is None:
142             context = {}
143         pick_obj = self.pool.get('stock.picking')
144         res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context)
145         for pick in pick_obj.browse(cr, uid, context.get('active_ids', []), context=context):
146             has_product_cost = (pick.type == 'in' and pick.purchase_id)
147             for m in pick.move_lines:
148                 if m.state in ('done','cancel') :
149                     continue
150                 if has_product_cost and m.product_id.cost_method == 'average' and m.purchase_line_id:
151                     # We use the original PO unit purchase price as the basis for the cost, expressed
152                     # in the currency of the PO (i.e the PO's pricelist currency)
153                     list_index = 0
154                     for item in res['product_moves_in']:
155                         if item['move_id'] == m.id:
156                             res['product_moves_in'][list_index]['cost'] = m.purchase_line_id.price_unit
157                             res['product_moves_in'][list_index]['currency'] = m.picking_id.purchase_id.pricelist_id.currency_id.id
158                         list_index += 1
159         return res
160 stock_partial_picking()
161
162 class stock_partial_move(osv.osv_memory):
163     _inherit = "stock.partial.move"
164     def default_get(self, cr, uid, fields, context=None):
165         """ To get default values for the object.
166         @param self: The object pointer.
167         @param cr: A database cursor
168         @param uid: ID of the user currently logged in
169         @param fields: List of fields for which we want default values
170         @param context: A standard dictionary
171         @return: A dictionary which of fields with values.
172         """
173         if context is None:
174             context = {}
175         res = super(stock_partial_move, self).default_get(cr, uid, fields, context=context)
176         move_obj = self.pool.get('stock.move')
177         for m in move_obj.browse(cr, uid, context.get('active_ids', []), context=context):
178             if m.picking_id.type == 'in' and m.product_id.cost_method == 'average' \
179                 and m.purchase_line_id and m.picking_id.purchase_id:
180                     # We use the original PO unit purchase price as the basis for the cost, expressed
181                     # in the currency of the PO (i.e the PO's pricelist currency)
182                     list_index = 0
183                     for item in res['product_moves_in']:
184                         if item['move_id'] == m.id:
185                             res['product_moves_in'][list_index]['cost'] = m.purchase_line_id.price_unit
186                             res['product_moves_in'][list_index]['currency'] = m.picking_id.purchase_id.pricelist_id.currency_id.id
187                         list_index += 1
188         return res
189 stock_partial_move()
190 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
191