<commit_before># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe

from frappe.utils import add_days, cint, cstr, flt, getdate, nowdate, rounded, date_diff, money_in_words
from frappe.model.naming import make_autoname

from frappe import msgprint, _
from erpnext.accounts.utils import get_fiscal_year
from erpnext.setup.utils import get_company_currency
from erpnext.hr.utils import set_employee_name
from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
from erpnext.utilities.transaction_base import TransactionBase

class SalarySlip(TransactionBase):
	def autoname(self):
		self.name = make_autoname('Sal Slip/' +self.employee + '/.#####')

	def validate(self):
		self.check_existing()

		if not (len(self.get("earnings")) or len(self.get("deductions"))):
			self.get_emp_and_leave_details()
		else:
			self.get_leave_details(lwp = self.leave_without_pay)

		if not self.net_pay:
			self.calculate_net_pay()

		company_currency = get_company_currency(self.company)
		self.total_in_words = money_in_words(self.rounded_total, company_currency)

		set_employee_name(self)
	
	def get_users(self):
		"""get list of users"""
		if not self.employee:
			msgprint(_("Please set employee first."))

		user_list = frappe.db.sql("""
			select company_email, personal_email, user_id from tabEmployee
			where name = %s """, self.employee, as_dict=1)

		if self.recipients_list:
			recipients_list = self.recipients_list.split("\n")
		else:
			recipients_list = []
		for p in user_list:
			p["checked_company"] = p["company_email"] in recipients_list and 1 or 0
			p["checked_personal"] = p["personal_email"] in recipients_list and 1 or 0
			p["checked_user"] = p["user_id"] in recipients_list and 1 or 0

		frappe.response['user_list'] = user_list

	def get_emp_and_leave_details(self):
		if self.employee:
			joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
				["date_of_joining", "relieving_date"])

			self.get_leave_details(joining_date, relieving_date)

			struct = self.check_sal_struct(joining_date, relieving_date)
			if struct:
				self.set("earnings", [])
				self.set("deduction", [])
				self.pull_sal_struct(struct)

	def check_sal_struct(self, joining_date, relieving_date):
		m = get_month_details(self.fiscal_year, self.month)

		struct = frappe.db.sql("""select name from `tabSalary Structure`
			where employee=%s and is_active = 'Yes'
			and (from_date <= %s or from_date <= %s)
			and (to_date is null or to_date >= %s or to_date >= %s)""",
			(self.employee, m.month_start_date, joining_date, m.month_end_date, relieving_date))
		
		if not struct:
			msgprint(_("No active Salary Structure found for employee {0} and the month")
				.format(self.employee))
			self.employee = None

		return struct and struct[0][0] or ''

	def pull_sal_struct(self, struct):
		from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
		make_salary_slip(struct, self)

	def pull_emp_details(self):
		emp = frappe.db.get_value("Employee", self.employee, ["bank_name", "bank_ac_no"], as_dict=1)
		if emp:
			self.bank_name = emp.bank_name
			self.bank_account_no = emp.bank_ac_no

	def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None):
		if not self.fiscal_year:
			# if default fiscal year is not set, get from nowdate
			self.fiscal_year = get_fiscal_year(nowdate())[0]

		if not self.month:
			self.month = "%02d" % getdate(nowdate()).month

		if not joining_date:
			joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
				["date_of_joining", "relieving_date"])

		m = get_month_details(self.fiscal_year, self.month)
		holidays = self.get_holidays_for_employee(m['month_start_date'], m['month_end_date'])

		working_days = m["month_days"]
		if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")):
			working_days -= len(holidays)
			if working_days < 0:
				frappe.throw(_("There are more holidays than working days this month."))

		if not lwp:
			lwp = self.calculate_lwp(holidays, m)
		self.total_days_in_month = working_days
		self.leave_without_pay = lwp
		payment_days = flt(self.get_payment_days(m, joining_date, relieving_date)) - flt(lwp)
		self.payment_days = payment_days > 0 and payment_days or 0

	def get_payment_days(self, month, joining_date, relieving_date):
		start_date = month['month_start_date']
		if joining_date:
			if joining_date > month['month_start_date']:
				start_date = joining_date
			elif joining_date > month['month_end_date']:
				return

		end_date = month['month_end_date']
		if relieving_date:
			if relieving_date > start_date and relieving_date < month['month_end_date']:
				end_date = relieving_date
			elif relieving_date < month['month_start_date']:
				frappe.throw(_("Employee relieved on {0} must be set as 'Left'")
					.format(relieving_date))

		payment_days = date_diff(end_date, start_date) + 1

		if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")):
			holidays = self.get_holidays_for_employee(start_date, end_date)
			payment_days -= len(holidays)

		return payment_days

	def get_holidays_for_employee(self, start_date, end_date):
		holiday_list = get_holiday_list_for_employee(self.employee)
		holidays = frappe.db.sql_list('''select holiday_date from `tabHoliday`
			where
				parent=%(holiday_list)s
				and holiday_date >= %(start_date)s
				and holiday_date <= %(end_date)s''', {
					"holiday_list": holiday_list,
					"start_date": start_date,
					"end_date": end_date
				})

		holidays = [cstr(i) for i in holidays]

		return holidays

	def calculate_lwp(self, holidays, m):
		lwp = 0
		for d in range(m['month_days']):
			dt = add_days(cstr(m['month_start_date']), d)
			if dt not in holidays:
				leave = frappe.db.sql("""
					select t1.name, t1.half_day
					from `tabLeave Application` t1, `tabLeave Type` t2
					where t2.name = t1.leave_type
					and t2.is_lwp = 1
					and t1.docstatus = 1
					and t1.employee = %s
					and %s between from_date and to_date
				""", (self.employee, dt))
				if leave:<commit_msg>working days calculate and warnings<commit_after># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe

from frappe.utils import add_days, cint, cstr, flt, getdate, nowdate, rounded, date_diff, money_in_words
from frappe.model.naming import make_autoname

from frappe import msgprint, _
from erpnext.accounts.utils import get_fiscal_year
from erpnext.setup.utils import get_company_currency
from erpnext.hr.utils import set_employee_name
from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
from erpnext.utilities.transaction_base import TransactionBase

class SalarySlip(TransactionBase):
	def autoname(self):
		self.name = make_autoname('Sal Slip/' +self.employee + '/.#####')

	def validate(self):
		self.check_existing()

		if not (len(self.get("earnings")) or len(self.get("deductions"))):
			self.get_emp_and_leave_details()
		else:
			self.get_leave_details(lwp = self.leave_without_pay)

		if not self.net_pay:
			self.calculate_net_pay()

		company_currency = get_company_currency(self.company)
		self.total_in_words = money_in_words(self.rounded_total, company_currency)

		set_employee_name(self)
	
	def get_users(self):
		"""get list of users"""
		if not self.employee:
			msgprint(_("Please set employee first."))

		user_list = frappe.db.sql("""
			select company_email, personal_email, user_id from tabEmployee
			where name = %s """, self.employee, as_dict=1)

		if self.recipients_list:
			recipients_list = self.recipients_list.split("\n")
		else:
			recipients_list = []
		for p in user_list:
			p["checked_company"] = p["company_email"] in recipients_list and 1 or 0
			p["checked_personal"] = p["personal_email"] in recipients_list and 1 or 0
			p["checked_user"] = p["user_id"] in recipients_list and 1 or 0

		frappe.response['user_list'] = user_list

	def get_emp_and_leave_details(self):
		if self.employee:
			joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
				["date_of_joining", "relieving_date"])
			
			self.get_leave_details(joining_date, relieving_date)
			struct = self.check_sal_struct(joining_date, relieving_date)
			if struct:
				self.set("earnings", [])
				self.set("deduction", [])
				self.pull_sal_struct(struct)

	def check_sal_struct(self, joining_date, relieving_date):
		m = get_month_details(self.fiscal_year, self.month)

		struct = frappe.db.sql("""select name from `tabSalary Structure`
			where employee=%s and is_active = 'Yes'
			and (from_date <= %s or from_date <= %s)
			and (to_date is null or to_date >= %s or to_date >= %s)""",
			(self.employee, m.month_start_date, joining_date, m.month_end_date, relieving_date))
		
		if not struct:
			msgprint(_("No active Salary Structure found for employee {0} and the month")
				.format(self.employee))
			self.employee = None

		return struct and struct[0][0] or ''

	def pull_sal_struct(self, struct):
		from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
		make_salary_slip(struct, self)

	def pull_emp_details(self):
		emp = frappe.db.get_value("Employee", self.employee, ["bank_name", "bank_ac_no"], as_dict=1)
		if emp:
			self.bank_name = emp.bank_name
			self.bank_account_no = emp.bank_ac_no

	def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None):
		if not self.fiscal_year:
			# if default fiscal year is not set, get from nowdate
			self.fiscal_year = get_fiscal_year(nowdate())[0]

		if not self.month:
			self.month = "%02d" % getdate(nowdate()).month
		
		if not joining_date:
			get_type = None
			joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
				["date_of_joining", "relieving_date"])
		else:
			get_type = "working"

		m = get_month_details(self.fiscal_year, self.month)
		
		holidays = self.get_holidays_for_employee(m['month_start_date'], m['month_end_date'], get_type)
		
		working_days = m["month_days"]
		if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")):
			working_days -= len(holidays)
			if working_days < 0:
				frappe.throw(_("There are more holidays than working days this month."))

		if not lwp:
			lwp = self.calculate_lwp(holidays, m)
		self.total_days_in_month = working_days
		self.leave_without_pay = lwp
		payment_days = flt(self.get_payment_days(m, joining_date, relieving_date)) - flt(lwp)
		self.payment_days = payment_days > 0 and payment_days or 0

	def get_payment_days(self, month, joining_date, relieving_date):
		start_date = month['month_start_date']
		if joining_date:
			if joining_date > month['month_start_date']:
				start_date = joining_date
			elif joining_date > month['month_end_date']:
				return

		end_date = month['month_end_date']
		if relieving_date:
			if relieving_date > start_date and relieving_date < month['month_end_date']:
				end_date = relieving_date
			elif relieving_date < month['month_start_date']:
				frappe.throw(_("Employee relieved on {0} must be set as 'Left'")
					.format(relieving_date))

		payment_days = date_diff(end_date, start_date) + 1

		if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")):
			holidays = self.get_holidays_for_employee(start_date, end_date)
			payment_days -= len(holidays)

		return payment_days

	def get_holidays_for_employee(self, start_date, end_date, get_type=None):
		holiday_list = get_holiday_list_for_employee(self.employee)

		count, d_count = frappe.db.sql('''select count(*),count(distinct holiday_date) from `tabHoliday`
				where holiday_date >= %(start_date)s
				and holiday_date <= %(end_date)s''', {
					"start_date": start_date,
					"end_date": end_date
				})[0]
		
		if count == d_count:
			if count == 0 and get_type == "working":
				frappe.msgprint(_("No Holiday lists have been found for in this period.The default Holiday list is {0} as specified in the Company.").format(holiday_list))

			holidays = frappe.db.sql_list('''select holiday_date from `tabHoliday`
				where holiday_date >= %(start_date)s
					and holiday_date <= %(end_date)s''', {
						"start_date": start_date,
						"end_date": end_date
					})
		else:
			if get_type == "working":
				frappe.msgprint(_("Multiple holiday lists have been found for the same period. The default Holiday list {0} has been selected.").format(holiday_list))

			holidays = frappe.db.sql_list('''select holiday_date from `tabHoliday`
				where
					parent=%(holiday_list)s
					and holiday_date >= %(start_date)s
					and holiday_date <= %(end_date)s''', {
						"holiday_list": holiday_list,
						"start_date": start_date,
						"end_date": end_date
					})
			if len(holidays) == 0 and get_type == "working":
				frappe.msgprint(_("There is no Holiday Date in this payslip period."))

		holidays = [cstr(i) for i in holidays]

		return holidays

	def calculate_lwp(self, holidays, m):
		lwp = 0
		for d in range(m['month_days']):
			dt = add_days(cstr(m['month_start_date']), d)
			if dt not in holidays:
				leave = frappe.db.sql("""
					select t1.name, t1.half_day
					from `tabLeave Application` t1, `tabLeave Type` t2
					where t2.name = t1.leave_type
					and t2.is_lwp = 1
					and t1.docstatus = 1
					and t1.employee = %s
					and %s between from_date and to_date
				""", (self.employee, dt))
				if leave:
{'fraction_non_alphanumeric': 0.11174077303109561, 'fraction_numerical': 0.005594303981400756, 'mean_word_length': 4.683319570602808, 'pattern_counts': {'":': 13, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3861264', 'n_tokens_mistral': 5496, 'n_tokens_neox': 4819, 'n_words': 1097}