Merge lp:~akretion-team/openerp-connector-magento/openerp-connector-magento-catalog into lp:~openerp-connector-core-editors/openerp-connector-magento/7.0
- openerp-connector-magento-catalog
- Merge into 7.0
Status: | Rejected |
---|---|
Rejected by: | Sébastien BEAU - http://www.akretion.com |
Proposed branch: | lp:~akretion-team/openerp-connector-magento/openerp-connector-magento-catalog |
Merge into: | lp:~openerp-connector-core-editors/openerp-connector-magento/7.0 |
Diff against target: |
2313 lines (+2228/-0) (has conflicts) 16 files modified
magentoerpconnect_catalog/__init__.py (+29/-0) magentoerpconnect_catalog/__openerp__.py (+67/-0) magentoerpconnect_catalog/connector.py (+26/-0) magentoerpconnect_catalog/consumer.py (+118/-0) magentoerpconnect_catalog/magento_model.py (+50/-0) magentoerpconnect_catalog/magento_model_view.xml (+26/-0) magentoerpconnect_catalog/product.py (+185/-0) magentoerpconnect_catalog/product_attribute.py (+527/-0) magentoerpconnect_catalog/product_attribute_view.xml (+231/-0) magentoerpconnect_catalog/product_category.py (+239/-0) magentoerpconnect_catalog/product_image.py (+336/-0) magentoerpconnect_catalog/product_image_view.xml (+79/-0) magentoerpconnect_catalog/product_view.xml (+78/-0) magentoerpconnect_catalog/tests/__init__.py (+29/-0) magentoerpconnect_catalog/tests/test_attribute_synchronisation.py (+109/-0) magentoerpconnect_catalog/tests/test_data.py (+99/-0) Conflict adding file magentoerpconnect_catalog. Moved existing file to magentoerpconnect_catalog.moved. |
To merge this branch: | bzr merge lp:~akretion-team/openerp-connector-magento/openerp-connector-magento-catalog |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP Connector Core Editors | Pending | ||
Review via email: mp+223605@code.launchpad.net |
Commit message
Description of the change
Add product catalog export
- 44. By Sébastien BEAU - http://www.akretion.com
-
[REF] comment product image view for now, need to be fixed
- 45. By Sébastien BEAU - http://www.akretion.com
-
[REF] attribute set export skeletonSetId should be map only at creation
- 46. By Sébastien BEAU - http://www.akretion.com
-
[FIX] fix backend view, move attribute_
set_tpl_ id just after default category - 47. By Sébastien BEAU - http://www.akretion.com
-
[FIX] replace fields by vals (connector 2.2 update)
- 48. By Sébastien BEAU - http://www.akretion.com
-
[IMP] add test for attribute set synchronisation
Sébastien BEAU - http://www.akretion.com (sebastien.beau) wrote : | # |
Unmerged revisions
- 48. By Sébastien BEAU - http://www.akretion.com
-
[IMP] add test for attribute set synchronisation
- 47. By Sébastien BEAU - http://www.akretion.com
-
[FIX] replace fields by vals (connector 2.2 update)
- 46. By Sébastien BEAU - http://www.akretion.com
-
[FIX] fix backend view, move attribute_
set_tpl_ id just after default category - 45. By Sébastien BEAU - http://www.akretion.com
-
[REF] attribute set export skeletonSetId should be map only at creation
- 44. By Sébastien BEAU - http://www.akretion.com
-
[REF] comment product image view for now, need to be fixed
- 43. By Chafique DELLI
-
[ADD]:add module that manages the product variant's price and fix export product attributes and fix export products
(../connector-magentoconnect- catalog rev 736) - 42. By Sébastien BEAU - http://www.akretion.com
-
[IMP] add multi-lang support for exporting product and add a TODO FIXME
(../connector-magentoconnect- catalog rev 735) - 41. By Sébastien BEAU - http://www.akretion.com
-
[FIX] fix export of attrbute option, now support multi-lang, TODO fix the option sequence or add comment to understand the +1
(../connector-magentoconnect- catalog rev 734) - 40. By Sébastien BEAU - http://www.akretion.com
-
[IMP] improve view for attribute set
(../connector-magentoconnect- catalog rev 733) - 39. By Sébastien BEAU - http://www.akretion.com
-
[IMP] add the export of the translation for the category
(../connector-magentoconnect- catalog rev 731)
Preview Diff
1 | === added directory 'magentoerpconnect_catalog' |
2 | === renamed directory 'magentoerpconnect_catalog' => 'magentoerpconnect_catalog.moved' |
3 | === added file 'magentoerpconnect_catalog/__init__.py' |
4 | --- magentoerpconnect_catalog/__init__.py 1970-01-01 00:00:00 +0000 |
5 | +++ magentoerpconnect_catalog/__init__.py 2014-07-01 22:23:08 +0000 |
6 | @@ -0,0 +1,29 @@ |
7 | +# -*- coding: utf-8 -*- |
8 | +############################################################################## |
9 | +# |
10 | +# Copyright 2013 |
11 | +# Author: Guewen Baconnier - Camptocamp SA |
12 | +# Augustin Cisterne-Kaasv - Elico-corp |
13 | +# David Béal - Akretion |
14 | +# This program is free software: you can redistribute it and/or modify |
15 | +# it under the terms of the GNU Affero General Public License as |
16 | +# published by the Free Software Foundation, either version 3 of the |
17 | +# License, or (at your option) any later version. |
18 | +# |
19 | +# This program is distributed in the hope that it will be useful, |
20 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | +# GNU Affero General Public License for more details. |
23 | +# |
24 | +# You should have received a copy of the GNU Affero General Public License |
25 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
26 | +# |
27 | +############################################################################## |
28 | + |
29 | +import connector |
30 | +import consumer |
31 | +import magento_model |
32 | +import product |
33 | +import product_category |
34 | +import product_attribute |
35 | +import product_image |
36 | |
37 | === added file 'magentoerpconnect_catalog/__openerp__.py' |
38 | --- magentoerpconnect_catalog/__openerp__.py 1970-01-01 00:00:00 +0000 |
39 | +++ magentoerpconnect_catalog/__openerp__.py 2014-07-01 22:23:08 +0000 |
40 | @@ -0,0 +1,67 @@ |
41 | +# -*- coding: utf-8 -*- |
42 | +############################################################################## |
43 | +# |
44 | +# Author: Guewen Baconnier |
45 | +# Copyright 2013 Camptocamp SA |
46 | +# Copyright 2013 Akretion |
47 | +# |
48 | +# This program is free software: you can redistribute it and/or modify |
49 | +# it under the terms of the GNU Affero General Public License as |
50 | +# published by the Free Software Foundation, either version 3 of the |
51 | +# License, or (at your option) any later version. |
52 | +# |
53 | +# This program is distributed in the hope that it will be useful, |
54 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
55 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
56 | +# GNU Affero General Public License for more details. |
57 | +# |
58 | +# You should have received a copy of the GNU Affero General Public License |
59 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
60 | +# |
61 | +############################################################################## |
62 | + |
63 | + |
64 | +{'name': 'Magento Connector - Catalog', |
65 | + 'version': '2.0.0', |
66 | + 'category': 'Connector', |
67 | + 'depends': ['magentoerpconnect', |
68 | + 'product_custom_attributes', |
69 | + #'product_links', |
70 | + 'product_image', |
71 | + ], |
72 | + 'author': 'MagentoERPconnect Core Editors', |
73 | + 'license': 'AGPL-3', |
74 | + 'website': 'https://launchpad.net/magentoerpconnect', |
75 | + 'description': """ |
76 | +Magento Connector - Catalog |
77 | +=========================== |
78 | + |
79 | +Extension for **Magento Connector**, add management of the product's catalog: |
80 | + |
81 | +Export |
82 | +* products |
83 | +* categories |
84 | +* attributes (only export up to now): attribute set, attributes and attribute options : |
85 | + |
86 | + - to be used, you need to manually create an attribute set which match with magento 'Default' attribute set (generally magento_id '4') |
87 | + |
88 | +* product image: dependency |
89 | + |
90 | + - dev branch: lp:~akretion-team/openerp-product-attributes/openerp-product-attributes-image |
91 | + - future production branch: lp:openerp-product-attributes/openerp-product-attributes |
92 | + |
93 | +TODO: |
94 | +* import/export product links |
95 | +* import attributes |
96 | +""", |
97 | + 'images': [], |
98 | + 'demo': [], |
99 | + 'data': [ |
100 | + 'magento_model_view.xml', |
101 | + 'product_view.xml', |
102 | + 'product_attribute_view.xml', |
103 | + 'product_image_view.xml', |
104 | + ], |
105 | + 'installable': True, |
106 | + 'application': False, |
107 | +} |
108 | \ No newline at end of file |
109 | |
110 | === added file 'magentoerpconnect_catalog/connector.py' |
111 | --- magentoerpconnect_catalog/connector.py 1970-01-01 00:00:00 +0000 |
112 | +++ magentoerpconnect_catalog/connector.py 2014-07-01 22:23:08 +0000 |
113 | @@ -0,0 +1,26 @@ |
114 | +# -*- coding: utf-8 -*- |
115 | +############################################################################## |
116 | +# |
117 | +# Copyright 2013 |
118 | +# Author: Guewen Baconnier - Camptocamp SA |
119 | +# Augustin Cisterne-Kaasv - Elico-corp |
120 | +# David Béal - Akretion |
121 | +# This program is free software: you can redistribute it and/or modify |
122 | +# it under the terms of the GNU Affero General Public License as |
123 | +# published by the Free Software Foundation, either version 3 of the |
124 | +# License, or (at your option) any later version. |
125 | +# |
126 | +# This program is distributed in the hope that it will be useful, |
127 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
128 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
129 | +# GNU Affero General Public License for more details. |
130 | +# |
131 | +# You should have received a copy of the GNU Affero General Public License |
132 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
133 | +# |
134 | +############################################################################## |
135 | + |
136 | +from openerp.addons.connector.connector import install_in_connector |
137 | + |
138 | + |
139 | +install_in_connector() |
140 | |
141 | === added file 'magentoerpconnect_catalog/consumer.py' |
142 | --- magentoerpconnect_catalog/consumer.py 1970-01-01 00:00:00 +0000 |
143 | +++ magentoerpconnect_catalog/consumer.py 2014-07-01 22:23:08 +0000 |
144 | @@ -0,0 +1,118 @@ |
145 | +# -*- coding: utf-8 -*- |
146 | +############################################################################## |
147 | +# |
148 | +# Copyright 2013 |
149 | +# Author: Guewen Baconnier - Camptocamp SA |
150 | +# Augustin Cisterne-Kaasv - Elico-corp |
151 | +# David Béal - Akretion |
152 | +# This program is free software: you can redistribute it and/or modify |
153 | +# it under the terms of the GNU Affero General Public License as |
154 | +# published by the Free Software Foundation, either version 3 of the |
155 | +# License, or (at your option) any later version. |
156 | +# |
157 | +# This program is distributed in the hope that it will be useful, |
158 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
159 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
160 | +# GNU Affero General Public License for more details. |
161 | +# |
162 | +# You should have received a copy of the GNU Affero General Public License |
163 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
164 | +# |
165 | +############################################################################## |
166 | + |
167 | +from openerp.addons.connector.event import (on_record_write, |
168 | + on_record_create, |
169 | + on_record_unlink |
170 | + ) |
171 | + |
172 | +import openerp.addons.magentoerpconnect.consumer as magentoerpconnect |
173 | + |
174 | +from openerp.addons.connector.connector import Binder |
175 | +from openerp.addons.magentoerpconnect.connector import get_environment |
176 | +from openerp.addons.magentoerpconnect.unit.delete_synchronizer import ( |
177 | + export_delete_record) |
178 | + |
179 | + |
180 | +EXCLUDED_FIELDS_WRITING = { |
181 | + 'product.product': ['magento_bind_ids', 'image_ids'], |
182 | + 'product.category': ['magento_bind_ids',], |
183 | + 'magento.product.category': ['magento_bind_ids',], |
184 | +} |
185 | + |
186 | +def exclude_fields_from_synchro(model_name, fields): |
187 | + if fields and EXCLUDED_FIELDS_WRITING.get(model_name): |
188 | + fields = list(set(fields).difference(EXCLUDED_FIELDS_WRITING)) |
189 | + return fields |
190 | + |
191 | +@on_record_create(model_names=[ |
192 | + 'magento.product.category', |
193 | + 'magento.product.product', |
194 | + 'magento.product.attribute', |
195 | + 'magento.attribute.set', |
196 | + 'magento.attribute.option', |
197 | + 'magento.product.image', |
198 | + ]) |
199 | +@on_record_write(model_names=[ |
200 | + 'magento.product.category', |
201 | + 'magento.product.product', |
202 | + 'magento.product.attribute', |
203 | + 'magento.attribute.option', |
204 | + 'magento.product.image', |
205 | + #'magento.product.storeview', |
206 | + ]) |
207 | +def delay_export(session, model_name, record_id, vals=None): |
208 | + #fields = exclude_fields_from_synchro(model_name, fields) |
209 | + magentoerpconnect.delay_export(session, model_name, |
210 | + record_id, vals=vals) |
211 | + |
212 | + |
213 | +@on_record_write(model_names=[ |
214 | + 'product.product', |
215 | + 'product.category', |
216 | + ]) |
217 | +def delay_export_all_bindings(session, model_name, record_id, vals=None): |
218 | + #fields = exclude_fields_from_synchro(model_name, fields) |
219 | + magentoerpconnect.delay_export_all_bindings(session, model_name, |
220 | + record_id, vals=vals) |
221 | + |
222 | +# |
223 | +#@on_record_unlink(model_names=[ |
224 | +# 'product.category', |
225 | +# ]) |
226 | +#def delay_unlink_all_bindings(session, model_name, record_id): |
227 | +# #magentoerpconnect.delay_unlink_all_bindings(session, model_name, record_id) |
228 | +# import pdb;pdb.set_trace() |
229 | +# magentoerpconnect.delay_unlink(session, model_name, record_id) |
230 | + |
231 | + |
232 | +@on_record_unlink(model_names=[ |
233 | + 'magento.product.category', |
234 | + 'magento.product.product' |
235 | + 'magento.product.attribute', |
236 | + 'magento.attribute.set', |
237 | + 'magento.attribute.option', |
238 | + ]) |
239 | +def delay_unlink(session, model_name, record_id): |
240 | + magentoerpconnect.delay_unlink(session, model_name, record_id) |
241 | + |
242 | + |
243 | +@on_record_unlink(model_names=['magento.product.image']) |
244 | +def delay_image_unlink(session, model_name, record_id): |
245 | + model = session.pool.get('magento.product.image') |
246 | + record = model.browse(session.cr, session.uid, |
247 | + record_id, context=session.context) |
248 | + magento_keys = [] |
249 | + env = get_environment(session, 'magento.product.image', |
250 | + record.backend_id.id) |
251 | + binder = env.get_connector_unit(Binder) |
252 | + magento_keys.append(binder.to_backend(record_id)) |
253 | + # in addition to magento 'image id' needs 'product id' to remove images |
254 | + # see http://www.magentocommerce.com/api/soap/catalog/... |
255 | + # catalogProductAttributeMedia/catalog_product_attribute_media.remove.html |
256 | + env = get_environment(session, 'magento.product.product', |
257 | + record.backend_id.id) |
258 | + binder = env.get_connector_unit(Binder) |
259 | + magento_keys.append(binder.to_backend(record.openerp_id.product_id.id, wrap=True)) |
260 | + if magento_keys: |
261 | + export_delete_record.delay(session, 'magento.product.image', |
262 | + record.backend_id.id, magento_keys) |
263 | |
264 | === added directory 'magentoerpconnect_catalog/i18n' |
265 | === added file 'magentoerpconnect_catalog/magento_model.py' |
266 | --- magentoerpconnect_catalog/magento_model.py 1970-01-01 00:00:00 +0000 |
267 | +++ magentoerpconnect_catalog/magento_model.py 2014-07-01 22:23:08 +0000 |
268 | @@ -0,0 +1,50 @@ |
269 | +# -*- coding: utf-8 -*- |
270 | +############################################################################## |
271 | +# |
272 | +# Copyright 2013 |
273 | +# Author: Guewen Baconnier - Camptocamp |
274 | +# David Béal - Akretion |
275 | +# Sébastien Beau - Akretion |
276 | +# This program is free software: you can redistribute it and/or modify |
277 | +# it under the terms of the GNU Affero General Public License as |
278 | +# published by the Free Software Foundation, either version 3 of the |
279 | +# License, or (at your option) any later version. |
280 | +# |
281 | +# This program is distributed in the hope that it will be useful, |
282 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
283 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
284 | +# GNU Affero General Public License for more details. |
285 | +# |
286 | +# You should have received a copy of the GNU Affero General Public License |
287 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
288 | +# |
289 | +############################################################################## |
290 | + |
291 | +import logging |
292 | +from openerp.osv import orm, fields |
293 | +from openerp.addons.connector.session import ConnectorSession |
294 | +from openerp.addons.magentoerpconnect.unit.import_synchronizer import import_batch |
295 | + |
296 | + |
297 | +_logger = logging.getLogger(__name__) |
298 | + |
299 | + |
300 | +class magento_backend(orm.Model): |
301 | + _inherit = 'magento.backend' |
302 | + |
303 | + def import_attribute_sets(self, cr, uid, ids, context=None): |
304 | + if not hasattr(ids, '__iter__'): |
305 | + ids = [ids] |
306 | + self.check_magento_structure(cr, uid, ids, context=context) |
307 | + session = ConnectorSession(cr, uid, context=context) |
308 | + for backend_id in ids: |
309 | + import_batch.delay(session, 'magento.attribute.set', backend_id) |
310 | + return True |
311 | + |
312 | + _columns = { |
313 | + 'attribute_set_tpl_id': fields.many2one( |
314 | + 'magento.attribute.set', |
315 | + 'Attribute set template', |
316 | + help="Attribute set ID basing on which the new attribute set " |
317 | + "will be created."), |
318 | + } |
319 | |
320 | === added file 'magentoerpconnect_catalog/magento_model_view.xml' |
321 | --- magentoerpconnect_catalog/magento_model_view.xml 1970-01-01 00:00:00 +0000 |
322 | +++ magentoerpconnect_catalog/magento_model_view.xml 2014-07-01 22:23:08 +0000 |
323 | @@ -0,0 +1,26 @@ |
324 | +<?xml version="1.0" encoding="utf-8"?> |
325 | +<openerp> |
326 | + <data> |
327 | + |
328 | +<record id="view_magento_backend_form" model="ir.ui.view"> |
329 | + <field name="model">magento.backend</field> |
330 | + <field name="inherit_id" ref="magentoerpconnect.view_magento_backend_form"/> |
331 | + <field name="arch" type="xml"> |
332 | + <xpath expr="//notebook/page[@name='import']/group[5]" position="after"> |
333 | + <group> |
334 | + <label string="Import attribute sets" |
335 | + class="oe_inline"/> |
336 | + <button name="import_attribute_sets" |
337 | + type="object" |
338 | + class="oe_highlight" |
339 | + string="Import in background"/> |
340 | + </group> |
341 | + </xpath> |
342 | + <xpath expr="//notebook/page[@name='advanced_configuration']/group/field[@name='default_category_id']" position="after"> |
343 | + <field name="attribute_set_tpl_id"/> |
344 | + </xpath> |
345 | + </field> |
346 | +</record> |
347 | + |
348 | + </data> |
349 | +</openerp> |
350 | |
351 | === added file 'magentoerpconnect_catalog/product.py' |
352 | --- magentoerpconnect_catalog/product.py 1970-01-01 00:00:00 +0000 |
353 | +++ magentoerpconnect_catalog/product.py 2014-07-01 22:23:08 +0000 |
354 | @@ -0,0 +1,185 @@ |
355 | +# -*- coding: utf-8 -*- |
356 | +############################################################################## |
357 | +# |
358 | +# Copyright 2013 |
359 | +# Author: Guewen Baconnier - Camptocamp SA |
360 | +# Augustin Cisterne-Kaasv - Elico-corp |
361 | +# David Béal - Akretion |
362 | +# This program is free software: you can redistribute it and/or modify |
363 | +# it under the terms of the GNU Affero General Public License as |
364 | +# published by the Free Software Foundation, either version 3 of the |
365 | +# License, or (at your option) any later version. |
366 | +# |
367 | +# This program is distributed in the hope that it will be useful, |
368 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
369 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
370 | +# GNU Affero General Public License for more details. |
371 | +# |
372 | +# You should have received a copy of the GNU Affero General Public License |
373 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
374 | +# |
375 | +############################################################################## |
376 | + |
377 | +from openerp.osv import fields, orm, osv |
378 | +from openerp.addons.connector.queue.job import job |
379 | +from openerp.addons.connector.unit.mapper import (mapping, |
380 | + changed_by, |
381 | + ExportMapper) |
382 | +from openerp.addons.magentoerpconnect.unit.delete_synchronizer import ( |
383 | + MagentoDeleteSynchronizer) |
384 | +from openerp.addons.magentoerpconnect.unit.export_synchronizer import ( |
385 | + MagentoTranslationExporter) |
386 | +from openerp.addons.magentoerpconnect.backend import magento |
387 | +from openerp.addons.magentoerpconnect.product import ProductProductAdapter |
388 | +from openerp.addons.connector.exception import MappingError |
389 | +from openerp.addons.magentoerpconnect.unit.export_synchronizer import ( |
390 | + export_record |
391 | +) |
392 | + |
393 | + |
394 | +@magento |
395 | +class ProductProductDeleteSynchronizer(MagentoDeleteSynchronizer): |
396 | + """ Partner deleter for Magento """ |
397 | + _model_name = ['magento.product.product'] |
398 | + |
399 | + |
400 | +@magento |
401 | +class ProductProductExport(MagentoTranslationExporter): |
402 | + _model_name = ['magento.product.product'] |
403 | + |
404 | + def _export_dependencies(self): |
405 | + """ Export the dependencies for the product""" |
406 | + #TODO add export of category |
407 | + attribute_binder = self.get_binder_for_model('magento.product.attribute') |
408 | + option_binder = self.get_binder_for_model('magento.attribute.option') |
409 | + record = self.binding_record |
410 | + for group in record.attribute_group_ids: |
411 | + for attribute in group.attribute_ids: |
412 | + attribute_ext_id = attribute_binder.to_backend(attribute.attribute_id.id, wrap=True) |
413 | + if attribute_ext_id: |
414 | + options = [] |
415 | + if attribute.ttype == 'many2one' and record[attribute.name]: |
416 | + options = [record[attribute.name]] |
417 | + elif attribute.ttype == 'many2many': |
418 | + options = record[attribute.name] |
419 | + for option in options: |
420 | + if not option_binder.to_backend(option.id, wrap=True): |
421 | + ctx = self.session.context.copy() |
422 | + ctx['connector_no_export'] = True |
423 | + binding_id = self.session.pool['magento.attribute.option'].create( |
424 | + self.session.cr, self.session.uid,{ |
425 | + 'backend_id': self.backend_record.id, |
426 | + 'openerp_id': option.id, |
427 | + 'name': option.name, |
428 | + }, context=ctx) |
429 | + export_record(self.session, 'magento.attribute.option', binding_id) |
430 | + |
431 | + |
432 | +@magento |
433 | +class ProductProductExportMapper(ExportMapper): |
434 | + _model_name = 'magento.product.product' |
435 | + |
436 | + #TODO FIXME |
437 | + # direct = [('name', 'name'), |
438 | + # ('description', 'description'), |
439 | + # ('weight', 'weight'), |
440 | + # ('list_price', 'price'), |
441 | + # ('description_sale', 'short_description'), |
442 | + # ('default_code', 'sku'), |
443 | + # ('product_type', 'type'), |
444 | + # ('created_at', 'created_at'), |
445 | + # ('updated_at', 'updated_at'), |
446 | + # ('status', 'status'), |
447 | + # ('visibility', 'visibility'), |
448 | + # ('product_type', 'product_type') |
449 | + # ] |
450 | + @mapping |
451 | + def all(self, record): |
452 | + return {'name': record.name, |
453 | + 'description': record.description, |
454 | + 'weight': record.weight, |
455 | + 'price': record.list_price, |
456 | + 'short_description': record.description_sale, |
457 | + 'type': record.product_type, |
458 | + 'created_at': record.created_at, |
459 | + #'updated_at': record.updated_at, |
460 | + 'status': record.status, |
461 | + 'visibility': record.visibility, |
462 | + 'product_type': record.product_type } |
463 | + |
464 | + @mapping |
465 | + def sku(self, record): |
466 | + sku = record.default_code |
467 | + if not sku: |
468 | + raise MappingError("The product attribute default code cannot be empty.") |
469 | + return {'sku': sku} |
470 | + |
471 | + @mapping |
472 | + def set(self, record): |
473 | + binder = self.get_binder_for_model('magento.attribute.set') |
474 | + set_id = binder.to_backend(record.attribute_set_id.id, wrap=True) |
475 | + return {'attrset': set_id} |
476 | + |
477 | + @mapping |
478 | + def updated_at(self, record): |
479 | + updated_at = record.updated_at |
480 | + if not updated_at: |
481 | + updated_at = '1970-01-01' |
482 | + return {'updated_at': updated_at} |
483 | + |
484 | + @mapping |
485 | + def website_ids(self, record): |
486 | + website_ids = [] |
487 | + for website_id in record.website_ids: |
488 | + magento_id = website_id.magento_id |
489 | + website_ids.append(magento_id) |
490 | + return {'website_ids': website_ids} |
491 | + |
492 | + @mapping |
493 | + def category(self, record): |
494 | + categ_ids = [] |
495 | + if record.categ_id: |
496 | + for m_categ in record.categ_id.magento_bind_ids: |
497 | + if m_categ.backend_id.id == self.backend_record.id: |
498 | + categ_ids.append(m_categ.magento_id) |
499 | + |
500 | + for categ in record.categ_ids: |
501 | + for m_categ in categ.magento_bind_ids: |
502 | + if m_categ.backend_id.id == self.backend_record.id: |
503 | + categ_ids.append(m_categ.magento_id) |
504 | + return {'categories': categ_ids} |
505 | + |
506 | + @mapping |
507 | + def get_product_attribute_option(self, record): |
508 | + result = {} |
509 | + attribute_binder = self.get_binder_for_model('magento.product.attribute') |
510 | + option_binder = self.get_binder_for_model('magento.attribute.option') |
511 | + for group in record.attribute_group_ids: |
512 | + for attribute in group.attribute_ids: |
513 | + magento_attribute = None |
514 | + #TODO maybe adding a get_bind function can be better |
515 | + for bind in attribute.magento_bind_ids: |
516 | + if bind.backend_id.id == self.backend_record.id: |
517 | + magento_attribute = bind |
518 | + |
519 | + if not magento_attribute: |
520 | + continue |
521 | + |
522 | + if attribute.ttype == 'many2one': |
523 | + option = record[attribute.name] |
524 | + if option: |
525 | + result[magento_attribute.attribute_code] = \ |
526 | + option_binder.to_backend(option.id, wrap=True) |
527 | + else: |
528 | + continue |
529 | + elif attribute.ttype == 'many2many': |
530 | + options = record[attribute.name] |
531 | + if options: |
532 | + result[magento_attribute.attribute_code] = \ |
533 | + [option_binder.to_backend(option.id, wrap=True) for option in options] |
534 | + else: |
535 | + continue |
536 | + else: |
537 | + #TODO add support of lang |
538 | + result[magento_attribute.attribute_code] = record[attribute.name] |
539 | + return result |
540 | |
541 | === added file 'magentoerpconnect_catalog/product_attribute.py' |
542 | --- magentoerpconnect_catalog/product_attribute.py 1970-01-01 00:00:00 +0000 |
543 | +++ magentoerpconnect_catalog/product_attribute.py 2014-07-01 22:23:08 +0000 |
544 | @@ -0,0 +1,527 @@ |
545 | +# -*- coding: utf-8 -*- |
546 | +############################################################################## |
547 | +# |
548 | +# Copyright 2013 |
549 | +# Author: Guewen Baconnier - Camptocamp |
550 | +# Augustin Cisterne-Kaas - Elico-corp |
551 | +# David Béal - Akretion |
552 | +# Sébastien Beau - Akretion |
553 | +# Chafique Delli - Akretion |
554 | +# This program is free software: you can redistribute it and/or modify |
555 | +# it under the terms of the GNU Affero General Public License as |
556 | +# published by the Free Software Foundation, either version 3 of the |
557 | +# License, or (at your option) any later version. |
558 | +# |
559 | +# This program is distributed in the hope that it will be useful, |
560 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
561 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
562 | +# GNU Affero General Public License for more details. |
563 | +# |
564 | +# You should have received a copy of the GNU Affero General Public License |
565 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
566 | +# |
567 | +############################################################################## |
568 | + |
569 | + |
570 | +from openerp.osv import fields, orm |
571 | +#from openerp.tools.translate import _ |
572 | +from openerp.osv.osv import except_osv |
573 | +from openerp.addons.connector.unit.mapper import ( |
574 | + mapping, |
575 | + #changed_by, |
576 | + only_create, |
577 | + ImportMapper, |
578 | + ExportMapper,) |
579 | +#from openerp.addons.connector.exception import MappingError |
580 | +from openerp.addons.magentoerpconnect.backend import magento |
581 | +from openerp.addons.magentoerpconnect.unit.backend_adapter import GenericAdapter |
582 | +from openerp.addons.magentoerpconnect.unit.binder import MagentoModelBinder |
583 | +from openerp.addons.magentoerpconnect.unit.delete_synchronizer import ( |
584 | + MagentoDeleteSynchronizer) |
585 | +from openerp.addons.magentoerpconnect.unit.export_synchronizer import ( |
586 | + MagentoExporter) |
587 | +from openerp.addons.magentoerpconnect.unit.import_synchronizer import ( |
588 | + DelayedBatchImport, |
589 | + MagentoImportSynchronizer,) |
590 | +from openerp.addons.connector.exception import FailedJobError |
591 | + |
592 | + |
593 | +@magento(replacing=MagentoModelBinder) |
594 | +class MagentoAttributeBinder(MagentoModelBinder): |
595 | + _model_name = [ |
596 | + 'magento.product.attribute', |
597 | + 'magento.attribute.option', |
598 | + 'magento.attribute.set', |
599 | + ] |
600 | + |
601 | + |
602 | +# Attribute Set |
603 | +class AttributeSet(orm.Model): |
604 | + _inherit = 'attribute.set' |
605 | + |
606 | + _columns = { |
607 | + 'magento_bind_ids': fields.one2many( |
608 | + 'magento.attribute.set', |
609 | + 'openerp_id', |
610 | + string='Magento Bindings',), |
611 | + } |
612 | + |
613 | + |
614 | +class MagentoAttributeSet(orm.Model): |
615 | + _name = 'magento.attribute.set' |
616 | + _description = "Magento attribute set" |
617 | + _inherit = 'magento.binding' |
618 | + _rec_name = 'attribute_set_name' |
619 | + |
620 | + _columns = { |
621 | + 'openerp_id': fields.many2one( |
622 | + 'attribute.set', |
623 | + string='Attribute set', |
624 | + ondelete='cascade'), |
625 | + 'attribute_set_name': fields.char( |
626 | + 'Name', |
627 | + size=64, |
628 | + required=True), |
629 | + 'sort_order': fields.integer( |
630 | + 'Sort order', |
631 | + readonly=True), |
632 | + } |
633 | + |
634 | + def name_get(self, cr, uid, ids, context=None): |
635 | + res = [] |
636 | + for elm in self.read(cr, uid, ids, ['attribute_set_name'], |
637 | + context=context): |
638 | + res.append((elm['id'], elm['attribute_set_name'])) |
639 | + return res |
640 | + |
641 | + _sql_constraints = [ |
642 | + ('magento_uniq', 'unique(backend_id, openerp_id)', |
643 | + "An 'Attribute set' with the same ID on this Magento backend " |
644 | + "already exists") |
645 | + ] |
646 | + |
647 | + |
648 | +@magento |
649 | +class AttributeSetAdapter(GenericAdapter): |
650 | + _model_name = 'magento.attribute.set' |
651 | + _magento_default_model = 'product_attribute_set' |
652 | + _magento_model = 'ol_catalog_product_attributeset' |
653 | + |
654 | + def create(self, data): |
655 | + """ Create a record on the external system """ |
656 | + return self._call('%s.create' % self._magento_default_model, |
657 | + [data['attribute_set_name'], data['skeletonSetId']]) |
658 | + |
659 | + def delete(self, id): |
660 | + """ Delete a record on the external system """ |
661 | + return self._call('%s.remove' % self._magento_default_model, [str(id)]) |
662 | + |
663 | + def search(self, filters=None): |
664 | + """ Search records according and returns a list of ids |
665 | + :rtype: list |
666 | + """ |
667 | + return self._call('%s.search' % self._magento_model, []) |
668 | + |
669 | + def read(self, id, storeview_id=None, attributes=None): |
670 | + """ Returns the information of a record |
671 | + :rtype: dict |
672 | + """ |
673 | + return self._call('%s.info' % self._magento_model, [int(id)]) |
674 | + |
675 | + def update(self, id, attribute_id): |
676 | + """ Add an existing attribute to an attribute set on the external system |
677 | + :rtype: boolean |
678 | + """ |
679 | + return self._call('%s.attributeAdd' % self._magento_default_model, |
680 | + [str(attribute_id),str(id)]) |
681 | + |
682 | + |
683 | +@magento |
684 | +class AttributeSetDelayedBatchImport(DelayedBatchImport): |
685 | + _model_name = ['magento.attribute.set'] |
686 | + |
687 | + |
688 | +@magento |
689 | +class AttributeSetImport(MagentoImportSynchronizer): |
690 | + _model_name = ['magento.attribute.set'] |
691 | + |
692 | + |
693 | +@magento |
694 | +class AttributeSetImportMapper(ImportMapper): |
695 | + _model_name = 'magento.attribute.set' |
696 | + |
697 | + direct = [ |
698 | + ('attribute_set_name', 'attribute_set_name'), |
699 | + ('attribute_set_id', 'magento_id'), |
700 | + ('sort_order', 'sort_order'), ] |
701 | + |
702 | + @mapping |
703 | + def backend_id(self, record): |
704 | + return {'backend_id': self.backend_record.id} |
705 | + |
706 | + |
707 | +@magento |
708 | +class AttributeSetDeleteSynchronizer(MagentoDeleteSynchronizer): |
709 | + _model_name = ['magento.attribute.set'] |
710 | + |
711 | + |
712 | +@magento |
713 | +class AttributeSetExport(MagentoExporter): |
714 | + _model_name = ['magento.attribute.set'] |
715 | + |
716 | + |
717 | +@magento |
718 | +class AttributeSetExportMapper(ExportMapper): |
719 | + _model_name = 'magento.attribute.set' |
720 | + |
721 | + direct = [ |
722 | + ('attribute_set_name', 'attribute_set_name'), |
723 | + ('sort_order', 'sort_order'), |
724 | + ] |
725 | + |
726 | + @only_create |
727 | + @mapping |
728 | + def skeletonSetId(self, record): |
729 | + tmpl_set_id = self.backend_record.attribute_set_tpl_id.id |
730 | + if tmpl_set_id: |
731 | + binder = self.get_binder_for_model('magento.attribute.set') |
732 | + magento_tpl_set_id = binder.to_backend(tmpl_set_id) |
733 | + else: |
734 | + raise FailedJobError(( |
735 | + "'Attribute set template' field must be define on " |
736 | + "the backend.\n\n" |
737 | + "Resolution: \n" |
738 | + "- Go to Connectors > Magento > Backends > '%s'\n" |
739 | + "- Fill the field Attribte set Tempalte\n" |
740 | + )% self.backend_record.name) |
741 | + return {'skeletonSetId': magento_tpl_set_id} |
742 | + |
743 | + |
744 | +# Attribute |
745 | +class AttributeAttribute(orm.Model): |
746 | + _inherit = 'attribute.attribute' |
747 | + |
748 | + def _get_model_product(self, cr, uid, ids, idcontext=None): |
749 | + model, res_id = self.pool['ir.model.data'].get_object_reference( |
750 | + cr, uid, 'product', 'model_product_product') |
751 | + return res_id |
752 | + |
753 | + _columns = { |
754 | + 'magento_bind_ids': fields.one2many( |
755 | + 'magento.product.attribute', |
756 | + 'openerp_id', |
757 | + string='Magento Bindings',), |
758 | + } |
759 | + |
760 | + _defaults = { |
761 | + 'model_id': _get_model_product, |
762 | + } |
763 | + |
764 | + |
765 | +class MagentoProductAttribute(orm.Model): |
766 | + _name = 'magento.product.attribute' |
767 | + _description = "Magento Product Attribute" |
768 | + _inherit = 'magento.binding' |
769 | + _rec_name = 'attribute_code' |
770 | + MAGENTO_HELP = "This field is a technical / configuration field for " \ |
771 | + "the attribute on Magento. \nPlease refer to the Magento " \ |
772 | + "documentation for details. " |
773 | + |
774 | + def copy(self, cr, uid, id, default=None, context=None): |
775 | + if default is None: |
776 | + default = {} |
777 | + default['attribute_code'] = default.get('attribute_code', '') + 'Copy ' |
778 | + return super(MagentoProductAttribute, self).copy( |
779 | + cr, uid, id, default, context=context) |
780 | + |
781 | + def _frontend_input(self, cr, uid, ids, field_names, arg, context=None): |
782 | + res={} |
783 | + for elm in self.browse(cr, uid, ids): |
784 | + field_type = elm.openerp_id.attribute_type |
785 | + map_type = { |
786 | + 'char': 'text', |
787 | + 'text': 'textarea', |
788 | + 'float': 'price', |
789 | + 'datetime': 'date', |
790 | + 'binary': 'media_image', |
791 | + } |
792 | + res[elm.id] = map_type.get(field_type, field_type) |
793 | + return res |
794 | + |
795 | + _columns = { |
796 | + 'openerp_id': fields.many2one( |
797 | + 'attribute.attribute', |
798 | + string='Attribute', |
799 | + required=True, |
800 | + ondelete='cascade'), |
801 | + 'attribute_code': fields.char( |
802 | + 'Code', |
803 | + required=True, |
804 | + size=200,), |
805 | + 'scope': fields.selection( |
806 | + [('store', 'store'), ('website', 'website'), ('global', 'global')], |
807 | + 'Scope', |
808 | + required=True, |
809 | + help=MAGENTO_HELP), |
810 | + 'apply_to': fields.selection([ |
811 | + ('simple', 'simple'), |
812 | + ], |
813 | + 'Apply to', |
814 | + required=True, |
815 | + help=MAGENTO_HELP), |
816 | + 'frontend_input': fields.function( |
817 | + _frontend_input, |
818 | + method=True, |
819 | + string='Frontend input', |
820 | + type='char', |
821 | + store=False, |
822 | + help="This field depends on OpenERP attribute 'type' field " |
823 | + "but used on Magento"), |
824 | + 'frontend_label': fields.char( |
825 | + 'Label', required=True, size=100, help=MAGENTO_HELP), |
826 | + 'position': fields.integer('Position', help=MAGENTO_HELP), |
827 | + 'group_id': fields.integer('Group', help=MAGENTO_HELP) , |
828 | + 'default_value': fields.char( |
829 | + 'Default Value', |
830 | + size=10, |
831 | + help=MAGENTO_HELP), |
832 | + 'note': fields.char( |
833 | + 'Note', size=200, help=MAGENTO_HELP), |
834 | + 'entity_type_id': fields.integer( |
835 | + 'Entity Type', help=MAGENTO_HELP), |
836 | + # boolean fields |
837 | + 'is_visible_in_advanced_search': fields.boolean( |
838 | + 'Visible in advanced search?', help=MAGENTO_HELP), |
839 | + 'is_visible': fields.boolean('Visible?', help=MAGENTO_HELP), |
840 | + 'is_visible_on_front': fields.boolean( |
841 | + 'Visible (front)?', help=MAGENTO_HELP), |
842 | + 'is_html_allowed_on_front': fields.boolean( |
843 | + 'Html (front)?', help=MAGENTO_HELP), |
844 | + 'is_wysiwyg_enabled': fields.boolean( |
845 | + 'Wysiwyg enabled?', help=MAGENTO_HELP), |
846 | + 'is_global': fields.boolean('Global?', help=MAGENTO_HELP), |
847 | + 'is_unique': fields.boolean('Unique?', help=MAGENTO_HELP), |
848 | + 'is_required': fields.boolean('Required?', help=MAGENTO_HELP), |
849 | + 'is_filterable': fields.boolean('Filterable?', help=MAGENTO_HELP), |
850 | + 'is_comparable': fields.boolean('Comparable?', help=MAGENTO_HELP), |
851 | + 'is_searchable': fields.boolean('Searchable ?', help=MAGENTO_HELP), |
852 | + 'is_configurable': fields.boolean('Configurable?', help=MAGENTO_HELP), |
853 | + 'is_user_defined': fields.boolean('User defined?', help=MAGENTO_HELP), |
854 | + 'used_for_sort_by': fields.boolean('Use for sort?', help=MAGENTO_HELP), |
855 | + 'is_used_for_price_rules': fields.boolean( |
856 | + 'Used for pricing rules?', help=MAGENTO_HELP), |
857 | + 'is_used_for_promo_rules': fields.boolean( |
858 | + 'Use for promo?', help=MAGENTO_HELP), |
859 | + 'used_in_product_listing': fields.boolean( |
860 | + 'In product listing?', help=MAGENTO_HELP), |
861 | + } |
862 | + |
863 | + _defaults = { |
864 | + 'scope': 'global', |
865 | + 'apply_to': 'simple', |
866 | + 'is_visible': True, |
867 | + 'is_visible_on_front': True, |
868 | + 'is_visible_in_advanced_search': True, |
869 | + 'is_filterable': True, |
870 | + 'is_searchable': True, |
871 | + 'is_comparable': True, |
872 | + } |
873 | + |
874 | + _sql_constraints = [ |
875 | + ('magento_uniq', 'unique(attribute_code)', |
876 | + "Attribute with the same code already exists : must be unique"), |
877 | + ('openerp_uniq', 'unique(backend_id, openerp_id)', |
878 | + 'An attribute can not be bound to several records on the same backend.'), |
879 | + ] |
880 | + |
881 | + |
882 | +@magento |
883 | +class ProductAttributeAdapter(GenericAdapter): |
884 | + _model_name = 'magento.product.attribute' |
885 | + _magento_model = 'product_attribute' |
886 | + |
887 | + def delete(self, id): |
888 | + return self._call('%s.remove'% self._magento_model,[int(id)]) |
889 | + |
890 | + |
891 | +@magento |
892 | +class ProductAttributeDeleteSynchronizer(MagentoDeleteSynchronizer): |
893 | + _model_name = ['magento.product.attribute'] |
894 | + |
895 | + |
896 | +@magento |
897 | +class ProductAttributeExport(MagentoExporter): |
898 | + _model_name = ['magento.product.attribute'] |
899 | + |
900 | + def _should_import(self): |
901 | + "Attributes in magento doesn't retrieve infos on dates" |
902 | + return False |
903 | + |
904 | + def _after_export(self): |
905 | + """ Run the after export""" |
906 | + sess = self.session |
907 | + attribute_location_obj = sess.pool.get('attribute.location') |
908 | + magento_attribute_obj = sess.pool.get('magento.product.attribute') |
909 | + magento_attribute_set_obj = sess.pool.get('magento.attribute.set') |
910 | + attribute_set_adapter = self.get_connector_unit_for_model( |
911 | + GenericAdapter, 'magento.attribute.set') |
912 | + attribute_id = self.binding_record.openerp_id.id |
913 | + magento_attribute_id = magento_attribute_obj.browse( |
914 | + sess.cr, sess.uid, |
915 | + self.binding_record.id,context=sess.context).magento_id |
916 | + attribute_location_ids = attribute_location_obj.search( |
917 | + sess.cr, sess.uid, |
918 | + [['attribute_id','=',attribute_id]], context=sess.context) |
919 | + for attribute_location in attribute_location_ids: |
920 | + attribute_set_id = attribute_location_obj.browse( |
921 | + sess.cr, sess.uid, |
922 | + attribute_location, context=sess.context).attribute_set_id.id |
923 | + magento_attribute_set_ids = magento_attribute_set_obj.search( |
924 | + sess.cr, sess.uid, |
925 | + [['openerp_id','=',attribute_set_id]], |
926 | + context=sess.context) |
927 | + for magento_attribute_set in magento_attribute_set_ids: |
928 | + magento_attribute_set_id = magento_attribute_set_obj.browse( |
929 | + sess.cr, sess.uid, |
930 | + magento_attribute_set,context=sess.context).magento_id |
931 | + attribute_set_adapter.update( |
932 | + magento_attribute_set_id, magento_attribute_id) |
933 | + |
934 | + |
935 | + |
936 | +@magento |
937 | +class ProductAttributeExportMapper(ExportMapper): |
938 | + _model_name = 'magento.product.attribute' |
939 | + |
940 | + direct = [ |
941 | + ('attribute_code', 'attribute_code'), # required |
942 | + ('frontend_input', 'frontend_input'), |
943 | + ('scope', 'scope'), |
944 | + ('is_global', 'is_global'), |
945 | + ('is_filterable', 'is_filterable'), |
946 | + ('is_comparable', 'is_comparable'), |
947 | + ('is_visible', 'is_visible'), |
948 | + ('is_searchable', 'is_searchable'), |
949 | + ('is_user_defined', 'is_user_defined'), |
950 | + ('is_configurable', 'is_configurable'), |
951 | + ('is_visible_on_front', 'is_visible_on_front'), |
952 | + ('is_used_for_price_rules', 'is_used_for_price_rules'), |
953 | + ('is_unique', 'is_unique'), |
954 | + ('is_required', 'is_required'), |
955 | + ('position', 'position'), |
956 | + ('group_id', 'group_id'), |
957 | + ('default_value', 'default_value'), |
958 | + ('is_visible_in_advanced_search', 'is_visible_in_advanced_search'), |
959 | + ('note', 'note'), |
960 | + ('entity_type_id', 'entity_type_id'), |
961 | + ] |
962 | + |
963 | + @mapping |
964 | + def frontend_label(self, record): |
965 | + #required |
966 | + return {'frontend_label': [{ |
967 | + 'store_id': 0, |
968 | + 'label': record.frontend_label, |
969 | + }]} |
970 | + |
971 | + |
972 | +# Attribute option |
973 | +class AttributeOption(orm.Model): |
974 | + _inherit = 'attribute.option' |
975 | + |
976 | + _columns = { |
977 | + 'magento_bind_ids': fields.one2many( |
978 | + 'magento.attribute.option', |
979 | + 'openerp_id', |
980 | + string='Magento Bindings',), |
981 | + } |
982 | + |
983 | + |
984 | +class MagentoAttributeOption(orm.Model): |
985 | + _name = 'magento.attribute.option' |
986 | + _description = "" |
987 | + _inherit = 'magento.binding' |
988 | + |
989 | + _columns = { |
990 | + 'openerp_id': fields.many2one( |
991 | + 'attribute.option', |
992 | + string='Attribute option', |
993 | + required=True, |
994 | + ondelete='cascade'), |
995 | + 'name': fields.char( |
996 | + 'Name', |
997 | + size=64, |
998 | + required=True), |
999 | + 'is_default': fields.boolean('Is default'), |
1000 | + } |
1001 | + |
1002 | + _defaults = { |
1003 | + 'is_default': True, |
1004 | + } |
1005 | + |
1006 | + _sql_constraints = [ |
1007 | + ('magento_uniq', 'unique(backend_id, magento_id)', |
1008 | + 'An attribute option with the same ID on Magento already exists.'), |
1009 | + ('openerp_uniq', 'unique(backend_id, openerp_id)', |
1010 | + 'An attribute option can not be bound to several records on the same backend.'), |
1011 | + ] |
1012 | + |
1013 | + |
1014 | + |
1015 | +@magento |
1016 | +class AttributeOptionAdapter(GenericAdapter): |
1017 | + _model_name = 'magento.attribute.option' |
1018 | + _magento_model = 'oerp_product_attribute' |
1019 | + |
1020 | + def create(self, data): |
1021 | + return self._call('%s.addOption'% self._magento_model, |
1022 | + [data.pop('attribute'), data]) |
1023 | + |
1024 | + |
1025 | +@magento |
1026 | +class AttributeOptionDeleteSynchronizer(MagentoDeleteSynchronizer): |
1027 | + _model_name = ['magento.attribute.option'] |
1028 | + |
1029 | + |
1030 | +@magento |
1031 | +class AttributeOptionExport(MagentoExporter): |
1032 | + _model_name = ['magento.attribute.option'] |
1033 | + |
1034 | + |
1035 | +@magento |
1036 | +class AttributeOptionExportMapper(ExportMapper): |
1037 | + _model_name = 'magento.attribute.option' |
1038 | + |
1039 | + direct = [] |
1040 | + |
1041 | + @mapping |
1042 | + def label(self, record): |
1043 | + storeview_ids = self.session.search( |
1044 | + 'magento.storeview', |
1045 | + [('backend_id', '=', self.backend_record.id)]) |
1046 | + storeviews = self.session.browse('magento.storeview', storeview_ids) |
1047 | + label = [] |
1048 | + for storeview in storeviews: |
1049 | + name = record.openerp_id.read(['name'], context={ |
1050 | + 'lang': storeview.lang_id.code, |
1051 | + })[0]['name'] |
1052 | + label.append({ |
1053 | + 'store_id': [storeview.magento_id], |
1054 | + 'value': name |
1055 | + }) |
1056 | + return {'label': label} |
1057 | + |
1058 | + @mapping |
1059 | + def attribute(self, record): |
1060 | + binder = self.get_binder_for_model('magento.product.attribute') |
1061 | + magento_attribute_id = binder.to_backend(record.openerp_id.attribute_id.id, wrap=True) |
1062 | + return {'attribute': magento_attribute_id} |
1063 | + |
1064 | + @mapping |
1065 | + def order(self, record): |
1066 | + #TODO FIXME |
1067 | + return {'order': record.openerp_id.sequence + 1 } |
1068 | + |
1069 | + @mapping |
1070 | + def is_default(self, record): |
1071 | + return {'is_default': int(record.is_default)} |
1072 | |
1073 | === added file 'magentoerpconnect_catalog/product_attribute_view.xml' |
1074 | --- magentoerpconnect_catalog/product_attribute_view.xml 1970-01-01 00:00:00 +0000 |
1075 | +++ magentoerpconnect_catalog/product_attribute_view.xml 2014-07-01 22:23:08 +0000 |
1076 | @@ -0,0 +1,231 @@ |
1077 | +<?xml version="1.0" encoding="UTF-8"?> |
1078 | +<openerp> |
1079 | + <data> |
1080 | + |
1081 | +<!-- Attribute--> |
1082 | +<record id="attribute_attribute_form_view" model="ir.ui.view"> |
1083 | + <field name="model">attribute.attribute</field> |
1084 | + <field name="inherit_id" |
1085 | + ref="base_custom_attributes.attribute_attribute_form_view"/> |
1086 | + <field name="arch" type="xml"> |
1087 | + <xpath expr="//group" position="after"> |
1088 | + <group colspan="4"> |
1089 | + <separator string="Magento attributes"/> |
1090 | + <field name="magento_bind_ids" nolabel="1" colspan="6" |
1091 | + context="{ |
1092 | + 'hide_openerp_id': True, |
1093 | + 'default_frontend_label': field_description, |
1094 | + 'default_attribute_code': name}"> |
1095 | + <tree name="magento"> |
1096 | + <field name="attribute_code"/> |
1097 | + <field name="backend_id"/> |
1098 | + <field name="is_required"/> |
1099 | + <field name="default_value" string="Default"/> |
1100 | + <field name="scope"/> |
1101 | + </tree> |
1102 | + </field> |
1103 | + </group> |
1104 | + </xpath> |
1105 | + </field> |
1106 | +</record> |
1107 | + |
1108 | +<record id="attribute_set_form_view" model="ir.ui.view"> |
1109 | + <field name="model">attribute.set</field> |
1110 | + <field name="inherit_id" |
1111 | + ref="base_custom_attributes.attribute_set_form_view"/> |
1112 | + <field name="arch" type="xml"> |
1113 | + <form string="Attribute Set" position="inside"> |
1114 | + <separator string="Magento attribute sets" colspan="6"/> |
1115 | + <field name="magento_bind_ids" nolabel="1" colspan="6" |
1116 | + context="{'default_attribute_set_name': name}"> |
1117 | + <tree string="Attribute set" editable="top"> |
1118 | + <field name="backend_id"/> |
1119 | + <field name="attribute_set_name"/> |
1120 | + <field name="sort_order"/> |
1121 | + <field name="magento_id" readonly="1"/> |
1122 | + </tree> |
1123 | + </field> |
1124 | + </form> |
1125 | + </field> |
1126 | +</record> |
1127 | + |
1128 | + |
1129 | +<menuitem id="menu_magento_product_attribute_main" |
1130 | + name="Attributes" |
1131 | + parent="magentoerpconnect.menu_magento_root" |
1132 | + sequence="40" /> |
1133 | + |
1134 | + |
1135 | + |
1136 | +<!--Magento attribute--> |
1137 | +<record id="magento_product_attribute_tree_view" model="ir.ui.view"> |
1138 | + <field name="model">magento.product.attribute</field> |
1139 | + <field name="arch" type="xml"> |
1140 | + <tree string="Attribute"> |
1141 | + <field name="openerp_id"/> |
1142 | + <field name="attribute_code"/> |
1143 | + <field name="backend_id"/> |
1144 | + </tree> |
1145 | + </field> |
1146 | +</record> |
1147 | + |
1148 | +<record id="magento_product_attribute_action" model="ir.actions.act_window"> |
1149 | + <field name="type">ir.actions.act_window</field> |
1150 | + <field name="res_model">magento.product.attribute</field> |
1151 | + <field name="view_type">form</field> |
1152 | + <field name="name">Magento attribute</field> |
1153 | + <field name="view_id" ref="magento_product_attribute_tree_view"/> |
1154 | + <field name="help" type="html"> |
1155 | + <p class="oe_view_nocontent_create"> |
1156 | + Click to add an attribute. |
1157 | + </p> |
1158 | + </field> |
1159 | +</record> |
1160 | + |
1161 | +<menuitem id="menu_magento_product_attribute" |
1162 | + name="Attributes" |
1163 | + action="magento_product_attribute_action" |
1164 | + parent="menu_magento_product_attribute_main" |
1165 | + sequence="10"/> |
1166 | + |
1167 | + |
1168 | +<record id="magento_product_attribute_form_view" model="ir.ui.view"> |
1169 | + <field name="model">magento.product.attribute</field> |
1170 | + <field name="arch" type="xml"> |
1171 | + <form string="main" version="7.0"> |
1172 | + <group name="main" col="4"> |
1173 | + <field name="frontend_label"/> |
1174 | + <field name="attribute_code" |
1175 | + attributes="{'readonly': [('magento_id', '!=', False)]}"/> |
1176 | + <field name="backend_id" string="Backend"/> |
1177 | + <field name="scope"/> |
1178 | + <field name="frontend_input"/> |
1179 | + <!-- TODO FIXME <field name="openerp_id" |
1180 | + invisible="context.get('hide_openerp_id')"/>--> |
1181 | + </group> |
1182 | + <group name="other" col="4"> |
1183 | + <field name="default_value" |
1184 | + attrs="{'invisible':[('frontend_input', 'in', |
1185 | + ['media_image', 'multiselect'])]}"/> |
1186 | + <field name="entity_type_id"/> |
1187 | + <field name="group_id"/> |
1188 | + <field name="apply_to"/> |
1189 | + <field name="position"/> |
1190 | + <field name="note"/> |
1191 | + </group> |
1192 | + <separator/> |
1193 | + <group name="boolean" col="6" |
1194 | + attrs="{'invisible':[ |
1195 | + ('frontend_input', 'in', ['media_image'])]}"> |
1196 | + <field name="is_required"/> |
1197 | + <field name="is_filterable"/> |
1198 | + <field name="is_visible"/> |
1199 | + <field name="is_global"/> |
1200 | + <field name="is_searchable"/> |
1201 | + <field name="is_visible_on_front"/> |
1202 | + <field name="is_unique"/> |
1203 | + <field name="is_configurable"/> |
1204 | + <field name="is_visible_in_advanced_search"/> |
1205 | + <field name="is_used_for_price_rules"/> |
1206 | + <field name="is_comparable"/> |
1207 | + <field name="is_user_defined"/> |
1208 | + <field name="is_used_for_promo_rules"/> |
1209 | + <field name="used_for_sort_by"/> |
1210 | + <field name="is_wysiwyg_enabled"/> |
1211 | + <field name="used_in_product_listing"/> |
1212 | + <span colspan="2"/> |
1213 | + <field name="is_html_allowed_on_front"/> |
1214 | + </group> |
1215 | + <group name="system" col="4"> |
1216 | + <field name="sync_date" readonly="1"/> |
1217 | + <field name="magento_id" readonly="1"/> |
1218 | + </group> |
1219 | + </form> |
1220 | + </field> |
1221 | +</record> |
1222 | + |
1223 | + |
1224 | +<!--Magento attribute set--> |
1225 | +<record id="magento_attribute_set_tree_view" model="ir.ui.view"> |
1226 | + <field name="model">magento.attribute.set</field> |
1227 | + <field name="arch" type="xml"> |
1228 | + <tree string="Attribute set" editable="top"> |
1229 | + <field name="backend_id"/> |
1230 | + <field name="attribute_set_name"/> |
1231 | + <field name="openerp_id"/> |
1232 | + <field name="sync_date" readonly="1"/> |
1233 | + <field name="sort_order"/> |
1234 | + <field name="magento_id" readonly="1"/> |
1235 | + </tree> |
1236 | + </field> |
1237 | +</record> |
1238 | + |
1239 | + |
1240 | +<record id="magento_attribute_set_form_view" model="ir.ui.view"> |
1241 | + <field name="model">magento.attribute.set</field> |
1242 | + <field name="arch" type="xml"> |
1243 | + <form string="main" version="7.0"> |
1244 | + <group col="4"> |
1245 | + <field name="backend_id"/> |
1246 | + <field name="attribute_set_name"/> |
1247 | + <field name="sync_date"/> |
1248 | + <field name="openerp_id"/> |
1249 | + <field name="sort_order"/> |
1250 | + <field name="magento_id"/> |
1251 | + </group> |
1252 | + </form> |
1253 | + </field> |
1254 | +</record> |
1255 | + |
1256 | + |
1257 | +<record id="magento_attribute_set_action" model="ir.actions.act_window"> |
1258 | + <field name="type">ir.actions.act_window</field> |
1259 | + <field name="res_model">magento.attribute.set</field> |
1260 | + <field name="view_type">form</field> |
1261 | + <field name="name">Mag. attr. set</field> |
1262 | + <!--<field name="view_id" ref="magento_attribute_set_tree_view"/>--> |
1263 | + <field name="help" type="html"> |
1264 | + <p class="oe_view_nocontent_create"> |
1265 | + Click to add an attribute set. |
1266 | + </p> |
1267 | + </field> |
1268 | +</record> |
1269 | + |
1270 | +<menuitem id="menu_magento_attribute_set" |
1271 | + name="Sets" |
1272 | + action="magento_attribute_set_action" |
1273 | + parent="menu_magento_product_attribute_main" |
1274 | + sequence="5"/> |
1275 | + |
1276 | + |
1277 | +<!--Magento attribute option--> |
1278 | +<record id="magento_attribute_option_tree_view" model="ir.ui.view"> |
1279 | + <field name="model">magento.attribute.option</field> |
1280 | + <field name="arch" type="xml"> |
1281 | + <tree string="Attribute option"> |
1282 | + <field name="openerp_id"/> |
1283 | + </tree> |
1284 | + </field> |
1285 | +</record> |
1286 | + |
1287 | +<record id="magento_attribute_option_action" model="ir.actions.act_window"> |
1288 | + <field name="type">ir.actions.act_window</field> |
1289 | + <field name="res_model">magento.attribute.option</field> |
1290 | + <field name="view_type">form</field> |
1291 | + <field name="name">Mag. attr. option</field> |
1292 | + <field name="view_id" ref="magento_attribute_option_tree_view"/> |
1293 | + <field name="help" type="html"> |
1294 | + <p class="oe_view_nocontent_create"> |
1295 | + Click to add an attribute option. |
1296 | + </p> |
1297 | + </field> |
1298 | +</record> |
1299 | + |
1300 | +<menuitem id="menu_magento_attribute_option" |
1301 | + name="Options" |
1302 | + action="magento_attribute_option_action" |
1303 | + parent="menu_magento_product_attribute_main" |
1304 | + sequence="15"/> |
1305 | + |
1306 | + </data> |
1307 | +</openerp> |
1308 | |
1309 | === added file 'magentoerpconnect_catalog/product_category.py' |
1310 | --- magentoerpconnect_catalog/product_category.py 1970-01-01 00:00:00 +0000 |
1311 | +++ magentoerpconnect_catalog/product_category.py 2014-07-01 22:23:08 +0000 |
1312 | @@ -0,0 +1,239 @@ |
1313 | +# -*- coding: utf-8 -*- |
1314 | +############################################################################## |
1315 | +# |
1316 | +# Copyright 2013 |
1317 | +# Author: Guewen Baconnier - Camptocamp SA |
1318 | +# Augustin Cisterne-Kaasv - Elico-corp |
1319 | +# David Béal - Akretion |
1320 | +# This program is free software: you can redistribute it and/or modify |
1321 | +# it under the terms of the GNU Affero General Public License as |
1322 | +# published by the Free Software Foundation, either version 3 of the |
1323 | +# License, or (at your option) any later version. |
1324 | +# |
1325 | +# This program is distributed in the hope that it will be useful, |
1326 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1327 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1328 | +# GNU Affero General Public License for more details. |
1329 | +# |
1330 | +# You should have received a copy of the GNU Affero General Public License |
1331 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1332 | +# |
1333 | +############################################################################## |
1334 | + |
1335 | +from openerp.osv import fields, orm |
1336 | +from openerp.addons.connector.unit.mapper import (mapping, |
1337 | + #changed_by, |
1338 | + ExportMapper) |
1339 | +from openerp.addons.magentoerpconnect.unit.delete_synchronizer import ( |
1340 | + MagentoDeleteSynchronizer) |
1341 | +from openerp.addons.magentoerpconnect.unit.export_synchronizer import ( |
1342 | + MagentoTranslationExporter) |
1343 | +from openerp.addons.magentoerpconnect.backend import magento |
1344 | +from openerp.addons.magentoerpconnect import product_category |
1345 | + |
1346 | + |
1347 | +class MagentoProductCategory(orm.Model): |
1348 | + _inherit = 'magento.product.category' |
1349 | + MAGENTO_HELP = "This field is a technical / configuration field for " \ |
1350 | + "the category on Magento. \nPlease refer to the Magento " \ |
1351 | + "documentation for details. " |
1352 | + |
1353 | + def get_custom_design(self, cr, uid, context=None): |
1354 | + return [ |
1355 | + ('base/default', 'base default'), |
1356 | + ('default/modern', 'default modern'), |
1357 | + ('default/iphone', 'default iphone'), |
1358 | + ('default/default', 'default default'), |
1359 | + ('default/blank', 'default blank'), |
1360 | + ] |
1361 | + |
1362 | + def _get_custom_design(self, cr, uid, context=None): |
1363 | + return self.get_custom_design(cr, uid, context=context) |
1364 | + |
1365 | + def get_page_layout(self, cr, uid, context=None): |
1366 | + return [ |
1367 | + ('empty', 'Empty'), |
1368 | + ('one_column', '1 colmun'), |
1369 | + ('two_columns_left', '2 columns with left bar'), |
1370 | + ('two_columns_right', '2 columns with right bar'), |
1371 | + ('three_columns', '3 columns'), |
1372 | + ] |
1373 | + |
1374 | + def _get_page_layout(self, cr, uid, context=None): |
1375 | + return self.get_page_layout(cr, uid, context=context) |
1376 | + |
1377 | + _columns = { |
1378 | + #==== General Information ==== |
1379 | + 'thumbnail_like_image': fields.boolean('Thumbnail like main image'), |
1380 | + 'thumbnail_binary': fields.binary('Thumbnail'), |
1381 | + 'thumbnail': fields.char( |
1382 | + 'Thumbnail name', |
1383 | + size=100, help=MAGENTO_HELP), |
1384 | + 'image_binary': fields.binary('Image'), |
1385 | + 'image': fields.char( |
1386 | + 'Image name', |
1387 | + size=100, help=MAGENTO_HELP), |
1388 | + 'meta_title': fields.char('Title (Meta)', size=75, help=MAGENTO_HELP), |
1389 | + 'meta_keywords': fields.text('Meta Keywords', help=MAGENTO_HELP), |
1390 | + 'meta_description': fields.text('Meta Description', help=MAGENTO_HELP), |
1391 | + 'url_key': fields.char('URL-key', size=100, readonly="True"), |
1392 | + #==== Display Settings ==== |
1393 | + 'display_mode': fields.selection([ |
1394 | + ('PRODUCTS', 'Products Only'), |
1395 | + ('PAGE', 'Static Block Only'), |
1396 | + ('PRODUCTS_AND_PAGE', 'Static Block & Products')], |
1397 | + 'Display Mode', required=True, help=MAGENTO_HELP), |
1398 | + 'is_anchor': fields.boolean('Anchor?', help=MAGENTO_HELP), |
1399 | + 'use_default_available_sort_by': fields.boolean( |
1400 | + 'Default Config For Available Sort By', help=MAGENTO_HELP), |
1401 | + |
1402 | + #TODO use custom attribut for category |
1403 | + |
1404 | + #'available_sort_by': fields.sparse( |
1405 | + # type='many2many', |
1406 | + # relation='magerp.product_category_attribute_options', |
1407 | + # string='Available Product Listing (Sort By)', |
1408 | + # serialization_field='magerp_fields', |
1409 | + # domain="[('attribute_name', '=', 'sort_by'), ('value', '!=','None')]", |
1410 | + # help=MAGENTO_HELP), |
1411 | + #filter_price_range landing_page ????????????? |
1412 | + 'default_sort_by': fields.selection([ |
1413 | + ('_', 'Config settings'), #????????????? |
1414 | + ('position', 'Best Value'), |
1415 | + ('name', 'Name'), |
1416 | + ('price', 'Price')], |
1417 | + 'Default sort by', required=True, help=MAGENTO_HELP), |
1418 | + |
1419 | + #==== Custom Design ==== |
1420 | + 'custom_apply_to_products': fields.boolean( |
1421 | + 'Apply to products', help=MAGENTO_HELP), |
1422 | + 'custom_design': fields.selection( |
1423 | + _get_custom_design, |
1424 | + string='Custom design', |
1425 | + help=MAGENTO_HELP), |
1426 | + 'custom_design_from': fields.date( |
1427 | + 'Active from', help=MAGENTO_HELP), |
1428 | + 'custom_design_to': fields.date( |
1429 | + 'Active to', help=MAGENTO_HELP), |
1430 | + 'custom_layout_update': fields.text( |
1431 | + 'Layout update', help=MAGENTO_HELP), |
1432 | + 'page_layout': fields.selection( |
1433 | + _get_page_layout, |
1434 | + 'Page layout', help=MAGENTO_HELP), |
1435 | + } |
1436 | + |
1437 | + _defaults = { |
1438 | + 'thumbnail_like_image': True, |
1439 | + 'display_mode': 'PRODUCTS', |
1440 | + 'use_default_available_sort_by': True, |
1441 | + 'default_sort_by': '_', |
1442 | + 'is_anchor': True, |
1443 | + 'include_in_menu': True, |
1444 | + } |
1445 | + |
1446 | + _sql_constraints = [ |
1447 | + ('magento_img_uniq', 'unique(backend_id, image)', |
1448 | + "'Image file name' already exists : must be unique"), |
1449 | + ('magento_thumb_uniq', 'unique(backend_id, thumbnail)', |
1450 | + "'thumbnail name' already exists : must be unique"), |
1451 | + ] |
1452 | + |
1453 | + |
1454 | +@magento |
1455 | +class ProductCategoryDeleteSynchronizer(MagentoDeleteSynchronizer): |
1456 | + """ Product category deleter for Magento """ |
1457 | + _model_name = ['magento.product.category'] |
1458 | + |
1459 | + |
1460 | +@magento |
1461 | +class ProductCategoryExport(MagentoTranslationExporter): |
1462 | + _model_name = ['magento.product.category'] |
1463 | + |
1464 | + def _export_dependencies(self): |
1465 | + """Export parent of the category""" |
1466 | + #TODO FIXME |
1467 | + return True |
1468 | + env = self.environment |
1469 | + record = self.binding_record |
1470 | + binder = self.get_binder_for_model() |
1471 | + if record.magento_parent_id: |
1472 | + mag_parent_id = record.magento_parent_id.id |
1473 | + if binder.to_backend(mag_parent_id) is None: |
1474 | + exporter = env.get_connector_unit(ProductCategoryExporter) |
1475 | + exporter.run(mag_parent_id) |
1476 | + elif record.openerp_id.parent_id: |
1477 | + parent = record.openerp_id.parent_id |
1478 | + if binder.to_backend(parent.id, wrap=True) is None: |
1479 | + exporter = env.get_connector_unit(ProductCategoryExporter) |
1480 | + exporter.run(parent.magento_parent_id.id) |
1481 | + |
1482 | +@magento |
1483 | +class ProductCategoryExportMapper(ExportMapper): |
1484 | + _model_name = 'magento.product.category' |
1485 | + |
1486 | + direct = [('description', 'description'), |
1487 | + #change that to mapping top level category has no name |
1488 | + ('name', 'name'), |
1489 | + ('meta_title', 'meta_title'), |
1490 | + ('meta_keywords', 'meta_keywords'), |
1491 | + ('meta_description', 'meta_description'), |
1492 | + ('display_mode', 'display_mode'), |
1493 | + ('is_anchor', 'is_anchor'), |
1494 | + ('use_default_available_sort_by', 'use_default_available_sort_by'), |
1495 | + ('custom_design', 'custom_design'), |
1496 | + ('custom_design_from', 'custom_design_from'), |
1497 | + ('custom_design_to', 'custom_design_to'), |
1498 | + ('custom_layout_update', 'custom_layout_update'), |
1499 | + ('page_layout', 'page_layout'), |
1500 | + ] |
1501 | + |
1502 | + @mapping |
1503 | + def sort(self, record): |
1504 | + return {'default_sort_by':'price', 'available_sort_by': 'price'} |
1505 | + |
1506 | + @mapping |
1507 | + def parent(self, record): |
1508 | + """ Magento root category's Id equals 1 """ |
1509 | + if not record.magento_parent_id: |
1510 | + openerp_parent = record.parent_id |
1511 | + binder = self.get_binder_for_model('magento.product.category') |
1512 | + parent_id = binder.to_backend(openerp_parent.id, wrap=True) |
1513 | + else: |
1514 | + parent_id = record.magento_parent_id.magento_id |
1515 | + if not parent_id: |
1516 | + parent_id = 1 |
1517 | + return {'parent_id':parent_id} |
1518 | + |
1519 | + @mapping |
1520 | + def active(self, record): |
1521 | + is_active = record['is_active'] |
1522 | + if not is_active: |
1523 | + is_active = 0 |
1524 | + return {'is_active':is_active} |
1525 | + |
1526 | + @mapping |
1527 | + def menu(self, record): |
1528 | + include_in_menu = record['include_in_menu'] |
1529 | + if not include_in_menu: |
1530 | + include_in_menu = 0 |
1531 | + return {'include_in_menu':include_in_menu} |
1532 | + |
1533 | + @mapping |
1534 | + def image(self, record): |
1535 | + res = {} |
1536 | + if record.image_binary: |
1537 | + res.update({'image': record.image, |
1538 | + 'image_binary': record.image_binary}) |
1539 | + if record.thumbnail_like_image == True : |
1540 | + res.update({'thumbnail': record.image,}) |
1541 | + elif record.thumbnail: |
1542 | + res.update({'thumbnail': record.thumbnail, |
1543 | + 'thumbnail_binary': record.thumbnail_binary}) |
1544 | + return res |
1545 | + |
1546 | +@magento(replacing=product_category.ProductCategoryImportMapper) |
1547 | +class ProductCategoryImportMapper(product_category.ProductCategoryImportMapper): |
1548 | + _model_name = 'magento.product.category' |
1549 | + direct = product_category.ProductCategoryImportMapper.direct + [] |
1550 | + |
1551 | + #TODO add mapping for default_sort_by and available_sort_by |
1552 | |
1553 | === added file 'magentoerpconnect_catalog/product_image.py' |
1554 | --- magentoerpconnect_catalog/product_image.py 1970-01-01 00:00:00 +0000 |
1555 | +++ magentoerpconnect_catalog/product_image.py 2014-07-01 22:23:08 +0000 |
1556 | @@ -0,0 +1,336 @@ |
1557 | +# -*- coding: utf-8 -*- |
1558 | +############################################################################## |
1559 | +# |
1560 | +# Copyright 2013 |
1561 | +# Author: Guewen Baconnier - Camptocamp |
1562 | +# David Béal - Akretion |
1563 | +# Sébastien Beau - Akretion |
1564 | +# This program is free software: you can redistribute it and/or modify |
1565 | +# it under the terms of the GNU Affero General Public License as |
1566 | +# published by the Free Software Foundation, either version 3 of the |
1567 | +# License, or (at your option) any later version. |
1568 | +# |
1569 | +# This program is distributed in the hope that it will be useful, |
1570 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1571 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1572 | +# GNU Affero General Public License for more details. |
1573 | +# |
1574 | +# You should have received a copy of the GNU Affero General Public License |
1575 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1576 | +# |
1577 | +############################################################################## |
1578 | + |
1579 | +import mimetypes |
1580 | + |
1581 | +from openerp.osv import fields, orm |
1582 | +#from openerp.tools.translate import _ |
1583 | +#from openerp.osv.osv import except_osv |
1584 | +from openerp.addons.connector.unit.mapper import (mapping, |
1585 | + ExportMapper) |
1586 | +from openerp.addons.magentoerpconnect.unit.binder import MagentoModelBinder |
1587 | +from openerp.addons.magentoerpconnect.unit.delete_synchronizer import ( |
1588 | + MagentoDeleteSynchronizer) |
1589 | +from openerp.addons.magentoerpconnect.unit.export_synchronizer import ( |
1590 | + MagentoExporter) |
1591 | +from openerp.addons.magentoerpconnect.backend import magento |
1592 | +from openerp.addons.magentoerpconnect.unit.backend_adapter import GenericAdapter |
1593 | + |
1594 | + |
1595 | +MAGENTO_HELP = "This field is a technical / configuration field for " \ |
1596 | + "the attribute on Magento. \nPlease refer to the Magento " \ |
1597 | + "documentation for details. " |
1598 | + |
1599 | + |
1600 | +@magento(replacing=MagentoModelBinder) |
1601 | +class MagentoImageBinder(MagentoModelBinder): |
1602 | + _model_name = [ |
1603 | + 'magento.product.image', |
1604 | + ] |
1605 | + |
1606 | + |
1607 | +class MagentoProductProduct(orm.Model): |
1608 | + _inherit = 'magento.product.product' |
1609 | + |
1610 | + def _get_images(self, cr, uid, ids, field_names, arg, context=None): |
1611 | + res={} |
1612 | + for prd in self.browse(cr, uid, ids, context=context): |
1613 | + img_ids = self.pool['magento.product.image'].search( |
1614 | + cr, uid, [ |
1615 | + ('product_id', '=', prd.openerp_id.id), |
1616 | + ('backend_id', '=', prd.backend_id.id), ], context=context) |
1617 | + res[prd.id] = img_ids |
1618 | + return res |
1619 | + |
1620 | + def copy(self, cr, uid, id, default=None, context=None): |
1621 | + #take care about duplicate on one2many and function fields |
1622 | + #https://bugs.launchpad.net/openobject-server/+bug/705364 |
1623 | + if default is None: |
1624 | + default = {} |
1625 | + default['magento_product_image_ids'] = None |
1626 | + return super(MagentoProductProduct, self).copy(cr, uid, id, |
1627 | + default=default, |
1628 | + context=context) |
1629 | + _columns = { |
1630 | + 'magento_product_image_ids': fields.function( |
1631 | + _get_images, |
1632 | + type='one2many', |
1633 | + relation='magento.product.image', |
1634 | + string='Magento product images'), |
1635 | + 'magento_product_storeview_ids': fields.one2many( |
1636 | + 'magento.product.storeview', |
1637 | + 'magento_product_id', |
1638 | + string='Magento storeview',), |
1639 | + } |
1640 | + |
1641 | + def open_images(self, cr, uid, ids, context=None): |
1642 | + view_id = self.pool['ir.model.data'].get_object_reference( |
1643 | + cr, uid, 'magentoerpconnect_catalog', |
1644 | + 'magento_product_img_form_view')[1] |
1645 | + return { |
1646 | + 'name': 'Product images', |
1647 | + 'view_type': 'form', |
1648 | + 'view_mode': 'form', |
1649 | + 'view_id': view_id, |
1650 | + 'res_model': self._name, |
1651 | + 'context': context, |
1652 | + 'type': 'ir.actions.act_window', |
1653 | + 'res_id': ids and ids[0] or False, |
1654 | + } |
1655 | + |
1656 | + |
1657 | +class ProductImage(orm.Model): |
1658 | + _inherit = 'product.image' |
1659 | + |
1660 | + _columns = { |
1661 | + 'magento_bind_ids': fields.one2many( |
1662 | + 'magento.product.image', |
1663 | + 'openerp_id', |
1664 | + string='Magento bindings',), |
1665 | + } |
1666 | + |
1667 | + |
1668 | +class MagentoProductImage(orm.Model): |
1669 | + _name = 'magento.product.image' |
1670 | + _description = "Magento product image" |
1671 | + _inherit = 'magento.binding' |
1672 | + _inherits = {'product.image': 'openerp_id'} |
1673 | + |
1674 | + _columns = { |
1675 | + 'openerp_id': fields.many2one( |
1676 | + 'product.image', |
1677 | + required=True, |
1678 | + ondelete="cascade", |
1679 | + string='Image'), |
1680 | + } |
1681 | + |
1682 | + def _get_backend(self, cr, uid, context=None): |
1683 | + backend_id = False |
1684 | + backend_m = self.pool['magento.backend'] |
1685 | + back_ids = backend_m.search(cr, uid, [], context=context) |
1686 | + if back_ids: |
1687 | + backend_id = backend_m.browse( |
1688 | + cr, uid, back_ids, context=context)[0].id |
1689 | + return backend_id |
1690 | + |
1691 | + _defaults = { |
1692 | + 'backend_id': _get_backend, |
1693 | + } |
1694 | + |
1695 | + _sql_constraints = [ |
1696 | + ('magento_uniq', 'unique(backend_id, magento_id)', |
1697 | + "An image with the same ID on Magento already exists") |
1698 | + ] |
1699 | + |
1700 | +@magento |
1701 | +class ProductImageDeleteSynchronizer(MagentoDeleteSynchronizer): |
1702 | + _model_name = ['magento.product.image'] |
1703 | + |
1704 | + |
1705 | +@magento |
1706 | +class ProductImageExport(MagentoExporter): |
1707 | + _model_name = ['magento.product.image'] |
1708 | + |
1709 | + def _should_import(self): |
1710 | + "Images in magento doesn't retrieve infos on dates" |
1711 | + return False |
1712 | + |
1713 | + |
1714 | +@magento |
1715 | +class ProductImageExportMapper(ExportMapper): |
1716 | + _model_name = 'magento.product.image' |
1717 | + |
1718 | + direct = [ |
1719 | + ('label', 'label'), |
1720 | + ('sequence', 'position'), |
1721 | + ] |
1722 | + |
1723 | + @mapping |
1724 | + def product(self, record): |
1725 | + binder = self.get_binder_for_model('magento.product.product') |
1726 | + external_product_id = binder.to_backend( |
1727 | + record.openerp_id.product_id.id, True) |
1728 | + return {'product': str(external_product_id)} |
1729 | + |
1730 | + @mapping |
1731 | + def identifierType(self, record): |
1732 | + return {'identifierType': 'ID'} |
1733 | + |
1734 | + @mapping |
1735 | + def types(self, record): |
1736 | + return {'types': ['image', 'small_image', 'thumbnail']} |
1737 | + # return {'types': |
1738 | + # [x for x in ['image', 'small_image', 'thumbnail'] if record[x]] |
1739 | + # } |
1740 | + |
1741 | + @mapping |
1742 | + def file(self, record): |
1743 | + return {'file': { |
1744 | + 'mime': mimetypes.guess_type(record.name + record.extension)[0], |
1745 | + 'name': record.label, |
1746 | + 'content': self.session.pool['image.image'].get_image( |
1747 | + self.session.cr, self.session.uid, |
1748 | + record.openerp_id.image_id.id, |
1749 | + context=self.session.context), |
1750 | + } |
1751 | + } |
1752 | + |
1753 | + |
1754 | +@magento |
1755 | +class ProductImageAdapter(GenericAdapter): |
1756 | + _model_name = 'magento.product.image' |
1757 | + _magento_model = 'catalog_product_attribute_media' |
1758 | + |
1759 | + def create(self, data, storeview_id=None): |
1760 | + #import pdb;pdb.set_trace() |
1761 | + print data |
1762 | + return self._call('%s.create' % self._magento_model, |
1763 | + [data.pop('product'), data, storeview_id]) |
1764 | + |
1765 | + def write(self, id, data): |
1766 | + """ Update records on the external system |
1767 | + changes with GenericAdapter : prevent 'int(id)' """ |
1768 | + return self._call('%s.update' % self._magento_model, |
1769 | + [data.pop('product'), id, data]) |
1770 | + |
1771 | + def delete(self, id): |
1772 | + """ Delete a record on the external system """ |
1773 | + image_id, external_product_id = id |
1774 | + return self._call('%s.remove' % self._magento_model, |
1775 | + [external_product_id, image_id]) |
1776 | + |
1777 | + |
1778 | +class MagentoProductStoreview(orm.Model): |
1779 | + _name = 'magento.product.storeview' |
1780 | + _description = "Magento product storeview" |
1781 | + _inherits = {'magento.product.product': 'magento_product_id'} |
1782 | + |
1783 | + _columns = { |
1784 | + 'magento_product_id' : fields.many2one( |
1785 | + 'magento.product.product', |
1786 | + required=True, |
1787 | + ondelete="cascade", |
1788 | + string='Image'), |
1789 | + 'storeview_id': fields.many2one( |
1790 | + 'magento.storeview', |
1791 | + required=True, |
1792 | + string='Storeview'), |
1793 | + 'image': fields.many2one( |
1794 | + 'magento.product.image', |
1795 | + 'Base image', |
1796 | + help=MAGENTO_HELP), |
1797 | + 'small_image': fields.many2one( |
1798 | + 'magento.product.image', |
1799 | + 'Small image', |
1800 | + help=MAGENTO_HELP), |
1801 | + 'thumbnail': fields.many2one( |
1802 | + 'magento.product.image', |
1803 | + 'Thumbnail', |
1804 | + domain="[('backend_id', '=', 'backend_id')]", |
1805 | + help=MAGENTO_HELP), |
1806 | + 'exclude_ids': fields.many2many( |
1807 | + 'magento.product.image', 'product_id', |
1808 | + string='Exclude', |
1809 | + help=MAGENTO_HELP), |
1810 | + } |
1811 | + |
1812 | + |
1813 | +@magento |
1814 | +class ProductStoreviewExport(MagentoExporter): |
1815 | + _model_name = ['magento.product.storeview'] |
1816 | + |
1817 | +# TODO |
1818 | +# def _export_dependencies(self): |
1819 | + |
1820 | + def _should_import(self): |
1821 | + "Images in magento doesn't retrieve infos on dates" |
1822 | + return False |
1823 | + # |
1824 | + #def _run(self, fields=None): |
1825 | + # """ Flow of the synchronization, implemented in inherited classes""" |
1826 | + # assert self.binding_id |
1827 | + # assert self.binding_record |
1828 | + # |
1829 | + # |
1830 | + # if not self.magento_id: |
1831 | + # fields = None # should be created with all the fields |
1832 | + # |
1833 | + # if self._has_to_skip(): |
1834 | + # return |
1835 | + # |
1836 | + # export the missing linked resources |
1837 | + # self._export_dependencies() |
1838 | + # |
1839 | + # self._map_data(fields=fields) |
1840 | + # |
1841 | + # if self.magento_id: |
1842 | + # record = self.mapper.data |
1843 | + # if not record: |
1844 | + # return _('Nothing to export.') |
1845 | + # special check on data before export |
1846 | + # self._validate_data(record) |
1847 | + # self._update(record) |
1848 | + # else: |
1849 | + # record = self.mapper.data_for_create |
1850 | + # if not record: |
1851 | + # return _('Nothing to export.') |
1852 | + # special check on data before export |
1853 | + # self._validate_data(record) |
1854 | + # self.magento_id = self._create(record) |
1855 | + # return _('Record exported with ID %s on Magento.') % self.magento_id |
1856 | + |
1857 | + |
1858 | +@magento |
1859 | +class ProductStoreviewExportMapper(ExportMapper): |
1860 | + _model_name = 'magento.product.storeview' |
1861 | + |
1862 | + direct = [ |
1863 | + ('label', 'label'), |
1864 | + ('sequence', 'position'), ] |
1865 | + |
1866 | + @mapping |
1867 | + def product(self, record): |
1868 | + return {'product': ''} |
1869 | + |
1870 | + |
1871 | +# |
1872 | +#@magento |
1873 | +#class ProductStoreviewAdapter(GenericAdapter): |
1874 | +# _model_name = 'magento.product.storeview' |
1875 | +# |
1876 | +# def update_image(self, product_id, data, storeview_id=None): |
1877 | +# #data = {'small', image_id, 'medium':image_id,...} |
1878 | +# |
1879 | +# return self._call('catalog_product_attribute_media.update', |
1880 | +# [product_id, image_id, data, storeview_id]) |
1881 | +# |
1882 | + |
1883 | + |
1884 | + |
1885 | +# |
1886 | +#@job |
1887 | +#def export_record(session, model_name, binding_id, fields=None): |
1888 | +# """ Export a record on Magento """ |
1889 | +# record = session.browse(model_name, binding_id) |
1890 | +# env = get_environment(session, model_name, record.backend_id.id) |
1891 | +# exporter = env.get_connector_unit(MagentoExporter) |
1892 | +# return exporter.run(binding_id, fields=fields) |
1893 | |
1894 | === added file 'magentoerpconnect_catalog/product_image_view.xml' |
1895 | --- magentoerpconnect_catalog/product_image_view.xml 1970-01-01 00:00:00 +0000 |
1896 | +++ magentoerpconnect_catalog/product_image_view.xml 2014-07-01 22:23:08 +0000 |
1897 | @@ -0,0 +1,79 @@ |
1898 | +<?xml version="1.0" encoding="UTF-8"?> |
1899 | +<openerp> |
1900 | + <data> |
1901 | + |
1902 | + <!-- |
1903 | +<record id="view_product_image_form" model="ir.ui.view"> |
1904 | + <field name="model">product.image</field> |
1905 | + <field name="inherit_id" |
1906 | + ref="product_image.view_product_image_form" /> |
1907 | + <field name="arch" type="xml" > |
1908 | + <xpath expr="//group[@name='link']" position="after"> |
1909 | + <field name="product_id" invisible="1"/> |
1910 | + <group name="magento"> |
1911 | + <field name="magento_bind_ids" nolabel="1"> |
1912 | + <tree name="magento_img_storeview" |
1913 | + editable="bottom"> |
1914 | + <field name="backend_id" string="Backend"/> |
1915 | + </tree> |
1916 | + </field> |
1917 | + </group> |
1918 | + </xpath> |
1919 | + </field> |
1920 | +</record> |
1921 | + |
1922 | +<record id="magento_product_img_form_view" model="ir.ui.view"> |
1923 | + <field name="model">magento.product.product</field> |
1924 | + <field name="priority">30</field> |
1925 | + <field name="arch" type="xml"> |
1926 | + <form version="7.0" string="_"> |
1927 | + <separator string="Magento images"/> |
1928 | + <field name="backend_id" invisible="True"/> |
1929 | + <field name="openerp_id" invisible="True"/> |
1930 | + <field name="magento_product_image_ids"> |
1931 | + <tree editable="bottom"> |
1932 | + <field name="product_id"/> |
1933 | + <field name="label"/> |
1934 | + <field name="sequence"/> |
1935 | + <field name="name"/> |
1936 | + <field name="extension" string="ext."/> |
1937 | + <field name="magento_id"/> |
1938 | + <field name="file" widget="image"/> |
1939 | + </tree> |
1940 | + </field> |
1941 | + <separator string="Magento storeviews"/> |
1942 | + <field name="magento_product_storeview_ids"> |
1943 | + <tree editable="bottom"> |
1944 | + <field name="image" |
1945 | + domain="[('backend_id', '=', parent.backend_id), ('product_id', '=', parent.openerp_id)]"/> |
1946 | + <field name="small_image" |
1947 | + domain="[('backend_id', '=', parent.backend_id), ('product_id', '=', parent.openerp_id)]"/> |
1948 | + <field name="thumbnail" |
1949 | + domain="[('backend_id', '=', parent.backend_id), ('product_id', '=', parent.openerp_id)]"/> |
1950 | + <field name="storeview_id" |
1951 | + domain="[('backend_id', '=', parent.backend_id)]"/> |
1952 | + <field name="exclude_ids" |
1953 | + widget="many2many_tags" |
1954 | + domain="[('backend_id', '=', parent.backend_id), ('product_id', '=', parent.openerp_id)]"/> |
1955 | + </tree> |
1956 | + </field> |
1957 | + </form> |
1958 | + </field> |
1959 | +</record> |
1960 | + |
1961 | +<record id="product_normal_form_view" model="ir.ui.view"> |
1962 | + <field name="model">product.product</field> |
1963 | + <field name="inherit_id" |
1964 | + ref="magentoerpconnect.product_normal_form_view"/> |
1965 | + <field name="arch" type="xml"> |
1966 | + <xpath expr="//field[@name='magento_bind_ids']/tree/field[@name='backend_id']" |
1967 | + position="before"> |
1968 | + <button string="Images management" type="object" |
1969 | + name="open_images" icon="stock_gantt"/> |
1970 | + </xpath> |
1971 | + </field> |
1972 | +</record> |
1973 | + |
1974 | +--> |
1975 | + </data> |
1976 | +</openerp> |
1977 | |
1978 | === added file 'magentoerpconnect_catalog/product_view.xml' |
1979 | --- magentoerpconnect_catalog/product_view.xml 1970-01-01 00:00:00 +0000 |
1980 | +++ magentoerpconnect_catalog/product_view.xml 2014-07-01 22:23:08 +0000 |
1981 | @@ -0,0 +1,78 @@ |
1982 | +<?xml version="1.0" encoding="UTF-8"?> |
1983 | +<openerp> |
1984 | + <data> |
1985 | + |
1986 | +<record id="view_magento_product_category_form" model="ir.ui.view"> |
1987 | + <field name="name">magento.product.category.form</field> |
1988 | + <field name="model">magento.product.category</field> |
1989 | + <field name="inherit_id" ref="magentoerpconnect.view_magento_product_category_form" /> |
1990 | + <field name="arch" type="xml" > |
1991 | + <xpath expr="/form/group[1]" position="replace"> |
1992 | + <group col="4"> |
1993 | + <field name="backend_id" colspan="2"/> |
1994 | + <field name="magento_id" readonly="1" colspan="2"/> |
1995 | + </group> |
1996 | + </xpath> |
1997 | + <xpath expr="/form" position="inside"> |
1998 | + <group string="General informations" col="4"> |
1999 | + <group colspan="2"> |
2000 | + <field name="is_active"/> |
2001 | + <field name="include_in_menu"/> |
2002 | + <field name="magento_parent_id"/> |
2003 | + </group> |
2004 | + <group colspan="2"> |
2005 | + <label for="magento_child_ids" class="oe_inline"/> |
2006 | + <field name="magento_child_ids" colspan="2" nolabel="1"/> |
2007 | + </group> |
2008 | + <field name="description" colspan="4"/> |
2009 | + <group colspan="2"> |
2010 | + <field name="image"/> |
2011 | + <field name="meta_title"/> |
2012 | + <field name="meta_description"/> |
2013 | + <field name="meta_keywords"/> |
2014 | + <field name="thumbnail_like_image"/> |
2015 | + <group name="thumbnail_grp" colspan="2" |
2016 | + attrs="{'invisible': [('thumbnail_like_image', '=', True)]}"> |
2017 | + |
2018 | + <field name="thumbnail"/> |
2019 | + <field name="thumbnail_binary" widget="image" |
2020 | + filename="thumbnail" nolabel="1"/> |
2021 | + </group> |
2022 | + </group> |
2023 | + <group colspan="2"> |
2024 | + <field name="image_binary" widget="image" |
2025 | + filename="image" nolabel="1"/> |
2026 | + </group> |
2027 | + </group> |
2028 | + <group string="Display settings" col="4"> |
2029 | + <field name="display_mode"/> |
2030 | + <field name="is_anchor"/> |
2031 | + <field name="use_default_available_sort_by"/> |
2032 | + </group> |
2033 | + <group string="Custom design" col="4"> |
2034 | + <field name="custom_design"/> |
2035 | + <field name="custom_design_from"/> |
2036 | + <field name="custom_apply_to_products"/> |
2037 | + <field name="custom_design_to"/> |
2038 | + <field name="page_layout"/><br/><br/> |
2039 | + <field name="custom_layout_update" colspan="4"/> |
2040 | + </group> |
2041 | + </xpath> |
2042 | + </field> |
2043 | +</record> |
2044 | + |
2045 | + |
2046 | +<record id="product_product_form_view_set_button" model="ir.ui.view"> |
2047 | + <field name="model">product.product</field> |
2048 | + <field name="inherit_id" |
2049 | + ref="product_custom_attributes.product_product_form_view_set_button"/> |
2050 | + <field name="arch" type="xml"> |
2051 | + <field name="attribute_set_id" position="attributes"> |
2052 | + <attribute name="attrs">{'required': [('magento_bind_ids','!=',[])]}</attribute> |
2053 | + </field> |
2054 | + </field> |
2055 | +</record> |
2056 | + |
2057 | + |
2058 | + </data> |
2059 | +</openerp> |
2060 | \ No newline at end of file |
2061 | |
2062 | === added directory 'magentoerpconnect_catalog/tests' |
2063 | === added file 'magentoerpconnect_catalog/tests/__init__.py' |
2064 | --- magentoerpconnect_catalog/tests/__init__.py 1970-01-01 00:00:00 +0000 |
2065 | +++ magentoerpconnect_catalog/tests/__init__.py 2014-07-01 22:23:08 +0000 |
2066 | @@ -0,0 +1,29 @@ |
2067 | +# -*- coding: utf-8 -*- |
2068 | +############################################################################## |
2069 | +# |
2070 | +# Author: Guewen Baconnier |
2071 | +# Copyright 2012 Camptocamp SA |
2072 | +# |
2073 | +# This program is free software: you can redistribute it and/or modify |
2074 | +# it under the terms of the GNU Affero General Public License as |
2075 | +# published by the Free Software Foundation, either version 3 of the |
2076 | +# License, or (at your option) any later version. |
2077 | +# |
2078 | +# This program is distributed in the hope that it will be useful, |
2079 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2080 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2081 | +# GNU Affero General Public License for more details. |
2082 | +# |
2083 | +# You should have received a copy of the GNU Affero General Public License |
2084 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2085 | +# |
2086 | +############################################################################## |
2087 | + |
2088 | +import test_attribute_synchronisation |
2089 | + |
2090 | +fast_suite = [ |
2091 | +] |
2092 | + |
2093 | +checks = [ |
2094 | + test_attribute_synchronisation, |
2095 | +] |
2096 | |
2097 | === added file 'magentoerpconnect_catalog/tests/test_attribute_synchronisation.py' |
2098 | --- magentoerpconnect_catalog/tests/test_attribute_synchronisation.py 1970-01-01 00:00:00 +0000 |
2099 | +++ magentoerpconnect_catalog/tests/test_attribute_synchronisation.py 2014-07-01 22:23:08 +0000 |
2100 | @@ -0,0 +1,109 @@ |
2101 | +# -*- coding: utf-8 -*- |
2102 | +############################################################################### |
2103 | +# |
2104 | +# Module for OpenERP |
2105 | +# Copyright (C) 2014 Akretion (http://www.akretion.com). |
2106 | +# @author Sébastien BEAU <sebastien.beau@akretion.com> |
2107 | +# |
2108 | +# This program is free software: you can redistribute it and/or modify |
2109 | +# it under the terms of the GNU Affero General Public License as |
2110 | +# published by the Free Software Foundation, either version 3 of the |
2111 | +# License, or (at your option) any later version. |
2112 | +# |
2113 | +# This program is distributed in the hope that it will be useful, |
2114 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2115 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2116 | +# GNU Affero General Public License for more details. |
2117 | +# |
2118 | +# You should have received a copy of the GNU Affero General Public License |
2119 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2120 | +# |
2121 | +############################################################################### |
2122 | + |
2123 | +from openerp.addons.magentoerpconnect.tests.test_synchronization import ( |
2124 | + SetUpMagentoSynchronized) |
2125 | +from openerp.addons.magentoerpconnect.unit.import_synchronizer import ( |
2126 | + import_record) |
2127 | +from openerp.addons.magentoerpconnect.tests.common import ( |
2128 | + mock_api, |
2129 | + mock_urlopen_image) |
2130 | +from openerp.addons.magentoerpconnect.unit.export_synchronizer import ( |
2131 | + export_record) |
2132 | +from .test_data import magento_attribute_responses |
2133 | + |
2134 | + |
2135 | +class TestImportAttribute(SetUpMagentoSynchronized): |
2136 | + """ Test the import from a Magento Mock. |
2137 | + |
2138 | + The data returned by Magento are those created for the |
2139 | + demo version of Magento on a standard 1.7 version. |
2140 | + """ |
2141 | + |
2142 | + def test_10_import_attribute_set(self): |
2143 | + """ Import the default attribute set""" |
2144 | + with mock_api(magento_attribute_responses): |
2145 | + import_record(self.session, 'magento.attribute.set', |
2146 | + self.backend_id, '9') |
2147 | + |
2148 | + mag_attr_obj = self.registry('magento.attribute.set') |
2149 | + cr, uid = self.cr, self.uid |
2150 | + mag_attr_set_ids = mag_attr_obj.search(cr, uid, [ |
2151 | + ('magento_id', '=', '9'), |
2152 | + ('backend_id', '=', self.backend_id), |
2153 | + ]) |
2154 | + self.assertEqual(len(mag_attr_set_ids), 1) |
2155 | + mag_attr_set = mag_attr_obj.browse(cr, uid, mag_attr_set_ids[0]) |
2156 | + self.assertEqual(mag_attr_set.attribute_set_name, 'Default') |
2157 | + |
2158 | + |
2159 | +class TestExportAttribute(SetUpMagentoSynchronized): |
2160 | + """ Test the export from a Magento Mock. |
2161 | + |
2162 | + The data returned by Magento are those created for the |
2163 | + demo version of Magento on a standard 1.7 version. |
2164 | + """ |
2165 | + def setUp(self): |
2166 | + super(TestExportAttribute, self).setUp() |
2167 | + with mock_api(magento_attribute_responses): |
2168 | + import_record(self.session, 'magento.attribute.set', |
2169 | + self.backend_id, '9') |
2170 | + |
2171 | + mag_attr_model = self.registry('magento.attribute.set') |
2172 | + cr, uid = self.cr, self.uid |
2173 | + mag_attr_set_ids = mag_attr_model.search(cr, uid, [ |
2174 | + ('magento_id', '=', '9'), |
2175 | + ('backend_id', '=', self.backend_id), |
2176 | + ]) |
2177 | + self.registry('magento.backend').write(cr, uid, self.backend_id, { |
2178 | + 'attribute_set_tpl_id': mag_attr_set_ids[0] |
2179 | + }) |
2180 | + |
2181 | + def test_20_export_attribute_set(self): |
2182 | + """ Test export of attribute set""" |
2183 | + response = { |
2184 | + 'product_attribute_set.create': 69, |
2185 | + } |
2186 | + cr = self.cr |
2187 | + uid = self.uid |
2188 | + with mock_api(response, key_func=lambda m, a: m) as calls_done: |
2189 | + mag_attr_set_model = self.registry('magento.attribute.set') |
2190 | + attr_set_model = self.registry('attribute.set') |
2191 | + |
2192 | + attr_set_id = attr_set_model.create(cr, uid, { |
2193 | + 'name': 'Test Export Attribute', |
2194 | + }, {'force_model': 'product.template'}) |
2195 | + mag_attr_set_id = mag_attr_set_model.create(cr, uid, { |
2196 | + 'attribute_set_name': 'Test Export Attribute', |
2197 | + 'openerp_id': attr_set_id, |
2198 | + 'backend_id': self.backend_id, |
2199 | + }) |
2200 | + |
2201 | + export_record(self.session, 'magento.attribute.set', |
2202 | + mag_attr_set_id) |
2203 | + |
2204 | + self.assertEqual(len(calls_done), 1) |
2205 | + |
2206 | + method, (data, skeleton_id) = calls_done[0] |
2207 | + print data |
2208 | + self.assertEqual(method, 'product_attribute_set.create') |
2209 | + self.assertEqual(skeleton_id, '9') |
2210 | |
2211 | === added file 'magentoerpconnect_catalog/tests/test_data.py' |
2212 | --- magentoerpconnect_catalog/tests/test_data.py 1970-01-01 00:00:00 +0000 |
2213 | +++ magentoerpconnect_catalog/tests/test_data.py 2014-07-01 22:23:08 +0000 |
2214 | @@ -0,0 +1,99 @@ |
2215 | +# -*- coding: utf-8 -*- |
2216 | +############################################################################### |
2217 | +# |
2218 | +# Module for OpenERP |
2219 | +# Copyright (C) 2014 Akretion (http://www.akretion.com). |
2220 | +# @author Sébastien BEAU <sebastien.beau@akretion.com> |
2221 | +# |
2222 | +# This program is free software: you can redistribute it and/or modify |
2223 | +# it under the terms of the GNU Affero General Public License as |
2224 | +# published by the Free Software Foundation, either version 3 of the |
2225 | +# License, or (at your option) any later version. |
2226 | +# |
2227 | +# This program is distributed in the hope that it will be useful, |
2228 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2229 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2230 | +# GNU Affero General Public License for more details. |
2231 | +# |
2232 | +# You should have received a copy of the GNU Affero General Public License |
2233 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2234 | +# |
2235 | +############################################################################### |
2236 | + |
2237 | + |
2238 | +magento_attribute_responses = \ |
2239 | +{('ol_catalog_product_attributeset.info', (9,)): {'attribute_set_id': '9', |
2240 | + 'attribute_set_name': 'Default', |
2241 | + 'entity_type_id': '10', |
2242 | + 'sort_order': '16'}, |
2243 | + ('ol_catalog_product_attributeset.info', (38,)): {'attribute_set_id': '38', |
2244 | + 'attribute_set_name': 'Cell Phones', |
2245 | + 'entity_type_id': '10', |
2246 | + 'sort_order': '0'}, |
2247 | + ('ol_catalog_product_attributeset.info', (39,)): {'attribute_set_id': '39', |
2248 | + 'attribute_set_name': 'Computer', |
2249 | + 'entity_type_id': '10', |
2250 | + 'sort_order': '0'}, |
2251 | + ('ol_catalog_product_attributeset.info', (40,)): {'attribute_set_id': '40', |
2252 | + 'attribute_set_name': 'Shoes', |
2253 | + 'entity_type_id': '10', |
2254 | + 'sort_order': '0'}, |
2255 | + ('ol_catalog_product_attributeset.info', (41,)): {'attribute_set_id': '41', |
2256 | + 'attribute_set_name': 'Shirts T', |
2257 | + 'entity_type_id': '10', |
2258 | + 'sort_order': '0'}, |
2259 | + ('ol_catalog_product_attributeset.info', (42,)): {'attribute_set_id': '42', |
2260 | + 'attribute_set_name': 'Furniture', |
2261 | + 'entity_type_id': '10', |
2262 | + 'sort_order': '0'}, |
2263 | + ('ol_catalog_product_attributeset.info', (44,)): {'attribute_set_id': '44', |
2264 | + 'attribute_set_name': 'Cameras', |
2265 | + 'entity_type_id': '10', |
2266 | + 'sort_order': '0'}, |
2267 | + ('ol_catalog_product_attributeset.info', (45,)): {'attribute_set_id': '45', |
2268 | + 'attribute_set_name': 'Shirts Other', |
2269 | + 'entity_type_id': '10', |
2270 | + 'sort_order': '0'}, |
2271 | + ('ol_catalog_product_attributeset.info', (46,)): {'attribute_set_id': '46', |
2272 | + 'attribute_set_name': 'Shirts (General)', |
2273 | + 'entity_type_id': '10', |
2274 | + 'sort_order': '0'}, |
2275 | + ('ol_catalog_product_attributeset.info', (58,)): {'attribute_set_id': '58', |
2276 | + 'attribute_set_name': 'RAM', |
2277 | + 'entity_type_id': '10', |
2278 | + 'sort_order': '0'}, |
2279 | + ('ol_catalog_product_attributeset.info', (59,)): {'attribute_set_id': '59', |
2280 | + 'attribute_set_name': 'Warranties', |
2281 | + 'entity_type_id': '10', |
2282 | + 'sort_order': '0'}, |
2283 | + ('ol_catalog_product_attributeset.info', (60,)): {'attribute_set_id': '60', |
2284 | + 'attribute_set_name': 'CPU', |
2285 | + 'entity_type_id': '10', |
2286 | + 'sort_order': '0'}, |
2287 | + ('ol_catalog_product_attributeset.info', (61,)): {'attribute_set_id': '61', |
2288 | + 'attribute_set_name': 'Monitors', |
2289 | + 'entity_type_id': '10', |
2290 | + 'sort_order': '0'}, |
2291 | + ('ol_catalog_product_attributeset.info', (62,)): {'attribute_set_id': '62', |
2292 | + 'attribute_set_name': 'Hard Drive', |
2293 | + 'entity_type_id': '10', |
2294 | + 'sort_order': '0'}, |
2295 | + ('ol_catalog_product_attributeset.info', (63,)): {'attribute_set_id': '63', |
2296 | + 'attribute_set_name': 't-shirt-open', |
2297 | + 'entity_type_id': '10', |
2298 | + 'sort_order': '0'}, |
2299 | + ('ol_catalog_product_attributeset.search', ()): ['44', |
2300 | + '38', |
2301 | + '39', |
2302 | + '60', |
2303 | + '9', |
2304 | + '42', |
2305 | + '62', |
2306 | + '61', |
2307 | + '58', |
2308 | + '46', |
2309 | + '45', |
2310 | + '41', |
2311 | + '40', |
2312 | + '63', |
2313 | + '59']} |
This merge have been moved on github https:/ /github. com/OCA/ connector- magento/ pull/4