1 # -*- coding: utf-8 -*-
3 from openerp import SUPERUSER_ID
4 from openerp.osv import osv
5 from openerp.addons.web import http
6 from openerp.addons.web.http import request
11 def get_order(order_id=None):
12 order_obj = request.registry.get('sale.order')
13 # check if order allready exists
17 order = order_obj.browse(request.cr, SUPERUSER_ID, order_id)
22 fields = [k for k, v in order_obj._columns.items()]
23 order_value = order_obj.default_get(request.cr, SUPERUSER_ID, fields)
24 if request.httprequest.session.get('ecommerce_pricelist'):
25 order_value['pricelist_id'] = request.httprequest.session['ecommerce_pricelist']
26 order_value['partner_id'] = request.registry.get('res.users').browse(request.cr, SUPERUSER_ID, request.uid).partner_id.id
27 order_value.update(order_obj.onchange_partner_id(request.cr, SUPERUSER_ID, [], order_value['partner_id'], context={})['value'])
28 order_id = order_obj.create(request.cr, SUPERUSER_ID, order_value)
29 order = order_obj.browse(request.cr, SUPERUSER_ID, order_id)
30 request.httprequest.session['ecommerce_order_id'] = order.id
33 'pricelist': order.pricelist_id.id,
35 return order_obj.browse(request.cr, SUPERUSER_ID, order_id, context=context)
37 def get_current_order():
38 if request.httprequest.session.get('ecommerce_order_id'):
39 return get_order(request.httprequest.session.get('ecommerce_order_id'))
43 class website(osv.osv):
45 def get_rendering_context(self, additional_values=None):
47 'order': get_current_order(),
48 # 'website_sale_get_current_order': get_current_order, # TODO: replace 'order' key in templates
51 values.update(additional_values)
52 return super(website, self).get_rendering_context(values)
54 class Ecommerce(http.Controller):
56 def get_categories(self):
57 category_obj = request.registry.get('product.public.category')
58 category_ids = category_obj.search(request.cr, SUPERUSER_ID, [('parent_id', '=', False)])
59 categories = category_obj.browse(request.cr, SUPERUSER_ID, category_ids)
62 @http.route(['/shop/', '/shop/category/<cat_id>/', '/shop/category/<cat_id>/page/<int:page>/', '/shop/page/<int:page>/'], type='http', auth="public")
63 def category(self, cat_id=0, page=0, **post):
66 self.change_pricelist(post.get('promo'))
68 website = request.registry['website']
69 product_obj = request.registry.get('product.template')
71 domain = [("sale_ok", "=", True)]
72 if SUPERUSER_ID != request.uid:
73 domain += [('website_published', '=', True)]
75 if post.get("search"):
76 domain += ['|', '|', '|',
77 ('name', 'ilike', "%%%s%%" % post.get("search")),
78 ('description', 'ilike', "%%%s%%" % post.get("search")),
79 ('website_description', 'ilike', "%%%s%%" % post.get("search")),
80 ('product_variant_ids.public_categ_id.name', 'ilike', "%%%s%%" % post.get("search"))]
83 domain += [('product_variant_ids.public_categ_id.id', 'child_of', cat_id)] + domain
86 product_count = len(product_obj.search(request.cr, request.uid, domain))
87 pager = website.pager(url="/shop/category/%s/" % cat_id, total=product_count, page=page, step=step, scope=7, url_args=post)
89 product_ids = product_obj.search(request.cr, request.uid, domain, limit=step, offset=pager['offset'])
91 context = {'pricelist': self.get_pricelist()}
93 values = website.get_rendering_context({
94 'categories': self.get_categories(),
95 'category_id': cat_id,
96 'products': product_obj.browse(request.cr, SUPERUSER_ID, product_ids, context=context),
97 'search': post.get("search"),
100 return website.render("website_sale.products", values)
102 @http.route(['/shop/product/<product_id>/'], type='http', auth="public")
103 def product(self, cat_id=0, product_id=0, **post):
106 self.change_pricelist(post.get('promo'))
108 website = request.registry['website']
110 product_id = product_id and int(product_id) or 0
111 product_obj = request.registry.get('product.template')
113 context = {'pricelist': self.get_pricelist()}
115 product = product_obj.browse(request.cr, request.uid, product_id, context=context)
116 values = website.get_rendering_context({
117 'category_id': post.get('category_id') and int(post.get('category_id')) or None,
118 'search': post.get("search"),
119 'categories': self.get_categories(),
122 return website.render("website_sale.product", values)
124 def get_pricelist(self):
125 if not request.httprequest.session.get('ecommerce_pricelist'):
126 self.change_pricelist(None)
127 return request.httprequest.session.get('ecommerce_pricelist')
129 def change_pricelist(self, code):
130 request.httprequest.session.setdefault('ecommerce_pricelist', False)
134 pricelist_obj = request.registry.get('product.pricelist')
135 pricelist_ids = pricelist_obj.search(request.cr, SUPERUSER_ID, [('code', '=', code)])
137 pricelist_id = pricelist_ids[0]
140 partner_id = request.registry.get('res.users').browse(request.cr, SUPERUSER_ID, request.uid).partner_id.id
141 pricelist_id = request.registry['sale.order'].onchange_partner_id(request.cr, SUPERUSER_ID, [], partner_id, context={})['value']['pricelist_id']
143 request.httprequest.session['ecommerce_pricelist'] = pricelist_id
145 order = get_current_order()
147 values = {'pricelist_id': pricelist_id}
148 values.update(order.onchange_pricelist_id(pricelist_id, None)['value'])
150 for line in order.order_line:
151 self.add_product_to_cart(order_line_id=line.id, number=0)
153 def add_product_to_cart(self, product_id=0, order_line_id=0, number=1, set_number=-1):
154 order_line_obj = request.registry.get('sale.order.line')
156 product_id = product_id and int(product_id) or 0
158 order = get_current_order()
162 context = {'pricelist': self.get_pricelist()}
166 # values initialisation
169 domain = [('order_id', '=', order.id)]
171 domain += [('id', '=', order_line_id)]
173 domain += [('product_id', '=', product_id)]
175 order_line_ids = order_line_obj.search(request.cr, SUPERUSER_ID, domain, context=context)
177 order_line = order_line_obj.read(request.cr, SUPERUSER_ID, order_line_ids, [], context=context)[0]
179 product_id = order_line['product_id'][0]
181 quantity = set_number
183 quantity = order_line['product_uom_qty'] + number
187 fields = [k for k, v in order_line_obj._columns.items()]
188 values = order_line_obj.default_get(request.cr, SUPERUSER_ID, fields, context=context)
191 # change and record value
192 vals = order_line_obj._recalculate_product_values(request.cr, request.uid, order_line_ids, product_id, context=context)
195 values['product_uom_qty'] = quantity
196 values['product_id'] = product_id
197 values['order_id'] = order.id
200 order_line_obj.write(request.cr, SUPERUSER_ID, order_line_ids, values, context=context)
202 order_line_obj.unlink(request.cr, SUPERUSER_ID, order_line_ids, context=context)
204 order_line_id = order_line_obj.create(request.cr, SUPERUSER_ID, values, context=context)
205 order.write({'order_line': [(4, order_line_id)]}, context=context)
207 return [quantity, order.get_total_quantity()]
209 @http.route(['/shop/mycart/'], type='http', auth="public")
210 def mycart(self, **post):
211 order = get_current_order()
212 website = request.registry['website']
213 prod_obj = request.registry.get('product.product')
216 self.change_pricelist(post.get('promo'))
220 for line in order.order_line:
221 suggested_ids += [p.id for p in line.product_id and line.product_id.suggested_product_ids or [] for line in order.order_line]
222 suggested_ids = prod_obj.search(request.cr, request.uid, [('id', 'in', suggested_ids)])
223 # select 3 random products
224 suggested_products = []
225 while len(suggested_products) < 3 and suggested_ids:
226 index = random.randrange(0, len(suggested_ids))
227 suggested_products.append(suggested_ids.pop(index))
229 values = website.get_rendering_context({
230 'categories': self.get_categories(),
231 'suggested_products': prod_obj.browse(request.cr, request.uid, suggested_products),
233 return website.render("website_sale.mycart", values)
235 @http.route(['/shop/<path:path>/add_cart/', '/shop/add_cart/'], type='http', auth="public")
236 def add_cart(self, path=None, product_id=None, order_line_id=None, remove=None, json=None):
237 quantity = self.add_product_to_cart(product_id=product_id, order_line_id=order_line_id, number=(remove and -1 or 1))
239 return simplejson.dumps(quantity)
241 return werkzeug.utils.redirect("/shop/%s/" % path)
243 return werkzeug.utils.redirect("/shop/")
245 @http.route(['/shop/remove_cart/', '/shop/<path:path>/remove_cart/'], type='http', auth="public")
246 def remove_cart(self, path=None, product_id=None, order_line_id=None, json=None):
247 return self.add_cart(product_id=product_id, order_line_id=order_line_id, path=path, remove=True, json=json)
249 @http.route(['/shop/set_cart/', '/shop/<path:path>/set_cart/'], type='http', auth="public")
250 def set_cart(self, path=None, product_id=None, order_line_id=None, set_number=0, json=None):
251 quantity = self.add_product_to_cart(product_id=product_id, order_line_id=order_line_id, set_number=set_number)
253 return simplejson.dumps(quantity)
255 return werkzeug.utils.redirect("/shop/%s/" % path)
257 return werkzeug.utils.redirect("/shop/")
259 @http.route(['/shop/checkout/'], type='http', auth="public")
260 def checkout(self, **post):
261 website = request.registry['website']
263 order = get_current_order()
265 if order.state != 'draft' or not order.order_line:
266 return self.mycart(**post)
268 partner_obj = request.registry.get('res.partner')
269 user_obj = request.registry.get('res.users')
270 country_obj = request.registry.get('res.country')
271 country_state_obj = request.registry.get('res.country.state')
273 values = website.get_rendering_context({
274 'shipping': post.get("shipping"),
275 'error': post.get("error") and dict.fromkeys(post.get("error").split(","), 'error') or {}
279 if request.uid != website.get_public_user().id:
280 partner = user_obj.browse(request.cr, request.uid, request.uid).partner_id
281 partner_id = partner.id
282 fields = ["name", "phone", "fax", "company", "email", "street", "city", "state_id", "zip", "country_id"]
283 checkout = user_obj.read(request.cr, SUPERUSER_ID, [partner_id], fields)[0]
284 checkout['company'] = partner.parent_id and partner.parent_id.name or ''
286 shipping_ids = partner_obj.search(request.cr, request.uid, [("parent_id", "=", partner_id), ('type', "=", 'delivery')])
288 for k,v in partner_obj.read(request.cr, request.uid, shipping_ids[0]).items():
289 checkout['shipping_'+k] = v or ''
291 checkout.update(request.session.setdefault('checkout', {}))
292 for k,v in checkout.items():
293 checkout[k] = v or ''
294 values['checkout'] = checkout
296 values['countries'] = country_obj.browse(request.cr, SUPERUSER_ID, country_obj.search(request.cr, SUPERUSER_ID, [(1, "=", 1)]))
297 values['states'] = country_state_obj.browse(request.cr, SUPERUSER_ID, country_state_obj.search(request.cr, SUPERUSER_ID, [(1, "=", 1)]))
299 return website.render("website_sale.checkout", values)
301 @http.route(['/shop/confirm_order/'], type='http', auth="public")
302 def confirm_order(self, **post):
303 website = request.registry['website']
304 order = get_current_order()
307 partner_obj = request.registry.get('res.partner')
308 user_obj = request.registry.get('res.users')
310 if order.state != 'draft':
311 return werkzeug.utils.redirect("/shop/checkout/")
312 if not order.order_line:
313 error.append("empty_cart")
314 return werkzeug.utils.redirect("/shop/checkout/")
317 request.session['checkout'] = post
318 required_field = ['phone', 'zip', 'email', 'street', 'city', 'name', 'country_id']
319 for key in required_field:
320 if not post.get(key):
322 if post.get('shipping_different') and key != 'email' and not post.get("shipping_%s" % key):
323 error.append("shipping_%s" % key)
325 return werkzeug.utils.redirect("/shop/checkout/?error=%s&shipping=%s" % (",".join(error), post.get('shipping_different') and 'on' or ''))
327 # search or create company
330 company_ids = partner_obj.search(request.cr, SUPERUSER_ID, [("name", "ilike", post['company']), ('is_company', '=', True)])
331 company_id = company_ids and company_ids[0] or None
333 company_id = partner_obj.create(request.cr, SUPERUSER_ID, {'name': post['company'], 'is_company': True})
337 'phone': post['phone'],
339 'email': post['email'],
340 'street': post['street'],
341 'city': post['city'],
342 'name': post['name'],
343 'parent_id': company_id,
344 'country_id': post['country_id'],
345 'state_id': post['state_id'],
347 if request.uid != website.get_public_user().id:
348 partner_id = user_obj.browse(request.cr, request.uid, request.uid).partner_id.id
349 partner_obj.write(request.cr, request.uid, [partner_id], partner_value)
351 partner_id = partner_obj.create(request.cr, SUPERUSER_ID, partner_value)
354 if 'shipping_name' in post:
356 'fax': post['shipping_fax'],
357 'phone': post['shipping_phone'],
358 'zip': post['shipping_zip'],
359 'street': post['shipping_street'],
360 'city': post['shipping_city'],
361 'name': post['shipping_name'],
363 'parent_id': partner_id,
364 'country_id': post['shipping_country_id'],
365 'state_id': post['shipping_state_id'],
367 domain = [(key, '_id' in key and '=' or 'ilike', '_id' in key and int(value) or value)
368 for key, value in shipping_value.items() if key in required_field + ["type", "parent_id"]]
369 shipping_ids = partner_obj.search(request.cr, SUPERUSER_ID, domain)
371 shipping_id = shipping_ids[0]
372 partner_obj.write(request.cr, SUPERUSER_ID, [shipping_id], shipping_value)
374 shipping_id = partner_obj.create(request.cr, SUPERUSER_ID, shipping_value)
377 'partner_id': partner_id,
378 'partner_invoice_id': partner_id,
379 'partner_shipping_id': shipping_id or partner_id
381 order_value.update(request.registry.get('sale.order').onchange_partner_id(request.cr, SUPERUSER_ID, [], order.partner_id.id, context={})['value'])
382 order.write(order_value)
384 return werkzeug.utils.redirect("/shop/payment/")
386 @http.route(['/shop/payment/'], type='http', auth="public")
387 def payment(self, **post):
388 website = request.registry['website']
389 order = get_current_order()
391 if not order or not order.order_line:
392 return self.mycart(**post)
394 values = website.get_rendering_context({
399 payment_obj = request.registry.get('portal.payment.acquirer')
400 payment_ids = payment_obj.search(request.cr, SUPERUSER_ID, [('visible', '=', True)])
401 values['payments'] = payment_obj.browse(request.cr, SUPERUSER_ID, payment_ids)
402 for payment in values['payments']:
403 content = payment_obj.render(request.cr, SUPERUSER_ID, payment.id, order, order.name, order.pricelist_id.currency_id, order.amount_total)
404 payment._content = content
406 return website.render("website_sale.payment", values)
408 @http.route(['/shop/payment_validate/'], type='http', auth="public")
409 def payment_validate(self, **post):
410 request.httprequest.session['ecommerce_order_id'] = False
411 request.httprequest.session['ecommerce_pricelist'] = False
412 return werkzeug.utils.redirect("/shop/")
414 # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: