Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[17.0][IMP] sale_project_task_recurrency: Allow forcing a specific month when the recurrence is yearly #1394

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions sale_project_task_recurrency/models/product_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ class ProductTemplate(models.Model):
and the period selected is 'Year(s)' the start date will be 2025/12/31.
""",
)
task_force_month = fields.Selection(
[
("1", "January"),
("2", "February"),
("3", "March"),
("4", "April"),
("5", "May"),
("6", "June"),
("7", "July"),
("8", "August"),
("9", "September"),
("10", "October"),
("11", "November"),
("12", "December"),
],
"Force Month",
)

@api.onchange("service_tracking")
def _onchange_service_tracking(self):
Expand Down
28 changes: 20 additions & 8 deletions sale_project_task_recurrency/models/sale_order_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,33 @@ def _timesheet_create_task_prepare_values(self, project):
if self.product_id.task_repeat_type == "repeat"
else self.product_id.task_repeat_type
)
date_deadline = self._get_task_date_deadline()
values.update(
{
"repeat_interval": self.product_id.task_repeat_interval,
"repeat_unit": self.product_id.task_repeat_unit,
"repeat_type": repeat_type,
"recurring_task": True,
"date_deadline": self._get_task_date_deadline(),
"repeat_until": self._get_task_repeat_until(),
"date_deadline": date_deadline,
"repeat_until": self._get_task_repeat_until(date_deadline),
}
)
return values

def _get_task_date_deadline(self):
self.ensure_one()
product = self.product_id
force_month = int(product.task_force_month) if product.task_force_month else 0
task_start_date_method = product.task_start_date_method
date_deadline_tz = fields.Datetime.context_timestamp(
self, datetime.now()
) + relativedelta(hour=12, minute=0, second=0)
if (
force_month
and product.task_repeat_unit == "year"
and task_start_date_method == "current_date"
):
date_deadline_tz += relativedelta(month=force_month)
date_deadline = date_deadline_tz.astimezone(pytz.UTC).replace(tzinfo=None)
if (
product.task_repeat_unit in ["month", "year"]
Expand All @@ -50,25 +58,29 @@ def _get_task_date_deadline(self):
if "end_" in task_start_date_method:
date_deadline += relativedelta(day=31)
else:
date_deadline += relativedelta(month=1, day=1)
date_deadline += relativedelta(month=force_month or 1, day=1)
if "_next" in task_start_date_method:
date_deadline += relativedelta(years=product.task_repeat_interval)
if "end_" in task_start_date_method:
date_deadline += relativedelta(month=12, day=31)
date_deadline += relativedelta(month=force_month or 12, day=31)
return date_deadline

def _get_task_repeat_until(self):
def _get_task_repeat_until(self, date_start):
self.ensure_one()
product = self.product_id
repeat_until = False
if product.task_repeat_type == "repeat":
if product.task_repeat_unit == "month":
repeat_until = fields.Date.context_today(self) + relativedelta(
repeat_until = date_start + relativedelta(
months=product.task_repeat_number * product.task_repeat_interval
)
else:
repeat_until = fields.Date.context_today(self) + relativedelta(
years=product.task_repeat_number * product.task_repeat_interval
force_month = (
int(product.task_force_month) if product.task_force_month else 0
)
repeat_until = date_start + relativedelta(
years=product.task_repeat_number * product.task_repeat_interval,
month=force_month or None,
)
elif product.task_repeat_type == "until":
repeat_until = product.task_repeat_until
Expand Down
49 changes: 49 additions & 0 deletions sale_project_task_recurrency/tests/test_product_task_recurrency.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,3 +698,52 @@ def test_task_recurrency_year_repeat_number(self):
last_task.state = "1_done"
task.invalidate_recordset(["recurring_count"])
self.assertEqual(task.recurring_count, 4)

@users("test-user")
@freeze_time("2024-11-15")
def test_task_recurrency_year_force_month(self):
"""Every 1 year, force month to July"""
self.service_task_recurrency.task_repeat_interval = 1
self.service_task_recurrency.task_repeat_unit = "year"
self.service_task_recurrency.task_force_month = "6"
self.service_task_recurrency.task_repeat_type = "forever"
self.sale_order.action_confirm()
self.assertFalse(self.sol_no_task.task_id)
self.assertFalse(self.sol_task.task_id.recurring_task)
task = self.sol_task_recurrency.task_id
self.assertTrue(task.recurring_task)
self.assertEqual(task.repeat_interval, 1)
self.assertEqual(task.repeat_unit, "year")
self.assertEqual(task.repeat_type, "forever")
self.assertEqual(task.recurring_count, 1)
self.assertEqual(
task.date_deadline.date(), fields.Date.from_string("2024-06-15")
)
# start_this
self.service_task_recurrency.task_start_date_method = "start_this"
self._reprocess_sale_order()
task = self.sol_task_recurrency.task_id
self.assertEqual(
task.date_deadline.date(), fields.Date.from_string("2024-06-01")
)
# end_this
self.service_task_recurrency.task_start_date_method = "end_this"
self._reprocess_sale_order()
task = self.sol_task_recurrency.task_id
self.assertEqual(
task.date_deadline.date(), fields.Date.from_string("2024-06-30")
)
# start_next
self.service_task_recurrency.task_start_date_method = "start_next"
self._reprocess_sale_order()
task = self.sol_task_recurrency.task_id
self.assertEqual(
task.date_deadline.date(), fields.Date.from_string("2025-06-01")
)
# end_next
self.service_task_recurrency.task_start_date_method = "end_next"
self._reprocess_sale_order()
task = self.sol_task_recurrency.task_id
self.assertEqual(
task.date_deadline.date(), fields.Date.from_string("2025-06-30")
)
5 changes: 5 additions & 0 deletions sale_project_task_recurrency/views/product_template_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
required="recurring_task"
groups="project.group_project_recurring_tasks"
/>
<field
name="task_force_month"
invisible="task_repeat_unit != 'year'"
groups="project.group_project_recurring_tasks"
/>
</xpath>
</field>
</record>
Expand Down
Loading