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 660b70a488c..8efacf7f75e 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -386,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/stock_view.xml b/addons/purchase/stock_view.xml
index 07aefef2e14..a924a5c341e 100644
--- a/addons/purchase/stock_view.xml
+++ b/addons/purchase/stock_view.xml
@@ -13,12 +13,12 @@
- Incoming Picking Inherited
+ Picking Inherited
stock.picking
-
-
+
+
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index b55fccc8984..497b99ef1b8 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:
@@ -1072,14 +1072,5 @@ class procurement_order(osv.osv):
_inherit = 'procurement.order'
_columns = {
'sale_line_id': fields.many2one('sale.order.line', string='Sale Order Line'),
- 'invoice_state': fields.selection(
- [
- ("invoiced", "Invoiced"),
- ("2binvoiced", "To Be Invoiced"),
- ("none", "Not Applicable")
- ], "Invoice Control", required=True),
}
- _defaults = {
- 'invoice_state': 'none',
- }
-
+
\ No newline at end of file
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index 3163365ffc0..055b4309d6d 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'),
}
@@ -158,11 +168,12 @@ class sale_order(osv.osv):
# if order_policy<>picking: super()
# else: call invoice_on_picking_method()
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_invoice = False, context=None):
- picking_obj = self.pool.get('stock.picking')
+ move_obj = self.pool.get("stock.move")
res = super(sale_order,self).action_invoice_create(cr, uid, ids, grouped=grouped, states=states, date_invoice = date_invoice, context=context)
for order in self.browse(cr, uid, ids, context=context):
if order.order_policy == 'picking':
- picking_obj.write(cr, uid, map(lambda x: x.id, order.picking_ids), {'invoice_state': 'invoiced'})
+ for picking in order.picking_ids:
+ move_obj.write(cr, uid, [x.id for x in picking.move_lines], {'invoice_state': 'invoiced'}, context=context)
return res
def action_cancel(self, cr, uid, ids, context=None):
@@ -223,7 +234,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 +276,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/stock/__openerp__.py b/addons/stock/__openerp__.py
index 57019053481..21cb3ced87d 100644
--- a/addons/stock/__openerp__.py
+++ b/addons/stock/__openerp__.py
@@ -91,7 +91,9 @@ Dashboard / Reports for Warehouse Management will include:
'test': [
'test/inventory.yml',
'test/move.yml',
-# 'test/shipment.yml',
+ 'test/procrule.yml',
+ 'test/shipment.yml',
+ 'test/packing.yml',
],
'installable': True,
'application': True,
diff --git a/addons/stock/res_config.py b/addons/stock/res_config.py
index 0f9e1e5943f..3abfc34ca23 100644
--- a/addons/stock/res_config.py
+++ b/addons/stock/res_config.py
@@ -62,6 +62,9 @@ This installs the module product_expiry."""),
'group_stock_tracking_lot': fields.boolean("Track serial number on logistic units (pallets)",
implied_group='stock.group_tracking_lot',
help="""When you select a serial number on product moves, you can get the upstream or downstream traceability of that product."""),
+ 'group_stock_tracking_owner': fields.boolean("Manage owner on stock",
+ implied_group='stock.group_tracking_owner',
+ help="""This way you can receive products attributed to a certain owner. """),
'module_stock_account': fields.boolean("Generate accounting entries per stock movement",
implied_group='stock.group_inventory_valuation',
help="""Allows to configure inventory valuations on products and product categories."""),
diff --git a/addons/stock/res_config_view.xml b/addons/stock/res_config_view.xml
index f5015b146b5..d3654b7abee 100644
--- a/addons/stock/res_config_view.xml
+++ b/addons/stock/res_config_view.xml
@@ -38,6 +38,10 @@
+
+
+
+
diff --git a/addons/stock/security/stock_security.xml b/addons/stock/security/stock_security.xml
index 6df63f351e7..105c4a7b7ce 100644
--- a/addons/stock/security/stock_security.xml
+++ b/addons/stock/security/stock_security.xml
@@ -29,6 +29,11 @@
+
+ Manage Different Stock Owners
+
+
+
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 740e60b9a50..0f7f7e2b176 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -157,7 +157,7 @@ class stock_quant(osv.osv):
'reservation_id': fields.many2one('stock.move', 'Reserved for Move', help="Is this quant reserved for a stock.move?"),
'lot_id': fields.many2one('stock.production.lot', 'Lot'),
'cost': fields.float('Unit Cost'),
- 'partner_id': fields.related('lot_id', 'partner_id', type='many2one', relation="res.partner", string="Owner", store=True), # TODO implement store={}
+ 'owner_id': fields.many2one('res.partner', 'Owner', help="This is the owner of the quant"),
'create_date': fields.datetime('Creation Date'),
'in_date': fields.datetime('Incoming Date'),
@@ -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
@@ -653,9 +653,11 @@ class stock_picking(osv.osv):
'product_qty': qty,
'quant_id': quant.id,
'product_id': quant.product_id.id,
- 'lot_id': quant.lot_id.id,
+ 'lot_id': quant.lot_id and quant.lot_id.id or False,
'product_uom_id': quant.product_id.uom_id.id,
+ 'owner_id': quant.owner_id and quant.owner_id.id or False,
'cost': quant.cost,
+ 'package_id': quant.package_id and quant.package_id.id or False,
}, context=context)
if remaining_qty > 0:
pack_operation_obj.create(cr, uid, {
@@ -725,6 +727,10 @@ class stock_picking(osv.osv):
for move in picking.move_lines:
quant_obj.quants_unreserve(cr, uid, move, context=context)
res2[move.id] = move.product_qty
+ # Resort pack_operation_ids
+
+
+ #
for ops in picking.pack_operation_ids:
#Find moves that correspond
if ops.product_id:
@@ -750,7 +756,8 @@ class stock_picking(osv.osv):
'history_ids': [(4, move.id)],
'in_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'company_id': move.company_id.id,
- 'lot_id': ops.lot_id and ops.lot_id.id or False,
+ 'lot_id': ops.lot_id and ops.lot_id.id or False,
+ 'owner_id': ops.owner_id and ops.owner_id.id or False,
'reservation_id': move.id, #Reserve at once
'package_id': ops.result_package_id and ops.result_package_id.id or False,
}
@@ -929,7 +936,7 @@ class stock_production_lot(osv.osv):
'product_id': fields.many2one('product.product', 'Product', required=True, domain=[('type', '<>', 'service')]),
'quant_ids': fields.one2many('stock.quant', 'lot_id', 'Quants'),
'create_date': fields.datetime('Creation Date'),
- 'partner_id': fields.many2one('res.partner', 'Owner'),
+# 'partner_id': fields.many2one('res.partner', 'Owner'),
}
_defaults = {
'name': lambda x, y, z, c: x.pool.get('ir.sequence').get(y, z, 'stock.lot.serial'),
@@ -942,8 +949,8 @@ class stock_production_lot(osv.osv):
res = []
for lot in self.browse(cr, uid, ids, context=context):
name = lot.name
- if lot.partner_id:
- name += ' (' + lot.partner_id.name + ')'
+# if lot.partner_id:
+# name += ' (' + lot.partner_id.name + ')'
res.append((lot.id, name))
return res
@@ -1130,7 +1137,10 @@ class stock_move(osv.osv):
'origin_returned_move_id': fields.many2one('stock.move', 'Origin return move', help='move that created the return move'),
'returned_move_ids': fields.one2many('stock.move', 'origin_returned_move_id', 'All returned moves', help='Optional: all returned moves created from this move'),
'availability': fields.function(_get_product_availability, type='float', string='Availability'),
- }
+ }
+
+
+
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
@@ -1442,6 +1452,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,11 +1627,11 @@ class stock_move(osv.osv):
self.action_done(cr, uid, res, context=context)
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
"""
if move.product_qty==qty:
return move.id
@@ -1648,6 +1660,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(cr, uid, move.move_dest_id, qty, context=context)
return new_move
class stock_inventory(osv.osv):
@@ -1925,7 +1940,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"
@@ -2072,6 +2087,7 @@ class stock_pack_operation(osv.osv):
'lot_id': fields.many2one('stock.production.lot', 'Lot/Serial Number'),
'result_package_id': fields.many2one('stock.quant.package', 'Container Package', help="If set, the operations are packed into this package", required=False, ondelete='cascade'),
'date': fields.datetime('Date', required=True),
+ 'owner_id': fields.many2one('res.partner', 'Owner', help="Owner of the quants"),
#'update_cost': fields.boolean('Need cost update'),
'cost': fields.float("Cost", help="Unit Cost for this product line"),
'currency': fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed", ondelete='CASCADE'),
@@ -2088,9 +2104,16 @@ class stock_pack_operation(osv.osv):
res += "package_id <> " + str(ops.package_id.id)
if ops.lot_id:
if res:
- res += ", lot_id <> " + str(ops.lot_id.id)
- else:
- res += "lot_id <> " + str(ops.lot_id.id)
+ res += ", "
+ res += "lot_id <> " + str(ops.lot_id.id)
+ if ops.owner_id:
+ if res:
+ res += ", "
+ res += "owner_id <> " + str(ops.owner_id.id)
+ else:
+ if res:
+ res += ", "
+ res += "owner_id IS NOT NULL"
return res
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index 30038952ce7..866d0ef64d2 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -614,11 +614,12 @@
-
-
-
+
+
+
+
-
+
@@ -1544,6 +1545,7 @@
+
diff --git a/addons/stock/test/packing.yml b/addons/stock/test/packing.yml
index 64f772268f4..234b00e78e9 100644
--- a/addons/stock/test/packing.yml
+++ b/addons/stock/test/packing.yml
@@ -1,68 +1,171 @@
--
+-
Create a new stockable product
-
- !record {model: product.product, id: packingtest}:
- name: nice product
+ !record {model: product.product, id: product1}:
+ name: Nice product
+ 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 an incoming picking for this product of 300 PCE from suppliers to stock
-
- !record{model: stock.picking}: |
+ !record {model: stock.picking, id: pick1}:
+ name: Incoming picking
+ partner_id: base.res_partner_2
+ picking_type_id: picking_type_in
+ move_lines:
+ - product_id: product1
+ product_uom_qty: 300.00
+ location_id: stock_location_suppliers
+ location_dest_id: stock_location_stock
-
Confirm and assign picking and prepare partial
-
- !python {model: stock.picking, id:}: |
- self.action_confirm(cr, uid, ref())
+ !python {model: stock.picking}: |
+ self.action_confirm(cr, uid, [ref('pick1')], context=context)
+ self.do_prepare_partial(cr, uid, [ref('pick1')], context=context)
-
Put 120 pieces on Pallet 1 (package), 120 pieces on Pallet 2 with lot A and 60 pieces on Pallet 3
-
- !python {model: stock.picking, id:} |
+ !python {model: stock.picking}: |
#Change quantity of first to 120 and create 2 others quant operations
+ record = self.browse(cr, uid, ref('pick1'), context=context)
+ stock_pack = self.pool.get('stock.pack.operation')
+ stock_quant_pack = self.pool.get('stock.quant.package')
+ #create lot A
+ lot_a = self.pool.get('stock.production.lot').create(cr, uid, {'name': 'Lot A', 'product_id': ref('product1')}, context=context)
+ #create package
+ package1 = stock_quant_pack.create(cr, uid, {'name': 'Pallet 1'}, context=context)
+ package2 = stock_quant_pack.create(cr, uid, {'name': 'Pallet 2'}, context=context)
+ package3 = stock_quant_pack.create(cr, uid, {'name': 'Pallet 3'}, context=context)
#Create package for each line and assign it as result_package_id
+ #create pack operation
+ stock_pack.write(cr, uid, record.pack_operation_ids[0].id, {'package_id': package1, 'result_package_id': package1, 'product_qty': 120})
+ new_pack1 = stock_pack.create(cr, uid, {'product_id': ref('product1'), 'product_uom_id': ref('product.product_uom_unit'), 'picking_id': ref('pick1'), 'lot_id': lot_a, 'package_id': package2, 'result_package_id': package2, 'product_qty': 120}, context=context)
+ new_pack2 = stock_pack.create(cr, uid, {'product_id': ref('product1'), 'product_uom_id': ref('product.product_uom_unit'), 'picking_id': ref('pick1'), 'package_id': package3, 'result_package_id': package3, 'product_qty': 60}, context=context)
-
- Use button rereserve and check the qtyremaining on the moves are correct (=0)
+ Use button rereserve and check the qtyremaining on the moves are correct (=original quantities)
-
-
+ !python {model: stock.picking}: |
+ self.rereserve(cr, uid, [ref('pick1')], context=context)
+ picking = self.browse(cr, uid, ref('pick1'), context=context)
+ move_reco = picking.move_lines[0]
+ assert move_reco.remaining_qty == 300.0, "Remaining quantities should not change upon receiving"
-
Transfer the reception
-
-
+ !python {model: stock.picking}: |
+ self.do_partial(cr, uid, [ref('pick1')], context=context)
-
Check the system created 3 quants one with 120 pieces on pallet 1, one with 120 pieces on pallet 2 with lot A and 60 pieces on pallet 3
-
-
+ !python {model: stock.quant}: |
+ reco_id = self.search(cr ,uid , [('product_id','=',ref('product1'))], context=context)
+ assert len(reco_id) == 3, "The number of quants created is not correct"
+ for rec in self.browse(cr, uid, reco_id, context=context):
+ if rec.package_id.name == 'Pallet 1':
+ assert rec.qty == 120, "Should have 120 pîeces on pallet 1"
+ elif rec.package_id.name == 'Pallet 2':
+ assert rec.qty == 120, "Should have 120 pieces on pallet 2"
+ elif rec.package_id.name == 'Pallet 3':
+ assert rec.qty == 60, "Should have 60 pieces on pallet 3"
-
Check there is no backorder or extra moves created
-
-
+ !python {model: stock.picking}: |
+ picking = self.browse(cr, uid, ref('pick1'), context=context)
+ backorder = self.search(cr, uid, [('backorder_id', '=', ref('pick1'))])
+ assert not backorder, ""
+ #Check extra moves created
+ assert len(picking.move_lines) == 1, ""
-
Make a delivery order of 300 pieces to the customer
-
-
+ !record {model: stock.picking, id: delivery_order1}:
+ name: outgoing picking
+ partner_id: base.res_partner_4
+ picking_type_id: stock.picking_type_out
+ move_lines:
+ - product_id: product1
+ product_uom_qty: 300.00
+ location_id: stock_location_stock
+ location_dest_id: stock_location_customers
-
Assign and confirm
-
-
+ !python {model: stock.picking}: |
+ self.action_confirm(cr, uid, [ref('delivery_order1')], context=context)
+ self.action_assign(cr, uid, [ref('delivery_order1')])
+ self.force_assign(cr, uid, [ref('delivery_order1')], context=context)
-
Instead of doing the 300 pieces, you decide to take pallet 1 (do not mention product in operation here) and 20 pieces from lot A and 10 pieces from pallet 3
-
-
+ !python {model: stock.picking}: |
+ stock_pack = self.pool.get('stock.pack.operation')
+ self.do_prepare_partial(cr, uid, [ref('delivery_order1')], context=context)
+ delivery_id = self.browse(cr, uid, ref('delivery_order1'), context=context)
+ for rec in delivery_id.pack_operation_ids:
+ if rec.package_id.name == 'Pallet 1' or rec.product_qty == 120:
+ stock_pack.write(cr, uid, rec.id, {'product_qty': 120}, context=context)
+ if rec.package_id.name == 'Pallet 2' or rec.lot_id.name == 'Lot A' :
+ stock_pack.write(cr, uid, rec.id, {'product_qty': 20}, context=context)
+ if rec.package_id.name == 'Pallet 3' or rec.product_qty == 60:
+ stock_pack.write(cr, uid, rec.id, {'product_qty': 10}, context=context)
-
Process this picking
-
-
+ !python {model: stock.picking}: |
+ self.rereserve(cr, uid, [ref('delivery_order1')], context=context)
+ self.do_partial(cr, uid, [ref('delivery_order1')], context=context)
-
Check the quants that you have 120 pieces pallet 1 in customers, 100 pieces pallet 2 in stock and 20 with customers and 50 in stock, 10 in customers from pallet 3
-
-
+ !python {model: stock.quant}: |
+ reco_id = self.search(cr ,uid , [('product_id','=',ref('product1'))], context=context)
+ for rec in self.browse(cr, uid, reco_id, context=context):
+ if rec.package_id.name == 'Pallet 1' and rec.location_id.id == ref('stock_location_customers'):
+ assert rec.qty == 120, "Should have 120 pieces on pallet 1"
+ if rec.package_id.name == 'Pallet 2' and rec.location_id.id == ref('stock_location_stock'):
+ assert rec.qty == 20, "Should have 20 pieces in stock on pallet 2"
+ if rec.package_id.name == 'Pallet 3' and rec.location_id.id == ref('stock_location_stock'):
+ assert rec.qty == 10, "Should have 10 pieces in stock on pallet 3"
-
Check a backorder was created and on that backorder, prepare partial and add an op with 20 pieces (20 that cannot be assigned) with lot B
-
-
+ !python {model: stock.picking}: |
+ picking = self.browse(cr, uid, ref('delivery_order1'), context=context)
+ backorder = self.search(cr, uid, [('backorder_id.id', '=', picking.id)], context=context)
+ assert backorder, "Backorder should have been created"
+ backorder_id = self.browse(cr, uid, backorder, context=context)
+ self.action_confirm(cr, uid, backorder, context=context)
+ self.action_assign(cr, uid, backorder)
+ self.force_assign(cr, uid, backorder, context=context)
+ self.do_prepare_partial(cr, uid, backorder, context=context)
+ #create lot B
+ lot_b = self.pool.get('stock.production.lot').create(cr, uid, {'name': 'Lot B', 'product_id': ref('product1')}, context=context)
+ stock_pack = self.pool.get('stock.pack.operation').create(cr, uid, {'picking_id': backorder_id[0].id, 'lot_id': lot_b, 'product_qty': 20})
-
Process this backorder
-
-
+ !python {model: stock.picking}: |
+ picking = self.browse(cr, uid, ref('delivery_order1'), context=context)
+ backorder = self.search(cr, uid, [('backorder_id.id', '=', picking.id)], context=context)
+ backorder_id = self.browse(cr, uid, backorder, context=context)
+ self.rereserve(cr, uid, [backorder_id[0].id], context=context)
+ self.do_partial(cr, uid, [backorder_id[0].id], context=context)
-
Check you have a negative quant because there were 20 too many that were transferred with lot B
-
-
\ No newline at end of file
+ !python {model: stock.quant}: |
+ reco_id = self.search(cr ,uid , [('product_id','=',ref('product1'))], context=context)
+ for rec in self.browse(cr, uid, reco_id, context=context):
+ if rec.lot_id.name == 'Lot B':
+ assert rec.qty != -20, ""
diff --git a/addons/stock/test/procrule.yml b/addons/stock/test/procrule.yml
index d1762ae4806..61d1c920bab 100644
--- a/addons/stock/test/procrule.yml
+++ b/addons/stock/test/procrule.yml
@@ -1,22 +1,35 @@
-
Create new global procurement rule from Stock -> Output
-
- !record {model: procurement.rule, ref:}
- location_id: stock
- location_dest_id: output
+ !record {model: procurement.rule, id: global_proc_rule}:
+ name: Stock -> output
+ action: move
+ picking_type_id: stock.picking_type_out
+ location_src_id: stock.stock_location_stock
+ location_id: stock.stock_location_output
-
Create Delivery Order from Output -> Customer
-
- !record {model: stock.picking, ref:}
+ !record {model: stock.picking, id: pick_output}:
+ name: Delivery order for procurement
+ partner_id: base.res_partner_2
+ picking_type_id: stock.picking_type_out
+ move_lines:
+ - product_id: product.product_product_3
+ product_uom_qty: 10.00
+ location_id: stock.stock_location_output
+ location_dest_id: stock.stock_location_customers
+ procure_method: make_to_order
-
- Confirm delivery order
+ Confirm delivery order.
-
-
+ !python {model: stock.picking}: |
+ self.action_confirm(cr, uid, [ref('pick_output')])
-
- Check procurement was created in output (as there is the global procurement rule) related to this delivery order
+ Check a picking was created from stock to output.
-
-
--
- Check a picking was created from stock to output
--
-
+ !python {model: stock.move }: |
+ picking = self.pool.get("stock.picking").browse(cr, uid, ref("pick_output"))
+ move_id = self.search(cr, uid, [('product_id', '=', ref('product.product_product_3')),('location_id', '=', ref('stock.stock_location_stock')),
+ ('location_dest_id', '=', ref('stock.stock_location_output'), ('move_dest_id', '=', picking.move_lines[0].id))])
+ assert len(move_id) == 1, "It should have created a picking from Stock to Output with the original picking as destination"
\ No newline at end of file
diff --git a/addons/stock/test/shipment.yml b/addons/stock/test/shipment.yml
index 70f9b14c57a..aa12770e867 100644
--- a/addons/stock/test/shipment.yml
+++ b/addons/stock/test/shipment.yml
@@ -1,7 +1,8 @@
-
I confirm outgoing shipment of 130 kgm Ice-cream.
-
- !workflow {model: stock.picking, action: button_confirm, ref: outgoing_shipment}
+ !python {model: stock.picking}: |
+ self.action_confirm(cr, uid, [ref("outgoing_shipment")])
-
I check shipment details after confirmed.
-
@@ -10,99 +11,72 @@
assert shipment.state == "confirmed", "Shipment should be confirmed."
for move_line in shipment.move_lines:
assert move_line.state == "confirmed", "Move should be confirmed."
-
-
- Now I check vitual stock of Ice-cream after confirmed outgoing shipment.
+ Now I check virtual stock of Ice-cream after confirmed outgoing shipment.
-
!python {model: product.product}: |
product = self.browse(cr, uid, ref('product_icecream'), context=context)
product.virtual_available == -30, "Vitual stock is not updated."
-
-
I confirm incomming shipment of 50 kgm Ice-cream.
-
- !workflow {model: stock.picking, action: button_confirm, ref: incomming_shipment}
+ !python {model: stock.picking}: |
+ self.action_confirm(cr, uid, [ref("incomming_shipment")])
-
- I receive 40kgm Ice-cream so I make backorder of incomming shipment for 40 kgm.
+ I receive 40kgm Ice-cream so It will make backorder of incomming shipment for 10 kgm.
-
- !python {model: stock.partial.picking}: |
+ !python {model: stock.picking}: |
+ pick = self.browse(cr, uid, ref("incomming_shipment"), context=context)
+ self.pool.get('stock.pack.operation').create(cr, uid, {
+ 'picking_id': pick.id,
+ 'product_id': ref('product_icecream'),
+ 'product_uom_id': ref('product.product_uom_kgm'),
+ 'product_qty': 40
+ })
context.update({'active_model': 'stock.picking', 'active_id': ref('incomming_shipment'), 'active_ids': [ref('incomming_shipment')]})
+ pick.do_partial(context=context)
-
- !record {model: stock.partial.picking, id: partial_incomming}:
- move_ids:
- - quantity: 40
- product_id: product_icecream
- product_uom: product.product_uom_kgm
- move_id: incomming_shipment_icecream
- location_id: location_convenience_shop
- location_dest_id: location_refrigerator
--
- !python {model: stock.partial.picking }: |
- self.do_partial(cr, uid, [ref('partial_incomming')], context=context)
--
- I check backorder shipment after received partial shipment.
+ I check backorder shipment after received partial shipment and check remaining shipment.
-
!python {model: stock.picking}: |
shipment = self.browse(cr, uid, ref("incomming_shipment"))
- backorder = shipment.backorder_id
- assert backorder, "Backorder should be created after partial shipment."
- assert backorder.state == 'done', "Backorder should be close after received."
+ for move_line in shipment.move_lines:
+ assert move_line.product_qty == 40, "Qty in shipment does not correspond."
+ assert move_line.state == 'done', "Move line of shipment should be closed."
+ backorder_id = self.search(cr, uid, [('backorder_id', '=', ref("incomming_shipment"))],context=context)
+ backorder = self.browse(cr, uid, backorder_id)[0]
for move_line in backorder.move_lines:
- assert move_line.product_qty == 40, "Qty in backorder does not correspond."
- assert move_line.state == 'done', "Move line of backorder should be closed."
+ assert move_line.product_qty == 10, "Qty in backorder does not correspond."
+ assert move_line.state == 'draft', "Move line of backorder should be draft."
+ context.update({'active_model': 'stock.picking', 'active_id': backorder_id[0], 'active_ids': backorder_id})
+ self.action_confirm(cr, uid, backorder_id, context=context)
+ self.do_partial(cr, uid, backorder_id, context=context)
-
I receive another 10kgm Ice-cream.
-
- !record {model: stock.partial.picking, id: partial_incomming}:
- move_ids:
- - quantity: 10
- product_id: product_icecream
- product_uom: product.product_uom_kgm
- move_id: incomming_shipment_icecream
- location_id: location_convenience_shop
- location_dest_id: location_refrigerator
--
- !python {model: stock.partial.picking }: |
- self.do_partial(cr, uid, [ref('partial_incomming')], context=context)
-
+ !python {model: stock.picking}: |
+ pick = self.browse(cr, uid, ref("incomming_shipment"))
+ self.pool.get('stock.pack.operation').create(cr, uid, {
+ 'picking_id': pick.id,
+ 'product_id': ref('product_icecream'),
+ 'product_uom_id': ref('product.product_uom_kgm'),
+ 'product_qty': 10
+ })
+ context.update({'active_model': 'stock.picking', 'active_id': ref('incomming_shipment'), 'active_ids': [ref('incomming_shipment')]})
+ pick.do_partial(context=context)
-
I check incomming shipment after received.
-
!python {model: stock.picking}: |
- shipment = self.browse(cr, uid, ref("incomming_shipment"))
+ shipment = self.browse(cr, uid, self.search(cr, uid, [('backorder_id', '=', ref("incomming_shipment"))]))[0]
assert shipment.state == 'done', "shipment should be close after received."
for move_line in shipment.move_lines:
assert move_line.product_qty == 10, "Qty does not correspond."
assert move_line.product_id.virtual_available == 20, "Virtual stock does not correspond."
assert move_line.state == 'done', "Move line should be closed."
-
-
- I return last incomming shipment for 10 kgm Ice-cream.
--
- !record {model: stock.return.picking, id: return_incomming}:
- invoice_state: none
+ Return picking
-
!python {model: stock.return.picking }: |
- # this work without giving the id of the picking to return, magically, thanks to the context
- self.create_returns(cr, uid, [ref('return_incomming')], context=context)
--
- I cancel incomming shipment after return it.
--
- !python {model: stock.picking}: |
- # the cancel is not on the return, but on the incomming shipment (which now has a quantity of 10, thanks to the
- # backorder). This situation is a little weird as we returned a move that we finally cancelled... As result, only
- # 30Kg from the original 50Kg will be counted in the stock (50 - 10 (cancelled quantity) - 10 (returned quantity))
- self.action_cancel(cr, uid, [ref("incomming_shipment")], context=context)
--
- I make invoice of backorder of incomming shipment.
--
- !python {model: stock.invoice.onshipping}: |
- shipment = self.pool.get('stock.picking').browse(cr, uid, ref("incomming_shipment"))
- context.update({'active_model': 'stock.picking', 'active_id': shipment.backorder_id.id, 'active_ids': [shipment.backorder_id.id]})
--
- I check available stock after received incomming shipping. (removed invoicing here)
--
- !python {model: product.product}: |
- product = self.browse(cr, uid, ref('product_icecream'), context=context)
- assert product.qty_available == 140, "Stock does not correspond."
- assert product.virtual_available == 0, "Vitual stock does not correspond."
\ No newline at end of file
+ # TODO: Should still work out according to the previous steps of shipment.yml
+ pass
diff --git a/addons/stock_account/stock.py b/addons/stock_account/stock.py
index e404ab3dd7b..ff48e865737 100644
--- a/addons/stock_account/stock.py
+++ b/addons/stock_account/stock.py
@@ -22,6 +22,66 @@
from openerp.osv import fields, osv
from openerp.tools.translate import _
+#----------------------------------------------------------
+# Procurement Rule
+#----------------------------------------------------------
+class procurement_rule(osv.osv):
+ _inherit = 'procurement.rule'
+ _columns= {
+ 'invoice_state': fields.selection([
+ ("invoiced", "Invoiced"),
+ ("2binvoiced", "To Be Invoiced"),
+ ("none", "Not Applicable")], "Invoice Status",
+ required=False),
+ }
+
+#----------------------------------------------------------
+# Procurement Order
+#----------------------------------------------------------
+
+
+class procurement_order(osv.osv):
+ _inherit = "procurement.order"
+ _columns = {
+ 'invoice_state': fields.selection(
+ [("invoiced", "Invoiced"),
+ ("2binvoiced", "To Be Invoiced"),
+ ("none", "Not Applicable")
+ ], "Invoice Control", required=True),
+ }
+
+ def _run_move_create(self, cr, uid, procurement, context=None):
+ res = super(procurement_order, self)._run_move_create(cr, uid, procurement, context=context)
+ res.update({'invoice_state': (procurement.rule_id.invoice_state in ('none', False) and procurement.invoice_state or procurement.rule_id.invoice_state) or 'none'})
+ return res
+
+ _defaults = {
+ 'invoice_state': 'none'
+ }
+
+
+#----------------------------------------------------------
+# Move
+#----------------------------------------------------------
+
+class stock_move(osv.osv):
+ _inherit = "stock.move"
+ _columns = {
+ 'invoice_state': fields.selection([("invoiced", "Invoiced"),
+ ("2binvoiced", "To Be Invoiced"),
+ ("none", "Not Applicable")], "Invoice Control",
+ select=True, required=True, track_visibility='onchange',
+ states={'draft': [('readonly', False)]}),
+ }
+ _defaults= {
+ 'invoice_state': lambda *args, **argv: 'none'
+ }
+
+
+
+#----------------------------------------------------------
+# Picking
+#----------------------------------------------------------
class stock_picking(osv.osv):
_inherit = 'stock.picking'
@@ -30,22 +90,13 @@ class stock_picking(osv.osv):
for pick in self.browse(cr, uid, ids, context=context):
result[pick.id] = 'none'
for move in pick.move_lines:
- if move.procurement_id:
- if move.procurement_id.invoice_state=='invoiced':
- result[pick.id] = 'invoiced'
- elif move.procurement_id.invoice_state=='2binvoiced':
- result[pick.id] = '2binvoiced'
- break
+ if move.invoice_state=='invoiced':
+ result[pick.id] = 'invoiced'
+ elif move.invoice_state=='2binvoiced':
+ result[pick.id] = '2binvoiced'
+ break
return result
- def __get_picking_procurement(self, cr, uid, ids, context={}):
- result = {}
- for proc in self.pool.get('procurement.order').browse(cr, uid, ids, context=context):
- for move in proc.move_ids:
- if move.picking_id:
- result[move.picking_id.id] = True
- return result.keys()
-
def __get_picking_move(self, cr, uid, ids, context={}):
res = []
for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context):
@@ -59,8 +110,8 @@ class stock_picking(osv.osv):
("2binvoiced", "To Be Invoiced"),
("none", "Not Applicable")
], string="Invoice Control", required=True,
+
store={
- 'procurement.order': (__get_picking_procurement, ['invoice_state'], 10),
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['state'], 10),
'stock.move': (__get_picking_move, ['picking_id'], 10),
},
diff --git a/addons/stock_account/stock_account.py b/addons/stock_account/stock_account.py
index f9e62fa80e2..659f53adf91 100644
--- a/addons/stock_account/stock_account.py
+++ b/addons/stock_account/stock_account.py
@@ -34,11 +34,6 @@ import openerp.addons.decimal_precision as dp
import logging
_logger = logging.getLogger(__name__)
-#----------------------------------------------------------
-# Invoice state
-#----------------------------------------------------------
-
-
#----------------------------------------------------------
diff --git a/addons/stock_account/stock_account_view.xml b/addons/stock_account/stock_account_view.xml
index a7e6bc8afe9..c6f9a581858 100644
--- a/addons/stock_account/stock_account_view.xml
+++ b/addons/stock_account/stock_account_view.xml
@@ -29,8 +29,18 @@
-
+
+
+ stock.move.form.inherit
+ stock.move
+
+
+
+
+
+
+
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 77d1a67149a..fc36d48d7f9 100644
--- a/addons/stock_location/stock_location.py
+++ b/addons/stock_location/stock_location.py
@@ -133,11 +133,7 @@ class procurement_rule(osv.osv):
'delay': fields.integer('Number of Hours'),
'procure_method': fields.selection([('make_to_stock','Make to Stock'),('make_to_order','Make to Order')], 'Procure Method', required=True, help="'Make to Stock': When needed, take from the stock or wait until re-supplying. 'Make to Order': When needed, purchase or produce for the procurement request."),
'partner_address_id': fields.many2one('res.partner', 'Partner Address'),
- 'invoice_state': fields.selection([
- ("invoiced", "Invoiced"),
- ("2binvoiced", "To Be Invoiced"),
- ("none", "Not Applicable")], "Invoice Status",
- required=True,),
+
'route_sequence': fields.related('route_id', 'sequence', string='Route Sequence', store={'stock.location.route': (_get_rules, ['sequence'], 10)}),
'sequence': fields.integer('Sequence'),
'propagate': fields.boolean('Propagate cancel and split', help='If checked, when the previous move of the move (which was generated by a next procurement) is cancelled or split, the move generated by this move will too'),
@@ -155,7 +151,7 @@ class procurement_rule(osv.osv):
class procurement_order(osv.osv):
_inherit = 'procurement.order'
_columns = {
- 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Destination route', help="Preferred route to be followed by the procurement order"),
+ 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Followed Route', help="Preferred route to be followed by the procurement order"),
}
def _run_move_create(self, cr, uid, procurement, context=None):