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