Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alternative workcenters #33018

Open
wants to merge 1 commit into
base: master
from

Conversation

Projects
None yet
5 participants
@Whenrow
Copy link
Contributor

commented Apr 29, 2019

Description of the issue/feature this PR addresses:

Current behavior before PR:

Desired behavior after PR is merged:

--
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr

@robodoo robodoo added the seen 🙂 label Apr 29, 2019

@C3POdoo C3POdoo added the RD label Apr 29, 2019

@robodoo robodoo added CI 🤖 and removed CI 🤖 labels Apr 30, 2019

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from 7840499 to 9c431c0 May 2, 2019

@robodoo robodoo added CI 🤖 and removed CI 🤖 labels May 2, 2019

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from 9c431c0 to d864c08 May 9, 2019

@robodoo robodoo removed the CI 🤖 label May 9, 2019

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch 2 times, most recently from c3feb22 to e11e4dd May 9, 2019

@robodoo robodoo added the CI 🤖 label May 10, 2019

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from e11e4dd to df94444 May 13, 2019

@robodoo robodoo added CI 🤖 and removed CI 🤖 labels May 13, 2019

order="date_planned_finished"
)
best_start_date = start_date
best_finished_date = start_date + relativedelta(year=MAXYEAR)

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 13, 2019

Contributor

datetime.max

to_date = from_date + relativedelta(minutes=workorder.duration_expected)
# Check interval
for wo in wos:
to_date = from_date + relativedelta(minutes=duration_expected)

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 13, 2019

Contributor

you could use dateutils

to_date = from_date + relativedelta(minutes=duration_expected)
# Check intervals
for wo in wos.filtered(lambda wo: wo.workcenter_id == workcenter):
if best_finished_date < fields.Datetime.from_string(wo.date_planned_finished):

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 13, 2019

Contributor

remove fields.Datetime.from_string(

workcenters = workorder.workcenter_id | workorder.workcenter_id.alternative_workcenter_ids

# extract already planned workorders
wos = self.env['mrp.workorder'].search([

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 13, 2019

Contributor

search_read or read_group for perf

qty = min(workorder.operation_id.batch_size, workorder.qty_production)
cycle_number = math.ceil(qty / workorder.production_id.product_qty / workcenter.capacity)
workcenter = workorder.workcenter_id
qty = min(workorder.operation_id.batch_size, workorder.qty_producing)

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 13, 2019

Contributor

qty = workorder.operation_id.batch_size

workorder.write(best_values)

# Compute start_date for next workorder
if workorder.next_work_order_id:
if (workorder.operation_id.batch == 'no') or (workorder.operation_id.batch_size >= workorder.qty_production):

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 13, 2019

Contributor

qty_producing instead of qty_production

if not to_date:
start_date = from_date + relativedelta(minutes=duration)
if has_schedule:
start_date = workcenter.resource_calendar_id.plan_hours(duration / 60.0, start_date, compute_leaves=True, resource=workcenter.resource_id)

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 13, 2019

Contributor

best_start_date

if has_schedule:
start_date = workcenter.resource_calendar_id.plan_hours(duration / 60.0, start_date, compute_leaves=True, resource=workcenter.resource_id)
else:
start_date = start_date + relativedelta(minutes=duration)

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 13, 2019

Contributor

best_start_date

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from df94444 to ab25968 May 14, 2019

@robodoo robodoo added CI 🤖 and removed CI 🤖 labels May 14, 2019

@robodoo robodoo added the CI 🤖 label May 16, 2019

wos = {}
for wc, dates in groupby_workcenter:
dates = [(date['date_planned_start'], date['date_planned_finished']) for date in dates]
wos[wc] = sorted(dates, key=itemgetter(1))

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 17, 2019

Contributor

try in search_read

for date_start, date_finished in wos.get(workcenter.id, []):
if best_finished_date < date_finished or to_date <= date_start:
# 1.workorders are ordered by date. There is no need to check the other ones
# or 2.The current time slot (from_date, to_date) intersect an existing workorder slot

This comment has been minimized.

Copy link
@amoyaux

amoyaux May 17, 2019

Contributor

remove or

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from a442815 to 4b67adf May 17, 2019

@robodoo robodoo added CI 🤖 and removed CI 🤖 labels May 17, 2019

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from 4b67adf to 2a205d8 May 20, 2019

@robodoo robodoo added CI 🤖 and removed CI 🤖 labels May 20, 2019

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from 2a205d8 to a889948 May 20, 2019

@robodoo robodoo removed the CI 🤖 label May 20, 2019

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from a889948 to d52362e May 21, 2019

@robodoo robodoo added the CI 🤖 label May 21, 2019

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from d52362e to 6a1c864 May 22, 2019

@robodoo robodoo removed the CI 🤖 label May 22, 2019

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from 6a1c864 to 262ba44 May 22, 2019

[IMP] mrp: alternative workcenters
Purpose: link workcenters that can do the same job together.
Planning a workorder will be done by choosing, among the similar
workcenters, the one that will finish the production the soonest.

This commit adds a new many2many field on the mrp.workcenter
model. Planning the workorders will:
 1. Loop on the operation's workcenter and all the alternative ones.
 2. Compute the first available work slot for each of those workcenters.
 3. Choose the soonest finished slot

Task : 1892819

@Whenrow Whenrow force-pushed the odoo-dev:master-alternative-wc-whe branch from 262ba44 to afc363a May 22, 2019

@robodoo robodoo added the CI 🤖 label May 22, 2019

workcenters = workorder.workcenter_id | workorder.workcenter_id.alternative_workcenter_ids

best_finished_date = datetime.datetime.max
best_values = {}

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

vals = {}

# get first free slot
# planning 0 hours gives the start of the next attendance
from_date = workcenter.resource_calendar_id.plan_hours(0, start_date, compute_leaves=True, resource=workcenter.resource_id, domain=[('time_type', 'in', ['leave', 'other'])])
if from_date:

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor
# If the workcenter is unavailable, try on the next one
if from_date is False:
   continue
'duration_expected': duration_expected,
}

if best_finished_date == datetime.datetime.max:

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

add a comment

# If all workcenters are unavailable, raise.
from_date = workcenter.resource_calendar_id.plan_hours(0, from_date, compute_leaves=True, resource=workcenter.resource_id)
from_date_set = True
start_date = self._get_start_date()
for workorder in self.workorder_ids:

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

you shouldn't rely on this! self.workorder_ids may not return the workorders correctly ordered
either you sort them by next_workorder_id before looping over or you enforce an order on the mrp.workorder model (currently none is enforced)


# Compute start_date for next workorder if operation allow batch producing
if workorder.next_work_order_id:
if (workorder.operation_id.batch == 'no') or (workorder.operation_id.batch_size >= workorder.qty_producing):

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

useless parens

'resource_id': best_workcenter.resource_id.id,
'time_type': 'other'
})
best_values.update({'leave_id': leave.id})

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

vals['leave_id'] = leave.id

if best_finished_date == datetime.datetime.max:
raise UserError(_('Impossible to plan the workorder. Please check the workcenter availabilities'))

# Compute start_date for next workorder if operation allow batch producing

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

add a comment
instantiate start_date for the next iteration

@api.depends('leave_id')
def _compute_dates_planned(self):
for wo in self:
wo.update({

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

why update in a compute?

@@ -114,6 +123,26 @@ class MrpWorkorder(models.Model):
'finished_workorder_id', string='By-products')
allowed_lots_domain = fields.One2many(comodel_name='stock.production.lot', compute="_compute_allowed_lots_domain")

@api.depends('leave_id')
def _compute_dates_planned(self):
for wo in self:

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

for workorder in self

@@ -114,6 +123,26 @@ class MrpWorkorder(models.Model):
'finished_workorder_id', string='By-products')
allowed_lots_domain = fields.One2many(comodel_name='stock.production.lot', compute="_compute_allowed_lots_domain")

@api.depends('leave_id')

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

add a comment:

Both `date_planned_start` and `date_planned_finished` are related fields on `leave_id`. Let's say
we slide a workorder on a gantt view, a single call to write is made with both fields. As the ORM
doesn't batch the write on related fields and instead makes multiple call, a constraint is raised. That's
why the four next methods are needed.
@@ -16,7 +16,7 @@
<field name="name">resource.calendar.leaves: employee modifies own</field>
<field name="model_id" ref="model_resource_calendar_leaves"/>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
<field name="domain_force">[('resource_id.user_id', '=', user.id)]</field>
<field name="domain_force">[('resource_id.user_id', 'in', [False, user.id])]</field>

This comment has been minimized.

Copy link
@sle-odoo

sle-odoo May 22, 2019

Contributor

split this part in another commit
[ref] resource: relax ir rule on resource.calendar.leaves

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.