2009-10-13 05:58:37 +00:00
# -*- coding: utf-8 -*-
2008-06-16 11:00:21 +00:00
##############################################################################
2012-03-22 10:41:24 +00:00
#
2009-01-20 08:48:19 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2008-06-16 11:00:21 +00:00
#
2008-11-03 19:18:56 +00:00
# This program is free software: you can redistribute it and/or modify
2009-10-14 11:15:34 +00:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2008-06-16 11:00:21 +00:00
#
2008-11-03 19:18:56 +00:00
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2009-10-14 11:15:34 +00:00
# GNU Affero General Public License for more details.
2008-06-16 11:00:21 +00:00
#
2009-10-14 11:15:34 +00:00
# You should have received a copy of the GNU Affero General Public License
2012-03-22 10:41:24 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2008-06-16 11:00:21 +00:00
#
2008-11-03 19:18:56 +00:00
##############################################################################
2008-09-04 16:17:33 +00:00
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
from openerp . tools . translate import _
2006-12-07 13:41:40 +00:00
2012-12-17 15:23:03 +00:00
import openerp . addons . decimal_precision as dp
2010-03-06 20:52:19 +00:00
2006-12-07 13:41:40 +00:00
# Overloaded stock_picking to manage carriers :
class stock_picking ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_inherit = ' stock.picking '
2010-02-10 09:10:17 +00:00
def _cal_weight ( self , cr , uid , ids , name , args , context = None ) :
res = { }
2010-11-19 13:48:01 +00:00
for picking in self . browse ( cr , uid , ids , context = context ) :
2010-09-03 22:38:14 +00:00
total_weight = total_weight_net = 0.00
2010-09-06 15:13:25 +00:00
2010-03-11 12:03:01 +00:00
for move in picking . move_lines :
2014-11-26 09:55:30 +00:00
if move . state != ' cancel ' :
total_weight + = move . weight
total_weight_net + = move . weight_net
2010-09-06 15:13:25 +00:00
2010-09-03 22:38:14 +00:00
res [ picking . id ] = {
2010-09-06 15:13:25 +00:00
' weight ' : total_weight ,
' weight_net ' : total_weight_net ,
}
2010-02-10 09:10:17 +00:00
return res
def _get_picking_line ( self , cr , uid , ids , context = None ) :
result = { }
for line in self . pool . get ( ' stock.move ' ) . browse ( cr , uid , ids , context = context ) :
result [ line . picking_id . id ] = True
return result . keys ( )
2012-03-22 10:41:24 +00:00
2013-07-25 14:43:35 +00:00
2008-07-22 15:11:28 +00:00
_columns = {
' carrier_id ' : fields . many2one ( " delivery.carrier " , " Carrier " ) ,
2015-01-15 13:43:32 +00:00
' volume ' : fields . float ( ' Volume ' , copy = False ) ,
2011-07-01 23:41:24 +00:00
' weight ' : fields . function ( _cal_weight , type = ' float ' , string = ' Weight ' , digits_compute = dp . get_precision ( ' Stock Weight ' ) , multi = ' _cal_weight ' ,
2010-09-03 22:38:14 +00:00
store = {
2014-09-19 07:35:23 +00:00
' stock.picking ' : ( lambda self , cr , uid , ids , c = { } : ids , [ ' move_lines ' ] , 40 ) ,
2015-04-10 16:35:34 +00:00
' stock.move ' : ( _get_picking_line , [ ' state ' , ' picking_id ' , ' product_id ' , ' product_uom_qty ' , ' product_uom ' ] , 40 ) ,
2010-09-03 22:38:14 +00:00
} ) ,
2011-07-01 23:41:24 +00:00
' weight_net ' : fields . function ( _cal_weight , type = ' float ' , string = ' Net Weight ' , digits_compute = dp . get_precision ( ' Stock Weight ' ) , multi = ' _cal_weight ' ,
2010-02-10 09:10:17 +00:00
store = {
2014-09-19 07:35:23 +00:00
' stock.picking ' : ( lambda self , cr , uid , ids , c = { } : ids , [ ' move_lines ' ] , 40 ) ,
2015-04-10 16:35:34 +00:00
' stock.move ' : ( _get_picking_line , [ ' state ' , ' picking_id ' , ' product_id ' , ' product_uom_qty ' , ' product_uom ' ] , 40 ) ,
2010-02-10 09:10:17 +00:00
} ) ,
2015-01-15 13:43:32 +00:00
' carrier_tracking_ref ' : fields . char ( ' Carrier Tracking Ref ' , copy = False ) ,
' number_of_packages ' : fields . integer ( ' Number of Packages ' , copy = False ) ,
2012-12-14 15:11:08 +00:00
' weight_uom_id ' : fields . many2one ( ' product.uom ' , ' Unit of Measure ' , required = True , readonly = " 1 " , help = " Unit of measurement for Weight " , ) ,
2014-05-07 16:59:51 +00:00
}
2006-12-07 13:41:40 +00:00
2011-12-21 18:11:49 +00:00
def _prepare_shipping_invoice_line ( self , cr , uid , picking , invoice , context = None ) :
""" Prepare the invoice line to add to the shipping costs to the shipping ' s
invoice .
: param browse_record picking : the stock picking being invoiced
: param browse_record invoice : the stock picking ' s invoice
: return : dict containing the values to create the invoice line ,
or None to create nothing
"""
carrier_obj = self . pool . get ( ' delivery.carrier ' )
grid_obj = self . pool . get ( ' delivery.grid ' )
if not picking . carrier_id or \
any ( inv_line . product_id . id == picking . carrier_id . product_id . id
for inv_line in invoice . invoice_line ) :
return None
grid_id = carrier_obj . grid_get ( cr , uid , [ picking . carrier_id . id ] ,
2012-03-30 08:11:36 +00:00
picking . partner_id . id , context = context )
2011-12-21 18:11:49 +00:00
if not grid_id :
2012-08-07 11:34:14 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) ,
2011-12-21 18:11:49 +00:00
_ ( ' The carrier %s (id: %d ) has no delivery grid! ' ) \
% ( picking . carrier_id . name ,
picking . carrier_id . id ) )
2014-08-27 15:13:14 +00:00
quantity = sum ( [ line . product_uom_qty for line in picking . move_lines ] )
2011-12-21 18:11:49 +00:00
price = grid_obj . get_price_from_picking ( cr , uid , grid_id ,
invoice . amount_untaxed , picking . weight , picking . volume ,
2014-08-27 15:13:14 +00:00
quantity , context = context )
2011-12-21 18:11:49 +00:00
account_id = picking . carrier_id . product_id . property_account_income . id
if not account_id :
account_id = picking . carrier_id . product_id . categ_id \
. property_account_income_categ . id
taxes = picking . carrier_id . product_id . taxes_id
2012-03-30 08:11:36 +00:00
partner = picking . partner_id or False
2011-12-21 18:11:49 +00:00
if partner :
account_id = self . pool . get ( ' account.fiscal.position ' ) . map_account ( cr , uid , partner . property_account_position , account_id )
taxes_ids = self . pool . get ( ' account.fiscal.position ' ) . map_tax ( cr , uid , partner . property_account_position , taxes )
else :
taxes_ids = [ x . id for x in taxes ]
return {
' name ' : picking . carrier_id . name ,
' invoice_id ' : invoice . id ,
' uos_id ' : picking . carrier_id . product_id . uos_id . id ,
' product_id ' : picking . carrier_id . product_id . id ,
' account_id ' : account_id ,
' price_unit ' : price ,
' quantity ' : 1 ,
' invoice_line_tax_id ' : [ ( 6 , 0 , taxes_ids ) ] ,
}
[FIX] delivery: shipping invoice line depending on amount total
The delivery module overrode the method _create_invoice_from_picking
to add the shipping costs according to the invoice and the shipping.
The issue is that the method _create_invoice_from_picking creates an empty
invoice, without any line. The lines are added afterwards, using the method
_create_invoice_line_from_vals, within the method _invoice_create_line.
So, after having called _create_invoice_from_picking, the invoice is indeed
created, but without lines, and therefore without the amount total value.
Adding the shipping costs there will thus prevent the shipping costs
based on the total price of the invoice (e.g. free for an order of 500€)
This rev. overrides the method _invoice_create_line instead, as, after
the call to this method, the invoice will be completely set, with all
its lines, and with a correct amount total. The side effect
is that we need to recompute the taxes a second time, using button_compute.
This is not the cleanest way to solve this issue. Indeed, a cleaner patch
would be to change the method _create_invoice_from_picking so it creates
the invoice along with its invoice lines, using the ORM command
(0, _, values) to creates the lines directly within the invoice creation:
invoice['invoice_line'] = [(0, _, values) for values in invoice_lines_vals].
Nevertheless, this is a bigger change, that will probably require API changes,
and therefore should be done in master.
opw-626226
opw-628517
2015-02-20 11:26:31 +00:00
def _invoice_create_line ( self , cr , uid , moves , journal_id , inv_type = ' out_invoice ' , context = None ) :
2014-11-06 10:40:04 +00:00
invoice_obj = self . pool . get ( ' account.invoice ' )
2012-03-22 10:41:24 +00:00
invoice_line_obj = self . pool . get ( ' account.invoice.line ' )
[FIX] delivery: shipping invoice line depending on amount total
The delivery module overrode the method _create_invoice_from_picking
to add the shipping costs according to the invoice and the shipping.
The issue is that the method _create_invoice_from_picking creates an empty
invoice, without any line. The lines are added afterwards, using the method
_create_invoice_line_from_vals, within the method _invoice_create_line.
So, after having called _create_invoice_from_picking, the invoice is indeed
created, but without lines, and therefore without the amount total value.
Adding the shipping costs there will thus prevent the shipping costs
based on the total price of the invoice (e.g. free for an order of 500€)
This rev. overrides the method _invoice_create_line instead, as, after
the call to this method, the invoice will be completely set, with all
its lines, and with a correct amount total. The side effect
is that we need to recompute the taxes a second time, using button_compute.
This is not the cleanest way to solve this issue. Indeed, a cleaner patch
would be to change the method _create_invoice_from_picking so it creates
the invoice along with its invoice lines, using the ORM command
(0, _, values) to creates the lines directly within the invoice creation:
invoice['invoice_line'] = [(0, _, values) for values in invoice_lines_vals].
Nevertheless, this is a bigger change, that will probably require API changes,
and therefore should be done in master.
opw-626226
opw-628517
2015-02-20 11:26:31 +00:00
invoice_ids = super ( stock_picking , self ) . _invoice_create_line ( cr , uid , moves , journal_id , inv_type = inv_type , context = context )
delivey_invoices = { }
for move in moves :
for invoice in move . picking_id . sale_id . invoice_ids :
if invoice . id in invoice_ids :
delivey_invoices [ invoice ] = move . picking_id
if delivey_invoices :
for invoice , picking in delivey_invoices . items ( ) :
invoice_line = self . _prepare_shipping_invoice_line ( cr , uid , picking , invoice , context = context )
if invoice_line :
invoice_line_obj . create ( cr , uid , invoice_line )
invoice_obj . button_compute ( cr , uid , [ invoice . id ] , context = context , set_total = ( inv_type in ( ' in_invoice ' , ' in_refund ' ) ) )
return invoice_ids
2013-09-09 14:23:50 +00:00
2014-05-07 16:59:51 +00:00
def _get_default_uom ( self , cr , uid , context = None ) :
uom_categ_id = self . pool . get ( ' ir.model.data ' ) . xmlid_to_res_id ( cr , uid , ' product.product_uom_categ_kgm ' )
2013-09-09 14:23:50 +00:00
return self . pool . get ( ' product.uom ' ) . search ( cr , uid , [ ( ' category_id ' , ' = ' , uom_categ_id ) , ( ' factor ' , ' = ' , 1 ) ] ) [ 0 ]
2014-05-07 16:59:51 +00:00
2012-11-12 13:33:21 +00:00
_defaults = {
2014-05-07 16:59:51 +00:00
' weight_uom_id ' : lambda self , cr , uid , c : self . _get_default_uom ( cr , uid , c ) ,
2012-11-12 13:33:21 +00:00
}
2008-07-23 14:41:47 +00:00
2010-03-11 12:03:01 +00:00
class stock_move ( osv . osv ) :
_inherit = ' stock.move '
def _cal_move_weight ( self , cr , uid , ids , name , args , context = None ) :
res = { }
uom_obj = self . pool . get ( ' product.uom ' )
2010-11-19 13:48:01 +00:00
for move in self . browse ( cr , uid , ids , context = context ) :
2010-09-03 22:38:14 +00:00
weight = weight_net = 0.00
2010-03-11 12:03:01 +00:00
if move . product_id . weight > 0.00 :
converted_qty = move . product_qty
weight = ( converted_qty * move . product_id . weight )
2010-09-06 15:13:25 +00:00
2010-09-03 22:38:14 +00:00
if move . product_id . weight_net > 0.00 :
weight_net = ( converted_qty * move . product_id . weight_net )
2010-09-06 15:13:25 +00:00
2010-09-03 22:38:14 +00:00
res [ move . id ] = {
' weight ' : weight ,
' weight_net ' : weight_net ,
}
2010-03-11 12:03:01 +00:00
return res
2010-09-06 15:13:25 +00:00
2010-03-11 12:03:01 +00:00
_columns = {
2011-07-01 23:41:24 +00:00
' weight ' : fields . function ( _cal_move_weight , type = ' float ' , string = ' Weight ' , digits_compute = dp . get_precision ( ' Stock Weight ' ) , multi = ' _cal_move_weight ' ,
2010-09-03 22:38:14 +00:00
store = {
2014-09-16 10:05:52 +00:00
' stock.move ' : ( lambda self , cr , uid , ids , c = None : ids , [ ' product_id ' , ' product_uom_qty ' , ' product_uom ' ] , 30 ) ,
2010-09-03 22:38:14 +00:00
} ) ,
2011-07-01 23:41:24 +00:00
' weight_net ' : fields . function ( _cal_move_weight , type = ' float ' , string = ' Net weight ' , digits_compute = dp . get_precision ( ' Stock Weight ' ) , multi = ' _cal_move_weight ' ,
2010-03-11 12:03:01 +00:00
store = {
2014-09-16 10:05:52 +00:00
' stock.move ' : ( lambda self , cr , uid , ids , c = None : ids , [ ' product_id ' , ' product_uom_qty ' , ' product_uom ' ] , 30 ) ,
2010-03-11 12:03:01 +00:00
} ) ,
2012-12-04 10:58:29 +00:00
' weight_uom_id ' : fields . many2one ( ' product.uom ' , ' Unit of Measure ' , required = True , readonly = " 1 " , help = " Unit of Measure (Unit of Measure) is the unit of measurement for Weight " , ) ,
2010-03-11 12:03:01 +00:00
}
2014-05-07 16:59:51 +00:00
2014-11-05 10:45:04 +00:00
def action_confirm ( self , cr , uid , ids , context = None ) :
2014-11-04 16:28:43 +00:00
"""
Pass the carrier to the picking from the sales order
( Should also work in case of Phantom BoMs when on explosion the original move is deleted )
"""
procs_to_check = [ ]
for move in self . browse ( cr , uid , ids , context = context ) :
if move . procurement_id and move . procurement_id . sale_line_id and move . procurement_id . sale_line_id . order_id . carrier_id :
procs_to_check + = [ move . procurement_id ]
2014-11-05 10:45:04 +00:00
res = super ( stock_move , self ) . action_confirm ( cr , uid , ids , context = context )
pick_obj = self . pool . get ( " stock.picking " )
2014-11-04 16:28:43 +00:00
for proc in procs_to_check :
pickings = list ( set ( [ x . picking_id . id for x in proc . move_ids if x . picking_id and not x . picking_id . carrier_id ] ) )
if pickings :
pick_obj . write ( cr , uid , pickings , { ' carrier_id ' : proc . sale_line_id . order_id . carrier_id . id } , context = context )
2014-11-05 10:45:04 +00:00
return res
2014-05-07 16:59:51 +00:00
def _get_default_uom ( self , cr , uid , context = None ) :
uom_categ_id = self . pool . get ( ' ir.model.data ' ) . xmlid_to_res_id ( cr , uid , ' product.product_uom_categ_kgm ' )
2012-12-14 15:11:08 +00:00
return self . pool . get ( ' product.uom ' ) . search ( cr , uid , [ ( ' category_id ' , ' = ' , uom_categ_id ) , ( ' factor ' , ' = ' , 1 ) ] ) [ 0 ]
2014-05-07 16:59:51 +00:00
2012-12-04 10:58:29 +00:00
_defaults = {
2014-05-07 16:59:51 +00:00
' weight_uom_id ' : lambda self , cr , uid , c : self . _get_default_uom ( cr , uid , c ) ,
2012-12-04 10:58:29 +00:00
}
2010-03-11 12:03:01 +00:00
2012-07-02 09:41:47 +00:00
2008-07-23 14:41:47 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: