[MIG] hr_luncheon_voucher: migrate to 18.0
This commit is contained in:
3
hr_luncheon_voucher/tests/__init__.py
Normal file
3
hr_luncheon_voucher/tests/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from . import test_hr_employee
|
||||
from . import test_hr_lv_allocation
|
||||
from . import test_generate_lv_allocations_wizard
|
||||
112
hr_luncheon_voucher/tests/test_generate_lv_allocations_wizard.py
Normal file
112
hr_luncheon_voucher/tests/test_generate_lv_allocations_wizard.py
Normal file
@@ -0,0 +1,112 @@
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestGenerateLvAllocationsWizard(TransactionCase):
|
||||
"""Tests for generate.lv.allocation.requests wizard."""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.employee_admin = cls.env.ref("hr.employee_admin")
|
||||
cls.employee_other = cls.env["hr.employee"].create(
|
||||
{
|
||||
"name": "Other Employee",
|
||||
"resource_calendar_id": cls.employee_admin.resource_calendar_id.id,
|
||||
}
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# generate_lv_allocations
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_generate_for_single_employee(self):
|
||||
"""Wizard creates one allocation for the selected employee."""
|
||||
wizard = self._create_wizard()
|
||||
# Simulate single employee selection
|
||||
ctx = {"active_ids": [self.employee_admin.id]}
|
||||
wizard = wizard.with_context(**ctx)
|
||||
wizard.generate_lv_allocations()
|
||||
|
||||
allocations = self.env["hr.lv.allocation"].search(
|
||||
[("distrib_campaign_name", "=", "March 2026")]
|
||||
)
|
||||
self.assertEqual(len(allocations), 1)
|
||||
self.assertEqual(allocations.employee_id, self.employee_admin)
|
||||
|
||||
def test_generate_for_multiple_employees(self):
|
||||
"""Wizard creates one allocation per selected employee."""
|
||||
wizard = self._create_wizard()
|
||||
ctx = {
|
||||
"active_ids": [
|
||||
self.employee_admin.id,
|
||||
self.employee_other.id,
|
||||
]
|
||||
}
|
||||
wizard = wizard.with_context(**ctx)
|
||||
wizard.generate_lv_allocations()
|
||||
|
||||
allocations = self.env["hr.lv.allocation"].search(
|
||||
[("distrib_campaign_name", "=", "March 2026")]
|
||||
)
|
||||
self.assertEqual(len(allocations), 2)
|
||||
|
||||
def test_generate_allocation_name_format(self):
|
||||
"""Allocation name follows 'campaign - employee' pattern."""
|
||||
wizard = self._create_wizard()
|
||||
ctx = {"active_ids": [self.employee_admin.id]}
|
||||
wizard = wizard.with_context(**ctx)
|
||||
wizard.generate_lv_allocations()
|
||||
|
||||
alloc = self.env["hr.lv.allocation"].search(
|
||||
[("distrib_campaign_name", "=", "March 2026")]
|
||||
)
|
||||
expected_name = f"March 2026 - {self.employee_admin.name}"
|
||||
self.assertEqual(alloc.name, expected_name)
|
||||
|
||||
def test_generate_allocations_have_dates(self):
|
||||
"""Allocations carry the wizard's date range."""
|
||||
wizard = self._create_wizard()
|
||||
ctx = {"active_ids": [self.employee_admin.id]}
|
||||
wizard = wizard.with_context(**ctx)
|
||||
wizard.generate_lv_allocations()
|
||||
|
||||
alloc = self.env["hr.lv.allocation"].search(
|
||||
[("distrib_campaign_name", "=", "March 2026")]
|
||||
)
|
||||
self.assertEqual(alloc.date_from, wizard.date_from)
|
||||
self.assertEqual(alloc.date_to, wizard.date_to)
|
||||
|
||||
def test_generate_allocations_start_in_draft(self):
|
||||
"""New allocations start in 'draft' state."""
|
||||
wizard = self._create_wizard()
|
||||
ctx = {"active_ids": [self.employee_admin.id]}
|
||||
wizard = wizard.with_context(**ctx)
|
||||
wizard.generate_lv_allocations()
|
||||
|
||||
alloc = self.env["hr.lv.allocation"].search(
|
||||
[("distrib_campaign_name", "=", "March 2026")]
|
||||
)
|
||||
self.assertEqual(alloc.state, "draft")
|
||||
|
||||
def test_generate_returns_action(self):
|
||||
"""The wizard returns an action dict (act_window)."""
|
||||
wizard = self._create_wizard()
|
||||
ctx = {"active_ids": [self.employee_admin.id]}
|
||||
wizard = wizard.with_context(**ctx)
|
||||
action = wizard.generate_lv_allocations()
|
||||
self.assertIn("type", action)
|
||||
self.assertEqual(action["type"], "ir.actions.act_window")
|
||||
self.assertEqual(action["res_model"], "hr.lv.allocation")
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _create_wizard(self):
|
||||
return self.env["generate.lv.allocation.requests"].create(
|
||||
{
|
||||
"distrib_campaign_name": "March 2026",
|
||||
"date_from": "2026-03-01",
|
||||
"date_to": "2026-03-31",
|
||||
}
|
||||
)
|
||||
169
hr_luncheon_voucher/tests/test_hr_employee.py
Normal file
169
hr_luncheon_voucher/tests/test_hr_employee.py
Normal file
@@ -0,0 +1,169 @@
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestHrEmployee(TransactionCase):
|
||||
"""Tests for hr.employee extensions (_compute*, generate_lv_allocation)."""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
# Use a demo employee (created by hr module)
|
||||
cls.employee = cls.env.ref("hr.employee_admin")
|
||||
# Ensure a clean slate
|
||||
cls.employee.write(
|
||||
{
|
||||
"total_acquired_lv": 0,
|
||||
"distributed_lv": 0,
|
||||
"dued_lv": 0,
|
||||
}
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# _compute_total_acquired_lv
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_compute_total_acquired_lv_no_allocations(self):
|
||||
"""No allocations → total_acquired_lv is 0."""
|
||||
self.employee.refresh_lv_values()
|
||||
self.assertEqual(self.employee.total_acquired_lv, 0)
|
||||
|
||||
def test_compute_total_acquired_lv_with_allocations(self):
|
||||
"""Confirmed + distributed allocations are summed."""
|
||||
self._create_allocation(state="confirmed", number_acquired_lv=5)
|
||||
self._create_allocation(state="distributed", number_acquired_lv=3)
|
||||
self.employee.refresh_lv_values()
|
||||
self.assertEqual(self.employee.total_acquired_lv, 8)
|
||||
|
||||
def test_compute_total_acquired_lv_excludes_draft(self):
|
||||
"""Draft allocations are NOT counted."""
|
||||
self._create_allocation(state="draft", number_acquired_lv=10)
|
||||
self.employee.refresh_lv_values()
|
||||
self.assertEqual(self.employee.total_acquired_lv, 0)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# _compute_distributed_lv
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_compute_distributed_lv_no_allocations(self):
|
||||
"""No allocations → distributed_lv is 0."""
|
||||
self.employee.refresh_lv_values()
|
||||
self.assertEqual(self.employee.distributed_lv, 0)
|
||||
|
||||
def test_compute_distributed_lv_only_distributed(self):
|
||||
"""Only 'distributed' state allocations are counted."""
|
||||
self._create_allocation(state="distributed", number_distributed_lv=4)
|
||||
self._create_allocation(state="confirmed", number_distributed_lv=2)
|
||||
self._create_allocation(state="draft", number_distributed_lv=1)
|
||||
self.employee.refresh_lv_values()
|
||||
self.assertEqual(self.employee.distributed_lv, 4)
|
||||
|
||||
def test_compute_distributed_lv_multiple_distributed(self):
|
||||
"""Multiple distributed allocations are summed."""
|
||||
self._create_allocation(state="distributed", number_distributed_lv=3)
|
||||
self._create_allocation(state="distributed", number_distributed_lv=7)
|
||||
self.employee.refresh_lv_values()
|
||||
self.assertEqual(self.employee.distributed_lv, 10)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# _compute_dued_lv
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_compute_dued_lv(self):
|
||||
"""dued_lv = total_acquired_lv - distributed_lv."""
|
||||
self.employee.write(
|
||||
{"total_acquired_lv": 20, "distributed_lv": 6}
|
||||
)
|
||||
self.employee._compute_dued_lv()
|
||||
self.assertEqual(self.employee.dued_lv, 14)
|
||||
|
||||
def test_compute_dued_lv_zero_when_equal(self):
|
||||
"""dued_lv is 0 when acquired equals distributed."""
|
||||
self.employee.write(
|
||||
{"total_acquired_lv": 10, "distributed_lv": 10}
|
||||
)
|
||||
self.employee._compute_dued_lv()
|
||||
self.assertEqual(self.employee.dued_lv, 0)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# generate_lv_allocation
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_generate_lv_allocation_creates_record(self):
|
||||
"""generate_lv_allocation creates an hr.lv.allocation with correct values."""
|
||||
campaign_name = "Test Campaign"
|
||||
values = {
|
||||
"distrib_campaign_name": campaign_name,
|
||||
"date_from": "2026-01-01",
|
||||
"date_to": "2026-01-31",
|
||||
}
|
||||
self.employee.generate_lv_allocation(values)
|
||||
alloc = self.env["hr.lv.allocation"].search(
|
||||
[
|
||||
("employee_id", "=", self.employee.id),
|
||||
("distrib_campaign_name", "=", campaign_name),
|
||||
]
|
||||
)
|
||||
self.assertTrue(alloc)
|
||||
self.assertEqual(len(alloc), 1)
|
||||
self.assertEqual(alloc.distrib_campaign_name, campaign_name)
|
||||
self.assertEqual(alloc.employee_id, self.employee)
|
||||
self.assertIn(self.employee.name, alloc.name)
|
||||
|
||||
def test_generate_lv_allocation_sets_employee_id(self):
|
||||
"""The passed employee_id in values is overridden by the record's own id."""
|
||||
other = self.env["hr.employee"].create(
|
||||
{
|
||||
"name": "Other Employee",
|
||||
"resource_calendar_id": self.employee.resource_calendar_id.id,
|
||||
}
|
||||
)
|
||||
values = {
|
||||
"distrib_campaign_name": "Campaign Override",
|
||||
"employee_id": other.id,
|
||||
"date_from": "2026-02-01",
|
||||
"date_to": "2026-02-28",
|
||||
}
|
||||
self.employee.generate_lv_allocation(values)
|
||||
alloc = self.env["hr.lv.allocation"].search(
|
||||
[("distrib_campaign_name", "=", "Campaign Override")]
|
||||
)
|
||||
self.assertEqual(alloc.employee_id, self.employee)
|
||||
|
||||
def test_generate_lv_allocation_updates_counters(self):
|
||||
"""After creation, acquired and due are computed (triggers create logic)."""
|
||||
values = {
|
||||
"distrib_campaign_name": "Counters Check",
|
||||
"date_from": "2026-03-01",
|
||||
"date_to": "2026-03-31",
|
||||
}
|
||||
self.employee.generate_lv_allocation(values)
|
||||
alloc = self.env["hr.lv.allocation"].search(
|
||||
[("distrib_campaign_name", "=", "Counters Check")]
|
||||
)
|
||||
# number_acquired_lv should be computed (may be 0 on non-working days)
|
||||
self.assertIsNotNone(alloc.number_acquired_lv)
|
||||
self.assertIsNotNone(alloc.number_dued_lv)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _create_allocation(self, **kwargs):
|
||||
# Extract numeric fields that create() overrides, to set them after creation
|
||||
numeric_fields = {
|
||||
k: kwargs.pop(k)
|
||||
for k in ["number_acquired_lv", "number_dued_lv", "number_distributed_lv"]
|
||||
if k in kwargs
|
||||
}
|
||||
defaults = {
|
||||
"employee_id": self.employee.id,
|
||||
"distrib_campaign_name": "Test",
|
||||
"date_from": "2026-01-01",
|
||||
"date_to": "2026-01-31",
|
||||
"name": "Test - Employee",
|
||||
}
|
||||
defaults.update(kwargs)
|
||||
alloc = self.env["hr.lv.allocation"].create(defaults)
|
||||
if numeric_fields:
|
||||
alloc.write(numeric_fields)
|
||||
return alloc
|
||||
317
hr_luncheon_voucher/tests/test_hr_lv_allocation.py
Normal file
317
hr_luncheon_voucher/tests/test_hr_lv_allocation.py
Normal file
@@ -0,0 +1,317 @@
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestHrLvAllocation(TransactionCase):
|
||||
"""Tests for hr.lv.allocation model methods."""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.employee = cls.env.ref("hr.employee_admin")
|
||||
cls.calendar = cls.env.ref("resource.resource_calendar_std")
|
||||
cls.employee.resource_calendar_id = cls.calendar
|
||||
|
||||
# Ensure the calendar has attendances marked as effective periods
|
||||
# (required by hr_effective_attendance_period for is_working_day etc.)
|
||||
Attendance = cls.env["resource.calendar.attendance"]
|
||||
existing = Attendance.search([("calendar_id", "=", cls.calendar.id)])
|
||||
if existing:
|
||||
existing.write({"effective_attendance_period": True})
|
||||
else:
|
||||
for day_idx, day_name in enumerate(
|
||||
["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
|
||||
):
|
||||
Attendance.create(
|
||||
{
|
||||
"calendar_id": cls.calendar.id,
|
||||
"name": f"{day_name} Morning",
|
||||
"dayofweek": str(day_idx),
|
||||
"day_period": "morning",
|
||||
"hour_from": 8,
|
||||
"hour_to": 12,
|
||||
"effective_attendance_period": True,
|
||||
}
|
||||
)
|
||||
Attendance.create(
|
||||
{
|
||||
"calendar_id": cls.calendar.id,
|
||||
"name": f"{day_name} Afternoon",
|
||||
"dayofweek": str(day_idx),
|
||||
"day_period": "afternoon",
|
||||
"hour_from": 13,
|
||||
"hour_to": 17,
|
||||
"effective_attendance_period": True,
|
||||
}
|
||||
)
|
||||
|
||||
cls.allocation = cls._build_allocation(cls)
|
||||
|
||||
# Ensure a cancelling event type exists
|
||||
cls.cancelling_categ = cls.env.ref(
|
||||
"hr_luncheon_voucher.categ_meet_free_lunch",
|
||||
raise_if_not_found=False,
|
||||
)
|
||||
if not cls.cancelling_categ:
|
||||
cls.cancelling_categ = cls.env["calendar.event.type"].create(
|
||||
{"name": "Free Lunch Test", "remove_luncheon_voucher": True}
|
||||
)
|
||||
else:
|
||||
cls.cancelling_categ.remove_luncheon_voucher = True
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _build_allocation(self, **overrides):
|
||||
vals = {
|
||||
"employee_id": self.employee.id,
|
||||
"distrib_campaign_name": "Test Campaign",
|
||||
"date_from": "2026-01-01",
|
||||
"date_to": "2026-01-31",
|
||||
"name": "Test Campaign - Admin",
|
||||
}
|
||||
vals.update(overrides)
|
||||
return self.env["hr.lv.allocation"].create(vals)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# _compute_lv_balance
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_lv_balance_positive(self):
|
||||
"""Balance = number_dued_lv - number_distributed_lv (positive)."""
|
||||
alloc = self._build_allocation()
|
||||
alloc.write(
|
||||
{"number_dued_lv": 10, "number_distributed_lv": 3}
|
||||
)
|
||||
alloc._compute_lv_balance()
|
||||
self.assertEqual(alloc.lv_balance, 7)
|
||||
|
||||
def test_lv_balance_zero(self):
|
||||
"""Balance is 0 when due equals distributed."""
|
||||
alloc = self._build_allocation()
|
||||
alloc.write(
|
||||
{"number_dued_lv": 5, "number_distributed_lv": 5}
|
||||
)
|
||||
alloc._compute_lv_balance()
|
||||
self.assertEqual(alloc.lv_balance, 0)
|
||||
|
||||
def test_lv_balance_negative(self):
|
||||
"""Balance can be negative (over-distribution)."""
|
||||
alloc = self._build_allocation()
|
||||
alloc.write(
|
||||
{"number_dued_lv": 2, "number_distributed_lv": 5}
|
||||
)
|
||||
alloc._compute_lv_balance()
|
||||
self.assertEqual(alloc.lv_balance, -3)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# _has_cancelling_voucher_event
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_has_cancelling_event_true(self):
|
||||
"""Returns True when a cancelling event exists for the employee."""
|
||||
partner = self.employee.user_id.partner_id
|
||||
self.env["calendar.event"].create(
|
||||
{
|
||||
"name": "Team Lunch",
|
||||
"start": "2026-01-15 12:00:00",
|
||||
"stop": "2026-01-15 14:00:00",
|
||||
"categ_ids": [(6, 0, self.cancelling_categ.ids)],
|
||||
"partner_ids": [(4, partner.id)],
|
||||
}
|
||||
)
|
||||
day = self.env.cr.now().replace(day=15, month=1, year=2026)
|
||||
self.assertTrue(self.allocation._has_cancelling_voucher_event(day))
|
||||
|
||||
def test_has_cancelling_event_false_no_event(self):
|
||||
"""Returns False when no cancelling event exists."""
|
||||
day = self.env.cr.now().replace(day=10, month=1, year=2026)
|
||||
self.assertFalse(self.allocation._has_cancelling_voucher_event(day))
|
||||
|
||||
def test_has_cancelling_event_false_non_cancelling_category(self):
|
||||
"""Returns False when events exist but without the cancelling flag."""
|
||||
categ = self.env["calendar.event.type"].create(
|
||||
{"name": "Regular Meeting", "remove_luncheon_voucher": False}
|
||||
)
|
||||
partner = self.employee.user_id.partner_id
|
||||
self.env["calendar.event"].create(
|
||||
{
|
||||
"name": "Stand-up",
|
||||
"start": "2026-01-15 09:00:00",
|
||||
"stop": "2026-01-15 09:30:00",
|
||||
"categ_ids": [(6, 0, categ.ids)],
|
||||
"partner_ids": [(4, partner.id)],
|
||||
}
|
||||
)
|
||||
day = self.env.cr.now().replace(day=15, month=1, year=2026)
|
||||
self.assertFalse(self.allocation._has_cancelling_voucher_event(day))
|
||||
|
||||
def test_has_cancelling_event_outside_day(self):
|
||||
"""Returns False when the event is entirely outside the target day."""
|
||||
partner = self.employee.user_id.partner_id
|
||||
self.env["calendar.event"].create(
|
||||
{
|
||||
"name": "Late Dinner",
|
||||
"start": "2026-01-15 22:00:00",
|
||||
"stop": "2026-01-16 00:30:00",
|
||||
"categ_ids": [(6, 0, self.cancelling_categ.ids)],
|
||||
"partner_ids": [(4, partner.id)],
|
||||
}
|
||||
)
|
||||
# Check a different day
|
||||
day = self.env.cr.now().replace(day=14, month=1, year=2026)
|
||||
self.assertFalse(self.allocation._has_cancelling_voucher_event(day))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# _calculate_number_acquired_lv
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_calculate_acquired_on_non_working_day(self):
|
||||
"""Acquired is 0 for a period of non-working days (e.g. weekend-only)."""
|
||||
alloc = self._build_allocation(
|
||||
date_from="2026-01-03", # Saturday
|
||||
date_to="2026-01-04", # Sunday
|
||||
)
|
||||
alloc._calculate_number_acquired_lv()
|
||||
self.assertEqual(alloc.number_acquired_lv, 0)
|
||||
|
||||
def test_calculate_acquired_basic(self):
|
||||
"""Acquired is > 0 for a normal working period (employee works)."""
|
||||
alloc = self._build_allocation(
|
||||
date_from="2026-01-05", # Monday
|
||||
date_to="2026-01-09", # Friday
|
||||
)
|
||||
alloc._calculate_number_acquired_lv()
|
||||
# Standard 5-day calendar: 5 working days, no leaves, no events
|
||||
self.assertEqual(alloc.number_acquired_lv, 5)
|
||||
|
||||
def test_calculate_acquired_with_leave(self):
|
||||
"""Acquired excludes days covered by leave."""
|
||||
# Create a leave covering Wednesday 2026-01-07
|
||||
self.env["resource.calendar.leaves"].create(
|
||||
{
|
||||
"name": "Sick leave",
|
||||
"date_from": "2026-01-07 00:00:00",
|
||||
"date_to": "2026-01-07 23:59:59",
|
||||
"calendar_id": self.calendar.id,
|
||||
"resource_id": self.employee.resource_id.id,
|
||||
}
|
||||
)
|
||||
alloc = self._build_allocation(
|
||||
date_from="2026-01-05", # Monday
|
||||
date_to="2026-01-09", # Friday
|
||||
)
|
||||
alloc._calculate_number_acquired_lv()
|
||||
# 5 working days - 1 leave = 4
|
||||
self.assertEqual(alloc.number_acquired_lv, 4)
|
||||
|
||||
def test_calculate_acquired_with_half_day_cancel(self):
|
||||
"""When hr_half_day_cancels_voucher is enabled, partial days are excluded."""
|
||||
self.env.company.hr_half_day_cancels_voucher = True
|
||||
# Modify calendar to have only morning attendance on Wednesday
|
||||
wed_attendance = self.env["resource.calendar.attendance"].search(
|
||||
[
|
||||
("calendar_id", "=", self.calendar.id),
|
||||
("dayofweek", "=", "2"), # Wednesday
|
||||
("day_period", "=", "afternoon"),
|
||||
]
|
||||
)
|
||||
wed_attendance.unlink()
|
||||
|
||||
alloc = self._build_allocation(
|
||||
date_from="2026-01-05", # Monday
|
||||
date_to="2026-01-09", # Friday
|
||||
)
|
||||
alloc._calculate_number_acquired_lv()
|
||||
# 4 full days + 1 half-day excluded = 4
|
||||
self.assertEqual(alloc.number_acquired_lv, 4)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# _calculate_number_dued_lv
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_calculate_dued_draft(self):
|
||||
"""In non-distributed state: dued = employee.dued_lv + number_acquired_lv."""
|
||||
self.employee.write({"dued_lv": 5})
|
||||
alloc = self._build_allocation(state="draft")
|
||||
alloc.number_acquired_lv = 10
|
||||
alloc._calculate_number_dued_lv()
|
||||
self.assertEqual(alloc.number_dued_lv, 15)
|
||||
|
||||
def test_calculate_dued_distributed(self):
|
||||
"""In distributed: dued = employee.dued_lv only (no addition)."""
|
||||
self.employee.write({"dued_lv": 8})
|
||||
alloc = self._build_allocation(state="distributed")
|
||||
alloc.number_acquired_lv = 20
|
||||
alloc._calculate_number_dued_lv()
|
||||
self.assertEqual(alloc.number_dued_lv, 8)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# confirm_allocation
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_confirm_draft(self):
|
||||
"""confirm_allocation transitions draft → confirmed and updates counters."""
|
||||
self.employee.write({"total_acquired_lv": 0, "dued_lv": 0})
|
||||
alloc = self._build_allocation(state="draft")
|
||||
alloc.number_acquired_lv = 6
|
||||
alloc.confirm_allocation()
|
||||
self.assertEqual(alloc.state, "confirmed")
|
||||
self.employee.refresh_lv_values()
|
||||
self.assertEqual(self.employee.total_acquired_lv, 6)
|
||||
|
||||
def test_confirm_already_confirmed_does_not_change(self):
|
||||
"""confirm_allocation on a confirmed record is a no-op."""
|
||||
alloc = self._build_allocation(state="confirmed")
|
||||
alloc.confirm_allocation()
|
||||
self.assertEqual(alloc.state, "confirmed")
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# back_to_draft
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_back_to_draft_from_confirmed(self):
|
||||
"""back_to_draft transitions confirmed → draft."""
|
||||
alloc = self._build_allocation(state="confirmed")
|
||||
alloc.back_to_draft()
|
||||
self.assertEqual(alloc.state, "draft")
|
||||
|
||||
def test_back_to_draft_from_distributed(self):
|
||||
"""back_to_draft transitions distributed → draft."""
|
||||
alloc = self._build_allocation(state="distributed")
|
||||
alloc.back_to_draft()
|
||||
self.assertEqual(alloc.state, "draft")
|
||||
|
||||
def test_back_to_draft_draft_is_noop(self):
|
||||
"""back_to_draft on a draft record is a no-op."""
|
||||
alloc = self._build_allocation(state="draft")
|
||||
alloc.back_to_draft()
|
||||
self.assertEqual(alloc.state, "draft")
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# distribute_allocation
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_distribute_confirmed(self):
|
||||
"""distribute_allocation transitions confirmed → distributed."""
|
||||
alloc = self._build_allocation(state="confirmed")
|
||||
alloc.distribute_allocation()
|
||||
self.assertEqual(alloc.state, "distributed")
|
||||
|
||||
def test_distribute_draft_is_noop(self):
|
||||
"""distribute_allocation on draft is a no-op."""
|
||||
alloc = self._build_allocation(state="draft")
|
||||
alloc.distribute_allocation()
|
||||
self.assertEqual(alloc.state, "draft")
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# adjust_distribution
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_adjust_distribution(self):
|
||||
"""Adjust distribution sets number_distributed_lv = dued + acquired."""
|
||||
alloc = self._build_allocation(state="draft")
|
||||
alloc.number_acquired_lv = 5
|
||||
alloc.employee_id.dued_lv = 3
|
||||
alloc.adjust_distribution()
|
||||
self.assertEqual(alloc.number_distributed_lv, 8)
|
||||
Reference in New Issue
Block a user