Thibault Francois
8 years ago
14 changed files with 731 additions and 0 deletions
-
3beesdoo_shift/__init__.py
-
28beesdoo_shift/__openerp__.py
-
3beesdoo_shift/models/__init__.py
-
118beesdoo_shift/models/planning.py
-
36beesdoo_shift/models/task.py
-
6beesdoo_shift/security/ir.model.access.csv
-
80beesdoo_shift/views/planning.xml
-
77beesdoo_shift/views/task.xml
-
246beesdoo_shift/views/task_template.xml
-
2beesdoo_shift/wizard/__init__.py
-
53beesdoo_shift/wizard/batch_template.py
-
41beesdoo_shift/wizard/batch_template.xml
-
18beesdoo_shift/wizard/instanciate_planning.py
-
20beesdoo_shift/wizard/instanciate_planning.xml
@ -0,0 +1,3 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
import models |
||||
|
import wizard |
@ -0,0 +1,28 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
{ |
||||
|
'name': "Beescoop Shift Management", |
||||
|
|
||||
|
'summary': """ |
||||
|
Volonteer Timetable Management""", |
||||
|
|
||||
|
'description': """ |
||||
|
|
||||
|
""", |
||||
|
|
||||
|
'author': "Thibault Francois", |
||||
|
'website': "https://github.com/beescoop/Obeesdoo", |
||||
|
|
||||
|
'category': 'Coop', |
||||
|
'version': '0.1', |
||||
|
|
||||
|
'depends': ['beesdoo_base'], |
||||
|
|
||||
|
'data': [ |
||||
|
"security/ir.model.access.csv", |
||||
|
"views/task_template.xml", |
||||
|
"views/task.xml", |
||||
|
"views/planning.xml", |
||||
|
"wizard/instanciate_planning.xml", |
||||
|
"wizard/batch_template.xml", |
||||
|
], |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
import planning |
||||
|
import task |
@ -0,0 +1,118 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from openerp import models, fields, api, _ |
||||
|
from openerp.exceptions import UserError |
||||
|
|
||||
|
from pytz import UTC |
||||
|
import math |
||||
|
from datetime import datetime, timedelta |
||||
|
|
||||
|
def float_to_time(f): |
||||
|
decimal, integer = math.modf(f) |
||||
|
return "%s:%s" % (str(int(integer)).zfill(2), str(int(round(decimal * 60))).zfill(2)) |
||||
|
|
||||
|
def floatime_to_hour_minute(f): |
||||
|
decimal, integer = math.modf(f) |
||||
|
return int(integer), int(round(decimal * 60)) |
||||
|
|
||||
|
def get_first_day_of_week(): |
||||
|
today = datetime.now() |
||||
|
return datetime.now() - timedelta(days=today.weekday()) |
||||
|
|
||||
|
class TaskType(models.Model): |
||||
|
_name = 'beesdoo.shift.type' |
||||
|
|
||||
|
name = fields.Char() |
||||
|
description = fields.Text() |
||||
|
active = fields.Boolean(default=True) |
||||
|
|
||||
|
class DayNumber(models.Model): |
||||
|
_name = 'beesdoo.shift.daynumber' |
||||
|
|
||||
|
_order = 'number asc' |
||||
|
|
||||
|
name = fields.Char() |
||||
|
number = fields.Integer("Day Number", help="From 1 to N, When you will instanciate your planning, Day 1 will be the start date of the instance, Day 2 the second, etc...") |
||||
|
active = fields.Boolean(default=True) |
||||
|
|
||||
|
class Planning(models.Model): |
||||
|
_name = 'beesdoo.shift.planning' |
||||
|
|
||||
|
name = fields.Char() |
||||
|
task_template_ids = fields.One2many('beesdoo.shift.template', 'planning_id') |
||||
|
|
||||
|
class TaskTemplate(models.Model): |
||||
|
_name = 'beesdoo.shift.template' |
||||
|
|
||||
|
name = fields.Char(required=True) |
||||
|
planning_id = fields.Many2one('beesdoo.shift.planning', required=True) |
||||
|
day_nb_id = fields.Many2one('beesdoo.shift.daynumber', string='Day', required=True) |
||||
|
task_type_id = fields.Many2one('beesdoo.shift.type', string="Type") |
||||
|
start_time = fields.Float(required=True) |
||||
|
end_time = fields.Float(required=True) |
||||
|
|
||||
|
duration = fields.Float(help="Duration in Hour") |
||||
|
worker_nb = fields.Integer(string="Number of worker", help="Max number of worker for this task", default=1) |
||||
|
worker_ids = fields.Many2many('res.partner', string="Recurrent worker assigned", domain=[('eater', '=', 'worker_eater')]) |
||||
|
remaining_worker = fields.Integer(compute="_get_remaining", store=True, string="Remaining Place") |
||||
|
active = fields.Boolean(default=True) |
||||
|
#For Kanban View Only |
||||
|
color = fields.Integer('Color Index') |
||||
|
worker_name = fields.Char(compute="_get_worker_name") |
||||
|
#For calendar View |
||||
|
start_date = fields.Datetime(compute="_get_fake_date", search="_dummy_search") |
||||
|
end_date = fields.Datetime(compute="_get_fake_date", search="_dummy_search") |
||||
|
|
||||
|
@api.depends('start_time', 'end_time') |
||||
|
def _get_fake_date(self): |
||||
|
today = datetime.strptime(self._context.get('visualize_date'), '%Y-%m-%d') if self._context.get('visualize_date') else get_first_day_of_week() |
||||
|
for rec in self: |
||||
|
day = today + timedelta(days=rec.day_nb_id.number - 1) |
||||
|
h_begin, m_begin = floatime_to_hour_minute(rec.start_time) |
||||
|
h_end, m_end = floatime_to_hour_minute(rec.end_time) |
||||
|
rec.start_date = fields.Datetime.context_timestamp(self, day).replace(hour=h_begin, minute=m_begin, second=0).astimezone(UTC) |
||||
|
rec.end_date = fields.Datetime.context_timestamp(self, day).replace(hour=h_end, minute=m_end, second=0).astimezone(UTC) |
||||
|
|
||||
|
def _dummy_search(self, operator, value): |
||||
|
return [] |
||||
|
|
||||
|
@api.depends('worker_ids', 'worker_nb') |
||||
|
def _get_remaining(self): |
||||
|
for rec in self: |
||||
|
rec.remaining_worker = rec.worker_nb - len(rec.worker_ids) |
||||
|
|
||||
|
@api.depends("worker_ids") |
||||
|
def _get_worker_name(self): |
||||
|
for rec in self: |
||||
|
rec.worker_name = ','.join(rec.worker_ids.mapped('display_name')) |
||||
|
|
||||
|
@api.constrains('worker_nb', 'worker_ids') |
||||
|
def _nb_worker_max(self): |
||||
|
for rec in self: |
||||
|
if len(rec.worker_ids) > rec.worker_nb: |
||||
|
raise UserError(_('you cannot assign more worker then the number maximal define on the template')) |
||||
|
|
||||
|
|
||||
|
@api.onchange('start_time', 'end_time') |
||||
|
def _get_duration(self): |
||||
|
if self.start_time and self.end_time: |
||||
|
self.duration = self.end_time - self.start_time |
||||
|
|
||||
|
@api.onchange('duration') |
||||
|
def _set_duration(self): |
||||
|
if self.start_time: |
||||
|
self.end_time = self.start_time +self.duration |
||||
|
|
||||
|
def _generate_task_day(self): |
||||
|
tasks = self.env['beesdoo.shift.shift'] |
||||
|
for rec in self: |
||||
|
for i in xrange(0, rec.worker_nb): |
||||
|
tasks |= tasks.create({ |
||||
|
'name' : "%s (%s) - (%s) [%s]" % (rec.name, float_to_time(rec.start_time), float_to_time(rec.end_time), i), |
||||
|
'task_template_id' : rec.id, |
||||
|
'task_type_id' : rec.task_type_id.id, |
||||
|
'worker_id' : rec.worker_ids[i].id if len(rec.worker_ids) > i else False, |
||||
|
'start_time' : rec.start_date, |
||||
|
'end_time' : rec.end_date, |
||||
|
}) |
||||
|
return tasks |
@ -0,0 +1,36 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from openerp import models, fields |
||||
|
|
||||
|
STATES = [ |
||||
|
('draft', 'Unconfirmed'), |
||||
|
('open', 'Confirmed'), |
||||
|
('done', 'Attended'), |
||||
|
('absent', 'Absent'), |
||||
|
('excused', 'Excused'), |
||||
|
('replaced', 'Replaced'), |
||||
|
('cancel', 'Cancelled'), |
||||
|
] |
||||
|
|
||||
|
class Task(models.Model): |
||||
|
_name = 'beesdoo.shift.shift' |
||||
|
|
||||
|
#EX01 ADD inheritance |
||||
|
_inherit = ['mail.thread'] |
||||
|
|
||||
|
name = fields.Char(track_visibility='always') |
||||
|
task_template_id = fields.Many2one('beesdoo.shift.template') |
||||
|
planning_id = fields.Many2one(related='task_template_id.planning_id', store=True) |
||||
|
task_type_id = fields.Many2one('beesdoo.shift.type', string="Task Type") |
||||
|
worker_id = fields.Many2one('res.partner', track_visibility='onchange', domain=[('eater', '=', 'worker_eater')]) |
||||
|
start_time = fields.Datetime(track_visibility='always') |
||||
|
end_time = fields.Datetime(track_visibility='always') |
||||
|
state = fields.Selection(STATES, default='draft', track_visibility='onchange') |
||||
|
|
||||
|
def message_auto_subscribe(self, updated_fields, values=None): |
||||
|
self._add_follower(values) |
||||
|
return super(Task, self).message_auto_subscribe(updated_fields, values=values) |
||||
|
|
||||
|
def _add_follower(self, vals): |
||||
|
if vals.get('worker_id'): |
||||
|
worker = self.env['res.partner'].browse(vals['worker_id']) |
||||
|
self.message_subscribe(partner_ids=worker.ids) |
@ -0,0 +1,6 @@ |
|||||
|
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink |
||||
|
access_coopplanning_task_type,access_coopplanning_task_type,model_beesdoo_shift_type,,1,1,1,1 |
||||
|
access_coopplanning_daynumber,access_coopplanning_daynumber,model_beesdoo_shift_daynumber,,1,1,1,1 |
||||
|
access_coopplanning_planning,access_coopplanning_planning,model_beesdoo_shift_planning,,1,1,1,1 |
||||
|
access_coopplanning_task_template,access_coopplanning_task_template,model_beesdoo_shift_template,,1,1,1,1 |
||||
|
access_coopplanning_task,access_coopplanning_task,model_beesdoo_shift_shift,,1,1,1,1 |
@ -0,0 +1,80 @@ |
|||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="planning_view_tree"> |
||||
|
<field name="name">Planning List</field> |
||||
|
<field name="model">beesdoo.shift.planning</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<tree> |
||||
|
<field name="name" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.actions.act_window" id="action_shift_template"> |
||||
|
<field name="name">Planning Action</field> |
||||
|
<field name="res_model">beesdoo.shift.template</field> |
||||
|
<field name="view_mode">kanban,tree,form,calendar,pivot</field> |
||||
|
<field name="context">{'group_by': 'day_nb_id', |
||||
|
'search_default_planning_id': active_id, |
||||
|
'default_planning_id': active_id}</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.actions.act_window" id="action_generate_shift_wizard"> |
||||
|
<field name="name">Instanciate Planning Action</field> |
||||
|
<field name="res_model">beesddoo.shift.generate_planning</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="planning_view_form"> |
||||
|
<field name="name">Planning Form</field> |
||||
|
<field name="model">beesdoo.shift.planning</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<header> |
||||
|
|
||||
|
</header> |
||||
|
<sheet> |
||||
|
<div class="oe_button_box" name="button_box"> |
||||
|
<button class="oe_stat_button" type="action" |
||||
|
name="%(action_shift_template)d" icon="fa-book" |
||||
|
string="Shifts"> |
||||
|
<!-- <field string="Ventes" name="sale_order_count" |
||||
|
widget="statinfo" modifiers="{'readonly': true}"/> --> |
||||
|
</button> |
||||
|
</div> |
||||
|
<div class="oe_title"> |
||||
|
<h1> |
||||
|
<field name="name" placeholder="name" /> |
||||
|
</h1> |
||||
|
</div> |
||||
|
<group> |
||||
|
<button type="action" |
||||
|
name="%(action_generate_shift_wizard)d" string="Generate shifts" colspan="2"/> |
||||
|
</group> |
||||
|
</sheet> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="planning_view_tree"> |
||||
|
<field name="name">Planning Tree</field> |
||||
|
<field name="model">beesdoo.shift.planning</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<tree> |
||||
|
<field name="name" /> |
||||
|
<button type="action" name="%(action_shift_template)d" |
||||
|
string="Shifts" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<!-- Actions --> |
||||
|
<record model="ir.actions.act_window" id="action_planning"> |
||||
|
<field name="name">Planning Action</field> |
||||
|
<field name="res_model">beesdoo.shift.planning</field> |
||||
|
<field name="view_mode">tree,form</field> |
||||
|
</record> |
||||
|
|
||||
|
<menuitem name="Planning Week" id="menu_planning" parent="menu_template_top" |
||||
|
sequence="10" action="action_planning" /> |
||||
|
</odoo> |
@ -0,0 +1,77 @@ |
|||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="task_view_tree"> |
||||
|
<field name="name">Task Template List</field> |
||||
|
<field name="model">beesdoo.shift.shift</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<tree> |
||||
|
<field name="start_time" /> |
||||
|
<field name="planning_id" /> |
||||
|
<field name="task_type_id" /> |
||||
|
<field name="name" /> |
||||
|
<field name="worker_id" /> |
||||
|
<field name="end_time" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="task_view_calendar"> |
||||
|
<field name="name">Task Template List</field> |
||||
|
<field name="model">beesdoo.shift.shift</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<calendar string="Calendar View" date_start="start_time" |
||||
|
date_stop="end_time" color="task_type_id"> |
||||
|
<field name="name" /> |
||||
|
<field name="worker_id" /> |
||||
|
</calendar> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="task_view_form"> |
||||
|
<field name="name">Task Template Form</field> |
||||
|
<field name="model">beesdoo.shift.shift</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<header> |
||||
|
<field name="state" widget="statusbar" clickable="1" /> |
||||
|
</header> |
||||
|
<sheet> |
||||
|
<div class="oe_title"> |
||||
|
<h1> |
||||
|
<field name="name" /> |
||||
|
</h1> |
||||
|
</div> |
||||
|
<group> |
||||
|
<group> |
||||
|
<field name="task_template_id" /> |
||||
|
<field name="task_type_id" /> |
||||
|
<field name="worker_id" /> |
||||
|
</group> |
||||
|
<group> |
||||
|
<field name="start_time" /> |
||||
|
<field name="end_time" /> |
||||
|
</group> |
||||
|
</group> |
||||
|
</sheet> |
||||
|
<!-- Solution Ex1 --> |
||||
|
<div class="oe_chatter"> |
||||
|
<field name="message_follower_ids" widget="mail_followers" /> |
||||
|
<field name="message_ids" widget="mail_thread" /> |
||||
|
</div> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<!-- Actions --> |
||||
|
<record model="ir.actions.act_window" id="action_task"> |
||||
|
<field name="name">Task Action</field> |
||||
|
<field name="res_model">beesdoo.shift.shift</field> |
||||
|
<field name="view_mode">calendar,tree,form,pivot</field> |
||||
|
</record> |
||||
|
|
||||
|
<!-- Top menu item --> |
||||
|
<menuitem name="Planning" id="menu_task_top" parent="menu_root" |
||||
|
sequence="1" /> |
||||
|
<!-- actions --> |
||||
|
<menuitem name="Shift" id="menu_task" parent="menu_task_top" |
||||
|
action="action_task" /> |
||||
|
</odoo> |
@ -0,0 +1,246 @@ |
|||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="task_template_view_tree"> |
||||
|
<field name="name">Shift Template List</field> |
||||
|
<field name="model">beesdoo.shift.template</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<tree> |
||||
|
<field name="planning_id" /> |
||||
|
<field name="task_type_id" /> |
||||
|
<field name="name" /> |
||||
|
<field name="day_nb_id" /> |
||||
|
<field name="start_time" /> |
||||
|
<field name="end_time" /> |
||||
|
<field name="duration" /> |
||||
|
<field name="worker_nb" /> |
||||
|
<field name="remaining_worker" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="task_template_view_search"> |
||||
|
<field name="name">Shift Template Search</field> |
||||
|
<field name="model">beesdoo.shift.template</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<search> |
||||
|
<field name="name" /> |
||||
|
<field name="planning_id" /> |
||||
|
<field name="task_type_id" /> |
||||
|
<field name="day_nb_id" /> |
||||
|
<field name="worker_ids" /> |
||||
|
<filter string="Planning" context="{'group_by':'planning_id'}" /> |
||||
|
<filter string="Week Day" context="{'group_by':'day_nb_id'}" /> |
||||
|
<filter string="Place Available" name="available" |
||||
|
domain="[('remaining_worker', '>', 0)]" /> |
||||
|
</search> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="task_template_view_form"> |
||||
|
<field name="name">Task Template Form</field> |
||||
|
<field name="model">beesdoo.shift.template</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<sheet> |
||||
|
<div class="oe_title"> |
||||
|
<h1> |
||||
|
<field name="name" placeholder="name" /> |
||||
|
</h1> |
||||
|
</div> |
||||
|
<group> |
||||
|
<group> |
||||
|
<field name="day_nb_id" /> |
||||
|
<field name="planning_id" /> |
||||
|
<field name="task_type_id" /> |
||||
|
<field name="worker_nb" /> |
||||
|
<field name="remaining_worker" /> |
||||
|
<field name="active" /> |
||||
|
</group> |
||||
|
<group> |
||||
|
<field name="start_time" widget="float_time" /> |
||||
|
<field name="duration" widget="float_time" /> |
||||
|
<field name="end_time" widget="float_time" /> |
||||
|
</group> |
||||
|
</group> |
||||
|
<separator string="Recurring Workers" /> |
||||
|
<field name="worker_ids" nolabel="1" /> |
||||
|
</sheet> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="task_template_view_calendar"> |
||||
|
<field name="name">Shift Template Calendar</field> |
||||
|
<field name="model">beesdoo.shift.template</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<calendar string="Calendar View" date_start="start_date" |
||||
|
date_stop="end_date" color="task_type_id"> |
||||
|
<field name="name" /> |
||||
|
<field name="worker_ids" /> |
||||
|
</calendar> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="task_template_view_kanban"> |
||||
|
<field name="name">Task Template Kanban</field> |
||||
|
<field name="model">beesdoo.shift.template</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<kanban> |
||||
|
<field name="planning_id" /> |
||||
|
<field name="color" /> |
||||
|
<field name="task_type_id" /> |
||||
|
<field name="name" /> |
||||
|
<field name="day_nb_id" /> |
||||
|
<field name="worker_nb" /> |
||||
|
<field name="worker_ids" /> |
||||
|
<field name="worker_name" /> |
||||
|
<templates> |
||||
|
<t t-name="kanban-box"> |
||||
|
<div |
||||
|
t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click"> |
||||
|
<div class="o_dropdown_kanban dropdown" |
||||
|
groups="base.group_user"> |
||||
|
<a class="dropdown-toggle btn" |
||||
|
data-toggle="dropdown" href="#"> |
||||
|
<span class="fa fa-bars fa-lg" /> |
||||
|
</a> |
||||
|
<ul class="dropdown-menu" role="menu" |
||||
|
aria-labelledby="dLabel"> |
||||
|
<t t-if="widget.editable"> |
||||
|
<li> |
||||
|
<a type="edit">Edit Shift |
||||
|
Template</a> |
||||
|
</li> |
||||
|
</t> |
||||
|
<t t-if="widget.deletable"> |
||||
|
<li> |
||||
|
<a type="delete">Delete</a> |
||||
|
</li> |
||||
|
</t> |
||||
|
<li> |
||||
|
<ul class="oe_kanban_colorpicker" |
||||
|
data-field="color" /> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="oe_kanban_content"> |
||||
|
<strong> |
||||
|
<field name="name" /> |
||||
|
</strong> |
||||
|
<div> |
||||
|
<field name="planning_id" /> |
||||
|
</div> |
||||
|
<div t-if="record.task_type_id.raw_value"> |
||||
|
Type: |
||||
|
<field name="task_type_id" /> |
||||
|
</div> |
||||
|
<div> |
||||
|
Worker Number: |
||||
|
<field name="worker_nb" /> |
||||
|
</div> |
||||
|
<div> |
||||
|
<field name="start_time" |
||||
|
widget="float_time" /> |
||||
|
- |
||||
|
<field name="end_time" widget="float_time" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div> |
||||
|
<br /> |
||||
|
<strong>Recurring Workers</strong> |
||||
|
<t |
||||
|
t-foreach="record.worker_name.raw_value.split(',')" |
||||
|
t-as="worker"> |
||||
|
<div> |
||||
|
<t t-esc="worker" /> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</templates> |
||||
|
</kanban> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<menuitem name="Shift Management" id="menu_root" /> |
||||
|
<menuitem name="Templates" id="menu_template_top" parent="menu_root" /> |
||||
|
|
||||
|
|
||||
|
<!-- Configuration --> |
||||
|
<record model="ir.ui.view" id="daynumber_view_tree"> |
||||
|
<field name="name">Day Number List</field> |
||||
|
<field name="model">beesdoo.shift.daynumber</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<tree editable="top"> |
||||
|
<field name="name" /> |
||||
|
<field name="number" /> |
||||
|
<field name="active" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="type_view_tree"> |
||||
|
<field name="name">Shift Type List</field> |
||||
|
<field name="model">beesdoo.shift.type</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<tree> |
||||
|
<field name="name" /> |
||||
|
<field name="description" /> |
||||
|
<field name="active" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.actions.act_window" id="action_generate_shift_template_wizard"> |
||||
|
<field name="name">Generate Shift Template</field> |
||||
|
<field name="res_model">beesddoo.shift.generate_shift_template</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="type_view_form"> |
||||
|
<field name="name">Shift Type Form</field> |
||||
|
<field name="model">beesdoo.shift.type</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<header> |
||||
|
<button type="action" |
||||
|
name="%(action_generate_shift_template_wizard)d" |
||||
|
string="Generate shift Templates" /> |
||||
|
</header> |
||||
|
<sheet> |
||||
|
<group> |
||||
|
<group> |
||||
|
<field name="name" /> |
||||
|
</group> |
||||
|
<group> |
||||
|
<field name="active" /> |
||||
|
</group> |
||||
|
</group> |
||||
|
<separator string="Description" /> |
||||
|
<field name="description" /> |
||||
|
</sheet> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<menuitem name="Configuration" id="menu_configuration_top" |
||||
|
parent="menu_root" /> |
||||
|
|
||||
|
<record model="ir.actions.act_window" id="action_day_number"> |
||||
|
<field name="name">Day Number</field> |
||||
|
<field name="res_model">beesdoo.shift.daynumber</field> |
||||
|
<field name="view_mode">tree</field> |
||||
|
</record> |
||||
|
|
||||
|
<menuitem name="Shift Day" id="menu_configuration_day" |
||||
|
parent="menu_configuration_top" action="action_day_number" /> |
||||
|
|
||||
|
<record model="ir.actions.act_window" id="action_type"> |
||||
|
<field name="name">Shift Type</field> |
||||
|
<field name="res_model">beesdoo.shift.type</field> |
||||
|
<field name="view_mode">tree,form</field> |
||||
|
</record> |
||||
|
|
||||
|
<menuitem name="Shift Type" id="menu_configuration_type" |
||||
|
parent="menu_configuration_top" action="action_type" /> |
||||
|
</odoo> |
@ -0,0 +1,2 @@ |
|||||
|
import instanciate_planning |
||||
|
import batch_template |
@ -0,0 +1,53 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
''' |
||||
|
Created on 2 janv. 2017 |
||||
|
|
||||
|
@author: Thibault Francois |
||||
|
''' |
||||
|
|
||||
|
from openerp import models, fields, api, _ |
||||
|
|
||||
|
class GenerateShiftTemplate(models.TransientModel): |
||||
|
_name = 'beesddoo.shift.generate_shift_template' |
||||
|
|
||||
|
day_ids = fields.Many2many('beesdoo.shift.daynumber', relation='template_gen_day_number_rel', column1='wizard_id', column2='day_id') |
||||
|
planning_id = fields.Many2one('beesdoo.shift.planning', required=True) |
||||
|
type_id = fields.Many2one('beesdoo.shift.type', default=lambda self: self._context.get('active_id')) |
||||
|
line_ids = fields.One2many('beesddoo.shift.generate_shift_template.line', 'wizard_id') |
||||
|
|
||||
|
@api.multi |
||||
|
def generate(self): |
||||
|
self.ensure_one() |
||||
|
ids = [] |
||||
|
for day in self.day_ids: |
||||
|
for line in self.line_ids: |
||||
|
shift_template_data = { |
||||
|
'name': '%s' % self.type_id.name, |
||||
|
'planning_id': self.planning_id.id, |
||||
|
'task_type_id': self.type_id.id, |
||||
|
'day_nb_id': day.id, |
||||
|
'start_time': line.start_time, |
||||
|
'end_time': line.end_time, |
||||
|
'duration': line.end_time - line.start_time, |
||||
|
'worker_nb': line.worker_nb, |
||||
|
} |
||||
|
new_rec = self.env['beesdoo.shift.template'].create(shift_template_data) |
||||
|
ids.append(new_rec.id) |
||||
|
return { |
||||
|
'name': _('Generated Shift Template'), |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'view_type': 'form', |
||||
|
'view_mode': 'kanban,tree,form', |
||||
|
'res_model': 'beesdoo.shift.template', |
||||
|
'target': 'current', |
||||
|
'domain': [('id', 'in', ids)], |
||||
|
'context': {'group_by': 'day_nb_id'}, |
||||
|
} |
||||
|
|
||||
|
class GenerateShiftTemplateLine(models.TransientModel): |
||||
|
_name = 'beesddoo.shift.generate_shift_template.line' |
||||
|
|
||||
|
wizard_id = fields.Many2one('beesddoo.shift.generate_shift_template') |
||||
|
start_time = fields.Float(required=True) |
||||
|
end_time = fields.Float(required=True) |
||||
|
worker_nb = fields.Integer(default=1) |
@ -0,0 +1,41 @@ |
|||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="task_template_generation_view_form"> |
||||
|
<field name="name">Planning Form</field> |
||||
|
<field name="model">beesddoo.shift.generate_shift_template</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group> |
||||
|
<field name="planning_id" /> |
||||
|
<field name="type_id" invisible="1" /> |
||||
|
</group> |
||||
|
<group> |
||||
|
<group> |
||||
|
<separator string="Daily Schedule" colspan="2"/> |
||||
|
<field name="line_ids" nolabel="1" > |
||||
|
<tree editable="bottom"> |
||||
|
<field name="start_time" widget="float_time" /> |
||||
|
<field name="end_time" widget="float_time" /> |
||||
|
<field name="worker_nb" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</group> |
||||
|
<group> |
||||
|
<separator string="Apply for Days" colspan="2"/> |
||||
|
<field name="day_ids" nolabel="1" > |
||||
|
<tree> |
||||
|
<field name="name" /> |
||||
|
<field name="number" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</group> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button type="object" name="generate" string="Confirm" class="oe_highlight"/> |
||||
|
or |
||||
|
<button special="cancel" string="Cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,18 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from openerp import models, fields, api |
||||
|
|
||||
|
|
||||
|
class InstanciatePlanning(models.TransientModel): |
||||
|
_name = 'beesddoo.shift.generate_planning' |
||||
|
|
||||
|
def _get_planning(self): |
||||
|
return self._context.get('active_id') |
||||
|
|
||||
|
date_start = fields.Date("First Day of planning", required=True) |
||||
|
planning_id = fields.Many2one('beesdoo.shift.planning', readonly=True, default=_get_planning) |
||||
|
|
||||
|
@api.multi |
||||
|
def generate_task(self): |
||||
|
self.ensure_one() |
||||
|
self = self.with_context(visualize_date=self.date_start) |
||||
|
self.planning_id.task_template_ids._generate_task_day() |
@ -0,0 +1,20 @@ |
|||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="planning_instanciate_view_form"> |
||||
|
<field name="name">Planning Form</field> |
||||
|
<field name="model">beesddoo.shift.generate_planning</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group> |
||||
|
<field name="date_start" /> |
||||
|
<field name="planning_id" invisible="1" /> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button type="object" name="generate_task" string="Confirm" class="oe_highlight"/> |
||||
|
or |
||||
|
<button special="cancel" string="Cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue