diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py
index 2782f822149..591f65cf925 100644
--- a/addons/point_of_sale/point_of_sale.py
+++ b/addons/point_of_sale/point_of_sale.py
@@ -700,7 +700,7 @@ class pos_order(osv.osv):
picking_id = picking_obj.create(cr, uid, {
'origin': order.name,
'partner_id': addr.get('delivery',False),
- 'type': 'out',
+ 'picking_type_id': self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'picking_type_out', context=context).id,
'company_id': order.company_id.id,
'move_type': 'direct',
'note': order.note or "",
diff --git a/addons/point_of_sale/wizard/pos_return.py b/addons/point_of_sale/wizard/pos_return.py
index eeba6cab676..fac55c593e7 100644
--- a/addons/point_of_sale/wizard/pos_return.py
+++ b/addons/point_of_sale/wizard/pos_return.py
@@ -213,7 +213,7 @@ class add_product(osv.osv_memory):
'name':'%s (Added)' %order_id.name,
'move_lines':[],
'state':'draft',
- 'type':'out',
+ 'picking_type_id': self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'picking_type_out', context=context).id,
'date':date_cur
})
stock_move_obj.create(cr, uid, {
diff --git a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml
index 99e5fc41401..2d95eb89d71 100644
--- a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml
+++ b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml
@@ -14,8 +14,7 @@
!record {model: product.product, id: product_product_hrmanger0}:
categ_id: product.product_category_6
mes_type: fixed
- name: HR Manger
- procure_method: make_to_stock
+ name: HR Manager
standard_price: 1.0
supply_method: buy
type: service
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 79df9f31103..8efacf7f75e 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -150,6 +150,10 @@ class purchase_order(osv.osv):
limit=1)
return res and res[0] or False
+ def _get_picking_in(self, cr, uid, context=None):
+ obj_data = self.pool.get('ir.model.data')
+ return obj_data.get_object_reference(cr, uid, 'stock','picking_type_in')[1]
+
STATE_SELECTION = [
('draft', 'Draft PO'),
('sent', 'RFQ Sent'),
@@ -230,6 +234,7 @@ class purchase_order(osv.osv):
'journal_id': fields.many2one('account.journal', 'Journal'),
'bid_date': fields.date('Bid Received On', readonly=True, help="Date on which the bid was received"),
'bid_validity': fields.date('Bid Valid Until', help="Date on which the bid expired"),
+ 'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', help="This will determine picking type of incoming shipment"),
}
_defaults = {
'date_order': fields.date.context_today,
@@ -241,7 +246,8 @@ class purchase_order(osv.osv):
'pricelist_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').browse(cr, uid, context['partner_id']).property_product_pricelist_purchase.id,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'purchase.order', context=c),
'journal_id': _get_journal,
- 'currency_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
+ 'currency_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id,
+ 'picking_type_id': _get_picking_in,
}
_sql_constraints = [
('name_uniq', 'unique(name, company_id)', 'Order Reference must be unique per Company!'),
@@ -380,6 +386,8 @@ class purchase_order(osv.osv):
'''
This function returns an action that display existing picking orders of given purchase order ids.
'''
+ if context is None:
+ context = {}
mod_obj = self.pool.get('ir.model.data')
pick_ids = []
for po in self.browse(cr, uid, ids, context=context):
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index e3af7bd6243..973757770c4 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -198,6 +198,7 @@
+
diff --git a/addons/purchase/test/average_price.yml b/addons/purchase/test/average_price.yml
index 0fa2dfb0a4f..79bae838f7e 100644
--- a/addons/purchase/test/average_price.yml
+++ b/addons/purchase/test/average_price.yml
@@ -55,10 +55,9 @@
-
Process the reception of purchase order 1
-
- !python {model: stock.partial.picking}: |
+ !python {model: stock.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_average1")).picking_ids
- partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
- self.do_partial(cr, uid, [partial_id])
+ self.do_partial(cr, uid, [pick_ids[0].id])
-
Check the standard price of the product (average icecream).
-
@@ -69,10 +68,9 @@
-
Process the reception of purchase order 2
-
- !python {model: stock.partial.picking}: |
+ !python {model: stock.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_average2")).picking_ids
- partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
- self.do_partial(cr, uid, [partial_id])
+ self.do_partial(cr, uid, [pick_ids[0].id])
-
Check the standard price
-
@@ -82,7 +80,7 @@
Create picking to send some goods
-
!record {model: stock.picking, id: outgoing_average_shipment}:
- type: out
+ picking_type_id: stock.picking_type_out
-
Create move for picking
-
@@ -91,18 +89,12 @@
product_id: product_average_icecream
product_uom: product.product_uom_kgm
product_qty: 20.0
- type: out
-
- I assign this outgoing shipment
+ I assign this outgoing shipment and process the delivery
-
!python {model: stock.picking}: |
self.action_assign(cr, uid, [ref("outgoing_average_shipment")])
--
- Process the delivery of the outgoing shipment
--
- !python {model: stock.partial.picking}: |
- partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_average_shipment")], 'default_type':'out'})
- self.do_partial(cr, uid, [partial_id])
+ self.do_partial(cr, uid, [ref("outgoing_average_shipment")])
-
Check the standard price (60 * 10 + 30 * 80) / 40 = 75.0 did not change
-
@@ -129,10 +121,9 @@
-
Process the reception of purchase order 3 in grams
-
- !python {model: stock.partial.picking}: |
+ !python {model: stock.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_average3")).picking_ids
- partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
- self.do_partial(cr, uid, [partial_id])
+ self.do_partial(cr, uid, [pick_ids[0].id])
-
Check price is (75.0*20 + 500) / 20.5 = 97.56097561
-
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index b55fccc8984..6535ed7bc6d 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -658,7 +658,7 @@ class sale_order(osv.osv):
for order in self.browse(cr, uid, ids, context=context):
proc_ids = []
group_id = self.pool.get("procurement.group").create(cr, uid, {
- 'name': order.name, 'partner_id': order.partner_shipping_id.id
+ 'name': order.name, 'partner_id': order.partner_shipping_id.id, 'move_type': order.picking_policy
}, context=context)
order.write({'procurement_group_id': group_id}, context=context)
for line in order.order_line:
@@ -1082,4 +1082,4 @@ class procurement_order(osv.osv):
_defaults = {
'invoice_state': 'none',
}
-
+
\ No newline at end of file
diff --git a/addons/sale_stock/__init__.py b/addons/sale_stock/__init__.py
index 9c74739d4c9..72b3d5672d5 100644
--- a/addons/sale_stock/__init__.py
+++ b/addons/sale_stock/__init__.py
@@ -20,9 +20,7 @@
##############################################################################
import sale_stock
-import stock
import report
import company
import res_config
-import wizard
diff --git a/addons/sale_stock/__openerp__.py b/addons/sale_stock/__openerp__.py
index b1686bebb20..059c5a59c1d 100644
--- a/addons/sale_stock/__openerp__.py
+++ b/addons/sale_stock/__openerp__.py
@@ -51,7 +51,6 @@ You can choose flexible invoicing methods:
'security/sale_stock_security.xml',
'security/ir.model.access.csv',
'company_view.xml',
- 'wizard/stock_invoice_onshipping_view.xml',
'sale_stock_view.xml',
'sale_stock_workflow.xml',
'stock_view.xml',
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index 3163365ffc0..015347449ae 100644
--- a/addons/sale_stock/sale_stock.py
+++ b/addons/sale_stock/sale_stock.py
@@ -61,7 +61,14 @@ class sale_order(osv.osv):
if move.procurement_id and move.procurement_id.sale_line_id:
res.add(move.procurement_id.sale_line_id.order_id.id)
return list(res)
-
+
+ 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):
+ if proc.sale_line_id:
+ res.add(proc.sale_line_id.order_id.id)
+ return list(res)
+
def _get_picking_ids(self, cr, uid, ids, name, args, context=None):
res = {}
for sale in self.browse(cr, uid, ids, context=context):
@@ -107,7 +114,10 @@ class sale_order(osv.osv):
('prepaid', 'Before Delivery'),
], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
help="""On demand: A draft invoice can be created from the sales order when needed. \nOn delivery order: A draft invoice can be created from the delivery order when the products have been delivered. \nBefore delivery: A draft invoice is created from the sales order and must be paid before the products can be delivered."""),
- 'shipped': fields.function(_get_shipped, string='Delivered', type='boolean', store={'stock.move': (_get_orders, ['state'], 10)}),
+ 'shipped': fields.function(_get_shipped, string='Delivered', type='boolean', store={
+ 'stock.move': (_get_orders, ['state'], 10),
+ 'procurement.order': (_get_orders_procurements, ['state'], 10)
+ }),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True),
'picking_ids': fields.function(_get_picking_ids, method=True, type='one2many', relation='stock.picking', string='Picking associated to this sale'),
}
@@ -223,7 +233,7 @@ class sale_order(osv.osv):
self.pool.get('sale.order.line').write(cr, uid, write_done_ids, {'state': 'done'})
if write_cancel_ids:
self.pool.get('sale.order.line').write(cr, uid, write_cancel_ids, {'state': 'exception'})
-
+
if mode == 'finished':
return finished
elif mode == 'canceled':
@@ -265,7 +275,7 @@ class sale_order(osv.osv):
class sale_order_line(osv.osv):
_inherit = 'sale.order.line'
-
+
def _number_packages(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for line in self.browse(cr, uid, ids, context=context):
diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml
index 03731bd737c..9e14ce46ce1 100644
--- a/addons/sale_stock/sale_stock_view.xml
+++ b/addons/sale_stock/sale_stock_view.xml
@@ -104,21 +104,7 @@
groups="sale.group_delivery_invoice_address"
/>
-
- stock.picking.form.inherit
- stock.picking
-
-
-
-
-
-
-
-
-
-
- stock.picking.search.inherit
diff --git a/addons/sale_stock/wizard/__init__.py b/addons/sale_stock/wizard/__init__.py
deleted file mode 100644
index e32a95fef96..00000000000
--- a/addons/sale_stock/wizard/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
-#
-# 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,
-# 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 .
-#
-##############################################################################
-
-import stock_invoice_onshipping
diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py
index 7f36871b9d1..392e65d1c91 100644
--- a/addons/stock/procurement.py
+++ b/addons/stock/procurement.py
@@ -40,7 +40,7 @@ class procurement_rule(osv.osv):
'location_id': fields.many2one('stock.location', 'Destination Location'),
'location_src_id': fields.many2one('stock.location', 'Source Location',
help="Source location is action=move"),
- 'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', required=True,
+ 'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type',
help="Picking Type determines the way the picking should be shown in the view, reports, ...")
}
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 56b6c311074..931b4c002ea 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -332,7 +332,7 @@ class stock_quant(osv.osv):
def quants_unreserve(self, cr, uid, move, context=None):
#cr.execute('update stock_quant set reservation_id=NULL where reservation_id=%s', (move.id,))
#need write for related store of remaining qty
- related_quants = self.search(cr, uid, [('reservation_id', '=', move.id)], context=context)
+ related_quants = [x.id for x in move.reserved_quant_ids]
self.write(cr, uid, related_quants, {'reservation_id': False}, context=context)
return True
@@ -530,7 +530,8 @@ class stock_picking(osv.osv):
picking_obj = self.browse(cr, uid, id, context=context)
if ('name' not in default) or (picking_obj.name == '/'):
default['name'] = '/'
- default['backorder_id'] = False
+ if not default.get('backorder_id'):
+ default['backorder_id'] = False
return super(stock_picking, self).copy(cr, uid, id, default, context)
def action_confirm(self, cr, uid, ids, context=None):
@@ -1441,6 +1442,8 @@ class stock_move(osv.osv):
"""
context = context or {}
for move in self.browse(cr, uid, ids, context=context):
+ if move.reserved_quant_ids:
+ self.pool.get("stock.quant").quants_unreserve(cr, uid, move, context=context)
if move.move_dest_id:
if move.propagate:
self.action_cancel(cr, uid, [move.move_dest_id.id], context=context)
@@ -1615,10 +1618,9 @@ class stock_move(osv.osv):
return res
def split(self, cr, uid, move, qty, context=None):
- """ Partially (or not) moves a stock.move.
- @param partial_datas: Dictionary containing details of partial picking
- like partner_id, delivery_date, delivery
- moves with product_id, product_qty, uom
+ """
+ Splits qty from move move into a new move
+ It will check if it can propagate the split
"""
if move.product_qty==qty:
return move.id
@@ -1647,6 +1649,9 @@ class stock_move(osv.osv):
'product_uos_qty': move.product_uos_qty - uos_qty,
# 'reserved_quant_ids': [(6,0,[])] SHOULD NOT CHANGE as it has been reserved already
}, context=context)
+
+ if move.move_dest_id and move.propagate:
+ self.split(self, cr, uid, move.move_dest_id, qty, context=context)
return new_move
class stock_inventory(osv.osv):
@@ -1930,7 +1935,7 @@ report_sxw.report_sxw('report.stock.quant.package.barcode', 'stock.quant.package
class stock_package(osv.osv):
"""
- These are the packages, containing quants and/or others packages
+ These are the packages, containing quants and/or other packages
"""
_name = "stock.quant.package"
_description = "Physical Packages"
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index e274eb28758..487c97cdd2a 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -484,6 +484,7 @@
stock.warehouse
@@ -1442,10 +1444,41 @@
-
+
+
+
+
+ stock.procurement.form
+ procurement.rule
+
+
+
+
+
+
@@ -1529,6 +1562,7 @@
+
diff --git a/addons/stock/wizard/orderpoint_procurement_view.xml b/addons/stock/wizard/orderpoint_procurement_view.xml
index 227b79b3234..20250bb78dd 100644
--- a/addons/stock/wizard/orderpoint_procurement_view.xml
+++ b/addons/stock/wizard/orderpoint_procurement_view.xml
@@ -31,6 +31,7 @@
target="new"
key2="client_action_multi"
id="action_procurement_compute"/>
+
diff --git a/addons/stock_account/__init__.py b/addons/stock_account/__init__.py
index 3bab8f50207..d74ac75cb98 100644
--- a/addons/stock_account/__init__.py
+++ b/addons/stock_account/__init__.py
@@ -21,5 +21,6 @@
import product
import stock_account
+import stock
import wizard
diff --git a/addons/stock_account/__openerp__.py b/addons/stock_account/__openerp__.py
index 93ffe4006ec..6a22e327bb1 100644
--- a/addons/stock_account/__openerp__.py
+++ b/addons/stock_account/__openerp__.py
@@ -49,6 +49,7 @@ Dashboard / Reports for Warehouse Management will include:
'data': [
'stock_account_data.xml',
'wizard/stock_change_standard_price_view.xml',
+ 'wizard/stock_invoice_onshipping_view.xml',
'product_data.xml',
'product_view.xml',
'stock_account_view.xml',
diff --git a/addons/sale_stock/stock.py b/addons/stock_account/stock.py
similarity index 100%
rename from addons/sale_stock/stock.py
rename to addons/stock_account/stock.py
diff --git a/addons/stock_account/stock_account.py b/addons/stock_account/stock_account.py
index 2dc3d804ccd..f9e62fa80e2 100644
--- a/addons/stock_account/stock_account.py
+++ b/addons/stock_account/stock_account.py
@@ -34,6 +34,12 @@ import openerp.addons.decimal_precision as dp
import logging
_logger = logging.getLogger(__name__)
+#----------------------------------------------------------
+# Invoice state
+#----------------------------------------------------------
+
+
+
#----------------------------------------------------------
# Stock Location
diff --git a/addons/stock_account/stock_account_view.xml b/addons/stock_account/stock_account_view.xml
index cf9aaebf236..a7e6bc8afe9 100644
--- a/addons/stock_account/stock_account_view.xml
+++ b/addons/stock_account/stock_account_view.xml
@@ -16,5 +16,21 @@
+
+
+ stock.picking.form.inherit
+ stock.picking
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/stock_account/wizard/__init__.py b/addons/stock_account/wizard/__init__.py
index ecb883ed6fb..001a39e763e 100644
--- a/addons/stock_account/wizard/__init__.py
+++ b/addons/stock_account/wizard/__init__.py
@@ -20,3 +20,4 @@
##############################################################################
import stock_change_standard_price
+import stock_invoice_onshipping
diff --git a/addons/sale_stock/wizard/stock_invoice_onshipping.py b/addons/stock_account/wizard/stock_invoice_onshipping.py
similarity index 100%
rename from addons/sale_stock/wizard/stock_invoice_onshipping.py
rename to addons/stock_account/wizard/stock_invoice_onshipping.py
diff --git a/addons/sale_stock/wizard/stock_invoice_onshipping_view.xml b/addons/stock_account/wizard/stock_invoice_onshipping_view.xml
similarity index 100%
rename from addons/sale_stock/wizard/stock_invoice_onshipping_view.xml
rename to addons/stock_account/wizard/stock_invoice_onshipping_view.xml
diff --git a/addons/stock_complex_routes/__openerp__.py b/addons/stock_complex_routes/__openerp__.py
index 872f42d98b5..6120538cc64 100644
--- a/addons/stock_complex_routes/__openerp__.py
+++ b/addons/stock_complex_routes/__openerp__.py
@@ -38,7 +38,12 @@ This adds a route on the sales order and sales order line (mini module)
'init_xml': [],
'update_xml': ['stock_complex_routes.xml'],
'demo_xml': [],
- 'test': ['test/lifo_price.yml'],
+ 'test': [
+ 'test/crossdock.yml',
+ 'test/dropship.yml',
+ 'test/procurementexception.yml',
+ 'test/lifo_price.yml'
+ ],
'installable': True,
'auto_install': True,
}
diff --git a/addons/stock_complex_routes/test/crossdock.yml b/addons/stock_complex_routes/test/crossdock.yml
new file mode 100644
index 00000000000..e757cbfd554
--- /dev/null
+++ b/addons/stock_complex_routes/test/crossdock.yml
@@ -0,0 +1,37 @@
+-
+ Create new product without any routes
+-
+ !record {model: product.product, id: cross_shop_product}:
+ name: PCE
+ type: product
+ categ_id: product.product_category_1
+ list_price: 100.0
+ standard_price: 70.0
+ seller_ids:
+ - delay: 1
+ name: base.res_partner_2
+ min_qty: 2.0
+ qty: 5.0
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ Create a sales order with a line of 100 PCE incoming shipment, with route_id crossdock shipping.
+-
+ !record {model: sale.order, id: sale_order_crossdock_shpng}:
+ partner_id: base.res_partner_4
+ note: Create Sales order
+ order_line:
+ - product_id: cross_shop_product
+ product_uom_qty: 100.00
+ route_id: stock_location.route_warehouse0_crossdock
+-
+ Confirm sales order
+-
+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_crossdock_shpng}
+-
+ Check a quotation was created to a certain supplier and confirm so it becomes a confirmed purchase order
+-
+ !python {model: purchase.order}: |
+ po_id = self.search(cr, uid, [('partner_id', '=', ref('base.res_partner_2'))])
+ self.wkf_confirm_order(cr, uid, po_id)
diff --git a/addons/stock_complex_routes/test/dropship.yml b/addons/stock_complex_routes/test/dropship.yml
index 7bcb1b93a71..a8f19969dc4 100644
--- a/addons/stock_complex_routes/test/dropship.yml
+++ b/addons/stock_complex_routes/test/dropship.yml
@@ -1,53 +1,68 @@
-
- Create new product without any routes
+ Create new product without any routes
-
- !record {model:product.product, id:}
+ !record {model: product.product, id: drop_shop_product}:
+ name: Pen drive
+ type: product
+ categ_id: product.product_category_1
+ list_price: 100.0
+ standard_price: 70.0
+ seller_ids:
+ - delay: 1
+ name: base.res_partner_2
+ min_qty: 2.0
+ qty: 5.0
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
-
- Create a sales order with a line of 200 PCE incoming shipment, with route_id drop shipping
+ Create a sales order with a line of 200 PCE incoming shipment, with route_id drop shipping.
-
- !record {model: sale.order, id: } :
- customer:
- - product_id:
- product_qty: 200
- product_uom:
- supplier_ids:
-
-
+ !record {model: sale.order, id: sale_order_drp_shpng}:
+ partner_id: base.res_partner_2
+ note: Create sale order for drop shipping
+ payment_term: account.account_payment_term
+ order_line:
+ - product_id: drop_shop_product
+ product_uom_qty: 200
+ price_unit: 100.00
+ route_id: route_drop_shipping
-
- Confirm sales order
+ Confirm sales order
-
- !python{model: sale.order}: |
- self.browse(cr, uid, ref()).action_b
+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_drp_shpng}
-
- Check the sales order created a procurement group which has a procurement of 200 pieces
+ Check the sales order created a procurement group which has a procurement of 200 pieces
-
- !python{model: procurement.group}: |
- proc_group = self.search(cr, uid, [('sale_id', '=', ref())])
- assert self.browse(cr, uid, proc_group)[0].procurement_ids[0].product_qty == 200
+ !python {model: procurement.group}: |
+ sale_record = self.pool.get("sale.order").browse(cr, uid, ref('sale_order_drp_shpng'))
+ assert self.browse(cr, uid, sale_record.procurement_group_id.id).procurement_ids[0].product_qty == 200
-
- Check a quotation was created to a certain supplier and confirm so it becomes a confirmed purchase order
+ Check a quotation was created to a certain supplier and confirm so it becomes a confirmed purchase order
+-
+ !python {model: purchase.order}: |
+ from openerp import netsvc
+ sale_record = self.pool.get("sale.order").browse(cr, uid, ref('sale_order_drp_shpng'))
+ procurement_order = self.pool.get("procurement.group").browse(cr, uid, sale_record.procurement_group_id.id).procurement_ids[0]
+ purchase_id = procurement_order.purchase_id.id
+ wf_service = netsvc.LocalService('workflow')
+ wf_service.trg_validate(uid, 'purchase.order', purchase_id, 'purchase_confirm', cr)
-
-
+ Use 'Receive Products' button to immediately view this picking, it should have created a picking with 200 pieces..
+-
+ !python {model: purchase.order}: |
+ po_id = self.search(cr, uid, [('partner_id', '=', ref('base.res_partner_2'))])
+ self.view_picking(cr, uid, po_id)
+-
+ Send the 200 pieces.
-
- Check the sales order has one picking with 200 pieces
+ !python {model: stock.picking}: |
+ po_id = self.pool.get('purchase.order').search(cr, uid, [('partner_id', '=', ref('base.res_partner_2'))])
+ picking_id = self.search(cr, uid, [('purchase_id', '=', po_id[0])])
+ self.do_partial(cr, uid, picking_id)
-
- !python{model: sale.order}: |
- assert len(self.browse(cr, uid, ref()).picking_ids) == 1
+ Check one quant was created in Customers location with 200 pieces and one move in the history_ids
-
- Use 'View Delivery Order' button to immediately view this picking and check shipped of purchase order is False
--
-
--
- Send the 200 pieces
--
- !python{model: stock.partial.picking}: |
-
-
--
- Check one quant was created in Customers location with 200 pieces and one move in the move_history_ids
--
-
--
- Check the sum of the moves related to this product and the sum of the quants is equal
--
-
+ !python {model: stock.quant}: |
+ quant_id = self.search(cr, uid, [('location_id', '=', ref('stock.stock_location_customers')),('qty', '=', 200)])
+ assert len(self.browse(cr, uid, quant_id)[0].history_ids) == 1
+ assert len(quant_id) == 1
diff --git a/addons/stock_complex_routes/test/procurementexception.yml b/addons/stock_complex_routes/test/procurementexception.yml
index 67afc101089..e5c7dbfd72c 100644
--- a/addons/stock_complex_routes/test/procurementexception.yml
+++ b/addons/stock_complex_routes/test/procurementexception.yml
@@ -1,37 +1,63 @@
--
- Create product with no seller_ids
-
-
--
- Create a sales order with 1 piece for that product and route crossdock
--
- !record{sale.order}
--
- Confirm sales order
--
- !python {
--
- Check there is a procurement in exception that has the procurement group of the sales order
--
- !python {
- assert
--
- Adjust the product that it has at least one seller_id
--
- !record{id: model: product.product) or in !python
--
- Run the Scheduler
--
- !python
--
- Check the status changed there is no procurement order in exception any more from that procurement group
--
- !python{model: procurement.order}
- search procurement from
--
- Check a purchase quotation was created
--
-
-
-
-
+ I create a product with no supplier define for it.
+-
+ !record {model: product.product, id: product_with_no_seller}:
+ name: 'product with no seller'
+ list_price: 20.00
+ standard_price: 15.00
+ categ_id: product.product_category_1
+-
+ I create a sales order with this product with route crossdock.
+-
+ !record {model: sale.order, id: sale_order_route_crossdock}:
+ partner_id: base.res_partner_2
+ partner_invoice_id: base.res_partner_address_3
+ partner_shipping_id: base.res_partner_address_3
+ note: crossdock route
+ payment_term: account.account_payment_term
+ order_line:
+ - product_id: product_with_no_seller
+ product_uom_qty: 1
+ route_id: stock_location.route_warehouse0_crossdock
+-
+ I confirm the sales order.
+-
+ !workflow {model: sale.order, ref: sale_order_route_crossdock, action: order_confirm}
+-
+ I check there is a procurement in exception that has the procurement group of the sales order created before.
+-
+ !python {model: procurement.order}: |
+ self.run_scheduler(cr, uid)
+ sale_id = self.pool.get('sale.order').browse(cr, uid, ref("sale_order_route_crossdock"))
+ proc_id = self.search(cr, uid, [('group_id.name', '=', sale_id.name), ('state', '=', 'exception')])
+ assert proc_id, 'No Procurement!'
+-
+ I set the at least one supplier on the product.
+-
+ !record {model: product.product, id: product_with_no_seller}:
+ seller_ids:
+ - delay: 1
+ name: base.res_partner_2
+ min_qty: 2.0
+-
+ I run the Procurement.
+-
+ !python {model: procurement.order}: |
+ sale_id = self.pool.get('sale.order').browse(cr, uid, ref("sale_order_route_crossdock"))
+ proc_id = self.search(cr, uid, [('group_id.name', '=', sale_id.name), ('state', '=', 'exception')])
+ self.run(cr, uid, proc_id)
+-
+ I check the status changed there is no procurement order in exception any more from that procurement group
+-
+ !python {model: procurement.order}: |
+ sale_id = self.pool.get('sale.order').browse(cr, uid, ref("sale_order_route_crossdock"))
+ proc_id = self.search(cr, uid, [('group_id.name', '=', sale_id.name), ('state', '=', 'exception')])
+ assert not proc_id, 'Procurement should be in running state'
+-
+ I check a purchase quotation was created.
+-
+ !python {model: procurement.order}: |
+ sale_id = self.pool.get('sale.order').browse(cr, uid, ref("sale_order_route_crossdock"))
+ proc_ids = self.search(cr, uid, [('group_id.name', '=', sale_id.name)])
+ purchase_id = [proc.purchase_id for proc in self.browse(cr, uid, proc_ids) if proc.purchase_id]
+ assert purchase_id, 'No Purchase Quotation is created'
diff --git a/addons/stock_location/stock_location.py b/addons/stock_location/stock_location.py
index 8a389721733..77d1a67149a 100644
--- a/addons/stock_location/stock_location.py
+++ b/addons/stock_location/stock_location.py
@@ -28,20 +28,29 @@ class stock_location_route(osv.osv):
_name = 'stock.location.route'
_description = "Inventory Routes"
_order = 'sequence'
+
+ def _default_warehouse(self, cr, uid, context=None):
+ user = self.pool.get('res.users').browse(cr, uid, uid, context)
+ res = self.pool.get('stock.warehouse').search(cr, uid, [('company_id', '=', user.company_id.id)], limit=1, context=context)
+ return res and res[0] or False
+
_columns = {
'name': fields.char('Route Name', required=True),
'sequence': fields.integer('Sequence'),
'pull_ids': fields.one2many('procurement.rule', 'route_id', 'Pull Rules'),
'push_ids': fields.one2many('stock.location.path', 'route_id', 'Push Rules'),
+ 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
}
_defaults = {
'sequence': lambda self,cr,uid,ctx: 0,
+ 'warehouse_id': _default_warehouse,
}
class stock_warehouse(osv.osv):
_inherit = 'stock.warehouse'
_columns = {
'route_id': fields.many2one('stock.location.route', 'Default Logistic Route', help='Default route through the warehouse', required=True),
+ 'route_ids': fields.one2many('stock.location.route', 'warehouse_id', 'All Routes'),
}
@@ -60,7 +69,7 @@ class stock_location_path(osv.osv):
("2binvoiced", "To Be Invoiced"),
("none", "Not Applicable")], "Invoice Status",
required=True,),
- 'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', help="This is the picking type associated with the different pickings"),
+ 'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', required=True, help="This is the picking type associated with the different pickings"),
'auto': fields.selection(
[('auto','Automatic Move'), ('manual','Manual Operation'),('transparent','Automatic No Step Added')],
'Automatic Move',
diff --git a/addons/stock_location/stock_location_view.xml b/addons/stock_location/stock_location_view.xml
index 8a42f2afb46..f3a0a0726c9 100644
--- a/addons/stock_location/stock_location_view.xml
+++ b/addons/stock_location/stock_location_view.xml
@@ -2,6 +2,26 @@
+
+ stock.procurement.rule.inherit.form
+ procurement.rule
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ stock.location.form
@@ -137,6 +157,14 @@
+
+
+
+
+
+
+
+
@@ -147,6 +175,7 @@
+
@@ -159,6 +188,7 @@
You can define here the main logistic routes that run through
your warehouses and that define the flows of your products. These
- routes can be assigned to a product, a product category or on a
- location.
+ routes can be assigned to a product, a product category or be fixed
+ on procurement or sales order.
@@ -191,5 +221,17 @@
+
+
+
+ procurement.order.form.view.inherit
+
+ procurement.order
+
+
+
+
+
+
diff --git a/addons/stock_location/test/stock_location_push_flow.yml b/addons/stock_location/test/stock_location_push_flow.yml
index 3a6f0a1b2c3..0d9c71acd48 100644
--- a/addons/stock_location/test/stock_location_push_flow.yml
+++ b/addons/stock_location/test/stock_location_push_flow.yml
@@ -32,9 +32,11 @@
- invoice_state: none
location_dest_id: stock_location.stock_location_qualitytest0
location_from_id: stock.stock_location_stock
+ picking_type_id: stock.picking_type_internal
- invoice_state: none
location_dest_id: stock.stock_location_components
location_from_id: stock_location.stock_location_qualitytest0
+ picking_type_id: stock.picking_type_internal
-
!record {model: product.product, id: product_product_hpcdwriters01}:
list_price: 1000.0