1
# -*- encoding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (c) 2008 Zikzakmedia S.L. (http://zikzakmedia.com) All Rights Reserved.
6
# Jordi Esteve <jesteve@zikzakmedia.com>
7
# NaN Projectes de Programari Lliure, S.L. (http://www.nan-tic.com)
10
# This program is free software: you can redistribute it and/or modify
11
# it under the terms of the GNU General Public License as published by
12
# the Free Software Foundation, either version 3 of the License, or
13
# (at your option) any later version.
15
# This program is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
# GNU General Public License for more details.
20
# You should have received a copy of the GNU General Public License
21
# along with this program. If not, see <http://www.gnu.org/licenses/>.
23
##############################################################################
25
from osv import fields,osv,orm
27
from tools.translate import _
30
class esale_oscom_product_manufacturer(osv.osv):
31
_name = 'product.manufacturer'
32
_description = 'Product Manufacturer that produces the product'
34
'name':fields.char('Name', size=64, required=True, select="1"),
35
'manufacturer_url':fields.char('URL', size=128, select="2", translate=True),
37
esale_oscom_product_manufacturer()
40
class esale_oscom_product_inherit(osv.osv):
41
_inherit = 'product.product'
44
'product_url':fields.char('URL', size=64, translate=True),
45
'in_out_stock':fields.selection([('1','In Stock'), ('0','Out Stock')], 'In/Out Stock'),
46
'product_picture':fields.char('Product Picture', size=64),
47
'date_available':fields.date('Available Date'),
48
'manufacturer_id':fields.many2one('product.manufacturer',' Manufacturer'),
49
'spe_price':fields.char('Special price', size=8),
50
'exp_date':fields.datetime('Expiry date'),
51
'spe_price_status':fields.selection([('1','On'), ('0','Off')], 'Status'),
52
'oscom_url':fields.char('URL to OScommerce', size=256, readonly=True),
55
'in_out_stock' : lambda *a:'0',
56
'spe_price_status':lambda *a:'0',
59
def create(self, cr, uid, vals, context=None):
60
esale_web_obj = self.pool.get('esale.oscom.web')
61
esale_category_obj = self.pool.get('esale.oscom.category')
63
ret_create = super(esale_oscom_product_inherit,self).create(cr, uid, vals, context)
64
print "Creating product."
66
category_id = self.browse(cr, uid, ret_create).categ_id.id
67
category_maping_ids = esale_category_obj.search(cr, uid, [('category_id','=',category_id)])
68
if len(category_maping_ids):
69
print "Product CREATED. New category is mapped to OScommerce => update OScommerce products"
70
#self.oscom_export(cr, uid, product_ids=[ret_create], context=context)
73
def check_update_products( self, vals ):
76
def write(self, cr, uid, ids, vals, context=None):
77
esale_category_obj = self.pool.get('esale.oscom.category')
78
esale_product_obj = self.pool.get('esale.oscom.product')
80
ret_write = super(esale_oscom_product_inherit,self).write(cr, uid, ids, vals, context)
81
if not self.check_update_products( vals ):
83
esale_product_ids = esale_product_obj.search(cr, uid, [('product_id','in',ids)])
84
esale_products = esale_product_obj.browse(cr, uid, esale_product_ids)
85
category_id = vals.get('categ_id', False)
87
# OpenERP products mapped to OScommerce
88
product_ids = [x.product_id.id for x in esale_products]
89
if len(product_ids) and ret_write:
90
if category_id: # Updated product category field
91
category_maping_ids = esale_category_obj.search(cr, uid, [('category_id','=',category_id)])
92
if len(category_maping_ids):
93
print "New category is mapped to OScommerce => update OScommerce products"
94
#self.oscom_export(cr, uid, product_ids=product_ids, context=context)
96
print "New category is not mapped to OScommerce => delete OScommerce products"
97
#esale_product_obj.unlink(cr, uid, esale_product_ids, context)
99
print "No updated product category field (same category => update OScommerce products)"
100
#self.oscom_export(cr, uid, product_ids=product_ids, context=context)
102
# OpenERP products not mapped to OScommerce
103
product_no_ids = [x for x in ids if x not in product_ids]
104
if len(product_no_ids) and ret_write:
105
if category_id: # Updated product category field
106
category_maping_ids = esale_category_obj.search(cr, uid, [('category_id','=',category_id)])
107
if len(category_maping_ids):
108
print "Previously NOT MAPPED. New category is mapped to OScommerce => update OScommerce products"
109
#self.oscom_export(cr, uid, product_ids=product_no_ids, context=context)
112
def unlink(self, cr, uid, ids, context=None):
113
esale_product_obj = self.pool.get('esale.oscom.product')
114
esale_product_ids = esale_product_obj.search(cr, uid, [('product_id','in',ids)])
115
if len(esale_product_ids):
116
esale_product_obj.unlink(cr, uid, esale_product_ids, context)
117
ret_del = super(esale_oscom_product_inherit,self).unlink(cr, uid, ids, context)
120
def _check_spe_price(self, cr, uid, ids):
121
products = self.browse(cr, uid, ids)
124
spe_price = p.spe_price
126
if spe_price.find('%') > 0:
127
float(spe_price[0:-1])
135
(_check_spe_price, _('You can not give other value in Special Price! Please enter number with % or decimal value'), ['spe_price'])
138
def product_fields(self, esale_product):
139
"""If you want compute additional product fields you can redefine this method in your own module"""
141
#'field_name': esale_product['field_name']
146
def product_trans_fields(self, product):
147
"""If you want compute additional product translatable fields you can redefine this method in your own module"""
149
#'field_name': product['field_name']
154
def product_extra_info(self, cr, uid, website, esale_product):
155
"""If you want compute extra information from other OpenERP objects to send to OScommerce you can redefine this method in your own module"""
161
def product_extra_info_extra_fields(self, cr, uid, website, esale_product):
162
"""If you want compute extra information from other OpenERP objects to send to OScommerce you can redefine this method in your own module"""
168
def product_extra_info_m2m(self, cr, uid, website, esale_product):
169
"""If you want compute extra information from other OpenERP objects to send to OScommerce you can redefine this method in your own module"""
176
def product_images(self, cr, uid, esale_product):
177
"""Adds images from attachment or field"""
178
attach_obj = self.pool.get('ir.attachment')
179
product = esale_product.product_id
182
attach_ids = attach_obj.search(cr, uid, [('res_model','=','product.product'), ('res_id','=',product.id)])
183
attachs = attach_obj.browse(cr, uid, attach_ids)
184
if len(attachs): # Picture attached to product object
186
vals['picture'] = attachs[0].datas
187
vals['fname'] = attachs[0].datas_fname
188
elif product.product_picture: # URL to external picture
190
vals['fname'] = product.product_picture
196
def oscom_export(self, cr, uid, website=None, product_ids=[], context={}):
197
"""Export product_ids to OScommerce website (all the websites where there are product_ids if website is not defined)"""
198
esale_web_obj = self.pool.get('esale.oscom.web')
199
esale_category_obj = self.pool.get('esale.oscom.category')
200
esale_product_obj = self.pool.get('esale.oscom.product')
201
category_obj = self.pool.get('product.category')
202
product_obj = self.pool.get('product.product')
203
pricelist_obj = self.pool.get('product.pricelist')
204
tax_obj = self.pool.get('account.tax')
205
manufacturer_obj = self.pool.get('product.manufacturer')
213
products = product_obj.browse(cr, uid, product_ids)
214
category_ids = [x.categ_id.id for x in products]
215
category_maping_ids = esale_category_obj.search(cr, uid, [('category_id','in',category_ids)])
216
category_mapings = esale_category_obj.browse(cr, uid, category_maping_ids)
217
web_ids = [x.web_id.id for x in category_mapings]
218
for web_id in web_ids:
219
websites[web_id] = product_ids
221
websites[website.id] = product_ids
223
# Main loop for the web shops
224
websites_objs = esale_web_obj.browse(cr, uid, websites.keys())
226
for website in websites_objs:
227
print "%s/openerp-synchro.php" % website.url
228
server = xmlrpclib.ServerProxy("%s/openerp-synchro.php" % website.url)
229
website_url = website.url.split("/")
231
# Pricelist of the web shop
232
pricelist = website.shop_id.pricelist_id.id
234
raise osv.except_osv(_('User Error'), _('You must define a pricelist in the sale shop associated to the web shop!'))
236
# Taxes of the web shop
238
for oscom_tax in website.tax_ids:
239
tiny_tax_id = oscom_tax.tax_id and oscom_tax.tax_id.id
241
tax_maping[oscom_tax.esale_oscom_id] = tiny_tax_id
243
# Loop for the OpenERP products
244
esale_products_ids = []
245
web_product_ids = websites.get(website.id, False)
246
products = product_obj.browse(cr, uid, web_product_ids)
247
print website.id, web_product_ids
248
for product in products:
249
exist_esale_products_ids = esale_product_obj.search(cr, uid, [('web_id','=',website.id), ('product_id','=',product.id)])
250
if not len(exist_esale_products_ids):
254
'product_id':product.id,
257
new_esale_product_id = esale_product_obj.create(cr, uid, create_dict)
258
esale_products_ids.append(new_esale_product_id)
259
print "==================== Esale oscom no existe. Subiendo nuevo prod creado en open: " ,new_esale_product_id
261
esale_products_ids.append(exist_esale_products_ids[0])
262
print "==================== Esale oscom existe. Subiendo id open existente: " , exist_esale_products_ids[0]
265
# Loop for the web shop products
266
esale_products = esale_product_obj.browse(cr, uid, esale_products_ids)
267
for esale_product in esale_products:
268
print "==================== Esale oscom existe. Subiendo id oscom existente: " , esale_product.esale_oscom_id
271
category_id = esale_product.product_id.categ_id.id
272
category_ids = esale_category_obj.search(cr, uid, [('web_id','=', website.id), ('category_id', '=', category_id)])
273
if len(category_ids) > 0:
274
category_id = esale_category_obj.browse(cr, uid, category_ids[0]).esale_oscom_id
279
tax_ids = [x.id for x in esale_product.product_id.taxes_id]
282
if tax_ids[0] in tax_maping.values():
283
tax_class_id = tax_maping.keys()[tax_maping.values().index(tax_ids[0])]
285
'product_id' : esale_product.esale_oscom_id,
286
'quantity' : product_obj._product_available(cr, uid, [esale_product.product_id.id], ['virtual_available'], False, {'shop':website.shop_id.id})[esale_product.product_id.id]['virtual_available'],
287
'model' : esale_product.product_id.code,
288
'weight' : float(esale_product.product_id.weight),
289
'status' : int(esale_product.product_id.in_out_stock),
290
'tax_class_id' : tax_class_id,
291
'category_id' : category_id,
292
'date_available' : esale_product.product_id.date_available or 'NULL',
293
'exp_date' : esale_product.product_id.exp_date or 'NULL',
294
'spe_price' : esale_product.product_id.spe_price,
295
'spe_price_status': esale_product.product_id.spe_price_status
297
print "====================webproduct en primera ===================",esale_product.product_id.code
300
webproduct.update(self.product_fields(esale_product)) # Adds additional fields
301
webproduct.update(self.product_images(cr, uid, esale_product)) # Adds image fields
302
webproduct.update(self.product_extra_info(cr, uid, website, esale_product)) # Adds extra fields computed from other OpenERP objects
305
if website.price_type == '0':
306
webproduct['price'] = pricelist_obj.price_get(cr, uid, [pricelist], esale_product.product_id.id, 1, 'list')[pricelist].__str__()
307
#print "LIST PRICE:::::::::::::::::::",webproduct['price']
309
tax_ids = esale_product.product_id.taxes_id
310
#print "\TAX_IDS:::::::::::::::::",tax_ids
312
tax_amount = tax_obj.browse(cr, uid, tax_ids[0]).amount
315
#print"\TAX BROWSE:::::::::::::::::::",tax_amount
316
t_price = (pricelist_obj.price_get(cr, uid, [pricelist], esale_product.product_id.id, 1, 'list')[pricelist]) / (1 + tax_amount)
317
webproduct['price'] = round(t_price,5).__str__()
318
#print "FROM TAX PRICE:::::::::::::", webproduct['price']
320
# Get multi language attributes
322
manufacturer_langs = {}
323
for lang in website.language_ids:
324
if lang.language_id and lang.language_id.translatable:
325
product = product_obj.browse(cr, uid, esale_product.product_id.id, {'lang': lang.language_id.code})
326
langs[str(lang.esale_oscom_id)] = {
327
'name': product.name or '',
328
'description': product.description_sale or '',
329
'url': product.product_url or '',
331
langs[str(lang.esale_oscom_id)].update(self.product_trans_fields(product)) # Adds additional fields
332
#print "==========trans========="
333
#print lang.esale_oscom_id, langs[str(lang.esale_oscom_id)]
334
if esale_product.product_id.manufacturer_id:
335
manufacturer = manufacturer_obj.browse(cr, uid, esale_product.product_id.manufacturer_id.id, {'lang': lang.language_id.code})
336
manufacturer_langs[str(lang.esale_oscom_id)] = {
337
'manufacturers_url': manufacturer.manufacturer_url or '',
340
webproduct['langs'] = langs
341
webproduct['name'] = esale_product.product_id.name
342
webproduct['description'] = esale_product.product_id.description_sale or ''
343
webproduct['url'] = esale_product.product_id.product_url or ''
345
if esale_product.product_id.manufacturer_id:
346
webproduct['manufacturers_name'] = esale_product.product_id.manufacturer_id.name
347
webproduct['manufacturers_url'] = esale_product.product_id.manufacturer_id.manufacturer_url or ''
348
webproduct['manufacturer_langs'] = manufacturer_langs
349
print "====================webproduct en segunda ===================", esale_product.product_id.code
352
# Sends product to web shop
353
prod_id = webproduct['product_id']
354
print "======enviando producto===", prod_id
357
if webproduct['spe_price']:
358
price = float(webproduct['price'])
359
spe_price = webproduct['spe_price']
360
if spe_price.find('%') > 0:
361
spe_price = spe_price[0:-1]
362
spe_price = "%.4f" % (price - (price*float(spe_price)/100))
363
webproduct['spe_price'] = spe_price
364
oscom_id = server.set_product_spe(webproduct)
365
print "======actualizando producto en oferta===", oscom_id
366
elif not webproduct['spe_price']:
367
print "==============en set classical1" , esale_product.product_id.code
368
oscom_id = server.set_product_classical(webproduct)
369
print "======actualizando producto sin oferta===", oscom_id
370
server.del_spe_price(prod_id)
372
if (webproduct['spe_price'] == 0):
373
print "==============en set classical2" , esale_product.product_id.code
374
oscom_id = server.set_product_classical(webproduct)
376
elif (webproduct['spe_price'] != 0):
377
oscom_id = server.set_product_spe(webproduct)
379
if oscom_id != esale_product.esale_oscom_id:
380
esale_product_obj.write(cr, uid, [esale_product.id], {'esale_oscom_id': oscom_id})
386
self.product_extra_info_extra_fields(cr, uid, website, esale_product)
387
self.product_extra_info_m2m(cr, uid, website, esale_product)
389
#####################PRODUCT URL IN OSCOMMERCE###################
390
esale_prod_ids = esale_product_obj.search(cr, uid, [('esale_oscom_id','=',oscom_id)])
391
esale_prod = esale_product_obj.browse(cr, uid, esale_prod_ids[0])
392
#print "ESALE PROD DATA (id, web, product, category):",esale_prod.id, esale_prod.web_id.id, esale_prod.product_id.id, esale_prod.product_id.categ_id.id
393
prod_url = website_url[0] + "//" + website_url[2] + "/" +"product_info.php?cPath=" + str(category_id) + "&products_id=" + str(oscom_id)
394
super(esale_oscom_product_inherit, self).write(cr, uid, esale_prod.product_id.id, {'oscom_url': prod_url})
396
# Remove delete products
397
#delete_esale_products_ids = esale_product_obj.search(cr, uid, [('web_id','=',website.id),('product_id','=',False)])
398
#esale_products = esale_product_obj.browse(cr, uid, delete_esale_products_ids)
399
#delete_oscom_ids = tuple([x.esale_oscom_id for x in esale_products])
400
#prod_delete = len(delete_esale_products_ids)
402
#ret_delete = server.remove_product({'oscom_product_ids' : delete_oscom_ids})
404
#esale_product_obj.unlink(cr, uid, delete_esale_products_ids)
406
return {'prod_new':prod_new, 'prod_update':prod_update, 'prod_delete': prod_delete}
409
def oscom_update_stock(self, cr, uid, website = None, product_ids=[], context={}):
410
"""Update stock for product_ids to OScommerce website (all the websites where there are product_ids if website is not defined)"""
411
esale_web_obj = self.pool.get('esale.oscom.web')
412
esale_product_obj = self.pool.get('esale.oscom.product')
413
product_obj = self.pool.get('product.product')
418
cr.execute('select distinct(web_id) from esale_oscom_product where product_id in (%s)'%','.join([str(x) for x in product_ids]))
419
web_ids = [web[0] for web in cr.fetchall()]
420
websites_objs = esale_web_obj.browse(cr, uid, web_ids)
422
websites_objs.append(website)
423
for website in websites_objs:
424
server = xmlrpclib.ServerProxy("%s/openerp-synchro.php" % website.url)
426
esale_products = website.product_ids
428
esale_product_ids = esale_product_obj.search(cr, uid, [('web_id','=',website.id), ('product_id','in',product_ids)])
429
esale_products = esale_product_obj.browse(cr, uid, esale_product_ids)
430
for esale_product in esale_products:
432
'product_id': esale_product.esale_oscom_id,
433
'quantity': product_obj._product_available(cr, uid, [esale_product.product_id.id], ['virtual_available'], False, {'shop':website.shop_id.id})[esale_product.product_id.id]['virtual_available']
435
oscom_id = server.set_product_stock(webproduct)
439
## def on_change_gross_price(self, cr, uid, ids, list_price):
442
## product = self.pool.get('product.product').browse(cr, uid, ids[0])
443
## if not product.taxes_id:
446
## VAT = product.taxes_id[0].amount
447
## gr_pr = list_price *(1 + VAT)
449
## raise osv.except_osv(_('Could not change the price!'), _('You must first save the record and then enter price.'))
454
## return {'value':{'gross_price':gr_pr,'list_price':list_price}}
457
## def on_change_list_price(self, cr, uid, ids, gross_price):
460
## product = self.pool.get('product.product').browse(cr, uid, ids[0])
461
## if not product.taxes_id:
464
## VAT = product.taxes_id[0].amount
465
## l_pr = gross_price / (1 + VAT)
467
## raise osv.except_osv(_('Could not change the price!'), _('You must first save the record and then enter price.'))
472
## return {'value':{'list_price':l_pr, 'gross_price':gross_price}}
474
def oscom_import(self, cr, uid, website=None, esale_oscom_ids=[], context={}):
475
"""Import product_ids from OScommerce website (all the websites where there are product_ids if website is not defined)"""
476
esale_web_obj = self.pool.get('esale.oscom.web')
477
esale_product_obj = self.pool.get('esale.oscom.product')
478
print "En oscom_import Website", website
479
print "En oscom_import Productos", esale_oscom_ids
481
for esale_id in esale_oscom_ids :
482
print "id interno", esale_id
483
oscom_obj = esale_product_obj.browse(cr, uid, esale_id)
484
oscom_id = oscom_obj.esale_oscom_id
485
print "id Oscommerce", oscom_id
486
esale_web_obj.selected_product_import_create(cr, uid, website, [oscom_id] )
489
return {'prod_update':prod_update}
491
esale_oscom_product_inherit()