[MERGE] forward port of branch 8.0 up to 591e329
[odoo/odoo.git] / addons / website_sale / models / sale_order.py
1 # -*- coding: utf-8 -*-
2 import random
3
4 from openerp import SUPERUSER_ID
5 from openerp.osv import osv, orm, fields
6 from openerp.addons.web.http import request
7
8
9 class sale_order(osv.Model):
10     _inherit = "sale.order"
11
12     def _cart_qty(self, cr, uid, ids, field_name, arg, context=None):
13         res = dict()
14         for order in self.browse(cr, uid, ids, context=context):
15             res[order.id] = int(sum(l.product_uom_qty for l in (order.website_order_line or [])))
16         return res
17
18     _columns = {
19         'website_order_line': fields.one2many(
20             'sale.order.line', 'order_id',
21             string='Order Lines displayed on Website', readonly=True,
22             help='Order Lines to be displayed on the website. They should not be used for computation purpose.',
23         ),
24         'cart_quantity': fields.function(_cart_qty, type='integer', string='Cart Quantity'),
25         'payment_acquirer_id': fields.many2one('payment.acquirer', 'Payment Acquirer', on_delete='set null', copy=False),
26         'payment_tx_id': fields.many2one('payment.transaction', 'Transaction', on_delete='set null', copy=False),
27     }
28
29     def _get_errors(self, cr, uid, order, context=None):
30         return []
31
32     def _get_website_data(self, cr, uid, order, context):
33         return {
34             'partner': order.partner_id.id,
35             'order': order
36         }
37
38     def _cart_find_product_line(self, cr, uid, ids, product_id=None, line_id=None, context=None, **kwargs):
39         for so in self.browse(cr, uid, ids, context=context):
40             domain = [('order_id', '=', so.id), ('product_id', '=', product_id)]
41             if line_id:
42                 domain += [('id', '=', line_id)]
43             return self.pool.get('sale.order.line').search(cr, SUPERUSER_ID, domain, context=context)
44
45     def _website_product_id_change(self, cr, uid, ids, order_id, product_id, qty=0, line_id=None, context=None):
46         so = self.pool.get('sale.order').browse(cr, uid, order_id, context=context)
47
48         values = self.pool.get('sale.order.line').product_id_change(cr, SUPERUSER_ID, [],
49             pricelist=so.pricelist_id.id,
50             product=product_id,
51             partner_id=so.partner_id.id,
52             fiscal_position=so.fiscal_position.id,
53             qty=qty,
54             context=context
55         )['value']
56
57         if line_id:
58             line = self.pool.get('sale.order.line').browse(cr, SUPERUSER_ID, line_id, context=context)
59             values['name'] = line.name
60         else:
61             product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
62             values['name'] = product.description_sale or product.name
63
64         values['product_id'] = product_id
65         values['order_id'] = order_id
66         if values.get('tax_id') != None:
67             values['tax_id'] = [(6, 0, values['tax_id'])]
68         return values
69
70     def _cart_update(self, cr, uid, ids, product_id=None, line_id=None, add_qty=0, set_qty=0, context=None, **kwargs):
71         """ Add or set product quantity, add_qty can be negative """
72         sol = self.pool.get('sale.order.line')
73
74         quantity = 0
75         for so in self.browse(cr, uid, ids, context=context):
76             if line_id != False:
77                 line_ids = so._cart_find_product_line(product_id, line_id, context=context, **kwargs)
78                 if line_ids:
79                     line_id = line_ids[0]
80
81             # Create line if no line with product_id can be located
82             if not line_id:
83                 values = self._website_product_id_change(cr, uid, ids, so.id, product_id, qty=1, context=context)
84                 line_id = sol.create(cr, SUPERUSER_ID, values, context=context)
85                 if add_qty:
86                     add_qty -= 1
87
88             # compute new quantity
89             if set_qty:
90                 quantity = set_qty
91             elif add_qty != None:
92                 quantity = sol.browse(cr, SUPERUSER_ID, line_id, context=context).product_uom_qty + (add_qty or 0)
93
94             # Remove zero of negative lines
95             if quantity <= 0:
96                 sol.unlink(cr, SUPERUSER_ID, [line_id], context=context)
97             else:
98                 # update line
99                 values = self._website_product_id_change(cr, uid, ids, so.id, product_id, qty=quantity, line_id=line_id, context=context)
100                 values['product_uom_qty'] = quantity
101                 sol.write(cr, SUPERUSER_ID, [line_id], values, context=context)
102
103         return {'line_id': line_id, 'quantity': quantity}
104
105     def _cart_accessories(self, cr, uid, ids, context=None):
106         for order in self.browse(cr, uid, ids, context=context):
107             s = set(j.id for l in (order.website_order_line or []) for j in (l.product_id.accessory_product_ids or []))
108             s -= set(l.product_id.id for l in order.order_line)
109             product_ids = random.sample(s, min(len(s),3))
110             return self.pool['product.product'].browse(cr, uid, product_ids, context=context)
111
112 class website(orm.Model):
113     _inherit = 'website'
114
115     _columns = {
116         'pricelist_id': fields.related('user_id','partner_id','property_product_pricelist',
117             type='many2one', relation='product.pricelist', string='Default Pricelist'),
118         'currency_id': fields.related('pricelist_id','currency_id',
119             type='many2one', relation='res.currency', string='Default Currency'),
120     }
121
122     def sale_product_domain(self, cr, uid, ids, context=None):
123         return [("sale_ok", "=", True)]
124
125     def sale_get_order(self, cr, uid, ids, force_create=False, code=None, update_pricelist=None, context=None):
126         sale_order_obj = self.pool['sale.order']
127         sale_order_id = request.session.get('sale_order_id')
128         sale_order = None
129         # create so if needed
130         if not sale_order_id and (force_create or code):  
131             # TODO cache partner_id session
132             partner = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id
133
134             for w in self.browse(cr, uid, ids):
135                 values = {
136                     'user_id': w.user_id.id,
137                     'partner_id': partner.id,
138                     'pricelist_id': partner.property_product_pricelist.id,
139                     'team_id': self.pool.get('ir.model.data').get_object_reference(cr, uid, 'website', 'salesteam_website_sales')[1],
140                 }
141                 sale_order_id = sale_order_obj.create(cr, SUPERUSER_ID, values, context=context)
142                 values = sale_order_obj.onchange_partner_id(cr, SUPERUSER_ID, [], partner.id, context=context)['value']
143                 sale_order_obj.write(cr, SUPERUSER_ID, [sale_order_id], values, context=context)
144                 request.session['sale_order_id'] = sale_order_id
145         if sale_order_id:
146             # TODO cache partner_id session
147             partner = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id
148
149             sale_order = sale_order_obj.browse(cr, SUPERUSER_ID, sale_order_id, context=context)
150             if not sale_order.exists():
151                 request.session['sale_order_id'] = None
152                 return None
153
154             # check for change of pricelist with a coupon
155             if code and code != sale_order.pricelist_id.code:
156                 pricelist_ids = self.pool['product.pricelist'].search(cr, SUPERUSER_ID, [('code', '=', code)], context=context)
157                 if pricelist_ids:
158                     pricelist_id = pricelist_ids[0]
159                     request.session['sale_order_code_pricelist_id'] = pricelist_id
160                     update_pricelist = True
161
162             pricelist_id = request.session.get('sale_order_code_pricelist_id') or partner.property_product_pricelist.id
163
164             # check for change of partner_id ie after signup
165             if sale_order.partner_id.id != partner.id and request.website.partner_id.id != partner.id:
166                 flag_pricelist = False
167                 if pricelist_id != sale_order.pricelist_id.id:
168                     flag_pricelist = True
169                 fiscal_position = sale_order.fiscal_position and sale_order.fiscal_position.id or False
170
171                 values = sale_order_obj.onchange_partner_id(cr, SUPERUSER_ID, [sale_order_id], partner.id, context=context)['value']
172                 if values.get('fiscal_position'):
173                     order_lines = map(int,sale_order.order_line)
174                     values.update(sale_order_obj.onchange_fiscal_position(cr, SUPERUSER_ID, [],
175                         values['fiscal_position'], [[6, 0, order_lines]], context=context)['value'])
176
177                 values['partner_id'] = partner.id
178                 sale_order_obj.write(cr, SUPERUSER_ID, [sale_order_id], values, context=context)
179
180                 if flag_pricelist or values.get('fiscal_position') != fiscal_position:
181                     update_pricelist = True
182
183             # update the pricelist
184             if update_pricelist:
185                 values = {'pricelist_id': pricelist_id}
186                 values.update(sale_order.onchange_pricelist_id(pricelist_id, None)['value'])
187                 sale_order.write(values)
188                 for line in sale_order.order_line:
189                     sale_order._cart_update(product_id=line.product_id.id, line_id=line.id, add_qty=0)
190
191             # update browse record
192             if (code and code != sale_order.pricelist_id.code) or sale_order.partner_id.id !=  partner.id:
193                 sale_order = sale_order_obj.browse(cr, SUPERUSER_ID, sale_order.id, context=context)
194
195         return sale_order
196
197     def sale_get_transaction(self, cr, uid, ids, context=None):
198         transaction_obj = self.pool.get('payment.transaction')
199         tx_id = request.session.get('sale_transaction_id')
200         if tx_id:
201             tx_ids = transaction_obj.search(cr, SUPERUSER_ID, [('id', '=', tx_id), ('state', 'not in', ['cancel'])], context=context)
202             if tx_ids:
203                 return transaction_obj.browse(cr, SUPERUSER_ID, tx_ids[0], context=context)
204             else:
205                 request.session['sale_transaction_id'] = False
206         return False
207
208     def sale_reset(self, cr, uid, ids, context=None):
209         request.session.update({
210             'sale_order_id': False,
211             'sale_transaction_id': False,
212             'sale_order_code_pricelist_id': False,
213         })
214
215