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