diff --git a/addons/event_sale/event_sale.py b/addons/event_sale/event_sale.py index b4f42673aba..c96b5d73932 100644 --- a/addons/event_sale/event_sale.py +++ b/addons/event_sale/event_sale.py @@ -37,6 +37,9 @@ class product_template(osv.osv): class product(osv.osv): _inherit = 'product.product' + _columns = { + 'event_ticket_ids': fields.one2many('event.event.ticket', 'product_id', 'Event Tickets'), + } def onchange_event_ok(self, cr, uid, ids, type, event_ok, context=None): # cannot directly forward to product.template as the ids are theoretically different diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 5e3f27805a4..9b9cb48e91d 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -626,6 +626,48 @@ class sale_order(osv.osv): def action_done(self, cr, uid, ids, context=None): return self.write(cr, uid, ids, {'state': 'done'}, context=context) + def onchange_fiscal_position(self, cr, uid, ids, fiscal_position, order_lines, context=None): + '''Update taxes of order lines for each line where a product is defined + + :param list ids: not used + :param int fiscal_position: sale order fiscal position + :param list order_lines: command list for one2many write method + ''' + order_line = [] + fiscal_obj = self.pool.get('account.fiscal.position') + product_obj = self.pool.get('product.product') + line_obj = self.pool.get('sale.order.line') + + fpos = False + if fiscal_position: + fpos = fiscal_obj.browse(cr, uid, fiscal_position, context=context) + + for line in order_lines: + # create (0, 0, { fields }) + # update (1, ID, { fields }) + if line[0] in [0, 1]: + prod = None + if line[2].get('product_id'): + prod = product_obj.browse(cr, uid, line[2]['product_id'], context=context) + elif line[1]: + prod = line_obj.browse(cr, uid, line[1], context=context).product_id + if prod and prod.taxes_id: + line[2]['tax_id'] = [[6, 0, fiscal_obj.map_tax(cr, uid, fpos, prod.taxes_id)]] + order_line.append(line) + + # link (4, ID) + # link all (6, 0, IDS) + elif line[0] in [4, 6]: + line_ids = line[0] == 4 and [line[1]] or line[2] + for line_id in line_ids: + prod = line_obj.browse(cr, uid, line_id, context=context).product_id + if prod and prod.taxes_id: + order_line.append([1, line_id, {'tax_id': [[6, 0, fiscal_obj.map_tax(cr, uid, fpos, prod.taxes_id)]]}]) + else: + order_line.append([4, line_id]) + else: + order_line.append(line) + return {'value': {'order_line': order_line}} # TODO add a field price_unit_uos @@ -862,15 +904,15 @@ class sale_order_line(osv.osv): lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None): context = context or {} lang = lang or context.get('lang',False) - if not partner_id: + if not partner_id: raise osv.except_osv(_('No Customer Defined!'), _('Before choosing a product,\n select a customer in the sales form.')) warning = {} product_uom_obj = self.pool.get('product.uom') partner_obj = self.pool.get('res.partner') product_obj = self.pool.get('product.product') context = {'lang': lang, 'partner_id': partner_id} - if partner_id: - lang = partner_obj.browse(cr, uid, partner_id).lang + partner = partner_obj.browse(cr, uid, partner_id) + lang = partner.lang context_partner = {'lang': lang, 'partner_id': partner_id} if not product: @@ -896,7 +938,12 @@ class sale_order_line(osv.osv): uos = False else: uos = False - fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False + + fpos = False + if not fiscal_position: + fpos = partner.property_account_position or False + else: + fpos = self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) if update_tax: #The quantity only have changed result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, product_obj.taxes_id) diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 0090c4a9bfc..600505bfdf1 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -206,7 +206,8 @@ - + diff --git a/addons/website/__openerp__.py b/addons/website/__openerp__.py index f2b31726468..9de078a8a48 100644 --- a/addons/website/__openerp__.py +++ b/addons/website/__openerp__.py @@ -12,7 +12,7 @@ OpenERP Website CMS 'depends': ['web', 'share', 'mail'], 'installable': True, 'data': [ - 'data/website_data.xml', + 'data/data.xml', 'security/ir.model.access.csv', 'security/ir_ui_view.xml', 'views/website_templates.xml', @@ -23,7 +23,7 @@ OpenERP Website CMS 'views/ir_actions.xml', ], 'demo': [ - 'data/website_demo.xml', + 'data/demo.xml', ], 'qweb': ['static/src/xml/website.backend.xml'], 'application': True, diff --git a/addons/website/data/website_data.xml b/addons/website/data/data.xml similarity index 100% rename from addons/website/data/website_data.xml rename to addons/website/data/data.xml diff --git a/addons/website/data/website_demo.xml b/addons/website/data/demo.xml similarity index 100% rename from addons/website/data/website_demo.xml rename to addons/website/data/demo.xml diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 8d8e0b3c91d..e137bfa6207 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -32,6 +32,13 @@ class ir_http(orm.AbstractModel): page=PageConverter, ) + def _auth_method_public(self): + # TODO: select user_id from matching website + if not request.session.uid: + request.uid = self.pool['ir.model.data'].xmlid_to_res_id(request.cr, openerp.SUPERUSER_ID, 'base.public_user') + else: + request.uid = request.session.uid + def _dispatch(self): first_pass = not hasattr(request, 'website') request.website = None diff --git a/addons/website/models/website.py b/addons/website/models/website.py index d0aca1c815f..3b14cd1e9c4 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -109,10 +109,6 @@ class website(osv.osv): menu = menus and menus[0] or False return dict( map(lambda x: (x, menu), ids) ) - def _get_public_user(self, cr, uid, ids, name='public_user', arg=(), context=None): - ref = self.get_public_user(cr, uid, context=context) - return dict( map(lambda x: (x, ref), ids) ) - _name = "website" # Avoid website.website convention for conciseness (for new api). Got a special authorization from xmo and rco _description = "Website" _columns = { @@ -129,13 +125,17 @@ class website(osv.osv): 'social_googleplus': fields.char('Google+ Account'), 'google_analytics_key': fields.char('Google Analytics Key'), 'user_id': fields.many2one('res.users', string='Public User'), - 'public_user': fields.function(_get_public_user, relation='res.users', type='many2one', string='Public User'), + 'partner_id': fields.related('user_id','partner_id', type='many2one', relation='res.partner', string='Public Partner'), 'menu_id': fields.function(_get_menu, relation='website.menu', type='many2one', string='Main Menu', store= { 'website.menu': (_get_menu_website, ['sequence','parent_id','website_id'], 10) }) } + _defaults = { + 'company_id': lambda self,cr,uid,c: self.pool['ir.model.data'].xmlid_to_res_id(cr, openerp.SUPERUSER_ID, 'base.public_user'), + } + # cf. Wizard hack in website_views.xml def noop(self, *args, **kwargs): pass @@ -186,11 +186,6 @@ class website(osv.osv): except: return False - def get_public_user(self, cr, uid, context=None): - uid = openerp.SUPERUSER_ID - res = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'public_user') - return res and res[1] or False - @openerp.tools.ormcache(skiparg=3) def _get_languages(self, cr, uid, id, context=None): website = self.browse(cr, uid, id) @@ -342,7 +337,7 @@ class website(osv.osv): """ router = request.httprequest.app.get_db_router(request.db) # Force enumeration to be performed as public user - uid = self.get_public_user(cr, uid, context=context) + uid = request.website.user_id.id url_list = [] for rule in router.iter_rules(): if not self.rule_is_enumerable(rule): diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js index 2a661b4cc9b..0544d29df08 100644 --- a/addons/website/static/src/js/website.tour.js +++ b/addons/website/static/src/js/website.tour.js @@ -104,11 +104,11 @@ var T = website.Tour = { if (tour.path && !window.location.href.match(new RegExp("("+T.getLang()+")?"+tour.path+"#?$", "i"))) { var href = "/"+T.getLang()+tour.path; console.log("Tour Begin from run method (redirection to "+href+")"); - T.saveState(tour.id, mode || tour.mode, -1); + T.saveState(tour.id, mode || tour.mode, -1, 0); window.location.href = href; } else { console.log("Tour Begin from run method"); - T.saveState(tour.id, mode || tour.mode, 0); + T.saveState(tour.id, mode || tour.mode, 0, 0); T.running(); } }, @@ -311,7 +311,7 @@ var T = website.Tour = { }; window.location.hash = ""; console.log("Tour Begin from url hash"); - T.saveState(state.id, state.mode, state.step_id); + T.saveState(state.id, state.mode, state.step_id, 0); } if (!state.id) { return; @@ -341,8 +341,8 @@ var T = website.Tour = { } return tour_ids; }, - saveState: function (tour_id, mode, step_id) { - localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0, "time": this.time})); + saveState: function (tour_id, mode, step_id, number) { + localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0, "time": this.time, "number": number+1})); }, reset: function () { var state = T.getState(); @@ -402,6 +402,7 @@ var T = website.Tour = { if (T.check(next)) { clearTimeout(T.currentTimer); // use an other timeout for cke dom loading + T.saveState(state.id, state.mode, state.step.id, 0); setTimeout(function () { T.nextStep(next); }, T.defaultDelay); @@ -421,7 +422,13 @@ var T = website.Tour = { } step = step || state.step; - T.saveState(state.id, state.mode, step.id); + var next = state.tour.steps[step.id+1]; + + if (state.number > 3) { + T.error(next, "Cycling. Can't reach the next step"); + } + + T.saveState(state.id, state.mode, step.id, state.number); if (step.id !== state.step_id) { console.log("Tour Step: '" + (step._title || step.title) + "' (" + (new Date().getTime() - this.time) + "ms)"); @@ -433,7 +440,6 @@ var T = website.Tour = { step.onload(); } - var next = state.tour.steps[step.id+1]; if (next) { setTimeout(function () { T.waitNextStep(); diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py index aae57e32a93..b00e7038d5c 100644 --- a/addons/website_event/controllers/main.py +++ b/addons/website_event/controllers/main.py @@ -34,6 +34,7 @@ import time from dateutil.relativedelta import relativedelta from openerp import tools import werkzeug.urls +from openerp.addons.website.models.website import slug try: import GeoIP @@ -211,7 +212,8 @@ class website_event(http.Controller): 'date_end': (date_begin + timedelta(days=(1))).strftime('%Y-%m-%d'), } event_id = Event.create(request.cr, request.uid, vals, context=context) - return request.redirect("/event/%s?enable_editor=1" % event_id) + event = Event.browse(request.cr, request.uid, event_id, context=context) + return request.redirect("/event/%s/register?enable_editor=1" % slug(event)) def get_visitors_country(self): GI = GeoIP.open('/usr/share/GeoIP/GeoIP.dat', 0) diff --git a/addons/website_event/security/ir.model.access.csv b/addons/website_event/security/ir.model.access.csv index 2d98213669f..aeb66c3e088 100644 --- a/addons/website_event/security/ir.model.access.csv +++ b/addons/website_event/security/ir.model.access.csv @@ -1,3 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_event_event_public,event.event.public,event.model_event_event,base.group_public,1,0,0,0 +access_event_event_portal,event.event.portal,event.model_event_event,base.group_portal,1,0,0,0 access_event_type_public,event.type.public,event.model_event_type,base.group_public,1,0,0,0 +access_event_type_portal,event.type.portal,event.model_event_type,base.group_portal,1,0,0,0 diff --git a/addons/website_event_sale/controllers/main.py b/addons/website_event_sale/controllers/main.py index 2db874cf5b7..1c39484f8c8 100644 --- a/addons/website_event_sale/controllers/main.py +++ b/addons/website_event_sale/controllers/main.py @@ -27,57 +27,24 @@ from openerp.tools.translate import _ class website_event(website_event): - @http.route(['/event/add_cart'], type='http', auth="public", website=True, multilang=True) - def add_cart(self, event_id, **post): - user_obj = request.registry['res.users'] - order_line_obj = request.registry.get('sale.order.line') + + @http.route(['/event/cart/update'], type='http', auth="public", methods=['POST'], website=True, multilang=True) + def cart_update(self, event_id, **post): + cr, uid, context = request.cr, request.uid, request.context ticket_obj = request.registry.get('event.event.ticket') - order_obj = request.registry.get('sale.order') - website = request.registry['website'] - order = website.ecommerce_get_current_order(request.cr, request.uid, context=request.context) - if not order: - order = website.ecommerce_get_new_order(request.cr, request.uid, context=request.context) - - partner_id = user_obj.browse(request.cr, SUPERUSER_ID, request.uid, - context=request.context).partner_id.id - - fields = [k for k, v in order_line_obj._columns.items()] - values = order_line_obj.default_get(request.cr, SUPERUSER_ID, fields, - context=request.context) - - _values = None + sale = False for key, value in post.items(): - try: - quantity = int(value) - assert quantity > 0 - except: - quantity = None - ticket_id = key.split("-")[0] == 'ticket' and int(key.split("-")[1]) or None - if not ticket_id or not quantity: + quantity = int(value or "0") + if not quantity: continue - ticket = ticket_obj.browse(request.cr, request.uid, ticket_id, - context=request.context) + sale = True + ticket_id = key.split("-")[0] == 'ticket' and int(key.split("-")[1]) or None + ticket = ticket_obj.browse(cr, SUPERUSER_ID, ticket_id, context=context) + request.website.sale_get_order(force_create=1)._cart_update( + product_id=ticket.product_id.id, add_qty=quantity, context=dict(context, event_ticket_id=ticket.id)) - values['product_id'] = ticket.product_id.id - values['event_id'] = ticket.event_id.id - values['event_ticket_id'] = ticket.id - values['product_uom_qty'] = quantity - values['price_unit'] = ticket.price - values['order_id'] = order.id - values['name'] = "%s: %s" % (ticket.event_id.name, ticket.name) - - # change and record value - pricelist_id = order.pricelist_id and order.pricelist_id.id or False - _values = order_line_obj.product_id_change( - request.cr, SUPERUSER_ID, [], pricelist_id, ticket.product_id.id, - partner_id=partner_id, context=request.context)['value'] - _values.update(values) - - order_line_id = order_line_obj.create(request.cr, SUPERUSER_ID, _values, context=request.context) - order_obj.write(request.cr, SUPERUSER_ID, [order.id], {'order_line': [(4, order_line_id)]}, context=request.context) - - if not _values: + if not sale: return request.redirect("/event/%s" % event_id) return request.redirect("/shop/checkout") diff --git a/addons/website_event_sale/models/__init__.py b/addons/website_event_sale/models/__init__.py index b0e3f323f8c..ed23b1cd133 100644 --- a/addons/website_event_sale/models/__init__.py +++ b/addons/website_event_sale/models/__init__.py @@ -1,3 +1,3 @@ import product -import sale_order import website +import sale_order diff --git a/addons/website_event_sale/models/sale_order.py b/addons/website_event_sale/models/sale_order.py index 066fd98fc8a..91f282a1c00 100644 --- a/addons/website_event_sale/models/sale_order.py +++ b/addons/website_event_sale/models/sale_order.py @@ -1,22 +1,49 @@ # -*- coding: utf-8 -*- -from openerp.osv import osv from openerp import SUPERUSER_ID -from openerp.addons.web.http import request +from openerp.osv import osv, fields +from openerp.tools.translate import _ +# defined for access rules +class sale_order(osv.Model): + _inherit = "sale.order" -class sale_order_line(osv.osv): - _inherit = "sale.order.line" + def _cart_find_product_line(self, cr, uid, ids, product_id=None, line_id=None, context=None): + for so in self.browse(cr, uid, ids, context=context): + order_line_id = None + domain = [('order_id', '=', so.id), ('product_id', '=', product_id)] + if line_id: + domain += [('id', '=', line_id)] + elif context.get("event_ticket_id"): + domain += [('event_ticket_id', '=', context.get("event_ticket_id"))] + order_line_ids = self.pool.get('sale.order.line').search(cr, SUPERUSER_ID, domain, context=context) + if order_line_ids: + order_line_id = order_line_ids[0] + return order_line_id - def _recalculate_product_values(self, cr, uid, ids, product_id=0, fiscal_position=False, context=None): - if not ids: - return super(sale_order_line, self)._recalculate_product_values(cr, uid, ids, product_id, fiscal_position=fiscal_position, context=context) + def _website_product_id_change(self, cr, uid, ids, order_id, product_id, line_id=None, context=None): + values = super(sale_order,self)._website_product_id_change(cr, uid, ids, order_id, product_id, line_id=None, context=None) - order_line = self.browse(cr, SUPERUSER_ID, ids[0], context=context) - assert order_line.order_id.website_session_id == request.session['website_session_id'] + event_ticket_id = None + if context.get("event_ticket_id"): + event_ticket_id = context.get("event_ticket_id") + elif line_id: + line = self.pool.get('sale.order.line').browse(cr, SUPERUSER_ID, line_id, context=context) + if line.event_ticket_id: + event_ticket_id = line.event_ticket_id.id + else: + product = self.pool.get('product.product').browse(cr, uid, product_id, context=context) + if product.event_ticket_ids: + event_ticket_id = product.event_ticket_ids[0] - product = product_id and self.pool.get('product.product').browse(cr, uid, product_id, context=context) or order_line.product_id - res = super(sale_order_line, self)._recalculate_product_values(cr, uid, ids, product.id, fiscal_position=fiscal_position, context=context) - if product.event_type_id and order_line.event_ticket_id and order_line.event_ticket_id.price != product.lst_price: - res.update({'price_unit': order_line.event_ticket_id.price}) + if event_ticket_id: + ticket = self.pool.get('event.event.ticket').browse(cr, uid, event_ticket_id, context=context) + if product_id != ticket.product_id.id: + raise osv.except_osv(_('Error!'),_("The ticket doesn't match with this product.")) - return res + values['product_id'] = ticket.product_id.id + values['event_id'] = ticket.event_id.id + values['event_ticket_id'] = ticket.id + values['price_unit'] = ticket.price + values['name'] = "%s: %s" % (ticket.event_id.name, ticket.name) + + return values diff --git a/addons/website_event_sale/models/website.py b/addons/website_event_sale/models/website.py index e41a7092404..83c653a3999 100644 --- a/addons/website_event_sale/models/website.py +++ b/addons/website_event_sale/models/website.py @@ -5,6 +5,6 @@ from openerp.osv import orm class Website(orm.Model): _inherit = 'website' - def ecommerce_get_product_domain(self): + def sale_product_domain(self, cr, uid, ids, context=None): # remove product event from the website content grid and list view (not removed in detail view) - return ['&'] + super(Website, self).ecommerce_get_product_domain() + [('event_ok', '=', False)] + return ['&'] + super(Website, self).sale_product_domain(cr, uid, ids, context=context) + [('event_ok', '=', False)] diff --git a/addons/website_event_sale/views/website_event_sale.xml b/addons/website_event_sale/views/website_event_sale.xml index f8f3436f17e..b2f5d2a78f5 100644 --- a/addons/website_event_sale/views/website_event_sale.xml +++ b/addons/website_event_sale/views/website_event_sale.xml @@ -20,7 +20,7 @@ -