main.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. # -*- coding: utf-8 -*-
  2. # Part of Biztech Consultancy. See LICENSE file for full copyright and licensing details.
  3. import werkzeug
  4. from openerp import http
  5. from openerp.http import request
  6. from openerp import SUPERUSER_ID
  7. from openerp.addons.website.models.website import slug
  8. from openerp.addons.website_sale.controllers.main import QueryURL
  9. from openerp.addons.website_sale.controllers.main import get_pricelist
  10. from openerp.addons.web.controllers.main import login_redirect
  11. from openerp.addons.website_sale.controllers.main import website_sale
  12. import re
  13. PPG = 12 # Products Per Page
  14. PPR = 3 # Products Per Row
  15. class table_compute(object):
  16. def __init__(self):
  17. self.table = {}
  18. def _check_place(self, posx, posy, sizex, sizey):
  19. res = True
  20. for y in range(sizey):
  21. for x in range(sizex):
  22. if posx+x>=PPR:
  23. res = False
  24. break
  25. row = self.table.setdefault(posy+y, {})
  26. if row.setdefault(posx+x) is not None:
  27. res = False
  28. break
  29. for x in range(PPR):
  30. self.table[posy+y].setdefault(x, None)
  31. return res
  32. def process(self, products):
  33. # Compute products positions on the grid
  34. minpos = 0
  35. index = 0
  36. maxy = 0
  37. for p in products:
  38. x = min(max(p.website_size_x, 1), PPR)
  39. y = min(max(p.website_size_y, 1), PPR)
  40. if index>=PPG:
  41. x = y = 1
  42. pos = minpos
  43. while not self._check_place(pos%PPR, pos/PPR, x, y):
  44. pos += 1
  45. # if 21st products (index 20) and the last line is full (PPR products in it), break
  46. # (pos + 1.0) / PPR is the line where the product would be inserted
  47. # maxy is the number of existing lines
  48. # + 1.0 is because pos begins at 0, thus pos 20 is actually the 21st block
  49. # and to force python to not round the division operation
  50. if index >= PPG and ((pos + 1.0) / PPR) > maxy:
  51. break
  52. if x==1 and y==1: # simple heuristic for CPU optimization
  53. minpos = pos/PPR
  54. for y2 in range(y):
  55. for x2 in range(x):
  56. self.table[(pos/PPR)+y2][(pos%PPR)+x2] = False
  57. self.table[pos/PPR][pos%PPR] = {
  58. 'product': p, 'x':x, 'y': y,
  59. 'class': " ".join(map(lambda x: x.html_class or '', p.website_style_ids))
  60. }
  61. if index<=PPG:
  62. maxy=max(maxy,y+(pos/PPR))
  63. index += 1
  64. # Format table according to HTML needs
  65. rows = self.table.items()
  66. rows.sort()
  67. rows = map(lambda x: x[1], rows)
  68. for col in range(len(rows)):
  69. cols = rows[col].items()
  70. cols.sort()
  71. x += len(cols)
  72. rows[col] = [c for c in map(lambda x: x[1], cols) if c != False]
  73. return rows
  74. # TODO keep with input type hidden
  75. class biztech_theme(http.Controller):
  76. # For multi product slider
  77. @http.route(['/kingfisher_pro/product_multi_get_options'], type='json', auth="public", website=True)
  78. def product_multi_get_slider_options(self):
  79. slider_options = []
  80. option = request.env['multi.slider.config'].search(
  81. [('active', '=', True)], order="name asc")
  82. for record in option:
  83. slider_options.append({'id': record.id,
  84. 'name': record.name})
  85. return slider_options
  86. @http.route(['/kingfisher_pro/product_multi_get_dynamic_slider'], type='http', auth='public', website=True)
  87. def product_multi_get_dynamic_slider(self, **post):
  88. if post.get('slider-type'):
  89. slider_header = request.env['multi.slider.config'].sudo().search(
  90. [('id', '=', int(post.get('slider-type')))])
  91. values = {
  92. 'slider_details': slider_header,
  93. 'slider_header': slider_header
  94. }
  95. return request.website.render("kingfisher_pro.kingfisher_pro_multi_cat_slider_view", values)
  96. @http.route(['/kingfisher_pro/product_multi_image_effect_config'], type='json', auth='public', website=True)
  97. def product_multi_product_image_dynamic_slider(self, **post):
  98. slider_data = request.env['multi.slider.config'].search(
  99. [('id', '=', int(post.get('slider_type')))])
  100. values = {
  101. 's_id': slider_data.no_of_collection + '-' + str(slider_data.id),
  102. 'counts': slider_data.no_of_collection,
  103. 'auto_rotate': slider_data.auto_rotate,
  104. 'auto_play_time': slider_data.sliding_speed,
  105. }
  106. return values
  107. @http.route(['/home/subscribe'
  108. ], type='http', auth="public", website=True)
  109. def subscribe(self, **post):
  110. email=post.pop('email')
  111. values={'sub_error':{},'subscribe':{'email':email}}
  112. if not email:
  113. values = {'sub_error':{'email':True},'subscribe':{'email':email}}
  114. return request.website.render("website.homepage",values)
  115. if email:
  116. if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None:
  117. pass
  118. else:
  119. values['sub_error'].update({'email': 'invalid'})
  120. return request.website.render("website.homepage",values)
  121. cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
  122. model_id=pool.get('ir.model').search(cr,uid,[('model','=','res.partner')])
  123. mass_mail = pool.get('distribution.list').search(cr,uid,[('name','=','Subscribe')])
  124. if not mass_mail:
  125. mass_mail=pool.get('distribution.list').create(cr,uid,{
  126. 'name':'Subscribe',
  127. 'dst_model_id': model_id[0],
  128. 'bridge_field':'id',
  129. 'partner_path':'id',
  130. 'to_include_distribution_list_line_ids':[[0,False,
  131. {'name':'Subscribe',
  132. 'src_model_id':model_id[0],
  133. 'domain':"[['subscribe', '=', True]]"}
  134. ]]},context)
  135. email_id=email
  136. success_msg=False
  137. already_sub_msg=False
  138. if email_id:
  139. uid=SUPERUSER_ID
  140. partner=pool.get('res.partner').search(cr,uid,[('email','=',email_id),('subscribe','=',True)])
  141. if not partner:
  142. pool.get('res.partner').create(cr,uid,{'name':email_id.split('@')[0],'email':email_id,
  143. 'customer':True,'subscribe':True},context)
  144. success_msg='You have been subscribed successfully.'
  145. else:
  146. already_sub_msg='You are already subscribed.'
  147. return request.website.render("website.homepage", {'successmsg':success_msg,'already_sub_msg':already_sub_msg})
  148. @http.route(['/home/contact_info'
  149. ], type='http', auth="public", website=True)
  150. def contacts(self,**post):
  151. cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
  152. uid=SUPERUSER_ID
  153. partner = pool.get('res.users').browse(cr, SUPERUSER_ID, request.uid, context).partner_id
  154. super_email=pool.get('res.users').browse(cr, SUPERUSER_ID, SUPERUSER_ID, context).email
  155. name=post.pop('full_name', '')
  156. email=post.pop('emp_email', '')
  157. subject=post.pop('email_subject', '')
  158. msg=post.pop('message', '')
  159. contact={'full_name':name,'emp_email':email,'email_subject':subject,'message':msg}
  160. values={'error':{},'contact':contact}
  161. if not name:
  162. values['error'].update({'full_name': True})
  163. if not email:
  164. values['error'].update({'emp_email': True})
  165. if email:
  166. if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None:
  167. pass
  168. else:
  169. values['error'].update({'emp_email': 'invalid'})
  170. if values and values.has_key('error') and values['error']:
  171. return request.website.render("website.contactus", values)
  172. if super_email:
  173. body="<p>Hello,Admin<br/><br/> Name: "+name+" <br/><br/>Email Address: "+email+ " <br/><br/> Subject: "+subject+" <br/><br/> Message:"+msg+"<br/><br/> Thanks"
  174. temp_id= pool.get('ir.model.data').get_object(cr, uid, 'kingfisher', 'contact_info_email')
  175. pool.get('email.template').write(cr, uid, temp_id.id, {'email_to': super_email,'subject' : subject,'body_html':body or ''}, context=context)
  176. pool.get('email.template').send_mail(cr, uid, temp_id.id,partner.id,True, context=context)
  177. return request.website.render("website.contactus", {'successmsg':'Your message has been sent successfully.'})
  178. return request.website.render("website.contactus", {'failmsg':'Your message has not been sent.'})
  179. #return request.redirect("/page/contactus")
  180. def get_pricelist(self):
  181. return get_pricelist()
  182. @http.route(['/shop/product/comment/<int:product_template_id>'], type='http', auth="public", methods=['GET','POST'], website=True)
  183. def product_comment(self, product_template_id, **post):
  184. if not request.session.uid:
  185. request.session.update({'comments':post.get('comment')})
  186. return login_redirect()
  187. cr, uid, context = request.cr, request.uid, request.context
  188. if post.get('comment') or request.session.has_key('comments') and request.session.comments!=None:
  189. request.registry['product.template'].message_post(
  190. cr, uid, product_template_id,
  191. body=post.get('comment') or request.session.comments,
  192. type='comment',
  193. subtype='mt_comment',
  194. context=dict(context, mail_create_nosubscribe=True))
  195. if request.session.has_key('comments') and request.session.comments!=None:
  196. request.session.update({'comments':None})
  197. return werkzeug.utils.redirect('/shop/product/' +str(product_template_id)+ "#comments")
  198. return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
  199. @http.route(['/shop',
  200. '/shop/page/<int:page>',
  201. '/shop/category/<model("product.public.category"):category>',
  202. '/shop/category/<model("product.public.category"):category>/page/<int:page>'
  203. ], type='http', auth="public", website=True)
  204. def shop(self, page=0, category=None, search='', **post):
  205. cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
  206. domain = request.website.sale_product_domain()
  207. if search:
  208. for srch in search.split(" "):
  209. domain += ['|', '|', '|', ('name', 'ilike', srch), ('description', 'ilike', srch),
  210. ('description_sale', 'ilike', srch), ('product_variant_ids.default_code', 'ilike', srch)]
  211. if category:
  212. domain += [('public_categ_ids', 'child_of', int(category))]
  213. attrib_list = request.httprequest.args.getlist('attrib')
  214. attrib_values = [map(int,v.split("-")) for v in attrib_list if v]
  215. attrib_set = set([v[1] for v in attrib_values])
  216. if attrib_values:
  217. attrib = None
  218. ids = []
  219. for value in attrib_values:
  220. if not attrib:
  221. attrib = value[0]
  222. ids.append(value[1])
  223. elif value[0] == attrib:
  224. ids.append(value[1])
  225. else:
  226. domain += [('attribute_line_ids.value_ids', 'in', ids)]
  227. attrib = value[0]
  228. ids = [value[1]]
  229. if attrib:
  230. domain += [('attribute_line_ids.value_ids', 'in', ids)]
  231. keep = QueryURL('/shop', category=category and int(category), search=search, attrib=attrib_list)
  232. if not context.get('pricelist'):
  233. pricelist = self.get_pricelist()
  234. context['pricelist'] = int(pricelist)
  235. else:
  236. pricelist = pool.get('product.pricelist').browse(cr, uid, context['pricelist'], context)
  237. product_obj = pool.get('product.template')
  238. url = "/shop"
  239. product_count = product_obj.search_count(cr, uid, domain, context=context)
  240. if search:
  241. post["search"] = search
  242. if category:
  243. category = pool['product.public.category'].browse(cr, uid, int(category), context=context)
  244. url = "/shop/category/%s" % slug(category)
  245. if attrib_list:
  246. post['attrib'] = attrib_list
  247. pager = request.website.pager(url=url, total=product_count, page=page, step=PPG, scope=7, url_args=post)
  248. product_ids = product_obj.search(cr, uid, domain, limit=PPG, offset=pager['offset'], order='website_published desc, website_sequence desc', context=context)
  249. products = product_obj.browse(cr, uid, product_ids, context=context)
  250. style_obj = pool['product.style']
  251. style_ids = style_obj.search(cr, uid, [], context=context)
  252. styles = style_obj.browse(cr, uid, style_ids, context=context)
  253. category_obj = pool['product.public.category']
  254. category_ids = category_obj.search(cr, uid, [('parent_id', '=', False)], context=context)
  255. categs = category_obj.browse(cr, uid, category_ids, context=context)
  256. attributes_obj = request.registry['product.attribute']
  257. attributes_ids = attributes_obj.search(cr, uid, [], context=context)
  258. attributes = attributes_obj.browse(cr, uid, attributes_ids, context=context)
  259. from_currency = pool.get('product.price.type')._get_field_currency(cr, uid, 'list_price', context)
  260. to_currency = pricelist.currency_id
  261. compute_currency = lambda price: pool['res.currency']._compute(cr, uid, from_currency, to_currency, price, context=context)
  262. values = {
  263. 'search': search,
  264. 'category': category,
  265. 'attrib_values': attrib_values,
  266. 'attrib_set': attrib_set,
  267. 'pager': pager,
  268. 'pricelist': pricelist,
  269. 'products': products,
  270. 'bins': table_compute().process(products),
  271. 'rows': PPR,
  272. 'styles': styles,
  273. 'categories': categs,
  274. 'attributes': attributes,
  275. 'compute_currency': compute_currency,
  276. 'keep': keep,
  277. 'style_in_product': lambda style, product: style.id in [s.id for s in product.website_style_ids],
  278. 'attrib_encode': lambda attribs: werkzeug.url_encode([('attrib',i) for i in attribs]),
  279. }
  280. return request.website.render("website_sale.products", values)
  281. @http.route(['/shop/get_products_slider'], type='http', auth='public', website=True)
  282. def get_slider_product(self, **post):
  283. cr, uid, context = request.cr, request.uid, request.context
  284. value = {'products': False, 'header': False}
  285. if post.get('product_count') and post.get('slider_type'):
  286. prod_ids = request.registry['product.template'].search(cr, uid, [(post.get(
  287. 'slider_type'), '=', 'True'), ("sale_ok", "=", True)], limit=int(post.get('product_count')), context=context)
  288. price_list = request.registry[
  289. 'website'].price_list_get(cr, uid, context)
  290. product_data = request.registry['product.template'].browse(
  291. cr, uid, prod_ids, {'pricelist': int(price_list)})
  292. if product_data:
  293. value['products'] = product_data
  294. if post.get('slider_type') == 'is_arrival':
  295. if post.get('product_label'):
  296. value['header'] = post.get('product_label')
  297. else:
  298. value['header'] = "LANZAMIENTOS"
  299. if post.get('slider_type') == 'is_features':
  300. if post.get('product_label'):
  301. value['header'] = post.get('product_label')
  302. else:
  303. value['header'] = "FEATURES PRODUCT"
  304. if post.get('product_label'):
  305. value['header'] = post.get('product_label')
  306. return request.website.render("kingfisher.product_snippet", value)
  307. @http.route(['/shop/get_brand_slider'], type='http', auth='public', website=True)
  308. def get_brand_slider(self, **post):
  309. cr, uid, context = request.cr, request.uid, request.context
  310. value = {'brand_header': False}
  311. if post.get('product_label'):
  312. value['brand_header'] = post.get('product_label')
  313. return request.website.render("kingfisher.our_brand_slider", value)
  314. @http.route(['/shop/cart/update'], type='http', auth="public", methods=['POST'], website=True)
  315. def cart_update(self, product_id, add_qty=1, set_qty=0, **kw):
  316. cr, uid, context = request.cr, request.uid, request.context
  317. request.website.sale_get_order(force_create=1)._cart_update(product_id=int(product_id), add_qty=float(add_qty), set_qty=float(set_qty))
  318. #return request.redirect("/shop/cart")
  319. prod_obj = request.registry.get('product.product')
  320. product = prod_obj.browse(cr,uid,int(product_id),context=context)
  321. tpl_obj = request.registry('product.template')
  322. tpl_ids = tpl_obj.search(cr,uid, [('id', '=', product.product_tmpl_id.id)],context=context);
  323. template = tpl_obj.browse(cr,uid,tpl_ids, context=context)
  324. return request.redirect('/shop/product/%s' % slug(template))
  325. class product_zoom_config(website_sale):
  326. @http.route(['/product/zoom_type'], type='json', auth="public", website=True)
  327. def get_zoom_type(self, type_id=None):
  328. cr, uid, context = request.cr, request.uid, request.context
  329. result=False
  330. result=request.website.inner_zoom
  331. return result
  332. # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: