Skip to content

Commit 8b1df60

Browse files
authored
Merge pull request #1773 from frappe/version-15-hotfix
chore: release v15
2 parents b21a6ca + e0b8cb8 commit 8b1df60

File tree

20 files changed

+126
-179
lines changed

20 files changed

+126
-179
lines changed

hrms/hr/doctype/shift_assignment/shift_assignment.py

+2-23
Original file line numberDiff line numberDiff line change
@@ -80,33 +80,12 @@ def get_overlapping_dates(self):
8080
& (shift.docstatus == 1)
8181
& (shift.name != self.name)
8282
& (shift.status == "Active")
83+
& ((shift.end_date >= self.start_date) | (shift.end_date.isnull()))
8384
)
8485
)
8586

8687
if self.end_date:
87-
query = query.where(
88-
Criterion.any(
89-
[
90-
Criterion.any(
91-
[
92-
shift.end_date.isnull(),
93-
((self.start_date >= shift.start_date) & (self.start_date <= shift.end_date)),
94-
]
95-
),
96-
Criterion.any(
97-
[
98-
((self.end_date >= shift.start_date) & (self.end_date <= shift.end_date)),
99-
shift.start_date.between(self.start_date, self.end_date),
100-
]
101-
),
102-
]
103-
)
104-
)
105-
else:
106-
query = query.where(
107-
shift.end_date.isnull()
108-
| ((self.start_date >= shift.start_date) & (self.start_date <= shift.end_date))
109-
)
88+
query = query.where(shift.start_date <= self.end_date)
11089

11190
return query.run(as_dict=True)
11291

hrms/hr/doctype/shift_assignment/test_shift_assignment.py

+10-54
Original file line numberDiff line numberDiff line change
@@ -23,39 +23,18 @@ def setUp(self):
2323
frappe.db.delete("Shift Assignment")
2424
frappe.db.delete("Shift Type")
2525

26-
def test_make_shift_assignment(self):
27-
setup_shift_type(shift_type="Day Shift")
28-
shift_assignment = frappe.get_doc(
29-
{
30-
"doctype": "Shift Assignment",
31-
"shift_type": "Day Shift",
32-
"company": "_Test Company",
33-
"employee": "_T-Employee-00001",
34-
"start_date": nowdate(),
35-
}
36-
).insert()
37-
shift_assignment.submit()
38-
39-
self.assertEqual(shift_assignment.docstatus, 1)
40-
4126
def test_overlapping_for_ongoing_shift(self):
4227
# shift should be Ongoing if Only start_date is present and status = Active
4328
setup_shift_type(shift_type="Day Shift")
44-
shift_assignment_1 = frappe.get_doc(
45-
{
46-
"doctype": "Shift Assignment",
47-
"shift_type": "Day Shift",
48-
"company": "_Test Company",
49-
"employee": "_T-Employee-00001",
50-
"start_date": nowdate(),
51-
"status": "Active",
52-
}
53-
).insert()
54-
shift_assignment_1.submit()
29+
make_shift_assignment("Day Shift", "_T-Employee-00001", nowdate())
5530

56-
self.assertEqual(shift_assignment_1.docstatus, 1)
31+
# shift ends before ongoing shift starts
32+
non_overlapping_shift = make_shift_assignment(
33+
"Day Shift", "_T-Employee-00001", add_days(nowdate(), -1), add_days(nowdate(), -1)
34+
)
35+
self.assertEqual(non_overlapping_shift.docstatus, 1)
5736

58-
shift_assignment = frappe.get_doc(
37+
overlapping_shift = frappe.get_doc(
5938
{
6039
"doctype": "Shift Assignment",
6140
"shift_type": "Day Shift",
@@ -64,23 +43,11 @@ def test_overlapping_for_ongoing_shift(self):
6443
"start_date": add_days(nowdate(), 2),
6544
}
6645
)
67-
68-
self.assertRaises(OverlappingShiftError, shift_assignment.save)
46+
self.assertRaises(OverlappingShiftError, overlapping_shift.save)
6947

7048
def test_multiple_shift_assignments_for_same_date(self):
7149
setup_shift_type(shift_type="Day Shift")
72-
shift_assignment_1 = frappe.get_doc(
73-
{
74-
"doctype": "Shift Assignment",
75-
"shift_type": "Day Shift",
76-
"company": "_Test Company",
77-
"employee": "_T-Employee-00001",
78-
"start_date": nowdate(),
79-
"end_date": add_days(nowdate(), 30),
80-
"status": "Active",
81-
}
82-
).insert()
83-
shift_assignment_1.submit()
50+
make_shift_assignment("Day Shift", "_T-Employee-00001", nowdate(), add_days(nowdate(), 30))
8451

8552
setup_shift_type(shift_type="Night Shift", start_time="19:00:00", end_time="23:00:00")
8653
shift_assignment_2 = frappe.get_doc(
@@ -103,18 +70,7 @@ def test_multiple_shift_assignments_for_same_date(self):
10370
def test_overlapping_for_fixed_period_shift(self):
10471
# shift should is for Fixed period if Only start_date and end_date both are present and status = Active
10572
setup_shift_type(shift_type="Day Shift")
106-
shift_assignment_1 = frappe.get_doc(
107-
{
108-
"doctype": "Shift Assignment",
109-
"shift_type": "Day Shift",
110-
"company": "_Test Company",
111-
"employee": "_T-Employee-00001",
112-
"start_date": nowdate(),
113-
"end_date": add_days(nowdate(), 30),
114-
"status": "Active",
115-
}
116-
).insert()
117-
shift_assignment_1.submit()
73+
make_shift_assignment("Day Shift", "_T-Employee-00001", nowdate(), add_days(nowdate(), 30))
11874

11975
# it should not allowed within period of any shift.
12076
shift_assignment_3 = frappe.get_doc(

hrms/hr/doctype/shift_request/shift_request.py

+7-24
Original file line numberDiff line numberDiff line change
@@ -93,33 +93,16 @@ def get_overlapping_dates(self):
9393
query = (
9494
frappe.qb.from_(shift)
9595
.select(shift.name, shift.shift_type)
96-
.where((shift.employee == self.employee) & (shift.docstatus < 2) & (shift.name != self.name))
96+
.where(
97+
(shift.employee == self.employee)
98+
& (shift.docstatus < 2)
99+
& (shift.name != self.name)
100+
& ((shift.to_date >= self.from_date) | (shift.to_date.isnull()))
101+
)
97102
)
98103

99104
if self.to_date:
100-
query = query.where(
101-
Criterion.any(
102-
[
103-
Criterion.any(
104-
[
105-
shift.to_date.isnull(),
106-
((self.from_date >= shift.from_date) & (self.from_date <= shift.to_date)),
107-
]
108-
),
109-
Criterion.any(
110-
[
111-
((self.to_date >= shift.from_date) & (self.to_date <= shift.to_date)),
112-
shift.from_date.between(self.from_date, self.to_date),
113-
]
114-
),
115-
]
116-
)
117-
)
118-
else:
119-
query = query.where(
120-
shift.to_date.isnull()
121-
| ((self.from_date >= shift.from_date) & (self.from_date <= shift.to_date))
122-
)
105+
query = query.where(shift.from_date <= self.to_date)
123106

124107
return query.run(as_dict=True)
125108

hrms/patches.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ hrms.patches.v14_0.update_title_in_employee_onboarding_and_separation_templates
2323
hrms.patches.v15_0.make_hr_settings_tab_in_company_master
2424
hrms.patches.v15_0.enable_allow_checkin_setting
2525
hrms.patches.v15_0.set_default_asset_action_in_fnf
26-
hrms.patches.v15_0.add_loan_docperms_to_ess
26+
hrms.patches.v15_0.add_loan_docperms_to_ess #2024-05-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import frappe
22

3-
from hrms.setup import add_lending_docperms_to_ess
3+
from hrms.setup import add_lending_docperms_to_ess, update_user_type_doctype_limit
44

55

66
def execute():
77
if "lending" in frappe.get_installed_apps():
8+
update_user_type_doctype_limit()
89
add_lending_docperms_to_ess()

hrms/payroll/doctype/payroll_period/payroll_period.js

+31-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,35 @@
22
// For license information, please see license.txt
33

44
frappe.ui.form.on("Payroll Period", {
5-
refresh: function (frm) {},
5+
onload: function (frm) {
6+
frm.trigger("set_start_date");
7+
},
8+
9+
set_start_date: function (frm) {
10+
if (!frm.doc.__islocal) return;
11+
12+
frappe.db
13+
.get_list("Payroll Period", {
14+
fields: ["end_date"],
15+
order_by: "end_date desc",
16+
limit: 1,
17+
})
18+
.then((result) => {
19+
// set start date based on end date of the last payroll period if found
20+
// else set it based on the current fiscal year's start date
21+
if (result.length) {
22+
const last_end_date = result[0].end_date;
23+
frm.set_value("start_date", frappe.datetime.add_days(last_end_date, 1));
24+
} else {
25+
frm.set_value("start_date", frappe.defaults.get_default("year_start_date"));
26+
}
27+
});
28+
},
29+
30+
start_date: function (frm) {
31+
frm.set_value(
32+
"end_date",
33+
frappe.datetime.add_days(frappe.datetime.add_months(frm.doc.start_date, 12), -1),
34+
);
35+
},
636
});

hrms/payroll/doctype/payroll_period/payroll_period.json

+3-4
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
}
5454
],
5555
"links": [],
56-
"modified": "2024-05-05 14:50:12.419714",
56+
"modified": "2024-05-07 17:27:51.903593",
5757
"modified_by": "Administrator",
5858
"module": "Payroll",
5959
"name": "Payroll Period",
@@ -105,8 +105,7 @@
105105
"write": 1
106106
}
107107
],
108-
"quick_entry": 1,
109-
"sort_field": "modified",
108+
"sort_field": "creation",
110109
"sort_order": "DESC",
111110
"track_changes": 1
112-
}
111+
}

hrms/payroll/doctype/salary_component/salary_component.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ frappe.ui.form.on("Salary Component", {
125125
args: {
126126
structures: structures,
127127
field: df.toLowerCase(),
128-
value: frm.get_field(df.toLowerCase()).value,
128+
value: frm.get_field(df.toLowerCase()).value || "",
129129
},
130130
})
131131
.then((r) => {

hrms/payroll/doctype/salary_slip/salary_slip.py

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def __init__(self, *args, **kwargs):
7070
"float": float,
7171
"long": int,
7272
"round": round,
73+
"rounded": rounded,
7374
"date": date,
7475
"getdate": getdate,
7576
"ceil": ceil,

hrms/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js

+36-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ frappe.ui.form.on("Salary Structure Assignment", {
6060
}
6161

6262
if (frm.doc.docstatus != 1) return;
63+
6364
frm.add_custom_button(
6465
__("Payroll Entry"),
6566
() => {
@@ -71,6 +72,14 @@ frappe.ui.form.on("Salary Structure Assignment", {
7172
__("Create"),
7273
);
7374
frm.page.set_inner_btn_group_as_primary(__("Create"));
75+
76+
frm.add_custom_button(
77+
__("Preview Salary Slip"),
78+
function () {
79+
frm.trigger("preview_salary_slip");
80+
},
81+
__("Actions"),
82+
);
7483
},
7584

7685
employee: function (frm) {
@@ -95,6 +104,33 @@ frappe.ui.form.on("Salary Structure Assignment", {
95104
}
96105
},
97106

107+
preview_salary_slip: function (frm) {
108+
frappe.db.get_value(
109+
"Salary Structure",
110+
frm.doc.salary_structure,
111+
"salary_slip_based_on_timesheet",
112+
(r) => {
113+
const print_format = r.salary_slip_based_on_timesheet
114+
? "Salary Slip based on Timesheet"
115+
: "Salary Slip Standard";
116+
frappe.call({
117+
method: "hrms.payroll.doctype.salary_structure.salary_structure.make_salary_slip",
118+
args: {
119+
source_name: frm.doc.salary_structure,
120+
employee: frm.doc.employee,
121+
as_print: 1,
122+
print_format: print_format,
123+
for_preview: 1,
124+
},
125+
callback: function (r) {
126+
const new_window = window.open();
127+
new_window.document.write(r.message);
128+
},
129+
});
130+
},
131+
);
132+
},
133+
98134
set_payroll_cost_centers: function (frm) {
99135
if (frm.doc.payroll_cost_centers && frm.doc.payroll_cost_centers.length < 1) {
100136
frappe.call({
@@ -106,7 +142,6 @@ frappe.ui.form.on("Salary Structure Assignment", {
106142
});
107143
}
108144
},
109-
110145
valiadte_joining_date_and_salary_slips: function (frm) {
111146
frappe.call({
112147
method: "earning_and_deduction_entries_does_not_exists",

hrms/payroll/module_onboarding/payroll/payroll.json

+3-9
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,15 @@
1010
"creation": "2020-06-01 12:10:52.560472",
1111
"docstatus": 0,
1212
"doctype": "Module Onboarding",
13-
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/human-resources/payroll-entry",
13+
"documentation_url": "https://frappehr.com/docs/v14/en/payroll-entry",
1414
"idx": 0,
1515
"is_complete": 0,
16-
"modified": "2020-07-08 14:06:13.994310",
16+
"modified": "2024-05-07 17:44:05.258878",
1717
"modified_by": "Administrator",
1818
"module": "Payroll",
1919
"name": "Payroll",
2020
"owner": "Administrator",
2121
"steps": [
22-
{
23-
"step": "Create Employee"
24-
},
2522
{
2623
"step": "Create Salary Component"
2724
},
@@ -32,10 +29,7 @@
3229
"step": "Create Income Tax Slab"
3330
},
3431
{
35-
"step": "Create Salary Structure"
36-
},
37-
{
38-
"step": "Assign Salary Structure"
32+
"step": "Create & Assign Salary Structure"
3933
},
4034
{
4135
"step": "Create Salary Slip"

hrms/payroll/onboarding_step/assign_salary_structure/assign_salary_structure.json

-19
This file was deleted.

0 commit comments

Comments
 (0)