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

[15.0][IMP] hr_payroll_period: Add a cron to create next fiscal year automatically #162

Merged
merged 1 commit into from
Sep 26, 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
1 change: 1 addition & 0 deletions hr_payroll_period/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"security/hr_period_security.xml",
"data/ir_sequence_data.xml",
"data/date_range_type.xml",
"data/ir_cron.xml",
"views/menus.xml",
"views/date_range_type_view.xml",
"views/hr_period_view.xml",
Expand Down
15 changes: 15 additions & 0 deletions hr_payroll_period/data/ir_cron.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="ir_cron_hr_payroll_period" model="ir.cron">
<field name='name'>Create Next Fiscal Year</field>
<field name='interval_number'>1</field>
<field name='interval_type'>months</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False" />
<field name="active" eval="False" />
<field name="code">model.cron_create_next_fiscal_year()</field>
<field name="state">code</field>
<field name="user_id" ref="base.user_root" />
<field name="model_id" ref="model_hr_fiscalyear" />
</record>
</odoo>
50 changes: 50 additions & 0 deletions hr_payroll_period/models/hr_fiscal_year.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,53 @@
return next(
(p for p in self.period_ids if p.number == number), self.env["hr.period"]
)

@api.model
def cron_create_next_fiscal_year(self):
current_year = datetime.now().year
next_year = current_year + 1
# Get the latest fiscal year that has not ended yet
latest_fiscal_year = self.search(
[("date_end", "<", datetime(next_year, 1, 1).strftime(DF))],
order="date_end desc",
limit=1,
)
if not latest_fiscal_year:
return self

Check warning on line 317 in hr_payroll_period/models/hr_fiscal_year.py

View check run for this annotation

Codecov / codecov/patch

hr_payroll_period/models/hr_fiscal_year.py#L317

Added line #L317 was not covered by tests
latest_period_end = max(latest_fiscal_year.period_ids.mapped("date_end"))
fiscal_year_start = latest_period_end + relativedelta(days=1)
fiscal_year_end = datetime(next_year, 12, 31).strftime(DF)
# Check if a fiscal year with the same start and end dates already exists
existing_fiscal_year = self.search(
[
("date_start", "=", fiscal_year_start),
("date_end", "=", fiscal_year_end),
],
limit=1,
)
if existing_fiscal_year:
return existing_fiscal_year

Check warning on line 330 in hr_payroll_period/models/hr_fiscal_year.py

View check run for this annotation

Codecov / codecov/patch

hr_payroll_period/models/hr_fiscal_year.py#L330

Added line #L330 was not covered by tests

schedule_pay = latest_fiscal_year.schedule_pay
payment_weekday = latest_fiscal_year.payment_weekday
payment_week = latest_fiscal_year.payment_week
schedule_name = next(
(s[1] for s in get_schedules(self) if s[0] == schedule_pay), False
)

fiscal_year = self.create(
{
"name": "%(year)s - %(schedule)s"
% {
"year": next_year,
"schedule": schedule_name,
},
"date_start": fiscal_year_start,
"date_end": fiscal_year_end,
"schedule_pay": schedule_pay,
"payment_weekday": payment_weekday,
"payment_week": payment_week,
}
)
fiscal_year.create_periods()
return fiscal_year
1 change: 0 additions & 1 deletion hr_payroll_period/static/description/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
Expand Down
49 changes: 48 additions & 1 deletion hr_payroll_period/tests/test_hr_fiscalyear.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright 2015 Savoir-faire Linux. All Rights Reserved.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import date
from datetime import date, datetime

from dateutil.relativedelta import relativedelta

from odoo import fields
from odoo.exceptions import UserError, ValidationError
Expand Down Expand Up @@ -344,3 +346,48 @@ def test_create_periods_semi_monthly_payment_last_day(self):
self.assertEqual(periods[2].date_payment, date(2015, 5, 4))
self.assertEqual(periods[22].date_payment, date(2016, 3, 5))
self.assertEqual(periods[23].date_payment, date(2016, 3, 19))

def test_cron_create_next_fiscal_year(self):
# if we are in 2024, it should create the periods for 2025
current_year = datetime.now().year
current_fiscal_year = self.fy_model.search(
[
("date_start", "=", f"{current_year}-01-01"),
("date_end", "=", f"{current_year}-12-31"),
],
limit=1,
)

# If 2024 doesn't exist, create it
if not current_fiscal_year:
current_fiscal_year = self.create_fiscal_year(
{
"date_start": f"{current_year}-01-01",
"date_end": f"{current_year}-12-31",
}
)
current_fiscal_year.create_periods()
next_fiscal_year = self.env["hr.fiscalyear"].cron_create_next_fiscal_year()
periods = self.get_periods(next_fiscal_year)
# Ensure the periods are continuous and within the fiscal year dates
for i, period in enumerate(periods):
if i == 0:
self.assertEqual(period.date_start, next_fiscal_year.date_start)
else:
self.assertEqual(
period.date_start, periods[i - 1].date_end + relativedelta(days=1)
)
if i == len(periods) - 1:
self.assertEqual(period.date_end, next_fiscal_year.date_end)
# Check that the first period of next fiscal year starts 1 day after
current_year_periods = self.get_periods(current_fiscal_year)
last_period_current_year = current_year_periods[-1]
first_period_next_year = periods[0]
self.assertEqual(
first_period_next_year.date_start,
last_period_current_year.date_end + relativedelta(days=1),
)
# Check that the first period end is on last of January
self.assertEqual(
first_period_next_year.date_end, datetime(current_year + 1, 1, 31).date()
)
Loading