diff --git a/addons/delivery/sale.py b/addons/delivery/sale.py index 4ef3224fc3e..a7e8b5d3716 100644 --- a/addons/delivery/sale.py +++ b/addons/delivery/sale.py @@ -53,10 +53,6 @@ class sale_order(osv.Model): result['value']['carrier_id'] = dtype return result - def _prepare_order_picking(self, cr, uid, order, context=None): - result = super(sale_order, self)._prepare_order_picking(cr, uid, order, context=context) - result.update(carrier_id=order.carrier_id.id) - return result def _delivery_unset(self, cr, uid, ids, context=None): sale_obj = self.pool['sale.order.line'] @@ -92,4 +88,4 @@ class sale_order(osv.Model): 'price_unit': grid_obj.get_price(cr, uid, grid.id, order, time.strftime('%Y-%m-%d'), context), 'tax_id': [(6, 0, taxes_ids)], 'is_delivery': True - }) + }) \ No newline at end of file diff --git a/addons/delivery/stock.py b/addons/delivery/stock.py index 7bfd52df420..c8781244fe0 100644 --- a/addons/delivery/stock.py +++ b/addons/delivery/stock.py @@ -120,9 +120,10 @@ class stock_picking(osv.osv): } def _create_invoice_from_picking(self, cr, uid, picking, vals, context=None): + invoice_obj = self.pool.get('account.invoice') invoice_line_obj = self.pool.get('account.invoice.line') invoice_id = super(stock_picking, self)._create_invoice_from_picking(cr, uid, picking, vals, context=context) - invoice = self.browse(cr, uid, invoice_id, context=context) + invoice = invoice_obj.browse(cr, uid, invoice_id, context=context) invoice_line = self._prepare_shipping_invoice_line(cr, uid, picking, invoice, context=context) if invoice_line: invoice_line_obj.create(cr, uid, invoice_line) @@ -170,6 +171,24 @@ class stock_move(osv.osv): 'weight_uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True,readonly="1",help="Unit of Measure (Unit of Measure) is the unit of measurement for Weight",), } + def action_confirm(self, cr, uid, ids, context=None): + """ + Pass the carrier to the picking from the sales order + (Should also work in case of Phantom BoMs when on explosion the original move is deleted) + """ + procs_to_check = [] + for move in self.browse(cr, uid, ids, context=context): + if move.procurement_id and move.procurement_id.sale_line_id and move.procurement_id.sale_line_id.order_id.carrier_id: + procs_to_check += [move.procurement_id] + res = super(stock_move, self).action_confirm(cr, uid, ids, context=context) + pick_obj = self.pool.get("stock.picking") + for proc in procs_to_check: + pickings = list(set([x.picking_id.id for x in proc.move_ids if x.picking_id and not x.picking_id.carrier_id])) + if pickings: + pick_obj.write(cr, uid, pickings, {'carrier_id': proc.sale_line_id.order_id.carrier_id.id}, context=context) + return res + + def _get_default_uom(self, cr, uid, context=None): uom_categ_id = self.pool.get('ir.model.data').xmlid_to_res_id(cr, uid, 'product.product_uom_categ_kgm') return self.pool.get('product.uom').search(cr, uid, [('category_id', '=', uom_categ_id),('factor','=',1)])[0] diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index b87061696e4..f08c16943b6 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -150,7 +150,20 @@ class purchase_order(osv.osv): 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') and obj_data.get_object_reference(cr, uid, 'stock','picking_type_in')[1] or False + type_obj = self.pool.get('stock.picking.type') + user_obj = self.pool.get('res.users') + company_id = user_obj.browse(cr, uid, uid, context=context).company_id.id + pick_type = obj_data.get_object_reference(cr, uid, 'stock', 'picking_type_in') and obj_data.get_object_reference(cr, uid, 'stock', 'picking_type_in')[1] or False + if pick_type: + type = type_obj.browse(cr, uid, pick_type, context=context) + if type and type.warehouse_id and type.warehouse_id.company_id.id == company_id: + return pick_type + types = type_obj.search(cr, uid, [('code', '=', 'incoming'), ('warehouse_id.company_id', '=', company_id)], context=context) + if not types: + types = type_obj.search(cr, uid, [('code', '=', 'incoming'), ('warehouse_id', '=', False)], context=context) + if not types: + raise osv.except_osv(_('Error!'), _("Make sure you have at least an incoming picking type defined")) + return types[0] def _get_picking_ids(self, cr, uid, ids, field_names, args, context=None): res = {} diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 2273a889aaf..30cec292af8 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -712,10 +712,11 @@ class sale_order(osv.osv): 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 in ('exception', 'cancel')] + procurement_obj.reset_to_confirmed(cr, uid, proc_ids, context=context) elif sale_line_obj.need_procurement(cr, uid, [line.id], context=context): if (line.state == 'done') or not line.product_id: continue - vals = self._prepare_order_line_procurement(cr, uid, order, line, group_id=group_id, context=context) + vals = self._prepare_order_line_procurement(cr, uid, order, line, group_id=order.procurement_group_id.id, context=context) proc_id = procurement_obj.create(cr, uid, vals, context=context) proc_ids.append(proc_id) #Confirm procurement order such that rules will be applied on it diff --git a/addons/sale_journal/__openerp__.py b/addons/sale_journal/__openerp__.py index 5c03c562033..643dc687441 100644 --- a/addons/sale_journal/__openerp__.py +++ b/addons/sale_journal/__openerp__.py @@ -59,7 +59,7 @@ Some statistics by journals are provided. ], 'demo': ['sale_journal_demo.xml'], 'test': [ ], - 'installable': True, + 'installable': False, 'auto_install': False, } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml index 0d5223a03c8..404316324f5 100644 --- a/addons/sale_stock/sale_stock_view.xml +++ b/addons/sale_stock/sale_stock_view.xml @@ -38,17 +38,11 @@ + on_change="product_id_change_with_wh(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,False,name,parent.partner_id, False, False, parent.date_order, product_packaging, parent.fiscal_position, True, parent.warehouse_id, context)"/> - - - - - + diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index 07024a2529e..c105ed6c017 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -273,7 +273,7 @@ class procurement_order(osv.osv): @param context: A standard dictionary for contextual values @return: Dictionary of values ''' - super(procurement_order, self).run_scheduler(cr, uid, use_new_cursor=use_new_cursor, context=context) + super(procurement_order, self).run_scheduler(cr, uid, use_new_cursor=use_new_cursor, company_id=company_id, context=context) if context is None: context = {} try: @@ -283,7 +283,7 @@ class procurement_order(osv.osv): move_obj = self.pool.get('stock.move') #Minimum stock rules - self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=False, company_id=company_id, context=context) + self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=use_new_cursor, company_id=company_id, context=context) #Search all confirmed stock_moves and try to assign them confirmed_ids = move_obj.search(cr, uid, [('state', '=', 'confirmed')], limit=None, order='priority desc, date_expected asc', context=context) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index ab0807b40bf..902a9f287e9 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2640,13 +2640,27 @@ class stock_inventory(osv.osv): def prepare_inventory(self, cr, uid, ids, context=None): inventory_line_obj = self.pool.get('stock.inventory.line') for inventory in self.browse(cr, uid, ids, context=context): - #clean the existing inventory lines before redoing an inventory proposal + # If there are inventory lines already (e.g. from import), respect those and set their theoretical qty line_ids = [line.id for line in inventory.line_ids] - inventory_line_obj.unlink(cr, uid, line_ids, context=context) - #compute the inventory lines and create them - vals = self._get_inventory_lines(cr, uid, inventory, context=context) - for product_line in vals: - inventory_line_obj.create(cr, uid, product_line, context=context) + if not line_ids: + #compute the inventory lines and create them + vals = self._get_inventory_lines(cr, uid, inventory, context=context) + for product_line in vals: + inventory_line_obj.create(cr, uid, product_line, context=context) + else: + # On import calculate theoretical quantity + quant_obj = self.pool.get("stock.quant") + for line in inventory.line_ids: + dom = [('company_id', '=', line.company_id.id), ('location_id', 'child_of', line.location_id.id), ('lot_id', '=', line.prod_lot_id.id), + ('product_id','=', line.product_id.id), ('owner_id', '=', line.partner_id.id)] + if line.package_id: + dom += [('package_id', '=', line.package_id.id)] + quants = quant_obj.search(cr, uid, dom, context=context) + tot_qty = 0 + for quant in quant_obj.browse(cr, uid, quants, context=context): + tot_qty += quant.qty + inventory_line_obj.write(cr, uid, [line.id], {'theoretical_qty': tot_qty}, context=context) + return self.write(cr, uid, ids, {'state': 'confirm', 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}) def _get_inventory_lines(self, cr, uid, inventory, context=None): @@ -2712,7 +2726,7 @@ class stock_inventory_line(osv.osv): 'company_id': fields.related('inventory_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, select=True, readonly=True), 'prod_lot_id': fields.many2one('stock.production.lot', 'Serial Number', domain="[('product_id','=',product_id)]"), 'state': fields.related('inventory_id', 'state', type='char', string='Status', readonly=True), - 'theoretical_qty': fields.float('Theoretical Quantity', readonly=True), + 'theoretical_qty': fields.float('Theoretical Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), readonly=True), 'partner_id': fields.many2one('res.partner', 'Owner'), 'product_name': fields.related('product_id', 'name', type='char', string='Product Name', store={ 'product.product': (_get_product_name_change, ['name', 'default_code'], 20), diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 7e45cb20a8d..d6a6dcf01f8 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1093,7 +1093,7 @@ - + @@ -1662,7 +1662,7 @@ stock.quant -
+
diff --git a/addons/stock/wizard/stock_transfer_details.py b/addons/stock/wizard/stock_transfer_details.py index 831f225ca13..17f302f6317 100644 --- a/addons/stock/wizard/stock_transfer_details.py +++ b/addons/stock/wizard/stock_transfer_details.py @@ -133,7 +133,7 @@ class stock_transfer_details_items(models.TransientModel): packop_id = fields.Many2one('stock.pack.operation', 'Operation') product_id = fields.Many2one('product.product', 'Product') product_uom_id = fields.Many2one('product.uom', 'Product Unit of Measure') - quantity = fields.Float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), default = 1.0) + quantity = fields.Float('Quantity', digits=dp.get_precision('Product Unit of Measure'), default = 1.0) package_id = fields.Many2one('stock.quant.package', 'Source package', domain="['|', ('location_id', 'child_of', sourceloc_id), ('location_id','=',False)]") lot_id = fields.Many2one('stock.production.lot', 'Lot/Serial Number') sourceloc_id = fields.Many2one('stock.location', 'Source Location', required=True) diff --git a/addons/stock_account/stock_account.py b/addons/stock_account/stock_account.py index c5308fde462..9707263391a 100644 --- a/addons/stock_account/stock_account.py +++ b/addons/stock_account/stock_account.py @@ -282,17 +282,25 @@ class stock_move(osv.osv): def product_price_update_before_done(self, cr, uid, ids, context=None): product_obj = self.pool.get('product.product') + tmpl_dict = {} for move in self.browse(cr, uid, ids, context=context): #adapt standard price on incomming moves if the product cost_method is 'average' if (move.location_id.usage == 'supplier') and (move.product_id.cost_method == 'average'): product = move.product_id - product_avail = product.qty_available - if product.qty_available <= 0: + prod_tmpl_id = move.product_id.product_tmpl_id.id + qty_available = move.product_id.product_tmpl_id.qty_available + if tmpl_dict.get(prod_tmpl_id): + product_avail = qty_available + tmpl_dict[prod_tmpl_id] + else: + tmpl_dict[prod_tmpl_id] = 0 + product_avail = qty_available + if product_avail <= 0: new_std_price = move.price_unit else: # Get the standard price amount_unit = product.standard_price new_std_price = ((amount_unit * product_avail) + (move.price_unit * move.product_qty)) / (product_avail + move.product_qty) + tmpl_dict[prod_tmpl_id] += move.product_qty # Write the standard price, as SUPERUSER_ID because a warehouse manager may not have the right to write on products product_obj.write(cr, SUPERUSER_ID, [product.id], {'standard_price': new_std_price}, context=context)