0

I'm migrating invoices from OpenERP 7 database to Odoo8. I'm retrieving OERP7 data with psycopg2 and then using envs and model.create() to insert invoices into Odoo8 database. In general, the code works fine, but Odoo8 is not generating the invoice number (associated to account_move table) and amount_tax.

My codes are the following:

Import Account Invoice

class ImportAccountInvoice(Command):
    """Import account invoices from source DB"""

    def process_account_invoice(self, model, data):
        if not data:
            return

        # Model structure
        model.create({
            'account_id': data['account_id'],
            'amount_tax': data['amount_tax'],
            'amount_total': data['amount_total'],
            'amount_untaxed': data['amount_untaxed'],
            'check_total': data['check_total'],
            'company_id': data['company_id'],
            'currency_id': data['currency_id'],
            'date_due': data['date_due'],
            'date_invoice': data['date_invoice'],
            'fiscal_position': data['fiscal_position'],
            'internal_number': data['internal_number'],
            'move_name': data['move_name'],
            'name': data['name'],
            'origin': data['origin'],
            'partner_id': data['partner_id'],
            'period_id': data['period_id'],
            'reconciled': data['reconciled'],
            'reference': data['reference'],
            'residual': data['residual'],
            'state': data['state'],
            'type': data['type'],
            'ship_addr_city': data['ship_addr_city'],
            'ship_addr_name': data['ship_addr_name'],
            'client_notes': data['client_notes'],
            'ship_addr_state': data['ship_addr_state'],
            'ship_addr_street': data['ship_addr_street'],
            'ship_addr_phone': data['ship_addr_phone'],
            'ship_addr_zip': data['ship_addr_zip'],
            'drupal_order_name': data['drupal_order_name'],
            'payment_method': data['payment_method'],
            'drupal_total': data['drupal_total']
        })


    def run(self, cmdargs):
        print "Importing account invoices"
        execute_old_database_query("""
            SELECT i.id, i.account_id, i.amount_tax, i.amount_total, i.amount_untaxed, i.check_total, i.company_id, i.currency_id, i.date_due, 
                    i.date_invoice, i.fiscal_position, i.internal_number, i.journal_id, i.move_name, i.name, i.origin, i.partner_id, i.period_id, 
                    i.reconciled, i.reference, i.residual, i.sent, i.state, i.type, i.x_dir_city, i.x_dir_name, i.x_dir_observations, 
                    i.x_dir_state, i.x_dir_street, i.x_dir_telephone, i.x_dir_zip, i.x_drupal_order, i.x_pago, i.x_total,
                    rp.id, rp.email, rp.name, rp.type, rp.vat, rp.street,
                    rc.id, rc.name,
                    aa.id, aa.code, aa.name,
                    ap.id, ap.code, ap.name, ap.date_start, ap.date_stop,
                    aj.type, aj.code,
                    fp.name
                FROM account_invoice i
                    LEFT JOIN res_partner rp
                        ON rp.id = i.partner_id
                    LEFT JOIN res_currency rc
                        ON rc.id = i.currency_id
                    LEFT JOIN account_account aa
                        ON aa.id = i.account_id
                    LEFT JOIN account_period ap
                        ON ap.id = i.partner_id
                    LEFT JOIN account_journal aj
                        ON aj.id = i.journal_id
                    LEFT JOIN account_fiscal_position fp
                        ON fp.id = i.fiscal_position
                ORDER BY i.id;
        """)

        openerp.tools.config.parse_config(cmdargs)
        dbname = openerp.tools.config['db_name']
        r = modules.registry.RegistryManager.get(dbname)
        cr = r.cursor()

        with api.Environment.manage():
            env = api.Environment(cr, 1, {})
            # Define target model 
            account_invoice = env['account.invoice']

            id_ptr = None
            c_data = {}
            while True:
                r = src_cr.fetchone()
                if not r:
                    self.process_account_invoice(account_invoice, c_data)
                    break

                print r

                account = env['account.account'].search([('code','=',r[43]),('name','=',r[44]),])
                currency = env['res.currency'].search([('name','=',r[41]),])

                period = match_account_period(env,code=r[46],name=r[47],date_start=r[48],date_stop=r[49])
                journal = match_account_journal(env,type=r[50],code=r[51])
                fiscal_position = match_account_fiscal_position(env,name=r[52])

                company_id = 1
                if r[38] is not None and r[39] is not None:
                    partner = env['res.partner'].search([('email','=',r[35]),('name','=',r[36]),('type','=',r[37]),('vat','=',r[38]),('street','=',r[39])])
                elif r[38] is not None:
                    partner = env['res.partner'].search([('email','=',r[35]),('name','=',r[36]),('type','=',r[37]),('vat','=',r[38])])
                elif r[39] is not None:
                    partner = env['res.partner'].search([('email','=',r[35]),('name','=',r[36]),('type','=',r[37]),('street','=',r[39])])
                else:
                    partner = env['res.partner'].search([('email','=',r[35]),('name','=',r[36]),('type','=',r[37])])

                # Take one when partners are duplicated
                partner_id = partner.id if len(list(partner)) <= 1 else partner[0].id
                fiscal_position_id = fiscal_position.id if fiscal_position else None

                if id_ptr != r[0]:
                    self.process_account_invoice(account_invoice, c_data)
                    id_ptr = r[0]

                    c_data = {
                        'id': r[0],
                        'account_id': account.id,
                        'amount_tax': r[2],
                        'amount_total': r[3],
                        'amount_untaxed': r[4],
                        'check_total': r[5],
                        'company_id': company_id,
                        'currency_id': currency.id,
                        'date_due': r[8],
                        'date_invoice': r[9],
                        'fiscal_position': fiscal_position_id,
                        'internal_number': r[11],
                        'journal_id': journal.id,
                        'move_name': r[13],
                        'name': r[14],
                        'origin': r[15],
                        'partner_id': partner_id,
                        'partner_invoice_id': partner_id,
                        'partner_shipping_id': partner_id,
                        'period_id': period.id,
                        'reconciled': r[18],
                        'reference': r[19],
                        'residual': r[20],
                        'sent': r[21],
                        'state': r[22],
                        'type': r[23],
                        'ship_addr_city': r[24],
                        'ship_addr_name': r[25],
                        'client_notes': r[26],
                        'ship_addr_state': r[27],
                        'ship_addr_country': '',
                        'ship_addr_street': r[28],
                        'ship_addr_phone': r[29],
                        'ship_addr_zip': r[30],
                        'drupal_order_name': r[31],
                        'payment_method': r[32],
                        'drupal_total': r[33]
                    }

        cr.commit()
        cr.close()

Import Account Invoice Lines

class ImportAccountInvoiceLine(Command):
    """Import account invoice lines from source DB"""

    def process_account_invoice_line(self, model, data):
        if not data:
            return

        # Model structure
        m = {
            'account_id': data['account_id'],
            'create_date': data['create_date'],
            'company_id': data['company_id'],
            'discount': data['discount'],
            'invoice_id': data['invoice_id'],
            'name': data['name'],
            'partner_id': data['partner_id'],
            'product_id': data['product_id'],
            'quantity': data['quantity'],
            'price_unit': data['price_unit'],
            'price_subtotal': data['price_subtotal'],
            'supplier_name': data['supplier_name'],
            'supplier_ref': data['supplier_ref'],
            'item_lot_number': data['item_lot_number'],
            'item_expiration': data['item_expiration'],
            'item_delivery_note': data['item_delivery_note'],
        }

        if not data['invoice_line_tax_id'] is None:
            m['invoice_line_tax_id'] = [(4,data['invoice_line_tax_id'])] # http://stackoverflow.com/questions/31853402/filling-many2many-field-odoo-8

        print model.create(m)


    def recalculate_tax_amount(self,cr):
        with api.Environment.manage():
            env = api.Environment(cr, 1, {})
            invoices = env['account.invoice'].search([])
            account_invoice_tax = env['account.invoice.tax']
            print "Recalculating invoice taxes"
            for invoice in invoices:
                print invoice
                print invoice.action_move_create()
#                print invoice.button_reset_taxes()

                if invoice.id <= 32600:
                    break

    def run(self, cmdargs):
        print "Importing account invoice lines"
        execute_old_database_query("""
            SELECT il.id, il.account_id, il.create_date, il.company_id, il.discount, il.invoice_id, il.name, il.partner_id, il.price_unit, 
                    il.price_subtotal, il.product_id, il.quantity, il.x_prov, il.x_ref_prov, il.x_lote, il.x_caducidad, il.x_albaran,
                    i.internal_number, i.name, i.origin, i.reference, i.type, i.x_drupal_order, i.date_invoice,
                    rp.email, rp.name, rp.type, rp.vat, rp.street,
                    pp.default_code, pp.name_template, pp.x_subcategoria, pp.x_marca,
                    at.type_tax_use, at.name
                FROM account_invoice_line il
                    LEFT JOIN account_invoice i
                        ON i.id = il.invoice_id
                    LEFT JOIN res_partner rp
                        ON rp.id = il.partner_id
                    LEFT JOIN product_product pp
                        ON pp.id = il.product_id
                    LEFT JOIN account_invoice_line_tax ailt
                        ON ailt.invoice_line_id = il.id
                    LEFT JOIN account_tax at
                        ON at.id = ailt.tax_id
                WHERE il.id > 28700
                ORDER BY il.id DESC;
        """)

        openerp.tools.config.parse_config(cmdargs)
        dbname = openerp.tools.config['db_name']
        r = modules.registry.RegistryManager.get(dbname)
        cr = r.cursor()

        with api.Environment.manage():
            env = api.Environment(cr, 1, {})
            # Define target model 
            account_invoice_line = env['account.invoice.line']

            id_ptr = None
            c_data = {}

            company_id = 1
            while True:
                r = src_cr.fetchone()
                if not r:
                    self.process_account_invoice_line(account_invoice_line, c_data)
                    break

                print r

                print r[17],r[18],r[19],r[20],r[21]

                if not (r[17] is None and r[18] is None and r[19] is None and r[20] is None):
                    account_invoice = env['account.invoice'].search([('internal_number','=',r[17]),('name','=',r[18]),('origin','=',r[19]),('reference','=',r[20]),('type','=',r[21]),('drupal_order_name','=',r[22]),('date_invoice','=',r[23])])
                    print "normal"
                else:
                    print "parner"
                    if r[27] is not None and r[28] is not None:
                        partner = env['res.partner'].search([('email','=',r[24]),('name','=',r[25]),('type','=',r[26]),('vat','=',r[27]),('street','=',r[28])])
                    elif r[27] is not None:
                        partner = env['res.partner'].search([('email','=',r[24]),('name','=',r[25]),('type','=',r[26]),('vat','=',r[27])])
                    elif r[28] is not None:
                        partner = env['res.partner'].search([('email','=',r[24]),('name','=',r[25]),('type','=',r[26]),('street','=',r[28])])
                    else:
                        partner = env['res.partner'].search([('email','=',r[24]),('name','=',r[25]),('type','=',r[26])])

                    # Take one when partners are duplicated
                    partner_id = partner.id if len(list(partner)) <= 1 else partner[0].id
                    account_invoice = env['account.invoice'].search([('internal_number','=',r[17]),('name','=',r[18]),('origin','=',r[19]),('reference','=',r[20]),('type','=',r[21]),('drupal_order_name','=',r[22]),('date_invoice','=',r[23]),('partner_id','=',partner_id)])

                    if not account_invoice: # If there is not an account_invoice for this partner, continue with the next row
                        print "^ NO INVOICE FOR THIS LINE ^"
                        continue 

                product = env['product.product'].search([('default_code','=',r[29]),('name_template','=',r[30]),('subcategory_txt','=',r[31]),('brand','=',r[32])])

                # Take one when invoices are duplicated
                invoice = account_invoice if len(list(account_invoice)) <= 1 else account_invoice[0]
                # Take one when products are duplicated
                product_id = product.id if len(list(product)) <= 1 else product[0].id

                print r[33],r[34]
                if r[33] is None and r[34] is None:
                    tax_id = None
                else:
                    tax = match_account_tax(env, r[33], r[34])
                    tax_id = tax.id

                if id_ptr != r[0]:
                    self.process_account_invoice_line(account_invoice_line, c_data)
                    id_ptr = r[0]

                    c_data = {
                        'id': r[0],
                        'account_id': invoice.account_id.id,
                        'create_date': r[2],
                        'company_id': r[3],
                        'discount': r[4],
                        'invoice_id': invoice.id,
                        'name': r[6],
                        'partner_id': invoice.partner_id.id,
                        'price_unit': r[8],
                        'price_subtotal': r[9],
                        'product_id': product_id,
                        'quantity': r[11],
                        'supplier_name': r[12],
                        'supplier_ref': r[13],
                        'item_lot_number': r[14],
                        'item_expiration': r[15],
                        'item_delivery_note': r[16],
                        'invoice_line_tax_id': tax_id
                    }

        cr.commit()

        self.recalculate_tax_amount(cr)

        cr.close()

I have associated Journals, Periods... but I can't get Odoo creates the account.move and compute all taxes. What should I do?

IMPORTANT: I need to assign the same number each invoice already have in old database.

1 Answers1

0

The solution was to create a function to update invoice taxes and move, at the end of invoice lines insertion and before commit.

The function:

def refresh_invoices_and_recompute_taxes(self, model, invoice_ids):
    for i in invoice_ids:
        print "Updating invoice", i
        invoice = model.browse(i)
        print "- Computing taxes"
        invoice.button_compute(set_total=True)
        invoice.action_date_assign()
        print "- Creating account move"
        invoice.action_move_create()
        print "- Assigning number"
        invoice.action_number()

My class:

class ImportAccountInvoiceLine(Command):
    """Import account invoice lines from source DB"""

    def process_account_invoice_line(self, model, data):
        if not data:
            return

        m = {
            'account_id': data['account_id'],
            'create_date': data['create_date'],
            'company_id': data['company_id'],
            'discount': data['discount'],
            'invoice_id': data['invoice_id'],
            'name': data['name'],
            'partner_id': data['partner_id'],
            'product_id': data['product_id'],
            'quantity': data['quantity'],
            'price_unit': data['price_unit'],
            'price_subtotal': data['price_subtotal'],
            'supplier_name': data['supplier_name'],
            'supplier_ref': data['supplier_ref'],
            'item_lot_number': data['item_lot_number'],
            'item_expiration': data['item_expiration'],
            'item_delivery_note': data['item_delivery_note'],
        }

        if not data['invoice_line_tax_id'] is None:
            m['invoice_line_tax_id'] = [(4,data['invoice_line_tax_id'])] # http://stackoverflow.com/questions/31853402/filling-many2many-field-odoo-8

        # Model structure
        model.create(m)

    def refresh_invoices_and_recompute_taxes(self, model,invoice_ids):
        for i in invoice_ids:
            print "Updating invoice", i
            invoice = model.browse(i)
            print "- Computing taxes"
            invoice.button_compute(set_total=True)
            invoice.action_date_assign()
            print "- Creating account move"
            invoice.action_move_create()
            print "- Assigning number"
            invoice.action_number()


    def run(self, cmdargs):
        print "Importing account invoice lines"
        execute_old_database_query("""
            SELECT il.id, il.account_id, il.create_date, il.company_id, il.discount, il.invoice_id, il.name, il.partner_id, il.price_unit, 
                    il.price_subtotal, il.product_id, il.quantity, il.x_prov, il.x_ref_prov, il.x_lote, il.x_caducidad, il.x_albaran,
                    i.internal_number, i.name, i.origin, i.reference, i.type, i.x_drupal_order, i.date_invoice,
                    rp.email, rp.name, rp.type, rp.vat, rp.street,
                    pp.default_code, pp.name_template, pp.x_subcategoria, pp.x_marca,
                    at.type_tax_use, at.name
                FROM account_invoice_line il
                    LEFT JOIN account_invoice i
                        ON i.id = il.invoice_id
                    LEFT JOIN res_partner rp
                        ON rp.id = il.partner_id
                    LEFT JOIN product_product pp
                        ON pp.id = il.product_id
                    LEFT JOIN account_invoice_line_tax ailt
                        ON ailt.invoice_line_id = il.id
                    LEFT JOIN account_tax at
                        ON at.id = ailt.tax_id
                ORDER BY il.invoice_id ASC, il.id ASC
                LIMIT 10000;
        """)

        openerp.tools.config.parse_config(cmdargs)
        dbname = openerp.tools.config['db_name']
        r = modules.registry.RegistryManager.get(dbname)
        cr = r.cursor()

        invoice_ids = []
        inv_id = 0
        with api.Environment.manage():
            env = api.Environment(cr, 1, {})
            # Define target model 
            account_invoice_line = env['account.invoice.line']

            id_ptr = None
            c_data = {}

            company_id = 1
            while True:
                r = src_cr.fetchone()
                if not r:
                    self.process_account_invoice_line(account_invoice_line, c_data)
                    break

                if not (r[17] is None and r[18] is None and r[19] is None and r[20] is None):
                    account_invoice = env['account.invoice'].search([('internal_number','=',r[17]),('name','=',r[18]),('origin','=',r[19]),('reference','=',r[20]),('type','=',r[21]),('drupal_order_name','=',r[22]),('date_invoice','=',r[23])])
                else:
                    if r[27] is not None and r[28] is not None:
                        partner = env['res.partner'].search([('email','=',r[24]),('name','=',r[25]),('type','=',r[26]),('vat','=',r[27]),('street','=',r[28])])
                    elif r[27] is not None:
                        partner = env['res.partner'].search([('email','=',r[24]),('name','=',r[25]),('type','=',r[26]),('vat','=',r[27])])
                    elif r[28] is not None:
                        partner = env['res.partner'].search([('email','=',r[24]),('name','=',r[25]),('type','=',r[26]),('street','=',r[28])])
                    else:
                        partner = env['res.partner'].search([('email','=',r[24]),('name','=',r[25]),('type','=',r[26])])

                    # Take one when partners are duplicated
                    partner_id = partner.id if len(list(partner)) <= 1 else partner[0].id
                    account_invoice = env['account.invoice'].search([('internal_number','=',r[17]),('name','=',r[18]),('origin','=',r[19]),('reference','=',r[20]),('type','=',r[21]),('drupal_order_name','=',r[22]),('date_invoice','=',r[23]),('partner_id','=',partner_id)])

                    if not account_invoice: # If there is not an account_invoice for this partner, continue with the next row
                        print "^ NO INVOICE FOR THIS LINE ^"
                        continue 

                product = env['product.product'].search([('default_code','=',r[29]),('name_template','=',r[30]),('subcategory_txt','=',r[31]),('brand','=',r[32])])

                # Take one when invoices are duplicated
                invoice = account_invoice if len(list(account_invoice)) <= 1 else account_invoice[0]
                # Take one when products are duplicated
                product_id = product.id if len(list(product)) <= 1 else product[0].id
                if not invoice:
                    continue
                else:
                    if inv_id != invoice.id:
                        inv_id = invoice.id
                        invoice_ids.append(inv_id)

                tax = match_account_tax(env, r[33], r[34])
                tax_id = tax.id if tax is not None and tax else None

                if id_ptr != r[0]:
                    id_ptr = r[0]

                    c_data = {
                        'id': r[0],
                        'account_id': invoice.account_id.id,
                        'create_date': r[2],
                        'company_id': r[3],
                        'discount': r[4],
                        'invoice_id': invoice.id,
                        'name': r[6],
                        'partner_id': invoice.partner_id.id,
                        'price_unit': r[8],
                        'price_subtotal': r[9],
                        'product_id': product_id,
                        'quantity': r[11],
                        'supplier_name': r[12],
                        'supplier_ref': r[13],
                        'item_lot_number': r[14],
                        'item_expiration': r[15],
                        'item_delivery_note': r[16],
                        'invoice_line_tax_id': tax_id
                    }

                    self.process_account_invoice_line(account_invoice_line, c_data)

            self.refresh_invoices_and_recompute_taxes(env['account.invoice'], invoice_ids)

        cr.commit()
        cr.close()