def migrate_pos_config(cr, pool): pc_obj = pool['pos.config'] pc_ids = pc_obj.search(cr, SUPERUSER_ID, []) for pc in pc_obj.browse(cr, SUPERUSER_ID, pc_ids): cr.execute(""" SELECT %s FROM pos_config WHERE id = %d """ % (openupgrade.get_legacy_name('shop_id'), pc.id)) shop_id = cr.fetchone()[0] stock_loc_id = get_stock_location_id(cr, pool, shop_id) vals = { 'stock_location_id': stock_loc_id, 'company_id': get_company_id(cr, pool, shop_id, pc, stock_loc_id), 'picking_type_id': get_picking_type_id(cr, pool, shop_id, pc), } pricelist_id = get_pricelist_id(cr, pool, shop_id, pc) if pricelist_id: vals.update({'pricelist_id': pricelist_id}) pc.write(vals)
def migrate(cr, version): registry = RegistryManager.get(cr.dbname) openupgrade.map_values(cr, openupgrade.get_legacy_name('priority'), 'priority', [('4', '0'), ('3', '0'), ('2', '1'), ('1', '2'), ('0', '2')], table='project_task', write='sql') openupgrade_80.update_aliases(cr, registry, 'project.project', set_parent_thread_id=True, defaults_id_key='project_id') openupgrade_80.set_message_last_post(cr, uid, registry, ['project.project', 'project.task']) openupgrade.load_data(cr, 'project', 'migrations/8.0.1.1/noupdate_changes.xml')
def migrate_stock_production_lot(cr, registry): """Serial numbers migration :param cr: """ lot_obj = registry['stock.production.lot'] user_obj = registry['res.users'] # Revisions to mail messages cr.execute(""" SELECT lot_id, author_id, description FROM stock_production_lot_revision""") for lot, author, description in cr.fetchall(): user = user_obj.browse(cr, uid, author) if user.email: lot_obj.message_post(cr, author, lot, body=description) # Move: prodlot_id -> Quants lot_id. # Only on dangling/inventory moves, because the other (from pickings) had # stock.pack.operation linked with related lot before creating the quant field_name = openupgrade.get_legacy_name('prodlot_id') cr.execute(""" SELECT id, %s FROM stock_move WHERE %s IS NOT NULL AND picking_id IS NULL""" % ( field_name, field_name)) res1 = cr.fetchall() for move, lot in res1: cr.execute(""" SELECT quant_id FROM stock_quant_move_rel WHERE move_id = %s""" % (move,)) res2 = cr.fetchall() for quant in res2: cr.execute(""" UPDATE stock_quant SET lot_id = %s WHERE id = %s""" % (lot, quant[0],)) cr.commit()
def inventory_period_id(cr, pool): """ Replacing the confirmation date of the inventory with the accounting period of the associated company. """ period_obj = pool['account.period'] inventory_obj = pool['stock.inventory'] date_done = openupgrade.get_legacy_name('date_done') cr.execute(""" SELECT id, company_id, {date_done} FROM stock_inventory WHERE {date_done} IS NOT NULL """.format(date_done=date_done)) for inv_id, company_id, date in cr.fetchall(): period_ids = period_obj.find(cr, SUPERUSER_ID, dt=date[:10], context={'company_id': company_id}) inventory_obj.write(cr, SUPERUSER_ID, inv_id, {'period_id': period_ids[0]}) # Drop column as a marker that this script has run openupgrade.drop_columns(cr, [('stock_inventory', date_done)])
def migrate_move_inventory(cr, registry): """ Inventory's move_ids needs migration from many2many to one2many on the stock move's inventory_id field. Should be safe to assume that a move was always related to a single inventory anyway. Set product and filter for single product inventories. """ openupgrade.logged_query( cr, """ UPDATE stock_move sm SET inventory_id = rel.inventory_id FROM {stock_inventory_move_rel} rel WHERE sm.id = rel.move_id """.format(stock_inventory_move_rel=openupgrade.get_legacy_name( 'stock_inventory_move_rel'))) openupgrade.logged_query( cr, """ UPDATE stock_inventory si SET product_id = l.product_id, filter = 'product' FROM stock_inventory_line l WHERE l.inventory_id = si.id AND (SELECT COUNT(*) FROM stock_inventory_line WHERE inventory_id = si.id) = 1; """) openupgrade.logged_query( cr, """ UPDATE stock_inventory si SET location_id = l.location_id FROM stock_inventory_line l WHERE l.inventory_id = si.id """)
def migrate_product_supply_method(cr): """ Procurements of products: change the supply_method for the matching route Buy -> Buy Rule :param cr: Database cursor """ pool = pooler.get_pool(cr.dbname) template_obj = pool['product.template'] mto_route_id = pool['ir.model.data'].get_object_reference( cr, uid, 'purchase', 'route_warehouse0_buy')[1] procure_method_legacy = openupgrade.get_legacy_name('supply_method') if mto_route_id: product_ids = [] cr.execute( """SELECT id FROM product_template WHERE %s = %%s""" % (procure_method_legacy), ('buy', )) product_ids = [res[0] for res in cr.fetchall()] template_obj.write(cr, uid, product_ids, {'route_ids': [(4, mto_route_id)]})
def update_hr_expense_ok(cr, pool): field_name = openupgrade.get_legacy_name('hr_expense_ok') template_obj = pool.get('product.template') openupgrade.logged_query( cr, """SELECT product_templ_id FROM product_product WHERE %s = 't';""" % field_name) template_ids = [row[0] for row in cr.fetchall()] template_obj.write(cr, SUPERUSER_ID, template_ids, {'hr_expense_ok': True}) for template_id in template_ids: openupgrade.logged_query( cr, """SELECT DISTINCT t.id FROM product_template t LEFT JOIN product_product p1 ON t.id = p1.product_tmpl_id LEFT JOIN product_product p2 ON t.id = p2.product_tmpl_id WHERE p1.%s = 't' AND p2.%s = 'f';""" % (field_name, field_name)) for row in cr.fetchall(): logger.warning( 'hr_expense_ok of product.template %d has been set to True ' 'whereas at least one of its product_product was False', row[0])
def migrate_stock_production_lot(cr, registry): """Serial numbers migration :param cr: """ lot_obj = registry['stock.production.lot'] user_obj = registry['res.users'] # Revisions to mail messages cr.execute(""" SELECT lot_id, author_id, description FROM stock_production_lot_revision""") for lot, author, description in cr.fetchall(): user = user_obj.browse(cr, uid, author) if user.email: lot_obj.message_post(cr, author, lot, body=description) # Move: prodlot_id -> Quants lot_id. field_name = openupgrade.get_legacy_name('prodlot_id') cr.execute("""select id, %s from stock_move where %s is not null""" % (field_name, field_name)) res1 = cr.fetchall() for move, lot in res1: cr.execute(""" SELECT quant_id FROM stock_quant_move_rel WHERE move_id = %s""" % (move, )) res2 = cr.fetchall() for quant in res2: cr.execute(""" UPDATE stock_quant SET lot_id = %s WHERE id = %s""" % ( lot, quant[0], )) cr.commit()
def create_properties(cr, pool): """ Fields moved to properties (standard_price). Write using the ORM so the prices will be written as properties. """ template_obj = pool['product.template'] company_obj = pool['res.company'] company_ids = company_obj.search(cr, SUPERUSER_ID, []) sql = ("SELECT id, %s FROM product_template" % openupgrade.get_legacy_name('standard_price')) cr.execute(sql) for template_id, std_price in cr.fetchall(): for company_id in company_ids: ctx = {'force_company': company_id} template_obj.write(cr, SUPERUSER_ID, [template_id], {'standard_price': std_price}, context=ctx) # product.price.history entries have been generated with a value for # today, we want a value for the past as well, write a bogus date to # be sure that we have an historic value whenever we want cr.execute("UPDATE product_price_history SET " # calling a field 'datetime' is not really a good idea "datetime = '1970-01-01 00:00:00+00'")
def migrate_invoice_addresses(cr, pool): # Contact id takes precedence over old partner id openupgrade_70.set_partner_id_from_partner_address_id( cr, pool, 'account.invoice', 'partner_id', openupgrade.get_legacy_name('address_contact_id'))
def migrate(cr, version): pool = pooler.get_pool(cr.dbname) set_message_last_post(cr, SUPERUSER_ID, pool, ['event.event', 'event.registration']) convert_field_to_html(cr, 'event_event', get_legacy_name('note'), 'description')
def set_procurement_groups(cr): """ Create and propagate the sale order's procurement groups, because this is the only way that sale orders and pickings are linked. """ # Create a procurement group for every sale order pointed to by a picking, # and link the procurement group to the sale order. cr.execute( """ SELECT DISTINCT {sale_id} FROM stock_picking WHERE {sale_id} IS NOT NULL """.format( sale_id=openupgrade.get_legacy_name('sale_id'))) logger.debug( "Creating procurement groups for %s sale orders with " "pickings.", cr.rowcount) for sale_order_id, in cr.fetchall(): cr.execute( """ INSERT INTO procurement_group (create_date, create_uid, name, partner_id, move_type) SELECT now(), %s, so.name, so.partner_shipping_id, so.picking_policy FROM sale_order so WHERE so.id = %s RETURNING id""", (SUPERUSER_ID, sale_order_id)) group_id = cr.fetchone()[0] cr.execute( """ UPDATE sale_order so SET procurement_group_id = %s WHERE so.id = %s """, (group_id, sale_order_id)) # Progagate sale procurement groups to the related pickings openupgrade.logged_query( cr, """ UPDATE stock_picking sp SET group_id = so.procurement_group_id FROM sale_order so WHERE sp.{sale_id} = so.id """.format( sale_id=openupgrade.get_legacy_name('sale_id'))) # Propagate picking procurement groups to the related stock moves openupgrade.logged_query( cr, """ UPDATE stock_move sm SET group_id = sp.group_id FROM stock_picking sp WHERE sm.picking_id = sp.id """) # Propagate sale procurement groups, and the shop's warehouse # to the related procurements. The warehouse is propagated # to the the procurement's dest move and generated moves # in the deferred step. openupgrade.logged_query( cr, """ UPDATE procurement_order po SET group_id = so.procurement_group_id, warehouse_id = so.warehouse_id FROM sale_order so, sale_order_line sol WHERE po.sale_line_id = sol.id AND sol.order_id = so.id """)
def import_crm_meeting(cr): ''' merge crm.meeting records into plain calendar events, record crm.meeting's id in get_legacy_name('crm_meeting_id') to correct references in modules using crm.meeting before. Finally, update chatter. ''' cr.execute('alter table calendar_event add column %s int' % (openupgrade.get_legacy_name('crm_meeting_id'), )) cr.execute('''insert into calendar_event (%s, create_uid, create_date, write_date, write_uid, name, state, allday, duration, description, class, location, show_as, rrule, rrule_type, recurrency, recurrent_id, recurrent_id_date, end_type, interval, count, mo, tu, we, th, fr, sa, su, day, week_list, byday, user_id, active, -- those are actually different start, stop, start_date, start_datetime, stop_date, stop_datetime, final_date, month_by) select id, create_uid, create_date, write_date, write_uid, name, state, allday, duration, description, class, location, show_as, rrule, rrule_type, recurrency, recurrent_id, recurrent_id_date, end_type, interval, count, mo, tu, we, th, fr, sa, su, day, week_list, byday, user_id, active, -- those are actually different date, date, date, date, coalesce(date + interval '1 hour' * duration, date), coalesce(date + interval '1 hour' * duration, date), end_date, select1 from crm_meeting''' % (openupgrade.get_legacy_name('crm_meeting_id'), )) cr.execute('''insert into calendar_event_res_partner_rel (calendar_event_id, res_partner_id) select calendar_event.id, partner_id from crm_meeting_partner_rel join calendar_event on %s=crm_meeting_partner_rel.meeting_id''' % (openupgrade.get_legacy_name('crm_meeting_id'), )) # there's a chance we still have the old constraint because # the values we update now caused the new constrained to be invalid cr.execute('''alter table meeting_category_rel drop constraint meeting_category_rel_event_id_fkey''') cr.execute('''update meeting_category_rel set event_id=calendar_event.id from calendar_event where event_id=%s''' % (openupgrade.get_legacy_name('crm_meeting_id'), )) # recreate the constraint as odoo would do it cr.execute('''alter table meeting_category_rel add constraint meeting_category_rel_event_id_fkey foreign key (event_id) references calendar_event(id) on delete cascade''') # attendees now refer to their event in a m2o field cr.execute('''update calendar_attendee set event_id=calendar_event.id from meeting_attendee_rel join calendar_event on %s=meeting_attendee_rel.event_id where attendee_id=calendar_attendee.id''' % (openupgrade.get_legacy_name('crm_meeting_id'), )) # and update chatter cr.execute('''update mail_message set model='calendar.event', res_id=calendar_event.id from calendar_event where model='crm.meeting' and res_id=%s''' % (openupgrade.get_legacy_name('crm_meeting_id'), ))
def migrate_procurement_order(cr): """ On procurements, purchase_id is replaced by purchase_line_id. We should be able to match most purchase lines because they got the procurement's move_id as their move_dest_id. Fallback on product_id, for presumably the manually created procurements without a related move from a sale or production order. In Odoo 8.0, stock moves generated for the procurement (moves from the supplier or production location to stock) are also recorded on the procurement. For purchase procurements, gather them here. Note that procurement_order.move_dest_id was proc.move_id in 7.0, renamed to legacy in the 8.0 procurement migration script and then renamed again to move_dest_id in the stock migration script. """ openupgrade.logged_query( cr, """ UPDATE procurement_order proc SET purchase_line_id = pol.id FROM purchase_order_line pol WHERE proc.{purchase_id} = pol.order_id AND pol.{move_dest_id} IS NOT NULL AND pol.{move_dest_id} = proc.move_dest_id """.format(purchase_id=openupgrade.get_legacy_name('purchase_id'), move_dest_id=openupgrade.get_legacy_name('move_dest_id'))) openupgrade.logged_query( cr, """ UPDATE procurement_order proc SET purchase_line_id = pol.id FROM purchase_order_line pol WHERE proc.{purchase_id} = pol.order_id AND proc.purchase_line_id IS NULL AND pol.product_id = proc.product_id AND pol.id NOT IN ( SELECT purchase_line_id FROM procurement_order WHERE purchase_line_id IS NOT NULL) """.format(purchase_id=openupgrade.get_legacy_name('purchase_id'))) # Warn about dangling procurements cr.execute(""" SELECT count(*) FROM procurement_order WHERE purchase_line_id IS NULL AND {purchase_id} IS NOT NULL AND state NOT IN ('done', 'exception') """.format(purchase_id=openupgrade.get_legacy_name('purchase_id'))) count = cr.fetchone()[0] if count: logger.warning( "Failed to match the purchase order line for %s running " "procurements.", count) # Populate the moves generated from purchase procurements (the move_ids # field on the procurement order) openupgrade.logged_query( cr, """ UPDATE stock_move sm SET procurement_id = proc.id FROM procurement_order proc WHERE proc.purchase_line_id = sm.purchase_line_id AND sm.purchase_line_id IS NOT NULL """)
def migrate_stock_picking(cr, registry): """Update picking records with the correct picking_type_id and state. As elsewhere, multiple warehouses with the same company pose a problem. """ warehouse_obj = registry['stock.warehouse'] company_obj = registry['res.company'] picking_obj = registry['stock.picking'] type_legacy = openupgrade.get_legacy_name('type') for company in company_obj.browse(cr, uid, company_obj.search(cr, uid, [])): warehouse_ids = warehouse_obj.search(cr, uid, [('company_id', '=', company.id)]) if not warehouse_ids: picking_ids = picking_obj.search(cr, uid, [('company_id', '=', company.id)]) if not picking_ids: continue warehouse_ids = [ registry['ir.model.data'].xmlid_to_res_id( cr, uid, 'stock.warehouse0', raise_if_not_found=True) ] openupgrade.message( cr, 'stock', 'stock_picking', 'picking_type_id', 'No warehouse found for company %s, but this company does ' 'have pickings. Taking the default warehouse.', company.name) warehouse = warehouse_obj.browse(cr, uid, warehouse_ids[0]) if len(warehouse_ids) > 1: openupgrade.message( cr, 'stock', 'stock_picking', 'picking_type_id', 'Multiple warehouses found for company %s. Taking first' 'one found (%s) to determine the picking types for this ' 'company\'s pickings. Please verify this setting.', company.name, warehouse.name) # Fill picking_type_id required field for picking_type, type_id in (('in', warehouse.in_type_id.id), ('out', warehouse.out_type_id.id), ('internal', warehouse.int_type_id.id)): openupgrade.logged_query( cr, """ UPDATE stock_picking SET picking_type_id = %s WHERE {type_legacy} = %s """.format(type_legacy=type_legacy), ( type_id, picking_type, )) # state key auto -> waiting cr.execute("UPDATE stock_picking SET state = %s WHERE state = %s", ( 'waiting', 'auto', )) # Add a column for referring stock moves in stock pack operation cr.execute(""" ALTER TABLE stock_pack_operation ADD COLUMN %s INTEGER """ % openupgrade.get_legacy_name('move_id')) # Recreate stock.pack.operation (only for moves that belongs to a picking) stock_move_obj = registry['stock.move'] done_move_ids = stock_move_obj.search(cr, uid, [('state', '=', 'done')]) if not done_move_ids: return openupgrade.logged_query( cr, """ INSERT INTO stock_pack_operation (%s, picking_id, product_id, product_uom_id, product_qty, qty_done, lot_id, date, location_id, location_dest_id, processed) SELECT id, picking_id, product_id, product_uom, product_uom_qty, product_uom_qty, %s, date, location_id, location_dest_id, 'true' FROM stock_move WHERE id IN %%s AND picking_id IS NOT NULL """ % (openupgrade.get_legacy_name('move_id'), openupgrade.get_legacy_name('prodlot_id')), (tuple(done_move_ids), )) # And link it with moves creating stock.move.operation.link records openupgrade.logged_query( cr, """ INSERT INTO stock_move_operation_link (move_id, operation_id, qty) SELECT %s, id, product_qty FROM stock_pack_operation """ % openupgrade.get_legacy_name('move_id'))
def migrate_stock_picking(cr, registry): """Update picking records with the correct picking_type_id and state. As elsewhere, multiple warehouses with the same company pose a problem. """ warehouse_obj = registry['stock.warehouse'] company_obj = registry['res.company'] picking_obj = registry['stock.picking'] location_obj = registry['stock.location'] type_legacy = openupgrade.get_legacy_name('type') for company in company_obj.browse(cr, uid, company_obj.search(cr, uid, [])): warehouse_ids = warehouse_obj.search(cr, uid, [('company_id', '=', company.id)]) if not warehouse_ids: picking_ids = picking_obj.search(cr, uid, [('company_id', '=', company.id)]) if not picking_ids: continue warehouse_ids = [ registry['ir.model.data'].xmlid_to_res_id( cr, uid, 'stock.warehouse0', raise_if_not_found=True) ] openupgrade.message( cr, 'stock', 'stock_picking', 'picking_type_id', 'No warehouse found for company %s, but this company does ' 'have pickings. Taking the default warehouse.', company.name) for warehouse in warehouse_obj.browse(cr, uid, warehouse_ids): # Select all the child locations of this Warehouse location_ids = location_obj.search( cr, uid, [('id', 'child_of', warehouse.view_location_id.id)]) # Fill picking_type_id required field for picking_type, type_id in (('in', warehouse.in_type_id.id), ('out', warehouse.out_type_id.id), ('internal', warehouse.int_type_id.id)): openupgrade.logged_query( cr, """ UPDATE stock_picking AS sp SET picking_type_id = %s WHERE sp.id IN ( SELECT sp1.id FROM stock_picking AS sp1 INNER JOIN stock_move AS sm1 ON sm1.picking_id = sp1.id WHERE ( sm1.location_dest_id in %s OR sm1.location_id in %s ) AND sp1.{type_legacy} = %s ) """.format(type_legacy=type_legacy), ( type_id, tuple(location_ids), tuple(location_ids), picking_type, )) if warehouse_ids: warehouse = warehouse_obj.browse(cr, uid, warehouse_ids[0]) # For other stock pickings that were associated to no warehouse # at all, just take the picking from the main warehouse. for picking_type, type_id in (('in', warehouse.in_type_id.id), ('out', warehouse.out_type_id.id), ('internal', warehouse.int_type_id.id)): openupgrade.logged_query( cr, """ UPDATE stock_picking as sp SET picking_type_id = %s WHERE picking_type_id IS NULL AND sp.{type_legacy} = %s """.format(type_legacy=type_legacy), ( type_id, picking_type, )) # state key auto -> waiting cr.execute("UPDATE stock_picking SET state = %s WHERE state = %s", ( 'waiting', 'auto', )) # Add a column for referring stock moves in stock pack operation cr.execute(""" ALTER TABLE stock_pack_operation ADD COLUMN %s INTEGER """ % openupgrade.get_legacy_name('move_id')) # Recreate stock.pack.operation (only for moves that belongs to a picking) openupgrade.logged_query( cr, """ INSERT INTO stock_pack_operation (%s, picking_id, product_id, product_uom_id, product_qty, qty_done, lot_id, date, location_id, location_dest_id, processed) SELECT id, picking_id, product_id, product_uom, product_uom_qty, product_uom_qty, %s, date, location_id, location_dest_id, 'true' FROM stock_move WHERE state = 'done' AND picking_id IS NOT NULL """ % (openupgrade.get_legacy_name('move_id'), openupgrade.get_legacy_name('prodlot_id')), ) # And link it with moves creating stock.move.operation.link records openupgrade.logged_query( cr, """ INSERT INTO stock_move_operation_link (move_id, operation_id, qty) SELECT %s, id, product_qty FROM stock_pack_operation """ % openupgrade.get_legacy_name('move_id'))
def migrate_stock_location(cr, registry): """Create a Push rule for each pair of locations linked. Will break if there are multiple warehouses for the same company.""" path_obj = registry['stock.location.path'] location_obj = registry['stock.location'] warehouse_obj = registry['stock.warehouse'] head_sql = """SELECT id, %s, %s, %s, %s, name, %s FROM stock_location""" % ( openupgrade.get_legacy_name('chained_location_id'), openupgrade.get_legacy_name('chained_auto_packing'), openupgrade.get_legacy_name('chained_company_id'), openupgrade.get_legacy_name('chained_delay'), openupgrade.get_legacy_name('chained_picking_type')) tail_sql = """ WHERE %s = 'fixed'""" % ( openupgrade.get_legacy_name('chained_location_type')) cr.execute(head_sql + tail_sql) for location in cr.fetchall(): loc = location_obj.browse(cr, uid, location[1]) loc_from = location_obj.browse(cr, uid, location[0]) name = '{} -> {}'.format(location[5], loc.name) vals = { 'active': True, 'propagate': True, 'location_from_id': location[0], 'location_dest_id': location[1], 'auto': location[2], 'company_id': location[3], 'delay': location[4], 'name': name, } company_id = location[3] or loc.company_id.id or loc_from.company_id.id args = company_id and [('company_id', '=', company_id)] or [] warehouse_ids = warehouse_obj.search(cr, uid, args) if not warehouse_ids: warehouse_ids = [ registry['ir.model.data'].xmlid_to_res_id( cr, uid, 'stock.warehouse0', raise_if_not_found=True) ] openupgrade.message( cr, 'stock', 'stock_location_path', 'warehouse_id', 'No warehouse found for company #%s, but this company does ' 'have chained pickings. Taking the default warehouse.', company_id) vals['warehouse_id'] = warehouse_ids[0] warehouse = warehouse_obj.browse(cr, uid, vals['warehouse_id']) if len(warehouse_ids) > 1: openupgrade.message( cr, 'stock', 'stock_location_path', 'warehouse_id', 'Multiple warehouses found for location path %s. Taking ' '%s. Please verify this setting.', name, warehouse.name) if location[6] == 'in': vals['picking_type_id'] = warehouse.in_type_id.id elif location[6] == 'out': vals['picking_type_id'] = warehouse.out_type_id.id else: vals['picking_type_id'] = warehouse.int_type_id.id if warehouse and warehouse[0].company_id: vals['company_id'] = warehouse[0].company_id.id path_obj.create(cr, uid, vals)
def migrate(cr, version): registry = RegistryManager.get(cr.dbname) openupgrade.m2o_to_x2m( cr, registry['sale.order.line'], 'sale_order_line', 'procurement_ids', openupgrade.get_legacy_name('procurement_id'))
def migrate_procurement_order(cr, registry): """ In 7.0: procurement_order.move_id: the reservation for which the procurement was generated. Counterpart field on the stock move is stock_move.procurements. This is the move_dest_id on the purchase order lines that are created for the procurement, which is propagated as the move_dest_id on the move lines created for the incoming products of the purchase order. The id(s) of these move lines are recorded as the purchase line's move_ids (or stock_move.purchase_line_id). Something similar occurs in mrp: stock_move.production_id vs. production_ order.move_created_ids(2), and procurement_order.production_id. The procurement order's move_id is production_order.move_prod_id. In 8.0: procurement_order.move_dest_id: stock move that generated the procurement order, e.g. a sold product from stock to customer location. Counterpart field on the stock move does not seem to exist. procurement_order.move_ids: moves that the procurement order has generated, e.g. a purchased product from supplier to stock location. Counterpart field on the stock move is stock_move.procurement_id. """ # Reverse the link between procurement orders and the stock moves that # satisfy them. cr.execute(""" UPDATE stock_move sm SET procurement_id = po.id FROM procurement_order po WHERE po.{move_id} = sm.id """.format(move_id=openupgrade.get_legacy_name('move_id'))) # Sync the destination move, if any cr.execute(""" UPDATE procurement_order po SET move_dest_id = sm.move_dest_id FROM stock_move sm WHERE sm.procurement_id = po.id AND sm.move_dest_id IS NOT NULL """) # Set partner from the destination move. cr.execute(""" UPDATE procurement_order AS po SET partner_dest_id = sm.partner_id FROM stock_move AS sm WHERE po.move_dest_id = sm.id AND sm.partner_id IS NOT NULL """) # Set warehouse company_obj = registry['res.company'] warehouse_obj = registry['stock.warehouse'] procurement_obj = registry['procurement.order'] for company in company_obj.browse(cr, uid, company_obj.search(cr, uid, [])): procurement_ids = procurement_obj.search( cr, uid, [('company_id', '=', company.id)]) if not procurement_ids: continue warehouse_ids = warehouse_obj.search(cr, uid, [('company_id', '=', company.id)]) if not warehouse_ids: # Warehouse_id is not required on procurements openupgrade.message( cr, 'stock', 'procurement_order', 'warehouse_id', 'No warehouse found for company %s, but this company does ' 'have procurements. Not setting a warehouse on them.', company.name) continue warehouse = warehouse_obj.browse(cr, uid, warehouse_ids[0]) if len(warehouse_ids) > 1: openupgrade.message( cr, 'stock', 'procurement_order', 'warehouse_id', 'Multiple warehouses found for company %s. Taking first' 'one found (%s) to append to this company\'s procurements. ' 'Please verify this setting.', company.name, warehouse.name) procurement_obj.write(cr, uid, procurement_ids, {'warehouse_id': warehouse.id})
def migrate_procurement_order_method(cr, pool): """Procurements method: change the supply_method for the matching rule Needs to be deferred because the rules are created in the migration of stock, purchase and mrp. Will only run if stock is installed. Will run after every attempt to upgrade, but harmless when run multiple times. """ cr.execute( """ SELECT id FROM ir_module_module WHERE name = 'stock' AND state = 'installed' AND latest_version = '8.0.1.1' """) if not cr.fetchone(): # Only warn if there are traces of stock if openupgrade.table_exists(cr, 'stock_move'): logger.debug( "Stock not installed or not properly migrated, skipping " "migration of procurement orders.") return procure_method_legacy = openupgrade.get_legacy_name('procure_method') if not openupgrade.column_exists( cr, 'product_template', procure_method_legacy): # in this case, there was no migration for the procurement module # which can be okay if procurement was not installed in the 7.0 db return procurement_obj = pool['procurement.order'] rule_obj = pool['procurement.rule'] rules = {} for rule in rule_obj.browse( cr, SUPERUSER_ID, rule_obj.search(cr, SUPERUSER_ID, [])): rules.setdefault( rule.location_id.id, {})[rule.procure_method] = rule.id rules.setdefault(rule.location_id.id, {})[rule.action] = rule.id cr.execute( """ SELECT pp.id FROM product_product pp, product_template pt WHERE pp.product_tmpl_id = pt.id AND pt.%s = 'produce' """ % openupgrade.get_legacy_name('supply_method')) production_products = [row[0] for row in cr.fetchall()] cr.execute( """ SELECT id, %s FROM procurement_order WHERE rule_id is NULL AND state != %%s """ % procure_method_legacy, ('done',)) procurements = cr.fetchall() if len(procurements): logger.debug( "Trying to find rules for %s procurements", len(procurements)) for proc_id, procure_method in procurements: procurement = procurement_obj.browse(cr, SUPERUSER_ID, proc_id) location_id = procurement.location_id.id # if location type is internal (presumably stock), then # find the rule with this location and the appropriate action, # regardless of procure method rule_id = False action = 'move' # Default, only for log message if procure_method == 'make_to_order': if procurement.location_id.usage == 'internal': if procurement.product_id.id in production_products: action = 'manufacture' else: action = 'buy' rule_id = rules.get(location_id, {}).get(action) else: rule_id = rules.get(location_id, {}).get('make_to_order') else: rule_id = rules.get(location_id, {}).get('make_to_stock') if rule_id: procurement.write({'rule_id': rule_id}) else: logger.warn( "Procurement order #%s with location %s " "has no %s procurement rule with action %s, please create and " "assign a new rule for this procurement""", procurement.id, procurement.location_id.name, procure_method, action)