代码之家  ›  专栏  ›  技术社区  ›  Ancient

Odoo-使用代码而不是id搜索产品

  •  3
  • Ancient  · 技术社区  · 7 年前

    我使用的是odoo 10,我有两种型号的订单和产品。

    订单行

    class OrderLine(models.Model):
    _name = 'order_line'
    _description = 'Order Lines'
    
    name = fields.Char()
    products = fields.Many2one('amgl.products', String='Products')
    

    产品

    class Products(models.Model):
    _name = 'products'
    _description = 'Products'
        _sql_constraints = [
        ('uniq_poduct_code', 'unique(product_code)', 'Product Code already exists!')
    ]
    
    name = fields.Char()
    product_code = Char()
    

    现在,我试图从csv文件创建订单行,在csv文件中,客户向我提供“产品代码”,而不是 Id . 如何处理这个问题,我们使用产品代码,系统自动填充与该产品代码关联的产品。

    注:

    Product Code 在产品表中也是唯一的,所以没有复制的机会。

    CSV模板:

    customer/account_number,customer/first_name,customer/last_name,customer/account_type,order/transaction_id,order/products/product_code,order/quantity,order/customer_id/id
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   forvas    7 年前

    案例1 :数据库中没有存储有客户提供给您的任何产品代码的产品

    如果尚未在数据库中创建产品代码,则应该有两个CSV文件( 产品。csv 订单行。csv ). 第一个必须有三列( id , name product_code ). 第二个也必须有三列( 身份证件 , 名称 products/id ). 因此,您只需在 身份证件 中的列 产品。csv 并从列的相应行中调用该XML ID 产品/id 文件的 订单行。csv .

    案例2 :客户提供给您的产品代码属于数据库中的现有产品

    现在,客户已经为您提供了数据库中已经存在的产品的产品代码。在这种情况下,您不必创建 产品。csv 文件您需要知道哪些产品的XML ID具有客户提供给您的产品代码。为此,您可以通过Odoo的接口访问模型的树状视图 products (如果此视图不存在,则必须创建它)。然后,您必须选择所有记录(如果需要,请单击右上角的数字80以显示每页的更多记录)。选择所有选项后,单击 More 按钮和战后开启 Export . 选择列 产品代码 名称 然后继续。将生成的CSV文件另存为 产品。csv 例如打开它,您将看到导出产品的所有XML ID(如果它们没有XML ID,则在导出后,它们将执行-如果没有任何导出记录,则导出会为每个导出记录生成XML ID-)。现在,我猜客户给了你一些类似于带列的文件的东西 订单行的名称 , 产品代码 ,因此更换 产品代码 列值,其中包含您刚才导出的产品的相应XML ID。所以最后你应该有一个文件要导入, 订单行。csv 具有 身份证件 , 名称 产品/id 柱。

    案例3 :数据库中存储了一些属于现有产品的产品代码,还有一些仍然不存在

    在这种情况下,您必须结合案例1和案例2,首先按照案例2所述导出产品,然后使用代码尚不存在的产品创建一个新产品,如案例1所述。然后将客户提供给您的产品代码替换为案例2中所述的相应代码。

    笔记 :如果有数千条记录要导入并手动替换,则此过程将为您提供大量时间。在这种情况下,必须在CSV编辑器中创建一个宏来进行替换(搜索和替换)。例如,使用LibreOffice,您可以使用Python执行宏。

    实例 (案例3)

    客户向您提供了一份订单行文件,其中有两行:

    • 名称:OL A,产品代码:AAA
    • 名称:OL B,产品代码:BBB

    你从Odoo界面导出产品,你会得到一个文件 生产线:

    id,name,product_code __export__.products_a,"Product A","AAA"

    在两个文件中查找产品代码的一致性,以及 在客户文件的副本中进行替换,因此现在 这是:

    • 名称:OL A,产品代码: __export__.products_a
    • 名称:OL B,产品代码:BBB

    然后创建一个新的CSV 产品。csv 然后把产品放进去 其产品代码尚不存在:

    id,name,product_code __import__.products_b,"Product B","BBB"

    现在再次应用替换,将此新文件与 我们有,你们会得到:

    • 名称:OL A,产品代码: __export\uuuu。产品\u a
    • 名称:OL B,产品代码: __import__.products_b

    将此文件转换为Odoo的正确CSV格式,并将其另存为 订单行。csv :

    id,name,products/id __import__.order_line_1,"OL A",__export__.products_a __import__.order_line_2,"OL B",__import__.products_b

    最后,导入文件,并考虑:import 产品。csv 之前 订单行。csv .

    编辑

    我认为最好是浪费一点时间为CSV编辑器(Excel、LibreOffice、Open Office或其他)编写宏,但如果你绝望了,只需要通过Odoo来完成这项工作,我想出了一个糟糕的解决方法,但至少它应该也能工作。

    1、新建 Char 名为的字段 产品代码 在里面 order_line 模型(临时存在)。

    2、修改该模型的ORM创建方法:

    @api.model
    def create(self, vals):
        product_id = False
        product_code = vals.get('product_code', False)
        if product_code:
            product = self.env['products'].search([
                ('product_code', '=', product_code)
            ])
            if product:
                product_id = product[0].id
        vals.update({
            'products': product_id,
        })
        return super(OrderLine, self).create(vals)
    

    3、复制客户发送给你的文件,正确重命名标题,并重命名列 order/products/product_code 产品代码 . 导入CSV文件。每次导入记录都将调用ORM create方法 订单行 模型

    导入后,您将在数据库中获得与产品正确相关的订单行。

    完成后,必须记住删除已添加的代码(同时删除列 产品代码 从…起 订单行 模型,以删除垃圾)。

        2
  •  1
  •   ChesuCR Ayansplatt    7 年前

    解决方案1

    您可以使用CSV中使用的字段创建瞬态模型。运用@forvas的理念:

    class ImportOrderLines(models.TransientModel):
        _name = 'import.order.lines'
    
        product_code = Char()
    
        @api.model
        def create(self, vals):
            product_id = False
            product_code = vals.get('product_code', False)
            if product_code:
                product = self.env['products'].search([
                    ('product_code', '=', product_code)
                ])
                if product:
                    product_id = product[0].id
    
            self.env['order_line'].create({
                'products': product_id,
            })
            return False   # you don't need to create the record in the transient model
    

    您可以转到该瞬态模型的列表视图,并像在任何其他模型中一样导入,使用 base_import 看法

    解决方案2

    您可以创建一个向导来导入CSV以创建订单行。 检查以下源代码。你必须学会这种方法 import_order_lines 到向导中的按钮。

    import base64
    import magic
    import csv
    from cStringIO import StringIO
    import codecs
    
    from openerp import models, fields, api, _
    from openerp.exceptions import Warning
    
    
    class ImportDefaultCodeWizard(models.TransientModel):
        _name = 'import.default_code.wizard'
    
        name = fields.Char(
            string='File name',
        )
    
        file = fields.Binary(
            string='ZIP file to import to Odoo',
            required=True,
        )
    
        @api.multi
        def import_order_lines(self):
            self.ensure_one()
            content = base64.decodestring(self.file)
    
            if codecs.BOM_UTF8 == content[:3]:  # remove "byte order mark" (windows)
                content = content[3:]
    
            file_type = magic.from_buffer(content, mime=True)
    
            if file_type == 'text/plain':
                self._generate_order_line_from_csv(content)
                return self._show_result_wizard()
    
            raise Warning(
                _('WRONG FILETYPE'),
                _('You should send a CSV file')
            )
    
        def _show_result_wizard(self):
            return {
                'type': 'ir.actions.act_window',
                'res_model': self._name,
                'view_type': 'form',
                'view_mode': 'form',
                'target': 'new',
                'context': self.env.context,
            }        
    
        def _generate_order_line_from_csv(self, data):
            try:
                reader = csv.DictReader(StringIO(data))
            except Exception:
                raise Warning(
                    _('ERROR getting data from csv file'
                    '\nThere was some error trying to get the data from the csv file.'
                    '\nMake sure you are using the right format.'))
            n = 1
    
            for row in reader:
                n += 1
                self._validate_data(n, row)
    
                default_code = row.get('default_code', False)
    
    
                order_line = {
                    'default_code': self._get_product_id(default_code),
    
                    # here you should add all the order line fields
                }
    
                try:
                    self.env['order_line'].create(order_line)
                except Exception:
                    raise Warning(
                        _('The order line could not be created.'
                        '\nROW: %s') % n
                    )
    
        def _validate_data(self, n, row):
            csv_fields = [
                'default_code',
            ]
            """ here is where you should add the CSV fields in order to validate them
                    customer/account_number, customer/first_name, customer/last_name, 
                    customer/account_type, order/transaction_id, order/products/product_code ,order/quantity, order/customer_id/id
            """
    
    
            for key in row:
                if key not in csv_fields:
                    raise Warning(_('ERROR\nThe file format is not right.'
                                    '\nCheck the column names and the CSV format'
                                    '\nKEY: %s' % key))
    
            if row.get('default_code', False) == '':
                raise Warning(
                    _('ERROR Validating data'),
                    _('The product code should be filled.'
                    '\nROW: %s') % n
                )
    
        def _get_product_id(self, default_code):
            if partner_id:
                product_obj = self.env['product.product'].search([
                    ('default_code', '=', default_code),
                ])
                if len(product_code_obj) == 1:
                    return product_obj.default_code
                else:
                    raise Warning(
                        _('ERROR Validating data'),
                        _('The product code should be filled.'
                        '\nROW: %s') % n
                    )        
                return False
    
        3
  •  0
  •   Lucas    7 年前

    您可以按product\u代码进行搜索,如下所示:

    @api.model
    def search_by_code(self, code):
        result = self.env['products'].search([('product_code', '=', code)])