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

时间:2017-12-11 12:42:47

标签: mysql odoo-9 odoo-10 odoo

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

OrderLine

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文件创建order_line,客户正在向我提供产品代码'而不是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

3 个答案:

答案 0 :(得分:1)

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

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

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

现在,客户已经为您提供了数据库中已存在的产品的产品代码。在这种情况下,您不必创建 Products.csv 文件。您需要知道哪些产品的XML ID包含客户提供给您的产品代码。为此,您可以通过Odoo界面到模型products的树视图(如果此视图不存在,则必须创建它)。然后,您必须选择所有记录(如果需要,请单击右上角的数字80以显示每页的更多记录)。选择所有这些内容后,点击More上的Export按钮和之后的product_code。选择列nameid,然后继续。例如,将生成的CSV文件另存为 Products.csv 。打开它,您将看到导出产品的所有XML ID(如果他们没有XML ID,则在导出后他们会执行-an exportation为每个导出的记录生成XML ID,如果它没有& #39;有任何人 - )。现在,我想客户已经给你一些类似于订单行名称产品代码的文件,所以替换产品代码列值,包含刚导出的产品的相应XML ID。因此,最终你应该有一个要导入的文件, OrderLine.csv ,包含nameproducts/idid,name,product_code __export__.products_a,"Product A","AAA"列。

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

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

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

  

示例(案例3)

     

客户已经为您提供了一个订单行文件,其中包含两行:

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

您从Odoo界面导出产品,并获得一个文件   行:

     

__export__.products_a

     

您在两个文件中查找产品代码的巧合,以及   在客户文件的副本中进行替换,现在就可以了   这样:

     
      
  • 名称:OL A,产品代码:id,name,product_code __import__.products_b,"Product B","BBB"
  •   
  • 名称:OL B,产品代码:BBB
  •   
     

然后您创建一个新的CSV Products.csv 并将产品放入其中   其产品代码尚不存在:

     

__export__.products_a

     

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

     
      
  • 名称:OL A,产品代码:__import__.products_b
  •   
  • 名称:OL B,产品代码:id,name,products/id __import__.order_line_1,"OL A",__export__.products_a __import__.order_line_2,"OL B",__import__.products_b
  •   
     

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

     

Char

     

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

修改

我认为在为CSV编辑器(Excel,LibreOffice,Open Office或其他)编程宏时浪费一些时间应该更好,但是如果你已经绝望了,你只需要通过Odoo,我提出了一个糟糕的解决方法,但至少,它应该也有效。

1.在product_code模型中创建一个名为order_line的新@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) 字段(它会暂时存在)。

2.修改此模型的ORM创建方法:

order/products/product_code

3.复制客户发送给您的文件,正确重命名标题,并将列product_code重命名为order_line。导入CSV文件。每次记录输入都将调用product_code模型的ORM创建方法。

输入后,您将在数据库中拥有与产品正确相关的订单行。

当您完成后,我们必须记住删除您已添加的代码(并从数据库中删除order_line模型中的{{1}}列,为了删除垃圾)。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

您可以按照以下方式搜索product_code:

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