|
|
@ -2,7 +2,8 @@ |
|
|
|
# Copyright 2019 - Today Coop IT Easy SCRLfs (<http://www.coopiteasy.be>) |
|
|
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
|
|
|
|
|
|
|
from datetime import date, datetime, timedelta |
|
|
|
import time |
|
|
|
from datetime import datetime, timedelta |
|
|
|
|
|
|
|
from openerp import exceptions, fields |
|
|
|
from openerp.exceptions import UserError, ValidationError |
|
|
@ -33,6 +34,10 @@ class TestAttendanceSheet(TransactionCase): |
|
|
|
"beesdoo_shift.beesdoo_shift_user_2_demo" |
|
|
|
) |
|
|
|
|
|
|
|
self.setting_wizard = self.env["beesdoo.shift.config.settings"].sudo( |
|
|
|
self.user_admin |
|
|
|
) |
|
|
|
|
|
|
|
self.worker_regular_1 = self.env.ref( |
|
|
|
"beesdoo_base.res_partner_cooperator_6_demo" |
|
|
|
) |
|
|
@ -69,24 +74,33 @@ class TestAttendanceSheet(TransactionCase): |
|
|
|
"beesdoo_shift.beesdoo_shift_task_template_2_demo" |
|
|
|
) |
|
|
|
|
|
|
|
# Set time in and out of generation interval parameter |
|
|
|
self.start_in_1 = self.current_time + timedelta(seconds=2) |
|
|
|
self.end_in_1 = self.current_time + timedelta(minutes=10) |
|
|
|
self.start_in_2 = self.current_time + timedelta(minutes=9) |
|
|
|
self.end_in_2 = self.current_time + timedelta(minutes=21) |
|
|
|
self.start_out_1 = self.current_time - timedelta(minutes=50) |
|
|
|
self.end_out_1 = self.current_time - timedelta(minutes=20) |
|
|
|
self.start_out_2 = self.current_time + timedelta(minutes=40) |
|
|
|
self.end_out_2 = self.current_time + timedelta(minutes=50) |
|
|
|
|
|
|
|
self.shift_regular_regular_1 = self.shift_model.create( |
|
|
|
{ |
|
|
|
"task_template_id": self.task_template_1.id, |
|
|
|
"task_type_id": self.task_type_1.id, |
|
|
|
"worker_id": self.worker_regular_1.id, |
|
|
|
"start_time": self.current_time + timedelta(minutes=5), |
|
|
|
"end_time": self.current_time + timedelta(minutes=10), |
|
|
|
"start_time": self.start_in_1, |
|
|
|
"end_time": self.end_in_1, |
|
|
|
"is_regular": True, |
|
|
|
"is_compensation": False, |
|
|
|
} |
|
|
|
) |
|
|
|
self.shift_regular_regular_2 = self.shift_model.create( |
|
|
|
{ |
|
|
|
"task_template_id": self.task_template_2.id, |
|
|
|
"task_type_id": self.task_type_2.id, |
|
|
|
"worker_id": self.worker_regular_2.id, |
|
|
|
"start_time": self.current_time - timedelta(minutes=50), |
|
|
|
"end_time": self.current_time - timedelta(minutes=20), |
|
|
|
"start_time": self.start_out_1, |
|
|
|
"end_time": self.end_out_1, |
|
|
|
"is_regular": True, |
|
|
|
"is_compensation": False, |
|
|
|
} |
|
|
@ -96,8 +110,8 @@ class TestAttendanceSheet(TransactionCase): |
|
|
|
"task_template_id": self.task_template_1.id, |
|
|
|
"task_type_id": self.task_type_3.id, |
|
|
|
"worker_id": self.worker_regular_3.id, |
|
|
|
"start_time": self.current_time + timedelta(minutes=5), |
|
|
|
"end_time": self.current_time + timedelta(minutes=10), |
|
|
|
"start_time": self.start_in_1, |
|
|
|
"end_time": self.end_in_1, |
|
|
|
"is_regular": True, |
|
|
|
"is_compensation": False, |
|
|
|
"replaced_id": self.worker_regular_2.id, |
|
|
@ -108,53 +122,52 @@ class TestAttendanceSheet(TransactionCase): |
|
|
|
"task_template_id": self.task_template_2.id, |
|
|
|
"task_type_id": self.task_type_1.id, |
|
|
|
"worker_id": self.worker_regular_super_1.id, |
|
|
|
"start_time": self.current_time + timedelta(minutes=9), |
|
|
|
"end_time": self.current_time + timedelta(minutes=21), |
|
|
|
"start_time": self.start_in_2, |
|
|
|
"end_time": self.end_in_2, |
|
|
|
"is_regular": False, |
|
|
|
"is_compensation": True, |
|
|
|
} |
|
|
|
) |
|
|
|
self.shift_irregular_1 = self.shift_model.create( |
|
|
|
{ |
|
|
|
"task_template_id": self.task_template_2.id, |
|
|
|
"task_template_id": self.task_template_1.id, |
|
|
|
"task_type_id": self.task_type_2.id, |
|
|
|
"worker_id": self.worker_irregular_1.id, |
|
|
|
"start_time": self.current_time + timedelta(minutes=5), |
|
|
|
"end_time": self.current_time + timedelta(minutes=10), |
|
|
|
"start_time": self.start_in_1, |
|
|
|
"end_time": self.end_in_1, |
|
|
|
} |
|
|
|
) |
|
|
|
self.shift_irregular_2 = self.shift_model.create( |
|
|
|
{ |
|
|
|
"task_template_id": self.task_template_1.id, |
|
|
|
"task_type_id": self.task_type_3.id, |
|
|
|
"worker_id": self.worker_irregular_2.id, |
|
|
|
"start_time": self.current_time + timedelta(minutes=40), |
|
|
|
"end_time": self.current_time + timedelta(minutes=50), |
|
|
|
"start_time": self.start_out_2, |
|
|
|
"end_time": self.end_out_2, |
|
|
|
} |
|
|
|
) |
|
|
|
self.shift_empty_1 = self.shift_model.create( |
|
|
|
{ |
|
|
|
"task_template_id": self.task_template_2.id, |
|
|
|
"task_template_id": self.task_template_1.id, |
|
|
|
"task_type_id": self.task_type_1.id, |
|
|
|
"start_time": self.current_time + timedelta(minutes=5), |
|
|
|
"end_time": self.current_time + timedelta(minutes=10), |
|
|
|
"start_time": self.start_in_1, |
|
|
|
"end_time": self.end_in_1, |
|
|
|
} |
|
|
|
) |
|
|
|
|
|
|
|
def _search_sheets(self, start_time, end_time): |
|
|
|
def search_sheets(self, start_time, end_time): |
|
|
|
if (type(start_time) and type(end_time)) == datetime: |
|
|
|
start_time = fields.Datetime.to_string(start_time) |
|
|
|
end_time = fields.Datetime.to_string(end_time) |
|
|
|
return self.attendance_sheet_model.search( |
|
|
|
[("start_time", "=", start_time), ("end_time", "=", end_time)] |
|
|
|
) |
|
|
|
|
|
|
|
def test_default_task_type_setting(self): |
|
|
|
"Test default task type setting" |
|
|
|
setting_wizard = self.env["beesdoo.shift.config.settings"].sudo( |
|
|
|
self.user_admin |
|
|
|
) |
|
|
|
|
|
|
|
for task_type in (self.task_type_1, self.task_type_2): |
|
|
|
# setting default value |
|
|
|
setting_wizard_1 = setting_wizard.create( |
|
|
|
# Setting default value |
|
|
|
setting_wizard_1 = self.setting_wizard.create( |
|
|
|
{"default_task_type_id": task_type.id} |
|
|
|
) |
|
|
|
setting_wizard_1.execute() |
|
|
@ -162,7 +175,7 @@ class TestAttendanceSheet(TransactionCase): |
|
|
|
"beesdoo_shift.default_task_type_id" |
|
|
|
) |
|
|
|
self.assertEquals(int(param_id), task_type.id) |
|
|
|
# check propagation on attendance sheet shifts |
|
|
|
# Check propagation on attendance sheet shifts |
|
|
|
self.assertEquals( |
|
|
|
self.attendance_sheet_shift_model.default_task_type_id(), |
|
|
|
task_type, |
|
|
@ -171,36 +184,47 @@ class TestAttendanceSheet(TransactionCase): |
|
|
|
def test_attendance_sheet_creation(self): |
|
|
|
"Test creation of an attendance sheet with all its expected shifts" |
|
|
|
|
|
|
|
start_in_1 = self.shift_regular_regular_1.start_time |
|
|
|
end_in_1 = self.shift_regular_regular_1.end_time |
|
|
|
start_in_2 = self.shift_regular_compensation_1.start_time |
|
|
|
end_in_2 = self.shift_regular_compensation_1.end_time |
|
|
|
start_out_1 = self.shift_regular_regular_2.start_time |
|
|
|
end_out_1 = self.shift_regular_regular_2.end_time |
|
|
|
start_out_2 = self.shift_irregular_2.start_time |
|
|
|
end_out_2 = self.shift_irregular_2.end_time |
|
|
|
# Set generation interval setting |
|
|
|
setting_wizard_1 = self.setting_wizard.create( |
|
|
|
{ |
|
|
|
"default_task_type_id": self.task_type_1.id, |
|
|
|
"attendance_sheet_generation_interval": 15, |
|
|
|
} |
|
|
|
) |
|
|
|
setting_wizard_1.execute() |
|
|
|
|
|
|
|
# test attendance sheets creation |
|
|
|
# Test attendance sheets creation |
|
|
|
self.attendance_sheet_model._generate_attendance_sheet() |
|
|
|
|
|
|
|
self.assertEquals(len(self._search_sheets(start_in_1, end_in_1)), 1) |
|
|
|
self.assertEquals(len(self._search_sheets(start_in_2, end_in_2)), 1) |
|
|
|
self.assertEquals(len(self._search_sheets(start_out_1, end_out_1)), 0) |
|
|
|
self.assertEquals(len(self._search_sheets(start_out_2, end_out_2)), 0) |
|
|
|
self.assertEquals( |
|
|
|
len(self.search_sheets(self.start_in_1, self.end_in_1)), 1 |
|
|
|
) |
|
|
|
self.assertEquals( |
|
|
|
len(self.search_sheets(self.start_in_2, self.end_in_2)), 1 |
|
|
|
) |
|
|
|
self.assertEquals( |
|
|
|
len(self.search_sheets(self.start_out_1, self.end_out_1)), 0 |
|
|
|
) |
|
|
|
self.assertEquals( |
|
|
|
len(self.search_sheets(self.start_out_2, self.end_out_2)), 0 |
|
|
|
) |
|
|
|
|
|
|
|
# test expected shifts creation |
|
|
|
sheet_1 = self._search_sheets(start_in_1, end_in_1) |
|
|
|
sheet_2 = self._search_sheets(start_in_2, end_in_2) |
|
|
|
# Test expected shifts creation |
|
|
|
# Sheet 1 starts at current time + 2 secs, ends at current time + 10 min |
|
|
|
# Sheet 2 starts at current time + 9 min, ends at current time + 21 min |
|
|
|
|
|
|
|
sheet_1 = self.search_sheets(self.start_in_1, self.end_in_1) |
|
|
|
sheet_2 = self.search_sheets(self.start_in_2, self.end_in_2) |
|
|
|
|
|
|
|
self.assertTrue(sheet_1.start_time) |
|
|
|
self.assertTrue(sheet_1.end_time) |
|
|
|
|
|
|
|
# empty shift should not be added |
|
|
|
# Empty shift should not be added |
|
|
|
self.assertEquals(len(sheet_1.expected_shift_ids), 3) |
|
|
|
self.assertEquals(len(sheet_1.added_shift_ids), 0) |
|
|
|
self.assertEquals(len(sheet_2.expected_shift_ids), 1) |
|
|
|
|
|
|
|
# test consistency with actual shift |
|
|
|
# Test consistency with actual shift for sheet 1 |
|
|
|
for shift in sheet_1.expected_shift_ids: |
|
|
|
self.assertEquals(shift.worker_id, shift.task_id.worker_id) |
|
|
|
self.assertEquals( |
|
|
@ -210,73 +234,73 @@ class TestAttendanceSheet(TransactionCase): |
|
|
|
self.assertEquals(shift.super_coop_id, shift.task_id.super_coop_id) |
|
|
|
self.assertEquals(shift.working_mode, shift.task_id.working_mode) |
|
|
|
|
|
|
|
if shift.working_mode == "regular": |
|
|
|
self.assertEquals(shift.state, "absent_2") |
|
|
|
if shift.working_mode == "irregular": |
|
|
|
self.assertEquals(shift.state, "absent_1") |
|
|
|
# Status should be "absent" for all shifts |
|
|
|
self.assertEquals(shift.state, "absent") |
|
|
|
self.assertEquals(shift.compensation_no, "2") |
|
|
|
|
|
|
|
# test maximum number of workers calculation from task_templates |
|
|
|
self.assertEquals(sheet_1.max_worker_no, 21) |
|
|
|
# Empty shift should be considered in max worker number calculation |
|
|
|
self.assertEquals(sheet_1.max_worker_no, 4) |
|
|
|
|
|
|
|
# test default values creation |
|
|
|
# Test default values creation |
|
|
|
self.assertTrue(sheet_1.time_slot) |
|
|
|
self.assertEquals(sheet_1.day, fields.Date.to_string(self.start_in_1)) |
|
|
|
self.assertEquals(sheet_1.day_abbrevation, "Lundi") |
|
|
|
self.assertEquals(sheet_1.week, "Semaine A") |
|
|
|
self.assertTrue(sheet_1.name) |
|
|
|
day = fields.Datetime.from_string(sheet_1.start_time) |
|
|
|
self.assertEquals(sheet_1.day, fields.Date.to_string(day)) |
|
|
|
self.assertFalse(sheet_1.annotation) |
|
|
|
self.assertFalse(sheet_1.is_annotated) |
|
|
|
|
|
|
|
# test default super-cooperator setting |
|
|
|
self.assertTrue(self.shift_expected_model.default_task_type_id()) |
|
|
|
|
|
|
|
def test_attendance_sheet_barcode_scanner(self): |
|
|
|
"Test edition of an attendance sheet with barcode scanner" |
|
|
|
def test_attendance_sheet_barcode_scan(self): |
|
|
|
""" |
|
|
|
Edition of an attendance sheet |
|
|
|
with barcode scanner, as a generic user" |
|
|
|
""" |
|
|
|
|
|
|
|
# attendance sheet generation |
|
|
|
self.attendance_sheet_model.sudo(self.user_generic)._generate_attendance_sheet() |
|
|
|
sheet_1 = self._search_sheets( |
|
|
|
self.shift_regular_regular_1.start_time, |
|
|
|
self.shift_regular_regular_1.end_time, |
|
|
|
) |
|
|
|
# Attendance sheet generation |
|
|
|
self.attendance_sheet_model.sudo( |
|
|
|
self.user_generic |
|
|
|
)._generate_attendance_sheet() |
|
|
|
sheet_1 = self.search_sheets(self.start_in_1, self.end_in_1,) |
|
|
|
|
|
|
|
""" |
|
|
|
Expected workers : |
|
|
|
Expected workers are : |
|
|
|
worker_regular_1 (barcode : 421457731745) |
|
|
|
worker_regular_3 replaced by worker_regular_2 (barcode : 421457731744)) |
|
|
|
worker_irregular_1 (barcode : 429919251493) |
|
|
|
""" |
|
|
|
|
|
|
|
# scan barcode for expected workers |
|
|
|
# Scan barcode for expected workers |
|
|
|
for barcode in [421457731745, 421457731744, 429919251493]: |
|
|
|
sheet_1.on_barcode_scanned(barcode) |
|
|
|
|
|
|
|
# check expected shifts update |
|
|
|
# Check expected shifts update |
|
|
|
for id in sheet_1.expected_shift_ids.ids: |
|
|
|
shift = sheet_1.expected_shift_ids.browse(id) |
|
|
|
self.assertEquals(shift.state, "present") |
|
|
|
self.assertEquals(shift.state, "done") |
|
|
|
|
|
|
|
""" |
|
|
|
Added workers : |
|
|
|
Added workers are : |
|
|
|
worker_regular_super_1 (barcode : 421457731741) |
|
|
|
worker_irregular_2 (barcode : 421457731743) |
|
|
|
""" |
|
|
|
|
|
|
|
# _onchange method not applying on temporary object in tests |
|
|
|
# Workararound for _onchange method |
|
|
|
# (not applying on temporary object in tests) |
|
|
|
sheet_1._origin = sheet_1 |
|
|
|
|
|
|
|
# scan barcode for added workers |
|
|
|
# Scan barcode for added workers |
|
|
|
sheet_1.on_barcode_scanned(421457731741) |
|
|
|
self.assertEquals(len(sheet_1.added_shift_ids), 1) |
|
|
|
sheet_1.on_barcode_scanned(421457731743) |
|
|
|
# scan an already added worker should not change anything |
|
|
|
# Scan an already added worker should not change anything |
|
|
|
sheet_1.on_barcode_scanned(421457731743) |
|
|
|
self.assertEquals(len(sheet_1.added_shift_ids), 2) |
|
|
|
|
|
|
|
# check added shifts fields |
|
|
|
# Check added shifts fields |
|
|
|
for id in sheet_1.added_shift_ids.ids: |
|
|
|
shift = sheet_1.added_shift_ids.browse(id) |
|
|
|
self.assertEquals(sheet_1, shift.attendance_sheet_id) |
|
|
|
self.assertEquals(shift.state, "present") |
|
|
|
self.assertEquals(shift.state, "done") |
|
|
|
self.assertEquals( |
|
|
|
shift.task_type_id, |
|
|
|
self.attendance_sheet_shift_model.default_task_type_id(), |
|
|
@ -286,21 +310,103 @@ class TestAttendanceSheet(TransactionCase): |
|
|
|
else: |
|
|
|
self.assertFalse(shift.is_compensation) |
|
|
|
|
|
|
|
# add a worker that should be replaced |
|
|
|
# Add a worker that should be replaced |
|
|
|
with self.assertRaises(UserError) as e: |
|
|
|
sheet_1.on_barcode_scanned(421457731742) |
|
|
|
# wrong barcode |
|
|
|
# Wrong barcode |
|
|
|
with self.assertRaises(UserError) as e: |
|
|
|
sheet_1.on_barcode_scanned(101010) |
|
|
|
|
|
|
|
# add an already expected worker |
|
|
|
with self.assertRaises(ValidationError) as e: |
|
|
|
# Add an unsubscribed worker |
|
|
|
self.worker_regular_1.cooperative_status_ids.sr = -2 |
|
|
|
self.worker_regular_1.cooperative_status_ids.sc = -2 |
|
|
|
with self.assertRaises(UserError) as e: |
|
|
|
sheet_1.on_barcode_scanned(421457731745) |
|
|
|
|
|
|
|
def test_attendance_sheet_edition(self): |
|
|
|
|
|
|
|
# Attendance sheet generation |
|
|
|
self.attendance_sheet_model.sudo( |
|
|
|
self.user_generic |
|
|
|
)._generate_attendance_sheet() |
|
|
|
sheet_1 = self.search_sheets(self.start_in_1, self.end_in_1) |
|
|
|
|
|
|
|
# Expected shifts edition |
|
|
|
sheet_1.expected_shift_ids[1].state = "done" |
|
|
|
sheet_1.expected_shift_ids[1].compensation_no = False |
|
|
|
sheet_1.expected_shift_ids[2].compensation_no = "1" |
|
|
|
|
|
|
|
# Added shits addition |
|
|
|
sheet_1.added_shift_ids |= sheet_1.added_shift_ids.new( |
|
|
|
{ |
|
|
|
"task_type_id": sheet_1.added_shift_ids.default_task_type_id(), |
|
|
|
"state": "present", |
|
|
|
"task_type_id": self.task_type_2.id, |
|
|
|
"state": "done", |
|
|
|
"attendance_sheet_id": sheet_1.id, |
|
|
|
"worker_id": self.worker_regular_1.id, |
|
|
|
"regular_task_type": "normal", |
|
|
|
"worker_id": self.worker_regular_super_1.id, |
|
|
|
"is_compensation": False, |
|
|
|
} |
|
|
|
) |
|
|
|
# Same task type as empty shift (should edit it on validation) |
|
|
|
sheet_1.added_shift_ids |= sheet_1.added_shift_ids.new( |
|
|
|
{ |
|
|
|
"task_type_id": self.task_type_1.id, |
|
|
|
"state": "done", |
|
|
|
"attendance_sheet_id": sheet_1.id, |
|
|
|
"worker_id": self.worker_irregular_2.id, |
|
|
|
"is_compensation": True, |
|
|
|
} |
|
|
|
) |
|
|
|
|
|
|
|
# Wait necessary time for shifts to begin |
|
|
|
waiting_time = (self.start_in_1 - datetime.now()).total_seconds() |
|
|
|
if waiting_time > 0: |
|
|
|
with self.assertRaises(UserError) as e: |
|
|
|
sheet_1.validate_with_checks() |
|
|
|
self.assertIn("wait", str(e.exception)) |
|
|
|
time.sleep(waiting_time) |
|
|
|
|
|
|
|
# TODO: test validation with wizard (as generic user) |
|
|
|
# class odoo.tests.common.Form(recordp, view=None) |
|
|
|
# is only available from version 12 |
|
|
|
|
|
|
|
# sheet_1 = sheet_1.sudo(self.user_generic) |
|
|
|
|
|
|
|
# Validation without wizard (as admin user) |
|
|
|
sheet_1 = sheet_1.sudo(self.user_admin) |
|
|
|
sheet_1.worker_nb_feedback = "enough" |
|
|
|
sheet_1.feedback = "Great session." |
|
|
|
sheet_1.notes = "Important information." |
|
|
|
|
|
|
|
sheet_1.validate_with_checks() |
|
|
|
|
|
|
|
with self.assertRaises(UserError) as e: |
|
|
|
sheet_1.validate_with_checks() |
|
|
|
self.assertIn("already been validated", str(e.exception)) |
|
|
|
|
|
|
|
self.assertEquals(sheet_1.state, "validated") |
|
|
|
self.assertEquals(sheet_1.validated_by, self.user_admin.partner_id) |
|
|
|
self.assertTrue(sheet_1.is_annotated) |
|
|
|
self.assertFalse(sheet_1.is_read) |
|
|
|
|
|
|
|
# Check actual shifts update |
|
|
|
workers = sheet_1.expected_shift_ids.mapped( |
|
|
|
"worker_id" |
|
|
|
) | sheet_1.added_shift_ids.mapped("worker_id") |
|
|
|
self.assertEquals(len(workers), 5) |
|
|
|
self.assertEquals( |
|
|
|
sheet_1.expected_shift_ids[0].task_id.state, "absent_2" |
|
|
|
) |
|
|
|
self.assertEquals(sheet_1.expected_shift_ids[1].task_id.state, "done") |
|
|
|
self.assertEquals( |
|
|
|
sheet_1.expected_shift_ids[2].task_id.state, "absent_1" |
|
|
|
) |
|
|
|
self.assertEquals(sheet_1.added_shift_ids[0].task_id.state, "done") |
|
|
|
self.assertEquals(sheet_1.added_shift_ids[1].task_id.state, "done") |
|
|
|
|
|
|
|
# Empty shift should have been updated |
|
|
|
self.assertEquals( |
|
|
|
sheet_1.added_shift_ids[0].task_id, self.shift_empty_1 |
|
|
|
) |
|
|
|
|
|
|
|
# sheet_1.expected_shift_ids[0].worker_id |
|
|
|
# sheet_1.expected_shift_ids[2].replacement_worker_id |