2018-01-16 06:58:15 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
2018-01-16 11:34:37 +01:00
|
|
|
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
2018-01-16 06:58:15 +01:00
|
|
|
|
|
|
|
import base64
|
|
|
|
|
2018-01-16 11:34:37 +01:00
|
|
|
from flectra import http, _
|
|
|
|
from flectra.exceptions import AccessError
|
|
|
|
from flectra.http import request
|
|
|
|
from flectra.tools import consteq
|
|
|
|
from flectra.addons.portal.controllers.mail import _message_post_helper
|
|
|
|
from flectra.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager, get_records_pager
|
2018-01-16 06:58:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
class CustomerPortal(CustomerPortal):
|
|
|
|
|
|
|
|
def _prepare_portal_layout_values(self):
|
|
|
|
values = super(CustomerPortal, self)._prepare_portal_layout_values()
|
|
|
|
partner = request.env.user.partner_id
|
|
|
|
|
|
|
|
SaleOrder = request.env['sale.order']
|
|
|
|
quotation_count = SaleOrder.search_count([
|
|
|
|
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
|
|
|
|
('state', 'in', ['sent', 'cancel'])
|
|
|
|
])
|
|
|
|
order_count = SaleOrder.search_count([
|
|
|
|
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
|
|
|
|
('state', 'in', ['sale', 'done'])
|
|
|
|
])
|
|
|
|
|
|
|
|
values.update({
|
|
|
|
'quotation_count': quotation_count,
|
|
|
|
'order_count': order_count,
|
|
|
|
})
|
|
|
|
return values
|
|
|
|
|
|
|
|
#
|
|
|
|
# Quotations and Sales Orders
|
|
|
|
#
|
|
|
|
|
|
|
|
def _order_check_access(self, order_id, access_token=None):
|
|
|
|
order = request.env['sale.order'].browse([order_id])
|
|
|
|
order_sudo = order.sudo()
|
|
|
|
try:
|
|
|
|
order.check_access_rights('read')
|
|
|
|
order.check_access_rule('read')
|
|
|
|
except AccessError:
|
|
|
|
if not access_token or not consteq(order_sudo.access_token, access_token):
|
|
|
|
raise
|
|
|
|
return order_sudo
|
|
|
|
|
|
|
|
def _order_get_page_view_values(self, order, access_token, **kwargs):
|
|
|
|
order_invoice_lines = {il.product_id.id: il.invoice_id for il in order.invoice_ids.mapped('invoice_line_ids')}
|
|
|
|
values = {
|
|
|
|
'order': order,
|
|
|
|
'order_invoice_lines': order_invoice_lines,
|
|
|
|
}
|
|
|
|
if access_token:
|
|
|
|
values['no_breadcrumbs'] = True
|
|
|
|
values['access_token'] = access_token
|
2018-04-05 10:25:40 +02:00
|
|
|
values['portal_confirmation'] = order.get_portal_confirmation_action()
|
2018-01-16 06:58:15 +01:00
|
|
|
|
|
|
|
if kwargs.get('error'):
|
|
|
|
values['error'] = kwargs['error']
|
|
|
|
if kwargs.get('warning'):
|
|
|
|
values['warning'] = kwargs['warning']
|
|
|
|
if kwargs.get('success'):
|
|
|
|
values['success'] = kwargs['success']
|
|
|
|
|
|
|
|
history = request.session.get('my_orders_history', [])
|
|
|
|
values.update(get_records_pager(history, order))
|
|
|
|
|
|
|
|
return values
|
|
|
|
|
|
|
|
@http.route(['/my/quotes', '/my/quotes/page/<int:page>'], type='http', auth="user", website=True)
|
|
|
|
def portal_my_quotes(self, page=1, date_begin=None, date_end=None, sortby=None, **kw):
|
|
|
|
values = self._prepare_portal_layout_values()
|
|
|
|
partner = request.env.user.partner_id
|
|
|
|
SaleOrder = request.env['sale.order']
|
|
|
|
|
|
|
|
domain = [
|
|
|
|
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
|
|
|
|
('state', 'in', ['sent', 'cancel'])
|
|
|
|
]
|
|
|
|
|
|
|
|
searchbar_sortings = {
|
|
|
|
'date': {'label': _('Order Date'), 'order': 'date_order desc'},
|
|
|
|
'name': {'label': _('Reference'), 'order': 'name'},
|
|
|
|
'stage': {'label': _('Stage'), 'order': 'state'},
|
|
|
|
}
|
|
|
|
|
|
|
|
# default sortby order
|
|
|
|
if not sortby:
|
|
|
|
sortby = 'date'
|
|
|
|
sort_order = searchbar_sortings[sortby]['order']
|
|
|
|
|
|
|
|
archive_groups = self._get_archive_groups('sale.order', domain)
|
|
|
|
if date_begin and date_end:
|
|
|
|
domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]
|
|
|
|
|
|
|
|
# count for pager
|
|
|
|
quotation_count = SaleOrder.search_count(domain)
|
|
|
|
# make pager
|
|
|
|
pager = portal_pager(
|
|
|
|
url="/my/quotes",
|
|
|
|
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby},
|
|
|
|
total=quotation_count,
|
|
|
|
page=page,
|
|
|
|
step=self._items_per_page
|
|
|
|
)
|
|
|
|
# search the count to display, according to the pager data
|
|
|
|
quotations = SaleOrder.search(domain, order=sort_order, limit=self._items_per_page, offset=pager['offset'])
|
|
|
|
request.session['my_quotes_history'] = quotations.ids[:100]
|
|
|
|
|
|
|
|
values.update({
|
|
|
|
'date': date_begin,
|
|
|
|
'quotations': quotations.sudo(),
|
|
|
|
'page_name': 'quote',
|
|
|
|
'pager': pager,
|
|
|
|
'archive_groups': archive_groups,
|
|
|
|
'default_url': '/my/quotes',
|
|
|
|
'searchbar_sortings': searchbar_sortings,
|
|
|
|
'sortby': sortby,
|
|
|
|
})
|
|
|
|
return request.render("sale.portal_my_quotations", values)
|
|
|
|
|
|
|
|
@http.route(['/my/orders', '/my/orders/page/<int:page>'], type='http', auth="user", website=True)
|
|
|
|
def portal_my_orders(self, page=1, date_begin=None, date_end=None, sortby=None, **kw):
|
|
|
|
values = self._prepare_portal_layout_values()
|
|
|
|
partner = request.env.user.partner_id
|
|
|
|
SaleOrder = request.env['sale.order']
|
|
|
|
|
|
|
|
domain = [
|
|
|
|
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
|
|
|
|
('state', 'in', ['sale', 'done'])
|
|
|
|
]
|
|
|
|
|
|
|
|
searchbar_sortings = {
|
|
|
|
'date': {'label': _('Order Date'), 'order': 'date_order desc'},
|
|
|
|
'name': {'label': _('Reference'), 'order': 'name'},
|
|
|
|
'stage': {'label': _('Stage'), 'order': 'state'},
|
|
|
|
}
|
|
|
|
# default sortby order
|
|
|
|
if not sortby:
|
|
|
|
sortby = 'date'
|
|
|
|
sort_order = searchbar_sortings[sortby]['order']
|
|
|
|
|
|
|
|
archive_groups = self._get_archive_groups('sale.order', domain)
|
|
|
|
if date_begin and date_end:
|
|
|
|
domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]
|
|
|
|
|
|
|
|
# count for pager
|
|
|
|
order_count = SaleOrder.search_count(domain)
|
|
|
|
# pager
|
|
|
|
pager = portal_pager(
|
|
|
|
url="/my/orders",
|
|
|
|
url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby},
|
|
|
|
total=order_count,
|
|
|
|
page=page,
|
|
|
|
step=self._items_per_page
|
|
|
|
)
|
|
|
|
# content according to pager and archive selected
|
|
|
|
orders = SaleOrder.search(domain, order=sort_order, limit=self._items_per_page, offset=pager['offset'])
|
|
|
|
request.session['my_orders_history'] = orders.ids[:100]
|
|
|
|
|
|
|
|
values.update({
|
|
|
|
'date': date_begin,
|
|
|
|
'orders': orders.sudo(),
|
|
|
|
'page_name': 'order',
|
|
|
|
'pager': pager,
|
|
|
|
'archive_groups': archive_groups,
|
|
|
|
'default_url': '/my/orders',
|
|
|
|
'searchbar_sortings': searchbar_sortings,
|
|
|
|
'sortby': sortby,
|
|
|
|
})
|
|
|
|
return request.render("sale.portal_my_orders", values)
|
|
|
|
|
|
|
|
@http.route(['/my/orders/<int:order>'], type='http', auth="public", website=True)
|
|
|
|
def portal_order_page(self, order=None, access_token=None, **kw):
|
|
|
|
try:
|
|
|
|
order_sudo = self._order_check_access(order, access_token=access_token)
|
|
|
|
except AccessError:
|
|
|
|
return request.redirect('/my')
|
|
|
|
|
|
|
|
values = self._order_get_page_view_values(order_sudo, access_token, **kw)
|
|
|
|
return request.render("sale.portal_order_page", values)
|
|
|
|
|
|
|
|
@http.route(['/my/orders/pdf/<int:order_id>'], type='http', auth="public", website=True)
|
|
|
|
def portal_order_report(self, order_id, access_token=None, **kw):
|
|
|
|
try:
|
|
|
|
order_sudo = self._order_check_access(order_id, access_token)
|
|
|
|
except AccessError:
|
|
|
|
return request.redirect('/my')
|
|
|
|
|
|
|
|
# print report as sudo, since it require access to taxes, payment term, ... and portal
|
|
|
|
# does not have those access rights.
|
|
|
|
pdf = request.env.ref('sale.action_report_saleorder').sudo().render_qweb_pdf([order_sudo.id])[0]
|
|
|
|
pdfhttpheaders = [
|
|
|
|
('Content-Type', 'application/pdf'),
|
|
|
|
('Content-Length', len(pdf)),
|
|
|
|
]
|
|
|
|
return request.make_response(pdf, headers=pdfhttpheaders)
|
|
|
|
|
|
|
|
def _portal_quote_user_can_accept(self, order_id):
|
|
|
|
return request.env['ir.config_parameter'].sudo().get_param('sale.sale_portal_confirmation_options', default='none') in ('pay', 'sign')
|
|
|
|
|
|
|
|
@http.route(['/my/quotes/accept'], type='json', auth="public", website=True)
|
|
|
|
def portal_quote_accept(self, res_id, access_token=None, partner_name=None, signature=None):
|
|
|
|
if not self._portal_quote_user_can_accept(res_id):
|
|
|
|
return {'error': _('Operation not allowed')}
|
|
|
|
if not signature:
|
|
|
|
return {'error': _('Signature is missing.')}
|
|
|
|
|
|
|
|
try:
|
|
|
|
order_sudo = self._order_check_access(res_id, access_token=access_token)
|
|
|
|
except AccessError:
|
|
|
|
return {'error': _('Invalid order')}
|
|
|
|
if order_sudo.state != 'sent':
|
|
|
|
return {'error': _('Order is not in a state requiring customer validation.')}
|
|
|
|
|
|
|
|
order_sudo.action_confirm()
|
|
|
|
|
|
|
|
_message_post_helper(
|
|
|
|
res_model='sale.order',
|
|
|
|
res_id=order_sudo.id,
|
|
|
|
message=_('Order signed by %s') % (partner_name,),
|
|
|
|
attachments=[('signature.png', base64.b64decode(signature))] if signature else [],
|
|
|
|
**({'token': access_token} if access_token else {}))
|
|
|
|
return {
|
|
|
|
'success': _('Your Order has been confirmed.'),
|
|
|
|
'redirect_url': '/my/orders/%s?%s' % (order_sudo.id, access_token and 'access_token=%s' % order_sudo.access_token or ''),
|
|
|
|
}
|