2012-07-26 20:56:59 +00:00
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# 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.
#
# This program is distributed in the hope that it will be useful,
2012-09-17 05:07:38 +00:00
2012-07-26 20:56:59 +00:00
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from datetime import datetime , timedelta
2012-12-06 14:56:32 +00:00
from openerp . tools import DEFAULT_SERVER_DATE_FORMAT , DEFAULT_SERVER_DATETIME_FORMAT , DATETIME_FORMATS_MAP , float_compare
from openerp . osv import fields , osv
2013-09-05 13:02:34 +00:00
from openerp . tools . safe_eval import safe_eval as eval
2012-12-06 14:56:32 +00:00
from openerp . tools . translate import _
2013-03-26 12:14:37 +00:00
import pytz
from openerp import SUPERUSER_ID
2012-07-26 20:56:59 +00:00
class sale_order ( osv . osv ) :
_inherit = " sale.order "
2013-09-13 09:38:15 +00:00
2013-01-22 11:08:57 +00:00
def _get_default_warehouse ( self , cr , uid , context = None ) :
2013-06-14 14:33:17 +00:00
company_id = self . pool . get ( ' res.users ' ) . _get_company ( cr , uid , context = context )
2013-06-14 14:16:43 +00:00
warehouse_ids = self . pool . get ( ' stock.warehouse ' ) . search ( cr , uid , [ ( ' company_id ' , ' = ' , company_id ) ] , context = context )
2013-01-22 11:08:57 +00:00
if not warehouse_ids :
2013-12-03 09:55:44 +00:00
return False
2013-01-22 11:08:57 +00:00
return warehouse_ids [ 0 ]
2012-07-26 20:56:59 +00:00
2013-07-22 14:37:47 +00:00
def _get_shipped ( self , cr , uid , ids , name , args , context = None ) :
res = { }
for sale in self . browse ( cr , uid , ids , context = context ) :
2013-08-03 07:42:36 +00:00
group = sale . procurement_group_id
if group :
res [ sale . id ] = all ( [ proc . state in [ ' cancel ' , ' done ' ] for proc in group . procurement_ids ] )
else :
2013-07-22 14:37:47 +00:00
res [ sale . id ] = False
return res
def _get_orders ( self , cr , uid , ids , context = None ) :
res = set ( )
2013-08-26 07:14:05 +00:00
for move in self . browse ( cr , uid , ids , context = context ) :
2013-08-04 13:40:14 +00:00
if move . procurement_id and move . procurement_id . sale_line_id :
res . add ( move . procurement_id . sale_line_id . order_id . id )
2013-07-22 14:37:47 +00:00
return list ( res )
2013-11-07 11:20:53 +00:00
2013-08-23 06:51:19 +00:00
def _get_orders_procurements ( self , cr , uid , ids , context = None ) :
res = set ( )
for proc in self . pool . get ( ' procurement.order ' ) . browse ( cr , uid , ids , context = context ) :
2014-02-24 11:04:13 +00:00
if proc . state == ' done ' and proc . sale_line_id :
2013-08-23 06:51:19 +00:00
res . add ( proc . sale_line_id . order_id . id )
return list ( res )
2013-11-07 11:20:53 +00:00
2013-07-11 13:40:44 +00:00
def _get_picking_ids ( self , cr , uid , ids , name , args , context = None ) :
res = { }
2013-08-03 19:03:59 +00:00
for sale in self . browse ( cr , uid , ids , context = context ) :
if not sale . procurement_group_id :
res [ sale . id ] = [ ]
continue
2013-11-07 11:20:53 +00:00
res [ sale . id ] = self . pool . get ( ' stock.picking ' ) . search ( cr , uid , [ ( ' group_id ' , ' = ' , sale . procurement_group_id . id ) ] , context = context )
2013-07-11 13:40:44 +00:00
return res
2013-10-22 12:06:05 +00:00
def _prepare_order_line_procurement ( self , cr , uid , order , line , group_id = False , context = None ) :
2013-08-02 11:33:08 +00:00
vals = super ( sale_order , self ) . _prepare_order_line_procurement ( cr , uid , order , line , group_id = group_id , context = context )
2013-08-03 07:42:36 +00:00
location_id = order . partner_shipping_id . property_stock_customer . id
2013-08-02 11:33:08 +00:00
vals [ ' location_id ' ] = location_id
2013-10-22 12:06:05 +00:00
routes = line . route_id and [ ( 4 , line . route_id . id ) ] or [ ]
vals [ ' route_ids ' ] = routes
vals [ ' warehouse_id ' ] = order . warehouse_id and order . warehouse_id . id or False
2014-03-27 12:11:40 +00:00
vals [ ' partner_dest_id ' ] = order . partner_shipping_id . id
2013-08-02 11:33:08 +00:00
return vals
2013-07-11 13:40:44 +00:00
2012-07-26 20:56:59 +00:00
_columns = {
2012-10-23 12:04:15 +00:00
' incoterm ' : fields . many2one ( ' stock.incoterms ' , ' Incoterm ' , help = " International Commercial Terms are a series of predefined commercial terms used in international transactions. " ) ,
2012-07-26 20:56:59 +00:00
' picking_policy ' : fields . selection ( [ ( ' direct ' , ' Deliver each product when available ' ) , ( ' one ' , ' Deliver all products at once ' ) ] ,
' Shipping Policy ' , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] , ' sent ' : [ ( ' readonly ' , False ) ] } ,
2012-10-31 11:03:26 +00:00
help = """ Pick ' Deliver each product when available ' if you allow partial delivery. """ ) ,
2012-07-26 20:56:59 +00:00
' order_policy ' : fields . selection ( [
( ' manual ' , ' On Demand ' ) ,
( ' picking ' , ' On Delivery Order ' ) ,
( ' prepaid ' , ' Before Delivery ' ) ,
] , ' Create Invoice ' , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] , ' sent ' : [ ( ' readonly ' , False ) ] } ,
2012-10-31 11:03:26 +00:00
help = """ On demand: A draft invoice can be created from the sales order when needed. \n On delivery order: A draft invoice can be created from the delivery order when the products have been delivered. \n Before delivery: A draft invoice is created from the sales order and must be paid before the products can be delivered. """ ) ,
2013-08-23 06:51:19 +00:00
' shipped ' : fields . function ( _get_shipped , string = ' Delivered ' , type = ' boolean ' , store = {
' procurement.order ' : ( _get_orders_procurements , [ ' state ' ] , 10 )
} ) ,
2013-06-14 14:16:43 +00:00
' warehouse_id ' : fields . many2one ( ' stock.warehouse ' , ' Warehouse ' , required = True ) ,
2013-07-11 13:40:44 +00:00
' picking_ids ' : fields . function ( _get_picking_ids , method = True , type = ' one2many ' , relation = ' stock.picking ' , string = ' Picking associated to this sale ' ) ,
2012-07-26 20:56:59 +00:00
}
_defaults = {
2013-06-29 22:17:03 +00:00
' warehouse_id ' : _get_default_warehouse ,
' picking_policy ' : ' direct ' ,
' order_policy ' : ' manual ' ,
}
2013-01-31 06:26:13 +00:00
def onchange_warehouse_id ( self , cr , uid , ids , warehouse_id , context = None ) :
val = { }
if warehouse_id :
warehouse = self . pool . get ( ' stock.warehouse ' ) . browse ( cr , uid , warehouse_id , context = context )
2013-06-14 14:16:43 +00:00
if warehouse . company_id :
2013-01-31 06:26:13 +00:00
val [ ' company_id ' ] = warehouse . company_id . id
return { ' value ' : val }
2012-07-26 20:56:59 +00:00
def action_view_delivery ( self , cr , uid , ids , context = None ) :
'''
2013-06-29 22:17:03 +00:00
This function returns an action that display existing delivery orders
of given sales order ids . It can either be a in a list or in a form
view , if there is only one delivery order to show .
2012-07-26 20:56:59 +00:00
'''
2013-10-14 14:25:40 +00:00
2012-07-26 20:56:59 +00:00
mod_obj = self . pool . get ( ' ir.model.data ' )
2012-09-19 09:38:42 +00:00
act_obj = self . pool . get ( ' ir.actions.act_window ' )
2013-10-04 09:01:52 +00:00
result = mod_obj . get_object_reference ( cr , uid , ' stock ' , ' action_picking_tree_all ' )
2012-09-19 09:38:42 +00:00
id = result and result [ 1 ] or False
result = act_obj . read ( cr , uid , [ id ] , context = context ) [ 0 ]
2013-06-29 22:17:03 +00:00
2012-07-26 20:56:59 +00:00
#compute the number of delivery orders to display
pick_ids = [ ]
for so in self . browse ( cr , uid , ids , context = context ) :
pick_ids + = [ picking . id for picking in so . picking_ids ]
2013-10-14 14:25:40 +00:00
2012-07-26 20:56:59 +00:00
#choose the view_mode accordingly
if len ( pick_ids ) > 1 :
2013-10-04 09:01:52 +00:00
result [ ' domain ' ] = " [( ' id ' , ' in ' ,[ " + ' , ' . join ( map ( str , pick_ids ) ) + " ])] "
2012-07-26 20:56:59 +00:00
else :
2013-07-23 16:47:55 +00:00
res = mod_obj . get_object_reference ( cr , uid , ' stock ' , ' view_picking_form ' )
2012-09-19 09:38:42 +00:00
result [ ' views ' ] = [ ( res and res [ 1 ] or False , ' form ' ) ]
result [ ' res_id ' ] = pick_ids and pick_ids [ 0 ] or False
2012-07-26 20:56:59 +00:00
return result
2012-08-13 05:17:48 +00:00
2012-12-15 17:50:33 +00:00
def action_invoice_create ( self , cr , uid , ids , grouped = False , states = [ ' confirmed ' , ' done ' , ' exception ' ] , date_invoice = False , context = None ) :
2013-08-30 08:16:48 +00:00
move_obj = self . pool . get ( " stock.move " )
2013-08-03 17:43:20 +00:00
res = super ( sale_order , self ) . action_invoice_create ( cr , uid , ids , grouped = grouped , states = states , date_invoice = date_invoice , context = context )
2012-07-29 16:07:56 +00:00
for order in self . browse ( cr , uid , ids , context = context ) :
if order . order_policy == ' picking ' :
2013-08-30 08:16:48 +00:00
for picking in order . picking_ids :
move_obj . write ( cr , uid , [ x . id for x in picking . move_lines ] , { ' invoice_state ' : ' invoiced ' } , context = context )
2012-07-26 20:56:59 +00:00
return res
def action_cancel ( self , cr , uid , ids , context = None ) :
if context is None :
context = { }
sale_order_line_obj = self . pool . get ( ' sale.order.line ' )
proc_obj = self . pool . get ( ' procurement.order ' )
[IMP] Workflow api changes: [account_payment, account_voucher, hr_holidays, hr_payroll, hr_timesheet_sheet, l10n_in_hr_payroll, point_of_sale, procurement, purchase, sale, sale_stock].
bzr revid: tta@openerp.com-20130204082943-vfevxeb7za6r4sy7
bzr revid: tta@openerp.com-20130204112949-07l1v3ru215iglut
2013-02-04 11:29:49 +00:00
stock_obj = self . pool . get ( ' stock.picking ' )
2012-07-26 20:56:59 +00:00
for sale in self . browse ( cr , uid , ids , context = context ) :
for pick in sale . picking_ids :
if pick . state not in ( ' draft ' , ' cancel ' ) :
raise osv . except_osv (
2012-09-21 08:13:39 +00:00
_ ( ' Cannot cancel sales order! ' ) ,
_ ( ' You must first cancel all delivery order(s) attached to this sales order. ' ) )
2014-07-07 09:50:30 +00:00
stock_obj . signal_workflow ( cr , uid , [ p . id for p in sale . picking_ids ] , ' button_cancel ' )
2012-07-26 20:56:59 +00:00
return super ( sale_order , self ) . action_cancel ( cr , uid , ids , context = context )
2012-09-21 08:13:39 +00:00
def action_wait ( self , cr , uid , ids , context = None ) :
res = super ( sale_order , self ) . action_wait ( cr , uid , ids , context = context )
for o in self . browse ( cr , uid , ids ) :
noprod = self . test_no_product ( cr , uid , o , context )
if noprod and o . order_policy == ' picking ' :
self . write ( cr , uid , [ o . id ] , { ' order_policy ' : ' manual ' } , context = context )
return res
2012-09-17 05:07:38 +00:00
2013-09-09 11:55:15 +00:00
def _get_date_planned ( self , cr , uid , order , line , start_date , context = None ) :
date_planned = super ( sale_order , self ) . _get_date_planned ( cr , uid , order , line , start_date , context = context )
date_planned = ( date_planned - timedelta ( days = order . company_id . security_lead ) ) . strftime ( DEFAULT_SERVER_DATETIME_FORMAT )
return date_planned
def _prepare_procurement_group ( self , cr , uid , order , context = None ) :
res = super ( sale_order , self ) . _prepare_procurement_group ( cr , uid , order , context = None )
res . update ( { ' move_type ' : order . picking_policy } )
return res
2012-07-26 20:56:59 +00:00
def action_ship_end ( self , cr , uid , ids , context = None ) :
2013-09-10 15:48:22 +00:00
super ( sale_order , self ) . action_ship_end ( cr , uid , ids , context = context )
2012-07-26 20:56:59 +00:00
for order in self . browse ( cr , uid , ids , context = context ) :
val = { ' shipped ' : True }
if order . state == ' shipping_except ' :
val [ ' state ' ] = ' progress '
if ( order . order_policy == ' manual ' ) :
for line in order . order_line :
if ( not line . invoiced ) and ( line . state not in ( ' cancel ' , ' draft ' ) ) :
val [ ' state ' ] = ' manual '
break
res = self . write ( cr , uid , [ order . id ] , val )
return True
def has_stockable_products ( self , cr , uid , ids , * args ) :
for order in self . browse ( cr , uid , ids ) :
for order_line in order . order_line :
2012-12-18 22:50:15 +00:00
if order_line . product_id and order_line . product_id . type in ( ' product ' , ' consu ' ) :
2012-07-26 20:56:59 +00:00
return True
return False
2013-08-03 07:25:46 +00:00
2013-09-10 15:48:22 +00:00
2014-08-08 15:22:14 +00:00
class product_product ( osv . osv ) :
_inherit = ' product.product '
def need_procurement ( self , cr , uid , ids , context = None ) :
2014-08-11 13:06:03 +00:00
#when sale/product is installed alone, there is no need to create procurements, but with sale_stock
2014-08-08 15:22:14 +00:00
#we must create a procurement for each product that is not a service.
for product in self . browse ( cr , uid , ids , context = context ) :
if product . type != ' service ' :
return True
return super ( product_product , self ) . need_procurement ( cr , uid , ids , context = context )
2012-07-26 20:56:59 +00:00
class sale_order_line ( osv . osv ) :
_inherit = ' sale.order.line '
2013-09-17 06:43:59 +00:00
2013-07-16 15:33:36 +00:00
def _number_packages ( self , cr , uid , ids , field_name , arg , context = None ) :
res = { }
for line in self . browse ( cr , uid , ids , context = context ) :
try :
res [ line . id ] = int ( ( line . product_uom_qty + line . product_packaging . qty - 0.0001 ) / line . product_packaging . qty )
except :
res [ line . id ] = 1
return res
2013-08-03 07:25:46 +00:00
_columns = {
2013-07-16 15:33:36 +00:00
' product_packaging ' : fields . many2one ( ' product.packaging ' , ' Packaging ' ) ,
' number_packages ' : fields . function ( _number_packages , type = ' integer ' , string = ' Number Packages ' ) ,
2013-10-08 14:32:31 +00:00
' route_id ' : fields . many2one ( ' stock.location.route ' , ' Route ' , domain = [ ( ' sale_selectable ' , ' = ' , True ) ] ) ,
2014-08-07 06:12:13 +00:00
' product_tmpl_id ' : fields . related ( ' product_id ' , ' product_tmpl_id ' , type = ' many2one ' , relation = ' product.template ' , string = ' Product Template ' ) ,
2012-09-21 08:13:39 +00:00
}
2013-07-16 15:33:36 +00:00
_defaults = {
' product_packaging ' : False ,
}
def product_packaging_change ( self , cr , uid , ids , pricelist , product , qty = 0 , uom = False ,
partner_id = False , packaging = False , flag = False , context = None ) :
if not product :
return { ' value ' : { ' product_packaging ' : False } }
product_obj = self . pool . get ( ' product.product ' )
product_uom_obj = self . pool . get ( ' product.uom ' )
pack_obj = self . pool . get ( ' product.packaging ' )
warning = { }
result = { }
warning_msgs = ' '
if flag :
res = self . product_id_change ( cr , uid , ids , pricelist = pricelist ,
product = product , qty = qty , uom = uom , partner_id = partner_id ,
packaging = packaging , flag = False , context = context )
2014-01-20 16:03:03 +00:00
warning_msgs = res . get ( ' warning ' ) and res [ ' warning ' ] . get ( ' message ' , ' ' ) or ' '
2013-07-16 15:33:36 +00:00
products = product_obj . browse ( cr , uid , product , context = context )
2014-06-03 09:53:41 +00:00
if not products . packaging_ids :
2013-07-16 15:33:36 +00:00
packaging = result [ ' product_packaging ' ] = False
if packaging :
default_uom = products . uom_id and products . uom_id . id
pack = pack_obj . browse ( cr , uid , packaging , context = context )
q = product_uom_obj . _compute_qty ( cr , uid , uom , pack . qty , default_uom )
# qty = qty - qty % q + q
if qty and ( q and not ( qty % q ) == 0 ) :
ean = pack . ean or _ ( ' (n/a) ' )
qty_pack = pack . qty
type_ul = pack . ul
if not warning_msgs :
warn_msg = _ ( " You selected a quantity of %d Units. \n "
" But it ' s not compatible with the selected packaging. \n "
" Here is a proposition of quantities according to the packaging: \n "
" EAN: %s Quantity: %s Type of ul: %s " ) % \
( qty , ean , qty_pack , type_ul . name )
warning_msgs + = _ ( " Picking Information ! : " ) + warn_msg + " \n \n "
warning = {
' title ' : _ ( ' Configuration Error! ' ) ,
' message ' : warning_msgs
}
result [ ' product_uom_qty ' ] = qty
return { ' value ' : result , ' warning ' : warning }
2013-10-23 08:57:58 +00:00
def product_id_change_with_wh ( self , cr , uid , ids , pricelist , product , qty = 0 ,
2013-07-16 15:33:36 +00:00
uom = False , qty_uos = 0 , uos = False , name = ' ' , partner_id = False ,
2013-10-10 08:14:42 +00:00
lang = False , update_tax = True , date_order = False , packaging = False , fiscal_position = False , flag = False , warehouse_id = False , context = None ) :
2013-07-16 15:33:36 +00:00
context = context or { }
product_uom_obj = self . pool . get ( ' product.uom ' )
product_obj = self . pool . get ( ' product.product ' )
2014-09-22 12:20:45 +00:00
warehouse_obj = self . pool [ ' stock.warehouse ' ]
2013-07-16 15:33:36 +00:00
warning = { }
2014-09-09 17:06:26 +00:00
#UoM False due to hack which makes sure uom changes price, ... in product_id_change
2014-08-08 09:38:57 +00:00
res = self . product_id_change ( cr , uid , ids , pricelist , product , qty = qty ,
2014-09-01 13:39:32 +00:00
uom = False , qty_uos = qty_uos , uos = uos , name = name , partner_id = partner_id ,
2013-07-16 15:33:36 +00:00
lang = lang , update_tax = update_tax , date_order = date_order , packaging = packaging , fiscal_position = fiscal_position , flag = flag , context = context )
if not product :
res [ ' value ' ] . update ( { ' product_packaging ' : False } )
return res
2013-10-10 08:14:42 +00:00
2013-07-16 15:33:36 +00:00
#update of result obtained in super function
product_obj = product_obj . browse ( cr , uid , product , context = context )
2014-08-07 06:12:13 +00:00
res [ ' value ' ] . update ( { ' product_tmpl_id ' : product_obj . product_tmpl_id . id , ' delay ' : ( product_obj . sale_delay or 0.0 ) } )
2013-07-16 15:33:36 +00:00
# Calling product_packaging_change function after updating UoM
res_packing = self . product_packaging_change ( cr , uid , ids , pricelist , product , qty , uom , partner_id , packaging , context = context )
res [ ' value ' ] . update ( res_packing . get ( ' value ' , { } ) )
warning_msgs = res_packing . get ( ' warning ' ) and res_packing [ ' warning ' ] [ ' message ' ] or ' '
2013-10-10 08:14:42 +00:00
2014-08-08 11:49:10 +00:00
if product_obj . type == ' product ' :
#determine if the product is MTO or not (for a further check)
isMto = False
if warehouse_id :
2014-09-22 12:20:45 +00:00
warehouse = warehouse_obj . browse ( cr , uid , warehouse_id , context = context )
2013-10-10 08:14:42 +00:00
for product_route in product_obj . route_ids :
2014-08-08 11:49:10 +00:00
if warehouse . mto_pull_id and warehouse . mto_pull_id . route_id and warehouse . mto_pull_id . route_id . id == product_route . id :
2013-10-10 08:14:42 +00:00
isMto = True
break
2014-08-08 11:49:10 +00:00
else :
try :
2014-09-22 12:20:45 +00:00
mto_route_id = warehouse_obj . _get_mto_route ( cr , uid , context = context )
2014-08-08 11:49:10 +00:00
except :
# if route MTO not found in ir_model_data, we treat the product as in MTS
mto_route_id = False
if mto_route_id :
for product_route in product_obj . route_ids :
if product_route . id == mto_route_id :
isMto = True
break
2013-10-10 08:14:42 +00:00
2014-08-08 11:49:10 +00:00
#check if product is available, and if not: raise a warning, but do this only for products that aren't processed in MTO
if not isMto :
uom_record = False
if uom :
uom_record = product_uom_obj . browse ( cr , uid , uom , context = context )
if product_obj . uom_id . category_id . id != uom_record . category_id . id :
uom_record = False
if not uom_record :
uom_record = product_obj . uom_id
compare_qty = float_compare ( product_obj . virtual_available , qty , precision_rounding = uom_record . rounding )
if compare_qty == - 1 :
warn_msg = _ ( ' You plan to sell %.2f %s but you only have %.2f %s available ! \n The real stock is %.2f %s . (without reservations) ' ) % \
( qty , uom_record . name ,
max ( 0 , product_obj . virtual_available ) , uom_record . name ,
max ( 0 , product_obj . qty_available ) , uom_record . name )
warning_msgs + = _ ( " Not enough stock ! : " ) + warn_msg + " \n \n "
2013-07-16 15:33:36 +00:00
#update of warning messages
if warning_msgs :
warning = {
' title ' : _ ( ' Configuration Error! ' ) ,
' message ' : warning_msgs
}
res . update ( { ' warning ' : warning } )
return res
2013-09-09 14:23:50 +00:00
class stock_move ( osv . osv ) :
_inherit = ' stock.move '
def _create_invoice_line_from_vals ( self , cr , uid , move , invoice_line_vals , context = None ) :
2014-06-16 14:04:04 +00:00
invoice_line_id = super ( stock_move , self ) . _create_invoice_line_from_vals ( cr , uid , move , invoice_line_vals , context = context )
2013-09-09 14:23:50 +00:00
if move . procurement_id and move . procurement_id . sale_line_id :
sale_line = move . procurement_id . sale_line_id
self . pool . get ( ' sale.order.line ' ) . write ( cr , uid , [ sale_line . id ] , {
' invoice_lines ' : [ ( 4 , invoice_line_id ) ]
} , context = context )
self . pool . get ( ' sale.order ' ) . write ( cr , uid , [ sale_line . order_id . id ] , {
' invoice_ids ' : [ ( 4 , invoice_line_vals [ ' invoice_id ' ] ) ] ,
} )
return invoice_line_id
def _get_master_data ( self , cr , uid , move , company , context = None ) :
if move . procurement_id and move . procurement_id . sale_line_id :
sale_order = move . procurement_id . sale_line_id . order_id
return sale_order . partner_invoice_id , sale_order . user_id . id , sale_order . pricelist_id . currency_id . id
return super ( stock_move , self ) . _get_master_data ( cr , uid , move , company , context = context )
def _get_invoice_line_vals ( self , cr , uid , move , partner , inv_type , context = None ) :
res = super ( stock_move , self ) . _get_invoice_line_vals ( cr , uid , move , partner , inv_type , context = context )
if move . procurement_id and move . procurement_id . sale_line_id :
sale_line = move . procurement_id . sale_line_id
res [ ' invoice_line_tax_id ' ] = [ ( 6 , 0 , [ x . id for x in sale_line . tax_id ] ) ]
res [ ' account_analytic_id ' ] = sale_line . order_id . project_id and sale_line . order_id . project_id . id or False
res [ ' discount ' ] = sale_line . discount
2014-07-07 10:04:01 +00:00
if move . product_id . id != sale_line . product_id . id :
res [ ' price_unit ' ] = self . pool [ ' product.pricelist ' ] . price_get (
cr , uid , [ sale_line . order_id . pricelist_id . id ] ,
move . product_id . id , move . product_uom_qty or 1.0 ,
sale_line . order_id . partner_id , context = context ) [ sale_line . order_id . pricelist_id . id ]
else :
res [ ' price_unit ' ] = sale_line . price_unit
2014-11-26 14:23:34 +00:00
uos_coeff = move . product_uom_qty and move . product_uos_qty / move . product_uom_qty or 1.0
res [ ' price_unit ' ] = res [ ' price_unit ' ] / uos_coeff
2013-09-17 06:43:59 +00:00
return res
2013-10-08 14:32:31 +00:00
class stock_location_route ( osv . osv ) :
_inherit = " stock.location.route "
_columns = {
2014-01-20 14:42:43 +00:00
' sale_selectable ' : fields . boolean ( " Selectable on Sales Order Line " )
2013-10-08 14:32:31 +00:00
}
2014-01-20 14:42:43 +00:00
class stock_picking ( osv . osv ) :
_inherit = " stock.picking "
2014-08-08 12:15:13 +00:00
def _get_partner_to_invoice ( self , cr , uid , picking , context = None ) :
""" Inherit the original function of the ' stock ' module
We select the partner of the sales order as the partner of the customer invoice
"""
saleorder_ids = self . pool [ ' sale.order ' ] . search ( cr , uid , [ ( ' procurement_group_id ' , ' = ' , picking . group_id . id ) ] , context = context )
saleorders = self . pool [ ' sale.order ' ] . browse ( cr , uid , saleorder_ids , context = context )
if saleorders and saleorders [ 0 ] :
saleorder = saleorders [ 0 ]
return saleorder . partner_invoice_id . id
return super ( stock_picking , self ) . _get_partner_to_invoice ( cr , uid , picking , context = context )
2014-03-18 12:18:23 +00:00
def _get_sale_id ( self , cr , uid , ids , name , args , context = None ) :
sale_obj = self . pool . get ( " sale.order " )
res = { }
for picking in self . browse ( cr , uid , ids , context = context ) :
2014-03-28 08:24:16 +00:00
res [ picking . id ] = False
2014-03-18 12:18:23 +00:00
if picking . group_id :
sale_ids = sale_obj . search ( cr , uid , [ ( ' procurement_group_id ' , ' = ' , picking . group_id . id ) ] , context = context )
if sale_ids :
res [ picking . id ] = sale_ids [ 0 ]
return res
_columns = {
2014-03-27 17:42:28 +00:00
' sale_id ' : fields . function ( _get_sale_id , type = " many2one " , relation = " sale.order " , string = " Sale Order " ) ,
}
2014-03-18 12:18:23 +00:00
2014-01-20 14:42:43 +00:00
def _create_invoice_from_picking ( self , cr , uid , picking , vals , context = None ) :
2012-09-09 17:03:41 +00:00
sale_obj = self . pool . get ( ' sale.order ' )
2012-10-15 10:03:03 +00:00
sale_line_obj = self . pool . get ( ' sale.order.line ' )
2014-01-20 14:42:43 +00:00
invoice_line_obj = self . pool . get ( ' account.invoice.line ' )
invoice_id = super ( stock_picking , self ) . _create_invoice_from_picking ( cr , uid , picking , vals , context = context )
if picking . group_id :
sale_ids = sale_obj . search ( cr , uid , [ ( ' procurement_group_id ' , ' = ' , picking . group_id . id ) ] , context = context )
if sale_ids :
sale_line_ids = sale_line_obj . search ( cr , uid , [ ( ' order_id ' , ' in ' , sale_ids ) , ( ' product_id.type ' , ' = ' , ' service ' ) , ( ' invoiced ' , ' = ' , False ) ] , context = context )
if sale_line_ids :
created_lines = sale_line_obj . invoice_line_create ( cr , uid , sale_line_ids , context = context )
invoice_line_obj . write ( cr , uid , created_lines , { ' invoice_id ' : invoice_id } , context = context )
return invoice_id
2014-11-25 22:14:03 +00:00
def _get_invoice_vals ( self , cr , uid , key , inv_type , journal_id , move , context = None ) :
inv_vals = super ( stock_picking , self ) . _get_invoice_vals ( cr , uid , key , inv_type , journal_id , move , context = context )
sale = move . picking_id . sale_id
if sale :
inv_vals . update ( {
' fiscal_position ' : sale . fiscal_position . id ,
' payment_term ' : sale . payment_term . id ,
' user_id ' : sale . user_id . id ,
2014-12-10 10:58:03 +00:00
' section_id ' : sale . section_id . id ,
2014-11-25 22:14:03 +00:00
' name ' : sale . client_order_ref or ' ' ,
} )
return inv_vals