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
10 def get_order(order_id=None):
11 order_obj = request.registry.get('sale.order')
12 # check if order allready exists
16 order = order_obj.browse(request.cr, SUPERUSER_ID, order_id)
21 fields = [k for k, v in order_obj._columns.items()]
22 order_value = order_obj.default_get(request.cr, SUPERUSER_ID, fields)
23 if request.httprequest.session.get('ecommerce_pricelist'):
24 order_value['pricelist_id'] = request.httprequest.session['ecommerce_pricelist']
25 order_value['partner_id'] = request.registry.get('res.users').browse(request.cr, SUPERUSER_ID, request.uid).partner_id.id
26 order_value.update(order_obj.onchange_partner_id(request.cr, SUPERUSER_ID, [], request.uid, context={})['value'])
27 order_id = order_obj.create(request.cr, SUPERUSER_ID, order_value)
28 order = order_obj.browse(request.cr, SUPERUSER_ID, order_id)
31 'pricelist': order.pricelist_id.id,
33 return order_obj.browse(request.cr, SUPERUSER_ID, order_id, context=context)
35 def get_current_order():
36 if request.httprequest.session.get('ecommerce_order_id'):
37 return get_order(request.httprequest.session.get('ecommerce_order_id'))
41 class website(osv.osv):
43 def get_rendering_context(self, additional_values=None):
45 'order': get_current_order(),
46 # 'website_sale_get_current_order': get_current_order, # TODO: replace 'order' key in templates
49 values.update(additional_values)
50 return super(website, self).get_rendering_context(values)
52 class Ecommerce(http.Controller):
54 def get_categories(self):
55 category_obj = request.registry.get('pos.category')
56 category_ids = category_obj.search(request.cr, SUPERUSER_ID, [('parent_id', '=', False)])
57 categories = category_obj.browse(request.cr, SUPERUSER_ID, category_ids)
60 @http.route(['/shop/', '/shop/category/<cat_id>/', '/shop/category/<cat_id>/page/<int:page>/', '/shop/page/<int:page>/'], type='http', auth="public")
61 def category(self, cat_id=0, page=0, **post):
64 self.change_pricelist(post.get('promo'))
66 website = request.registry['website']
67 product_obj = request.registry.get('product.template')
69 domain = [("sale_ok", "=", True)]
70 if SUPERUSER_ID != request.uid:
71 domain += [('website_published', '=', True)]
73 if post.get("search"):
74 domain += ['|', '|', '|',
75 ('name', 'ilike', "%%%s%%" % post.get("search")),
76 ('description', 'ilike', "%%%s%%" % post.get("search")),
77 ('website_description', 'ilike', "%%%s%%" % post.get("search")),
78 ('product_variant_ids.pos_categ_id.name', 'ilike', "%%%s%%" % post.get("search"))]
81 domain += [('product_variant_ids.pos_categ_id.id', 'child_of', cat_id)] + domain
84 product_count = len(product_obj.search(request.cr, request.uid, domain))
85 pager = website.pager(url="/shop/category/%s/" % cat_id, total=product_count, page=page, step=step, scope=7, url_args=post)
87 product_ids = product_obj.search(request.cr, request.uid, domain, limit=step, offset=pager['offset'])
89 context = {'pricelist': self.get_pricelist()}
91 values = website.get_rendering_context({
92 'categories': self.get_categories(),
93 'category_id': cat_id,
94 'products': product_obj.browse(request.cr, request.uid, product_ids, context=context),
95 'search': post.get("search"),
98 return website.render("website_sale.products", values)
100 @http.route(['/shop/product/<product_id>/'], type='http', auth="public")
101 def product(self, cat_id=0, product_id=0, **post):
104 self.change_pricelist(post.get('promo'))
106 website = request.registry['website']
108 product_id = product_id and int(product_id) or 0
109 product_obj = request.registry.get('product.template')
111 context = {'pricelist': self.get_pricelist()}
113 product = product_obj.browse(request.cr, request.uid, product_id, context=context)
114 values = website.get_rendering_context({
115 'category_id': post.get('category_id') and int(post.get('category_id')) or None,
116 'search': post.get("search"),
117 'categories': self.get_categories(),
120 return website.render("website_sale.product", values)
122 def get_pricelist(self):
123 if not request.httprequest.session.get('ecommerce_pricelist'):
124 self.change_pricelist(None)
125 return request.httprequest.session.get('ecommerce_pricelist')
127 def change_pricelist(self, code):
128 request.httprequest.session.setdefault('ecommerce_pricelist', False)
132 pricelist_obj = request.registry.get('product.pricelist')
133 pricelist_ids = pricelist_obj.search(request.cr, SUPERUSER_ID, [('code', '=', code)])
135 pricelist_id = pricelist_ids[0]
138 pricelist_id = request.registry['sale.order'].onchange_partner_id(request.cr, SUPERUSER_ID, [], request.uid, context={})['value']['pricelist_id']
140 request.httprequest.session['ecommerce_pricelist'] = pricelist_id
142 order = get_current_order()
144 values = {'pricelist_id': pricelist_id}
145 values.update(order.onchange_pricelist_id(pricelist_id, None)['value'])
147 for line in order.order_line:
148 self.add_product_to_cart(line.product_id.id, 0)
150 def add_product_to_cart(self, product_id=0, number=1, set_number=-1):
151 order_line_obj = request.registry.get('sale.order.line')
152 user_obj = request.registry.get('res.users')
154 product_id = product_id and int(product_id) or 0
155 order = get_current_order()
158 request.httprequest.session['ecommerce_order_id'] = order.id
160 context = {'pricelist': self.get_pricelist()}
164 # values initialisation
166 order_line_ids = order_line_obj.search(request.cr, SUPERUSER_ID, [('order_id', '=', order.id), ('product_id', '=', product_id)], context=context)
168 order_line = order_line_obj.read(request.cr, SUPERUSER_ID, order_line_ids, [], context=context)[0]
170 quantity = set_number
172 quantity = order_line['product_uom_qty'] + number
176 fields = [k for k, v in order_line_obj._columns.items()]
177 values = order_line_obj.default_get(request.cr, SUPERUSER_ID, fields, context=context)
180 values['product_uom_qty'] = quantity
181 values['product_id'] = product_id
182 values['order_id'] = order.id
184 # change and record value
185 pricelist_id = order.pricelist_id and order.pricelist_id.id or False
187 vals = order_line_obj.product_id_change(request.cr, SUPERUSER_ID, [], pricelist_id, product_id,
188 partner_id=user_obj.browse(request.cr, SUPERUSER_ID, request.uid).partner_id.id,
189 context=context)['value']
193 order_line_obj.write(request.cr, SUPERUSER_ID, order_line_ids, values, context=context)
195 order_line_obj.unlink(request.cr, SUPERUSER_ID, order_line_ids, context=context)
197 order_line_id = order_line_obj.create(request.cr, SUPERUSER_ID, values, context=context)
198 order.write({'order_line': [(4, order_line_id)]}, context=context)
202 @http.route(['/shop/mycart/'], type='http', auth="public")
203 def mycart(self, **post):
204 order = get_current_order()
205 website = request.registry['website']
206 prod_obj = request.registry.get('product.product')
209 self.change_pricelist(post.get('promo'))
213 for line in order.order_line:
214 suggested_ids += [p.id for p in line.product_id.suggested_product_ids for line in order.order_line]
215 suggested_ids = prod_obj.search(request.cr, request.uid, [('id', 'in', suggested_ids)])
216 # select 3 random products
217 suggested_products = []
218 while len(suggested_products) < 3 and suggested_ids:
219 index = random.randrange(0, len(suggested_ids))
220 suggested_products.append(suggested_ids.pop(index))
222 values = website.get_rendering_context({
223 'categories': self.get_categories(),
224 'suggested_products': prod_obj.browse(request.cr, request.uid, suggested_products),
226 return website.render("website_sale.mycart", values)
228 @http.route(['/shop/<path:path>/add_cart/', '/shop/add_cart/', '/shop/add_cart/<product_id>/', '/shop/<path:path>/add_cart/<product_id>/'], type='http', auth="public")
229 def add_cart(self, path=None, product_id=0, remove=None):
230 self.add_product_to_cart(product_id, number=(remove and -1 or 1))
232 return werkzeug.utils.redirect("/shop/%s/" % path)
234 return werkzeug.utils.redirect("/shop/")
236 @http.route(['/shop/remove_cart/<product_id>/', '/shop/<path:path>/remove_cart/<product_id>/'], type='http', auth="public")
237 def remove_cart(self, path=None, product_id=0):
238 return self.add_cart(product_id=product_id, path=path, remove=True)
240 @http.route(['/shop/set_cart/<product_id>/<set_number>/', '/shop/<path:path>/set_cart/<product_id>/<set_number>/'], type='http', auth="public")
241 def set_cart(self, path=None, product_id=0, set_number=0):
242 self.add_product_to_cart(product_id, set_number=set_number)
244 return werkzeug.utils.redirect("/shop/%s/" % path)
246 return werkzeug.utils.redirect("/shop/")
248 @http.route(['/shop/checkout/'], type='http', auth="public")
249 def checkout(self, **post):
250 website = request.registry['website']
252 order = get_current_order()
254 if order.state != 'draft' or not order.order_line:
255 return self.mycart(**post)
257 partner_obj = request.registry.get('res.partner')
258 user_obj = request.registry.get('res.users')
259 country_obj = request.registry.get('res.country')
260 country_state_obj = request.registry.get('res.country.state')
262 values = website.get_rendering_context({
263 'shipping': post.get("shipping"),
264 'error': post.get("error") and dict.fromkeys(post.get("error").split(","), 'error') or {}
268 if request.uid != website.get_public_user().id:
269 partner = user_obj.browse(request.cr, request.uid, request.uid).partner_id
270 partner_id = partner.id
271 checkout = user_obj.read(request.cr, SUPERUSER_ID, [partner_id], [])[0]
272 checkout['company'] = partner.parent_id and partner.parent_id.name or ''
274 shipping_ids = partner_obj.search(request.cr, request.uid, [("parent_id", "=", partner_id), ('type', "=", 'delivery')])
276 for k,v in partner_obj.read(request.cr, request.uid, shipping_ids[0]).items():
277 checkout['shipping_'+k] = v or ''
279 checkout.update(request.session.setdefault('checkout', {}))
280 for k,v in checkout.items():
281 checkout[k] = v or ''
282 values['checkout'] = checkout
284 values['countries'] = country_obj.browse(request.cr, SUPERUSER_ID, country_obj.search(request.cr, SUPERUSER_ID, [(1, "=", 1)]))
285 values['states'] = country_state_obj.browse(request.cr, SUPERUSER_ID, country_state_obj.search(request.cr, SUPERUSER_ID, [(1, "=", 1)]))
287 return website.render("website_sale.checkout", values)
289 @http.route(['/shop/confirm_order/'], type='http', auth="public")
290 def confirm_order(self, **post):
291 website = request.registry['website']
292 order = get_current_order()
295 partner_obj = request.registry.get('res.partner')
296 user_obj = request.registry.get('res.users')
298 if order.state != 'draft':
299 return werkzeug.utils.redirect("/shop/checkout/")
300 if not order.order_line:
301 error.append("empty_cart")
302 return werkzeug.utils.redirect("/shop/checkout/")
305 request.session['checkout'] = post
306 required_field = ['phone', 'zip', 'email', 'street', 'city', 'name', 'country_id']
307 for key in required_field:
308 if not post.get(key):
310 if post.get('shipping_different') and key != 'email' and not post.get("shipping_%s" % key):
311 error.append("shipping_%s" % key)
313 return werkzeug.utils.redirect("/shop/checkout/?error=%s&shipping=%s" % (",".join(error), post.get('shipping_different') and 'on' or ''))
315 # search or create company
318 company_ids = partner_obj.search(request.cr, SUPERUSER_ID, [("name", "ilike", post['company']), ('is_company', '=', True)])
319 company_id = company_ids and company_ids[0] or None
321 company_id = partner_obj.create(request.cr, SUPERUSER_ID, {'name': post['company'], 'is_company': True})
325 'phone': post['phone'],
327 'email': post['email'],
328 'street': post['street'],
329 'city': post['city'],
330 'name': post['name'],
331 'parent_id': company_id,
332 'country_id': post['country_id'],
333 'state_id': post['state_id'],
335 if request.uid != website.get_public_user().id:
336 partner_id = user_obj.browse(request.cr, request.uid, request.uid).partner_id.id
337 partner_obj.write(request.cr, request.uid, [partner_id], partner_value)
339 partner_id = partner_obj.create(request.cr, SUPERUSER_ID, partner_value)
342 if 'shipping_name' in post:
344 'fax': post['shipping_fax'],
345 'phone': post['shipping_phone'],
346 'zip': post['shipping_zip'],
347 'street': post['shipping_street'],
348 'city': post['shipping_city'],
349 'name': post['shipping_name'],
351 'parent_id': partner_id,
352 'country_id': post['shipping_country_id'],
353 'state_id': post['shipping_state_id'],
355 domain = [(key, '_id' in key and '=' or 'ilike', '_id' in key and int(value) or value)
356 for key, value in shipping_value.items() if key in required_field + ["type", "parent_id"]]
357 shipping_ids = partner_obj.search(request.cr, SUPERUSER_ID, domain)
359 shipping_id = shipping_ids[0]
360 partner_obj.write(request.cr, SUPERUSER_ID, [shipping_id], shipping_value)
362 shipping_id = partner_obj.create(request.cr, SUPERUSER_ID, shipping_value)
365 'partner_id': partner_id,
366 'partner_invoice_id': partner_id,
367 'partner_shipping_id': shipping_id or partner_id
369 order_value.update(request.registry.get('sale.order').onchange_partner_id(request.cr, SUPERUSER_ID, [], request.uid, context={})['value'])
370 order.write(order_value)
372 return werkzeug.utils.redirect("/shop/payment/")
374 @http.route(['/shop/payment/'], type='http', auth="public")
375 def payment(self, **post):
376 website = request.registry['website']
377 order = get_current_order()
379 if not order or not order.order_line:
380 return self.mycart(**post)
382 values = website.get_rendering_context({
387 payment_obj = request.registry.get('portal.payment.acquirer')
388 payment_ids = payment_obj.search(request.cr, SUPERUSER_ID, [('visible', '=', True)])
389 values['payments'] = payment_obj.browse(request.cr, SUPERUSER_ID, payment_ids)
390 for payment in values['payments']:
391 content = payment_obj.render(request.cr, SUPERUSER_ID, payment.id, order, order.name, order.pricelist_id.currency_id, order.amount_total)
392 payment._content = content
394 return website.render("website_sale.payment", values)
396 @http.route(['/shop/payment_validate/'], type='http', auth="public")
397 def payment_validate(self, **post):
398 request.httprequest.session['ecommerce_order_id'] = False
399 request.httprequest.session['ecommerce_pricelist'] = False
400 return werkzeug.utils.redirect("/shop/")
402 # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: