main.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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.tools.translate import _
  8. from openerp.addons.website.models.website import slug
  9. from openerp.addons.website_sale.controllers.main import QueryURL
  10. from openerp.addons.website_sale.controllers.main import get_pricelist
  11. from openerp.addons.web.controllers.main import login_and_redirect
  12. from openerp.addons.website_sale.controllers.main import website_sale
  13. import re
  14. PPG = 12 # Products Per Page
  15. PPR = 3 # Products Per Row
  16. class table_compute(object):
  17. def __init__(self):
  18. self.table = {}
  19. def _check_place(self, posx, posy, sizex, sizey):
  20. res = True
  21. for y in range(sizey):
  22. for x in range(sizex):
  23. if posx + x >= PPR:
  24. res = False
  25. break
  26. row = self.table.setdefault(posy + y, {})
  27. if row.setdefault(posx + x) is not None:
  28. res = False
  29. break
  30. for x in range(PPR):
  31. self.table[posy + y].setdefault(x, None)
  32. return res
  33. def process(self, products):
  34. # Compute products positions on the grid
  35. minpos = 0
  36. index = 0
  37. maxy = 0
  38. for p in products:
  39. x = min(max(p.website_size_x, 1), PPR)
  40. y = min(max(p.website_size_y, 1), PPR)
  41. if index >= PPG:
  42. x = y = 1
  43. pos = minpos
  44. while not self._check_place(pos % PPR, pos / PPR, x, y):
  45. pos += 1
  46. # if 21st products (index 20) and the last line is full (PPR products in it), break
  47. # (pos + 1.0) / PPR is the line where the product would be inserted
  48. # maxy is the number of existing lines
  49. # + 1.0 is because pos begins at 0, thus pos 20 is actually the 21st block
  50. # and to force python to not round the division operation
  51. if index >= PPG and ((pos + 1.0) / PPR) > maxy:
  52. break
  53. if x == 1 and y == 1: # simple heuristic for CPU optimization
  54. minpos = pos / PPR
  55. for y2 in range(y):
  56. for x2 in range(x):
  57. self.table[(pos / PPR) + y2][(pos % PPR) + x2] = False
  58. self.table[pos / PPR][pos % PPR] = {
  59. 'product': p, 'x': x, 'y': y,
  60. 'class': " ".join(map(lambda x: x.html_class or '', p.website_style_ids))
  61. }
  62. if index <= PPG:
  63. maxy = max(maxy, y + (pos / PPR))
  64. index += 1
  65. # Format table according to HTML needs
  66. rows = self.table.items()
  67. rows.sort()
  68. rows = map(lambda x: x[1], rows)
  69. for col in range(len(rows)):
  70. cols = rows[col].items()
  71. cols.sort()
  72. x += len(cols)
  73. rows[col] = [c for c in map(lambda x: x[1], cols) if c != False]
  74. return rows
  75. # TODO keep with input type hidden
  76. class biztech_theme(http.Controller):
  77. @http.route(['/home/contact_info'
  78. ], type='http', auth="public", website=True)
  79. def contacts(self, **post):
  80. partner = request.env.user.partner_id
  81. super_email = request.env.user.email
  82. name = post.pop('full_name', '')
  83. email = post.pop('emp_email', '')
  84. subject = post.pop('email_subject', '')
  85. msg = post.pop('message', '')
  86. contact = {'full_name': name, 'emp_email': email,
  87. 'email_subject': subject, 'message': msg}
  88. values = {'error': {}, 'contact': contact}
  89. if not name:
  90. values['error'].update({'full_name': True})
  91. if not email:
  92. values['error'].update({'emp_email': True})
  93. if email:
  94. if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None:
  95. pass
  96. else:
  97. values['error'].update({'emp_email': 'invalid'})
  98. if values and values.has_key('error') and values['error']:
  99. return request.website.render("website.contactus", values)
  100. if super_email:
  101. body = "<p>Hello,Admin<br/><br/> Name: " + name + " <br/><br/>Email Address: " + email + \
  102. " <br/><br/> Subject: " + subject + \
  103. " <br/><br/> Message:" + msg + "<br/><br/> Thanks"
  104. temp_id = request.env.ref('kingfisher.contact_info_email')
  105. request.registry['mail.template'].browse(temp_id.id).write({
  106. 'email_to': super_email, 'subject': subject, 'body_html': body or ''})
  107. request.registry['mail.template'].send_mail(
  108. temp_id.id, partner.id, True)
  109. return request.website.render("website.contactus", {'successmsg': 'Your message has been sent successfully.'})
  110. return request.website.render("website.contactus", {'failmsg': 'Your message has not been sent.'})
  111. def get_pricelist(self):
  112. return get_pricelist()
  113. @http.route(['/shop',
  114. '/shop/page/<int:page>',
  115. '/shop/category/<model("product.public.category"):category>',
  116. '/shop/category/<model("product.public.category"):category>/page/<int:page>'
  117. ], type='http', auth="public", website=True)
  118. def shop(self, page=0, category=None, search='', **post):
  119. cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
  120. domain = request.website.sale_product_domain()
  121. if search:
  122. for srch in search.split(" "):
  123. domain += ['|', '|', '|', ('name', 'ilike', srch), ('description', 'ilike', srch),
  124. ('description_sale', 'ilike', srch), ('product_variant_ids.default_code', 'ilike', srch)]
  125. if category:
  126. domain += [('public_categ_ids', 'child_of', int(category))]
  127. attrib_list = request.httprequest.args.getlist('attrib')
  128. attrib_values = [map(int, v.split("-")) for v in attrib_list if v]
  129. attrib_set = set([v[1] for v in attrib_values])
  130. if attrib_values:
  131. attrib = None
  132. ids = []
  133. for value in attrib_values:
  134. if not attrib:
  135. attrib = value[0]
  136. ids.append(value[1])
  137. elif value[0] == attrib:
  138. ids.append(value[1])
  139. else:
  140. domain += [('attribute_line_ids.value_ids', 'in', ids)]
  141. attrib = value[0]
  142. ids = [value[1]]
  143. if attrib:
  144. domain += [('attribute_line_ids.value_ids', 'in', ids)]
  145. keep = QueryURL(
  146. '/shop', category=category and int(category), search=search, attrib=attrib_list)
  147. if not context.get('pricelist'):
  148. pricelist = self.get_pricelist()
  149. context['pricelist'] = int(pricelist)
  150. else:
  151. pricelist = pool.get('product.pricelist').browse(
  152. cr, uid, context['pricelist'], context)
  153. product_obj = pool.get('product.template')
  154. parent_category_ids = []
  155. if category:
  156. parent_category_ids = [category.id]
  157. current_category = category
  158. while current_category.parent_id:
  159. parent_category_ids.append(current_category.parent_id.id)
  160. current_category = current_category.parent_id
  161. url = "/shop"
  162. product_count = product_obj.search_count(cr, uid, domain, context=context)
  163. if search:
  164. post["search"] = search
  165. if category:
  166. category = pool['product.public.category'].browse(
  167. cr, uid, int(category), context=context)
  168. url = "/shop/category/%s" % slug(category)
  169. if attrib_list:
  170. post['attrib'] = attrib_list
  171. pager = request.website.pager(
  172. url=url, total=product_count, page=page, step=PPG, scope=7, url_args=post)
  173. product_ids = product_obj.search(cr, uid, domain, limit=PPG, offset=pager[
  174. 'offset'], order='website_published desc, website_sequence desc', context=context)
  175. products = product_obj.browse(cr, uid, product_ids, context=context)
  176. style_obj = pool['product.style']
  177. style_ids = style_obj.search(cr, uid, [], context=context)
  178. styles = style_obj.browse(cr, uid, style_ids, context=context)
  179. category_obj = pool['product.public.category']
  180. category_ids = category_obj.search(cr, uid, [('parent_id', '=', False)], context=context)
  181. categs = category_obj.browse(cr, uid, category_ids, context=context)
  182. attributes_obj = request.registry['product.attribute']
  183. attributes_ids = attributes_obj.search(cr, uid, [], context=context)
  184. attributes = attributes_obj.browse(cr, uid, attributes_ids, context=context)
  185. #from_currency = pool.get('product.price.type')._get_field_currency(cr, uid, 'list_price', context)
  186. from_currency = pool['res.users'].browse(cr, uid, uid, context=context).company_id.currency_id
  187. to_currency = pricelist.currency_id
  188. compute_currency = lambda price: pool['res.currency']._compute(
  189. cr, uid, from_currency, to_currency, price, context=context)
  190. values = {
  191. 'search': search,
  192. 'category': category,
  193. 'attrib_values': attrib_values,
  194. 'attrib_set': attrib_set,
  195. 'pager': pager,
  196. 'pricelist': pricelist,
  197. 'products': products,
  198. 'bins': table_compute().process(products),
  199. 'rows': PPR,
  200. 'styles': styles,
  201. 'categories': categs,
  202. 'attributes': attributes,
  203. 'compute_currency': compute_currency,
  204. 'keep': keep,
  205. 'parent_category_ids': parent_category_ids,
  206. 'style_in_product': lambda style, product: style.id in [s.id for s in product.website_style_ids],
  207. 'attrib_encode': lambda attribs: werkzeug.url_encode([('attrib', i) for i in attribs]),
  208. }
  209. return request.website.render("website_sale.products", values)
  210. @http.route(['/shop/get_products_slider'], type='http', auth='public', website=True)
  211. def get_slider_product(self, **post):
  212. cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
  213. value = {'products': False, 'header': False}
  214. if not context.get('pricelist'):
  215. pricelist = self.get_pricelist()
  216. context['pricelist'] = int(pricelist)
  217. else:
  218. pricelist = pool.get('product.pricelist').browse(
  219. cr, uid, context['pricelist'], context)
  220. from_currency = pool['res.users'].browse(
  221. cr, uid, uid, context=context).company_id.currency_id
  222. to_currency = pricelist.currency_id
  223. compute_currency = lambda price: pool['res.currency']._compute(
  224. cr, uid, from_currency, to_currency, price, context=context)
  225. value.update({'compute_currency': compute_currency})
  226. if post.get('product_count') and post.get('slider_type'):
  227. prod_ids = request.registry['product.template'].search(cr, uid, [(post.get(
  228. 'slider_type'), '=', 'True'), ("sale_ok", "=", True)], limit=int(post.get('product_count')), context=context)
  229. price_list = request.registry['website'].price_list_get()
  230. product_data = request.registry['product.template'].browse(
  231. cr, uid, prod_ids, context)
  232. if product_data:
  233. value['products'] = product_data
  234. if post.get('slider_type') == 'is_arrival':
  235. if post.get('product_label'):
  236. value['header'] = post.get('product_label')
  237. else:
  238. value['default_header'] = 'is_arrival'
  239. if post.get('slider_type') == 'is_features':
  240. if post.get('product_label'):
  241. value['header'] = post.get('product_label')
  242. else:
  243. value['default_header'] = 'is_features'
  244. if post.get('product_label'):
  245. value['header'] = post.get('product_label')
  246. if not post.get('product_label') and post.get('slider_type') == 'is_arrival':
  247. value['default_header'] = 'is_arrival'
  248. if not post.get('product_label') and post.get('slider_type') == 'is_features':
  249. value['default_header'] = 'is_features'
  250. return request.website.render("kingfisher.product_snippet", value)
  251. @http.route(['/shop/get_brand_slider'], type='http', auth='public', website=True)
  252. def get_brand_slider(self, **post):
  253. value = {'brand_header': False}
  254. if post.get('product_label'):
  255. value['brand_header'] = post.get('product_label')
  256. return request.website.render("kingfisher.our_brand_slider", value)
  257. class product_zoom_config(website_sale):
  258. @http.route(['/product/zoom_type'], type='json', auth="public", website=True)
  259. def get_zoom_type(self, type_id=None):
  260. result = False
  261. result = request.website.inner_zoom
  262. return result