[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:
hiroh-odoo
2023-03-31 17:02:24 +02:00
parent 5f8c5deeb5
commit 0e9498a345
7 changed files with 22 additions and 9 deletions
+9 -3
View File
@@ -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):
+1 -2
View File
@@ -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"/>
+1 -1
View File
@@ -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>