mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-27 10:32:01 +02:00
Initial commit: Sale packages
This commit is contained in:
commit
14e3d26998
6469 changed files with 2479670 additions and 0 deletions
|
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<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="context">{
|
||||
'create': False,
|
||||
'edit': False,
|
||||
'delete': False,
|
||||
"is_timesheet": 1,
|
||||
}</field>
|
||||
<field name="domain">[('timesheet_invoice_id', '=', active_id)]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No activities found
|
||||
</p>
|
||||
<p>
|
||||
Track your working hours by projects every day and invoice this time to your customers.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<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_id" ref="hr_timesheet.hr_timesheet_line_tree"/>
|
||||
<field name="act_window_id" ref="action_timesheet_from_invoice"/>
|
||||
</record>
|
||||
|
||||
<record id="action_timesheet_from_invoice_view_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="4"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="hr_timesheet.hr_timesheet_line_form"/>
|
||||
<field name="act_window_id" ref="action_timesheet_from_invoice"/>
|
||||
</record>
|
||||
|
||||
<record id="action_timesheet_from_invoice_view_kanban" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="5"/>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="view_id" ref="hr_timesheet.view_kanban_account_analytic_line"/>
|
||||
<field name="act_window_id" ref="action_timesheet_from_invoice"/>
|
||||
</record>
|
||||
|
||||
<record id="action_timesheet_from_invoice_view_pivot" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="6"/>
|
||||
<field name="view_mode">pivot</field>
|
||||
<field name="view_id" ref="hr_timesheet.view_hr_timesheet_line_pivot"/>
|
||||
<field name="act_window_id" ref="action_timesheet_from_invoice"/>
|
||||
</record>
|
||||
|
||||
<record id="action_timesheet_from_invoice_view_graph" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="7"/>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="view_id" ref="hr_timesheet.view_hr_timesheet_line_graph"/>
|
||||
<field name="act_window_id" ref="action_timesheet_from_invoice"/>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_view_form_inherit_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">account.invoice.form.inherit.timesheet</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<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">
|
||||
<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>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="timesheet_view_search" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.search</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<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"/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='month']" position="before">
|
||||
<filter name="billable_fixed" string="Billed at a Fixed Price" domain="[('timesheet_invoice_type', '=', 'billable_fixed')]"
|
||||
groups="sales_team.group_sale_salesman"/>
|
||||
<filter name="billable_time" string="Billed on Timesheets" domain="[('timesheet_invoice_type', '=', 'billable_time')]"
|
||||
groups="sales_team.group_sale_salesman"/>
|
||||
<filter name="billable_milestones" string="Billed on Milestones" domain="[('timesheet_invoice_type', '=', 'billable_milestones')]"
|
||||
groups="sales_team.group_sale_salesman"/>
|
||||
<filter name="billable_manual" string="Billed Manually" domain="[('timesheet_invoice_type', '=', 'billable_manual')]"
|
||||
groups="sales_team.group_sale_salesman"/>
|
||||
<filter name="non_billable" string="Non-Billable" domain="[('timesheet_invoice_type', '=', 'non_billable')]"
|
||||
groups="sales_team.group_sale_salesman"/>
|
||||
<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'}"
|
||||
groups="sales_team.group_sale_salesman"/>
|
||||
<filter string="Billing Type" name="groupby_timesheet_invoice_type" domain="[]"
|
||||
context="{'group_by': 'timesheet_invoice_type'}" groups="sales_team.group_sale_salesman"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_timesheet_line_tree_inherit" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.tree.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>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_timesheet_line_form_inherit" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.form.inherit</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<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"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_timesheet_line_pivot_billing_rate" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.pivot.billing.rate</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<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="amount" string="Timesheet Costs"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_timesheet_line_graph_employee_per_date" model="ir.ui.view">
|
||||
<field name="name">account.analytic.line.graph.employee.per.date</field>
|
||||
<field name="model">account.analytic.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Timesheet" sample="1" js_class="hr_timesheet_graphview">
|
||||
<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"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Timesheet from Sales Order
|
||||
-->
|
||||
<record id="timesheet_action_from_sales_order" model="ir.actions.act_window">
|
||||
<field name="name">Timesheets</field>
|
||||
<field name="res_model">account.analytic.line</field>
|
||||
<field name="search_view_id" ref="hr_timesheet.hr_timesheet_line_search"/>
|
||||
<field name="context">{
|
||||
"is_timesheet": 1,
|
||||
}</field>
|
||||
<field name="domain">[('project_id', '!=', False)]</field>
|
||||
</record>
|
||||
|
||||
<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_id" ref="hr_timesheet.timesheet_view_tree_user"/>
|
||||
<field name="act_window_id" ref="timesheet_action_from_sales_order"/>
|
||||
</record>
|
||||
|
||||
<record id="timesheet_action_from_sales_order_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="5"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="hr_timesheet.timesheet_view_form_user"/>
|
||||
<field name="act_window_id" ref="timesheet_action_from_sales_order"/>
|
||||
</record>
|
||||
|
||||
<!-- Timesheets from Sales Order Item -->
|
||||
<record id="timesheet_action_from_sales_order_item" model="ir.actions.act_window">
|
||||
<field name="name">Timesheets</field>
|
||||
<field name="res_model">account.analytic.line</field>
|
||||
<field name="search_view_id" ref="hr_timesheet.hr_timesheet_line_search"/>
|
||||
<field name="domain">[('project_id', '!=', False), ('so_line', '=', active_id)]</field>
|
||||
<field name="context">{
|
||||
'search_default_billable_timesheet': True,
|
||||
'search_default_week': 1,
|
||||
'default_so_line': active_id,
|
||||
'default_is_so_line_edited': True,
|
||||
"is_timesheet": 1,
|
||||
}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No timesheets found. Let's create one!
|
||||
</p>
|
||||
<p>
|
||||
Keep track of your working hours by project every day and bill your customers for that time.
|
||||
</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_id" ref="hr_timesheet.timesheet_view_tree_user"/>
|
||||
<field name="act_window_id" ref="timesheet_action_from_sales_order_item"/>
|
||||
</record>
|
||||
|
||||
<record id="timesheet_action_from_sales_order_item_kanban" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="view_id" ref="hr_timesheet.view_kanban_account_analytic_line"/>
|
||||
<field name="act_window_id" ref="timesheet_action_from_sales_order_item"/>
|
||||
</record>
|
||||
|
||||
<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="act_window_id" ref="timesheet_action_from_sales_order_item"/>
|
||||
</record>
|
||||
|
||||
<record id="timesheet_action_from_sales_order_item_graph" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="view_id" ref="view_hr_timesheet_line_graph_employee_per_date"/>
|
||||
<field name="act_window_id" ref="timesheet_action_from_sales_order_item"/>
|
||||
</record>
|
||||
|
||||
<record id="timesheet_action_from_sales_order_item_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="50"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="hr_timesheet.timesheet_view_form_user"/>
|
||||
<field name="act_window_id" ref="timesheet_action_from_sales_order_item"/>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Plan
|
||||
-->
|
||||
<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="domain">[('project_id', '!=', False)]</field>
|
||||
<field name="context">{
|
||||
"is_timesheet": 1,
|
||||
}</field>
|
||||
<field name="search_view_id" ref="hr_timesheet.hr_timesheet_line_search"/>
|
||||
</record>
|
||||
|
||||
<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="domain">[('project_id', '!=', False)]</field>
|
||||
<field name="context">{
|
||||
"is_timesheet": 1,
|
||||
}</field>
|
||||
<field name="search_view_id" ref="hr_timesheet.hr_timesheet_line_search"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_product_timesheet_form" model="ir.ui.view">
|
||||
<field name="name">product.template.timesheet.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<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">
|
||||
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)]}"/>
|
||||
</div>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="product_template_view_search_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">product.template.search.timesheet</field>
|
||||
<field name="model">product.template</field>
|
||||
<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">
|
||||
<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>
|
||||
</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="search_view_id" ref="sale_timesheet.product_template_view_search_sale_timesheet"/>
|
||||
<field name="context">{'search_default_services': 1, 'default_detailed_type': 'service'}</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<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="arch" type="xml">
|
||||
<xpath expr="//field[@name='timesheet_ids']/tree" 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)]}"
|
||||
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>
|
||||
<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>
|
||||
<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)]}" />
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="project_project_view_form" model="ir.ui.view">
|
||||
<field name="name">project.project.form.inherit</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.project_invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<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}"/>
|
||||
<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>
|
||||
</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>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_project_view_kanban_inherit_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">project.project.kanban.inherit.sale.timesheet</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.view_project_kanban_inherited"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='allow_timesheets']" position="after">
|
||||
<field name="allow_billable"/>
|
||||
<field name="warning_employee_rate" invisible="1"/>
|
||||
<field name="sale_order_id" invisible="1"/>
|
||||
<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">
|
||||
<a name="action_view_all_rating" type="object">
|
||||
Customer Ratings
|
||||
</a>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- We do a separate inheritance from the base view for the SO button to give the buttons a deterministic order using priorities -->
|
||||
<record id="project_project_view_kanban_inherit_sale_timesheet_so_button" model="ir.ui.view">
|
||||
<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="arch" type="xml">
|
||||
<xpath expr="//div[hasclass('o_kanban_manage_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">
|
||||
<a name="action_view_sos" type="object">Sales Orders</a>
|
||||
</div>
|
||||
</xpath>
|
||||
</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="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"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_task_view_form_inherit_sale_timesheet" 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.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">
|
||||
<field name="pricing_type" invisible="1" groups="hr_timesheet.group_hr_timesheet_user"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='timesheet_ids']" position="attributes">
|
||||
<!-- <field name="timesheet_ids"/> is already inside a block groups="hr_timesheet.group_hr_timesheet_user" -->
|
||||
<attribute name="widget">so_line_one2many</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='timesheet_ids']/tree" position="inside">
|
||||
<!-- <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="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, 'no_open': True}"
|
||||
domain="[('is_service', '=', True), ('order_partner_id', 'child_of', parent.commercial_partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done'])]"
|
||||
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'])]"
|
||||
optional="hide"/>
|
||||
</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>
|
||||
<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>
|
||||
</t>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_task_form2_inherit_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">view.task.form2.inherit</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="sale_project.view_sale_project_inherit_form"/>
|
||||
<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>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<?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>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.sale.timesheet</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="priority" eval="1"/>
|
||||
<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>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?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>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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>
|
||||
</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'">
|
||||
<t t-set="sol" t-value="timesheets[0].so_line"/>
|
||||
<th colspan="5">
|
||||
<t t-if="sol">
|
||||
<span t-field="sol.display_name"/>
|
||||
<t t-if="sol.remaining_hours_available">
|
||||
<span class="text-muted fw-normal">
|
||||
<t t-if="is_uom_day">
|
||||
(<span t-esc="timesheets._timesheet_convert_sol_uom(sol, 'uom.product_uom_day')" t-options='{"widget": "timesheet_uom"}'></span> Days Ordered, <span t-esc="timesheets._convert_hours_to_days(sol.remaining_hours)" t-options='{"widget": "timesheet_uom"}'></span> Days Remaining)
|
||||
</t>
|
||||
<t t-else="">
|
||||
(<span t-esc="timesheets._timesheet_convert_sol_uom(sol, 'uom.product_uom_hour')" t-options='{"widget": "float_time"}'></span> Hours Ordered, <span t-esc="sol.remaining_hours" t-options='{"widget": "float_time"}'></span> Hours Remaining)
|
||||
</t>
|
||||
</span>
|
||||
</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"}'/>
|
||||
</t>
|
||||
</th>
|
||||
</t>
|
||||
<t t-elif="groupby == 'so'">
|
||||
<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"}'/>
|
||||
</t>
|
||||
</th>
|
||||
</t>
|
||||
<t t-elif="groupby == 'invoice'">
|
||||
<t t-set="invoice" t-value="timesheets.timesheet_invoice_id"/>
|
||||
<th colspan="6">
|
||||
<t t-if="invoice">
|
||||
<span t-field="invoice.display_name"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
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>
|
||||
<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>
|
||||
</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>
|
||||
</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">
|
||||
<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-else="" t-field="task.sale_order_id"></span>
|
||||
</div>
|
||||
<div t-if="invoices_accessible"><strong>Invoices:</strong>
|
||||
<span t-foreach="task.sale_order_id.invoice_ids" t-as="invoice_line">
|
||||
<t t-if="invoice_line.id in invoices_accessible">
|
||||
<a t-attf-href="/my/invoices/{{ invoice_line.id }}">
|
||||
<i t-if="invoice_line.state == 'draft'">Draft Invoice</i>
|
||||
<t t-else="" t-esc="invoice_line.name"/></a>
|
||||
<span t-if="not invoice_line_last">,</span>
|
||||
</t>
|
||||
<t t-else=""><span t-esc="invoice_line.name"></span><span t-if="not invoice_line_last">,</span></t>
|
||||
</span>
|
||||
</div>
|
||||
<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>
|
||||
<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