[IMP] project: improve the UX of the app
Generic UX improvements for the project app. task-2501760 See odoo/enterprise#18819 closes odoo/odoo#71232 Signed-off-by: LTU-Odoo <IT-Ideas@users.noreply.github.com>
This commit is contained in:
@@ -194,6 +194,9 @@ class Task(models.Model):
|
||||
'name': _('Timesheets'),
|
||||
'res_model': 'account.analytic.line',
|
||||
'view_mode': 'list,form',
|
||||
'context': {
|
||||
'default_project_id': self.project_id.id
|
||||
},
|
||||
'domain': [('project_id', '!=', False), ('task_id', 'in', tasks.ids)],
|
||||
}
|
||||
|
||||
|
||||
@@ -175,9 +175,9 @@
|
||||
</span>
|
||||
<field name="effective_hours" widget="timesheet_uom" nolabel="1"/>
|
||||
|
||||
<button name="action_view_subtask_timesheet" type="object" class="o_td_label o_form_label o_form_subtask_button oe_inline oe_link mr-0" attrs="{'invisible' : ['|', ('allow_subtasks', '=', False), ('subtask_effective_hours', '=', 0.0)]}">
|
||||
<span class="text-nowrap" attrs="{'invisible' : [('encode_uom_in_days', '=', True)]}">Sub-tasks Hours Spent</span>
|
||||
<span class="text-nowrap" attrs="{'invisible' : [('encode_uom_in_days', '=', False)]}">Sub-tasks Days Spent</span>
|
||||
<button name="action_view_subtask_timesheet" type="object" class="o_form_subtask_button oe_inline oe_link" attrs="{'invisible' : ['|', ('allow_subtasks', '=', False), ('subtask_effective_hours', '=', 0.0)]}">
|
||||
<span class="text-nowrap" attrs="{'invisible' : [('encode_uom_in_days', '=', True)]}">Hours Spent on Sub-tasks:</span>
|
||||
<span class="text-nowrap" attrs="{'invisible' : [('encode_uom_in_days', '=', False)]}">Days Spent on Sub-tasks:</span>
|
||||
</button>
|
||||
<field name="subtask_effective_hours" class="mt-2" widget="timesheet_uom"
|
||||
attrs="{'invisible' : ['|', ('allow_subtasks', '=', False), ('subtask_effective_hours', '=', 0.0)]}" nolabel="1"/>
|
||||
@@ -223,9 +223,9 @@
|
||||
<field name="allow_subtasks" invisible="1"/>
|
||||
<field name="planned_hours" widget="timesheet_uom_no_toggle" sum="Initially Planned Hours" optional="hide"/>
|
||||
<field name="effective_hours" widget="timesheet_uom" sum="Effective Hours" optional="show"/>
|
||||
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress >= 100" decoration-warning="progress >= 80 and progress < 100"/>
|
||||
<field name="subtask_effective_hours" widget="timesheet_uom" attrs="{'invisible' : [('allow_subtasks', '=', False)]}" optional="hide"/>
|
||||
<field name="total_hours_spent" widget="timesheet_uom" attrs="{'invisible' : [('allow_subtasks', '=', False)]}" optional="hide"/>
|
||||
<field name="remaining_hours" widget="timesheet_uom" sum="Remaining Hours" optional="hide" decoration-danger="progress >= 100" decoration-warning="progress >= 80 and progress < 100"/>
|
||||
<field name="progress" widget="progressbar" optional="show" groups="hr_timesheet.group_hr_timesheet_user"/>
|
||||
</field>
|
||||
</field>
|
||||
@@ -281,6 +281,9 @@
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="project.view_task_search_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='my_tasks']" position='after'>
|
||||
<filter string="My Team's Tasks" name="my_team_tasks" domain="[('user_id.employee_parent_id.user_id', '=', uid)]"/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='late']" position='after'>
|
||||
<filter string="Tasks in Overtime" name="overtime" domain="[('overtime', '>', 0)]"/>
|
||||
</xpath>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
<group>
|
||||
<field name="task_id" invisible="True"/>
|
||||
<field name="time_spent" string="Duration" class="oe_inline" widget="float_time" required="True"/>
|
||||
<field name="description" widget="text" placeholder="Describe your activity..."/>
|
||||
</group>
|
||||
<field name="description" widget="text" nolabel="1" placeholder="Describe your activity..." />
|
||||
<footer>
|
||||
<button string="Save" type="object" name="save_timesheet" class="btn btn-primary" data-hotkey="q"/>
|
||||
<button string="Delete" type="object" name="action_delete_timesheet" class="btn btn-secondary" data-hotkey="w"/>
|
||||
|
||||
@@ -730,7 +730,7 @@ class Task(models.Model):
|
||||
index=True, tracking=True)
|
||||
partner_id = fields.Many2one('res.partner',
|
||||
string='Customer',
|
||||
compute='_compute_partner_id', recursive=True, store=True, readonly=False,
|
||||
compute='_compute_partner_id', recursive=True, store=True, readonly=False, tracking=True,
|
||||
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
partner_is_company = fields.Boolean(related='partner_id.is_company', readonly=True)
|
||||
commercial_partner_id = fields.Many2one(related='partner_id.commercial_partner_id')
|
||||
@@ -1491,7 +1491,7 @@ class Task(models.Model):
|
||||
'name': 'Tasks in Recurrence',
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'project.task',
|
||||
'view_mode': 'tree,form',
|
||||
'view_mode': 'tree,form,kanban,calendar,pivot,graph,gantt,activity,map',
|
||||
'domain': [('recurrence_id', 'in', self.recurrence_id.ids)],
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,17 @@ const ProjectCalendarController = CalendarController.extend({
|
||||
_renderButtonsParameters() {
|
||||
return Object.assign({}, this._super(...arguments), {scaleDrop: true});
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {OdooEvent} event
|
||||
*/
|
||||
_onChangeDate: function (event) {
|
||||
this._super.apply(this, arguments);
|
||||
this.model.setScale('month');
|
||||
this.model.setDate(event.data.date);
|
||||
this.reload();
|
||||
},
|
||||
});
|
||||
|
||||
export const ProjectCalendarView = CalendarView.extend({
|
||||
|
||||
@@ -51,14 +51,13 @@ kanbanExamplesRegistry.add('project', {
|
||||
}, {
|
||||
name: _lt('Agile Scrum'),
|
||||
columns: [_lt('Backlog'), _lt('Sprint Backlog'), _lt('Sprint in Progress'), _lt('Sprint Complete'), _lt('Old Completed Sprint')],
|
||||
description: escFormat(_lt('Waiting for the next stage: use %s and %s bullets. %s'), greenBullet, redBullet, descriptionActivities),
|
||||
description: escFormat(_lt('Use %s and %s bullets to indicate the status of a task. %s'), greenBullet, redBullet, descriptionActivities),
|
||||
bullets: [greenBullet, redBullet],
|
||||
}, {
|
||||
name: _lt('Digital Marketing'),
|
||||
columns: [_lt('Ideas'), _lt('Researching'), _lt('Writing'), _lt('Editing'), _lt('Done')],
|
||||
description: escFormat(_lt('Everyone can propose ideas, and the Editor marks the best ones ' +
|
||||
'as %s. Attach all documents or links to the task directly, to have all information about ' +
|
||||
'a research centralized. %s'), greenBullet, descriptionActivities),
|
||||
'as %s. Attach all documents or links to the task directly, to have all research information centralized. %s'), greenBullet, descriptionActivities),
|
||||
bullets: [greenBullet, redBullet],
|
||||
}, {
|
||||
name: _lt('Customer Feedback'),
|
||||
@@ -71,7 +70,7 @@ kanbanExamplesRegistry.add('project', {
|
||||
name: _lt('Getting Things Done (GTD)'),
|
||||
columns: [_lt('Inbox'), _lt('Today'), _lt('This Week'), _lt('This Month'), _lt('Long Term')],
|
||||
description: escFormat(_lt('Fill your Inbox easily with the email gateway. Periodically review your ' +
|
||||
'Inbox and schedule tasks by moving them to others columns. Every day, you review the ' +
|
||||
'Inbox and schedule tasks by moving them to other columns. Every day, you review the ' +
|
||||
'%s column to move important tasks %s. Every Monday, you review the %s column. %s'), _lt('"This Week"'), _lt('"Today"'), _lt('"This Month"'), descriptionActivities),
|
||||
}, {
|
||||
name: _lt('Consulting'),
|
||||
@@ -91,8 +90,8 @@ kanbanExamplesRegistry.add('project', {
|
||||
name: _lt('T-shirt Printing'),
|
||||
columns: [_lt('New Orders'), _lt('Logo Design'), _lt('To Print'), _lt('Done')],
|
||||
description: escFormat(_lt('Communicate with customers on the task using the email gateway. ' +
|
||||
'Attach logo designs to the task, so that information flow from designers to the workers ' +
|
||||
'who print the t-shirt. Organize priorities amongst orders %s using the icon. %s'), star, descriptionActivities),
|
||||
'Attach logo designs to the task, so that information flows from designers to the workers ' +
|
||||
'who print the t-shirt. Organize priorities amongst orders using the %s icon. %s'), star, descriptionActivities),
|
||||
bullets: [star],
|
||||
}, {
|
||||
name: _lt('Design'),
|
||||
@@ -111,7 +110,7 @@ kanbanExamplesRegistry.add('project', {
|
||||
bullets: [greenBullet, redBullet, star, clock],
|
||||
}, {
|
||||
name: _lt('Podcast and Video Production'),
|
||||
columns: [_lt('Research'), _lt('Script'), _lt('Recording'), _lt('Mixing'), _lt('Publishing')],
|
||||
columns: [_lt('Research'), _lt('Script'), _lt('Recording'), _lt('Mixing'), _lt('Published')],
|
||||
description: description,
|
||||
bullets: [greenBullet, redBullet, star, clock],
|
||||
}],
|
||||
|
||||
@@ -19,16 +19,19 @@
|
||||
<field name="name" string="Task"/>
|
||||
<field name="tag_ids"/>
|
||||
<field name="user_id"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="stage_id"/>
|
||||
<field string="Project" name="display_project_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="parent_id"/>
|
||||
<filter string="My Tasks" name="my_tasks" domain="[('user_id', '=', uid)]"/>
|
||||
<filter string="Followed Tasks" name="my_followed_tasks" domain="[('message_is_follower', '=', True)]" />
|
||||
<filter string="Unassigned" name="unassigned" domain="[('user_id', '=', False)]"/>
|
||||
<separator/>
|
||||
<filter string="Starred" name="starred" domain="[('priority', 'in', [0, 1])]"/>
|
||||
<separator/>
|
||||
<filter string="Late Tasks" name="late" domain="[('date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<filter string="Rated tasks" name="rating_task" domain="[('rating_last_value', '!=', 0.0)]" groups="project.group_project_rating"/>
|
||||
<separator/>
|
||||
<filter string="Rated Tasks" name="rating_task" domain="[('rating_last_value', '!=', 0.0)]" groups="project.group_project_rating"/>
|
||||
<separator/>
|
||||
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction', '=', True)]"/>
|
||||
<separator/>
|
||||
@@ -45,12 +48,30 @@
|
||||
<filter string="Stage" name="stage" context="{'group_by': 'stage_id'}"/>
|
||||
<filter string="Assigned to" name="user" context="{'group_by': 'user_id'}"/>
|
||||
<filter string="Project" name="project" context="{'group_by': 'project_id'}"/>
|
||||
<filter string="Customer" name="customer" context="{'group_by': 'partner_id'}"/>
|
||||
<filter string="Kanban State" name="kanban_state" context="{'group_by': 'kanban_state'}"/>
|
||||
<filter string="Deadline" name="date_deadline" context="{'group_by': 'date_deadline'}"/>
|
||||
<filter string="Creation Date" name="group_create_date" context="{'group_by': 'create_date'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_task_search_form_extended" model="ir.ui.view">
|
||||
<field name="name">project.task.search.form.extended</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="view_task_search_form"></field>
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='unassigned']" position="after">
|
||||
<separator/>
|
||||
<filter string="My Projects" name="my_projects" domain="[('project_id.user_id', '=', uid)]"/>
|
||||
<filter string="My Favorite Projects" name="my_favorite_projects" domain="[('project_id.favorite_user_ids', 'in', [uid])]"/>
|
||||
<filter string="Followed Projects" name="my_followed_projects" domain="[('project_id.message_is_follower', '=', True)]"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="act_project_project_2_project_task_all" model="ir.actions.act_window">
|
||||
<field name="name">Tasks</field>
|
||||
<field name="res_model">project.task</field>
|
||||
@@ -732,7 +753,6 @@
|
||||
attrs="{'invisible' : [('allow_subtasks', '=', False)]}"
|
||||
groups="base.group_no_one"
|
||||
/>
|
||||
<field name="recurring_task" attrs="{'invisible': ['|', ('allow_recurring_tasks', '=', False), ('parent_id', '!=', False)]}" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="active" invisible="1"/>
|
||||
@@ -740,6 +760,7 @@
|
||||
<field name="partner_phone" widget="phone" attrs="{'invisible': True}"/>
|
||||
<field name="date_deadline" attrs="{'invisible': [('is_closed', '=', True)]}"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}"/>
|
||||
<field name="recurring_task" attrs="{'invisible': ['|', ('allow_recurring_tasks', '=', False), ('parent_id', '!=', False)]}" />
|
||||
<field name="legend_blocked" invisible="1"/>
|
||||
<field name="legend_normal" invisible="1"/>
|
||||
<field name="legend_done" invisible="1"/>
|
||||
@@ -769,6 +790,23 @@
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page name="task_dependencies" string="Blocked By" attrs="{'invisible': [('allow_task_dependencies', '=', False)]}" groups="project.group_project_task_dependencies">
|
||||
<field name="depend_on_ids" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="is_closed" invisible="1" />
|
||||
<field name="name" />
|
||||
<field name="project_id" optional="hide" />
|
||||
<field name="user_id" widget="many2one_avatar_user" optional="show"/>
|
||||
<field name="company_id" optional="hide" groups="base.group_multi_company" />
|
||||
<field name="activity_ids" widget="list_activity" optional="hide"/>
|
||||
<field name="date_deadline" attrs="{'invisible': [('is_closed', '=', True)]}" optional="show" />
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}" optional="hide"/>
|
||||
<field name="kanban_state" widget="state_selection" optional="hide" />
|
||||
<field name="stage_id" optional="show" />
|
||||
<button class="oe_link float-right" string="View Task" name="action_open_task" type="object"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page name="recurrence" string="Recurrence" attrs="{'invisible': [('recurring_task', '=', False)]}">
|
||||
<group>
|
||||
<group>
|
||||
@@ -814,7 +852,7 @@
|
||||
<field name="email_from" invisible="1"/>
|
||||
<field name="email_cc" groups="base.group_no_one"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="displayed_image_id" groups="base.group_no_one"/>
|
||||
<field name="displayed_image_id" groups="base.group_no_one" options="{'no_create': True}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date_assign" groups="base.group_no_one"/>
|
||||
@@ -830,23 +868,6 @@
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page name="task_dependencies" string="Blocked By" attrs="{'invisible': [('allow_task_dependencies', '=', False)]}" groups="project.group_project_task_dependencies">
|
||||
<field name="depend_on_ids" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="is_closed" invisible="1" />
|
||||
<field name="name" />
|
||||
<field name="project_id" optional="hide" />
|
||||
<field name="user_id" widget="many2one_avatar_user" optional="show"/>
|
||||
<field name="company_id" optional="hide" groups="base.group_multi_company" />
|
||||
<field name="activity_ids" widget="list_activity" optional="hide"/>
|
||||
<field name="date_deadline" attrs="{'invisible': [('is_closed', '=', True)]}" optional="show" />
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}" optional="hide"/>
|
||||
<field name="kanban_state" widget="state_selection" optional="hide" />
|
||||
<field name="stage_id" optional="show" />
|
||||
<button class="oe_link float-right" string="View Task" name="action_open_task" type="object"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
@@ -949,11 +970,6 @@
|
||||
<a t-if="widget.editable" role="menuitem" type="set_cover" class="dropdown-item" data-field="displayed_image_id">Set Cover Image</a>
|
||||
<a name="%(portal.portal_share_action)d" role="menuitem" type="action" class="dropdown-item">Share</a>
|
||||
<a t-if="widget.editable" role="menuitem" type="edit" class="dropdown-item">Edit</a>
|
||||
<a t-if="widget.editable" role="menuitem" class="dropdown-item" name="toggle_active" type="object">
|
||||
<t t-if="record.active.raw_value">Archive</t>
|
||||
<t t-if="!record.active.raw_value">Restore</t>
|
||||
</a>
|
||||
<a t-if="widget.deletable" role="menuitem" type="delete" class="dropdown-item">Delete</a>
|
||||
<div role="separator" class="dropdown-divider"></div>
|
||||
<ul class="oe_kanban_colorpicker" data-field="color"/>
|
||||
</div>
|
||||
@@ -1002,6 +1018,7 @@
|
||||
<field name="is_closed" invisible="1" />
|
||||
<field name="allow_subtasks" invisible="1" />
|
||||
<field name="sequence" invisible="1" readonly="1"/>
|
||||
<field name="priority" widget="priority" optional="show" nolabel="1"/>
|
||||
<field name="name" widget="name_with_subtask_count"/>
|
||||
<field name="child_text" invisible="1"/>
|
||||
<field name="project_id" optional="show" readonly="1"/>
|
||||
@@ -1012,7 +1029,7 @@
|
||||
<field name="activity_ids" widget="list_activity" optional="show"/>
|
||||
<field name="date_deadline" optional="hide" widget="remaining_days" attrs="{'invisible': [('is_closed', '=', True)]}"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}" optional="show"/>
|
||||
<field name="kanban_state" widget="state_selection" optional="hide" readonly="1"/>
|
||||
<field name="kanban_state" widget="selection" optional="hide" />
|
||||
<field name="stage_id" invisible="context.get('set_visible',False)" optional="show" readonly="not context.get('default_project_id')"/>
|
||||
<field name="recurrence_id" invisible="1" />
|
||||
</tree>
|
||||
@@ -1041,12 +1058,15 @@
|
||||
<field eval="2" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar date_start="date_deadline" string="Tasks" mode="month" color="user_id" event_limit="5"
|
||||
hide_time="true" quick_add="False" js_class="project_calendar">
|
||||
<field name="user_id" avatar_field="avatar_128" filters="1"/>
|
||||
<field name="date_deadline"/>
|
||||
hide_time="true" js_class="project_calendar" event_open_popup="true" quick_add="false">
|
||||
<field name="project_id"/>
|
||||
<field name="user_id" avatar_field="avatar_128" filters="1"/>
|
||||
<field name="partner_id" attrs="{'invisible': [('partner_id', '=', False)]}"/>
|
||||
<field name="priority" widget="priority"/>
|
||||
<field name="date_deadline"/>
|
||||
<field name="tag_ids" widget="many2many_tags" attrs="{'invisible': [('tag_ids', '=', [])]}"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="kanban_state"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
@@ -1059,8 +1079,11 @@
|
||||
<field name="project_id" type="row"/>
|
||||
<field name="stage_id" type="col"/>
|
||||
<field name="color" invisible="1"/>
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="rating_last_value" type="measure" string="Rating (/5)"/>
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="planned_hours" widget="float_time"/>
|
||||
<field name="working_hours_close" widget="float_time"/>
|
||||
<field name="working_hours_open" widget="float_time"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
@@ -1120,7 +1143,7 @@
|
||||
<field name="res_model">project.task</field>
|
||||
<field name="view_mode">tree,kanban,form,calendar,pivot,graph,activity</field>
|
||||
<field name="context">{'search_default_my_tasks': 1, 'all_task': 0}</field>
|
||||
<field name="search_view_id" ref="view_task_search_form"/>
|
||||
<field name="search_view_id" ref="view_task_search_form_extended"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No tasks found. Let's create one!
|
||||
@@ -1149,7 +1172,7 @@
|
||||
<field name="name">Tasks</field>
|
||||
<field name="res_model">project.task</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="search_view_id" ref="view_task_search_form"/>
|
||||
<field name="search_view_id" ref="view_task_search_form_extended"/>
|
||||
</record>
|
||||
|
||||
<record id="action_view_task_overpassed_draft" model="ir.actions.act_window">
|
||||
@@ -1158,7 +1181,7 @@
|
||||
<field name="view_mode">tree,form,calendar,graph,kanban</field>
|
||||
<field name="domain">[('is_closed', '=', False), ('date_deadline','<',time.strftime('%Y-%m-%d')), ('display_project_id', '!=', False)]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
<field name="search_view_id" ref="view_task_search_form"/>
|
||||
<field name="search_view_id" ref="view_task_search_form_extended"/>
|
||||
</record>
|
||||
|
||||
<!-- Opening task when double clicking on project -->
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
<xpath expr="//filter[@name='resource']" position="after">
|
||||
<filter string="Project" name="groupby_project" context="{'group_by': 'parent_res_name'}"/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='responsible']" position="replace"></xpath>
|
||||
<xpath expr="/search" position="inside">
|
||||
<filter string="Last 30 Days" name="rating_last_30_days" domain="[
|
||||
('write_date', '>=', (datetime.datetime.combine(context_today() + relativedelta(days=-30), datetime.time(0,0,0)).to_utc()).strftime('%Y-%m-%d %H:%M:%S'))]"
|
||||
|
||||
@@ -61,7 +61,7 @@ class ProjectTask(models.Model):
|
||||
sale_order_id = fields.Many2one('sale.order', 'Sales Order', compute='_compute_sale_order_id', store=True, help="Sales order to which the task is linked.")
|
||||
sale_line_id = fields.Many2one(
|
||||
'sale.order.line', 'Sales Order Item', domain="[('company_id', '=', company_id), ('is_service', '=', True), ('order_partner_id', 'child_of', commercial_partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done'])]",
|
||||
compute='_compute_sale_line', recursive=True, store=True, readonly=False, copy=False,
|
||||
compute='_compute_sale_line', recursive=True, store=True, readonly=False, copy=False, tracking=True,
|
||||
help="Sales Order Item to which the time spent on this task will be added, in order to be invoiced to your customer.")
|
||||
project_sale_order_id = fields.Many2one('sale.order', string="Project's sale order", related='project_id.sale_order_id')
|
||||
invoice_count = fields.Integer("Number of invoices", related='sale_order_id.invoice_count')
|
||||
|
||||
@@ -87,9 +87,12 @@
|
||||
<field name="model">project.task</field>
|
||||
<field name="inherit_id" ref="project.view_task_search_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='stage_id']" position="before">
|
||||
<xpath expr="//field[@name='partner_id']" position="after">
|
||||
<field name="sale_order_id" string="Sale Order" filter_domain="['|', ('sale_order_id', 'ilike', self), ('sale_line_id', 'ilike', self)]"/>
|
||||
</xpath>
|
||||
<xpath expr="//search/group/filter[@name='customer']" position="after">
|
||||
<filter string="Sales Order Item" name="sale_order_id" context="{'group_by': 'sale_order_id'}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
<xpath expr="//header" position='inside'>
|
||||
<field name="allow_billable" invisible="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='email_cc']" position="after">
|
||||
<xpath expr="//group/field[@name='sequence']" position="before">
|
||||
<field name="analytic_account_id" groups="base.group_no_one"/>
|
||||
</xpath>
|
||||
</field>
|
||||
|
||||
Reference in New Issue
Block a user