[MERGE] from trunk-website-event-chm: managment of tickets for an event to defined...
[odoo/odoo.git] / addons / website_sale / controllers / main.py
1 # -*- coding: utf-8 -*-
2
3 import math
4 import openerp
5 import simplejson
6 from openerp.osv import osv
7 from openerp.addons.web import http
8 from openerp.addons.web.http import request
9
10 def get_order(order_id=None):
11     order_obj = request.registry.get('sale.order')
12     # check if order allready exists
13     if order_id:
14         try:
15             order = order_obj.browse(request.cr, openerp.SUPERUSER_ID, order_id)
16             order.pricelist_id
17         except:
18             order_id = None
19     if not order_id:
20         fields = [k for k, v in order_obj._columns.items()]
21         order_value = order_obj.default_get(request.cr, openerp.SUPERUSER_ID, fields)
22         order_value['partner_id'] = request.registry.get('res.users').browse(request.cr, openerp.SUPERUSER_ID, request.uid).partner_id.id
23         order_value.update(order_obj.onchange_partner_id(request.cr, openerp.SUPERUSER_ID, [], request.uid, context={})['value'])
24         order_id = order_obj.create(request.cr, openerp.SUPERUSER_ID, order_value)
25         order = order_obj.browse(request.cr, openerp.SUPERUSER_ID, order_id)
26     return order
27
28 def get_current_order():
29     order = get_order(request.httprequest.session.get('ecommerce_order_id'))
30     if order.state != 'draft':
31         order = get_order()
32     request.httprequest.session['ecommerce_order_id'] = order.id
33     return order
34
35 class website(osv.osv):
36     _inherit = "website"
37     def get_rendering_context(self, additional_values=None):
38         values = {
39             'order': get_current_order(),
40             # 'website_sale_get_current_order': get_current_order, # TODO: replace 'order' key in templates
41         }
42         if additional_values:
43             values.update(additional_values)
44         return super(website, self).get_rendering_context(values)
45
46 class Ecommerce(http.Controller):
47
48     def get_categories(self):
49         category_obj = request.registry.get('pos.category')
50         category_ids = category_obj.search(request.cr, openerp.SUPERUSER_ID, [('parent_id', '=', False)])
51         categories = category_obj.browse(request.cr, openerp.SUPERUSER_ID, category_ids)
52         print categories
53         return categories
54
55     def render(self, template, values={}):
56         website = request.registry['website']
57         _values = {
58             'categories': self.get_categories(),
59         }
60         _values.update(values)
61         return website.render(template, _values)
62
63     def recommended_product(self, my_pids):
64         if not my_pids:
65             return []
66         product_obj = request.registry.get('product.product')
67
68         my_pids = str(my_pids)[1:-1]
69         product_ids = []
70         query = """
71             SELECT      sol.product_id
72             FROM        sale_order_line as my
73             LEFT JOIN   sale_order_line as sol
74             ON          sol.order_id = my.order_id
75             WHERE       my.product_id in (%s)
76             AND         sol.product_id not in (%s)
77             GROUP BY    sol.product_id
78             ORDER BY    COUNT(sol.order_id) DESC
79             LIMIT 8
80         """ % (my_pids, my_pids)
81         request.cr.execute(query)
82         for p in request.cr.fetchall():
83             product_ids.append(p[0])
84
85         # search to apply access rules
86         product_ids = product_obj.search(request.cr, request.uid, [("id", "in", product_ids)])
87         return product_obj.browse(request.cr, request.uid, product_ids)
88
89     @http.route(['/shop', '/shop/category/<cat_id>', '/shop/category/<cat_id>/page/<page>', '/shop/page/<page>'], type='http', auth="public")
90     def category(self, cat_id=0, page=0, **post):
91
92         website = request.registry['website']
93         product_obj = request.registry.get('product.product')
94
95         domain = [("sale_ok", "=", True)]
96         if openerp.SUPERUSER_ID != request.uid:
97             domain += [('website_published', '=', True)]
98
99         if cat_id:
100             cat_id = int(cat_id)
101             domain = [('pos_categ_id.id', 'child_of', cat_id)] + domain
102
103         product_count = len(product_obj.search(request.cr, request.uid, domain))
104         page_count = int(math.ceil(product_count / 20.0))
105
106         #if post.get("search"):
107          #   domain += ['|', '|', ('name', 'ilike', "%%%s%%" % post.get("search")), ('description', 'ilike', "%%%s%%" % post.get("search")), ('pos_categ_id.name', 'ilike', "%%%s%%" % post.get("search"))]
108
109         page = max(1,min(int(page),page_count))
110         offset = (page-1) * 20
111
112         if page_count <= 5 or page <= 3:
113             pmin = 1
114             pmax = min(page_count,5)
115         elif page >= page_count - 2:
116             pmin = page_count - 4
117             pmax = page_count
118         else:
119             pmin = page - 2
120             pmax = page + 2
121
122         pages = range(pmin, pmax+1)
123
124         product_ids = product_obj.search(request.cr, request.uid, domain, limit=20, offset=offset)
125
126         values = website.get_rendering_context({
127             'current_category': cat_id,
128             'products': product_obj.browse(request.cr, request.uid, product_ids),
129             'search': post.get("search"),
130             'page_count': page_count,
131             'pages': pages,
132             'page': page,
133         })
134         return self.render("website_sale.products", values)
135
136     @http.route(['/shop/product/<product_id>'], type='http', auth="public")
137     def product(self, cat_id=0, product_id=0):
138         website = request.registry['website']
139         order = get_current_order()
140
141         product_id = product_id and int(product_id) or 0
142         product_obj = request.registry.get('product.product')
143
144         line = [line for line in order.order_line if line.product_id.id == product_id]
145         quantity = line and int(line[0].product_uom_qty) or 0
146
147         values = website.get_rendering_context({
148             'product': product_obj.browse(request.cr, request.uid, product_id),
149             'quantity': quantity,
150             'recommended_products': self.recommended_product([product_id]),
151         })
152         return self.render("website_sale.product", values)
153
154     @http.route(['/shop/mycart'], type='http', auth="public")
155     def mycart(self, **post):
156         website = request.registry['website']
157         order = get_current_order()
158
159         if post.get('code'):
160             pricelist_obj = request.registry.get('product.pricelist')
161             pricelist_ids = pricelist_obj.search(request.cr, openerp.SUPERUSER_ID, [('code', '=', post.get('code'))])
162             if pricelist_ids:
163                 order.write({'pricelist_id': pricelist_ids[0]})
164
165         my_pids = [line.product_id.id for line in order.order_line]
166         values = website.get_rendering_context({
167             "recommended_products": self.recommended_product(my_pids),
168         })
169
170         return self.render("website_sale.mycart", values)
171
172     @http.route(['/shop/add_cart'], type='http', auth="public")
173     def add_cart(self, product_id=0, remove=False):
174         website = request.registry['website']
175         context = {}
176
177         order_line_obj = request.registry.get('sale.order.line')
178         user_obj = request.registry.get('res.users')
179
180         product_id = product_id and int(product_id) or 0
181         order = get_current_order()
182
183         quantity = 0
184
185         # values initialisation
186         values = {}
187         order_line_ids = order_line_obj.search(request.cr, openerp.SUPERUSER_ID, [('order_id', '=', order.id), ('product_id', '=', product_id)], context=context)
188         if order_line_ids:
189             order_line = order_line_obj.read(request.cr, openerp.SUPERUSER_ID, order_line_ids, [], context=context)[0]
190             quantity = order_line['product_uom_qty'] + (remove and -1 or 1)
191             if quantity <= 0:
192                 order_line_obj.unlink(request.cr, openerp.SUPERUSER_ID, order_line_ids, context=context)
193         else:
194             fields = [k for k, v in order_line_obj._columns.items()]
195             values = order_line_obj.default_get(request.cr, openerp.SUPERUSER_ID, fields, context=context)
196             quantity = 1
197         values['product_uom_qty'] = quantity
198         values['product_id'] = product_id
199         values['order_id'] = order.id
200
201         # change and record value
202         if quantity:
203             pricelist_id = order.pricelist_id and order.pricelist_id.id or False
204             values.update(order_line_obj.product_id_change(request.cr, openerp.SUPERUSER_ID, [], pricelist_id, product_id,
205                 partner_id=user_obj.browse(request.cr, openerp.SUPERUSER_ID, request.uid).partner_id.id,
206                 context=context)['value'])
207             if order_line_ids:
208                 order_line_obj.write(request.cr, openerp.SUPERUSER_ID, order_line_ids, values, context=context)
209             else:
210                 order_line_id = order_line_obj.create(request.cr, openerp.SUPERUSER_ID, values, context=context)
211                 order.write({'order_line': [(4, order_line_id)]}, context=context)
212
213         values = website.get_rendering_context()
214         html = self.render("website_sale.total", values)
215         return simplejson.dumps({"quantity": quantity, "totalHTML": html})
216
217     @http.route(['/shop/remove_cart'], type='http', auth="public")
218     def remove_cart(self, product_id=0):
219         return self.add_cart(product_id=product_id, remove=True)
220
221     @http.route(['/shop/checkout'], type='http', auth="public")
222     def checkout(self, **post):
223         website = request.registry['website']
224         values = website.get_rendering_context({
225             'partner': False
226         })
227         order = get_current_order()
228
229         if order.state != 'draft':
230             return self.confirmed(**post)
231         if not order.order_line:
232             return self.mycart(**post)
233
234         partner_obj = request.registry.get('res.partner')
235         user_obj = request.registry.get('res.users')
236         country_obj = request.registry.get('res.country')
237         country_state_obj = request.registry.get('res.country.state')
238         payment_obj = request.registry.get('portal.payment.acquirer')
239
240         if request.uid != website.get_public_user().id:
241             values['partner'] = user_obj.browse(request.cr, request.uid, request.uid).partner_id
242             shipping_ids = partner_obj.search(request.cr, request.uid, [("parent_id", "=", values['partner'].id), ('type', "=", 'delivery')])
243             values['shipping'] = None
244             if shipping_ids:
245                 values['shipping'] = partner_obj.browse(request.cr, request.uid, shipping_ids[0])
246
247         values['countries'] = country_obj.browse(request.cr, openerp.SUPERUSER_ID, country_obj.search(request.cr, openerp.SUPERUSER_ID, [(1, "=", 1)]))
248         values['states'] = country_state_obj.browse(request.cr, openerp.SUPERUSER_ID, country_state_obj.search(request.cr, openerp.SUPERUSER_ID, [(1, "=", 1)]))
249
250         payment_ids = payment_obj.search(request.cr, openerp.SUPERUSER_ID, [('visible', '=', True)])
251         values['payments'] = payment_obj.browse(request.cr, openerp.SUPERUSER_ID, payment_ids)
252         for payment in values['payments']:
253             content = payment_obj.render(request.cr, openerp.SUPERUSER_ID, payment.id, order, order.name, order.pricelist_id.currency_id, order.amount_total)
254             payment._content = content
255
256         return website.render("website_sale.checkout", values)
257
258     @http.route(['/shop/confirm_order'], type='http', auth="public")
259     def confirm_order(self, **post):
260         website = request.registry['website']
261         order = get_current_order()
262
263         json = {'error': [], 'validation': False}
264         partner_obj = request.registry.get('res.partner')
265         user_obj = request.registry.get('res.users')
266
267         if order.state != 'draft':
268             json['validation'] = True
269             return json
270         if not order.order_line:
271             json['error'].append("empty_cart")
272             return json
273
274         # check values
275         required_field = ['phone', 'zip', 'email', 'street', 'city', 'name', 'country_id']
276         for key in required_field:
277             if not post.get(key):
278                 json['error'].append(key)
279             if 'shipping_name' in post and key != 'email' and not post.get("shipping_%s" % key):
280                 json['error'].append("shipping_%s" % key)
281         if json['error']:
282             return simplejson.dumps(json)
283
284         # search or create company
285         company_id = None
286         if post['company']:
287             company_ids = partner_obj.search(request.cr, openerp.SUPERUSER_ID, [("name", "ilike", post['company']), ('is_company', '=', True)])
288             company_id = company_ids and company_ids[0] or None
289             if not company_id:
290                 company_id = partner_obj.create(request.cr, openerp.SUPERUSER_ID, {'name': post['company'], 'is_company': True})
291
292         partner_value = {
293             'fax': post['fax'],
294             'phone': post['phone'],
295             'zip': post['zip'],
296             'email': post['email'],
297             'street': post['street'],
298             'city': post['city'],
299             'name': post['name'],
300             'parent_id': company_id,
301             'country_id': post['country_id'],
302             'state_id': post['state_id'],
303         }
304         if request.uid != website.get_public_user().id:
305             partner_id = user_obj.browse(request.cr, request.uid, request.uid).partner_id.id
306             partner_obj.write(request.cr, request.uid, [partner_id], partner_value)
307         else:
308             partner_id = partner_obj.create(request.cr, openerp.SUPERUSER_ID, partner_value)
309
310         shipping_id = None
311         if 'shipping_name' in post:
312             shipping_value = {
313                 'fax': post['shipping_fax'],
314                 'phone': post['shipping_phone'],
315                 'zip': post['shipping_zip'],
316                 'street': post['shipping_street'],
317                 'city': post['shipping_city'],
318                 'name': post['shipping_name'],
319                 'type': 'delivery',
320                 'parent_id': partner_id,
321                 'country_id': post['shipping_country_id'],
322                 'state_id': post['shipping_state_id'],
323             }
324             domain = [(key, '_id' in key and '=' or 'ilike', '_id' in key and int(value) or value)
325                 for key, value in shipping_value.items() if key in required_field + ["type", "parent_id"]]
326             shipping_ids = partner_obj.search(request.cr, openerp.SUPERUSER_ID, domain)
327             if shipping_ids:
328                 shipping_id = shipping_ids[0]
329                 partner_obj.write(request.cr, openerp.SUPERUSER_ID, [shipping_id], shipping_value)
330             else:
331                 shipping_id = partner_obj.create(request.cr, openerp.SUPERUSER_ID, shipping_value)
332
333         order_value = {
334             'state': 'progress',
335             'partner_id': partner_id,
336             'partner_invoice_id': partner_id,
337             'partner_shipping_id': shipping_id or partner_id
338         }
339         order_value.update(request.registry.get('sale.order').onchange_partner_id(request.cr, openerp.SUPERUSER_ID, [], request.uid, context={})['value'])
340         order.write(order_value)
341
342         json['validation'] = True
343         return simplejson.dumps(json)
344
345     @http.route(['/shop/confirmed'], type='http', auth="public")
346     def confirmed(self, **post):
347         website = request.registry['website']
348
349         if request.httprequest.session.get('ecommerce_order_id'):
350             order = get_current_order()
351             if order.state != 'draft':
352                 request.httprequest.session['ecommerce_order_id_old'] = order.id
353                 request.httprequest.session['ecommerce_order_id'] = None
354
355         order_old = get_order(request.httprequest.session.get('ecommerce_order_id_old'))
356         if not order_old.order_line:
357             return self.mycart(**post)
358
359         values = website.get_rendering_context({
360             'temp': 0,
361             'order': order_old,
362         })
363         return self.render("website_sale.confirmed", values)
364
365     @http.route(['/shop/publish'], type='http', auth="public")
366     def publish(self, **post):
367         product_id = int(post['id'])
368         product_obj = request.registry['product.product']
369
370         product = product_obj.browse(request.cr, request.uid, product_id)
371         product_obj.write(request.cr, request.uid, [product_id], {'website_published': not product.website_published})
372         product = product_obj.browse(request.cr, request.uid, product_id)
373
374         return product.website_published and "1" or "0"
375
376 # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: