[IMP] sale_timesheet: adapt timesheet sections in portal

Prior to this commit:

    * The portal timesheet section was only visible in invoices when
      invoicing policy was set to delivery.
    * The portal timesheet section was not visible on orders.

After this commit:

    * The portal timesheet section will be displayed for both delivery and order invoicing
      policies.
    * The portal timesheet section will be available for orders.

task-2388500

closes odoo/odoo#62516

Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
Laurent Stukkens (LTU)
2020-11-25 18:13:11 +00:00
parent 788930d7d2
commit 009bcc59fe
4 changed files with 124 additions and 32 deletions
+35 -30
View File
@@ -33,6 +33,39 @@ class CustomerPortal(portal.CustomerPortal):
return values
def _order_get_page_view_values(self, order, access_token, **kwargs):
values = {
'sale_order': order,
'token': access_token,
'return_url': '/shop/payment/validate',
'bootstrap_formatting': True,
'partner_id': order.partner_id.id,
'report_type': 'html',
'action': order._get_portal_return_action(),
}
if order.company_id:
values['res_company'] = order.company_id
if order.has_to_be_paid():
domain = expression.AND([
['&', ('state', 'in', ['enabled', 'test']), ('company_id', '=', order.company_id.id)],
['|', ('country_ids', '=', False), ('country_ids', 'in', [order.partner_id.country_id.id])]
])
acquirers = request.env['payment.acquirer'].sudo().search(domain)
values['acquirers'] = acquirers.filtered(lambda acq: (acq.payment_flow == 'form' and acq.view_template_id) or
(acq.payment_flow == 's2s' and acq.registration_view_template_id))
values['pms'] = request.env['payment.token'].search([('partner_id', '=', order.partner_id.id)])
values['acq_extra_fees'] = acquirers.get_acquirer_extra_fees(order.amount_total, order.currency_id, order.partner_id.country_id.id)
if order.state in ('draft', 'sent', 'cancel'):
history = request.session.get('my_quotations_history', [])
else:
history = request.session.get('my_orders_history', [])
values.update(get_records_pager(history, order))
return values
#
# Quotations and Sales Orders
#
@@ -166,36 +199,8 @@ class CustomerPortal(portal.CustomerPortal):
partner_ids=order_sudo.user_id.sudo().partner_id.ids,
)
values = {
'sale_order': order_sudo,
'message': message,
'token': access_token,
'return_url': '/shop/payment/validate',
'bootstrap_formatting': True,
'partner_id': order_sudo.partner_id.id,
'report_type': 'html',
'action': order_sudo._get_portal_return_action(),
}
if order_sudo.company_id:
values['res_company'] = order_sudo.company_id
if order_sudo.has_to_be_paid():
domain = expression.AND([
['&', ('state', 'in', ['enabled', 'test']), ('company_id', '=', order_sudo.company_id.id)],
['|', ('country_ids', '=', False), ('country_ids', 'in', [order_sudo.partner_id.country_id.id])]
])
acquirers = request.env['payment.acquirer'].sudo().search(domain)
values['acquirers'] = acquirers.filtered(lambda acq: (acq.payment_flow == 'form' and acq.view_template_id) or
(acq.payment_flow == 's2s' and acq.registration_view_template_id))
values['pms'] = request.env['payment.token'].search([('partner_id', '=', order_sudo.partner_id.id)])
values['acq_extra_fees'] = acquirers.get_acquirer_extra_fees(order_sudo.amount_total, order_sudo.currency_id, order_sudo.partner_id.country_id.id)
if order_sudo.state in ('draft', 'sent', 'cancel'):
history = request.session.get('my_quotations_history', [])
else:
history = request.session.get('my_orders_history', [])
values.update(get_records_pager(history, order_sudo))
values = self._order_get_page_view_values(order_sudo, access_token, **kw)
values['message'] = message
return request.render('sale.sale_order_portal_template', values)
+23 -1
View File
@@ -12,7 +12,29 @@ class PortalAccount(portal.PortalAccount):
def _invoice_get_page_view_values(self, invoice, access_token, **kwargs):
values = super(PortalAccount, self)._invoice_get_page_view_values(invoice, access_token, **kwargs)
domain = request.env['account.analytic.line']._timesheet_get_portal_domain()
domain = expression.AND([domain, [('timesheet_invoice_id', '=', invoice.id)]])
domain = expression.AND([
domain,
request.env['account.analytic.line']._timesheet_get_sale_domain(
invoice.mapped('line_ids.sale_line_ids'),
request.env['account.move'].browse([invoice.id])
)
])
values['timesheets'] = request.env['account.analytic.line'].sudo().search(domain)
values['is_uom_day'] = request.env['account.analytic.line'].sudo()._is_timesheet_encode_uom_day()
return values
class CustomerPortal(portal.CustomerPortal):
def _order_get_page_view_values(self, order, access_token, **kwargs):
values = super(CustomerPortal, self)._order_get_page_view_values(order, access_token, **kwargs)
domain = request.env['account.analytic.line']._timesheet_get_portal_domain()
domain = expression.AND([
domain,
request.env['account.analytic.line']._timesheet_get_sale_domain(
order.mapped('order_line'),
order.invoice_ids
)
])
values['timesheets'] = request.env['account.analytic.line'].sudo().search(domain)
values['is_uom_day'] = request.env['account.analytic.line'].sudo()._is_timesheet_encode_uom_day()
return values
+14 -1
View File
@@ -131,7 +131,20 @@ class AccountAnalyticLine(models.Model):
thus there is no meaning of showing invoice with ordered quantity.
"""
domain = super(AccountAnalyticLine, self)._timesheet_get_portal_domain()
return expression.AND([domain, [('timesheet_invoice_type', 'in', ['billable_time', 'non_billable'])]])
return expression.AND([domain, [('timesheet_invoice_type', 'in', ['billable_time', 'non_billable', 'billable_fixed'])]])
@api.model
def _timesheet_get_sale_domain(self, order_lines_ids, invoice_ids):
return [
'|',
'&',
('timesheet_invoice_id', 'in', invoice_ids.ids),
#TODO Question to Reviewer: non_billable was part of domain in _timesheet_get_portal_domain so I kept it here, does this make sense?
('timesheet_invoice_type', 'in', ['billable_time', 'non_billable']),
'&',
('timesheet_invoice_type', '=', 'billable_fixed'),
('so_line', 'in', order_lines_ids.ids)
]
def _get_timesheets_to_merge(self):
res = super(AccountAnalyticLine, self)._get_timesheets_to_merge()
@@ -59,4 +59,56 @@
</xpath>
</template>
<template id="sale_order_portal_template_inherit" inherit_id="sale.sale_order_portal_template">
<xpath expr="//t[@t-call='portal.portal_record_sidebar']//div[hasclass('o_download_pdf')]" position="after">
<li t-if="timesheets" class="list-group-item flex-grow-1" >
<a href="#accordion">Timesheets</a>
</li>
</xpath>
<xpath expr="//div[@id='sale_order_communication']" position="before">
<div t-if="timesheets" class="container">
<div id="accordion" class="o_timesheet_accordion mt-4">
<div class="card mb-0">
<div class="card-header">
<h5 class="mb0">
<a class="card-title" data-toggle="collapse" href="#collapseTimesheet">
Timesheets
</a>
</h5>
</div>
<div id="collapseTimesheet" class="card-body show" data-parent="#accordion">
<t t-set="nr_tasks" t-value="len(timesheets.mapped('task_id'))"/>
<t t-set="nr_projects" t-value="len(timesheets.mapped('project_id'))"/>
<table class="table table-sm">
<thead>
<tr>
<th>Date</th>
<th>Employee</th>
<th t-if="nr_projects &gt; 1">Project</th>
<th t-if="nr_tasks &gt; 0">Task</th>
<th>Description</th>
<th t-if="timesheets[0]._is_timesheet_encode_uom_day()" class="text-right">Duration (days)</th>
<th t-else="" class="text-right">Duration (hours)</th>
</tr>
</thead>
<tr t-foreach="timesheets" t-as="timesheet">
<td><t t-esc="timesheet.date" t-options='{"widget": "date"}'/></td>
<td><t t-esc="timesheet.employee_id.name"/></td>
<td t-if="nr_projects &gt; 1"><span t-field="timesheet.project_id"/></td>
<td t-if="nr_tasks &gt; 0"><span t-field="timesheet.task_id"/></td>
<td><t t-esc="timesheet.name"/></td>
<td class="text-right">
<span t-if="timesheet._is_timesheet_encode_uom_day()" t-esc="timesheet._get_timesheet_time_day()" t-options='{"widget": "timesheet_uom"}'/>
<span t-else="" t-field="timesheet.unit_amount" t-options='{"widget": "float_time"}'/>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</xpath>
</template>
</odoo>