From 9381334f6ea94f9439d2492c95a034c996bc5547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 8 Jun 2017 10:32:58 +0200 Subject: [PATCH] [MOV] sale_*: move sale customer portal to sale Customer portal is now a feature coming directly with sale module. As it uses a simple website renderer customization and advanced website features are not available and depends on having website module installed. --- addons/sale/__init__.py | 1 + addons/sale/__manifest__.py | 3 +- .../controllers/__init__.py | 2 +- .../controllers/mail.py | 0 .../main.py => sale/controllers/portal.py} | 20 +++-- addons/sale/data/sale_demo.xml | 73 ++++++++++++++++++ addons/sale/models/sale.py | 60 ++++++++++++++- addons/sale/security/ir.model.access.csv | 2 + addons/sale/security/sale_security.xml | 19 +++++ .../static/src/less/sale_portal.less} | 0 .../views/sale_portal_templates.xml} | 9 +-- addons/website_portal_sale/__init__.py | 3 - addons/website_portal_sale/__manifest__.py | 4 - addons/website_portal_sale/data/sale_demo.xml | 76 ------------------- addons/website_portal_sale/models/__init__.py | 4 - .../website_portal_sale/models/sale_order.py | 74 ------------------ .../security/ir.model.access.csv | 3 - .../security/sale_order_security.xml | 23 ------ .../views/website_quote_templates.xml | 2 +- addons/website_sale/views/templates.xml | 2 +- .../website_sale_digital/controllers/main.py | 5 +- .../views/website_sale_digital.xml | 2 +- .../views/website_sale_stock_templates.xml | 2 +- 23 files changed, 177 insertions(+), 212 deletions(-) rename addons/{website_portal_sale => sale}/controllers/__init__.py (85%) rename addons/{website_portal_sale => sale}/controllers/mail.py (100%) rename addons/{website_portal_sale/controllers/main.py => sale/controllers/portal.py} (90%) rename addons/{website_portal_sale/static/src/less/website_portal_sale.less => sale/static/src/less/sale_portal.less} (100%) rename addons/{website_portal_sale/views/website_portal_sale_templates.xml => sale/views/sale_portal_templates.xml} (97%) delete mode 100644 addons/website_portal_sale/data/sale_demo.xml delete mode 100644 addons/website_portal_sale/models/__init__.py delete mode 100644 addons/website_portal_sale/models/sale_order.py delete mode 100644 addons/website_portal_sale/security/ir.model.access.csv delete mode 100644 addons/website_portal_sale/security/sale_order_security.xml diff --git a/addons/sale/__init__.py b/addons/sale/__init__.py index 42f44d32a03..59347877995 100644 --- a/addons/sale/__init__.py +++ b/addons/sale/__init__.py @@ -2,6 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import models +from . import controllers from . import report from . import wizard diff --git a/addons/sale/__manifest__.py b/addons/sale/__manifest__.py index 14574566fc8..4c9a443cc10 100644 --- a/addons/sale/__manifest__.py +++ b/addons/sale/__manifest__.py @@ -9,7 +9,7 @@ 'description': """ This module contains all the common features of Sales Management and eCommerce. """, - 'depends': ['sales_team', 'account', 'procurement'], + 'depends': ['sales_team', 'account', 'procurement', 'portal'], 'data': [ 'data/ir_sequence_data.xml', 'data/sale_data.xml', @@ -26,6 +26,7 @@ This module contains all the common features of Sales Management and eCommerce. 'views/sales_team_views.xml', 'views/res_partner_views.xml', 'views/sale_templates.xml', + 'views/sale_portal_templates.xml', 'views/sale_layout_category_view.xml', 'views/sale_config_settings_views.xml', ], diff --git a/addons/website_portal_sale/controllers/__init__.py b/addons/sale/controllers/__init__.py similarity index 85% rename from addons/website_portal_sale/controllers/__init__.py rename to addons/sale/controllers/__init__.py index ef077859bb9..e5a6112c48f 100644 --- a/addons/website_portal_sale/controllers/__init__.py +++ b/addons/sale/controllers/__init__.py @@ -2,4 +2,4 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from . import mail -from . import main +from . import portal diff --git a/addons/website_portal_sale/controllers/mail.py b/addons/sale/controllers/mail.py similarity index 100% rename from addons/website_portal_sale/controllers/mail.py rename to addons/sale/controllers/mail.py diff --git a/addons/website_portal_sale/controllers/main.py b/addons/sale/controllers/portal.py similarity index 90% rename from addons/website_portal_sale/controllers/main.py rename to addons/sale/controllers/portal.py index 2da2aa1ba06..eb8059568fa 100644 --- a/addons/website_portal_sale/controllers/main.py +++ b/addons/sale/controllers/portal.py @@ -6,14 +6,13 @@ from odoo.exceptions import AccessError from odoo.http import request from odoo.tools import consteq -from odoo.addons.portal.controllers.portal import get_records_pager -from odoo.addons.website_portal.controllers.main import website_account +from odoo.addons.portal.controllers.portal import CustomerPortal, get_records_pager -class website_account(website_account): +class CustomerPortal(CustomerPortal): def _prepare_portal_layout_values(self): - values = super(website_account, self)._prepare_portal_layout_values() + values = super(CustomerPortal, self)._prepare_portal_layout_values() partner = request.env.user.partner_id SaleOrder = request.env['sale.order'] @@ -64,7 +63,7 @@ class website_account(website_account): # count for pager quotation_count = SaleOrder.search_count(domain) # make pager - pager = request.website.pager( + pager = request.pager( url="/my/quotes", url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby}, total=quotation_count, @@ -85,7 +84,7 @@ class website_account(website_account): 'searchbar_sortings': searchbar_sortings, 'sortby': sortby, }) - return request.render("website_portal_sale.portal_my_quotations", values) + return request.render("sale.portal_my_quotations", values) @http.route(['/my/orders', '/my/orders/page/'], type='http', auth="user", website=True) def portal_my_orders(self, page=1, date_begin=None, date_end=None, sortby=None, **kw): @@ -114,7 +113,7 @@ class website_account(website_account): # count for pager order_count = SaleOrder.search_count(domain) # pager - pager = request.website.pager( + pager = request.pager( url="/my/orders", url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby}, total=order_count, @@ -135,7 +134,7 @@ class website_account(website_account): 'searchbar_sortings': searchbar_sortings, 'sortby': sortby, }) - return request.render("website_portal_sale.portal_my_orders", values) + return request.render("sale.portal_my_orders", values) @http.route(['/my/orders/'], type='http', auth="public", website=True) def orders_followup(self, order=None, access_token=None, **kw): @@ -147,7 +146,7 @@ class website_account(website_account): order.check_access_rule('read') except AccessError: if not access_token or not consteq(order_sudo.access_token, access_token): - return request.render("website.403") + return request.redirect('/my') values.update({'no_breadcrumbs': True}) order_invoice_lines = {il.product_id.id: il.invoice_id for il in order_sudo.invoice_ids.mapped('invoice_line_ids')} @@ -158,5 +157,4 @@ class website_account(website_account): 'order_invoice_lines': order_invoice_lines, }) values.update(get_records_pager(history, order_sudo)) - return request.render("website_portal_sale.orders_followup", values) - + return request.render("sale.orders_followup", values) diff --git a/addons/sale/data/sale_demo.xml b/addons/sale/data/sale_demo.xml index e68b4e03664..50ea6a0c2db 100644 --- a/addons/sale/data/sale_demo.xml +++ b/addons/sale/data/sale_demo.xml @@ -613,5 +613,78 @@ Thanks! + + + + + + + + + sent + + + + + + + + Laptop E5023 + + 3 + + 2950.00 + + + + + Pen drive, 16GB + + 5 + + 145.00 + + + + + Headset USB + + 2 + + 65.00 + + + + + + + + + + + + + + + + Service on demand + + 24 + + 75.00 + + + + + On Site Assistance + + 30 + + 38.25 + + + + + diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index 5299868d2ca..e94144da796 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -5,9 +5,10 @@ import uuid from itertools import groupby from datetime import datetime, timedelta +from werkzeug.urls import url_encode from odoo import api, fields, models, _ -from odoo.exceptions import UserError +from odoo.exceptions import UserError, AccessError from odoo.tools import float_is_zero, float_compare, DEFAULT_SERVER_DATETIME_FORMAT, pycompat from odoo.tools.misc import formatLang @@ -118,6 +119,9 @@ class SaleOrder(models.Model): access_token = fields.Char( 'Security Token', copy=False, default=_get_default_access_token) + website_url = fields.Char( + 'Website URL', compute='_website_url', + help='The full URL to access the document using the customer portal.') state = fields.Selection([ ('draft', 'Quotation'), @@ -166,6 +170,10 @@ class SaleOrder(models.Model): product_id = fields.Many2one('product.product', related='order_line.product_id', string='Product') + def _website_url(self): + for so in self: + so.website_url = '/my/orders/%s' % (so.id) + @api.model def _get_customer_lead(self, product_tmpl_id): return False @@ -560,6 +568,54 @@ class SaleOrder(models.Model): res = [(l[0].name, l[1]) for l in res] return res + @api.multi + def get_access_action(self, access_uid=None): + """ Instead of the classic form view, redirect to the online order for + portal users or if force_website=True in the context. """ + # TDE note: read access on sales order to portal users granted to followed sales orders + self.ensure_one() + if self.state == 'cancel' or (self.state == 'draft' and not self.env.context.get('mark_so_as_sent')): + return super(SaleOrder, self).get_access_action(access_uid) + + user = self.env['res.users'].sudo().browse(access_uid) if access_uid else self.env.user + if user.share or self.env.context.get('force_website'): + return { + 'type': 'ir.actions.act_url', + 'url': '/my/orders/%s?access_token=%s' % (self.id, self.access_token), + 'target': 'self', + 'res_id': self.id, + } + return super(SaleOrder, self).get_access_action(access_uid) + + def get_mail_url(self): + self.ensure_one() + params = { + 'model': self._name, + 'res_id': self.id, + 'access_token': self.access_token, + } + params.update(self.partner_id.signup_get_auth_param()[self.partner_id.id]) + return '/mail/view?' + url_encode(params) + + @api.multi + def _notification_recipients(self, message, groups): + groups = super(SaleOrder, self)._notification_recipients(message, groups) + + self.ensure_one() + if self.state not in ('draft', 'cancel'): + for group_name, group_method, group_data in groups: + group_data['has_button_access'] = True + + return groups + + @api.multi + def get_signup_url(self): + self.ensure_one() + return self.partner_id.with_context(signup_valid=True)._get_signup_url_for_action( + action='/mail/view', + model=self._name, + res_id=self.id)[self.partner_id.id] + class SaleOrderLine(models.Model): _name = 'sale.order.line' @@ -804,6 +860,8 @@ class SaleOrderLine(models.Model): product_id = fields.Many2one('product.product', string='Product', domain=[('sale_ok', '=', True)], change_default=True, ondelete='restrict', required=True) product_uom_qty = fields.Float(string='Quantity', digits=dp.get_precision('Product Unit of Measure'), required=True, default=1.0) product_uom = fields.Many2one('product.uom', string='Unit of Measure', required=True) + # Non-stored related field to allow portal user to see the image of the product he has ordered + product_image = fields.Binary('Product Image', related="product_id.image", store=False) qty_delivered_updateable = fields.Boolean(compute='_compute_qty_delivered_updateable', string='Can Edit Delivered', readonly=True, default=True) qty_delivered = fields.Float(string='Delivered', copy=False, digits=dp.get_precision('Product Unit of Measure'), default=0.0) diff --git a/addons/sale/security/ir.model.access.csv b/addons/sale/security/ir.model.access.csv index 8795e4f2a04..1606b63c73d 100644 --- a/addons/sale/security/ir.model.access.csv +++ b/addons/sale/security/ir.model.access.csv @@ -2,6 +2,8 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_sale_order,sale.order,model_sale_order,sales_team.group_sale_salesman,1,1,1,0 access_sale_order_line,sale.order.line,model_sale_order_line,sales_team.group_sale_salesman,1,1,1,1 access_sale_order_line_accountant,sale.order.line accountant,model_sale_order_line,account.group_account_user,1,1,0,0 +access_sale_order_portal,sale.order.portal,sale.model_sale_order,base.group_portal,1,0,0,0 +access_sale_order_line_portal,sale.order.line.portal,sale.model_sale_order_line,base.group_portal,1,0,0,0 access_account_invoice_tax_salesman,account_invoice_tax salesman,account.model_account_invoice_tax,sales_team.group_sale_salesman,1,1,1,0 access_account_invoice_salesman,account_invoice salesman,account.model_account_invoice,sales_team.group_sale_salesman,1,1,1,0 access_account_invoice_manager,account_invoice manager,account.model_account_invoice,sales_team.group_sale_manager,1,1,1,1 diff --git a/addons/sale/security/sale_security.xml b/addons/sale/security/sale_security.xml index 0a269ab44bf..0e62a89152d 100644 --- a/addons/sale/security/sale_security.xml +++ b/addons/sale/security/sale_security.xml @@ -90,6 +90,25 @@ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + Portal Personal Quotations/Sales Orders + + [('message_partner_ids','child_of',[user.commercial_partner_id.id])] + + + + + + + + + Portal Sales Orders Line + + [('order_id.message_partner_ids','child_of',[user.commercial_partner_id.id])] + + + diff --git a/addons/website_portal_sale/static/src/less/website_portal_sale.less b/addons/sale/static/src/less/sale_portal.less similarity index 100% rename from addons/website_portal_sale/static/src/less/website_portal_sale.less rename to addons/sale/static/src/less/sale_portal.less diff --git a/addons/website_portal_sale/views/website_portal_sale_templates.xml b/addons/sale/views/sale_portal_templates.xml similarity index 97% rename from addons/website_portal_sale/views/website_portal_sale_templates.xml rename to addons/sale/views/sale_portal_templates.xml index 1374d1a506d..68d677728ab 100644 --- a/addons/website_portal_sale/views/website_portal_sale_templates.xml +++ b/addons/sale/views/sale_portal_templates.xml @@ -1,8 +1,8 @@ - -