mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-27 17:52:01 +02:00
19.0 vanilla
This commit is contained in:
parent
79f83631d5
commit
73afc09215
6267 changed files with 1534193 additions and 1130106 deletions
|
|
@ -3,9 +3,8 @@
|
|||
|
||||
<record id="action_timesheet_from_invoice" model="ir.actions.act_window">
|
||||
<field name="name">Timesheets</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.analytic.line</field>
|
||||
<field name="view_mode">tree,form,graph,pivot,kanban</field>
|
||||
<field name="view_mode">list,form,graph,pivot,kanban</field>
|
||||
<field name="context">{
|
||||
'create': False,
|
||||
'edit': False,
|
||||
|
|
@ -25,7 +24,7 @@
|
|||
|
||||
<record id="action_timesheet_from_invoice_view_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_mode">list</field>
|
||||
<field name="view_id" ref="hr_timesheet.hr_timesheet_line_tree"/>
|
||||
<field name="act_window_id" ref="action_timesheet_from_invoice"/>
|
||||
</record>
|
||||
|
|
@ -65,10 +64,10 @@
|
|||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<field name="timesheet_count" invisible="1"/>
|
||||
<button name="%(sale_timesheet.action_timesheet_from_invoice)d" type="action" class="oe_stat_button" icon="fa-clock-o" attrs="{'invisible': [('timesheet_count', '=', 0)]}" groups="hr_timesheet.group_hr_timesheet_user">
|
||||
<button name="%(sale_timesheet.action_timesheet_from_invoice)d" type="action" class="oe_stat_button" icon="fa-clock-o" invisible="timesheet_count == 0" groups="hr_timesheet.group_hr_timesheet_user">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="timesheet_total_duration" class="mr4" widget="statinfo" nolabel="1"/>
|
||||
<field name="timesheet_total_duration" class="mr4" nolabel="1"/>
|
||||
<field name="timesheet_encode_uom_id" options="{'no_open': True}"/>
|
||||
</span>
|
||||
<span class="o_stat_text">Recorded</span>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@
|
|||
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='task_id']" position="after">
|
||||
<field name="order_id" string="Sales Order" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="so_line" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="order_id" string="Sales Order" filter_domain="['|', ('so_line', 'ilike', self), ('order_id', 'ilike', self)]"/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='month']" position="before">
|
||||
<filter name="billable_fixed" string="Billed at a Fixed Price" domain="[('timesheet_invoice_type', '=', 'billable_fixed')]"
|
||||
|
|
@ -24,8 +23,6 @@
|
|||
<separator/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='groupby_employee']" position="after">
|
||||
<filter string="Sales Order" name="groupby_sale_order" domain="[]" context="{'group_by': 'order_id'}"
|
||||
groups="sales_team.group_sale_salesman"/>
|
||||
<filter string="Sales Order Item" name="groupby_sale_order_item" domain="[]" context="{'group_by': 'so_line'}"
|
||||
groups="sales_team.group_sale_salesman"/>
|
||||
<filter string="Invoice" name="groupby_invoice" domain="[]" context="{'group_by': 'timesheet_invoice_id'}"
|
||||
|
|
@ -37,14 +34,15 @@
|
|||
</record>
|
||||
|
||||
<record id="hr_timesheet_line_tree_inherit" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.tree.inherit</field>
|
||||
<field name="name">account.analytic.line.list.inherit</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//tree/field[@name='name']" position="after">
|
||||
<field name="commercial_partner_id" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="is_so_line_edited" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="so_line" widget="so_line_field" optional="hide" options="{'no_create': True}" context="{'create': False, 'edit': False, 'delete': False}" groups="sales_team.group_sale_salesman"/>
|
||||
<xpath expr="//list/field[@name='name']" position="after">
|
||||
<field name="commercial_partner_id" column_invisible="True" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="is_so_line_edited" column_invisible="True" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="allow_billable" column_invisible="True" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="so_line" widget="so_line_field" optional="show" options="{'no_create': True, 'no_open': True}" context="{'create': False, 'edit': False, 'delete': False}" invisible="not allow_billable" readonly="readonly_timesheet" column_invisible="context.get('hide_so_line')" placeholder="Non-billable" groups="sales_team.group_sale_salesman"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
@ -57,7 +55,35 @@
|
|||
<xpath expr="//field[@name='task_id']" position="after">
|
||||
<field name="commercial_partner_id" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="is_so_line_edited" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="so_line" widget="so_line_field" options='{"no_create": True}' context="{'create': False, 'edit': False, 'delete': False}" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="allow_billable" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="sale_order_state" invisible="1"/>
|
||||
<label for="so_line" invisible="not allow_billable" groups="sales_team.group_sale_salesman"/>
|
||||
<div class="o_row" invisible="not allow_billable" groups="sales_team.group_sale_salesman">
|
||||
<field name="so_line" widget="so_line_field" options='{"no_create": True}' context="{'create': False, 'edit': False, 'delete': False, 'with_price_unit': True}" readonly="readonly_timesheet" placeholder="Non-billable"/>
|
||||
<span
|
||||
class="fa fa-exclamation-triangle text-warning"
|
||||
title="The sales order associated with this timesheet entry has been cancelled."
|
||||
invisible="sale_order_state != 'cancel'"
|
||||
/>
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//group" position="before">
|
||||
<t groups="sales_team.group_sale_salesman">
|
||||
<field name="order_id" invisible="1"/>
|
||||
<field name="timesheet_invoice_id" invisible="1"/>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_sale_order_from_timesheet" type="object" class="oe_stat_button" icon="fa-dollar" invisible="not order_id">
|
||||
<div class="o_stat_info">
|
||||
<span class="o_stat_text">Sales Order</span>
|
||||
</div>
|
||||
</button>
|
||||
<button name="action_invoice_from_timesheet" type="object" class="oe_stat_button" icon="fa-pencil-square-o" invisible="not timesheet_invoice_id">
|
||||
<div class="o_stat_info">
|
||||
<span class="o_stat_text">Invoice</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
@ -69,7 +95,7 @@
|
|||
<pivot string="Timesheets" sample="1">
|
||||
<field name="date" interval="month" type="row"/>
|
||||
<field name="timesheet_invoice_type" type="col"/>
|
||||
<field name="unit_amount" type="measure" widget="timesheet_uom"/>
|
||||
<field name="unit_amount" string="Time Spent" type="measure" widget="timesheet_uom"/>
|
||||
<field name="amount" string="Timesheet Costs"/>
|
||||
</pivot>
|
||||
</field>
|
||||
|
|
@ -83,11 +109,35 @@
|
|||
<field name="date" interval="month" />
|
||||
<field name="employee_id"/>
|
||||
<field name="amount" type="measure" string="Timesheet Costs"/>
|
||||
<field name="unit_amount" type="measure" widget="timesheet_uom"/>
|
||||
<field name="unit_amount" string="Time Spent" type="measure" widget="timesheet_uom"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_timesheet_line_graph_invoice_employee" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.graph.invoice.employee</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="mode">primary</field>
|
||||
<field name="inherit_id" ref="view_hr_timesheet_line_graph_employee_per_date"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='date']" position="replace">
|
||||
<field name="timesheet_invoice_id"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_timesheet_line_pivot_inherited" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.pivot</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="mode">primary</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.view_hr_timesheet_line_pivot"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='amount']" position="attributes">
|
||||
<attribute name="type">measure</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Timesheet from Sales Order
|
||||
-->
|
||||
|
|
@ -103,7 +153,7 @@
|
|||
|
||||
<record id="timesheet_action_from_sales_order_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="4"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_mode">list</field>
|
||||
<field name="view_id" ref="hr_timesheet.timesheet_view_tree_user"/>
|
||||
<field name="act_window_id" ref="timesheet_action_from_sales_order"/>
|
||||
</record>
|
||||
|
|
@ -130,17 +180,17 @@
|
|||
}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No timesheets found. Let's create one!
|
||||
No activities found. Let's start a new one!
|
||||
</p>
|
||||
<p>
|
||||
Keep track of your working hours by project every day and bill your customers for that time.
|
||||
Track your working hours by projects every day and invoice this time to your customers.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="timesheet_action_from_sales_order_item_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_mode">list</field>
|
||||
<field name="view_id" ref="hr_timesheet.timesheet_view_tree_user"/>
|
||||
<field name="act_window_id" ref="timesheet_action_from_sales_order_item"/>
|
||||
</record>
|
||||
|
|
@ -155,7 +205,7 @@
|
|||
<record id="timesheet_action_from_sales_order_item_pivot" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view_mode">pivot</field>
|
||||
<field name="view_id" ref="hr_timesheet.view_hr_timesheet_line_pivot"/>
|
||||
<field name="view_id" ref="view_hr_timesheet_line_pivot_inherited"/>
|
||||
<field name="act_window_id" ref="timesheet_action_from_sales_order_item"/>
|
||||
</record>
|
||||
|
||||
|
|
@ -179,7 +229,7 @@
|
|||
<record id="timesheet_action_plan_pivot" model="ir.actions.act_window">
|
||||
<field name="name">Timesheet</field>
|
||||
<field name="res_model">account.analytic.line</field>
|
||||
<field name="view_mode">pivot,tree,form</field>
|
||||
<field name="view_mode">pivot,list,form</field>
|
||||
<field name="domain">[('project_id', '!=', False)]</field>
|
||||
<field name="context">{
|
||||
"is_timesheet": 1,
|
||||
|
|
@ -190,7 +240,7 @@
|
|||
<record id="timesheet_action_from_plan" model="ir.actions.act_window">
|
||||
<field name="name">Timesheet</field>
|
||||
<field name="res_model">account.analytic.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('project_id', '!=', False)]</field>
|
||||
<field name="context">{
|
||||
"is_timesheet": 1,
|
||||
|
|
@ -198,4 +248,27 @@
|
|||
<field name="search_view_id" ref="hr_timesheet.hr_timesheet_line_search"/>
|
||||
</record>
|
||||
|
||||
<record id="view_calendar_account_analytic_line" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.calendar</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.view_calendar_account_analytic_line"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="before">
|
||||
<field name="so_line" invisible="not so_line"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_calendar_account_analytic_line_multi_create" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.calendar.multi_create</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.view_calendar_account_analytic_line_multi_create"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="unit_amount" position="before">
|
||||
<field name="allow_billable" invisible="1" groups="sales_team.group_sale_salesman"/>
|
||||
<field name="so_line" groups="sales_team.group_sale_salesman" options='{"no_create": True}' context="{'create': False, 'edit': False, 'delete': False, 'with_price_unit': True}" invisible="not allow_billable" placeholder="Non-billable"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -6,11 +6,25 @@
|
|||
<field name="inherit_id" ref="sale.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_tooltip" position="after">
|
||||
<label for="product_tooltip" string="" attrs="{'invisible': ['|', ('type', '!=', 'service'), ('service_policy', '!=', 'ordered_prepaid')]}"/>
|
||||
<div attrs="{'invisible': ['|', ('type', '!=', 'service'), ('service_policy', '!=', 'ordered_prepaid')]}" class="fst-italic text-muted">
|
||||
<label for="service_upsell_threshold" string=""
|
||||
invisible="type != 'service'
|
||||
or service_policy != 'ordered_prepaid'
|
||||
or not sale_ok
|
||||
or service_tracking not in ['no', 'task_global_project', 'task_in_project', 'project_only']"
|
||||
/>
|
||||
<div invisible="type != 'service'
|
||||
or service_policy != 'ordered_prepaid'
|
||||
or not sale_ok
|
||||
or service_tracking not in ['no', 'task_global_project', 'task_in_project', 'project_only']"
|
||||
class="fst-italic text-muted"
|
||||
>
|
||||
Warn the salesperson for an upsell when work done exceeds
|
||||
<field name="service_upsell_threshold" widget="percentage" class="oe_inline"/>
|
||||
of hours sold. <field name="service_upsell_threshold_ratio" class="oe_inline" attrs="{'invisible': [('service_upsell_threshold_ratio', '=', False)]}"/>
|
||||
<field
|
||||
name="service_upsell_threshold"
|
||||
widget="percentage"
|
||||
class="oe_inline o_field_highlight"
|
||||
/>
|
||||
of hours sold. <field name="service_upsell_threshold_ratio" class="oe_inline" invisible="not service_upsell_threshold_ratio"/>
|
||||
</div>
|
||||
</field>
|
||||
</field>
|
||||
|
|
@ -22,21 +36,21 @@
|
|||
<field name="inherit_id" ref="product.product_template_search_view"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='consumable']" position="after">
|
||||
<filter name="combo" position="after">
|
||||
<separator/>
|
||||
<filter string="Time-based services" name="product_time_based" domain="[('type', '=', 'service'), ('invoice_policy', '=', 'delivery'), ('service_type', '=', 'timesheet')]"/>
|
||||
<filter string="Fixed price services" name="product_service_fixed" domain="[('type', '=', 'service'), ('invoice_policy', '=', 'order'), ('service_type', '=', 'timesheet')]"/>
|
||||
<filter string="Milestone services" name="product_service_milestone" domain="[('type', '=', 'service'), ('invoice_policy', '=', 'delivery'), ('service_type', '=', 'manual')]"/>
|
||||
</xpath>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_action_default_services" model="ir.actions.act_window">
|
||||
<field name="name">Services</field>
|
||||
<field name="res_model">product.template</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="sale_timesheet.product_template_view_search_sale_timesheet"/>
|
||||
<field name="context">{'search_default_services': 1, 'default_detailed_type': 'service'}</field>
|
||||
<field name="context">{'search_default_services': 1, 'default_type': 'service'}</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="portal_timesheet_table_inherit" inherit_id="hr_timesheet.portal_timesheet_table">
|
||||
<th name="t_label" position="before">
|
||||
<t t-set="display_sol" t-value="False"/>
|
||||
<t t-foreach="timesheets" t-as="timesheet">
|
||||
<t t-if="timesheet.so_line != task.sale_line_id">
|
||||
<t t-set="display_sol" t-value="True"/>
|
||||
</t>
|
||||
</t>
|
||||
<th t-if="display_sol">Sales Order Item</th>
|
||||
</th>
|
||||
<xpath expr="//tr/td[t[@t-esc='timesheet.name']]" position="after">
|
||||
<td t-if="display_sol">
|
||||
<t t-if="timesheet.so_line.order_id.access_url and so_accessible"><a t-att-href="'%s' % timesheet.so_line.order_id.access_url"><t t-out="timesheet.so_line.display_name"/></a></t>
|
||||
<t t-elif="timesheet.so_line.display_name" t-out="timesheet.so_line.display_name"></t>
|
||||
<span t-else="" class="text-muted">Non-billable</span>
|
||||
</td>
|
||||
</xpath>
|
||||
<xpath expr="//div[@name='allocated_time']" position="after">
|
||||
<tr t-if="task.allow_billable and task.sale_line_id and task.sale_line_id.remaining_hours_available" t-attf-class="{{task.remaining_hours_so < 0 and 'text-danger'}}">
|
||||
<td><strong>Time Remaining on SO: </strong></td>
|
||||
<td class="text-end">
|
||||
<span t-if="is_uom_day" t-esc="timesheets._convert_hours_to_days(task.remaining_hours_so)" t-options='{"widget": "timesheet_uom"}'/>
|
||||
<span t-else="" t-esc="task.remaining_hours_so" t-options='{"widget": "float_time"}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -4,51 +4,38 @@
|
|||
<record id="project_sharing_inherit_project_task_view_form" model="ir.ui.view">
|
||||
<field name="name">project.task.form.inherit.timesheet</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="project.project_sharing_project_task_view_form"/>
|
||||
<field name="priority">600</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.project_sharing_inherit_project_task_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='timesheet_ids']/tree" position="attributes">
|
||||
<xpath expr="//field[@name='timesheet_ids']/list" position="attributes">
|
||||
<attribute name="decoration-muted">timesheet_invoice_id != False</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='timesheet_ids']/tree/field[@name='unit_amount']" position="before">
|
||||
<field name="timesheet_invoice_id" invisible="1"/>
|
||||
<field name="so_line"
|
||||
attrs="{'column_invisible': [('parent.allow_billable', '=', False)]}"
|
||||
<xpath expr="//field[@name='timesheet_ids']/list/field[@name='unit_amount']" position="before">
|
||||
<field name="timesheet_invoice_id" column_invisible="True"/>
|
||||
<field name="so_line" widget="so_line_field"
|
||||
column_invisible="not parent.allow_billable"
|
||||
context="{'with_remaining_hours': True, 'with_price_unit': True}" options="{'no_create': True, 'no_open': True}"
|
||||
optional="hide"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='child_ids']/tree/field[@name='remaining_hours']" position="after">
|
||||
<field name="remaining_hours_so" optional="hide" widget="timesheet_uom"
|
||||
attrs="{'column_invisible': ['|', ('parent.allow_billable', '=', False), ('parent.allow_timesheets', '=', False)]}" />
|
||||
<xpath expr="//field[@name='child_ids']/list/field[@name='remaining_hours']" position="after">
|
||||
<field name="remaining_hours_available" column_invisible="True"/>
|
||||
<field name="remaining_hours_so" optional="hide" widget="timesheet_uom" column_invisible="not parent.allow_timesheets"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='depend_on_ids']/list/field[@name='remaining_hours']" position="after">
|
||||
<field name="remaining_hours_available" column_invisible="True"/>
|
||||
<field name="remaining_hours_so" optional="hide" widget="timesheet_uom" column_invisible="not parent.allow_timesheets"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='remaining_hours']" position="after">
|
||||
<field name="allow_billable" invisible="1" />
|
||||
<field name="remaining_hours_available" invisible="1"/>
|
||||
<field name="sale_order_id" invisible="1"/>
|
||||
<span id="remaining_hours_so_label" attrs="{'invisible': ['|', '|', ('allow_billable', '=', False), ('allow_timesheets', '=', False), ('remaining_hours_available', '=', False)]}" class="o_td_label float-start">
|
||||
<label class="fw-bold" for="remaining_hours_so" string="Remaining Hours on SO"
|
||||
attrs="{'invisible': ['|', ('encode_uom_in_days', '=', True), ('remaining_hours_so', '<', 0)]}"/>
|
||||
<label class="fw-bold" for="remaining_hours_so" string="Remaining Days on SO"
|
||||
attrs="{'invisible': ['|', ('encode_uom_in_days', '=', False), ('remaining_hours_so', '<', 0)]}"/>
|
||||
<label class="fw-bold text-danger" for="remaining_hours_so" string="Remaining Hours on SO"
|
||||
attrs="{'invisible': ['|', ('encode_uom_in_days', '=', True), ('remaining_hours_so', '>=', 0)]}"/>
|
||||
<label class="fw-bold text-danger" for="remaining_hours_so" string="Remaining Days on SO"
|
||||
attrs="{'invisible': ['|', ('encode_uom_in_days', '=', False), ('remaining_hours_so', '>=', 0)]}"/>
|
||||
<span id="remaining_hours_so_label" invisible="not allow_billable or not sale_order_id or not partner_id or not sale_line_id or not remaining_hours_available" class="o_td_label float-start">
|
||||
<label class="fw-bold" for="remaining_hours_so"
|
||||
invisible="remaining_hours_so < 0"/>
|
||||
<label class="fw-bold text-danger" for="remaining_hours_so"
|
||||
invisible="remaining_hours_so >= 0"/>
|
||||
</span>
|
||||
<field name="remaining_hours_so" nolabel="1" widget="timesheet_uom" attrs="{'invisible': ['|', '|',('allow_billable', '=', False), ('allow_timesheets', '=', False), ('remaining_hours_available', '=', False)]}" decoration-danger="remaining_hours_so < 0"></field>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_sharing_inherit_project_task_view_tree_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">project.task.tree.inherit.sale.timesheet</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.project_sharing_inherit_project_task_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='remaining_hours']" position="after">
|
||||
<field name="allow_billable" invisible="1" />
|
||||
<field name="allow_timesheets" invisible="1"/>
|
||||
<field name="remaining_hours_so" optional="hide" widget="timesheet_uom"
|
||||
attrs="{'column_invisible': ['|', ('allow_billable', '=', False), ('allow_timesheets', '=', False)]}" />
|
||||
<field name="remaining_hours_so" nolabel="1" widget="timesheet_uom" invisible="not allow_billable or not sale_order_id or not partner_id or not sale_line_id or not remaining_hours_available" decoration-danger="remaining_hours_so < 0"></field>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
|||
|
|
@ -6,53 +6,107 @@
|
|||
<field name="model">project.project</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.project_invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//button[@name='action_view_sos'][1]" position="attributes">
|
||||
<attribute name="context">{'create_for_project_id': id, 'default_project_id': id, 'default_partner_id': partner_id}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='action_view_sos'][2]" position="attributes">
|
||||
<attribute name="context">{'create_for_project_id': id, 'default_project_id': id, 'default_partner_id': partner_id}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='settings']" position="after">
|
||||
<page name="billing_employee_rate" string="Invoicing" attrs="{'invisible': ['|', ('allow_billable', '=', False), ('partner_id', '=', False)]}">
|
||||
<group>
|
||||
<group>
|
||||
<field name="display_create_order" invisible="1"/>
|
||||
<field name="pricing_type" invisible="1" widget="radio"/>
|
||||
<field name="timesheet_product_id" string="Default Service" invisible="1" context="{'default_detailed_type': 'service', 'default_service_policy': 'delivered_timesheet', 'default_service_type': 'timesheet'}"/>
|
||||
<field name="sale_order_id" invisible="1" options="{'no_create': True, 'no_edit': True, 'delete': False, 'no_open': True}"/>
|
||||
<field name="sale_line_id" groups="!sales_team.group_sale_salesman" options="{'no_create': True, 'no_edit': True, 'delete': False, 'no_open': True}"/>
|
||||
<field name="sale_line_id" groups="sales_team.group_sale_salesman" options="{'no_create': True, 'no_edit': True, 'delete': False}"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="sale_line_employee_ids">
|
||||
<tree editable="bottom">
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<field name="employee_id" options="{'no_create': True}"/>
|
||||
<field name="sale_line_id" attrs="{'required': True}" options="{'no_create': True}"/>
|
||||
<page name="billing_employee_rate" string="Invoicing" invisible="not allow_billable or not partner_id or is_template">
|
||||
<field name="sale_line_employee_ids" mode="list,kanban" context="{'default_sale_line_id': sale_line_id}">
|
||||
<list editable="bottom">
|
||||
<field name="company_id" column_invisible="True"/>
|
||||
<field name="partner_id" column_invisible="True"/>
|
||||
<field name="sale_order_id" column_invisible="True"/>
|
||||
<field name="employee_id" widget="many2one_avatar_employee" context="{'create_project_employee_mapping': company_id}"/>
|
||||
<field name="existing_employee_ids" column_invisible="True"/>
|
||||
<field name="sale_line_id" column_invisible="parent.id" required="True" options="{'no_create': True}" context="{'search_default_order_id': sale_order_id}"/>
|
||||
<field name="sale_line_id" column_invisible="not parent.id" required="True" groups="!sales_team.group_sale_salesman" options="{'no_create': True}"
|
||||
context="{'search_default_order_id': sale_order_id}"/>
|
||||
<field name="sale_line_id" column_invisible="not parent.id" required="True" groups="sales_team.group_sale_salesman"
|
||||
options="{'no_create': True, 'no_open': True}"
|
||||
context="{
|
||||
'search_default_order_id': sale_order_id,
|
||||
'so_form_view_ref': 'sale_project.view_order_simple_form',
|
||||
'create_for_employee_mapping': True,
|
||||
'default_partner_id': partner_id,
|
||||
'default_company_id': company_id,
|
||||
'default_project_id': project_id,
|
||||
}"
|
||||
widget="so_line_create_button"
|
||||
/>
|
||||
<field name="price_unit" widget="monetary" force_save="1" options="{'currency_field': 'currency_id'}"/>
|
||||
<field name="display_cost" widget="monetary" options="{'currency_field': 'cost_currency_id'}"/>
|
||||
<field name="is_cost_changed" invisible="1"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="cost_currency_id" invisible="1"/>
|
||||
</tree>
|
||||
<field name="is_cost_changed" column_invisible="True"/>
|
||||
<field name="currency_id" column_invisible="True"/>
|
||||
<field name="cost_currency_id" column_invisible="True"/>
|
||||
</list>
|
||||
<kanban class="o_kanban_mobile">
|
||||
<field name="currency_id"/>
|
||||
<templates>
|
||||
<t t-name="card">
|
||||
<div class="row">
|
||||
<div class="col-8 d-flex">
|
||||
<field name="employee_id" widget="many2one_avatar_employee"/>
|
||||
<field name="employee_id" class="fw-bold ps-1"/>
|
||||
</div>
|
||||
<div class="col-4 float-end text-end">
|
||||
<b>Unit Price: </b>
|
||||
<field name="price_unit" widget="monetary" force_save="1" options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<field name="sale_line_id" class="col-8 text-muted"/>
|
||||
<div class="col-4 float-end text-end">
|
||||
<b>Daily Cost: </b>
|
||||
<field name="display_cost" widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
<form string="Timesheet Activities">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="existing_employee_ids" invisible="1"/>
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<field name="sale_order_id" invisible="1"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="employee_id" widget="many2one_avatar_employee" required="1"/>
|
||||
<field name="sale_line_id" invisible="parent.id" options="{'no_create': True}" context="{'search_default_order_id': sale_order_id}"/>
|
||||
<field name="sale_line_id" invisible="not parent.id" required="True" groups="!sales_team.group_sale_salesman" options="{'no_create': True}"
|
||||
context="{'search_default_order_id': sale_order_id}"/>
|
||||
<field name="sale_line_id" invisible="not parent.id" required="True" groups="sales_team.group_sale_salesman" options="{'no_create': True}"
|
||||
widget="so_line_create_button"
|
||||
context="{
|
||||
'search_default_order_id': sale_order_id,
|
||||
'so_form_view_ref': 'sale_project.view_order_simple_form',
|
||||
'create_for_employee_mapping': True,
|
||||
'default_partner_id': partner_id,
|
||||
'default_company_id': company_id,
|
||||
'default_project_id': project_id,
|
||||
}"
|
||||
/>
|
||||
<field name="price_unit" widget="monetary" readonly="True" force_save="1" options="{'currency_field': 'currency_id'}"/>
|
||||
<field name="display_cost" widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
<p class="text-muted">
|
||||
<i class="fa fa-lightbulb-o"/>
|
||||
<span>
|
||||
Define the rate at which an employee's time is billed based on their expertise, skills, or experience.
|
||||
To bill the same service at a different rate, create separate sales order items.
|
||||
</span>
|
||||
</p>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_project_view_form_simplified_inherit" model="ir.ui.view">
|
||||
<field name="name">project.project.view.form.simplified.inherit</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.project_project_view_form_simplified_inherit_timesheet"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[hasclass('o_setting_box')]" position="before">
|
||||
<div class="col-lg-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="allow_billable"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="allow_billable"/>
|
||||
<div class="text-muted" id="allow_billable_setting">
|
||||
Invoice your time and material to customers
|
||||
</div>
|
||||
</div>
|
||||
<xpath expr="//page[@name='settings']//field[@name='allow_billable']" position="after">
|
||||
<div invisible="not allow_billable or not allow_timesheets" class="text-muted">
|
||||
Timesheets without a sales order item are reported as
|
||||
<field name="billing_type" nolabel="1" class="w-auto"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
|
|
@ -70,11 +124,11 @@
|
|||
<field name="pricing_type" invisible="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//div[hasclass('o_kanban_manage_reporting')]" position="inside">
|
||||
<div role="menuitem" t-if="record.rating_active.raw_value" groups="project.group_project_manager">
|
||||
<div role="menuitem" t-if="record.show_ratings.raw_value" groups="project.group_project_manager">
|
||||
<a name="action_view_all_rating" type="object">
|
||||
Customer Ratings
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
@ -84,9 +138,9 @@
|
|||
<field name="name">project.project.kanban.inherit.sale.timesheet.so.button</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="inherit_id" ref="project.view_project_kanban"/>
|
||||
<field name="priority">30</field>
|
||||
<field name="priority">32</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[hasclass('o_kanban_manage_view')]" position="inside">
|
||||
<xpath expr="//div[@name='card_menu_view']" position="inside">
|
||||
<div t-if="record.allow_billable.raw_value and record.sale_order_id.raw_value and record.pricing_type.raw_value != 'task_rate'"
|
||||
role="menuitem"
|
||||
groups="sales_team.group_sale_salesman_all_leads">
|
||||
|
|
@ -96,31 +150,16 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_sale_service_inherit_form2" model="ir.ui.view">
|
||||
<field name="name">sale.service.form.view.inherit</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.view_task_form2_inherited"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//header" position="inside">
|
||||
<field name="allow_billable" invisible="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='child_ids']/tree//field[@name='remaining_hours']" position="after">
|
||||
<field name="remaining_hours_so" widget="timesheet_uom" optional="hide" groups="base.group_user"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='depend_on_ids']/tree//field[@name='remaining_hours']" position="after">
|
||||
<field name="remaining_hours_so" widget="timesheet_uom" optional="hide" groups="base.group_user"/>
|
||||
</xpath>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_task_tree2_inherited" model="ir.ui.view">
|
||||
<field name="name">project.task.tree.inherited</field>
|
||||
<field name="name">project.task.list.inherited</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.view_task_tree2_inherited" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='remaining_hours']" position="after">
|
||||
<field name="remaining_hours_so" widget="timesheet_uom" optional="hide"/>
|
||||
<field name="sale_line_id" column_invisible="True"/>
|
||||
<field name="remaining_hours_available" column_invisible="True"/>
|
||||
<field name="remaining_hours_so" invisible="not sale_line_id or not remaining_hours_available" widget="timesheet_uom" optional="hide"
|
||||
groups="hr_timesheet.group_hr_timesheet_user" column_invisible="not (context.get('allow_billable', True) and context.get('allow_timesheets', True)) or context.get('template_project')"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
@ -130,71 +169,75 @@
|
|||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="project.view_task_form2"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='timesheet_ids']/tree" position="attributes">
|
||||
<!-- <field name="timesheet_ids"/> is already inside a block groups="hr_timesheet.group_hr_timesheet_user" -->
|
||||
<attribute name="decoration-muted">timesheet_invoice_id != False</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='user_ids']" position="after">
|
||||
<field name="is_project_map_empty" invisible="1" groups="hr_timesheet.group_hr_timesheet_user"/>
|
||||
<field name="has_multi_sol" invisible="1" groups="hr_timesheet.group_hr_timesheet_user"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_phone']" position="after">
|
||||
<xpath expr="//field[@name='partner_id']" position="after">
|
||||
<field name="pricing_type" invisible="1" groups="hr_timesheet.group_hr_timesheet_user"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='timesheet_ids']" position="attributes">
|
||||
<xpath expr="//field[@name='timesheet_ids']/list" position="inside">
|
||||
<!-- <field name="timesheet_ids"/> is already inside a block groups="hr_timesheet.group_hr_timesheet_user" -->
|
||||
<attribute name="widget">so_line_one2many</attribute>
|
||||
<field name="is_so_line_edited" column_invisible="True"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='timesheet_ids']/tree" position="inside">
|
||||
<xpath expr="//field[@name='timesheet_ids']/list/field[@name='unit_amount']" position="before">
|
||||
<!-- <field name="timesheet_ids"/> is already inside a block groups="hr_timesheet.group_hr_timesheet_user" -->
|
||||
<field name="is_so_line_edited" invisible="1" />
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='timesheet_ids']/tree/field[@name='unit_amount']" position="before">
|
||||
<!-- <field name="timesheet_ids"/> is already inside a block groups="hr_timesheet.group_hr_timesheet_user" -->
|
||||
<field name="timesheet_invoice_id" invisible="1"/>
|
||||
<field name="timesheet_invoice_id" column_invisible="True"/>
|
||||
<field name="so_line" widget="so_line_field" groups="!sales_team.group_sale_salesman"
|
||||
attrs="{'column_invisible': [('parent.allow_billable', '=', False)]}"
|
||||
column_invisible="not parent.allow_billable"
|
||||
readonly="readonly_timesheet"
|
||||
context="{'with_remaining_hours': True, 'with_price_unit': True}" options="{'no_create': True, 'no_open': True}"
|
||||
domain="[('is_service', '=', True), ('order_partner_id', 'child_of', parent.commercial_partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done'])]"
|
||||
domain="[('is_service', '=', True), ('order_partner_id.commercial_partner_id.id', 'parent_of', parent.partner_id), ('is_expense', '=', False), ('state', '=', 'sale'), ('is_downpayment', '=', False)]"
|
||||
optional="hide"/>
|
||||
<field name="so_line" widget="so_line_field" groups="sales_team.group_sale_salesman"
|
||||
attrs="{'column_invisible': [('parent.allow_billable', '=', False)]}"
|
||||
context="{'with_remaining_hours': True, 'with_price_unit': True}" options="{'no_create': True}"
|
||||
domain="[('is_service', '=', True), ('order_partner_id', 'child_of', parent.commercial_partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done'])]"
|
||||
column_invisible="not parent.allow_billable"
|
||||
readonly="readonly_timesheet"
|
||||
context="{'with_remaining_hours': True, 'with_price_unit': True}" options="{'no_create': True, 'no_open': True}"
|
||||
domain="[('is_service', '=', True), ('order_partner_id.commercial_partner_id.id', 'parent_of', parent.partner_id), ('is_expense', '=', False), ('state', '=', 'sale'), ('is_downpayment', '=', False)]"
|
||||
optional="hide"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='timesheet_ids']/form//field[@name='unit_amount']" position="after">
|
||||
<field name="timesheet_invoice_id" invisible="1"/>
|
||||
<field name="so_line" widget="so_line_field" groups="!sales_team.group_sale_salesman"
|
||||
invisible="not parent.allow_billable"
|
||||
readonly="readonly_timesheet"
|
||||
context="{'with_remaining_hours': True, 'with_price_unit': True}" options="{'no_create': True, 'no_open': True}"
|
||||
domain="[('is_service', '=', True), ('order_partner_id', 'child_of', parent.partner_id), ('is_expense', '=', False), ('state', '=', 'sale')]"
|
||||
placeholder="Non-billable"
|
||||
optional="hide"/>
|
||||
<field
|
||||
name="so_line" widget="so_line_field" groups="sales_team.group_sale_salesman"
|
||||
options="{'no_create': True, 'no_open': True}"
|
||||
context="{'create': False, 'edit': False, 'delete': False, 'with_price_unit': True}"
|
||||
invisible="not parent.allow_billable"
|
||||
domain="[('is_service', '=', True), ('order_partner_id', 'child_of', parent.partner_id), ('is_expense', '=', False), ('state', '=', 'sale')]"
|
||||
readonly="readonly_timesheet"
|
||||
placeholder="Non-billable"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='remaining_hours']" position="after">
|
||||
<t groups="hr_timesheet.group_hr_timesheet_user">
|
||||
<field name="sale_order_id" invisible="1"/>
|
||||
<field name="remaining_hours_available" invisible="1"/>
|
||||
<span id="remaining_hours_so_label" attrs="{'invisible': ['|', '|', '|', '|', ('allow_billable', '=', False), ('sale_order_id', '=', False), ('partner_id', '=', False), ('sale_line_id', '=', False), ('remaining_hours_available', '=', False)]}" class="o_td_label float-start">
|
||||
<label class="fw-bold" for="remaining_hours_so" string="Remaining Hours on SO"
|
||||
attrs="{'invisible': ['|', ('encode_uom_in_days', '=', True), ('remaining_hours_so', '<', 0)]}"/>
|
||||
<label class="fw-bold" for="remaining_hours_so" string="Remaining Days on SO"
|
||||
attrs="{'invisible': ['|', ('encode_uom_in_days', '=', False), ('remaining_hours_so', '<', 0)]}"/>
|
||||
<label class="fw-bold text-danger" for="remaining_hours_so" string="Remaining Hours on SO"
|
||||
attrs="{'invisible': ['|', ('encode_uom_in_days', '=', True), ('remaining_hours_so', '>=', 0)]}"/>
|
||||
<label class="fw-bold text-danger" for="remaining_hours_so" string="Remaining Days on SO"
|
||||
attrs="{'invisible': ['|', ('encode_uom_in_days', '=', False), ('remaining_hours_so', '>=', 0)]}"/>
|
||||
<span id="remaining_hours_so_label" invisible="not allow_billable or not sale_order_id or not partner_id or not sale_line_id or not remaining_hours_available" class="o_td_label float-start">
|
||||
<label class="fw-bold" for="remaining_hours_so"
|
||||
invisible="remaining_hours_so < 0"/>
|
||||
<label class="fw-bold text-danger" for="remaining_hours_so"
|
||||
invisible="remaining_hours_so >= 0"/>
|
||||
</span>
|
||||
<field name="remaining_hours_so" nolabel="1" widget="timesheet_uom" attrs="{'invisible': ['|', '|', '|', '|', ('allow_billable', '=', False), ('sale_order_id', '=', False), ('partner_id', '=', False), ('sale_line_id', '=', False), ('remaining_hours_available', '=', False)]}" decoration-danger="remaining_hours_so < 0"></field>
|
||||
<field name="remaining_hours_so" nolabel="1" widget="timesheet_uom" invisible="not allow_billable or not sale_order_id or not partner_id or not sale_line_id or not remaining_hours_available" decoration-danger="remaining_hours_so < 0"></field>
|
||||
</t>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_task_form2_inherit_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">view.task.form2.inherit</field>
|
||||
<record id="project_task_view_search_inherit_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">project.task.view.search.inherit</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="sale_project.view_sale_project_inherit_form"/>
|
||||
<field name="inherit_id" ref="hr_timesheet.project_task_view_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='sale_line_id'][2]" position="attributes">
|
||||
<attribute name="context">{'create': False, 'edit': False, 'delete': False, 'with_price_unit': True, 'with_remaining_hours': True}</attribute>
|
||||
<!-- To do: move allow_billable field in sale_project and add attrs directly on field in master -->
|
||||
<attribute name="attrs">
|
||||
{'invisible': [('allow_billable', '=', False)]}
|
||||
</attribute>
|
||||
</xpath>
|
||||
<filter name="timesheet_exceeded" position="attributes">
|
||||
<attribute name="domain">['|', ('overtime', '>', 0), ('remaining_hours_so', '<', 0)]</attribute>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<template id="project_update_default_description" inherit_id="project.project_update_default_description">
|
||||
<!--As this template is rendered in an html field, the spaces may be interpreted as nbsp while editing. -->
|
||||
<xpath expr="//div[@name='milestone']" position="before">
|
||||
<br/>
|
||||
<div t-if="show_sold">
|
||||
<h3 style="font-weight: bolder"><u>Sold</u></h3>
|
||||
<table class="table table-bordered table-striped">
|
||||
<tbody>
|
||||
<thead>
|
||||
<td style="font-weight: bolder">Service</td>
|
||||
<td style="font-weight: bolder">Sold</td>
|
||||
<td style="font-weight: bolder">Effective</td>
|
||||
<td style="font-weight: bolder">Remaining</td>
|
||||
</thead>
|
||||
<tr t-foreach="services['data']" t-as="service">
|
||||
<t t-set="is_unit" t-value="service['is_unit']"/>
|
||||
<td t-attf-class="#{ 'fst-italic' if is_unit else ''}"><t t-esc="service['name']"/></td>
|
||||
<td t-attf-class="#{ 'fst-italic' if is_unit else ''}" style="text-align: right; vertical-align: middle;"><t t-esc="format_value(service['sold_value'], service['is_hour'])"/> <t t-esc="service['unit']"/></td>
|
||||
<td t-attf-class="#{ 'fst-italic' if is_unit else ''}" style="text-align: right; vertical-align: middle;"><t t-esc="format_value(service['effective_value'], service['is_hour'])"/> <t t-esc="service['unit']"/></td>
|
||||
<td t-attf-class="#{ 'fst-italic' if is_unit else ''}" style="text-align: right; vertical-align: middle;"><t t-esc="format_value(service['remaining_value'], service['is_hour'])"/> <t t-esc="service['unit']"/></td>
|
||||
</tr>
|
||||
<tfoot>
|
||||
<td style="font-weight: bolder; text-align: right">Total</td>
|
||||
<td style="font-weight: bolder; text-align: right; vertical-align: middle;"><t t-esc="format_value(services['total_sold'], services['is_hour'])"/> <t t-esc="services['company_unit_name']"/></td>
|
||||
<td style="font-weight: bolder; text-align: right; vertical-align: middle;"><t t-esc="format_value(services['total_effective'], services['is_hour'])"/> <t t-esc="services['company_unit_name']"/></td>
|
||||
<td style="font-weight: bolder; text-align: right; vertical-align: middle;"><t t-esc="format_value(services['total_remaining'], services['is_hour'])"/> <t t-esc="services['company_unit_name']"/></td>
|
||||
</tfoot>
|
||||
</tbody>
|
||||
</table>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div name="profitability" t-if="show_profitability">
|
||||
<t t-if="project.analytic_account_id and project.allow_billable and user.has_group('project.group_project_manager')" name="costs">
|
||||
<h3 style="font-weight: bolder"><u>Profitability</u></h3>
|
||||
The cost of the project is now at <t t-esc="profitability['costs_formatted']"/>, for a revenue of <t t-esc="profitability['revenues_formatted']"/>, leading to a
|
||||
<span>
|
||||
<font t-if="profitability['margin'] > 0" style="color: rgb(0, 128, 0)">
|
||||
<b><t t-esc="profitability['margin_formatted']"/></b>
|
||||
</font>
|
||||
<font t-elif="profitability['margin'] < 0" style="color: rgb(128, 0, 0)">
|
||||
<b><t t-esc="profitability['margin_formatted']"/></b>
|
||||
</font>
|
||||
<t t-else="" t-esc="profitability['margin_formatted']"/>
|
||||
</span> margin (<t t-esc="profitability['margin_percentage']"/>%).
|
||||
</t>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -8,35 +8,14 @@
|
|||
<field name="inherit_id" ref="hr_timesheet.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='section_leaves']" position="before">
|
||||
<h2>Billing</h2>
|
||||
<div name="timesheet_billing" class="row mt16 o_settings_container">
|
||||
<div class="col-12 col-lg-6 o_setting_box" id="time_billing_setting">
|
||||
<div class="o_setting_right_pane">
|
||||
<span class="o_form_label">Time Billing</span>
|
||||
<div class="text-muted">
|
||||
Sell services and invoice time spent
|
||||
</div>
|
||||
<div class="content-group" name="msg_module_sale_timesheet">
|
||||
<div class="mt8">
|
||||
<div>
|
||||
<button name="%(sale_timesheet.product_template_action_default_services)d" string="Configure your services" type="action" class="btn-link" icon="fa-arrow-right"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 o_setting_box" name="invoice_policy">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="invoice_policy" widget="upgrade_boolean"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="invoice_policy"/>
|
||||
<div class="text-muted">
|
||||
Timesheets taken into account when invoicing your time
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<block title="Billing">
|
||||
<setting string="Time Billing" help="Sell services and invoice time spent" id="time_billing_setting">
|
||||
<button name="%(sale_timesheet.product_template_action_default_services)d" string="Configure your services" type="action" class="btn-link" icon="oi-arrow-right"/>
|
||||
</setting>
|
||||
<setting help="Timesheets taken into account when invoicing your time" name="invoice_policy">
|
||||
<field name="invoice_policy" widget="upgrade_boolean"/>
|
||||
</setting>
|
||||
</block>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
|||
|
|
@ -1,29 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_order_form_inherit_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">sale.order.form.sale.timesheet</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale_project.view_order_form_inherit_sale_project"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="//button[@name='action_view_task']" position="after">
|
||||
<field name="timesheet_count" invisible="1"/>
|
||||
<button type="object"
|
||||
name="action_view_timesheet"
|
||||
class="oe_stat_button"
|
||||
icon="fa-clock-o"
|
||||
attrs="{'invisible': [('timesheet_count', '=', 0)]}"
|
||||
groups="hr_timesheet.group_hr_timesheet_user">
|
||||
<div class="o_field_widget o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="timesheet_total_duration" class="mr4" widget="statinfo" nolabel="1"/>
|
||||
<field name="timesheet_encode_uom_id" options="{'no_open': True}"/>
|
||||
</span>
|
||||
<span class="o_stat_text">Recorded</span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_order_form_inherit_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">sale.order.form.sale.timesheet</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale_project.view_order_form_inherit_sale_project"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_view_milestone" position="before">
|
||||
<button
|
||||
name="action_view_timesheet"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-clock-o"
|
||||
invisible="not show_hours_recorded_button"
|
||||
groups="hr_timesheet.group_hr_timesheet_user"
|
||||
>
|
||||
<div class="o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="timesheet_total_duration" class="mr4"/>
|
||||
<field name="timesheet_encode_uom_id" options="{'no_open': True}"/>
|
||||
</span>
|
||||
<span class="o_stat_text">Recorded</span>
|
||||
</div>
|
||||
</button>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -2,20 +2,19 @@
|
|||
<odoo>
|
||||
|
||||
<template id="sale_order_portal_content_inherit" inherit_id="sale.sale_order_portal_template">
|
||||
<xpath expr="//li[.//a[@id='print_invoice_report']]" position="after">
|
||||
<li t-if="sale_order.timesheet_count > 0 and sale_order.state in ('sale', 'done')" class="list-group-item flex-grow-1">
|
||||
<div class="btn-toolbar flex-sm-nowrap justify-content-center">
|
||||
<div class="btn-group">
|
||||
<a t-att-href="'/my/timesheets?search_in=so&search=%s' % sale_order.name">View Timesheets</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<xpath expr="//t[@t-set='entries']/div/div/div[hasclass('o_download_pdf')]" position="inside">
|
||||
<t t-if="sale_order.timesheet_count > 0 and sale_order.state == 'sale' and sale_order.env['account.analytic.line']._show_portal_timesheets()">
|
||||
<a class="btn btn-light flex-grow-1" t-att-href="'/my/timesheets?search_in=so&search=%s' % sale_order.name" title="View Timesheets" target="_blank" role="button">View Timesheets</a>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_timesheets_inherit" inherit_id="hr_timesheet.portal_my_timesheets">
|
||||
<xpath expr="//t[@t-foreach='grouped_timesheets']/tbody/tr[hasclass('table-light')]" position="inside">
|
||||
<t t-elif="groupby == 'sol'">
|
||||
<xpath expr="//t[@t-foreach='grouped_timesheets']/tbody/tr[hasclass('table-light')]/th[hasclass('text-end')]" position="attributes">
|
||||
<attribute name="colspan">2</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//t[@t-foreach='grouped_timesheets']/tbody/tr[hasclass('table-light')]/th[hasclass('text-end')]" position="before">
|
||||
<t t-elif="groupby == 'so_line'">
|
||||
<t t-set="sol" t-value="timesheets[0].so_line"/>
|
||||
<th colspan="5">
|
||||
<t t-if="sol">
|
||||
|
|
@ -32,38 +31,22 @@
|
|||
</t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
No Sales Order Item
|
||||
</t>
|
||||
</th>
|
||||
<th colspan="1" class="text-end text-muted fw-normal">
|
||||
<t t-if="is_uom_day">
|
||||
Total: <span t-esc="timesheets._convert_hours_to_days(hours_spent)" t-options='{"widget": "timesheet_uom"}'/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
Total: <span t-esc="hours_spent" t-options='{"widget": "float_time"}'/>
|
||||
Not Billed
|
||||
</t>
|
||||
</th>
|
||||
</t>
|
||||
<t t-elif="groupby == 'so'">
|
||||
<t t-elif="groupby == 'order_id'">
|
||||
<t t-set="so" t-value="timesheets[0].order_id"/>
|
||||
<th colspan="6">
|
||||
<t t-if="so">
|
||||
<span t-field="so.display_name"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
No Sales Order
|
||||
</t>
|
||||
</th>
|
||||
<th colspan="1" class="text-end text-muted">
|
||||
<t t-if="is_uom_day">
|
||||
Total: <span t-esc="timesheets._convert_hours_to_days(hours_spent)" t-options='{"widget": "timesheet_uom"}'/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
Total: <span t-esc="hours_spent" t-options='{"widget": "float_time"}'/>
|
||||
Not Billed
|
||||
</t>
|
||||
</th>
|
||||
</t>
|
||||
<t t-elif="groupby == 'invoice'">
|
||||
<t t-elif="groupby == 'timesheet_invoice_id'">
|
||||
<t t-set="invoice" t-value="timesheets.timesheet_invoice_id"/>
|
||||
<th colspan="6">
|
||||
<t t-if="invoice">
|
||||
|
|
@ -73,42 +56,37 @@
|
|||
No Invoice
|
||||
</t>
|
||||
</th>
|
||||
<th colspan="1" class="text-end text-muted">
|
||||
<t t-if="is_uom_day">
|
||||
Total: <span t-esc="timesheets._convert_hours_to_days(hours_spent)" t-options='{"widget": "timesheet_uom"}'/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
Total: <span t-esc="hours_spent" t-options='{"widget": "float_time"}'/>
|
||||
</t>
|
||||
</th>
|
||||
</t>
|
||||
</xpath>
|
||||
<xpath expr="//thead/tr/th[@t-if='is_uom_day']" position="before">
|
||||
<th t-if="not groupby == 'sol'">Sales Order Item</th>
|
||||
</xpath>
|
||||
<th name="t_label" position="before">
|
||||
<th t-if="not groupby == 'so_line'">Sales Order Item</th>
|
||||
<th t-if="not groupby == 'timesheet_invoice_id'">Invoice</th>
|
||||
</th>
|
||||
<xpath expr="//tbody//td[hasclass('text-end')]" position="before">
|
||||
<td t-if="not groupby == 'sol'"><span t-field="timesheet.so_line" t-att-title="timesheet.so_line.display_name"></span></td>
|
||||
<td t-if="not groupby == 'so_line' and timesheets[0].env['account.analytic.line']._show_portal_timesheets()">
|
||||
<span t-if="timesheet.so_line" t-field="timesheet.so_line" t-att-title="timesheet.so_line.display_name"></span>
|
||||
<span t-else="" class="text-muted">Non-billable</span>
|
||||
</td>
|
||||
<td t-if="not groupby == 'timesheet_invoice_id'"><span t-field="timesheet.timesheet_invoice_id" t-att-title="timesheet.timesheet_invoice_id.display_name"></span></td>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_invoice_page_inherit" inherit_id="account.portal_invoice_page">
|
||||
<xpath expr="//t[@t-set='entries']/ul/li[.//a[@id='print_invoice_report']]" position="after">
|
||||
<li class="list-group-item flex-grow-1">
|
||||
<div class="btn-toolbar flex-sm-nowrap justify-content-center">
|
||||
<div class="btn-group mb-1">
|
||||
<a t-if="invoice.move_type == 'out_invoice' and invoice.state in ('draft', 'posted') and invoice.timesheet_count > 0"
|
||||
target="_blank" t-att-href="'/my/timesheets?search_in=invoice&search=%s' % invoice.name">View Timesheets</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<xpath expr="//t[@t-set='entries']/div/div/div[hasclass('o_download_pdf')]" position="after">
|
||||
<t t-if="invoice.timesheet_count > 0 and invoice.env['account.analytic.line']._show_portal_timesheets()">
|
||||
<t t-set="search_value" t-value="invoice.name"/>
|
||||
<t t-if="invoice.state == 'draft'" t-set="search_value" t-value="invoice.id"/>
|
||||
<a t-if="invoice.move_type == 'out_invoice' and invoice.state in ('draft', 'posted') and invoice.timesheet_count > 0"
|
||||
target="_blank" t-att-href="'/my/timesheets?search_in=invoice&search=%s' % search_value" class="btn btn-light" role="button" title="View Timesheet">View Timesheets</a>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_my_task_inherit" inherit_id="project.portal_my_task">
|
||||
<xpath expr="//div[@name='portal_my_task_second_column']" position="inside">
|
||||
<t t-if="task.project_id.allow_billable">
|
||||
<t t-if="task.project_id.allow_billable and env.user.has_group('sales_team.group_sale_salesman')">
|
||||
<div t-if="task.sale_order_id"><strong>Sales Order:</strong>
|
||||
<span t-if="so_accessible"><a t-attf-href="/my/orders/{{ task.sale_order_id.id }}" t-field="task.sale_order_id"></a></span>
|
||||
<span t-if="so_accessible"><a t-attf-href="{{ task.sale_order_id.access_url }}" t-field="task.sale_order_id"></a></span>
|
||||
<span t-else="" t-field="task.sale_order_id"></span>
|
||||
</div>
|
||||
<div t-if="invoices_accessible"><strong>Invoices:</strong>
|
||||
|
|
@ -125,20 +103,11 @@
|
|||
<div t-if="task.sale_line_id.untaxed_amount_invoiced > 0"><strong>Invoiced:</strong>
|
||||
<span t-field="task.sale_line_id.untaxed_amount_invoiced"/>
|
||||
</div>
|
||||
<div t-if="task.sale_line_id.untaxed_amount_to_invoice > 0"><strong>To invoice:</strong>
|
||||
<div name="amount_due" t-if="task.sale_line_id.untaxed_amount_to_invoice > 0"><strong>Amount Due:</strong>
|
||||
<span t-field="task.sale_line_id.untaxed_amount_to_invoice"/>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="portal_timesheet_table_inherit" inherit_id="hr_timesheet.portal_timesheet_table">
|
||||
<xpath expr="//div[@name='planned_time']" position="after">
|
||||
<span t-if="task.allow_billable and task.sale_line_id and task.sale_line_id.remaining_hours_available" t-attf-class="{{task.remaining_hours_so < 0 and 'text-danger' or ''}}">
|
||||
<div t-if="is_uom_day">Remaining Days on SO: <span t-esc="timesheets._convert_hours_to_days(task.remaining_hours_so)" t-options='{"widget": "timesheet_uom"}'/></div>
|
||||
<div t-else="">Remaining Hours on SO: <span t-esc="task.remaining_hours_so" t-options='{"widget": "float_time"}'/></div>
|
||||
</span>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue