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