-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathcreate_product_attributes.py
executable file
·204 lines (169 loc) · 7.02 KB
/
create_product_attributes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#! /usr/bin/env python
# -*- encoding: utf-8 -*-
import odoorpc
import click
import csv
__version__ = '1.0.0'
# Define a limit of products to read from csv file
MAX_LINES = 10000000
# Use to create a map with product.template fields and csv headers related
FIELDS_MAPPER = {
'name': ['Nombre'],
'default_code': ['Codigo'],
'description_sale': ['Objeto y campo de aplicaci\xc3\xb3n'],
'list_price': ['Precio'],
}
# Use to ignore some csv headers
IGNORE_KEYS = ['id', 'Estado']
# Use to ignore attributes with this values
IGNORE_VALS = ['', 'N.A', 'N.A.']
# Attributes type mapper
ATTRIBUTE_TYPE = {
'select': [
'Organismo de la norma de correspondencia',
'Tipo de Norma',
'Sector',
'ICS',
],
}
# Column in csv that correspond to product category
CATEGORY_KEY = 'Sector'
# CSV file language
LANG = 'es_CR'
def print_version(ctx, param, value):
if not value or ctx.resilient_parsing:
return
click.echo('Version: %s' % __version__)
ctx.exit()
@click.command()
@click.argument('names', nargs=-1)
@click.option("--db", help="DataBase Name")
@click.option("--user", help="Odoo User")
@click.option("--pwd", help="Odoo Password")
@click.option("--port", type=int, help="Port: 8069 by default", default=8069)
@click.option("--host", help="IP: 127.0.0.1 by default", default="127.0.0.1")
@click.option("--path", help="Path to CSV file with product data")
@click.option('--version', is_flag=True, callback=print_version,
expose_value=False, is_eager=True, help='Show version and exit')
def main(names, db=None, user=None, pwd=None, port=None, host=None, path=None):
if db is None:
print "Database is required"
if user is None:
print "Odoo user is required"
if pwd is None:
print "Odoo password is required"
if path is None:
print "CSV file is required"
if db is None or user is None or pwd is None or path is None:
quit()
odoo = odoorpc.ODOO(host, port=port)
odoo.login(db, user, pwd)
ProductTemplate = odoo.env['product.template']
ProductProduct = odoo.env['product.product']
ProductCategory = odoo.env['product.category']
WebsiteCategory = odoo.env['product.public.category']
Attribute = odoo.env['product.attribute']
AttributeValue = odoo.env['product.attribute.value']
# define a default category
default_categ_id = odoo.env.ref('inteco.product_category_1_1').id
website_categ_id = odoo.env.ref('inteco.product_public_category_1').id
# get all categories that will be used to search in csv data
categ_ids = WebsiteCategory.search([('parent_id', '=', website_categ_id)])
categories = {
categ.with_context(lang=LANG).name.encode('utf8'): categ.id
for categ in WebsiteCategory.browse(categ_ids)
}
all_products = []
created_products = []
updated_products = []
csv_file = open(path, 'r')
csv_rows = csv.DictReader(csv_file)
count = 0
for row in csv_rows:
# search if category for the row exist on the category list
categ_id = row[CATEGORY_KEY].strip() in categories and \
categories[row[CATEGORY_KEY].strip()] or website_categ_id
# prepare product values
product_vals = {
'type': 'service',
'categ_id': default_categ_id,
'public_categ_ids': [(6, 0, [categ_id])],
'website_published': True,
}
# avoid use basic fields as attributes
ignore_attributes = IGNORE_KEYS
for field, possible_keys in FIELDS_MAPPER.iteritems():
match = [{field: row[key].replace('\n', '').strip()}
for key in row if key in possible_keys]
product_vals.update(match and match[0] or {})
ignore_attributes += possible_keys
attribute_line_ids = []
for attribute in row:
if attribute in ignore_attributes:
continue
attribute_type = 'hidden'
for ttype in ATTRIBUTE_TYPE:
if attribute in ATTRIBUTE_TYPE[ttype]:
attribute_type = ttype
attribute_ids = Attribute.search([('name', '=', attribute)])
attribute_id = attribute_ids and attribute_ids[0] or \
Attribute.create({
'name': attribute,
'type': attribute_type,
'create_variant': False})
value_ids = []
for attribute_value in row[attribute].split(','):
if attribute_value.strip() in IGNORE_VALS:
continue
attribute_value_ids = AttributeValue.search([
('name', '=', attribute_value.strip()),
('attribute_id', '=', attribute_id)])
attribute_value_id = attribute_value_ids and \
attribute_value_ids[0] or \
AttributeValue.create({
'name': attribute_value.strip(),
'attribute_id': attribute_id,
})
value_ids += [(4, attribute_value_id)]
if value_ids:
attribute_line_ids += [(0, 0, {
'attribute_id': attribute_id,
'value_ids': value_ids
})]
if attribute_line_ids:
product_vals.update({'attribute_line_ids': attribute_line_ids})
product_tmpl_ids = len(row.get('id', '')) > 0 and [int(row['id'])] or \
ProductTemplate.search([
('default_code', '=', product_vals['default_code'])])
if product_tmpl_ids:
product_tmpl_id = product_tmpl_ids[0]
ProductTemplate.browse(product_tmpl_id).attribute_line_ids.unlink()
ProductTemplate.write(product_tmpl_id, product_vals)
updated_products += [product_tmpl_id]
# FIX-ME: apparently when remove attribute is removed the variant
# now we need to add the default code to the new variant created
product_variant_id = ProductTemplate.browse(
product_tmpl_id).product_variant_id.id
ProductProduct.write(product_variant_id, {
'default_code': product_vals['default_code']})
print '>>>> Updated attributes for product:', product_vals['name']
else:
created_products += [ProductTemplate.create(product_vals)]
print '>>>> Created new product:', product_vals['name']
if count == MAX_LINES:
quit()
count += 1
all_products = updated_products + created_products
archived_products = ProductTemplate.search([
('id', 'not in', all_products),
('categ_id', 'child_of', default_categ_id),
])
ProductTemplate.unlink(archived_products)
print '>>>> Total products updated %d: %s' %(
len(updated_products), updated_products)
print '>>>> Total Products created %d: %s' %(
len(created_products), created_products)
print '>>>> Total products deleted %d: %s' %(
len(archived_products), archived_products)
if __name__ == '__main__':
main()