【问题标题】:Odoo - Search products with code instead of idOdoo - 使用代码而不是 id 搜索产品
【发布时间】:2017-12-11 12:42:46
【问题描述】:

我正在使用 odoo 10,我有两个模型 Order_Line 和 Products。

订单行

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 文件创建 order_line,并且在 csv 文件中,客户向我提供了“产品代码”而不是 Id。如何处理,我们使用产品代码,系统会自动填写与该产品代码关联的产品。

注意:

products 表中的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

【问题讨论】:

  • 能否请您出示您要导入的 CSV 模板?

标签: mysql odoo-9 odoo-10 odoo


【解决方案1】:

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

如果尚未在数据库中创建产品代码,您应该有两个 CSV 文件(Products.csvOrderLine.csv)。第一个必须包含三列(idnameproduct_code)。第二个也必须有三列(idnameproducts/id)。因此,您只需在 Products.csvid 列下创建一个 XML ID,并从文件 OrderLine 的 products/id 列的相应行调用此 XML ID .csv.

案例2:客户给你的产品代码属于数据库中已有的产品

现在,客户已经为您提供了数据库中已经存在的产品的产品代码。在这种情况下,您不必创建 Products.csv 文件。您需要知道哪些产品的 XML ID 具有客户提供给您的产品代码。为此,您可以通过 Odoo 的界面进入模型products 的树视图(如果此视图不存在,则必须创建它)。然后,您必须选择所有记录(如果需要,请单击右上角的数字 80 以显示每页的更多记录)。选择所有这些后,单击More 按钮,然后单击Export。选择列product_codename 然后继续。例如,将生成的 CSV 文件另存为 Products.csv。打开它,您将看到导出产品的所有 XML ID(如果它们没有 XML ID,则在导出后他们会执行 - 如果没有任何人,导出会为每个导出记录生成 XML ID -) .现在,我猜客户已经给了您类似文件的内容,其中包含 订单行的名称产品代码,因此请替换 产品代码列值与您刚刚导出的产品的相应 XML ID。所以最后你应该有一个文件要导入,OrderLine.csv,包含idnameproducts/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 Products.csv 并将产品放入其中 其产品代码尚不存在:

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

现在再次应用替换,将这个新文件与之前的文件进行比较 我们有,你会得到这个:

  • 姓名:OL A,产品编号:__export__.products_a
  • 姓名:OL B,产品编号:__import__.products_b

将此文件转换为适用于 Odoo 的正确 CSV 格式,并将其另存为 OrderLine.csv

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

最后,导入文件,并考虑:导入 Products.csvOrderLine.csv 之前。

编辑

我认为最好花点时间为 CSV 编辑器(Excel、LibreOffice、Open Office 或其他)编写宏,但如果您迫不及待,只需要通过 Odoo 进行此操作,我想出了一个糟糕的解决方法,但至少它应该也可以工作。

1.在order_line 模型中创建一个名为product_code 的新Char 字段(它会暂时存在)。

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列重命名为product_code。导入 CSV 文件。每次导入记录都会调用order_line模型的ORM创建方法。

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

完成后,您必须记住删除已添加的代码(还要从数据库中的 order_line 模型中删除列 product_code,以删除垃圾)。

【讨论】:

  • 嗯,它非常具有描述性和信息性,我的情况是#2。客户已经给了我他们在公司使用的产品代码,他们将在 csv 文件中提供相同的产品代码。现在,如果我们要解决您针对 #2 提供的解决方案,我们必须手动将 id 放在每一行上,我假设它会自动发生。
  • 我已经用解决方法编辑了我的答案。一点也不干净,但应该可以在不需要编程宏的情况下工作。
【解决方案2】:

解决方案 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

【讨论】:

  • 我差不多,您正在尝试做的事情,但这不会给我们提供 Odoo 提供的许多功能,例如预览、验证等。我的意思是 Odoo 的方式很花哨。那么有什么方法可以继承base_import 并且我们进行定制是一些特定的方法吗?
  • 该表格用于所有模型,因此如果您根据需要调整它,其余的输入将不起作用。如果你仍然想修改它,恐怕这并不容易。如果您想以奇特的方式查看 CSV,您可以使用 LibreOffice Calc 打开它。如果您仅验证 CSV,则可以在所有创建后强制回滚
  • 如果您检查其他导入模块,他们会创建另一个视图,例如模块 product_variant_csv_import 或者他们会做我所做的事情,请检查模块的屏幕截图 bi_generic_import
  • 您可以在向导中创建一个临时的one2many 字段来显示所有值
  • 我已经用另一个想法@ancient 更新了我的答案。请检查它是否对您有帮助
【解决方案3】:

您可以像这样按 product_code 搜索:

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

【讨论】:

  • 我知道这种搜索方法和域过滤器。但是当我将从 csv 导入时,这种方法将不起作用
猜你喜欢
  • 2016-01-06
  • 2017-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 2011-05-24
  • 1970-01-01
相关资源
最近更新 更多