Merge lp:~camptocamp/magentoerpconnect/oerp61-oldstable-import-partners-2012-12-13 into lp:magentoerpconnect/oerp6.1-oldstable
- oerp61-oldstable-import-partners-2012-12-13
- Merge into trunk_version
Status: | Merged |
---|---|
Merged at revision: | 665 |
Proposed branch: | lp:~camptocamp/magentoerpconnect/oerp61-oldstable-import-partners-2012-12-13 |
Merge into: | lp:magentoerpconnect/oerp6.1-oldstable |
Diff against target: |
365 lines (+259/-55) 3 files modified
magentoerpconnect/magerp_data.xml (+54/-40) magentoerpconnect/partner.py (+65/-0) magentoerpconnect/sale.py (+140/-15) |
To merge this branch: | bzr merge lp:~camptocamp/magentoerpconnect/oerp61-oldstable-import-partners-2012-12-13 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Guewen Baconnier @ Camptocamp | Approve | ||
Review via email: mp+139728@code.launchpad.net |
Commit message
Description of the change
Implement the logic for global partner import
Plus add a check on SO import from magento to make sure a partner having the same email is updated before importing SO emitter partner (in case of an outdated and forgot account of the same customer to solve)
More detail on bug report:
lp:1083592
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
l108 it must filter on the website
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : | # |
l187 if website_id:
I don't think that it is possible to have a website_id which is 0, but if it could be the case we would preferably test if website is not None:
If a website_id could be 0, in that case, website_id is at first a string before we cast it to int.
It could be '0' but not 0
Seems fine to me like that
I will fix the rest ASAP
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : | # |
Filter added on website if website_id is defined.
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Yay, seems great now.
Thanks
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Just noticed that the cron is missing, can you add it please?
Thanks
- 668. By Yannick Vaucher @ Camptocamp
-
[ADD] magentoerpconnect - cron job for partner import
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : | # |
Here we go for the cron job
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
I fixed one thing during the merge: run_import_
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) : | # |
Preview Diff
1 | === modified file 'magentoerpconnect/magerp_data.xml' | |||
2 | --- magentoerpconnect/magerp_data.xml 2011-11-15 15:42:00 +0000 | |||
3 | +++ magentoerpconnect/magerp_data.xml 2013-01-09 15:14:26 +0000 | |||
4 | @@ -1,36 +1,36 @@ | |||
5 | 1 | <?xml version="1.0"?> | 1 | <?xml version="1.0"?> |
6 | 2 | <openerp> | 2 | <openerp> |
38 | 3 | <data noupdate="1"> | 3 | <data noupdate="1"> |
39 | 4 | 4 | ||
40 | 5 | <record id="product_product_cash_on_delivery" model="product.product"> | 5 | <record id="product_product_cash_on_delivery" model="product.product"> |
41 | 6 | <field name="default_code">CASH ON DELIVERY MAGENTO</field> | 6 | <field name="default_code">CASH ON DELIVERY MAGENTO</field> |
42 | 7 | <field name="list_price">0.0</field> | 7 | <field name="list_price">0.0</field> |
43 | 8 | <field name="standard_price">0.0</field> | 8 | <field name="standard_price">0.0</field> |
44 | 9 | <field name="type">service</field> | 9 | <field name="type">service</field> |
45 | 10 | <field name="name">Cash on delivery</field> | 10 | <field name="name">Cash on delivery</field> |
46 | 11 | <field name="magento_exportable" eval="False" /> | 11 | <field name="magento_exportable" eval="False" /> |
47 | 12 | <field name="categ_id" ref="base_sale_multichannels.categ_0"/> | 12 | <field name="categ_id" ref="base_sale_multichannels.categ_0"/> |
48 | 13 | </record> | 13 | </record> |
49 | 14 | 14 | ||
50 | 15 | <record id="product_product_gift" model="product.product"> | 15 | <record id="product_product_gift" model="product.product"> |
51 | 16 | <field name="default_code">GIFT CERTIFICATE</field> | 16 | <field name="default_code">GIFT CERTIFICATE</field> |
52 | 17 | <field name="list_price">0.0</field> | 17 | <field name="list_price">0.0</field> |
53 | 18 | <field name="standard_price">0.0</field> | 18 | <field name="standard_price">0.0</field> |
54 | 19 | <field name="type">service</field> | 19 | <field name="type">service</field> |
55 | 20 | <field name="name">Gift Certificate</field> | 20 | <field name="name">Gift Certificate</field> |
56 | 21 | <field name="magento_exportable" eval="False" /> | 21 | <field name="magento_exportable" eval="False" /> |
57 | 22 | <field name="categ_id" ref="base_sale_multichannels.categ_0"/> | 22 | <field name="categ_id" ref="base_sale_multichannels.categ_0"/> |
58 | 23 | </record> | 23 | </record> |
59 | 24 | 24 | ||
60 | 25 | <record id="product_product_discount" model="product.product"> | 25 | <record id="product_product_discount" model="product.product"> |
61 | 26 | <field name="default_code">DISCOUNT MAGENTO</field> | 26 | <field name="default_code">DISCOUNT MAGENTO</field> |
62 | 27 | <field name="list_price">0.0</field> | 27 | <field name="list_price">0.0</field> |
63 | 28 | <field name="standard_price">0.0</field> | 28 | <field name="standard_price">0.0</field> |
64 | 29 | <field name="type">service</field> | 29 | <field name="type">service</field> |
65 | 30 | <field name="name">Discount Coupon</field> | 30 | <field name="name">Discount Coupon</field> |
66 | 31 | <field name="magento_exportable" eval="False" /> | 31 | <field name="magento_exportable" eval="False" /> |
67 | 32 | <field name="categ_id" ref="base_sale_multichannels.categ_0"/> | 32 | <field name="categ_id" ref="base_sale_multichannels.categ_0"/> |
68 | 33 | </record> | 33 | </record> |
69 | 34 | 34 | ||
70 | 35 | <record forcecreate="True" id="ir_cron_import_orders_scheduler_action" model="ir.cron"> | 35 | <record forcecreate="True" id="ir_cron_import_orders_scheduler_action" model="ir.cron"> |
71 | 36 | <field name="name">Magento Import Orders</field> | 36 | <field name="name">Magento Import Orders</field> |
72 | @@ -136,15 +136,29 @@ | |||
73 | 136 | <field eval="'()'" name="args"/> | 136 | <field eval="'()'" name="args"/> |
74 | 137 | </record> | 137 | </record> |
75 | 138 | 138 | ||
76 | 139 | <record forcecreate="True" id="ir_cron_import_partners_scheduler_action" model="ir.cron"> | ||
77 | 140 | <field name="name">Magento Import Partners</field> | ||
78 | 141 | <field eval="False" name="active"/> | ||
79 | 142 | <field name="user_id" ref="base.user_root"/> | ||
80 | 143 | <field name="interval_number">1</field> | ||
81 | 144 | <field name="interval_type">days</field> | ||
82 | 145 | <field name="numbercall">-1</field> | ||
83 | 146 | <field eval="False" name="doall"/> | ||
84 | 147 | <field eval="'external.shop.group'" name="model"/> | ||
85 | 148 | <field eval="'run_import_partners_scheduler'" name="function"/> | ||
86 | 149 | <field eval="'()'" name="args"/> | ||
87 | 150 | </record> | ||
88 | 151 | |||
89 | 139 | <record id="payment_type1" model="base.sale.payment.type"> | 152 | <record id="payment_type1" model="base.sale.payment.type"> |
94 | 140 | <field name="name">checkmo;cashondelivery</field> | 153 | <field name="name">checkmo;cashondelivery</field> |
95 | 141 | <field name="order_policy">manual</field> | 154 | <field name="order_policy">manual</field> |
96 | 142 | </record> | 155 | </record> |
97 | 143 | 156 | ||
98 | 144 | <record id="payment_type2" model="base.sale.payment.type"> | 157 | <record id="payment_type2" model="base.sale.payment.type"> |
104 | 145 | <field name="name">ccsave;free;googlecheckout;paypayl_express;paybox_system;paypal_standard;servired_standard;bbva;cofidis</field> | 158 | <field name="name">ccsave;free;googlecheckout;paypayl_express;paybox_system;paypal_standard;servired_standard;bbva;cofidis</field> |
105 | 146 | <field name="order_policy">prepaid</field> | 159 | <field name="order_policy">prepaid</field> |
106 | 147 | </record> | 160 | </record> |
107 | 148 | 161 | ||
108 | 149 | </data> | 162 | |
109 | 163 | </data> | ||
110 | 150 | </openerp> | 164 | </openerp> |
111 | 151 | 165 | ||
112 | === modified file 'magentoerpconnect/partner.py' | |||
113 | --- magentoerpconnect/partner.py 2012-05-16 09:15:39 +0000 | |||
114 | +++ magentoerpconnect/partner.py 2013-01-09 15:14:26 +0000 | |||
115 | @@ -317,4 +317,69 @@ | |||
116 | 317 | 317 | ||
117 | 318 | return False, partner_id | 318 | return False, partner_id |
118 | 319 | 319 | ||
119 | 320 | def _ext_import_one(self, cr, uid, external_id, vals, external_data, referential_id, defaults=None, context=None): | ||
120 | 321 | """ Import one external resource | ||
121 | 322 | |||
122 | 323 | This method can be inherited to do an action which have to be done | ||
123 | 324 | within the same transaction than the import of the resource. | ||
124 | 325 | All the database operations done within _ext_import_one | ||
125 | 326 | will be rollbacked if any error occurs. | ||
126 | 327 | So no action on an external referential should be done within this method. | ||
127 | 328 | |||
128 | 329 | :param int external_id: id of the resource on the external referential | ||
129 | 330 | :param dict vals: vals converted to openerp | ||
130 | 331 | :param dict external_data: vals of the external resource before conversion | ||
131 | 332 | :param int referential_id: external referential id from where we import the resource | ||
132 | 333 | :param dict defaults: defaults value for fields which are not in vals | ||
133 | 334 | :return: tuple created id, updated id | ||
134 | 335 | """ | ||
135 | 336 | cid, wid = super(res_partner, self)._ext_import_one( | ||
136 | 337 | cr, uid, external_id, vals, external_data, referential_id, defaults=defaults, context=context) | ||
137 | 338 | |||
138 | 339 | partner_id = cid or wid | ||
139 | 340 | if partner_id: | ||
140 | 341 | partner = self.browse(cr, uid, partner_id, context=context) | ||
141 | 342 | |||
142 | 343 | # As a partner without addresses can't be opened | ||
143 | 344 | # we create a dummy empty address | ||
144 | 345 | if not partner.address: | ||
145 | 346 | new_empty_address = [(0, 0, {})] | ||
146 | 347 | partner.write({'address': new_empty_address}, context=context) | ||
147 | 348 | |||
148 | 349 | return cid, wid | ||
149 | 350 | |||
150 | 351 | def _import_partner_from_external( | ||
151 | 352 | self, | ||
152 | 353 | cr, uid, | ||
153 | 354 | partner_ext_id, | ||
154 | 355 | connection, | ||
155 | 356 | referential_id, | ||
156 | 357 | context=None): | ||
157 | 358 | """ | ||
158 | 359 | Import partner data from magento for a given id | ||
159 | 360 | |||
160 | 361 | :param partner_ext_id: magento id of customer to import | ||
161 | 362 | :param connection: connection data to magento | ||
162 | 363 | :param referential_id: referential id from where we import the ressource | ||
163 | 364 | """ | ||
164 | 365 | if context is None: | ||
165 | 366 | context = {} | ||
166 | 367 | imp_ctx = dict(context, | ||
167 | 368 | id=partner_ext_id) | ||
168 | 369 | result = self.get_external_data( | ||
169 | 370 | cr, uid, | ||
170 | 371 | connection, | ||
171 | 372 | referential_id, | ||
172 | 373 | defaults={}, | ||
173 | 374 | context=imp_ctx) | ||
174 | 375 | partner_id = self.extid_to_oeid( | ||
175 | 376 | cr, uid, partner_ext_id, referential_id, context=context) | ||
176 | 377 | |||
177 | 378 | # update the address book of the customer, this addresses | ||
178 | 379 | # will be available in the partner form and the searches | ||
179 | 380 | self.import_magento_address_book( | ||
180 | 381 | cr, uid, partner_id, referential_id, context=context) | ||
181 | 382 | |||
182 | 383 | return result | ||
183 | 384 | |||
184 | 320 | res_partner() | 385 | res_partner() |
185 | 321 | 386 | ||
186 | === modified file 'magentoerpconnect/sale.py' | |||
187 | --- magentoerpconnect/sale.py 2012-12-06 08:08:36 +0000 | |||
188 | +++ magentoerpconnect/sale.py 2013-01-09 15:14:26 +0000 | |||
189 | @@ -30,6 +30,7 @@ | |||
190 | 30 | from tools.translate import _ | 30 | from tools.translate import _ |
191 | 31 | import string | 31 | import string |
192 | 32 | #from datetime import datetime | 32 | #from datetime import datetime |
193 | 33 | from contextlib import closing | ||
194 | 33 | import tools | 34 | import tools |
195 | 34 | import time | 35 | import time |
196 | 35 | from tools import DEFAULT_SERVER_DATETIME_FORMAT | 36 | from tools import DEFAULT_SERVER_DATETIME_FORMAT |
197 | @@ -49,6 +50,113 @@ | |||
198 | 49 | 'waiting_date': 'holded'} | 50 | 'waiting_date': 'holded'} |
199 | 50 | SALE_ORDER_IMPORT_STEP = 200 | 51 | SALE_ORDER_IMPORT_STEP = 200 |
200 | 51 | 52 | ||
201 | 53 | |||
202 | 54 | class external_shop_group(magerp_osv.magerp_osv): | ||
203 | 55 | _inherit = 'external.shop.group' | ||
204 | 56 | |||
205 | 57 | @staticmethod | ||
206 | 58 | def _get_magento_partners(connection, from_date=False, website_id=False): | ||
207 | 59 | """ | ||
208 | 60 | Get data from magento of new and updated customers since a specific_date | ||
209 | 61 | |||
210 | 62 | :param connection: connection data to magento | ||
211 | 63 | :param from_data: date from which we get the changes | ||
212 | 64 | """ | ||
213 | 65 | filters = [] | ||
214 | 66 | if from_date: | ||
215 | 67 | filters = [ | ||
216 | 68 | {'created_at': {'gt': from_date}}, # OR | ||
217 | 69 | {'updated_at': {'gt': from_date}} | ||
218 | 70 | ] | ||
219 | 71 | if website_id: | ||
220 | 72 | if filters: | ||
221 | 73 | for f in filters: | ||
222 | 74 | f.update(website_id={'eq': website_id}) | ||
223 | 75 | else: | ||
224 | 76 | filters = [{'website_id': {'eq': website_id}}] | ||
225 | 77 | |||
226 | 78 | data = connection.call('customer.list', filters) | ||
227 | 79 | return data | ||
228 | 80 | |||
229 | 81 | def _import_partners(self, cr, uid, group, context=None): | ||
230 | 82 | """ | ||
231 | 83 | Import partners for a single shop group | ||
232 | 84 | |||
233 | 85 | :param group: browse record of an external.shop.group | ||
234 | 86 | """ | ||
235 | 87 | if context is None: context = {} | ||
236 | 88 | |||
237 | 89 | referential_id = group.referential_id.id | ||
238 | 90 | from_date = group.import_partners_from_date | ||
239 | 91 | website_id = self.oeid_to_extid(cr, uid, group.id, referential_id) | ||
240 | 92 | partner_obj = self.pool.get('res.partner') | ||
241 | 93 | result = super(external_shop_group, self)._import_partners( | ||
242 | 94 | cr, uid, group, | ||
243 | 95 | context=context) | ||
244 | 96 | |||
245 | 97 | ref_obj = self.pool.get('external.referential') | ||
246 | 98 | connection = context.get('conn_obj') or \ | ||
247 | 99 | ref_obj.external_connection( | ||
248 | 100 | cr, uid, referential_id, context=context) | ||
249 | 101 | |||
250 | 102 | [result.setdefault(key, []) for key in ['create_ids', 'write_ids', 'unchanged_ids']] | ||
251 | 103 | |||
252 | 104 | # Get partners from magento which where created or updated | ||
253 | 105 | # since last import | ||
254 | 106 | data = self._get_magento_partners(connection, from_date, website_id) | ||
255 | 107 | |||
256 | 108 | data.sort(key=lambda customer: customer['updated_at'] or customer['created_at']) | ||
257 | 109 | |||
258 | 110 | imp_ctx = dict(context, import_no_new_cr=True) | ||
259 | 111 | with closing(pooler.get_db(cr.dbname).cursor()) as local_cr: | ||
260 | 112 | # here we commit each partner updated or created as it can | ||
261 | 113 | # be an long processing and we want to be able to restart | ||
262 | 114 | # from the state when it failed | ||
263 | 115 | for customer in data: | ||
264 | 116 | ext_id = customer['customer_id'] | ||
265 | 117 | change_date = customer['updated_at'] or customer['created_at'] | ||
266 | 118 | try: | ||
267 | 119 | current_result = partner_obj._import_partner_from_external( | ||
268 | 120 | local_cr, uid, ext_id, | ||
269 | 121 | connection, referential_id, | ||
270 | 122 | context=imp_ctx) | ||
271 | 123 | except Exception as e: | ||
272 | 124 | local_cr.rollback() | ||
273 | 125 | if "res_partner_emailid_uniq" in e.message: | ||
274 | 126 | message = _("Cannot import a partner: " | ||
275 | 127 | "A partner with email %s already exists ")\ | ||
276 | 128 | % customer['email'] | ||
277 | 129 | raise osv.except_osv(_("Import Error"), message) | ||
278 | 130 | else: | ||
279 | 131 | raise | ||
280 | 132 | else: | ||
281 | 133 | self.write( | ||
282 | 134 | local_cr, uid, | ||
283 | 135 | group.id, | ||
284 | 136 | {'import_partners_from_date': change_date}, | ||
285 | 137 | context=context) | ||
286 | 138 | local_cr.commit() | ||
287 | 139 | result['create_ids'] += current_result.get('create_ids') | ||
288 | 140 | result['write_ids'] += current_result.get('write_ids') | ||
289 | 141 | |||
290 | 142 | return result | ||
291 | 143 | |||
292 | 144 | def run_import_partners_scheduler(self, cr, uid, context=None): | ||
293 | 145 | """ | ||
294 | 146 | Methode to launch the import on all external shop groups | ||
295 | 147 | to be used by a cron job | ||
296 | 148 | """ | ||
297 | 149 | group_ids = self.search(cr, uid, [], context=context) | ||
298 | 150 | |||
299 | 151 | if group_ids: | ||
300 | 152 | shop_groups = self.browse(cr, uid, ids, context=context) | ||
301 | 153 | |||
302 | 154 | for group in shop_groups: | ||
303 | 155 | self._import_partners(cr, uid, group, context=context) | ||
304 | 156 | |||
305 | 157 | |||
306 | 158 | external_shop_group() | ||
307 | 159 | |||
308 | 52 | class sale_shop(magerp_osv.magerp_osv): | 160 | class sale_shop(magerp_osv.magerp_osv): |
309 | 53 | _inherit = "sale.shop" | 161 | _inherit = "sale.shop" |
310 | 54 | 162 | ||
311 | @@ -340,22 +448,39 @@ | |||
312 | 340 | cr, uid, customer_record, referential_id, | 448 | cr, uid, customer_record, referential_id, |
313 | 341 | defaults=partner_defaults, context=context) | 449 | defaults=partner_defaults, context=context) |
314 | 342 | else: | 450 | else: |
315 | 451 | ext_id = data_record['customer_id'] | ||
316 | 452 | connection = context.get('conn_obj') | ||
317 | 453 | website_id = data_record.get('website_id') | ||
318 | 454 | if website_id: | ||
319 | 455 | website_id = int(data_record['website_id']) | ||
320 | 456 | # check if another customer exists | ||
321 | 457 | existing_id = partner_obj.search_magento_partner( | ||
322 | 458 | cr, uid, | ||
323 | 459 | data_record['customer_email'], | ||
324 | 460 | website_id, | ||
325 | 461 | context=context) | ||
326 | 462 | if existing_id: | ||
327 | 463 | # check if the ext_id is the same | ||
328 | 464 | # to make sure it isn't some outdated data | ||
329 | 465 | # This could happen when a customer change his email | ||
330 | 466 | # from A to B on a old account and create | ||
331 | 467 | # a new account with A address. | ||
332 | 468 | # in such case we want to make sure the old account is | ||
333 | 469 | # updated | ||
334 | 470 | existing_ext_id = partner_obj.oeid_to_extid(cr, uid, existing_id, referential_id) | ||
335 | 471 | if existing_ext_id != ext_id: | ||
336 | 472 | partner_obj._import_partner_from_external( | ||
337 | 473 | cr, uid, existing_ext_id, | ||
338 | 474 | connection, referential_id, | ||
339 | 475 | context=context) | ||
340 | 476 | |||
341 | 343 | # always update the customer when importing an order | 477 | # always update the customer when importing an order |
357 | 344 | imp_ctx = dict(context) | 478 | result = partner_obj._import_partner_from_external( |
358 | 345 | imp_ctx['id'] = data_record['customer_id'] | 479 | cr, uid, ext_id, |
359 | 346 | partner_obj.get_external_data( | 480 | connection, referential_id, |
360 | 347 | cr, uid, | 481 | context=context) |
361 | 348 | context.get('conn_obj'), | 482 | partner_id = (result['create_ids'] and result['create_ids'][0] |
362 | 349 | referential_id, | 483 | or result['write_ids'] and result['write_ids'][0]) |
348 | 350 | defaults={}, | ||
349 | 351 | context=imp_ctx) | ||
350 | 352 | partner_id = partner_obj.extid_to_oeid( | ||
351 | 353 | cr, uid, data_record['customer_id'], referential_id) | ||
352 | 354 | |||
353 | 355 | # update the address book of the customer, this addresses | ||
354 | 356 | # will be available in the partner form and the searches | ||
355 | 357 | partner_obj.import_magento_address_book( | ||
356 | 358 | cr, uid, partner_id, referential_id, context=context) | ||
363 | 359 | 484 | ||
364 | 360 | # The addresses of the sale order are imported as active=false | 485 | # The addresses of the sale order are imported as active=false |
365 | 361 | # so they are linked with the sale order but they are not displayed | 486 | # so they are linked with the sale order but they are not displayed |
you may want to remove the FIXME tag at line 31 as you have fixed the issue ;-)
@nitpicking
l89. missing blank line
l93, l111 extra blank lines
The pep8 convention specifies 2 lines before classes and top level-functions and 1 single line between methods in class definition [0]
l112 'import_partners' should preferably be '_import_partners' because it can't be called from the outside (with XML/RPC for instance) due to the browse_record argument.
l158 useless parenthesis
l187 if website_id:
I don't think that it is possible to have a website_id which is 0, but if it could be the case we would preferably test if website is not None:
l189 mini typo s/an other/another/
l200
from A to B on a old account and create a new account with B address.
shouldn't it be?
from A to B on a old account and create a new account with A address.
Apart of these details (not all of them need to be changed, but please check the comment at l200), it sounds good to me, but I'll review the corresponding merge in extra-trunk and come back here.
[0] http:// www.python. org/dev/ peps/pep- 0008/#blank- lines