[IMP] website_{portal,portal_sale,project_issue,quote} : add pager for customer documents
This commit adds controller to list documents of customer, with pager and archive widget to sort documents. Impacted documents are : quotations, sale order, invoices, and issues. Portal breadcrumd is improved too : add the home icon, and keep the query params when using archive widget. Some editable zones were added to templates, allowing people to customize their frontend portal.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="header_footer_custom_payment" inherit_id="website_portal.account" customize_show="True" active="False" name="Payment Methods">
|
||||
<template id="header_footer_custom_payment" inherit_id="website_portal.portal_layout" customize_show="True" active="False" name="Payment Methods">
|
||||
<xpath expr="//div[@class='o_my_details']" position="inside">
|
||||
<h4 class="payment_method_title">Payment Method</h4>
|
||||
<ul class="payment_method_list list-inline">
|
||||
@@ -30,7 +30,7 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb mt8">
|
||||
<li><a href="/my/home">My Account</a></li>
|
||||
<li><a href="/my/home"><i class="fa fa-home"/></a></li>
|
||||
<li>Payment Methods</li>
|
||||
</ol>
|
||||
</div>
|
||||
@@ -78,7 +78,7 @@
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="pay_meth_link" inherit_id="website_portal.account">
|
||||
<template id="pay_meth_link" inherit_id="website_portal.portal_layout">
|
||||
<xpath expr="//div[@class='o_my_details']" position="inside">
|
||||
<a href="/my/payment_method">Manage your payment methods</a>
|
||||
</xpath>
|
||||
|
||||
@@ -4,12 +4,16 @@ from openerp.http import request
|
||||
from openerp import tools
|
||||
from openerp.tools.translate import _
|
||||
|
||||
from odoo.fields import Date
|
||||
|
||||
|
||||
class website_account(http.Controller):
|
||||
@http.route(['/my', '/my/home'], type='http', auth="public", website=True)
|
||||
def account(self):
|
||||
partner = request.env.user.partner_id
|
||||
|
||||
_items_per_page = 10
|
||||
|
||||
def _prepare_portal_layout_values(self):
|
||||
""" prepare the values to render portal layout """
|
||||
partner = request.env.user.partner_id
|
||||
# get customer sales rep
|
||||
if partner.user_id:
|
||||
sales_rep = partner.user_id
|
||||
@@ -20,8 +24,31 @@ class website_account(http.Controller):
|
||||
'company': request.website.company_id,
|
||||
'user': request.env.user
|
||||
}
|
||||
return values
|
||||
|
||||
return request.website.render("website_portal.account", values)
|
||||
def _get_archive_groups(self, model, domain=None, fields=None, groupby="create_date", order="create_date desc"):
|
||||
if not model:
|
||||
return []
|
||||
if domain is None:
|
||||
domain = []
|
||||
if fields is None:
|
||||
fields = ['name', 'create_date']
|
||||
groups = []
|
||||
for group in request.env[model]._read_group_raw(domain, fields=fields, groupby=groupby, orderby=order):
|
||||
dates, label = group[groupby]
|
||||
date_begin, date_end = dates.split('/')
|
||||
groups.append({
|
||||
'date_begin': Date.to_string(Date.from_string(date_begin)),
|
||||
'date_end': Date.to_string(Date.from_string(date_end)),
|
||||
'name': label,
|
||||
'item_count': group[groupby + '_count']
|
||||
})
|
||||
return groups
|
||||
|
||||
@http.route(['/my', '/my/home'], type='http', auth="public", website=True)
|
||||
def account(self):
|
||||
values = self._prepare_portal_layout_values()
|
||||
return request.website.render("website_portal.portal_my_home", values)
|
||||
|
||||
@http.route(['/my/account'], type='http', auth='user', website=True)
|
||||
def details(self, redirect=None, **post):
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
|
||||
odoo.define('website_portal', function(require) {
|
||||
'use strict';
|
||||
require('website.website');
|
||||
|
||||
if(!$('.o_website_portal_details, .o_my_show_more').length) {
|
||||
return $.Deferred().reject("DOM doesn't contain '.o_website_portal_details' or '.o_my_show_more'");
|
||||
if(!$('.o_website_portal_details').length) {
|
||||
return $.Deferred().reject("DOM doesn't contain '.o_website_portal_details'");
|
||||
}
|
||||
|
||||
var state_options = $("select[name='state_id']:enabled option:not(:first)");
|
||||
@@ -15,10 +16,4 @@ odoo.define('website_portal', function(require) {
|
||||
select.parent().toggle(nb>=1);
|
||||
});
|
||||
$('.o_website_portal_details').find("select[name='country_id']").change();
|
||||
|
||||
$('.o_my_show_more').on('click', function(ev) {
|
||||
ev.preventDefault();
|
||||
$(this).parents('table').find(".to_hide").toggleClass('hidden');
|
||||
$(this).find('span').toggleClass('hidden');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,4 +15,8 @@
|
||||
text-align: left;
|
||||
}
|
||||
table-layout: fixed;
|
||||
}
|
||||
}
|
||||
|
||||
.o_my_home_content > .page-header > a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -8,30 +8,76 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="account" name="Account">
|
||||
<template id="portal_archive_groups" name="Portal Archive Groups">
|
||||
<h3 class="page-header">Archives</h3>
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<t t-foreach="archive_groups" t-as="group">
|
||||
<t t-if="group['date_begin'] == date">
|
||||
<li class="active">
|
||||
<a t-att-href="default_url" t-ignore="True"><t t-esc="group['name']"/><span class="pull-right badge" t-esc="group['item_count']"/></a>
|
||||
</li>
|
||||
</t>
|
||||
<t t-if="group['date_begin'] != date">
|
||||
<li>
|
||||
<a t-ignore="True" t-attf-href="#{default_url}?date_begin=#{group['date_begin']}&date_end=#{group['date_end']}"><t t-esc="group['name']"/><span class="pull-right badge" t-esc="group['item_count']"/></a>
|
||||
</li>
|
||||
</t>
|
||||
</t>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<template id="portal_layout" name="Portal Layout">
|
||||
<t t-call="website.layout">
|
||||
<div class="container mt16">
|
||||
<div class="navbar navbar-default">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#oe-help-navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/my/home">
|
||||
My Account
|
||||
</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="oe-help-navbar-collapse">
|
||||
<ul class="nav navbar-nav o_portal_submenu">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wrap">
|
||||
<div class="container mb64">
|
||||
<div class="col-md-8 o_my_documents">
|
||||
<div class="oe_structure"/>
|
||||
</div>
|
||||
<div t-if="sales_rep" class="col-md-3">
|
||||
<t t-call="website_portal.contact" />
|
||||
<div class="oe_structure"/>
|
||||
<div class="col-md-8">
|
||||
<t t-raw="0"/>
|
||||
</div>
|
||||
<div id="o_my_sidebar" class="col-md-3 col-md-offset-1 o_my_sidebar">
|
||||
<div class="o_my_contact" t-if="sales_rep">
|
||||
<t t-call="website_portal.contact"/>
|
||||
</div>
|
||||
<div class="o_my_details">
|
||||
<h3 class="page-header">Your Details <a href="/my/account" class="btn btn-default btn-xs">Change</a></h3>
|
||||
<div t-field="user.partner_id" t-field-options='{"widget": "contact", "fields": ["email", "phone", "address", "name"]}'/>
|
||||
</div>
|
||||
<div class="o_my_archives" t-if="archive_groups">
|
||||
<t t-call="website_portal.portal_archive_groups"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 oe_structure"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="website_portal.custom_panel" inherit_id='website_portal.account' customize_show="True" name="Editable Panel" active="False">
|
||||
<template id="portal_my_home" name="My Portal">
|
||||
<t t-call="website_portal.portal_layout">
|
||||
<div class="o_my_home_content">
|
||||
<div class="oe_structure"></div>
|
||||
</div>
|
||||
<div class="col-md-12 oe_structure"/>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="website_portal.custom_panel" inherit_id='website_portal.portal_layout' customize_show="True" name="Editable Panel" active="False">
|
||||
<xpath expr="//div[@id='o_my_sidebar']" position="inside">
|
||||
<div class="oe_structure">
|
||||
<h3 class="page-header">Custom Panel</h3>
|
||||
@@ -56,7 +102,7 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb mt8">
|
||||
<li><a href="/my/home">My Account</a></li>
|
||||
<li><a href="/my/home"><i class="fa fa-home"/></a></li>
|
||||
<li>Details</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
@@ -9,45 +9,163 @@ from openerp.addons.website_portal.controllers.main import website_account
|
||||
|
||||
|
||||
class website_account(website_account):
|
||||
@http.route(['/my/home'], type='http', auth="user", website=True)
|
||||
def account(self, **kw):
|
||||
|
||||
@http.route()
|
||||
def account(self):
|
||||
""" Add sales documents to main account page """
|
||||
response = super(website_account, self).account()
|
||||
partner = request.env.user.partner_id
|
||||
|
||||
res_sale_order = request.env['sale.order']
|
||||
res_invoices = request.env['account.invoice']
|
||||
quotations = res_sale_order.search([
|
||||
SaleOrder = request.env['sale.order']
|
||||
Invoice = request.env['account.invoice']
|
||||
quotation_count = SaleOrder.search_count([
|
||||
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
|
||||
('state', 'in', ['sent', 'cancel'])
|
||||
])
|
||||
orders = res_sale_order.search([
|
||||
order_count = SaleOrder.search_count([
|
||||
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
|
||||
('state', 'in', ['sale', 'done'])
|
||||
])
|
||||
invoices = res_invoices.search([
|
||||
invoice_count = Invoice.search_count([
|
||||
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
|
||||
('state', 'in', ['open', 'paid', 'cancelled'])
|
||||
])
|
||||
|
||||
response.qcontext.update({
|
||||
'date': datetime.date.today().strftime('%Y-%m-%d'),
|
||||
'quotations': quotations,
|
||||
'orders': orders,
|
||||
'invoices': invoices,
|
||||
'quotation_count': quotation_count,
|
||||
'order_count': order_count,
|
||||
'invoice_count': invoice_count,
|
||||
})
|
||||
return response
|
||||
|
||||
#
|
||||
# Quotations and Sale Orders
|
||||
#
|
||||
|
||||
@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, **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'])
|
||||
]
|
||||
|
||||
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 = request.website.pager(
|
||||
url="/my/quotes",
|
||||
url_args={'date_begin': date_begin, 'date_end': date_end},
|
||||
total=quotation_count,
|
||||
page=page,
|
||||
step=self._items_per_page
|
||||
)
|
||||
# search the count to display, according to the pager data
|
||||
quotations = SaleOrder.search(domain, limit=self._items_per_page, offset=pager['offset'])
|
||||
|
||||
values.update({
|
||||
'date': date_begin,
|
||||
'quotations': quotations,
|
||||
'pager': pager,
|
||||
'archive_groups': archive_groups,
|
||||
'default_url': '/my/quotes',
|
||||
})
|
||||
return request.website.render("website_portal_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, **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'])
|
||||
]
|
||||
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 = request.website.pager(
|
||||
url="/my/orders",
|
||||
url_args={'date_begin': date_begin, 'date_end': date_end},
|
||||
total=order_count,
|
||||
page=page,
|
||||
step=self._items_per_page
|
||||
)
|
||||
# content according to pager and archive selected
|
||||
orders = SaleOrder.search(domain, limit=self._items_per_page, offset=pager['offset'])
|
||||
|
||||
values.update({
|
||||
'date': date_begin,
|
||||
'orders': orders,
|
||||
'page_name': 'order',
|
||||
'pager': pager,
|
||||
'archive_groups': archive_groups,
|
||||
'default_url': '/my/orders',
|
||||
})
|
||||
return request.website.render("website_portal_sale.portal_my_orders", values)
|
||||
|
||||
@http.route(['/my/orders/<int:order>'], type='http', auth="user", website=True)
|
||||
def orders_followup(self, order=None):
|
||||
def orders_followup(self, order=None, **kw):
|
||||
order = request.env['sale.order'].browse([order])
|
||||
try:
|
||||
order.check_access_rights('read')
|
||||
order.check_access_rule('read')
|
||||
except AccessError:
|
||||
return request.website.render("website.403")
|
||||
return request.website.render("website.403")
|
||||
order_invoice_lines = {il.product_id.id: il.invoice_id for il in order.invoice_ids.mapped('invoice_line_ids')}
|
||||
return request.website.render("website_portal_sale.orders_followup", {
|
||||
'order': order.sudo(),
|
||||
'order_invoice_lines': order_invoice_lines,
|
||||
})
|
||||
|
||||
#
|
||||
# Invoices
|
||||
#
|
||||
|
||||
@http.route(['/my/invoices', '/my/invoices/page/<int:page>'], type='http', auth="user", website=True)
|
||||
def portal_my_invoices(self, page=1, date_begin=None, date_end=None, **kw):
|
||||
values = self._prepare_portal_layout_values()
|
||||
partner = request.env.user.partner_id
|
||||
AccountInvoice = request.env['account.invoice']
|
||||
|
||||
domain = [
|
||||
('message_partner_ids', 'child_of', [partner.commercial_partner_id.id]),
|
||||
('state', 'in', ['open', 'paid', 'cancelled'])
|
||||
]
|
||||
archive_groups = self._get_archive_groups('account.invoice', domain)
|
||||
if date_begin and date_end:
|
||||
domain += [('create_date', '>=', date_begin), ('create_date', '<', date_end)]
|
||||
|
||||
# count for pager
|
||||
invoice_count = AccountInvoice.search_count(domain)
|
||||
# pager
|
||||
pager = request.website.pager(
|
||||
url="/my/invoices",
|
||||
url_args={'date_begin': date_begin, 'date_end': date_end},
|
||||
total=invoice_count,
|
||||
page=page,
|
||||
step=self._items_per_page
|
||||
)
|
||||
# content according to pager and archive selected
|
||||
invoices = AccountInvoice.search(domain, limit=self._items_per_page, offset=pager['offset'])
|
||||
values.update({
|
||||
'date': date_begin,
|
||||
'invoices': invoices,
|
||||
'page_name': 'invoice',
|
||||
'pager': pager,
|
||||
'archive_groups': archive_groups,
|
||||
'default_url': '/my/invoices',
|
||||
})
|
||||
return request.website.render("website_portal_sale.portal_my_invoices", values)
|
||||
|
||||
@@ -6,15 +6,63 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="account" name="Account" inherit_id="website_portal.account">
|
||||
<xpath expr="//div[contains(@class,'o_my_documents')]" position="inside">
|
||||
<t t-call="website_portal_sale.quotations" />
|
||||
<t t-call="website_portal_sale.sale_orders" />
|
||||
<t t-call="website_portal_sale.invoices" />
|
||||
<template id="portal_my_home_menu_sale" name="Portal layout : sales menu entries" inherit_id="website_portal.portal_layout" priority="25">
|
||||
<xpath expr="//ul[contains(@class,'o_portal_submenu')]" position="inside">
|
||||
<li>
|
||||
<a href="/my/quotes">Quotes</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/my/orders">Orders</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/my/invoices">Invoices</a>
|
||||
</li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="quotations" name="Quotations">
|
||||
<template id="portal_my_home_sale" name="Portal My Home : sales entries" inherit_id="website_portal.portal_my_home" priority="25">
|
||||
<xpath expr="//div[contains(@class,'o_my_home_content')]" position="inside">
|
||||
<h3 class="page-header">
|
||||
<a href="/my/quotes">Your Quotes
|
||||
<small class="ml8">
|
||||
<t t-if="quotation_count">
|
||||
<span class='badge'><t t-esc="quotation_count"/></span>
|
||||
</t>
|
||||
<t t-if="not quotation_count">
|
||||
There are currently no quotes for your account.
|
||||
</t>
|
||||
</small>
|
||||
</a>
|
||||
</h3>
|
||||
<h3 class="page-header">
|
||||
<a href="/my/orders">Your Orders
|
||||
<small class="ml8">
|
||||
<t t-if="order_count">
|
||||
<span class='badge'><t t-esc="order_count"/></span>
|
||||
</t>
|
||||
<t t-if="not order_count">
|
||||
There are currently no orders for your account.
|
||||
</t>
|
||||
</small>
|
||||
</a>
|
||||
</h3>
|
||||
<h3 class="page-header">
|
||||
<a href="/my/invoices">Your Invoices and Payments
|
||||
<small class="ml8">
|
||||
<t t-if="invoice_count">
|
||||
<span class='badge'><t t-esc="invoice_count"/></span>
|
||||
</t>
|
||||
<t t-if="not invoice_count">
|
||||
There are currently no invoices for your account.
|
||||
</t>
|
||||
</small>
|
||||
</a>
|
||||
</h3>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_quotations" name="My Quotations">
|
||||
<t t-call="website_portal.portal_layout">
|
||||
<h3 class="page-header">Your Quotes</h3>
|
||||
<t t-if="not quotations">
|
||||
<p>There are currently no quotes for your account.</p>
|
||||
@@ -30,9 +78,9 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="quotations" t-as="quotation">
|
||||
<tr t-att-class="'hidden to_hide' if quotation.state!='sent' and quotation_index > 4 else ''">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-att-href="'/my/orders/'+str(quotation.id)"><t t-esc="quotation.name"/></a>
|
||||
<a t-attf-href="/my/orders/#{quotation.id}?#{keep_query()}"><t t-esc="quotation.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="quotation.validity_date"/></td>
|
||||
<td>
|
||||
@@ -47,14 +95,16 @@
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(quotations) < 5 else ''">
|
||||
<td colspan="5"><a href="" class="o_my_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="website.pager"/>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="sale_orders" name="Sales Orders">
|
||||
<template id="portal_my_orders" name="My Sales Orders">
|
||||
<t t-call="website_portal.portal_layout">
|
||||
<h3 class="page-header">Your Orders</h3>
|
||||
<t t-if="not orders">
|
||||
<p>There are currently no orders for your account.</p>
|
||||
@@ -70,9 +120,9 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="orders" t-as="order">
|
||||
<tr t-att-class="'hidden to_hide' if order.state not in ['manual', 'progress'] and order_index > 4 else ''">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-att-href="'/my/orders/'+str(order.id)"><t t-esc="order.name"/></a>
|
||||
<a t-attf-href="/my/orders/{{order.id}}?{{keep_query()}}"><t t-esc="order.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="order.date_order"/></td>
|
||||
<td>
|
||||
@@ -89,14 +139,16 @@
|
||||
<td><span t-field="order.amount_total" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(orders) < 5 else ''">
|
||||
<td colspan="4"><a href="" class="o_my_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="website.pager"/>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="invoices" name="Invoices and Payments">
|
||||
<template id="portal_my_invoices" name="My Invoices and Payments">
|
||||
<t t-call="website_portal.portal_layout">
|
||||
<h3 class="page-header">Your Invoices and Payments</h3>
|
||||
<t t-if="not invoices">
|
||||
<p>There are currently no invoices for your account.</p>
|
||||
@@ -114,7 +166,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="invoices" t-as="invoice">
|
||||
<tr t-att-class="'hidden to_hide' if invoice.state!='open' and invoice_index > 4 else ''">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-att-href="'/report/pdf/account.report_invoice/'+str(invoice.id)"><t t-esc="invoice.number"/></a>
|
||||
</td>
|
||||
@@ -137,11 +189,12 @@
|
||||
<td><span t-field="invoice.residual" t-field-options='{"widget": "monetary", "display_currency": "invoice.currency_id"}'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(invoices) < 5 else ''">
|
||||
<td colspan="5"><a href="" class="o_my_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="website.pager"/>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="orders_followup" name="Sales Order">
|
||||
@@ -152,7 +205,17 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<ol class="breadcrumb mt8">
|
||||
<li><a href="/my/home">My Account</a></li>
|
||||
<li><a href="/my/home"><i class="fa fa-home"/></a></li>
|
||||
<li>
|
||||
<a t-attf-href="/my/#{'quotes' if order.state == 'sent' else 'orders'}?{{ keep_query()}}">
|
||||
<t t-if="order.state == 'sent'">
|
||||
My Quotes
|
||||
</t>
|
||||
<t t-if="order.state != 'sent'">
|
||||
My Orders
|
||||
</t>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<t t-if="order.state == 'sent'">
|
||||
Quotation
|
||||
@@ -318,7 +381,7 @@
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="sale_backend_link" inherit_id='website_portal_sale.sale_orders' customize_show="True" name="Link to Sales Backend" active="False">
|
||||
<template id="sale_backend_link" inherit_id='website_portal_sale.portal_my_orders' customize_show="True" name="Link to Sales Backend" active="False">
|
||||
<xpath expr="//h3[@class='page-header']" position="inside">
|
||||
<a href="/web#action=portal_sale.action_orders_portal" target="_blank" class="btn btn-default btn-xs pull-right"> Access the complete Sale application</a>
|
||||
</xpath>
|
||||
|
||||
@@ -6,17 +6,46 @@ from openerp.http import request
|
||||
|
||||
|
||||
class WebsiteAccount(website_account):
|
||||
@http.route(['/my', '/my/home'], type='http', auth="user", website=True)
|
||||
|
||||
@http.route()
|
||||
def account(self):
|
||||
response = super(WebsiteAccount, self).account()
|
||||
user = request.env.user
|
||||
project_issues = request.env['project.issue'].search([])
|
||||
response.qcontext.update({'issues': project_issues})
|
||||
issue_count = request.env['project.issue'].search_count([])
|
||||
response.qcontext.update({'issue_count': issue_count})
|
||||
return response
|
||||
|
||||
@http.route(['/my/issues', '/my/issues/page/<int:page>'], type='http', auth="user", website=True)
|
||||
def portal_my_issues(self, page=1, date_begin=None, date_end=None, **kw):
|
||||
values = self._prepare_portal_layout_values()
|
||||
ProjectIssue = request.env['project.issue']
|
||||
domain = []
|
||||
# archive groups - Default Group By 'create_date'
|
||||
archive_groups = self._get_archive_groups('project.issue', domain)
|
||||
if date_begin and date_end:
|
||||
domain += [('create_date', '>=', date_begin), ('create_date', '<', date_end)]
|
||||
# pager
|
||||
issue_count = ProjectIssue.search_count(domain)
|
||||
pager = request.website.pager(
|
||||
url="/my/issues",
|
||||
url_args={'date_begin': date_begin, 'date_end': date_end},
|
||||
total=issue_count,
|
||||
page=page,
|
||||
step=self._items_per_page
|
||||
)
|
||||
# content according to pager and archive selected
|
||||
project_issues = ProjectIssue.search(domain, order="stage_id", limit=self._items_per_page, offset=pager['offset'])
|
||||
|
||||
values.update({
|
||||
'date': date_begin,
|
||||
'issues': project_issues,
|
||||
'page_name': 'issue',
|
||||
'archive_groups': archive_groups,
|
||||
'default_url': '/my/issues',
|
||||
'pager': pager
|
||||
})
|
||||
return request.website.render("website_project_issue.portal_my_issues", values)
|
||||
|
||||
class WebsiteProjectIssue(http.Controller):
|
||||
@http.route(['/my/issues/<int:issue_id>'], type='http', auth="user", website=True)
|
||||
def issues_followup(self, issue_id=None):
|
||||
def issues_followup(self, issue_id=None, **kw):
|
||||
issue = request.env['project.issue'].browse(issue_id)
|
||||
return request.website.render("website_project_issue.issues_followup", {'issue': issue})
|
||||
|
||||
@@ -1,7 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="portal_project_issue" name="Portal Project Issues" inherit_id="website_portal.account">
|
||||
<xpath expr="//div[contains(@class,'o_my_documents')]/*[last()]" position="after">
|
||||
|
||||
<template id="portal_my_home_menu_issue" name="Portal layout : issues menu entry" inherit_id="website_portal.portal_layout" priority="30">
|
||||
<xpath expr="//ul[contains(@class,'o_portal_submenu')]" position="inside">
|
||||
<li t-att-class="page_name == 'issue' and 'active' or ''">
|
||||
<a href="/my/issues">Issues</a>
|
||||
</li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_home_issue" name="Portal My Home : issue entries" inherit_id="website_portal.portal_my_home" priority="30">
|
||||
<xpath expr="//div[contains(@class,'o_my_home_content')]" position="inside">
|
||||
<h3 class="page-header">
|
||||
<a href="/my/issues">Your Issues
|
||||
<small class="ml8">
|
||||
<t t-if="issue_count">
|
||||
<span class='badge'><t t-esc="issue_count"/></span>
|
||||
</t>
|
||||
<t t-if="not issue_count">
|
||||
There are currently no issues for your account.
|
||||
</t>
|
||||
</small>
|
||||
</a>
|
||||
</h3>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_issues" name="My Issues" priority="30">
|
||||
<t t-call="website_portal.portal_layout">
|
||||
<h3 class="page-header">Your Issues</h3>
|
||||
<t t-if="not issues">
|
||||
<p>There are currently no issues for your account.</p>
|
||||
@@ -16,20 +42,21 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="issues" t-as="issue">
|
||||
<tr t-att-class="'hidden to_hide' if issue_index > 4 else ''">
|
||||
<td><a t-attf-href="/my/issues/#{issue.id}">Issue <t t-esc="issue.id"/></a></td>
|
||||
<tr>
|
||||
|
||||
<td>
|
||||
<a t-attf-href="/my/issues/#{issue.id}?{{ keep_query() }}">Issue <t t-esc="issue.id"/></a>
|
||||
</td>
|
||||
<td><span t-field="issue.name"/></td><td/>
|
||||
<td><span t-field="issue.stage_id.name"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(issues) < 6 else ''">
|
||||
<td colspan="4">
|
||||
<a href="" class="o_my_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div t-if="pager" class="o_portal_pager text-center">
|
||||
<t t-call="website.pager"/>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="issues_followup" name="Project Issues">
|
||||
@@ -40,7 +67,8 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<ol class="breadcrumb mt8">
|
||||
<li><a href="/my/home">My Account</a></li>
|
||||
<li><a href="/my/home"><i class="fa fa-home"/></a></li>
|
||||
<li><a t-attf-href="/my/issues?#{keep_query()}">My Issues</a></li>
|
||||
<li>Issue <span t-field="issue.id"/></li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
@@ -162,7 +162,8 @@
|
||||
<div t-if="breadcrumb" class="row">
|
||||
<div class="col-sm-4">
|
||||
<ol class="breadcrumb mt8">
|
||||
<li><a href="/my/home">My Account</a></li>
|
||||
<li><a href="/my/home"><i class="fa fa-home"/></a></li>
|
||||
<li><a t-attf-href="/my/quotes?#{keep_query()}">My Quotations</a></li>
|
||||
<li>
|
||||
Quotation <t t-esc="quotation.name"/>
|
||||
</li>
|
||||
@@ -682,12 +683,12 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="quotations" inherit_id="website_portal_sale.quotations">
|
||||
<template id="quotations" inherit_id="website_portal_sale.portal_my_quotations">
|
||||
<xpath expr="//t[@t-foreach='quotations']" position="replace">
|
||||
<t t-foreach="quotations" t-as="quotation">
|
||||
<tr t-att-class="'hidden to_hide' if quotation_index > 4 else ''">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-att-href="'/quote/'+str(quotation.id)"><t t-esc="quotation.name"/></a>
|
||||
<a t-attf-href="/quote/#{quotation.id}?#{keep_query()}"><t t-esc="quotation.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="quotation.validity_date"/></td>
|
||||
<td>
|
||||
|
||||
Reference in New Issue
Block a user