我正在使用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
答案 0 :(得分:1)
案例1 :数据库中没有存储客户提供给您的任何产品代码的产品
如果尚未在数据库中创建产品代码,则应该有两个CSV文件( Products.csv 和 OrderLine.csv )。第一列必须有三列(id
,name
和product_code
)。第二个列也必须有三列(id
,name
和products/id
)。因此,您只需在 Products.csv 的id
列下构建XML ID,并从文件列products/id
的相应行调用此XML ID OrderLine.csv
案例2 :客户提供给您的产品代码属于数据库中的现有产品
现在,客户已经为您提供了数据库中已存在的产品的产品代码。在这种情况下,您不必创建 Products.csv 文件。您需要知道哪些产品的XML ID包含客户提供给您的产品代码。为此,您可以通过Odoo界面到模型products
的树视图(如果此视图不存在,则必须创建它)。然后,您必须选择所有记录(如果需要,请单击右上角的数字80以显示每页的更多记录)。选择所有这些内容后,点击More
上的Export
按钮和之后的product_code
。选择列name
和id
,然后继续。例如,将生成的CSV文件另存为 Products.csv 。打开它,您将看到导出产品的所有XML ID(如果他们没有XML ID,则在导出后他们会执行-an exportation为每个导出的记录生成XML ID,如果它没有& #39;有任何人 - )。现在,我想客户已经给你一些类似于订单行名称,产品代码的文件,所以替换产品代码列值,包含刚导出的产品的相应XML ID。因此,最终你应该有一个要导入的文件, OrderLine.csv ,包含name
,products/id
和id,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)])