Browse Source

[ADD] b_shift : attendance sheet compensation number

Changes from shift status update are made as well.
pull/143/head
Elouan Le Bars 4 years ago
parent
commit
d8f96f249c
  1. 128
      beesdoo_shift/models/attendance_sheet.py
  2. 10
      beesdoo_shift/tests/test_attendance_sheet.py
  3. 16
      beesdoo_shift/views/attendance_sheet.xml

128
beesdoo_shift/models/attendance_sheet.py

@ -30,14 +30,10 @@ class AttendanceSheetShift(models.AbstractModel):
required=True, required=True,
ondelete="cascade", ondelete="cascade",
) )
stage = fields.Selection(
[
("present", "Present"),
("absent_0", "Absent / 0 Compensation"),
("absent_1", "Absent / 1 Compensation"),
("absent_2", "Absent / 2 Compensations"),
],
string="Shift Stage",
state = fields.Selection(
[("done", "Present"), ("absent", "Absent"),],
string="Shift State",
required=True,
) )
worker_id = fields.Many2one( worker_id = fields.Many2one(
"res.partner", "res.partner",
@ -64,40 +60,24 @@ class AttendanceSheetShift(models.AbstractModel):
string="Compensation shift ?", string="Compensation shift ?",
help="Only for regular workers" help="Only for regular workers"
) )
def get_actual_stage(self):
"""
Mapping function returning the actual id
of corresponding beesdoo.shift.stage,
because we prefer users to select number of compensations
on the sheet rather than the exact stage name.
"""
if not self.working_mode or not self.stage:
raise UserError(
_("Impossible to map task stage, all values are not set.")
)
if self.working_mode == "regular":
if self.stage == "present":
return "done"
if self.stage == "absent_0":
return "excused_necessity"
if self.stage == "absent_1":
return "excused"
if self.stage == "absent_2":
return "absent"
if self.working_mode == "irregular":
if self.stage == "present":
return "done"
return "absent"
class AttendanceSheetShiftExpected(models.Model): class AttendanceSheetShiftExpected(models.Model):
"""
Irregulars can only have two compensations
"""
_name = "beesdoo.shift.sheet.expected" _name = "beesdoo.shift.sheet.expected"
_description = "Expected Shift" _description = "Expected Shift"
_inherit = ["beesdoo.shift.sheet.shift"] _inherit = ["beesdoo.shift.sheet.shift"]
compensation_no = fields.Selection(
[("0", "0"), ("1", "1"), ("2", "2"),], string="Compensations",
)
replacement_worker_id = fields.Many2one( replacement_worker_id = fields.Many2one(
"res.partner", "res.partner",
string="Replacement Worker", string="Replacement Worker",
help="Replacement Worker (must be regular)",
domain=[ domain=[
("eater", "=", "worker_eater"), ("eater", "=", "worker_eater"),
("working_mode", "=", "regular"), ("working_mode", "=", "regular"),
@ -105,24 +85,35 @@ class AttendanceSheetShiftExpected(models.Model):
], ],
) )
@api.onchange("state")
def on_change_state(self):
if not self.state or self.state == "done":
self.compensation_no = False
if self.state == "absent":
self.compensation_no = "2"
@api.constrains("state", "compensation_no")
def _constrain_compensation_no(self):
if self.state == "absent":
if not self.compensation_no:
raise UserError(_("You must choose a compensation number."))
class AttendanceSheetShiftAdded(models.Model): class AttendanceSheetShiftAdded(models.Model):
"""The added shifts stage must be Present
(add an SQL constraint ?)
"""
Added shifts are necessarily 'Present'
""" """
_name = "beesdoo.shift.sheet.added" _name = "beesdoo.shift.sheet.added"
_description = "Added Shift" _description = "Added Shift"
_inherit = ["beesdoo.shift.sheet.shift"] _inherit = ["beesdoo.shift.sheet.shift"]
stage = fields.Selection(default="present")
state = fields.Selection(default="done")
@api.onchange("working_mode") @api.onchange("working_mode")
def on_change_working_mode(self): def on_change_working_mode(self):
self.stage = "present"
self.state = "done"
self.is_compensation = self.working_mode == "regular" self.is_compensation = self.working_mode == "regular"
class AttendanceSheet(models.Model): class AttendanceSheet(models.Model):
_name = "beesdoo.shift.sheet" _name = "beesdoo.shift.sheet"
_inherit = [ _inherit = [
@ -326,7 +317,7 @@ class AttendanceSheet(models.Model):
if ( if (
shift.worker_id == worker and not shift.replacement_worker_id shift.worker_id == worker and not shift.replacement_worker_id
) or shift.replacement_worker_id == worker: ) or shift.replacement_worker_id == worker:
shift.stage = "present"
shift.state = "done"
return return
if shift.worker_id == worker and shift.replacement_worker_id: if shift.worker_id == worker and shift.replacement_worker_id:
raise UserError( raise UserError(
@ -336,13 +327,14 @@ class AttendanceSheet(models.Model):
is_compensation = (worker.working_mode == "regular") is_compensation = (worker.working_mode == "regular")
added_ids = map(lambda s: s.worker_id.id, self.added_shift_ids) added_ids = map(lambda s: s.worker_id.id, self.added_shift_ids)
if worker.id in added_ids: if worker.id in added_ids:
return return
self.added_shift_ids |= self.added_shift_ids.new( self.added_shift_ids |= self.added_shift_ids.new(
{ {
"task_type_id": self.added_shift_ids.default_task_type_id(), "task_type_id": self.added_shift_ids.default_task_type_id(),
"stage": "present",
"state": "done",
"attendance_sheet_id": self._origin.id, "attendance_sheet_id": self._origin.id,
"worker_id": worker.id, "worker_id": worker.id,
"is_compensation": is_compensation, "is_compensation": is_compensation,
@ -357,7 +349,6 @@ class AttendanceSheet(models.Model):
# to the time range # to the time range
tasks = self.env["beesdoo.shift.shift"] tasks = self.env["beesdoo.shift.shift"]
expected_shift = self.env["beesdoo.shift.sheet.expected"] expected_shift = self.env["beesdoo.shift.sheet.expected"]
cancelled_stage = self.env.ref("beesdoo_shift.cancel")
s_time = fields.Datetime.from_string(new_sheet.start_time) s_time = fields.Datetime.from_string(new_sheet.start_time)
e_time = fields.Datetime.from_string(new_sheet.end_time) e_time = fields.Datetime.from_string(new_sheet.end_time)
delta = timedelta(minutes=1) delta = timedelta(minutes=1)
@ -371,11 +362,7 @@ class AttendanceSheet(models.Model):
] ]
) )
for task in tasks: for task in tasks:
if task.working_mode == "irregular":
stage = "absent_1"
else:
stage = "absent_2"
if task.worker_id and (task.stage_id != cancelled_stage):
if task.worker_id and (task.state != "cancel"):
new_expected_shift = expected_shift.create( new_expected_shift = expected_shift.create(
{ {
"attendance_sheet_id": new_sheet.id, "attendance_sheet_id": new_sheet.id,
@ -383,7 +370,8 @@ class AttendanceSheet(models.Model):
"worker_id": task.worker_id.id, "worker_id": task.worker_id.id,
"replacement_worker_id": task.replaced_id.id, "replacement_worker_id": task.replaced_id.id,
"task_type_id": task.task_type_id.id, "task_type_id": task.task_type_id.id,
"stage": stage,
"state": "absent",
"compensation_no": "2",
"working_mode": task.working_mode, "working_mode": task.working_mode,
"is_compensation": task.is_compensation, "is_compensation": task.is_compensation,
} }
@ -415,7 +403,6 @@ class AttendanceSheet(models.Model):
raise UserError("The sheet has already been validated.") raise UserError("The sheet has already been validated.")
shift = self.env["beesdoo.shift.shift"] shift = self.env["beesdoo.shift.shift"]
stage = self.env["beesdoo.shift.stage"]
# Fields validation # Fields validation
for added_shift in self.added_shift_ids: for added_shift in self.added_shift_ids:
@ -423,9 +410,9 @@ class AttendanceSheet(models.Model):
raise UserError( raise UserError(
_("Worker must be set for shift %s") % added_shift.id _("Worker must be set for shift %s") % added_shift.id
) )
if not added_shift.stage:
if added_shift.state != "done":
raise UserError( raise UserError(
_("Shift Stage is missing for %s")
_("Shift State is missing or wrong for %s")
% added_shift.worker_id.name % added_shift.worker_id.name
) )
if not added_shift.task_type_id: if not added_shift.task_type_id:
@ -440,34 +427,40 @@ class AttendanceSheet(models.Model):
) )
for expected_shift in self.expected_shift_ids: for expected_shift in self.expected_shift_ids:
if not expected_shift.stage:
if not expected_shift.state:
raise UserError(
_("Shift State is missing for %s")
% expected_shift.worker_id.name
)
if (
expected_shift.state == "absent"
and not expected_shift.compensation_no
):
raise UserError( raise UserError(
_("Shift Stage is missing for %s")
_("Compensation number is missing for %s")
% expected_shift.worker_id.name % expected_shift.worker_id.name
) )
# Expected shifts status update # Expected shifts status update
for expected_shift in self.expected_shift_ids: for expected_shift in self.expected_shift_ids:
actual_shift = expected_shift.task_id actual_shift = expected_shift.task_id
actual_stage = self.env.ref(
"beesdoo_shift.%s" % expected_shift.get_actual_stage()
)
# Merge state with compensations number to fit Task model
if expected_shift.state == "absent" and expected_shift.compensation_no:
state_converted = "absent_%s" % expected_shift.compensation_no
else:
state_converted = expected_shift.state
if actual_stage:
actual_shift.stage_id = actual_stage
actual_shift.replaced_id = expected_shift.replacement_worker_id
actual_shift.replaced_id = expected_shift.replacement_worker_id
actual_shift.state = state_converted
if expected_shift.stage in ["absent_1", "absent_2"]:
mail_template = self.env.ref(
"beesdoo_shift.email_template_non_attendance", False
)
mail_template.send_mail(expected_shift.task_id.id, True)
if expected_shift.state == "absent":
mail_template = self.env.ref(
"beesdoo_shift.email_template_non_attendance", False
)
mail_template.send_mail(expected_shift.task_id.id, True)
# Added shifts status update # Added shifts status update
for added_shift in self.added_shift_ids: for added_shift in self.added_shift_ids:
actual_stage = self.env.ref(
"beesdoo_shift.%s" % added_shift.get_actual_stage()
)
is_regular_worker = added_shift.worker_id.working_mode == "regular" is_regular_worker = added_shift.worker_id.working_mode == "regular"
is_compensation = added_shift.is_compensation is_compensation = added_shift.is_compensation
@ -486,9 +479,8 @@ class AttendanceSheet(models.Model):
actual_shift = non_assigned_shifts[0] actual_shift = non_assigned_shifts[0]
actual_shift.write( actual_shift.write(
{ {
"stage_id": actual_stage.id,
"state": added_shift.state,
"worker_id": added_shift.worker_id.id, "worker_id": added_shift.worker_id.id,
"stage_id": actual_stage.id,
"is_regular": not is_compensation and is_regular_worker, "is_regular": not is_compensation and is_regular_worker,
"is_compensation": is_compensation "is_compensation": is_compensation
and is_regular_worker, and is_regular_worker,
@ -499,10 +491,10 @@ class AttendanceSheet(models.Model):
{ {
"name": _("[Added Shift] %s") % self.start_time, "name": _("[Added Shift] %s") % self.start_time,
"task_type_id": added_shift.task_type_id.id, "task_type_id": added_shift.task_type_id.id,
"state": added_shift.state,
"worker_id": added_shift.worker_id.id, "worker_id": added_shift.worker_id.id,
"start_time": self.start_time, "start_time": self.start_time,
"end_time": self.end_time, "end_time": self.end_time,
"stage_id": actual_stage.id,
"is_regular": not is_compensation and is_regular_worker, "is_regular": not is_compensation and is_regular_worker,
"is_compensation": is_compensation "is_compensation": is_compensation
and is_regular_worker, and is_regular_worker,

10
beesdoo_shift/tests/test_attendance_sheet.py

@ -211,9 +211,9 @@ class TestAttendanceSheet(TransactionCase):
self.assertEquals(shift.working_mode, shift.task_id.working_mode) self.assertEquals(shift.working_mode, shift.task_id.working_mode)
if shift.working_mode == "regular": if shift.working_mode == "regular":
self.assertEquals(shift.stage, "absent_2")
self.assertEquals(shift.state, "absent_2")
if shift.working_mode == "irregular": if shift.working_mode == "irregular":
self.assertEquals(shift.stage, "absent_1")
self.assertEquals(shift.state, "absent_1")
# test maximum number of workers calculation from task_templates # test maximum number of workers calculation from task_templates
self.assertEquals(sheet_1.max_worker_no, 21) self.assertEquals(sheet_1.max_worker_no, 21)
@ -253,7 +253,7 @@ class TestAttendanceSheet(TransactionCase):
# check expected shifts update # check expected shifts update
for id in sheet_1.expected_shift_ids.ids: for id in sheet_1.expected_shift_ids.ids:
shift = sheet_1.expected_shift_ids.browse(id) shift = sheet_1.expected_shift_ids.browse(id)
self.assertEquals(shift.stage, "present")
self.assertEquals(shift.state, "present")
""" """
Added workers : Added workers :
@ -276,7 +276,7 @@ class TestAttendanceSheet(TransactionCase):
for id in sheet_1.added_shift_ids.ids: for id in sheet_1.added_shift_ids.ids:
shift = sheet_1.added_shift_ids.browse(id) shift = sheet_1.added_shift_ids.browse(id)
self.assertEquals(sheet_1, shift.attendance_sheet_id) self.assertEquals(sheet_1, shift.attendance_sheet_id)
self.assertEquals(shift.stage, "present")
self.assertEquals(shift.state, "present")
self.assertEquals( self.assertEquals(
shift.task_type_id, shift.task_type_id,
self.attendance_sheet_shift_model.default_task_type_id(), self.attendance_sheet_shift_model.default_task_type_id(),
@ -298,7 +298,7 @@ class TestAttendanceSheet(TransactionCase):
sheet_1.added_shift_ids |= sheet_1.added_shift_ids.new( sheet_1.added_shift_ids |= sheet_1.added_shift_ids.new(
{ {
"task_type_id": sheet_1.added_shift_ids.default_task_type_id(), "task_type_id": sheet_1.added_shift_ids.default_task_type_id(),
"stage": "present",
"state": "present",
"attendance_sheet_id": sheet_1.id, "attendance_sheet_id": sheet_1.id,
"worker_id": self.worker_regular_1.id, "worker_id": self.worker_regular_1.id,
"regular_task_type": "normal", "regular_task_type": "normal",

16
beesdoo_shift/views/attendance_sheet.xml

@ -31,9 +31,10 @@
<field name="model">beesdoo.shift.sheet.expected</field> <field name="model">beesdoo.shift.sheet.expected</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree editable="bottom" create="false" delete="false" open="false" <tree editable="bottom" create="false" delete="false" open="false"
decoration-danger="stage == 'absent_0' or stage == 'absent_1' or stage == 'absent_2'"
decoration-success="stage == 'present'">
decoration-danger="state == 'absent'"
decoration-success="state == 'done'">
<field name="task_type_id" readonly="True" options="{'no_open': True}"/> <field name="task_type_id" readonly="True" options="{'no_open': True}"/>
<field name="super_coop_id" readonly="True" options="{'no_open': True}"/>
<field name="worker_id" readonly="True" options="{'no_open': True}"/> <field name="worker_id" readonly="True" options="{'no_open': True}"/>
<field name="working_mode" /> <field name="working_mode" />
<field name="replacement_worker_id" <field name="replacement_worker_id"
@ -57,7 +58,7 @@
<field name="model">beesdoo.shift.sheet.added</field> <field name="model">beesdoo.shift.sheet.added</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree editable="bottom" <tree editable="bottom"
decoration-success="stage == 'present'">
decoration-success="state == 'done'">
<field name="task_type_id" <field name="task_type_id"
options="{'no_open': True, 'no_create': True, 'no_create_edit':True }" /> options="{'no_open': True, 'no_create': True, 'no_create_edit':True }" />
<field name="worker_id" <field name="worker_id"
@ -66,7 +67,7 @@
<field name="is_compensation" <field name="is_compensation"
attrs="{'invisible': attrs="{'invisible':
[('working_mode','=','irregular')]}"/> [('working_mode','=','irregular')]}"/>
<field name="stage" readonly="True" />
<field name="state" readonly="True" />
</tree> </tree>
</field> </field>
</record> </record>
@ -82,7 +83,7 @@
<field name="worker_id" options="{'no_open': True}" /> <field name="worker_id" options="{'no_open': True}" />
<field name="working_mode" options="{'no_open': True}" /> <field name="working_mode" options="{'no_open': True}" />
<field name="replacement_worker_id" options="{'no_open': True}" /> <field name="replacement_worker_id" options="{'no_open': True}" />
<field name="stage" options="{'no_open': True}" />
<field name="state" options="{'no_open': True}" />
</group> </group>
</form> </form>
</field> </field>
@ -98,10 +99,7 @@
<field name="task_type_id" options="{'no_open': True}" /> <field name="task_type_id" options="{'no_open': True}" />
<field name="worker_id" options="{'no_open': True}" /> <field name="worker_id" options="{'no_open': True}" />
<field name="working_mode" options="{'no_open': True}" /> <field name="working_mode" options="{'no_open': True}" />
<field name="is_compensation" options="{'no_open': True}"
attrs="{'readonly':
[('working_mode','=','irregular')]}"
/>
<field name="is_compensation" options="{'no_open': True}" />
<field name="state" options="{'no_open': True}" /> <field name="state" options="{'no_open': True}" />
</group> </group>
</form> </form>

Loading…
Cancel
Save