[IMP] project,sale_timesheet: improve generic ux
Purpose of this commit is to improve the generic usage of the project app. So in this commit done the following changes: - add done task count field in milestone and display it in milestone form view stat button all tasks under this milestone and the done tasks of the milestone. - rename 'project.project' form view field lable from 'Name of the tasks' to 'Name of the Tasks'. - add 'invoiced' column in the project update description under the sales section. - remove helper for 'project.project' name field in form view. - add a placeholder in the 'project.task' form view. task-3073860 closes odoo/odoo#107076 Related: odoo/enterprise#34593 Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
This commit is contained in:
@@ -25,6 +25,7 @@ class ProjectMilestone(models.Model):
|
||||
is_deadline_exceeded = fields.Boolean(compute="_compute_is_deadline_exceeded")
|
||||
is_deadline_future = fields.Boolean(compute="_compute_is_deadline_future")
|
||||
task_count = fields.Integer('# of Tasks', compute='_compute_task_count', groups='project.group_project_milestone')
|
||||
done_task_count = fields.Integer('# of Done Tasks', compute='_compute_task_count', groups='project.group_project_milestone')
|
||||
can_be_marked_as_done = fields.Boolean(compute='_compute_can_be_marked_as_done', groups='project.group_project_milestone')
|
||||
|
||||
@api.depends('is_reached')
|
||||
@@ -45,10 +46,15 @@ class ProjectMilestone(models.Model):
|
||||
|
||||
@api.depends('task_ids.milestone_id')
|
||||
def _compute_task_count(self):
|
||||
task_read_group = self.env['project.task']._read_group([('milestone_id', 'in', self.ids), ('allow_milestones', '=', True)], ['milestone_id'], ['milestone_id'])
|
||||
task_count_per_milestone = {res['milestone_id'][0]: res['milestone_id_count'] for res in task_read_group}
|
||||
all_and_done_task_count_per_milestone = {
|
||||
group['milestone_id'][0]: (group['milestone_id_count'], group['is_closed'].count(True))
|
||||
for group in self.env['project.task']._read_group(
|
||||
[('milestone_id', 'in', self.ids), ('allow_milestones', '=', True)],
|
||||
['milestone_id', 'is_closed:array_agg'], ['milestone_id']
|
||||
)
|
||||
}
|
||||
for milestone in self:
|
||||
milestone.task_count = task_count_per_milestone.get(milestone.id, 0)
|
||||
milestone.task_count, milestone.done_task_count = all_and_done_task_count_per_milestone.get(milestone.id, (0, 0))
|
||||
|
||||
def _compute_can_be_marked_as_done(self):
|
||||
if not any(self._ids):
|
||||
|
||||
@@ -97,8 +97,7 @@ class Project(models.Model):
|
||||
def _read_group_stage_ids(self, stages, domain, order):
|
||||
return self.env['project.project.stage'].search([], order=order)
|
||||
|
||||
name = fields.Char("Name", index='trigram', required=True, tracking=True, translate=True, default_export_compatible=True,
|
||||
help="Name of your project. It can be anything you want e.g. the name of a customer or a service.")
|
||||
name = fields.Char("Name", index='trigram', required=True, tracking=True, translate=True, default_export_compatible=True)
|
||||
description = fields.Html(help="Description to provide more information and context about this project")
|
||||
active = fields.Boolean(default=True,
|
||||
help="If the active field is set to False, it will allow you to hide the project without removing it.")
|
||||
|
||||
@@ -18,9 +18,13 @@
|
||||
>
|
||||
<div class="o_form_field o_stat_info">
|
||||
<span class="o_stat_value">
|
||||
<field name="task_count" widget="statinfo" nolabel="1"/>
|
||||
<field name="task_count" nolabel="1"/>
|
||||
<span class="text-secondary fw-normal"> Tasks</span>
|
||||
</span>
|
||||
<span class="o_stat_value">
|
||||
<field name="done_task_count" nolabel="1"/>
|
||||
<span class="text-secondary fw-normal"> Done</span>
|
||||
</span>
|
||||
<span class="o_stat_text">Tasks</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="label_tasks" string="Name of the tasks" placeholder="e.g. Tasks"/>
|
||||
<field name="label_tasks" string="Name of the Tasks" placeholder="e.g. Tasks"/>
|
||||
<field name="partner_id" widget="res_partner_many2one"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
|
||||
@@ -368,7 +368,7 @@
|
||||
name="task_properties" nolabel="1" columns="2" hideKanbanOption="1"/>
|
||||
<notebook>
|
||||
<page name="description_page" string="Description">
|
||||
<field name="description" type="html" options="{'collaborative': true, 'resizable': false}" placeholder="Task description..."/>
|
||||
<field name="description" type="html" options="{'collaborative': true, 'resizable': false}" placeholder="Add details about this task..."/>
|
||||
</page>
|
||||
<page name="sub_tasks_page" string="Sub-tasks" attrs="{'invisible': [('allow_subtasks', '=', False)]}">
|
||||
<field name="child_ids"
|
||||
|
||||
@@ -47,12 +47,14 @@ class ProjectUpdate(models.Model):
|
||||
if sol.product_uom.category_id == company_uom.category_id or is_unit:
|
||||
product_uom_qty = sol.product_uom._compute_quantity(sol.product_uom_qty, company_uom, raise_if_failure=False)
|
||||
qty_delivered = sol.product_uom._compute_quantity(sol.qty_delivered, company_uom, raise_if_failure=False)
|
||||
qty_invoiced = sol.product_uom._compute_quantity(sol.qty_invoiced, company_uom, raise_if_failure=False)
|
||||
unit = sol.product_uom if is_unit else company_uom
|
||||
services.append({
|
||||
'name': name_by_sol[sol.id],
|
||||
'sold_value': product_uom_qty,
|
||||
'effective_value': qty_delivered,
|
||||
'remaining_value': product_uom_qty - qty_delivered,
|
||||
'invoiced_value': qty_invoiced,
|
||||
'unit': unit.name,
|
||||
'is_unit': is_unit,
|
||||
'is_hour': unit == product_uom_hour,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<td style="font-weight: bolder">Sold</td>
|
||||
<td style="font-weight: bolder">Delivered</td>
|
||||
<td style="font-weight: bolder">Remaining</td>
|
||||
<td style="font-weight: bolder">Invoiced</td>
|
||||
</thead>
|
||||
<tr t-foreach="services['data']" t-as="service">
|
||||
<t t-set="is_unit" t-value="service['is_unit']"/>
|
||||
@@ -20,6 +21,7 @@
|
||||
<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>
|
||||
<td t-attf-class="#{ 'fst-italic' if is_unit else ''}" style="text-align: right; vertical-align: middle;"><t t-out="format_value(service['invoiced_value'], service['is_hour'])"/> <t t-out="service['unit']"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
Reference in New Issue
Block a user