def migrate_stock_qty(cr, registry):
    """Reprocess stock moves in done state to fill stock.quant."""
    # First set restrict_lot_id so that quants point to correct moves
    sql = '''
        UPDATE stock_move SET restrict_lot_id = {}
    '''.format(openupgrade.get_legacy_name('prodlot_id'))
    openupgrade.logged_query(cr, sql)

    with api.Environment.manage():
        env = api.Environment(cr, SUPERUSER_ID, {})
        done_moves = env['stock.move'].search(
            [('state', '=', 'done')], order="date")
        openupgrade.message(
            cr, 'stock', 'stock_move', 'state',
            'Reprocess %s stock moves in state done to fill stock.quant',
            len(done_moves.ids))
        done_moves.write({'state': 'draft'})
        # disable all workflow steps - massive performance boost, no side
        # effects of workflow transitions with yet unknown condition
        set_workflow_org = models.BaseModel.step_workflow
        models.BaseModel.step_workflow = lambda *args, **kwargs: None
        # Process moves using action_done.
        for move in done_moves:
            date_done = move.date
            move.action_done()
            # Rewrite date to keep old data
            move.date = date_done
            # Assign the same date for the created quants (not the existing)
            quants_to_rewrite = move.quant_ids.filtered(
                lambda x: x.in_date > date_done)
            quants_to_rewrite.write({'in_date': date_done})
        models.BaseModel.step_workflow = set_workflow_org
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
        path_obj.create(cr, uid, vals)
def migrate_stock_qty(cr, registry):
    """Reprocess stock moves in done state to fill stock.quant."""
    # First set restrict_lot_id so that quants point to correct moves
    sql = '''
        UPDATE stock_move SET restrict_lot_id = {}
    '''.format(openupgrade.get_legacy_name('prodlot_id'))
    openupgrade.logged_query(cr, sql)

    with api.Environment.manage():
        env = api.Environment(cr, SUPERUSER_ID, {})
        done_moves = env['stock.move'].search([('state', '=', 'done')],
                                              order="date")
        openupgrade.message(
            cr, 'stock', 'stock_move', 'state',
            'Reprocess %s stock moves in state done to fill stock.quant',
            len(done_moves.ids))
        done_moves.write({'state': 'draft'})
        # Process moves using action_done.
        for move in done_moves:
            date_done = move.date
            move.action_done()
            # Rewrite date to keep old data
            move.date = date_done
            # Assign the same date for the created quants (not the existing)
            quants_to_rewrite = move.quant_ids.filtered(
                lambda x: x.in_date > date_done)
            quants_to_rewrite.write({'in_date': date_done})
def migrate_stock_qty(cr, registry):
    """Reprocess stock moves in state done to fill stock.quant."""
    stock_move_obj = registry['stock.move']

    done_move_ids = stock_move_obj.search(cr, uid, [('state', '=', 'done')])
    openupgrade.message(
        cr, 'stock', 'stock_move', 'state',
        'Reprocess %s stock moves in state done to fill stock.quant',
        len(done_move_ids))
    stock_move_obj.write(cr, uid, done_move_ids, {'state': 'draft'})
    # Process moves using action_done.
    stock_move_obj.action_done(cr, uid, done_move_ids, context=None)
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',
    ))
def ensure_admin_email(cr, pool):
    """During migration, there are writes via the ORM to tracking
    fields. This breaks if admin neither has a valid alias nor an email"""
    admin = pool['res.users'].browse(cr, SUPERUSER_ID, SUPERUSER_ID)
    if not admin.email and not pool['ir.config_parameter'].get_param(
            cr, SUPERUSER_ID, 'mail.catchall.domain'):
        # that's the default value for new installations
        default_email = '*****@*****.**'
        openupgrade.message(
            'base', None, None,
            'No email address for admin and no catchall domain defined - '
            'setting admin\'s email address to %s', default_email)
        admin.write({'email': default_email})
Exemple #7
0
def migrate_stock_warehouse(cr, pool):
    """Enable purchasing on all warehouses. This will trigger the creation
    of the purchase procurement rule"""
    warehouse_obj = pool['stock.warehouse']
    warehouse_ids = warehouse_obj.search(cr, uid, [])
    warehouse_obj.write(cr, uid, warehouse_ids, {'buy_to_resupply': True})
    if len(warehouse_ids) > 1:
        openupgrade.message(
            cr, 'purchase', False, False,
            "Purchasing is now enabled on all your warehouses. If this is "
            "not appropriate, disable the option 'Purchase to resupply this "
            "Warehouse' on the warehouse settings. You need to have 'Manage "
            "Push and Pull inventory flows' checked on your user record in "
            "order to access this setting.")
Exemple #8
0
def process_states(cr):
    """Map obsolete active states to 'running' and let the scheduler decide
    if these procurements are actually 'done'. Warn if there are procurements
    in obsolete draft state"""
    openupgrade.logged_query(
        cr, "UPDATE procurement_order SET state = %s WHERE state in %s",
        ('running', ('ready', 'waiting')))
    cr.execute("SELECT COUNT(*) FROM procurement_order WHERE state = 'draft'")
    count = cr.fetchone()[0]
    if count:
        openupgrade.message(
            cr, 'procurement', 'procurement_order', 'state',
            'In this database, %s procurements are in draft state. In '
            'Odoo 8.0, these procurements cannot be processed further.', count)
def migrate_procurement_order(cr, registry):
    """Set warehouse, partner from the 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
        """)
    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(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 set_warehouse_view_location(cr, registry, warehouse):
    """
    Getting the shared view locations of all existing locations which is
    not the overall Physical locations view. Searching for parent
    left/right explicitely for lack of a parent_of operator.
    For parent left/right clarification, refer to
    https://answers.launchpad.net/openobject-server/+question/186704

    Known issue: we don't know if the found view location includes locations
    of other warehouses and is thus not warehouse specific so we'll just warn
    about the changes we make.
    """
    location_obj = registry['stock.location']
    all_warehouse_view = registry['ir.model.data'].get_object_reference(
        cr, uid, 'stock', 'stock_location_locations')[1]
    location_ids = location_obj.search(cr, uid, [
        ('parent_left', '<', warehouse.lot_stock_id.parent_left),
        ('parent_left', '<', warehouse.lot_stock_id.parent_right),
        ('parent_right', '>', warehouse.lot_stock_id.parent_left),
        ('parent_right', '>', warehouse.lot_stock_id.parent_right),
        ('parent_left', '<', warehouse.wh_input_stock_loc_id.parent_left),
        ('parent_left', '<', warehouse.wh_input_stock_loc_id.parent_right),
        ('parent_right', '>', warehouse.wh_input_stock_loc_id.parent_left),
        ('parent_right', '>', warehouse.wh_input_stock_loc_id.parent_right),
        ('parent_left', '<', warehouse.wh_output_stock_loc_id.parent_left),
        ('parent_left', '<', warehouse.wh_output_stock_loc_id.parent_right),
        ('parent_right', '>', warehouse.wh_output_stock_loc_id.parent_left),
        ('parent_right', '>', warehouse.wh_output_stock_loc_id.parent_right),
        ('id', 'child_of', all_warehouse_view),
        ('id', '!=', all_warehouse_view),
    ])
    if location_ids:
        warehouse_view_id = location_ids[0]
        location = location_obj.browse(cr, uid, location_ids[0])
        openupgrade.message(
            cr, 'stock', 'stock_warehouse', 'view_location_id',
            "Selecting location '%s' as the view location of warehouse %s",
            location.name, warehouse.code)
    else:
        openupgrade.message(cr, 'stock', 'stock_warehouse', 'view_location_id',
                            "Creating new view location for warehouse %s",
                            warehouse.code)
        for location in (warehouse.lot_stock_id,
                         warehouse.wh_input_stock_loc_id,
                         warehouse.wh_output_stock_loc_id):
            if (location.location_id
                    and location.location_id.id != all_warehouse_view):
                openupgrade.message(
                    cr, 'stock', 'stock_location', 'location_id',
                    "Overwriting existing parent location (%s) of location %s "
                    "with the warehouse's new view location",
                    location.location_id.name, location.name)

        warehouse_view_id = location_obj.create(
            cr, uid, {
                'name': warehouse.code,
                'usage': 'view',
                'location_id': all_warehouse_view,
            })
        location_obj.write(
            cr, uid,
            set([
                warehouse.lot_stock_id.id, warehouse.wh_input_stock_loc_id.id,
                warehouse.wh_output_stock_loc_id.id
            ]), {'location_id': warehouse_view_id})
    warehouse.write({'view_location_id': warehouse_view_id})
    warehouse.refresh()
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'))
Exemple #13
0
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'))