Merge lp:~ajite/openerp-connector/7.0-magentoerpconnect-fix-000002 into lp:~openerp-connector-core-editors/openerp-connector-magento/7.0

Status: Work in progress
Proposed branch: lp:~ajite/openerp-connector/7.0-magentoerpconnect-fix-000002
Merge into: lp:~openerp-connector-core-editors/openerp-connector-magento/7.0
Diff against target: 576 lines (+391/-3)
15 files modified
magentoerpconnect/__init__.py (+1/-0)
magentoerpconnect/magento_model.py (+10/-0)
magentoerpconnect/magento_model_view.xml (+7/-0)
magentoerpconnect/product.py (+39/-1)
magentoerpconnect/product_attribute_set.py (+94/-0)
magentoerpconnect/product_category.py (+7/-0)
magentoerpconnect/product_view.xml (+22/-0)
magentoerpconnect/unit/binder.py (+1/-0)
magentoerpconnect_catalog/__init__.py (+5/-0)
magentoerpconnect_catalog/__openerp__.py (+2/-2)
magentoerpconnect_catalog/connector.py (+12/-0)
magentoerpconnect_catalog/consumer.py (+25/-0)
magentoerpconnect_catalog/product.py (+95/-0)
magentoerpconnect_catalog/product_category.py (+55/-0)
magentoerpconnect_catalog/product_view.xml (+16/-0)
To merge this branch: bzr merge lp:~ajite/openerp-connector/7.0-magentoerpconnect-fix-000002
Reviewer Review Type Date Requested Status
OpenERP Connector Core Editors Pending
Review via email: mp+180730@code.launchpad.net

Description of the change

The changes that I have made are experimental.
At the moment, some of the previous unit tests are not working because you need to import product attribute sets before importing products.

It is quite stable on my local environment but it still obviously needs improvements.

To try the changes that I have made please use the following branch of the OpenLabs Magento add-on:

bzr branch lp:~ajite/openerp-connector/magento-model-oerp7.x-experimental

It adds 2 API methods in the Product attribute set API (search and info).

Added the export of products and categories.
Added the import of product attribute sets (We need to have them to export export products).
Added a new backend advanced option (Export record On save)
Added attributes in both magento.product.product and magento.product.category (that are required for the export)

Please import the product attribute sets before importing products
You need to have a product code and a product description for the product export function to succeed.

We can create and edit a category then export it to a given backend but we can't move the category to another parent category after the creation. In fact the magento setParentId() will not change the parent id. We need to implement the magento category API move method to make it work.

To post a comment you must log in.
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Hi Augustin,

Thanks for the MP.
I read through the diff and that seems already nice, you very well understood the mechanisms and how the synchronizations are supposed to work and that makes me happy.

I'll need to take more time to do a proper review, but I'm already reassured that you go in the right direction so I am quite comfortable if let you continue in this direction.

There is just one thing I want to comment on, about the choice to push the records on save.
Basically in your diff:

    push_on_save = record.backend_id.push_on_save
    if push_on_save:

This option is to remove, any created or modified record must always me exported to Magento, that's the design we choose. So we don't need anymore the methods to export the products or categories like in l.411,498.

Another thing about the monkey patching in l.522: this is a bad idea, because OpenERP may import the python code of uninstalled modules (it wouldn't have bad effects in this case, remark). There is other techniques [0][1] for replacing ConnectorUnit classes, but in that case I would just redefine the create method in the main 'magentoerpconnect' module.

[0] https://code.launchpad.net/~openerp-connector-core-editors/openerp-connector/7.0-connector-replacing-connectorunit-classes/+merge/172309
[1] https://code.launchpad.net/~openerp-connector-core-editors/openerp-connector/7.0-magentoerpconnect-replacing-connectorunit-classes/+merge/172311

906. By Augustin Cisterne-Kaas <email address hidden>

[ADD] Export categories and products. Import of product set attributes.

Revision history for this message
Augustin Cisterne-Kaas - www.elico-corp.com (ajite) wrote :

Hi Guewen,

Thank you for your feedback.

> Hi Augustin,
>
> Thanks for the MP.
> I read through the diff and that seems already nice, you very well understood
> the mechanisms and how the synchronizations are supposed to work and that
> makes me happy.
>
> I'll need to take more time to do a proper review, but I'm already reassured
> that you go in the right direction so I am quite comfortable if let you
> continue in this direction.
>

I am glad that I am heading in the right direction.

> There is just one thing I want to comment on, about the choice to push the
> records on save.
> Basically in your diff:
>
> push_on_save = record.backend_id.push_on_save
> if push_on_save:
>
> This option is to remove, any created or modified record must always me
> exported to Magento, that's the design we choose. So we don't need anymore the
> methods to export the products or categories like in l.411,498.
>

Don't you think that the "push on save" function might be useful for people in a marketing team who are working on a product description and want to save the changes as a draft before sending the final description to a backend ? I think that not having that option might lead to more mistakes from the end-users.

> Another thing about the monkey patching in l.522: this is a bad idea, because
> OpenERP may import the python code of uninstalled modules (it wouldn't have
> bad effects in this case, remark). There is other techniques [0][1] for
> replacing ConnectorUnit classes, but in that case I would just redefine the
> create method in the main 'magentoerpconnect' module.
>
>
> [0] https://code.launchpad.net/~openerp-connector-core-editors/openerp-
> connector/7.0-connector-replacing-connectorunit-classes/+merge/172309
> [1] https://code.launchpad.net/~openerp-connector-core-editors/openerp-
> connector/7.0-magentoerpconnect-replacing-connectorunit-classes/+merge/172311

I forgot to remove the monkey patch line 622. Hopefully you saw it ;)!

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

On 08/19/2013 09:13 AM, Augustin Cisterne-Kaas (www.elico-corp.com) wrote:
>
>> There is just one thing I want to comment on, about the choice to push the
>> records on save.
>> Basically in your diff:
>>
>> push_on_save = record.backend_id.push_on_save
>> if push_on_save:
>>
>> This option is to remove, any created or modified record must always me
>> exported to Magento, that's the design we choose. So we don't need anymore the
>> methods to export the products or categories like in l.411,498.
>>
>
> Don't you think that the "push on save" function might be useful for people in a marketing team who are working on a product description and want to save the changes as a draft before sending the final description to a backend ? I think that not having that option might lead to more mistakes from the end-users.
>

You are right, that could be a nice option, I would be more in favor of
a single field on the 'magento.product.product' or
'magento.product.category', a 'ready' boolean field, the export being
skipped while it is not True. I don't like the global option.

Although, for records which are already exported, we'll miss the sync of
the changes (in both cases, "push on save" global option or "ready"
field) if the option is deactivated and we don't push them manually and
that could be a problem.

Anyhow, I need a bit more reflexion on that, but my feeling is that for
such cases, we should never deactivate the exports and just use the
"visibility" or "active" field of Magento.

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

On 08/19/2013 09:51 AM, Guewen Baconnier @ Camptocamp wrote:
> Anyhow, I need a bit more reflexion on that, but my feeling is that for
> such cases, we should never deactivate the exports and just use the
> "visibility" or "active" field of Magento.
>
That would also prevent many issues with cross-linking between records,
e.g. export a child category but parent category's not yet exported, or
export a product linked (cross-sell, up-sell, ...) to a product not yet
exported.

--
Guewen Baconnier
Business Solutions Software Developer

Camptocamp SA
PSE A, CH-1015 Lausanne
Phone: +41 21 619 10 39
Office: +41 21 619 10 10
http://www.camptocamp.com/

907. By Augustin Cisterne-Kaas <email address hidden>

Removed Global "Push On Save" button

Revision history for this message
Augustin Cisterne-Kaas - www.elico-corp.com (ajite) wrote :

> On 08/19/2013 09:51 AM, Guewen Baconnier @ Camptocamp wrote:
> > Anyhow, I need a bit more reflexion on that, but my feeling is that for
> > such cases, we should never deactivate the exports and just use the
> > "visibility" or "active" field of Magento.
> >
> That would also prevent many issues with cross-linking between records,
> e.g. export a child category but parent category's not yet exported, or
> export a product linked (cross-sell, up-sell, ...) to a product not yet
> exported.
>
>
> --
> Guewen Baconnier
> Business Solutions Software Developer
>
> Camptocamp SA
> PSE A, CH-1015 Lausanne
> Phone: +41 21 619 10 39
> Office: +41 21 619 10 10
> http://www.camptocamp.com/

You are absolutely right.
I have removed the global "push on save" option. I will try to think about something else.

908. By Augustin Cisterne-Kaas <email address hidden>

[ADD] Added the unlink method.

909. By Augustin Cisterne-Kaas <email address hidden>

[FIX] Improved push of products

910. By Augustin Cisterne-Kaas <email address hidden>

[FIX] Removed debug message

Revision history for this message
Augustin Cisterne-Kaas - www.elico-corp.com (ajite) wrote :

I have improved the way data were sent. I have added some required attributes in 'magento.product.product'.

I was able to push 2500 products with custom attribute sets and custom attributes without any problem. I have created another module to handle the custom attributes that were needed for my case.

The write and unlink functions are both working well.

I am not happy with my import product category mapper. How can I improve it ? I have tried to use a binder but that did not work well... Is there anyway to avoid the O(n*m) loop ?

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

On 08/22/2013 12:08 PM, Augustin Cisterne-Kaas (www.elico-corp.com) wrote:
> I have improved the way data were sent. I have added some required attributes in 'magento.product.product'.
>
> I was able to push 2500 products with custom attribute sets and custom attributes without any problem. I have created another module to handle the custom attributes that were needed for my case.
>
> The write and unlink functions are both working well.
>

Nice news! I'll have a look.

> I am not happy with my import product category mapper. How can I improve it ? I have tried to use a binder but that did not work well... Is there anyway to avoid the O(n*m) loop ?
>
Just to be sure, you speak about ProductProductExportMapper.category()
right?
I don't think we can avoid the O(n*m) loop, at least using the ORM, we
could maybe do it with SQL but with a penalty in clarity.
However, we can simplify the function by iterating over a single list
(record.categ_id + record.categ_ids)

Untested:

     @mapping
     def category(self, record):
         all_categs = [record.categ_id] + record.categ_ids
         mag_categ_ids = [m_categ.magento_id for categ in all_categs
                          for m_categ in categ.magento_bind_ids
                          if m_categ.backend_id.id ==
self.backend_record.id]
     return {'categories': mag_categ_ids}

Revision history for this message
Augustin Cisterne-Kaas - www.elico-corp.com (ajite) wrote :

> > I am not happy with my import product category mapper. How can I improve it
> ? I have tried to use a binder but that did not work well... Is there anyway
> to avoid the O(n*m) loop ?
> >
> Just to be sure, you speak about ProductProductExportMapper.category()
> right?
> I don't think we can avoid the O(n*m) loop, at least using the ORM, we
> could maybe do it with SQL but with a penalty in clarity.
> However, we can simplify the function by iterating over a single list
> (record.categ_id + record.categ_ids)
>
> Untested:
>
> @mapping
> def category(self, record):
> all_categs = [record.categ_id] + record.categ_ids
> mag_categ_ids = [m_categ.magento_id for categ in all_categs
> for m_categ in categ.magento_bind_ids
> if m_categ.backend_id.id ==
> self.backend_record.id]
> return {'categories': mag_categ_ids}

Yes. The syntax looks much better like that even though it is still O(n*m). I will update it as soon as I possible.
I think that it's better to avoid the SQL request.

Unmerged revisions

910. By Augustin Cisterne-Kaas <email address hidden>

[FIX] Removed debug message

909. By Augustin Cisterne-Kaas <email address hidden>

[FIX] Improved push of products

908. By Augustin Cisterne-Kaas <email address hidden>

[ADD] Added the unlink method.

907. By Augustin Cisterne-Kaas <email address hidden>

Removed Global "Push On Save" button

906. By Augustin Cisterne-Kaas <email address hidden>

[ADD] Export categories and products. Import of product set attributes.

905. By Augustin Cisterne-Kaas <email address hidden>

[ADD] Export categories and products. Import of product set attributes.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'magentoerpconnect/__init__.py'
2--- magentoerpconnect/__init__.py 2013-05-02 12:30:40 +0000
3+++ magentoerpconnect/__init__.py 2013-08-22 07:24:16 +0000
4@@ -6,6 +6,7 @@
5 import magento_model
6 import product
7 import product_category
8+import product_attribute_set
9 import partner
10 import partner_category
11 import invoice
12
13=== modified file 'magentoerpconnect/magento_model.py'
14--- magentoerpconnect/magento_model.py 2013-08-15 08:01:46 +0000
15+++ magentoerpconnect/magento_model.py 2013-08-22 07:24:16 +0000
16@@ -218,6 +218,16 @@
17 'import_products_from_date', context=context)
18 return True
19
20+ def import_product_attribute_set(self, cr, uid, ids, context=None):
21+ if not hasattr(ids, '__iter__'):
22+ ids = [ids]
23+ self.check_magento_structure(cr, uid, ids, context=context)
24+ session = ConnectorSession(cr, uid, context=context)
25+ for backend_id in ids:
26+ import_batch.delay(session, 'magento.product.attribute.set',
27+ backend_id)
28+ return True
29+
30 def update_product_stock_qty(self, cr, uid, ids, context=None):
31 if not hasattr(ids, '__iter__'):
32 ids = [ids]
33
34=== modified file 'magentoerpconnect/magento_model_view.xml'
35--- magentoerpconnect/magento_model_view.xml 2013-08-15 08:01:46 +0000
36+++ magentoerpconnect/magento_model_view.xml 2013-08-22 07:24:16 +0000
37@@ -91,6 +91,13 @@
38 string="Import in background"/>
39 </group>
40 <group>
41+ <label string="Import product attribute sets" class="oe_inline"/>
42+ <button name="import_product_attribute_set"
43+ type="object"
44+ class="oe_highlight"
45+ string="Import in background"/>
46+ </group>
47+ <group>
48 <label string="Import sales orders from all store views" class="oe_inline"/>
49 <button name="import_sale_orders"
50 type="object"
51
52=== modified file 'magentoerpconnect/product.py'
53--- magentoerpconnect/product.py 2013-07-26 09:06:53 +0000
54+++ magentoerpconnect/product.py 2013-08-22 07:24:16 +0000
55@@ -79,12 +79,34 @@
56 # XXX website_ids can be computed from categories
57 'website_ids': fields.many2many('magento.website',
58 string='Websites',
59- readonly=True),
60+ required=True),
61 'created_at': fields.date('Created At (on Magento)'),
62 'updated_at': fields.date('Updated At (on Magento)'),
63 'product_type': fields.selection(_product_type_get,
64 'Magento Product Type',
65 required=True),
66+ 'attribute_set_id': fields.many2one('product.attribute.set',
67+ string='Attribute Set',
68+ required=True),
69+ 'visibility': fields.selection(
70+ [('1', 'Not Visible Individually'),
71+ ('2', 'Catalog'),
72+ ('3', 'Search'),
73+ ('4', 'Catalog, Search')],
74+ string='Visibility in Magento',
75+ required=True),
76+ 'tax_class': fields.selection(
77+ [('0', 'None'),
78+ ('2', 'Default'),
79+ ('3', 'Taxable Goods'),
80+ ('4', 'Shipping')],
81+ string='Tax Class in Magento',
82+ ),
83+ 'status': fields.selection(
84+ [('1', 'Enabled'),
85+ ('2', 'Disabled')],
86+ string='Status in Magento',
87+ required=True),
88 'manage_stock': fields.selection(
89 [('use_default', 'Use Default Config'),
90 ('no', 'Do Not Manage Stock'),
91@@ -195,6 +217,9 @@
92 in self._call('%s.list' % self._magento_model,
93 [filters] if filters else [{}])]
94
95+ def create(self, data):
96+ return self._call('%s.create'% self._magento_model,[data.pop('product_type'),data.pop('attrset'),data.pop('sku'),data])
97+
98 def read(self, id, storeview_id=None, attributes=None):
99 """ Returns the information of a record
100
101@@ -356,6 +381,9 @@
102 ('type_id', 'product_type'),
103 ('created_at', 'created_at'),
104 ('updated_at', 'updated_at'),
105+ ('visibility', 'visibility'),
106+ ('tax_class_id', 'tax_class'),
107+ ('status', 'status')
108 ]
109
110 @mapping
111@@ -372,6 +400,16 @@
112 return
113
114 @mapping
115+ def set(self, record):
116+ binder = self.get_binder_for_model('magento.product.attribute.set')
117+ set_id = binder.to_openerp(record['set'])
118+ if set_id is None:
119+ raise MappingError("The product attribute set with "
120+ "magento id %s is not imported." %
121+ record['set'])
122+ return {'attribute_set_id': set_id}
123+
124+ @mapping
125 def website_ids(self, record):
126 website_ids = []
127 binder = self.get_binder_for_model('magento.website')
128
129=== added file 'magentoerpconnect/product_attribute_set.py'
130--- magentoerpconnect/product_attribute_set.py 1970-01-01 00:00:00 +0000
131+++ magentoerpconnect/product_attribute_set.py 2013-08-22 07:24:16 +0000
132@@ -0,0 +1,94 @@
133+# -*- coding: utf-8 -*-
134+
135+import logging
136+from openerp.osv import fields, orm, osv
137+import openerp.addons.decimal_precision as dp
138+from openerp.addons.connector.unit.mapper import (mapping,
139+ ImportMapper,
140+ )
141+from .backend import magento
142+from openerp.addons.magentoerpconnect.unit.backend_adapter import GenericAdapter
143+from openerp.addons.magentoerpconnect.unit.import_synchronizer import (BatchImportSynchronizer,
144+ DelayedBatchImport,
145+ MagentoImportSynchronizer
146+ )
147+from openerp.addons.magentoerpconnect.unit.binder import MagentoModelBinder
148+from openerp.addons.connector.queue.job import job
149+
150+
151+from openerp.tools.translate import _
152+_logger = logging.getLogger(__name__)
153+
154+class product_attribute_set(orm.Model):
155+ _name = 'product.attribute.set'
156+
157+ _columns = {
158+ 'name': fields.char('name', required=True),
159+ 'magento_bind_ids': fields.one2many('magento.product.attribute.set', 'openerp_id',
160+ string="Magento Bindings"),
161+ }
162+
163+
164+
165+
166+
167+class magento_product_attribute_set(orm.Model):
168+ _name = 'magento.product.attribute.set'
169+ _inherit = 'magento.binding'
170+ _inherits = {'product.attribute.set': 'openerp_id'}
171+
172+ _columns = {
173+ 'openerp_id': fields.many2one('product.attribute.set',
174+ string='Magento order',
175+ required=True,
176+ ondelete='cascade'),
177+ 'created_at': fields.date('Created At (on Magento)'),
178+ 'updated_at': fields.date('Updated At (on Magento)'),
179+ }
180+
181+ _sql_constraints = [
182+ ('magento_uniq', 'unique(backend_id, magento_id)',
183+ 'A partner tag with same ID on Magento already exists.'),
184+ ]
185+
186+
187+@magento
188+class ProductAttributeSetBatchImport(MagentoImportSynchronizer):
189+ _model_name = ['magento.product.attribute.set']
190+
191+@magento
192+class ProductAttributeSetBatchImport(DelayedBatchImport):
193+ """ Import the Magento Products.
194+
195+ For every product category in the list, a delayed job is created.
196+ Import from a date
197+ """
198+ _model_name = ['magento.product.attribute.set']
199+
200+
201+@magento
202+class ProductAttributeSetAdapter(GenericAdapter):
203+ _model_name = 'magento.product.attribute.set'
204+ _magento_model = 'ol_catalog_product_attributeset'
205+
206+
207+@magento
208+class ProductAttributeSetImportMapper(ImportMapper):
209+ _model_name = 'magento.product.attribute.set'
210+
211+ direct = [('attribute_set_id', 'magento_id'),
212+ ('attribute_set_name', 'name')
213+ ]
214+
215+ @mapping
216+ def backend_id(self, record):
217+ return {'backend_id': self.backend_record.id}
218+
219+@job
220+def product_attribute_set_import_batch(session, model_name, backend_id, filters=None):
221+ """ Prepare a batch import of records from Magento """
222+ if filters is None:
223+ filters = {}
224+ env = get_environment(session, model_name, backend_id)
225+ importer = env.get_connector_unit(ProductAttributeSetBatchImport)
226+ importer.run(filters)
227\ No newline at end of file
228
229=== modified file 'magentoerpconnect/product_category.py'
230--- magentoerpconnect/product_category.py 2013-07-26 09:06:53 +0000
231+++ magentoerpconnect/product_category.py 2013-08-22 07:24:16 +0000
232@@ -49,6 +49,8 @@
233 required=True,
234 ondelete='cascade'),
235 'description': fields.text('Description', translate=True),
236+ 'is_active': fields.boolean('Active in magento'),
237+ 'include_in_menu': fields.boolean('Include in magento menu'),
238 'magento_parent_id': fields.many2one(
239 'magento.product.category',
240 string='Magento Parent Category',
241@@ -99,6 +101,9 @@
242 else:
243 raise
244
245+ def create(self, data):
246+ return self._call('%s.create'% self._magento_model,[data['parent_id'],data])
247+
248 def search(self, filters=None, from_date=None):
249 """ Search records according to some criterias and returns a
250 list of ids
251@@ -216,6 +221,8 @@
252
253 direct = [
254 ('description', 'description'),
255+ ('is_active','is_active'),
256+ ('include_in_menu','include_in_menu')
257 ]
258
259 @mapping
260
261=== modified file 'magentoerpconnect/product_view.xml'
262--- magentoerpconnect/product_view.xml 2013-04-03 12:12:56 +0000
263+++ magentoerpconnect/product_view.xml 2013-08-22 07:24:16 +0000
264@@ -68,7 +68,12 @@
265 <field name="magento_id"/>
266 <field name="created_at" readonly="1"/>
267 <field name="updated_at" readonly="1"/>
268+ <field name="visibility" />
269+ <field name="tax_class" />
270+ <field name="status" />
271 <field name="product_type" readonly="1"/>
272+ <field name="website_ids" />
273+ <field name="attribute_set_id" />
274 </group>
275 <group string="Inventory Options">
276 <field name="manage_stock"/>
277@@ -96,5 +101,22 @@
278 </field>
279 </record>
280
281+ <record id="product_attribute_set_action_form" model="ir.actions.act_window">
282+ <field name="name">Product Attribute Set</field>
283+ <field name="type">ir.actions.act_window</field>
284+ <field name="res_model">product.attribute.set</field>
285+ <field name="view_type">form</field>
286+ <field name="view_mode">tree,form</field>
287+ <field name="help" type="html">
288+ <p class="oe_view_nocontent_create">
289+ Click to create a product attribute set
290+ </p>
291+ </field>
292+ </record>
293+
294+ <menuitem action="product_attribute_set_action_form"
295+ groups="base.group_no_one"
296+ id="menu_product_attribute_set_action_form"
297+ parent="product.prod_config_main" sequence="3"/>
298 </data>
299 </openerp>
300
301=== modified file 'magentoerpconnect/unit/binder.py'
302--- magentoerpconnect/unit/binder.py 2013-05-02 12:30:40 +0000
303+++ magentoerpconnect/unit/binder.py 2013-08-22 07:24:16 +0000
304@@ -53,6 +53,7 @@
305 'magento.sale.order',
306 'magento.sale.order.line',
307 'magento.account.invoice',
308+ 'magento.product.attribute.set',
309 ]
310
311 def to_openerp(self, external_id, unwrap=False):
312
313=== modified file 'magentoerpconnect_catalog/__init__.py'
314--- magentoerpconnect_catalog/__init__.py 2013-03-19 15:41:34 +0000
315+++ magentoerpconnect_catalog/__init__.py 2013-08-22 07:24:16 +0000
316@@ -1,1 +1,6 @@
317 # -*- coding: utf-8 -*-
318+
319+import connector
320+import consumer
321+import product
322+import product_category
323\ No newline at end of file
324
325=== modified file 'magentoerpconnect_catalog/__openerp__.py'
326--- magentoerpconnect_catalog/__openerp__.py 2013-03-19 15:41:34 +0000
327+++ magentoerpconnect_catalog/__openerp__.py 2013-08-22 07:24:16 +0000
328@@ -26,7 +26,7 @@
329 'category': 'Connector',
330 'depends': ['magentoerpconnect',
331 'product_links',
332- 'product_images',
333+ #'product_images',
334 ],
335 'author': 'MagentoERPconnect Core Editors',
336 'license': 'AGPL-3',
337@@ -44,7 +44,7 @@
338 """,
339 'images': [],
340 'demo': [],
341- 'data': [],
342+ 'data': ['product_view.xml'],
343 'installable': True,
344 'application': False,
345 }
346
347=== added file 'magentoerpconnect_catalog/connector.py'
348--- magentoerpconnect_catalog/connector.py 1970-01-01 00:00:00 +0000
349+++ magentoerpconnect_catalog/connector.py 2013-08-22 07:24:16 +0000
350@@ -0,0 +1,12 @@
351+# -*- coding: utf-8 -*-
352+
353+from openerp.osv import orm
354+
355+
356+class magentoerpconnect_export_partner_installed(orm.AbstractModel):
357+ """Empty model used to know if the module is installed on the
358+ database.
359+
360+ If the model is in the registry, the module is installed.
361+ """
362+ _name = 'magentoerpconnect_catalog.installed'
363\ No newline at end of file
364
365=== added file 'magentoerpconnect_catalog/consumer.py'
366--- magentoerpconnect_catalog/consumer.py 1970-01-01 00:00:00 +0000
367+++ magentoerpconnect_catalog/consumer.py 2013-08-22 07:24:16 +0000
368@@ -0,0 +1,25 @@
369+# -*- coding: utf-8 -*-
370+
371+from functools import wraps
372+from openerp.addons.connector.event import (on_record_write,
373+ on_record_create,
374+ on_record_unlink
375+ )
376+from openerp.addons.magentoerpconnect.unit.export_synchronizer import export_record
377+import openerp.addons.magentoerpconnect.consumer as magentoerpconnect
378+
379+
380+@on_record_create(model_names=['magento.product.category', 'magento.product.product'])
381+@on_record_write(model_names=['magento.product.category', 'magento.product.product'])
382+def delay_export(session, model_name, record_id, fields=None):
383+ magentoerpconnect.delay_export(session, model_name,
384+ record_id, fields=fields)
385+
386+@on_record_write(model_names=['product.category','product.product'])
387+def delay_export_all_bindings(session, model_name, record_id, fields=None):
388+ magentoerpconnect.delay_export_all_bindings(session, model_name,
389+ record_id, fields=fields)
390+
391+@on_record_unlink(model_names=['magento.product.category', 'magento.product.product'])
392+def delay_unlink(session, model_name, record_id):
393+ magentoerpconnect.delay_unlink(session, model_name, record_id)
394
395=== added file 'magentoerpconnect_catalog/product.py'
396--- magentoerpconnect_catalog/product.py 1970-01-01 00:00:00 +0000
397+++ magentoerpconnect_catalog/product.py 2013-08-22 07:24:16 +0000
398@@ -0,0 +1,95 @@
399+# -*- coding: utf-8 -*-
400+
401+from openerp.osv import fields, orm, osv
402+from openerp.addons.connector.queue.job import job
403+from openerp.addons.connector.unit.mapper import (mapping,
404+ changed_by,
405+ ExportMapper)
406+from openerp.addons.magentoerpconnect.unit.delete_synchronizer import (
407+ MagentoDeleteSynchronizer)
408+from openerp.addons.magentoerpconnect.unit.export_synchronizer import (
409+ MagentoExporter)
410+from openerp.addons.magentoerpconnect.backend import magento
411+from openerp.addons.magentoerpconnect.product import ProductProductAdapter
412+from openerp.addons.connector.exception import MappingError
413+
414+@magento
415+class ProductProductDeleteSynchronizer(MagentoDeleteSynchronizer):
416+ """ Partner deleter for Magento """
417+ _model_name = ['magento.product.product']
418+
419+
420+@magento
421+class ProductProductExport(MagentoExporter):
422+ _model_name = ['magento.product.product']
423+
424+@magento
425+class ProductProductExportMapper(ExportMapper):
426+ _model_name = 'magento.product.product'
427+
428+ # direct = [('name', 'name'),
429+ # ('description', 'description'),
430+ # ('weight', 'weight'),
431+ # ('list_price', 'price'),
432+ # ('description_sale', 'short_description'),
433+ # ('default_code', 'sku'),
434+ # ('product_type', 'type'),
435+ # ('created_at', 'created_at'),
436+ # ('updated_at', 'updated_at'),
437+ # ('status', 'status'),
438+ # ('visibility', 'visibility'),
439+ # ('product_type', 'product_type')
440+ # ]
441+ @mapping
442+ def all(self, record):
443+ return {'name': record.name,
444+ 'description': record.description,
445+ 'weight': record.weight,
446+ 'price': record.list_price,
447+ 'short_description': record.description_sale,
448+ 'type': record.product_type,
449+ 'created_at': record.created_at,
450+ 'updated_at': record.updated_at,
451+ 'status': record.status,
452+ 'visibility': record.visibility,
453+ 'product_type': record.product_type }
454+
455+ @mapping
456+ def sku(self, record):
457+ sku = record.default_code
458+ if not sku:
459+ raise MappingError("The product attribute default code cannot be empty.")
460+ return {'sku': sku}
461+
462+ @mapping
463+ def set(self, record):
464+ binder = self.get_binder_for_model('magento.product.attribute.set')
465+ set_id = binder.to_backend(record.attribute_set_id.id)
466+ return {'attrset': set_id}
467+
468+ @mapping
469+ def tax(self, record):
470+ tax_class_id = record.tax_class if record.tax_class else 0
471+ return {'tax_class_id': tax_class_id}
472+
473+ @mapping
474+ def website_ids(self, record):
475+ website_ids = []
476+ for website_id in record.website_ids:
477+ magento_id = website_id.magento_id
478+ website_ids.append(magento_id)
479+ return {'website_ids': website_ids}
480+
481+ @mapping
482+ def category(self, record):
483+ categ_ids = []
484+ if record.categ_id:
485+ for m_categ in record.categ_id.magento_bind_ids:
486+ if m_categ.backend_id.id == self.backend_record.id:
487+ categ_ids.append(m_categ.magento_id)
488+
489+ for categ in record.categ_ids:
490+ for m_categ in categ.magento_bind_ids:
491+ if m_categ.backend_id.id == self.backend_record.id:
492+ categ_ids.append(m_categ.magento_id)
493+ return {'categories': categ_ids}
494
495=== added file 'magentoerpconnect_catalog/product_category.py'
496--- magentoerpconnect_catalog/product_category.py 1970-01-01 00:00:00 +0000
497+++ magentoerpconnect_catalog/product_category.py 2013-08-22 07:24:16 +0000
498@@ -0,0 +1,55 @@
499+# -*- coding: utf-8 -*-
500+
501+from openerp.osv import fields, orm, osv
502+from openerp.addons.connector.unit.mapper import (mapping,
503+ changed_by,
504+ ExportMapper)
505+from openerp.addons.magentoerpconnect.unit.delete_synchronizer import (
506+ MagentoDeleteSynchronizer)
507+from openerp.addons.magentoerpconnect.unit.export_synchronizer import (
508+ MagentoExporter)
509+from openerp.addons.magentoerpconnect.backend import magento
510+from openerp.addons.magentoerpconnect.product_category import ProductCategoryAdapter
511+
512+@magento
513+class ProductCategoryDeleteSynchronizer(MagentoDeleteSynchronizer):
514+ """ Partner deleter for Magento """
515+ _model_name = ['magento.product.category']
516+
517+
518+@magento
519+class ProductCategoryExport(MagentoExporter):
520+ _model_name = ['magento.product.category']
521+
522+@magento
523+class ProductCategoryExportMapper(ExportMapper):
524+ _model_name = 'magento.product.category'
525+
526+ direct = [('description', 'description'),
527+ ('name', 'name'), #change that to mapping top level category has no name
528+ ]
529+ @mapping
530+ def sort(self, record):
531+ return {'default_sort_by':'price', 'available_sort_by': 'price'}
532+
533+ @mapping
534+ def parent(self, record):
535+ """ Magento root category's Id equals 1 """
536+ parent_id = record.magento_parent_id.magento_id
537+ if not parent_id:
538+ parent_id = 1
539+ return {'parent_id':parent_id}
540+
541+ @mapping
542+ def active(self, record):
543+ is_active = record['is_active']
544+ if not is_active:
545+ is_active = 0
546+ return {'is_active':is_active}
547+
548+ @mapping
549+ def menu(self, record):
550+ include_in_menu = record['include_in_menu']
551+ if not include_in_menu:
552+ include_in_menu = 0
553+ return {'include_in_menu':include_in_menu}
554\ No newline at end of file
555
556=== added file 'magentoerpconnect_catalog/product_view.xml'
557--- magentoerpconnect_catalog/product_view.xml 1970-01-01 00:00:00 +0000
558+++ magentoerpconnect_catalog/product_view.xml 2013-08-22 07:24:16 +0000
559@@ -0,0 +1,16 @@
560+<?xml version="1.0" encoding="UTF-8"?>
561+<openerp>
562+ <data>
563+ <record id="view_magento_product_category_form" model="ir.ui.view">
564+ <field name="name">magento.product.category.form</field>
565+ <field name="model">magento.product.category</field>
566+ <field name="inherit_id" ref="magentoerpconnect.view_magento_product_category_form" />
567+ <field name="arch" type="xml" >
568+ <field name="magento_id" position="replace">
569+ <field name="is_active" />
570+ <field name="include_in_menu" />
571+ </field>
572+ </field>
573+ </record>
574+ </data>
575+</openerp>
576\ No newline at end of file