main.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. # -*- coding: utf-8 -*-
  2. # Part of BiztechCS. 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. @http.route(['/home/subscribe'
  77. ], type='http', auth="public", website=True)
  78. def subscribe(self, **post):
  79. email = post.pop('email')
  80. values = {'sub_error': {}, 'subscribe': {'email': email}}
  81. if not email:
  82. values = {'sub_error': {'email': True}, 'subscribe': {'email': email}}
  83. return request.website.render("website.homepage", values)
  84. if email:
  85. if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None:
  86. pass
  87. else:
  88. values['sub_error'].update({'email': 'invalid'})
  89. return request.website.render("website.homepage", values)
  90. cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
  91. model_id = pool.get('ir.model').search(cr, uid, [('model', '=', 'res.partner')])
  92. mass_mail = pool.get('distribution.list').search(cr, uid, [('name', '=', 'Subscribe')])
  93. if not mass_mail:
  94. mass_mail = pool.get('distribution.list').create(cr, uid, {
  95. 'name': 'Subscribe',
  96. 'dst_model_id': model_id[0],
  97. 'bridge_field': 'id',
  98. 'partner_path': 'id',
  99. 'to_include_distribution_list_line_ids': [[0, False,
  100. {'name': 'Subscribe',
  101. 'src_model_id': model_id[0],
  102. 'domain':"[['subscribe', '=', True]]"}
  103. ]]}, context)
  104. email_id = email
  105. success_msg = False
  106. already_sub_msg = False
  107. if email_id:
  108. uid = SUPERUSER_ID
  109. partner = pool.get('res.partner').search(
  110. cr, uid, [('email', '=', email_id), ('subscribe', '=', True)])
  111. if not partner:
  112. pool.get('res.partner').create(cr, uid, {'name': email_id.split('@')[0], 'email': email_id,
  113. 'customer': True, 'subscribe': True}, context)
  114. success_msg = 'You have been subscribed successfully.'
  115. else:
  116. already_sub_msg = 'You are already subscribed.'
  117. return request.website.render("website.homepage", {'successmsg': success_msg, 'already_sub_msg': already_sub_msg})
  118. @http.route(['/home/contact_info'
  119. ], type='http', auth="public", website=True)
  120. def contacts(self, **post):
  121. cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
  122. uid = SUPERUSER_ID
  123. partner = pool.get('res.users').browse(cr, SUPERUSER_ID, request.uid, context).partner_id
  124. super_email = pool.get('res.users').browse(cr, SUPERUSER_ID, SUPERUSER_ID, context).email
  125. name = post.pop('full_name', '')
  126. email = post.pop('emp_email', '')
  127. subject = post.pop('email_subject', '')
  128. msg = post.pop('message', '')
  129. contact = {'full_name': name, 'emp_email': email, 'email_subject': subject, 'message': msg}
  130. values = {'error': {}, 'contact': contact}
  131. if not name:
  132. values['error'].update({'full_name': True})
  133. if not email:
  134. values['error'].update({'emp_email': True})
  135. if email:
  136. if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None:
  137. pass
  138. else:
  139. values['error'].update({'emp_email': 'invalid'})
  140. if values and values.has_key('error') and values['error']:
  141. return request.website.render("website.contactus", values)
  142. if super_email:
  143. body = "<p>Hello,Admin<br/><br/> Name: "+name+" <br/><br/>Email Address: "+email + \
  144. " <br/><br/> Subject: "+subject+" <br/><br/> Message:"+msg+"<br/><br/> Thanks"
  145. temp_id = pool.get('ir.model.data').get_object(
  146. cr, uid, 'kingfisher', 'contact_info_email')
  147. pool.get('email.template').write(cr, uid, temp_id.id, {
  148. 'email_to': super_email, 'subject': subject, 'body_html': body or ''}, context=context)
  149. pool.get('email.template').send_mail(
  150. cr, uid, temp_id.id, partner.id, True, context=context)
  151. return request.website.render("website.contactus", {'successmsg': 'Your message has been sent successfully.'})
  152. return request.website.render("website.contactus", {'failmsg': 'Your message has not been sent.'})
  153. # return request.redirect("/page/contactus")
  154. def get_pricelist(self):
  155. return get_pricelist()
  156. @http.route(['/shop/product/comment/<int:product_template_id>'], type='http', auth="public", methods=['GET', 'POST'], website=True)
  157. def product_comment(self, product_template_id, **post):
  158. if not request.session.uid:
  159. request.session.update({'comments': post.get('comment')})
  160. return login_redirect()
  161. cr, uid, context = request.cr, request.uid, request.context
  162. if post.get('comment') or request.session.has_key('comments') and request.session.comments != None:
  163. request.registry['product.template'].message_post(
  164. cr, uid, product_template_id,
  165. body=post.get('comment') or request.session.comments,
  166. type='comment',
  167. subtype='mt_comment',
  168. context=dict(context, mail_create_nosubscribe=True))
  169. if request.session.has_key('comments') and request.session.comments != None:
  170. request.session.update({'comments': None})
  171. return werkzeug.utils.redirect('/shop/product/' + str(product_template_id) + "#comments")
  172. return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
  173. @http.route(['/shop',
  174. '/shop/page/<int:page>',
  175. '/shop/category/<model("product.public.category"):category>',
  176. '/shop/category/<model("product.public.category"):category>/page/<int:page>'
  177. ], type='http', auth="public", website=True)
  178. def shop(self, page=0, category=None, search='', **post):
  179. cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
  180. domain = request.website.sale_product_domain()
  181. if search:
  182. for srch in search.split(" "):
  183. domain += ['|', '|', '|', ('name', 'ilike', srch), ('description', 'ilike', srch),
  184. ('description_sale', 'ilike', srch), ('product_variant_ids.default_code', 'ilike', srch)]
  185. if category:
  186. domain += [('public_categ_ids', 'child_of', int(category))]
  187. attrib_list = request.httprequest.args.getlist('attrib')
  188. attrib_values = [map(int, v.split("-")) for v in attrib_list if v]
  189. attrib_set = set([v[1] for v in attrib_values])
  190. if attrib_values:
  191. attrib = None
  192. ids = []
  193. for value in attrib_values:
  194. if not attrib:
  195. attrib = value[0]
  196. ids.append(value[1])
  197. elif value[0] == attrib:
  198. ids.append(value[1])
  199. else:
  200. domain += [('attribute_line_ids.value_ids', 'in', ids)]
  201. attrib = value[0]
  202. ids = [value[1]]
  203. if attrib:
  204. domain += [('attribute_line_ids.value_ids', 'in', ids)]
  205. keep = QueryURL(
  206. '/shop', category=category and int(category), search=search, attrib=attrib_list)
  207. if not context.get('pricelist'):
  208. pricelist = self.get_pricelist()
  209. context['pricelist'] = int(pricelist)
  210. else:
  211. pricelist = pool.get('product.pricelist').browse(
  212. cr, uid, context['pricelist'], context)
  213. product_obj = pool.get('product.template')
  214. url = "/shop"
  215. product_count = product_obj.search_count(cr, uid, domain, context=context)
  216. if search:
  217. post["search"] = search
  218. if category:
  219. category = pool['product.public.category'].browse(
  220. cr, uid, int(category), context=context)
  221. url = "/shop/category/%s" % slug(category)
  222. if attrib_list:
  223. post['attrib'] = attrib_list
  224. pager = request.website.pager(
  225. url=url, total=product_count, page=page, step=PPG, scope=7, url_args=post)
  226. product_ids = product_obj.search(cr, uid, domain, limit=PPG, offset=pager[
  227. 'offset'], order='website_published desc, website_sequence desc', context=context)
  228. products = product_obj.browse(cr, uid, product_ids, context=context)
  229. style_obj = pool['product.style']
  230. style_ids = style_obj.search(cr, uid, [], context=context)
  231. styles = style_obj.browse(cr, uid, style_ids, context=context)
  232. category_obj = pool['product.public.category']
  233. category_ids = category_obj.search(cr, uid, [('parent_id', '=', False)], context=context)
  234. categs = category_obj.browse(cr, uid, category_ids, context=context)
  235. attributes_obj = request.registry['product.attribute']
  236. attributes_ids = attributes_obj.search(cr, uid, [], context=context)
  237. attributes = attributes_obj.browse(cr, uid, attributes_ids, context=context)
  238. from_currency = pool.get('product.price.type')._get_field_currency(
  239. cr, uid, 'list_price', context)
  240. to_currency = pricelist.currency_id
  241. compute_currency = lambda price: pool['res.currency']._compute(
  242. cr, uid, from_currency, to_currency, price, context=context)
  243. values = {
  244. 'search': search,
  245. 'category': category,
  246. 'attrib_values': attrib_values,
  247. 'attrib_set': attrib_set,
  248. 'pager': pager,
  249. 'pricelist': pricelist,
  250. 'products': products,
  251. 'bins': table_compute().process(products),
  252. 'rows': PPR,
  253. 'styles': styles,
  254. 'categories': categs,
  255. 'attributes': attributes,
  256. 'compute_currency': compute_currency,
  257. 'keep': keep,
  258. 'style_in_product': lambda style, product: style.id in [s.id for s in product.website_style_ids],
  259. 'attrib_encode': lambda attribs: werkzeug.url_encode([('attrib', i) for i in attribs]),
  260. }
  261. return request.website.render("website_sale.products", values)
  262. @http.route(['/shop/get_products_slider'], type='http', auth='public', website=True)
  263. def get_slider_product(self, **post):
  264. cr, uid, context = request.cr, request.uid, request.context
  265. value = {'products': False, 'header': False}
  266. if post.get('product_count') and post.get('slider_type'):
  267. prod_ids = request.registry['product.template'].search(cr, uid, [(post.get(
  268. 'slider_type'), '=', 'True'), ("sale_ok", "=", True)], limit=int(post.get('product_count')), context=context)
  269. price_list = request.registry[
  270. 'website'].price_list_get(cr, uid, context)
  271. product_data = request.registry['product.template'].browse(
  272. cr, uid, prod_ids, {'pricelist': int(price_list)})
  273. if product_data:
  274. value['products'] = product_data
  275. if post.get('slider_type') == 'is_arrival':
  276. if post.get('product_label'):
  277. value['header'] = post.get('product_label')
  278. else:
  279. value['default_header'] = 'is_arrival'
  280. if post.get('slider_type') == 'is_features':
  281. if post.get('product_label'):
  282. value['header'] = post.get('product_label')
  283. else:
  284. value['default_header'] = 'is_features'
  285. if post.get('product_label'):
  286. value['header'] = post.get('product_label')
  287. if not post.get('product_label') and post.get('slider_type') == 'is_arrival':
  288. value['default_header'] = 'is_arrival'
  289. if not post.get('product_label') and post.get('slider_type') == 'is_features':
  290. value['default_header'] = 'is_features'
  291. return request.website.render("kingfisher.product_snippet", value)
  292. @http.route(['/shop/get_brand_slider'], type='http', auth='public', website=True)
  293. def get_brand_slider(self, **post):
  294. cr, uid, context = request.cr, request.uid, request.context
  295. value = {'brand_header': False}
  296. if post.get('product_label'):
  297. value['brand_header'] = post.get('product_label')
  298. return request.website.render("kingfisher.our_brand_slider", value)
  299. class product_zoom_config(website_sale):
  300. @http.route(['/product/zoom_type'], type='json', auth="public", website=True)
  301. def get_zoom_type(self, type_id=None):
  302. cr, uid, context = request.cr, request.uid, request.context
  303. result = False
  304. result = request.website.inner_zoom
  305. return result