lims_tools: add support to generate events by work shifts

This commit is contained in:
Adrián Bernardi 2023-07-11 13:34:13 -03:00
parent ffdcce5ec7
commit 522eb0562c
5 changed files with 211 additions and 24 deletions

View File

@ -139,6 +139,14 @@ msgctxt "field:lims.administrative.task.program,responsible:"
msgid "Responsible User"
msgstr "Usuario responsable"
msgctxt "field:lims.administrative.task.program,shift_time:"
msgid "Time of the shift"
msgstr "Momento del turno"
msgctxt "field:lims.administrative.task.program,shifts:"
msgid "Work shifts"
msgstr "Turnos de trabajo"
msgctxt "field:lims.administrative.task.program,specific_day:"
msgid "Specific Day"
msgstr "Día específico"
@ -528,6 +536,10 @@ msgctxt "selection:lims.administrative.task.program,finish_selection:"
msgid "Quantity"
msgstr "Cantidad"
msgctxt "selection:lims.administrative.task.program,frequence_selection:"
msgid "By work shift"
msgstr "Por turno de trabajo"
msgctxt "selection:lims.administrative.task.program,frequence_selection:"
msgid "Customize"
msgstr "Personalizada"
@ -556,6 +568,18 @@ msgctxt "selection:lims.administrative.task.program,frequence_selection:"
msgid "Yearly"
msgstr "Anual"
msgctxt "selection:lims.administrative.task.program,shift_time:"
msgid "At end"
msgstr "Al final"
msgctxt "selection:lims.administrative.task.program,shift_time:"
msgid "At start"
msgstr "Al inicio"
msgctxt "selection:lims.administrative.task.program,shift_time:"
msgid "At start and end"
msgstr "Al inicio y al final"
msgctxt "selection:lims.administrative.task.program,specific_day:"
msgid "Friday"
msgstr "Viernes"

View File

@ -23,6 +23,10 @@
<label name="specific_event_time"/>
<field name="specific_event_time"/>
</group>
<label name="shift_time"/>
<field name="shift_time"/>
<label name="shifts"/>
<field name="shifts"/>
</group>
<group id="create_tasks" colspan="4" string="Generate Administrative Tasks">
<label name="start_date"/>

View File

@ -127,6 +127,14 @@ msgctxt "field:lims.lab.device.maintenance.program,responsible:"
msgid "Responsible User"
msgstr "Usuario responsable"
msgctxt "field:lims.lab.device.maintenance.program,shift_time:"
msgid "Time of the shift"
msgstr "Momento del turno"
msgctxt "field:lims.lab.device.maintenance.program,shifts:"
msgid "Work shifts"
msgstr "Turnos de trabajo"
msgctxt "field:lims.lab.device.maintenance.program,specific_day:"
msgid "Specific Day"
msgstr "Día específico"
@ -316,6 +324,10 @@ msgctxt "selection:lims.lab.device.maintenance.program,finish_selection:"
msgid "Quantity"
msgstr "Cantidad"
msgctxt "selection:lims.lab.device.maintenance.program,frequence_selection:"
msgid "By work shift"
msgstr "Por turno de trabajo"
msgctxt "selection:lims.lab.device.maintenance.program,frequence_selection:"
msgid "Customize"
msgstr "Personalizada"
@ -344,6 +356,18 @@ msgctxt "selection:lims.lab.device.maintenance.program,frequence_selection:"
msgid "Yearly"
msgstr "Anual"
msgctxt "selection:lims.lab.device.maintenance.program,shift_time:"
msgid "At end"
msgstr "Al final"
msgctxt "selection:lims.lab.device.maintenance.program,shift_time:"
msgid "At start"
msgstr "Al inicio"
msgctxt "selection:lims.lab.device.maintenance.program,shift_time:"
msgid "At start and end"
msgstr "Al inicio y al final"
msgctxt "selection:lims.lab.device.maintenance.program,specific_day:"
msgid "Friday"
msgstr "Viernes"

View File

@ -29,6 +29,10 @@
<label name="specific_event_time"/>
<field name="specific_event_time"/>
</group>
<label name="shift_time"/>
<field name="shift_time"/>
<label name="shifts"/>
<field name="shifts"/>
<label name="notice_days"/>
<field name="notice_days"/>
</group>

View File

@ -1,9 +1,10 @@
# This file is part of lims_tools module for Tryton.
# The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms.
from datetime import timedelta
from datetime import datetime, timedelta
from trytond.model import Model, fields
from trytond.pool import Pool
from trytond.pyson import Eval
from trytond.exceptions import UserError
from trytond.i18n import gettext
@ -16,6 +17,7 @@ FREQUENCE_OPTIONS = [
('15_days', 'Every 15 days'),
('monthly', 'Monthly'),
('yearly', 'Yearly'),
('workshift', 'By work shift'),
('customize', 'Customize'),
]
@ -26,6 +28,7 @@ FREQUENCE_OPTIONS_VALUE_MAP = {
'15_days': (15, 'days'),
'monthly': (1, 'months'),
'yearly': (1, 'years'),
'workshift': (1, 'days'),
'customize': (None, None),
}
@ -44,13 +47,15 @@ class EventCreator(Model):
'Event Creator'
start_date = fields.DateTime('Start Date')
frequence_selection = fields.Selection(
FREQUENCE_OPTIONS,
frequence_selection = fields.Selection(FREQUENCE_OPTIONS,
'Select Frequence', sort=False)
detail_frequence = fields.Float('Frequence', required=True)
detail_frequence_selection = fields.Selection(
DETAIL_FREQUENCE_OPTIONS,
'Frequence', required=True, sort=False)
detail_frequence = fields.Float('Frequence', required=True,
states={'readonly': Eval('frequence_selection') == 'workshift'},
depends=['frequence_selection'])
detail_frequence_selection = fields.Selection(DETAIL_FREQUENCE_OPTIONS,
'Frequence', sort=False, required=True,
states={'readonly': Eval('frequence_selection') == 'workshift'},
depends=['frequence_selection'])
specific_day = fields.Selection([
(None, ''),
('monday', 'Monday'),
@ -61,14 +66,22 @@ class EventCreator(Model):
('saturday', 'Saturday'),
('sunday', 'Sunday')
], 'Specific Day',
states={
'invisible': Eval('frequence_selection') != 'weekly',
},
states={'invisible': Eval('frequence_selection') != 'weekly'},
depends=['frequence_selection'])
specific_event_time = fields.DateTime('Specific Time',
states={
'invisible': Eval('frequence_selection') != 'daily',
},
states={'invisible': Eval('frequence_selection') != 'daily'},
depends=['frequence_selection'])
shifts = fields.MultiSelection('get_workyear_shifts', 'Work shifts',
sort=False,
states={'invisible': Eval('frequence_selection') != 'workshift'},
depends=['frequence_selection'])
shift_time = fields.Selection([
(None, ''),
('start', 'At start'),
('end', 'At end'),
('start_end', 'At start and end'),
], 'Time of the shift', sort=False,
states={'invisible': Eval('frequence_selection') != 'workshift'},
depends=['frequence_selection'])
only_workdays = fields.Boolean('Allow working days only')
finish_selection = fields.Selection([
@ -91,20 +104,36 @@ class EventCreator(Model):
@fields.depends('frequence_selection')
def on_change_frequence_selection(self):
if self.frequence_selection:
if (self.frequence_selection and
self.frequence_selection in FREQUENCE_OPTIONS_VALUE_MAP):
self.detail_frequence, self.detail_frequence_selection = (
FREQUENCE_OPTIONS_VALUE_MAP[self.frequence_selection])
@classmethod
def create_events(cls, records, create_method, start_date=None, include_start_date=True):
def get_workyear_shifts(cls):
shifts = Pool().get('lims.lab.workshift').search([])
result = [(shift.id, shift.name) for shift in shifts]
return result
@classmethod
def create_events(cls, records, create_method,
start_date=None, include_start_date=True):
events = []
for record in records:
if record.finish_selection == 'quantity':
events.extend(
cls.create_fixed_events(record, create_method, start_date, include_start_date))
if record.frequence_selection == 'workshift':
events.extend(cls.create_workshift_fixed_events(
record, create_method, start_date, include_start_date))
else:
events.extend(cls.create_fixed_events(
record, create_method, start_date, include_start_date))
elif record.finish_selection == 'date':
events.extend(
cls.create_events_until_date(record, create_method, start_date, include_start_date))
if record.frequence_selection == 'workshift':
events.extend(cls.create_workshift_events_until_date(
record, create_method, start_date, include_start_date))
else:
events.extend(cls.create_events_until_date(
record, create_method, start_date, include_start_date))
else:
raise UserError(gettext(
'lims_tools.missing_end_condition'))
@ -112,7 +141,8 @@ class EventCreator(Model):
return events
@classmethod
def create_fixed_events(cls, record, create_method, start_date=None, include_start_date=True):
def create_fixed_events(cls, record, create_method,
start_date=None, include_start_date=True):
events = []
if not start_date:
start_date = record.start_date
@ -122,13 +152,13 @@ class EventCreator(Model):
date = start_date
if not include_start_date:
date = date + cls.get_delta(frequence, frequence_selection)
while len(events) < record.end_repetition:
event = {}
if record.specific_event_time:
date = date.replace(
hour=record.specific_event_time.hour,
minute=record.specific_event_time.minute,
hour=record.specific_event_time.hour,
minute=record.specific_event_time.minute,
second=record.specific_event_time.second
)
event['scheduled_date'] = date
@ -140,7 +170,57 @@ class EventCreator(Model):
return events
@classmethod
def create_events_until_date(cls, record, create_method, start_date=None, include_start_date=True):
def create_workshift_fixed_events(cls, record, create_method,
start_date=None, include_start_date=True):
pool = Pool()
LabWorkYear = pool.get('lims.lab.workyear')
WorkShift = pool.get('lims.lab.workyear.shift')
workyear_id = LabWorkYear.find()
workyear_shifts = WorkShift.search([
('workyear', '=', workyear_id),
('shift', 'in', [s for s in record.shifts]),
])
if not workyear_shifts:
return []
specific_times = []
for ws in workyear_shifts:
if record.shift_time in ['start', 'start_end']:
specific_times.append(ws.shift.start_time)
if record.shift_time in ['end', 'start_end']:
specific_times.append(ws.shift.end_time)
if not start_date:
start_date = record.start_date
frequence = record.detail_frequence
frequence_selection = record.detail_frequence_selection
date = start_date
if not include_start_date:
date = date + cls.get_delta(frequence, frequence_selection)
events = []
while len(events) < record.end_repetition:
for specific_time in specific_times:
event = {}
event_date = date.replace(
hour=specific_time.hour,
minute=specific_time.minute,
second=specific_time.second
)
event['scheduled_date'] = event_date
event['week_day'] = date.weekday()
new_event = create_method(record, event)
if new_event:
events.append(new_event)
if len(events) == record.end_repetition:
break
date = date + cls.get_delta(frequence, frequence_selection)
return events
@classmethod
def create_events_until_date(cls, record, create_method,
start_date=None, include_start_date=True):
events = []
if not start_date:
start_date = record.start_date
@ -160,6 +240,57 @@ class EventCreator(Model):
events.append(new_event)
return events
@classmethod
def create_workshift_events_until_date(cls, record, create_method,
start_date=None, include_start_date=True):
pool = Pool()
LabWorkYear = pool.get('lims.lab.workyear')
WorkShift = pool.get('lims.lab.workyear.shift')
workyear_id = LabWorkYear.find()
workyear_shifts = WorkShift.search([
('workyear', '=', workyear_id),
('shift', 'in', [s for s in record.shifts]),
])
if not workyear_shifts:
return []
specific_times = []
for ws in workyear_shifts:
if record.shift_time in ['start', 'start_end']:
specific_times.append(ws.shift.start_time)
if record.shift_time in ['end', 'start_end']:
specific_times.append(ws.shift.end_time)
if not start_date:
start_date = record.start_date
frequence = record.detail_frequence
frequence_selection = record.detail_frequence_selection
min_time = datetime.min.time()
max_time = datetime.max.time()
end_date = datetime.combine(record.end_date, max_time)
date = datetime.combine(start_date, min_time)
if not include_start_date:
date = date + cls.get_delta(frequence, frequence_selection)
events = []
while date < end_date:
for specific_time in specific_times:
event = {}
event_date = date.replace(
hour=specific_time.hour,
minute=specific_time.minute,
second=specific_time.second
)
event['scheduled_date'] = event_date
event['week_day'] = date.weekday()
new_event = create_method(record, event)
if new_event:
events.append(new_event)
date = date + cls.get_delta(frequence, frequence_selection)
return events
@classmethod
def get_delta(cls, frequence, unit):
if unit == 'minutes':