diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index d11fa30726c..3c8aa29be28 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -1925,7 +1925,7 @@ - + diff --git a/addons/account_analytic_default/account_analytic_default.py b/addons/account_analytic_default/account_analytic_default.py index e0e8f7292ef..f24ba556f91 100644 --- a/addons/account_analytic_default/account_analytic_default.py +++ b/addons/account_analytic_default/account_analytic_default.py @@ -130,4 +130,27 @@ class product_product(osv.Model): 'rules_count': fields.function(_rules_count, string='# Analytic Rules', type='integer'), } +class product_template(osv.Model): + _inherit = 'product.template' + + def _rules_count(self, cr, uid, ids, field_name, arg, context=None): + Analytic = self.pool['account.analytic.default'] + res = {} + for product_tmpl_id in self.browse(cr, uid, ids, context=context): + res[product_tmpl_id.id] = sum([p.rules_count for p in product_tmpl_id.product_variant_ids]) + return res + + _columns = { + 'rules_count': fields.function(_rules_count, string='# Analytic Rules', type='integer'), + } + + + def action_view_rules(self, cr, uid, ids, context=None): + products = self._get_products(cr, uid, ids, context=context) + result = self._get_act_window_dict(cr, uid, 'account_analytic_default.action_product_default_list', context=context) + result['domain'] = "[('product_id','in',[" + ','.join(map(str, products)) + "])]" + # Remove context so it is not going to filter on product_id with active_id of template + result['context'] = "{}" + return result + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_analytic_default/account_analytic_default_view.xml b/addons/account_analytic_default/account_analytic_default_view.xml index b4f8c646f90..8299cbca860 100644 --- a/addons/account_analytic_default/account_analytic_default_view.xml +++ b/addons/account_analytic_default/account_analytic_default_view.xml @@ -87,6 +87,20 @@ + + + product.template.stock.move + product.template + + + + + + + OpenERP" + 'openerp': "Odoo" }) footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 453bfe5c458..e2e94233861 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -1049,6 +1049,22 @@ class mrp_production(osv.osv): return "make_to_order" return "make_to_stock" + def _create_previous_move(self, cr, uid, move_id, product, source_location_id, dest_location_id, context=None): + ''' + When the routing gives a different location than the raw material location of the production order, + we should create an extra move from the raw material location to the location of the routing, which + precedes the consumption line (chained) + ''' + stock_move = self.pool.get('stock.move') + move = stock_move.copy(cr, uid, move_id, default = { + 'location_id': source_location_id, + 'location_dest_id': dest_location_id, + 'procure_method': self._get_raw_material_procure_method(cr, uid, product, context=context), + 'raw_material_production_id': False, + 'move_dest_id': move_id, + }, context=context) + return move + def _make_consume_line_from_data(self, cr, uid, production, product, uom_id, qty, uos_id, uos_qty, context=None): stock_move = self.pool.get('stock.move') # Internal shipment is created for Stockable and Consumer Products @@ -1056,12 +1072,13 @@ class mrp_production(osv.osv): return False # Take routing location as a Source Location. source_location_id = production.location_src_id.id - if production.routing_id and production.routing_id.location_id: - source_location_id = production.routing_id.location_id.id - + prod_location_id = source_location_id + prev_move= False + if production.bom_id.routing_id and production.bom_id.routing_id.location_id and production.bom_id.routing_id.location_id.id != source_location_id: + source_location_id = production.bom_id.routing_id.location_id.id + prev_move = True + destination_location_id = production.product_id.property_stock_production.id - if not source_location_id: - source_location_id = production.location_src_id.id move_id = stock_move.create(cr, uid, { 'name': production.name, 'date': production.date_planned, @@ -1073,12 +1090,15 @@ class mrp_production(osv.osv): 'location_id': source_location_id, 'location_dest_id': destination_location_id, 'company_id': production.company_id.id, - 'procure_method': self._get_raw_material_procure_method(cr, uid, product, context=context), + 'procure_method': prev_move and 'make_to_stock' or self._get_raw_material_procure_method(cr, uid, product, context=context), #Make_to_stock avoids creating procurement 'raw_material_production_id': production.id, #this saves us a browse in create() 'price_unit': product.standard_price, 'origin': production.name, - }) + }, context=context) + + if prev_move: + prev_move = self._create_previous_move(cr, uid, move_id, product, prod_location_id, source_location_id, context=context) return move_id def _make_production_consume_line(self, cr, uid, line, context=None): diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml index 0d0c1b3c4f9..17cba90224a 100644 --- a/addons/mrp/mrp_view.xml +++ b/addons/mrp/mrp_view.xml @@ -547,29 +547,21 @@ - - - product.product.form.view.inherited - product.product - - + + + product.form.mrp.inherited + product.template + + + + + - - - - - product.form.mrp.inherited - product.product - - - - - @@ -1052,6 +1044,7 @@ mrp.production + product.template.procurement product.template @@ -1065,6 +1058,7 @@ + product.product.procurement product.product @@ -1075,6 +1069,24 @@ groups="mrp.group_mrp_user" attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-flask"> + + + + + + + product.product.mrp.button + product.product + + +
+ - @@ -634,5 +628,33 @@ + + + product.template.purchase.button.inherit + product.template + + + + + + + + + + product.product.purchase.button.inherit + product.product + + + + + + + diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py index c719e7b51ec..a966ac8308f 100644 --- a/addons/purchase/stock.py +++ b/addons/purchase/stock.py @@ -46,8 +46,8 @@ class stock_move(osv.osv): return res def copy(self, cr, uid, id, default=None, context=None): - if not default: - default = {} + default = default or {} + context = context or {} if not default.get('split_from'): #we don't want to propagate the link to the purchase order line except in case of move split default['purchase_line_id'] = False @@ -102,7 +102,7 @@ class stock_picking(osv.osv): _columns = { 'reception_to_invoice': fields.function(_get_to_invoice, type='boolean', string='Invoiceable on incoming shipment?', - help='Does the picking contains some moves related to a purchase order invoiceable on the reception?', + help='Does the picking contains some moves related to a purchase order invoiceable on the receipt?', store={ 'stock.move': (_get_picking_to_recompute, ['purchase_line_id', 'picking_id'], 10), }), diff --git a/addons/purchase/stock_view.xml b/addons/purchase/stock_view.xml index acdecd2d400..174dc99d4f5 100644 --- a/addons/purchase/stock_view.xml +++ b/addons/purchase/stock_view.xml @@ -72,10 +72,10 @@

Click to create a new incoming shipment.

- Here you can track all the product receptions of purchase + Here you can track all the product receipts of purchase orders where the invoicing is "Based on Incoming Shipments", and for which you have not received a supplier invoice yet. - You can generate a supplier invoice based on those receptions. + You can generate a supplier invoice based on those receipts.

diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 0cac2e8b511..b85716b1aff 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -718,7 +718,7 @@ class sale_order(osv.osv): procurement_obj.check(cr, uid, [x.id for x in line.procurement_ids if x.state not in ['cancel', 'done']]) line.refresh() #run again procurement that are in exception in order to trigger another move - proc_ids += [x.id for x in line.procurement_ids if x.state == 'exception'] + proc_ids += [x.id for x in line.procurement_ids if x.state in ('exception', 'cancel')] elif sale_line_obj.need_procurement(cr, uid, [line.id], context=context): if (line.state == 'done') or not line.product_id: continue @@ -741,49 +741,7 @@ class sale_order(osv.osv): order.write(val) return True - # if mode == 'finished': - # returns True if all lines are done, False otherwise - # if mode == 'canceled': - # returns True if there is at least one canceled line, False otherwise - def test_state(self, cr, uid, ids, mode, *args): - assert mode in ('finished', 'canceled'), _("invalid mode for test_state") - finished = True - canceled = False - write_done_ids = [] - write_cancel_ids = [] - for order in self.browse(cr, uid, ids, context={}): - #TODO: Need to rethink what happens when cancelling - for line in order.order_line: - states = [x.state for x in line.procurement_ids] - cancel = states and all([x == 'cancel' for x in states]) - doneorcancel = all([x in ('done', 'cancel') for x in states]) - if cancel: - canceled = True - if line.state != 'exception': - write_cancel_ids.append(line.id) - if not doneorcancel: - finished = False - if doneorcancel and not cancel: - write_done_ids.append(line.id) - - if write_done_ids: - 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': - return canceled - - - def procurement_lines_get(self, cr, uid, ids, *args): - res = [] - for order in self.browse(cr, uid, ids, context={}): - for line in order.order_line: - res += [x.id for x in line.procurement_ids] - return res def onchange_fiscal_position(self, cr, uid, ids, fiscal_position, order_lines, context=None): '''Update taxes of order lines for each line where a product is defined @@ -828,6 +786,20 @@ class sale_order(osv.osv): order_line.append(line) return {'value': {'order_line': order_line}} + def test_procurements_done(self, cr, uid, ids, context=None): + for sale in self.browse(cr, uid, ids, context=context): + for line in sale.order_line: + if not all([x.state == 'done' for x in line.procurement_ids]): + return False + return True + + def test_procurements_except(self, cr, uid, ids, context=None): + for sale in self.browse(cr, uid, ids, context=context): + for line in sale.order_line: + if any([x.state == 'cancel' for x in line.procurement_ids]): + return True + return False + # TODO add a field price_unit_uos # - update it on change product and unit price @@ -924,6 +896,8 @@ class sale_order_line(osv.osv): 'delay': 0.0, } + + def _get_line_qty(self, cr, uid, line, context=None): if line.product_uos: return line.product_uos_qty or 0.0 @@ -1268,6 +1242,20 @@ class procurement_order(osv.osv): 'sale_line_id': fields.many2one('sale.order.line', string='Sale Order Line'), } + def write(self, cr, uid, ids, vals, context=None): + if isinstance(ids, (int, long)): + ids = [ids] + res = super(procurement_order, self).write(cr, uid, ids, vals, context=context) + from openerp import workflow + if vals.get('state') in ['done', 'cancel', 'exception']: + for proc in self.browse(cr, uid, ids, context=context): + if proc.sale_line_id and proc.sale_line_id.order_id and proc.move_ids: + order_id = proc.sale_line_id.order_id.id + if self.pool.get('sale.order').test_procurements_done(cr, uid, [order_id], context=context): + workflow.trg_validate(uid, 'sale.order', order_id, 'ship_end', cr) + if self.pool.get('sale.order').test_procurements_except(cr, uid, [order_id], context=context): + workflow.trg_validate(uid, 'sale.order', order_id, 'ship_except', cr) + return res class product_product(osv.Model): _inherit = 'product.product' @@ -1278,10 +1266,36 @@ class product_product(osv.Model): product_id: SaleOrderLine.search_count(cr,uid, [('product_id', '=', product_id)], context=context) for product_id in ids } + _columns = { 'sales_count': fields.function(_sales_count, string='# Sales', type='integer'), } +class product_template(osv.Model): + _inherit = 'product.template' + + def _sales_count(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) + for template in self.browse(cr, uid, ids, context=context): + res[template.id] = sum([p.sales_count for p in template.product_variant_ids]) + return res + + def action_view_sales(self, cr, uid, ids, context=None): + act_obj = self.pool.get('ir.actions.act_window') + mod_obj = self.pool.get('ir.model.data') + product_ids = [] + for template in self.browse(cr, uid, ids, context=context): + product_ids += [x.id for x in template.product_variant_ids] + result = mod_obj.xmlid_to_res_id(cr, uid, 'sale.action_order_line_product_tree',raise_if_not_found=True) + result = act_obj.read(cr, uid, [result], context=context)[0] + result['domain'] = "[('product_id','in',[" + ','.join(map(str, product_ids)) + "])]" + return result + + + _columns = { + 'sales_count': fields.function(_sales_count, string='# Sales', type='integer'), + + } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 13e5d952006..3946ff7b91f 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -508,6 +508,21 @@ + + product.template.sale.order.button + product.template + + + + + + + + + res.company.form.inherit diff --git a/addons/sale/sale_workflow.xml b/addons/sale/sale_workflow.xml index 831a0a9d12c..1dd093f4e1d 100644 --- a/addons/sale/sale_workflow.xml +++ b/addons/sale/sale_workflow.xml @@ -262,9 +262,7 @@ - procurement.order - procurement_lines_get() - test_state('finished') + ship_end diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index 20bac48c562..ffe96dd6cb3 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -350,15 +350,6 @@ class sale_order_line(osv.osv): class stock_move(osv.osv): _inherit = 'stock.move' - def action_cancel(self, cr, uid, ids, context=None): - sale_ids = [] - for move in self.browse(cr, uid, ids, context=context): - if move.procurement_id and move.procurement_id.sale_line_id: - sale_ids.append(move.procurement_id.sale_line_id.order_id.id) - if sale_ids: - self.pool.get('sale.order').signal_workflow(cr, uid, sale_ids, 'ship_except') - return super(stock_move, self).action_cancel(cr, uid, ids, context=context) - def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None): invoice_line_id = super(stock_move, self)._create_invoice_line_from_vals(cr, uid, move, invoice_line_vals, context=context) if move.procurement_id and move.procurement_id.sale_line_id: diff --git a/addons/stock/doc/stock.rst b/addons/stock/doc/stock.rst index 42b9c79b8a5..c43729889a9 100644 --- a/addons/stock/doc/stock.rst +++ b/addons/stock/doc/stock.rst @@ -27,7 +27,7 @@ To satisfy the need for a counterpart to each stock movement, the software suppo * Partner locations (suppliers and customers), * Virtual locations as counterparts for production, inventory and scrap. -Partner locations represent your customers' and suppliers' stocks. To reconcile them with your accounts, these stores play the role of third-party accounts. Reception from a supplier can be shown by the movement of goods from a partner location to a physical location in your own company. As you see, supplier locations usually show negative stocks and customer locations usually show positive stocks. +Partner locations represent your customers' and suppliers' stocks. To reconcile them with your accounts, these stores play the role of third-party accounts. Receipt from a supplier can be shown by the movement of goods from a partner location to a physical location in your own company. As you see, supplier locations usually show negative stocks and customer locations usually show positive stocks. Virtual locations as counterparts for production are used in manufacturing operations. Manufacturing is characterized by the consumption of raw materials and the production of finished products. Virtual locations are used for the counterparts of these two operations. diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index b8d7a03c9f2..2024b016ef3 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -222,27 +222,18 @@ class procurement_order(osv.osv): ''' if procurement.rule_id and procurement.rule_id.action == 'move': uom_obj = self.pool.get('product.uom') - done_test_list = [] - done_cancel_test_list = [] - qty_done = 0 - for move in procurement.move_ids: - done_test_list.append(move.state == 'done') - done_cancel_test_list.append(move.state in ('done', 'cancel')) - qty_done += move.product_qty if move.state == 'done' else 0 - qty_done = uom_obj._compute_qty(cr, uid, procurement.product_id.uom_id.id, qty_done, procurement.product_uom.id) - at_least_one_done = any(done_test_list) + cancel_test_list = [x.state == 'cancel' for x in procurement.move_ids] + done_cancel_test_list = [x.state in ('done', 'cancel') for x in procurement.move_ids] + at_least_one_cancel = any(cancel_test_list) all_done_or_cancel = all(done_cancel_test_list) + all_cancel = all(cancel_test_list) if not all_done_or_cancel: return False - elif all_done_or_cancel and procurement.product_qty == qty_done: + elif all_done_or_cancel and not all_cancel: return True - elif at_least_one_done: - #some move cancelled and some validated - self.message_post(cr, uid, [procurement.id], body=_('Some stock moves have been cancelled for this procurement. Run the procurement again to trigger a move for the remaining quantity or change the procurement quantity to finish it directly'), context=context) - else: - #all move are cancelled + elif all_cancel: self.message_post(cr, uid, [procurement.id], body=_('All stock moves have been cancelled for this procurement.'), context=context) - self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context) + self.write(cr, uid, [procurement.id], {'state': 'cancel'}, context=context) return False return super(procurement_order, self)._check(cr, uid, procurement, context) diff --git a/addons/stock/product.py b/addons/stock/product.py index 20470e45e9a..a0dbf68bb6f 100644 --- a/addons/stock/product.py +++ b/addons/stock/product.py @@ -175,7 +175,7 @@ class product_product(osv.osv): return res _columns = { - 'reception_count': fields.function(_stock_move_count, string="Reception", type='integer', multi='pickings'), + 'reception_count': fields.function(_stock_move_count, string="Receipt", type='integer', multi='pickings'), 'delivery_count': fields.function(_stock_move_count, string="Delivery", type='integer', multi='pickings'), 'qty_available_text': fields.function(_product_available_text, type='char'), 'qty_available': fields.function(_product_available, multi='qty_available', @@ -244,7 +244,7 @@ class product_product(osv.osv): if fields: if location_info.usage == 'supplier': if fields.get('virtual_available'): - res['fields']['virtual_available']['string'] = _('Future Receptions') + res['fields']['virtual_available']['string'] = _('Future Receipts') if fields.get('qty_available'): res['fields']['qty_available']['string'] = _('Received Qty') @@ -323,8 +323,18 @@ class product_template(osv.osv): res.append(('product_variant_ids', 'in', ids)) return res + + def _product_available_text(self, cr, uid, ids, field_names=None, arg=False, context=None): + res = {} + for product in self.browse(cr, uid, ids, context=context): + res[product.id] = str(product.qty_available) + _(" On Hand") + return res + + + _columns = { 'type': fields.selection([('product', 'Stockable Product'), ('consu', 'Consumable'), ('service', 'Service')], 'Product Type', required=True, help="Consumable: Will not imply stock management for this product. \nStockable product: Will imply stock management for this product."), + 'qty_available_text': fields.function(_product_available_text, type='char'), 'property_stock_procurement': fields.property( type='many2one', relation='stock.location', @@ -382,12 +392,48 @@ class product_template(osv.osv): product_route_ids |= set([r.id for r in product.route_ids]) product_route_ids |= set([r.id for r in product.categ_id.total_route_ids]) route_ids = route_obj.search(cr, uid, ['|', ('id', 'in', list(product_route_ids)), ('warehouse_selectable', '=', True)], context=context) - result = mod_obj.get_object_reference(cr, uid, 'stock', 'action_routes_form') - id = result and result[1] or False - result = act_obj.read(cr, uid, [id], context=context)[0] + result = mod_obj.xmlid_to_res_id(cr, uid, 'stock.action_routes_form', raise_if_not_found=True) + result = act_obj.read(cr, uid, [result], context=context)[0] result['domain'] = "[('id','in',[" + ','.join(map(str, route_ids)) + "])]" return result + + def _get_products(self, cr, uid, ids, context=None): + products = [] + for prodtmpl in self.browse(cr, uid, ids, context=None): + products += [x.id for x in prodtmpl.product_variant_ids] + return products + + def _get_act_window_dict(self, cr, uid, name, context=None): + mod_obj = self.pool.get('ir.model.data') + act_obj = self.pool.get('ir.actions.act_window') + result = mod_obj.xmlid_to_res_id(cr, uid, name, raise_if_not_found=True) + result = act_obj.read(cr, uid, [result], context=context)[0] + return result + + def action_open_quants(self, cr, uid, ids, context=None): + products = self._get_products(cr, uid, ids, context=context) + result = self._get_act_window_dict(cr, uid, 'stock.product_open_quants', context=context) + result['domain'] = "[('product_id','in',[" + ','.join(map(str, products)) + "])]" + result['context'] = "{'search_default_locationgroup': 1, 'search_default_internal_loc': 1}" + return result + + def action_view_orderpoints(self, cr, uid, ids, context=None): + products = self._get_products(cr, uid, ids, context=context) + result = self._get_act_window_dict(cr, uid, 'stock.product_open_orderpoint', context=context) + result['domain'] = "[('product_id','in',[" + ','.join(map(str, products)) + "])]" + result['context'] = "{}" + return result + + + def action_view_stock_moves(self, cr, uid, ids, context=None): + products = self._get_products(cr, uid, ids, context=context) + result = self._get_act_window_dict(cr, uid, 'stock.act_product_stock_move_open', context=context) + result['domain'] = "[('product_id','in',[" + ','.join(map(str, products)) + "])]" + result['context'] = "{}" + return result + + class product_removal_strategy(osv.osv): _name = 'product.removal' _description = 'Removal Strategy' diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml index c3941eb1887..df89820ff6d 100644 --- a/addons/stock/product_view.xml +++ b/addons/stock/product_view.xml @@ -16,21 +16,36 @@ + + product.template.stock.tree.inherit + product.template + + + + {'red':virtual_available<0, 'blue':virtual_available>=0 and state in ('draft', 'end', 'obsolete'), 'black':virtual_available>=0 and state not in ('draft', 'end', 'obsolete')} + + + + + + + + - Receptions + Receipts stock.move ir.actions.act_window form tree,form - +

- Click to register a reception for this product. + Click to register a receipt for this product.

- Here you will find the history of all receptions related to - this product, as well as all future receptions you are waiting + Here you will find the history of all receipts related to + this product, as well as all future receipts you are waiting from your suppliers.

@@ -42,7 +57,7 @@ ir.actions.act_window form tree,form - + @@ -111,6 +126,13 @@ + + + + + + + @@ -121,9 +143,6 @@ {'default_groups_ref': ['base.group_user', 'base.group_sale_manager', 'stock.group_stock_manager']} - - +
-
-
- - - product.normal.stock.acc.property.form.inherit - product.product - - 26 - @@ -73,6 +56,7 @@ + diff --git a/addons/stock_dropshipping/test/cancellation_propagated.yml b/addons/stock_dropshipping/test/cancellation_propagated.yml index 71f5e75385d..30a4ae338cc 100644 --- a/addons/stock_dropshipping/test/cancellation_propagated.yml +++ b/addons/stock_dropshipping/test/cancellation_propagated.yml @@ -1,5 +1,5 @@ - - I first create a warehouse with pick-pack-ship and reception in 2 steps + I first create a warehouse with pick-pack-ship and receipt in 2 steps - !record {model: stock.warehouse, id: wh_pps}: name: WareHouse PickPackShip diff --git a/addons/stock_dropshipping/test/lifo_price.yml b/addons/stock_dropshipping/test/lifo_price.yml index a9b641bab77..4d0634e0b7a 100644 --- a/addons/stock_dropshipping/test/lifo_price.yml +++ b/addons/stock_dropshipping/test/lifo_price.yml @@ -57,7 +57,7 @@ !assert {model: purchase.order, id: purchase_order_lifo1}: - state == 'approved' - - Process the reception of purchase order 1 + Process the receipt of purchase order 1 - !python {model: stock.picking}: | order = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_lifo1"), context=context).picking_ids[0] @@ -72,7 +72,7 @@ - !workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_lifo2} - - Process the reception of purchase order 2 + Process the receipt of purchase order 2 - !python {model: stock.picking}: | order = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_lifo2"), context=context).picking_ids[0] @@ -81,7 +81,7 @@ Check the standard price should not have changed - !python {model: product.product}: | - assert self.browse(cr, uid, ref("product_lifo_icecream")).standard_price == 70.0, 'Standard price as lifo price of second reception incorrect!' + assert self.browse(cr, uid, ref("product_lifo_icecream")).standard_price == 70.0, 'Standard price as lifo price of second receipt incorrect!' - Let us send some goods - diff --git a/addons/stock_dropshipping/test/stock_combi.yml b/addons/stock_dropshipping/test/stock_combi.yml index aa3a991838e..d4fb786e109 100644 --- a/addons/stock_dropshipping/test/stock_combi.yml +++ b/addons/stock_dropshipping/test/stock_combi.yml @@ -1,5 +1,5 @@ - - Create a warehouse and set it as having a 3-step delivery flow (Pick > Pack > Ship) and a 2-step reception route + Create a warehouse and set it as having a 3-step delivery flow (Pick > Pack > Ship) and a 2-step receipt route - - Create product Combi1 that is MTO / purchase and provide a supplier for it