Odoo - 使用代码而不是 ID 搜索产品
Odoo - Search products with code instead of id
我正在使用 odoo 10,我有两个型号 Order_Line 和产品。
订单行
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 文件中,客户向我提供 'Product Code' 而不是 Id
。如何处理,我们使用产品代码,系统自动填写与该产品代码关联的产品。
注:
Product Code
在产品table中也是唯一的,所以没有重复的机会。
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
您可以按 product_code 搜索:
@api.model
def search_by_code(self, code):
result = self.env['products'].search([('product_code', '=', code)])
案例 1:数据库中没有存储有客户给您的任何产品代码的产品
如果尚未在数据库中创建产品代码,您应该有两个 CSV 文件(Products.csv 和 OrderLine.csv)。第一个必须有三列(id
、name
和 product_code
)。第二个也必须有三列(id
、name
和 products/id
)。因此,您只需在 Products.csv 中的 id
列下创建一个 XML ID,并从文件 OrderLine.csv.
列的相应行 products/id
案例2:客户给你的产品编码属于数据库中已有的产品
现在,客户给了你数据库中已经存在的产品的产品代码。在这种情况下,您不必创建 Products.csv 文件。您需要知道哪些产品的 XML ID 具有客户提供给您的产品代码。为此,您可以通过 Odoo 的界面进入模型的树视图 products
(如果此视图不存在,则必须创建它)。然后,您必须 select 所有记录(如果需要,单击右上角的数字 80 可在每页显示更多记录)。一旦所有这些都被 selected,点击 More
按钮,然后点击 Export
。 Select 列 product_code
和 name
然后继续。例如,将生成的 CSV 文件保存为 Products.csv。打开它,你会看到所有出口产品的 XML ID(如果他们没有 XML ID,出口后他们会做 - 出口生成 XML ID每个导出的记录,如果它没有任何人-)。现在,我猜客户给了你一些类似文件的东西,其中包含列 订单行名称 、 产品代码 ,因此请替换 产品代码 列值与您刚刚导出的产品各自的 XML ID。所以最后你应该有一个文件要导入,OrderLine.csv,包含 id
、name
和 products/id
列。
案例3:数据库中有一些属于现有产品的产品代码,还有一些还不存在
在这种情况下,您必须结合案例 1 和案例 2,首先,按照案例 2 中的描述导出产品,然后,使用其代码尚不存在的产品创建一个新产品,如所述在案例1中,然后将客户给你的产品代码替换为案例2中描述的相应产品代码。
注意:如果您有数千条记录要导入并手动替换它们,此过程将为您节省很多时间。在这种情况下,必须在 CSV 编辑器中创建一个宏来执行替换(使用搜索和替换)。例如,在 LibreOffice 中,您可以使用 Python.
执行宏
Example (Case 3)
The customer has given you a file of order lines, with two lines:
- Name: OL A, Product Code: AAA
- Name: OL B, Product Code: BBB
You export products from Odoo interface and you get a file with one
line:
id,name,product_code
__export__.products_a,"Product A","AAA"
You look for the coincidences of the product codes in both files, and
do the replacements in a copy of the customer file, so now you have
this:
- Name: OL A, Product Code:
__export__.products_a
- Name: OL B, Product Code: BBB
Then you create a new CSV Products.csv and put in there the products
whose product code don't exist yet:
id,name,product_code
__import__.products_b,"Product B","BBB"
Now apply the replacements again comparing this new file with the one
we had, and you will get this:
- Name: OL A, Product Code:
__export__.products_a
- Name: OL B, Product Code:
__import__.products_b
Convert this file to a right CSV format for Odoo, and save it as
OrderLine.csv:
id,name,products/id
__import__.order_line_1,"OL A",__export__.products_a
__import__.order_line_2,"OL B",__import__.products_b
And finally, import the files, and take into account: import
Products.csv before OrderLine.csv.
编辑
我认为最好花点时间为您的 CSV 编辑器(Excel、LibreOffice、Open Office 或其他)编写一个宏,但如果您感到绝望并且需要仅通过 Odoo 执行此操作,我想出了一个糟糕的解决方法,但至少,它也应该有效。
1.Create order_line
模型中名为 product_code
的新 Char
字段(暂时存在)。
2.Modify该模型的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.Copy 客户发给你的文件,将headers 正确命名,并将order/products/product_code
列重命名为product_code
。导入 CSV 文件。每次导入记录都会调用order_line
模型的ORM创建方法。
导入后,您将在数据库中拥有与产品正确相关的订单行。
完成后,您必须记住删除已添加的代码(并从数据库的 order_line
模型中删除列 product_code
,以便删除垃圾)。
解决方案 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 10,我有两个型号 Order_Line 和产品。
订单行
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 文件中,客户向我提供 'Product Code' 而不是 Id
。如何处理,我们使用产品代码,系统自动填写与该产品代码关联的产品。
注:
Product Code
在产品table中也是唯一的,所以没有重复的机会。
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
您可以按 product_code 搜索:
@api.model
def search_by_code(self, code):
result = self.env['products'].search([('product_code', '=', code)])
案例 1:数据库中没有存储有客户给您的任何产品代码的产品
如果尚未在数据库中创建产品代码,您应该有两个 CSV 文件(Products.csv 和 OrderLine.csv)。第一个必须有三列(id
、name
和 product_code
)。第二个也必须有三列(id
、name
和 products/id
)。因此,您只需在 Products.csv 中的 id
列下创建一个 XML ID,并从文件 OrderLine.csv.
products/id
案例2:客户给你的产品编码属于数据库中已有的产品
现在,客户给了你数据库中已经存在的产品的产品代码。在这种情况下,您不必创建 Products.csv 文件。您需要知道哪些产品的 XML ID 具有客户提供给您的产品代码。为此,您可以通过 Odoo 的界面进入模型的树视图 products
(如果此视图不存在,则必须创建它)。然后,您必须 select 所有记录(如果需要,单击右上角的数字 80 可在每页显示更多记录)。一旦所有这些都被 selected,点击 More
按钮,然后点击 Export
。 Select 列 product_code
和 name
然后继续。例如,将生成的 CSV 文件保存为 Products.csv。打开它,你会看到所有出口产品的 XML ID(如果他们没有 XML ID,出口后他们会做 - 出口生成 XML ID每个导出的记录,如果它没有任何人-)。现在,我猜客户给了你一些类似文件的东西,其中包含列 订单行名称 、 产品代码 ,因此请替换 产品代码 列值与您刚刚导出的产品各自的 XML ID。所以最后你应该有一个文件要导入,OrderLine.csv,包含 id
、name
和 products/id
列。
案例3:数据库中有一些属于现有产品的产品代码,还有一些还不存在
在这种情况下,您必须结合案例 1 和案例 2,首先,按照案例 2 中的描述导出产品,然后,使用其代码尚不存在的产品创建一个新产品,如所述在案例1中,然后将客户给你的产品代码替换为案例2中描述的相应产品代码。
注意:如果您有数千条记录要导入并手动替换它们,此过程将为您节省很多时间。在这种情况下,必须在 CSV 编辑器中创建一个宏来执行替换(使用搜索和替换)。例如,在 LibreOffice 中,您可以使用 Python.
执行宏Example (Case 3)
The customer has given you a file of order lines, with two lines:
- Name: OL A, Product Code: AAA
- Name: OL B, Product Code: BBB
You export products from Odoo interface and you get a file with one line:
id,name,product_code __export__.products_a,"Product A","AAA"
You look for the coincidences of the product codes in both files, and do the replacements in a copy of the customer file, so now you have this:
- Name: OL A, Product Code:
__export__.products_a
- Name: OL B, Product Code: BBB
Then you create a new CSV Products.csv and put in there the products whose product code don't exist yet:
id,name,product_code __import__.products_b,"Product B","BBB"
Now apply the replacements again comparing this new file with the one we had, and you will get this:
- Name: OL A, Product Code:
__export__.products_a
- Name: OL B, Product Code:
__import__.products_b
Convert this file to a right CSV format for Odoo, and save it as OrderLine.csv:
id,name,products/id __import__.order_line_1,"OL A",__export__.products_a __import__.order_line_2,"OL B",__import__.products_b
And finally, import the files, and take into account: import Products.csv before OrderLine.csv.
编辑
我认为最好花点时间为您的 CSV 编辑器(Excel、LibreOffice、Open Office 或其他)编写一个宏,但如果您感到绝望并且需要仅通过 Odoo 执行此操作,我想出了一个糟糕的解决方法,但至少,它也应该有效。
1.Create order_line
模型中名为 product_code
的新 Char
字段(暂时存在)。
2.Modify该模型的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.Copy 客户发给你的文件,将headers 正确命名,并将order/products/product_code
列重命名为product_code
。导入 CSV 文件。每次导入记录都会调用order_line
模型的ORM创建方法。
导入后,您将在数据库中拥有与产品正确相关的订单行。
完成后,您必须记住删除已添加的代码(并从数据库的 order_line
模型中删除列 product_code
,以便删除垃圾)。
解决方案 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