Project and Services mailing list archives

project@odoo-community.org

Avatar

Re: [OCA/project] project_task_scheduling: Module for automatic task planning (#419)

by Andrea Stirpe <notifications@github.com> - 22/08/2018 11:56:08

@astirpe requested changes on this pull request.


In project_task_scheduling/wizards/scheduling_wizard.py:

> +                        'datetime_start': task_interval.start_datetime,
+                        'datetime_stop': task_interval.end_datetime,
+                    })
+
+        act = self.env['ir.actions.act_window']
+        return act.for_xml_id("project_task_scheduling",
+                              'project_task_scheduling_proposal_action')
+
+    # Business methods
+    # ----------------
+    @api.multi
+    def _get_sorted_tasks(self):
+        self.ensure_one()
+
+        def task_cmp(a, b):
+            a_date_deadline = fields.Date.from_string(a.date_deadline)

This function could be working fine even without converting to datetime (no need of fields.Date.from_string())


In project_task_scheduling/wizards/scheduling_wizard.py:

> +        tz_ctx = dict(tz=employee.resource_id.user_id.tz or self.env.user.tz)
+
+        calendar = employee.resource_calendar_id.with_context(tz_ctx)
+        user = self.env.user.with_context(tz_ctx)
+        day_dt_tz = resource_model.to_naive_user_tz(start, user)
+        current_dt = day_dt_tz
+
+        call_args = dict(compute_leaves=True,
+                         resource_id=employee.resource_id.id)
+
+        if float_compare(rem_hours, 0.0, 2) not in (-1, 0):
+            # avoid infinite loops
+            for it in range(1000):
+                intervals = calendar._get_day_work_intervals(current_dt.date(),
+                                                             current_dt.time(),
+                                                             **call_args)

Please replace the old style **call_args with the explicit parameters.


In project_task_scheduling/wizards/scheduling_wizard.py:

> +        tasks_dict = {}
+        for key, interval_list in state.employees_dict.items():
+            new_list = []
+            for interval in interval_list:
+                employee = interval.data['employee']
+                new_interval = self._duplicate_interval(interval, employee)
+
+                new_list.append(new_interval)
+                tasks_dict[interval.data['task'].id] = new_interval
+
+            employees_dict[key] = new_list
+
+        return self._state_obj(tasks_list, tasks_dict, employees_dict,
+                               state.evaluation)
+
+    def _get_interval(self, hours, employee, start, stop=False):

You cold move this helper method into the hr.employee model and invoke this method from a singleton employee record.
This way you reduce a bit the code in this wizard and make the method reusable for other cases.
You may consider to move this method to module project_task_assignment. What do you think?


In project_task_scheduling/wizards/scheduling_wizard.py:

> +
+from odoo import api, fields, models
+from odoo.exceptions import ValidationError
+from odoo.tools.float_utils import float_compare
+from odoo.tools.translate import _
+
+from odoo.addons.resource.models import resource as resource_model
+
+_logger = logging.getLogger(__name__)
+
+
+class ProjectTaskSchedulingWizard(models.TransientModel):
+    _name = "project.task.scheduling.wizard"
+    _description = "Project task scheduling wizard"
+
+    _state_obj = namedtuple('State', (

Could you separate the scheduling algorithm from the wizard?
An idea could be to move the _state_obj structure and the related algorithm methods to a separate abstract model which represents the scheduling algorithm. You could then make the wizard inheriting from that model.

This way you will make the module more easy to be customized or extended.
What do you think?


In project_task_scheduling/wizards/scheduling_wizard_views.xml:

> +        <field name="name">project.task.scheduling.wizard.form</field>
+        <field name="model">project.task.scheduling.wizard</field>
+        <field name="arch" type="xml">
+            <form string="Select event to register">
+                <group col="4">
+                    <field name="date_start"/>
+                    <field name="cooling_ratio"/>
+                </group>
+                <group>
+                    <field name="task_ids" nolabel="1"/>
+                </group>
+
+                <footer>
+                    <button name="action_accept" type="object" string="Accept"
+                            class="oe_highlight"/>
+                    or

This or string is old-fashioned 😆


In project_task_scheduling/wizards/scheduling_wizard.py:

> +
+        improvements = len(states_list) - 1
+        _logger.info('improvements: %(imp)d' % {'imp': improvements})
+
+        duration = current_duration.total_seconds()
+        _logger.info('Duration: %(duration)f' % {'duration': duration})
+
+        if current_duration >= max_duration:
+            _logger.info('Stopped because Execution time >= maximum time')
+
+        it_count *= iterations
+        _logger.info('Number of iterations: %(it)d' % {'it': it_count})
+
+        _logger.info('*****************************')
+
+    def simulated_annealing(self, init_temp, final_temp, iterations,

Did you consider to adopt some external library to implement this algorithm?
Did you also consider to adopt any other different algorithms for the allocation, eg.: any algorithm for a knapsack problem optimization? I see that the algorithm you adopted is a high resource consumption one.

—
You are receiving this because you are on a team that was mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.