mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-27 17:04:47 +00:00
Merge pull request #33510 from ruchamahabal/mark-attendance-period
This commit is contained in:
@@ -5,7 +5,16 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import cint, cstr, formatdate, get_datetime, getdate, nowdate
|
from frappe.utils import (
|
||||||
|
add_days,
|
||||||
|
cint,
|
||||||
|
cstr,
|
||||||
|
formatdate,
|
||||||
|
get_datetime,
|
||||||
|
get_link_to_form,
|
||||||
|
getdate,
|
||||||
|
nowdate,
|
||||||
|
)
|
||||||
|
|
||||||
from erpnext.hr.utils import get_holiday_dates_for_employee, validate_active_employee
|
from erpnext.hr.utils import get_holiday_dates_for_employee, validate_active_employee
|
||||||
|
|
||||||
@@ -106,8 +115,6 @@ class Attendance(Document):
|
|||||||
frappe.throw(_("Employee {0} is not active or does not exist").format(self.employee))
|
frappe.throw(_("Employee {0} is not active or does not exist").format(self.employee))
|
||||||
|
|
||||||
def unlink_attendance_from_checkins(self):
|
def unlink_attendance_from_checkins(self):
|
||||||
from frappe.utils import get_link_to_form
|
|
||||||
|
|
||||||
EmployeeCheckin = frappe.qb.DocType("Employee Checkin")
|
EmployeeCheckin = frappe.qb.DocType("Employee Checkin")
|
||||||
linked_logs = (
|
linked_logs = (
|
||||||
frappe.qb.from_(EmployeeCheckin)
|
frappe.qb.from_(EmployeeCheckin)
|
||||||
@@ -221,75 +228,39 @@ def mark_bulk_attendance(data):
|
|||||||
attendance.submit()
|
attendance.submit()
|
||||||
|
|
||||||
|
|
||||||
def get_month_map():
|
|
||||||
return frappe._dict(
|
|
||||||
{
|
|
||||||
"January": 1,
|
|
||||||
"February": 2,
|
|
||||||
"March": 3,
|
|
||||||
"April": 4,
|
|
||||||
"May": 5,
|
|
||||||
"June": 6,
|
|
||||||
"July": 7,
|
|
||||||
"August": 8,
|
|
||||||
"September": 9,
|
|
||||||
"October": 10,
|
|
||||||
"November": 11,
|
|
||||||
"December": 12,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_unmarked_days(employee, month, exclude_holidays=0):
|
def get_unmarked_days(employee, from_date, to_date, exclude_holidays=0):
|
||||||
import calendar
|
|
||||||
|
|
||||||
month_map = get_month_map()
|
|
||||||
today = get_datetime()
|
|
||||||
|
|
||||||
joining_date, relieving_date = frappe.get_cached_value(
|
joining_date, relieving_date = frappe.get_cached_value(
|
||||||
"Employee", employee, ["date_of_joining", "relieving_date"]
|
"Employee", employee, ["date_of_joining", "relieving_date"]
|
||||||
)
|
)
|
||||||
start_day = 1
|
|
||||||
end_day = calendar.monthrange(today.year, month_map[month])[1] + 1
|
|
||||||
|
|
||||||
if joining_date and joining_date.year == today.year and joining_date.month == month_map[month]:
|
from_date = max(getdate(from_date), joining_date or getdate(from_date))
|
||||||
start_day = joining_date.day
|
to_date = min(getdate(to_date), relieving_date or getdate(to_date))
|
||||||
|
|
||||||
if (
|
|
||||||
relieving_date and relieving_date.year == today.year and relieving_date.month == month_map[month]
|
|
||||||
):
|
|
||||||
end_day = relieving_date.day + 1
|
|
||||||
|
|
||||||
dates_of_month = [
|
|
||||||
"{}-{}-{}".format(today.year, month_map[month], r) for r in range(start_day, end_day)
|
|
||||||
]
|
|
||||||
month_start, month_end = dates_of_month[0], dates_of_month[-1]
|
|
||||||
|
|
||||||
records = frappe.get_all(
|
records = frappe.get_all(
|
||||||
"Attendance",
|
"Attendance",
|
||||||
fields=["attendance_date", "employee"],
|
fields=["attendance_date", "employee"],
|
||||||
filters=[
|
filters=[
|
||||||
["attendance_date", ">=", month_start],
|
["attendance_date", ">=", from_date],
|
||||||
["attendance_date", "<=", month_end],
|
["attendance_date", "<=", to_date],
|
||||||
["employee", "=", employee],
|
["employee", "=", employee],
|
||||||
["docstatus", "!=", 2],
|
["docstatus", "!=", 2],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
marked_days = [get_datetime(record.attendance_date) for record in records]
|
marked_days = [getdate(record.attendance_date) for record in records]
|
||||||
|
|
||||||
if cint(exclude_holidays):
|
if cint(exclude_holidays):
|
||||||
holiday_dates = get_holiday_dates_for_employee(employee, month_start, month_end)
|
holiday_dates = get_holiday_dates_for_employee(employee, from_date, to_date)
|
||||||
holidays = [get_datetime(record) for record in holiday_dates]
|
holidays = [getdate(record) for record in holiday_dates]
|
||||||
marked_days.extend(holidays)
|
marked_days.extend(holidays)
|
||||||
|
|
||||||
unmarked_days = []
|
unmarked_days = []
|
||||||
|
|
||||||
for date in dates_of_month:
|
while from_date <= to_date:
|
||||||
date_time = get_datetime(date)
|
if from_date not in marked_days:
|
||||||
if today.day <= date_time.day and today.month <= date_time.month:
|
unmarked_days.append(from_date)
|
||||||
break
|
|
||||||
if date_time not in marked_days:
|
from_date = add_days(from_date, 1)
|
||||||
unmarked_days.append(date)
|
|
||||||
|
|
||||||
return unmarked_days
|
return unmarked_days
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
frappe.listview_settings['Attendance'] = {
|
frappe.listview_settings["Attendance"] = {
|
||||||
add_fields: ["status", "attendance_date"],
|
add_fields: ["status", "attendance_date"],
|
||||||
|
|
||||||
get_indicator: function (doc) {
|
get_indicator: function (doc) {
|
||||||
if (["Present", "Work From Home"].includes(doc.status)) {
|
if (["Present", "Work From Home"].includes(doc.status)) {
|
||||||
return [__(doc.status), "green", "status,=," + doc.status];
|
return [__(doc.status), "green", "status,=," + doc.status];
|
||||||
@@ -10,157 +11,185 @@ frappe.listview_settings['Attendance'] = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onload: function(list_view) {
|
onload: function (list_view) {
|
||||||
let me = this;
|
let me = this;
|
||||||
const months = moment.months();
|
|
||||||
const curMonth = moment().format("MMMM");
|
list_view.page.add_inner_button(__("Mark Attendance"), function () {
|
||||||
months.splice(months.indexOf(curMonth) + 1);
|
let first_day_of_month = moment().startOf('month');
|
||||||
list_view.page.add_inner_button(__("Mark Attendance"), function() {
|
|
||||||
|
if (moment().toDate().getDate() === 1) {
|
||||||
|
first_day_of_month = first_day_of_month.subtract(1, "month");
|
||||||
|
}
|
||||||
|
|
||||||
let dialog = new frappe.ui.Dialog({
|
let dialog = new frappe.ui.Dialog({
|
||||||
title: __("Mark Attendance"),
|
title: __("Mark Attendance"),
|
||||||
fields: [{
|
fields: [
|
||||||
fieldname: 'employee',
|
{
|
||||||
label: __('For Employee'),
|
fieldname: "employee",
|
||||||
fieldtype: 'Link',
|
label: __("For Employee"),
|
||||||
options: 'Employee',
|
fieldtype: "Link",
|
||||||
get_query: () => {
|
options: "Employee",
|
||||||
return {query: "erpnext.controllers.queries.employee_query"};
|
get_query: () => {
|
||||||
|
return {
|
||||||
|
query: "erpnext.controllers.queries.employee_query",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
reqd: 1,
|
||||||
|
onchange: () => me.reset_dialog(dialog),
|
||||||
},
|
},
|
||||||
reqd: 1,
|
{
|
||||||
onchange: function() {
|
fieldtype: "Section Break",
|
||||||
dialog.set_df_property("unmarked_days", "hidden", 1);
|
fieldname: "time_period_section",
|
||||||
dialog.set_df_property("status", "hidden", 1);
|
hidden: 1,
|
||||||
dialog.set_df_property("exclude_holidays", "hidden", 1);
|
},
|
||||||
dialog.set_df_property("month", "value", '');
|
{
|
||||||
dialog.set_df_property("unmarked_days", "options", []);
|
label: __("Start"),
|
||||||
dialog.no_unmarked_days_left = false;
|
fieldtype: "Date",
|
||||||
}
|
fieldname: "from_date",
|
||||||
},
|
reqd: 1,
|
||||||
{
|
default: first_day_of_month.toDate(),
|
||||||
label: __("For Month"),
|
onchange: () => me.get_unmarked_days(dialog),
|
||||||
fieldtype: "Select",
|
},
|
||||||
fieldname: "month",
|
{
|
||||||
options: months,
|
fieldtype: "Column Break",
|
||||||
reqd: 1,
|
fieldname: "time_period_column",
|
||||||
onchange: function() {
|
},
|
||||||
if (dialog.fields_dict.employee.value && dialog.fields_dict.month.value) {
|
{
|
||||||
dialog.set_df_property("status", "hidden", 0);
|
label: __("End"),
|
||||||
dialog.set_df_property("exclude_holidays", "hidden", 0);
|
fieldtype: "Date",
|
||||||
dialog.set_df_property("unmarked_days", "options", []);
|
fieldname: "to_date",
|
||||||
dialog.no_unmarked_days_left = false;
|
reqd: 1,
|
||||||
me.get_multi_select_options(
|
default: moment().subtract(1, 'days').toDate(),
|
||||||
dialog.fields_dict.employee.value,
|
onchange: () => me.get_unmarked_days(dialog),
|
||||||
dialog.fields_dict.month.value,
|
},
|
||||||
dialog.fields_dict.exclude_holidays.get_value()
|
{
|
||||||
).then(options => {
|
fieldtype: "Section Break",
|
||||||
if (options.length > 0) {
|
fieldname: "days_section",
|
||||||
dialog.set_df_property("unmarked_days", "hidden", 0);
|
hidden: 1,
|
||||||
dialog.set_df_property("unmarked_days", "options", options);
|
},
|
||||||
} else {
|
{
|
||||||
dialog.no_unmarked_days_left = true;
|
label: __("Status"),
|
||||||
}
|
fieldtype: "Select",
|
||||||
});
|
fieldname: "status",
|
||||||
}
|
options: ["Present", "Absent", "Half Day", "Work From Home"],
|
||||||
}
|
reqd: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __("Status"),
|
label: __("Exclude Holidays"),
|
||||||
fieldtype: "Select",
|
fieldtype: "Check",
|
||||||
fieldname: "status",
|
fieldname: "exclude_holidays",
|
||||||
options: ["Present", "Absent", "Half Day", "Work From Home"],
|
onchange: () => me.get_unmarked_days(dialog),
|
||||||
hidden: 1,
|
},
|
||||||
reqd: 1,
|
{
|
||||||
|
label: __("Unmarked Attendance for days"),
|
||||||
},
|
fieldname: "unmarked_days",
|
||||||
{
|
fieldtype: "MultiCheck",
|
||||||
label: __("Exclude Holidays"),
|
options: [],
|
||||||
fieldtype: "Check",
|
columns: 2,
|
||||||
fieldname: "exclude_holidays",
|
},
|
||||||
hidden: 1,
|
],
|
||||||
onchange: function() {
|
|
||||||
if (dialog.fields_dict.employee.value && dialog.fields_dict.month.value) {
|
|
||||||
dialog.set_df_property("status", "hidden", 0);
|
|
||||||
dialog.set_df_property("unmarked_days", "options", []);
|
|
||||||
dialog.no_unmarked_days_left = false;
|
|
||||||
me.get_multi_select_options(
|
|
||||||
dialog.fields_dict.employee.value,
|
|
||||||
dialog.fields_dict.month.value,
|
|
||||||
dialog.fields_dict.exclude_holidays.get_value()
|
|
||||||
).then(options => {
|
|
||||||
if (options.length > 0) {
|
|
||||||
dialog.set_df_property("unmarked_days", "hidden", 0);
|
|
||||||
dialog.set_df_property("unmarked_days", "options", options);
|
|
||||||
} else {
|
|
||||||
dialog.no_unmarked_days_left = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Unmarked Attendance for days"),
|
|
||||||
fieldname: "unmarked_days",
|
|
||||||
fieldtype: "MultiCheck",
|
|
||||||
options: [],
|
|
||||||
columns: 2,
|
|
||||||
hidden: 1
|
|
||||||
}],
|
|
||||||
primary_action(data) {
|
primary_action(data) {
|
||||||
if (cur_dialog.no_unmarked_days_left) {
|
if (cur_dialog.no_unmarked_days_left) {
|
||||||
frappe.msgprint(__("Attendance for the month of {0} , has already been marked for the Employee {1}",
|
frappe.msgprint(
|
||||||
[dialog.fields_dict.month.value, dialog.fields_dict.employee.value]));
|
__(
|
||||||
|
"Attendance from {0} to {1} has already been marked for the Employee {2}",
|
||||||
|
[data.from_date, data.to_date, data.employee]
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
frappe.confirm(__('Mark attendance as {0} for {1} on selected dates?', [data.status, data.month]), () => {
|
frappe.confirm(
|
||||||
frappe.call({
|
__("Mark attendance as {0} for {1} on selected dates?", [
|
||||||
method: "erpnext.hr.doctype.attendance.attendance.mark_bulk_attendance",
|
data.status,
|
||||||
args: {
|
data.employee,
|
||||||
data: data
|
]),
|
||||||
},
|
() => {
|
||||||
callback: function (r) {
|
frappe.call({
|
||||||
if (r.message === 1) {
|
method: "erpnext.hr.doctype.attendance.attendance.mark_bulk_attendance",
|
||||||
frappe.show_alert({
|
args: {
|
||||||
message: __("Attendance Marked"),
|
data: data,
|
||||||
indicator: 'blue'
|
},
|
||||||
});
|
callback: function (r) {
|
||||||
cur_dialog.hide();
|
if (r.message === 1) {
|
||||||
}
|
frappe.show_alert({
|
||||||
}
|
message: __("Attendance Marked"),
|
||||||
});
|
indicator: "blue",
|
||||||
});
|
});
|
||||||
|
cur_dialog.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
list_view.refresh();
|
list_view.refresh();
|
||||||
},
|
},
|
||||||
primary_action_label: __('Mark Attendance')
|
primary_action_label: __("Mark Attendance"),
|
||||||
|
|
||||||
});
|
});
|
||||||
dialog.show();
|
dialog.show();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
get_multi_select_options: function(employee, month, exclude_holidays) {
|
reset_dialog: function (dialog) {
|
||||||
return new Promise(resolve => {
|
let fields = dialog.fields_dict;
|
||||||
frappe.call({
|
|
||||||
method: 'erpnext.hr.doctype.attendance.attendance.get_unmarked_days',
|
dialog.set_df_property(
|
||||||
async: false,
|
"time_period_section",
|
||||||
args: {
|
"hidden",
|
||||||
employee: employee,
|
fields.employee.value ? 0 : 1
|
||||||
month: month,
|
);
|
||||||
exclude_holidays: exclude_holidays
|
|
||||||
}
|
dialog.set_df_property("days_section", "hidden", 1);
|
||||||
}).then(r => {
|
dialog.set_df_property("unmarked_days", "options", []);
|
||||||
var options = [];
|
dialog.no_unmarked_days_left = false;
|
||||||
for (var d in r.message) {
|
fields.exclude_holidays.value = false;
|
||||||
var momentObj = moment(r.message[d], 'YYYY-MM-DD');
|
|
||||||
var date = momentObj.format('DD-MM-YYYY');
|
fields.to_date.datepicker.update({
|
||||||
options.push({
|
maxDate: moment().subtract(1, 'days').toDate()
|
||||||
"label": date,
|
|
||||||
"value": r.message[d],
|
|
||||||
"checked": 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
resolve(options);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
this.get_unmarked_days(dialog)
|
||||||
|
},
|
||||||
|
|
||||||
|
get_unmarked_days: function (dialog) {
|
||||||
|
let fields = dialog.fields_dict;
|
||||||
|
if (fields.employee.value && fields.from_date.value && fields.to_date.value) {
|
||||||
|
dialog.set_df_property("days_section", "hidden", 0);
|
||||||
|
dialog.set_df_property("status", "hidden", 0);
|
||||||
|
dialog.set_df_property("exclude_holidays", "hidden", 0);
|
||||||
|
dialog.no_unmarked_days_left = false;
|
||||||
|
|
||||||
|
frappe
|
||||||
|
.call({
|
||||||
|
method: "erpnext.hr.doctype.attendance.attendance.get_unmarked_days",
|
||||||
|
async: false,
|
||||||
|
args: {
|
||||||
|
employee: fields.employee.value,
|
||||||
|
from_date: fields.from_date.value,
|
||||||
|
to_date: fields.to_date.value,
|
||||||
|
exclude_holidays: fields.exclude_holidays.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((r) => {
|
||||||
|
var options = [];
|
||||||
|
|
||||||
|
for (var d in r.message) {
|
||||||
|
var momentObj = moment(r.message[d], "YYYY-MM-DD");
|
||||||
|
var date = momentObj.format("DD-MM-YYYY");
|
||||||
|
options.push({
|
||||||
|
label: date,
|
||||||
|
value: r.message[d],
|
||||||
|
checked: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.set_df_property(
|
||||||
|
"unmarked_days",
|
||||||
|
"options",
|
||||||
|
options.length > 0 ? options : []
|
||||||
|
);
|
||||||
|
dialog.no_unmarked_days_left = options.length === 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from frappe.tests.utils import FrappeTestCase
|
|||||||
from frappe.utils import (
|
from frappe.utils import (
|
||||||
add_days,
|
add_days,
|
||||||
add_months,
|
add_months,
|
||||||
|
get_first_day,
|
||||||
get_last_day,
|
get_last_day,
|
||||||
get_year_ending,
|
get_year_ending,
|
||||||
get_year_start,
|
get_year_start,
|
||||||
@@ -13,11 +14,7 @@ from frappe.utils import (
|
|||||||
nowdate,
|
nowdate,
|
||||||
)
|
)
|
||||||
|
|
||||||
from erpnext.hr.doctype.attendance.attendance import (
|
from erpnext.hr.doctype.attendance.attendance import get_unmarked_days, mark_attendance
|
||||||
get_month_map,
|
|
||||||
get_unmarked_days,
|
|
||||||
mark_attendance,
|
|
||||||
)
|
|
||||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||||
from erpnext.hr.tests.test_utils import get_first_sunday
|
from erpnext.hr.tests.test_utils import get_first_sunday
|
||||||
|
|
||||||
@@ -28,7 +25,7 @@ class TestAttendance(FrappeTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list
|
from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list
|
||||||
|
|
||||||
from_date = get_year_start(getdate())
|
from_date = get_year_start(add_months(getdate(), -1))
|
||||||
to_date = get_year_ending(getdate())
|
to_date = get_year_ending(getdate())
|
||||||
self.holiday_list = make_holiday_list(from_date=from_date, to_date=to_date)
|
self.holiday_list = make_holiday_list(from_date=from_date, to_date=to_date)
|
||||||
|
|
||||||
@@ -55,9 +52,10 @@ class TestAttendance(FrappeTestCase):
|
|||||||
frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list)
|
frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list)
|
||||||
|
|
||||||
mark_attendance(employee, attendance_date, "Present")
|
mark_attendance(employee, attendance_date, "Present")
|
||||||
month_name = get_month_name(attendance_date)
|
|
||||||
|
|
||||||
unmarked_days = get_unmarked_days(employee, month_name)
|
unmarked_days = get_unmarked_days(
|
||||||
|
employee, get_first_day(attendance_date), get_last_day(attendance_date)
|
||||||
|
)
|
||||||
unmarked_days = [getdate(date) for date in unmarked_days]
|
unmarked_days = [getdate(date) for date in unmarked_days]
|
||||||
|
|
||||||
# attendance already marked for the day
|
# attendance already marked for the day
|
||||||
@@ -81,9 +79,10 @@ class TestAttendance(FrappeTestCase):
|
|||||||
frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list)
|
frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list)
|
||||||
|
|
||||||
mark_attendance(employee, attendance_date, "Present")
|
mark_attendance(employee, attendance_date, "Present")
|
||||||
month_name = get_month_name(attendance_date)
|
|
||||||
|
|
||||||
unmarked_days = get_unmarked_days(employee, month_name, exclude_holidays=True)
|
unmarked_days = unmarked_days = get_unmarked_days(
|
||||||
|
employee, get_first_day(attendance_date), get_last_day(attendance_date), exclude_holidays=True
|
||||||
|
)
|
||||||
unmarked_days = [getdate(date) for date in unmarked_days]
|
unmarked_days = [getdate(date) for date in unmarked_days]
|
||||||
|
|
||||||
# attendance already marked for the day
|
# attendance already marked for the day
|
||||||
@@ -110,9 +109,10 @@ class TestAttendance(FrappeTestCase):
|
|||||||
|
|
||||||
attendance_date = add_days(date, 2)
|
attendance_date = add_days(date, 2)
|
||||||
mark_attendance(employee, attendance_date, "Present")
|
mark_attendance(employee, attendance_date, "Present")
|
||||||
month_name = get_month_name(attendance_date)
|
|
||||||
|
|
||||||
unmarked_days = get_unmarked_days(employee, month_name)
|
unmarked_days = get_unmarked_days(
|
||||||
|
employee, get_first_day(attendance_date), get_last_day(attendance_date)
|
||||||
|
)
|
||||||
unmarked_days = [getdate(date) for date in unmarked_days]
|
unmarked_days = [getdate(date) for date in unmarked_days]
|
||||||
|
|
||||||
# attendance already marked for the day
|
# attendance already marked for the day
|
||||||
@@ -124,10 +124,3 @@ class TestAttendance(FrappeTestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
|
|
||||||
|
|
||||||
def get_month_name(date):
|
|
||||||
month_number = date.month
|
|
||||||
for month, number in get_month_map().items():
|
|
||||||
if number == month_number:
|
|
||||||
return month
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from frappe.tests.utils import FrappeTestCase
|
from frappe.tests.utils import FrappeTestCase
|
||||||
from frappe.utils import now_datetime
|
from frappe.utils import add_months, getdate
|
||||||
|
|
||||||
from erpnext.hr.doctype.attendance.attendance import mark_attendance
|
from erpnext.hr.doctype.attendance.attendance import mark_attendance
|
||||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||||
@@ -14,9 +14,7 @@ class TestMonthlyAttendanceSheet(FrappeTestCase):
|
|||||||
frappe.db.delete("Attendance", {"employee": self.employee})
|
frappe.db.delete("Attendance", {"employee": self.employee})
|
||||||
|
|
||||||
def test_monthly_attendance_sheet_report(self):
|
def test_monthly_attendance_sheet_report(self):
|
||||||
now = now_datetime()
|
previous_month_first = add_months(getdate(), -1).replace(day=1)
|
||||||
previous_month = now.month - 1
|
|
||||||
previous_month_first = now.replace(day=1).replace(month=previous_month).date()
|
|
||||||
|
|
||||||
company = frappe.db.get_value("Employee", self.employee, "company")
|
company = frappe.db.get_value("Employee", self.employee, "company")
|
||||||
|
|
||||||
@@ -27,8 +25,8 @@ class TestMonthlyAttendanceSheet(FrappeTestCase):
|
|||||||
|
|
||||||
filters = frappe._dict(
|
filters = frappe._dict(
|
||||||
{
|
{
|
||||||
"month": previous_month,
|
"month": previous_month_first.month,
|
||||||
"year": now.year,
|
"year": previous_month_first.year,
|
||||||
"company": company,
|
"company": company,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user