fix: remove HR/Payroll patches

This commit is contained in:
Rucha Mahabal
2022-06-27 20:25:16 +05:30
parent c8712b02f9
commit 930e557fc6
42 changed files with 2 additions and 1400 deletions

View File

@@ -1,58 +0,0 @@
# Copyright (c) 2018, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
def execute():
if not frappe.db.table_exists("Daily Work Summary Group"):
frappe.reload_doc("hr", "doctype", "daily_work_summary_group")
frappe.reload_doc("hr", "doctype", "daily_work_summary_group_user")
# check if Daily Work Summary Settings Company table exists
try:
frappe.db.sql("DESC `tabDaily Work Summary Settings Company`")
except Exception:
return
# get the previously saved settings
previous_setting = get_previous_setting()
if previous_setting["companies"]:
for d in previous_setting["companies"]:
users = frappe.get_list(
"Employee", dict(company=d.company, user_id=("!=", " ")), "user_id as user"
)
if len(users):
# create new group entry for each company entry
new_group = frappe.get_doc(
dict(
doctype="Daily Work Summary Group",
name="Daily Work Summary for " + d.company,
users=users,
send_emails_at=d.send_emails_at,
subject=previous_setting["subject"],
message=previous_setting["message"],
)
)
new_group.flags.ignore_permissions = True
new_group.flags.ignore_validate = True
new_group.insert(ignore_if_duplicate=True)
frappe.delete_doc("DocType", "Daily Work Summary Settings")
frappe.delete_doc("DocType", "Daily Work Summary Settings Company")
def get_previous_setting():
obj = {}
setting_data = frappe.db.sql(
"select field, value from tabSingles where doctype='Daily Work Summary Settings'"
)
for field, value in setting_data:
obj[field] = value
obj["companies"] = get_setting_companies()
return obj
def get_setting_companies():
return frappe.db.sql("select * from `tabDaily Work Summary Settings Company`", as_dict=True)

View File

@@ -1,10 +0,0 @@
import frappe
def execute():
if frappe.db.table_exists("Offer Letter") and not frappe.db.table_exists("Job Offer"):
frappe.rename_doc("DocType", "Offer Letter", "Job Offer", force=True)
frappe.rename_doc("DocType", "Offer Letter Term", "Job Offer Term", force=True)
frappe.reload_doc("hr", "doctype", "job_offer")
frappe.reload_doc("hr", "doctype", "job_offer_term")
frappe.delete_doc("Print Format", "Offer Letter")

View File

@@ -1,38 +0,0 @@
import os
import frappe
from frappe import _
def execute():
frappe.reload_doc("email", "doctype", "email_template")
if not frappe.db.exists("Email Template", _("Leave Approval Notification")):
base_path = frappe.get_app_path("erpnext", "hr", "doctype")
response = frappe.read_file(
os.path.join(base_path, "leave_application/leave_application_email_template.html")
)
frappe.get_doc(
{
"doctype": "Email Template",
"name": _("Leave Approval Notification"),
"response": response,
"subject": _("Leave Approval Notification"),
"owner": frappe.session.user,
}
).insert(ignore_permissions=True)
if not frappe.db.exists("Email Template", _("Leave Status Notification")):
base_path = frappe.get_app_path("erpnext", "hr", "doctype")
response = frappe.read_file(
os.path.join(base_path, "leave_application/leave_application_email_template.html")
)
frappe.get_doc(
{
"doctype": "Email Template",
"name": _("Leave Status Notification"),
"response": response,
"subject": _("Leave Status Notification"),
"owner": frappe.session.user,
}
).insert(ignore_permissions=True)

View File

@@ -1,91 +0,0 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from datetime import datetime
import frappe
from frappe.utils import getdate
from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import (
DuplicateAssignment,
)
def execute():
frappe.reload_doc("Payroll", "doctype", "Salary Structure")
frappe.reload_doc("Payroll", "doctype", "Salary Structure Assignment")
frappe.db.sql(
"""
delete from `tabSalary Structure Assignment`
where salary_structure in (select name from `tabSalary Structure` where is_active='No' or docstatus!=1)
"""
)
if frappe.db.table_exists("Salary Structure Employee"):
ss_details = frappe.db.sql(
"""
select sse.employee, sse.employee_name, sse.from_date, sse.to_date,
sse.base, sse.variable, sse.parent as salary_structure, ss.company
from `tabSalary Structure Employee` sse, `tabSalary Structure` ss
where ss.name = sse.parent AND ss.is_active='Yes'
AND sse.employee in (select name from `tabEmployee` where ifNull(status, '') != 'Left')""",
as_dict=1,
)
else:
cols = ""
if "base" in frappe.db.get_table_columns("Salary Structure"):
cols = ", base, variable"
ss_details = frappe.db.sql(
"""
select name as salary_structure, employee, employee_name, from_date, to_date, company {0}
from `tabSalary Structure`
where is_active='Yes'
AND employee in (select name from `tabEmployee` where ifNull(status, '') != 'Left')
""".format(
cols
),
as_dict=1,
)
all_companies = frappe.db.get_all("Company", fields=["name", "default_currency"])
for d in all_companies:
company = d.name
company_currency = d.default_currency
frappe.db.sql(
"""update `tabSalary Structure` set currency = %s where company=%s""",
(company_currency, company),
)
for d in ss_details:
try:
joining_date, relieving_date = frappe.db.get_value(
"Employee", d.employee, ["date_of_joining", "relieving_date"]
)
from_date = d.from_date
if joining_date and getdate(from_date) < joining_date:
from_date = joining_date
elif relieving_date and getdate(from_date) > relieving_date:
continue
company_currency = frappe.db.get_value("Company", d.company, "default_currency")
s = frappe.new_doc("Salary Structure Assignment")
s.employee = d.employee
s.employee_name = d.employee_name
s.salary_structure = d.salary_structure
s.from_date = from_date
s.to_date = d.to_date if isinstance(d.to_date, datetime) else None
s.base = d.get("base")
s.variable = d.get("variable")
s.company = d.company
s.currency = company_currency
# to migrate the data of the old employees
s.flags.old_employee = True
s.save()
s.submit()
except DuplicateAssignment:
pass
frappe.db.sql("update `tabSalary Structure` set docstatus=1")

View File

@@ -1,7 +0,0 @@
import frappe
def execute():
if frappe.db.exists("DocType", "Leave Type"):
if "max_days_allowed" in frappe.db.get_table_columns("Leave Type"):
frappe.db.sql("alter table `tabLeave Type` drop column max_days_allowed")

View File

@@ -1,34 +0,0 @@
import frappe
from frappe.model.utils.rename_field import rename_field
def execute():
frappe.reload_doc("hr", "doctype", "department_approver")
frappe.reload_doc("hr", "doctype", "employee")
frappe.reload_doc("hr", "doctype", "department")
if frappe.db.has_column("Department", "leave_approver"):
rename_field("Department", "leave_approver", "leave_approvers")
if frappe.db.has_column("Department", "expense_approver"):
rename_field("Department", "expense_approver", "expense_approvers")
if not frappe.db.table_exists("Employee Leave Approver"):
return
approvers = frappe.db.sql(
"""select distinct app.leave_approver, emp.department from
`tabEmployee Leave Approver` app, `tabEmployee` emp
where app.parenttype = 'Employee'
and emp.name = app.parent
""",
as_dict=True,
)
for record in approvers:
if record.department:
department = frappe.get_doc("Department", record.department)
if not department:
return
if not len(department.leave_approvers):
department.append("leave_approvers", {"approver": record.leave_approver}).db_insert()

View File

@@ -1,11 +0,0 @@
import frappe
# this patch should have been included with this PR https://github.com/frappe/erpnext/pull/14302
def execute():
if frappe.db.table_exists("Additional Salary Component"):
if not frappe.db.table_exists("Additional Salary"):
frappe.rename_doc("DocType", "Additional Salary Component", "Additional Salary")
frappe.delete_doc("DocType", "Additional Salary Component")

View File

@@ -1,15 +0,0 @@
import frappe
from frappe.model.utils.rename_field import rename_field
def execute():
frappe.db.sql(
"""
UPDATE `tabLeave Type`
SET max_days_allowed = '0'
WHERE trim(coalesce(max_days_allowed, '')) = ''
"""
)
frappe.db.sql_ddl("""ALTER table `tabLeave Type` modify max_days_allowed int(8) NOT NULL""")
frappe.reload_doc("hr", "doctype", "leave_type")
rename_field("Leave Type", "max_days_allowed", "max_continuous_days_allowed")

View File

@@ -1,9 +0,0 @@
import frappe
from frappe import _
def execute():
hr_settings = frappe.get_single("HR Settings")
hr_settings.leave_approval_notification_template = _("Leave Approval Notification")
hr_settings.leave_status_notification_template = _("Leave Status Notification")
hr_settings.save()

View File

@@ -6,19 +6,6 @@ import frappe
def execute():
doctypes_to_update = {
"hr": [
"Appraisal",
"Leave Allocation",
"Expense Claim",
"Salary Slip",
"Attendance",
"Training Feedback",
"Training Result Employee",
"Leave Application",
"Employee Advance",
"Training Event Employee",
"Payroll Employee Detail",
],
"projects": ["Activity Cost", "Timesheet"],
"setup": ["Sales Person"],
}

View File

@@ -1,22 +0,0 @@
import frappe
def execute():
frappe.reload_doc("Payroll", "doctype", "salary_detail")
frappe.reload_doc("Payroll", "doctype", "salary_component")
frappe.db.sql("update `tabSalary Component` set is_tax_applicable=1 where type='Earning'")
frappe.db.sql(
"""update `tabSalary Component` set variable_based_on_taxable_salary=1
where type='Deduction' and name in ('TDS', 'Tax Deducted at Source')"""
)
frappe.db.sql(
"""update `tabSalary Detail` set is_tax_applicable=1
where parentfield='earnings' and statistical_component=0"""
)
frappe.db.sql(
"""update `tabSalary Detail` set variable_based_on_taxable_salary=1
where parentfield='deductions' and salary_component in ('TDS', 'Tax Deducted at Source')"""
)

View File

@@ -1,85 +0,0 @@
import frappe
from frappe.desk.form.linked_with import get_linked_doctypes
# Skips user permission check for doctypes where department link field was recently added
# https://github.com/frappe/erpnext/pull/14121
def execute():
doctypes_to_skip = []
for doctype in [
"Appraisal",
"Leave Allocation",
"Expense Claim",
"Instructor",
"Salary Slip",
"Attendance",
"Training Feedback",
"Training Result Employee",
"Leave Application",
"Employee Advance",
"Activity Cost",
"Training Event Employee",
"Timesheet",
"Sales Person",
"Payroll Employee Detail",
]:
if frappe.db.exists("Custom Field", {"dt": doctype, "fieldname": "department"}):
continue
doctypes_to_skip.append(doctype)
frappe.reload_doctype("User Permission")
user_permissions = frappe.get_all(
"User Permission",
filters=[["allow", "=", "Department"], ["applicable_for", "in", [None] + doctypes_to_skip]],
fields=["name", "applicable_for"],
)
user_permissions_to_delete = []
new_user_permissions_list = []
for user_permission in user_permissions:
if user_permission.applicable_for:
# simply delete user permission record since it needs to be skipped.
user_permissions_to_delete.append(user_permission.name)
else:
# if applicable_for is `None` it means that user permission is applicable for every doctype
# to avoid this we need to create other user permission records and only skip the listed doctypes in this patch
linked_doctypes = get_linked_doctypes(user_permission.allow, True).keys()
applicable_for_doctypes = list(set(linked_doctypes) - set(doctypes_to_skip))
user_permissions_to_delete.append(user_permission.name)
for doctype in applicable_for_doctypes:
if doctype:
# Maintain sequence (name, user, allow, for_value, applicable_for, apply_to_all_doctypes)
new_user_permissions_list.append(
(
frappe.generate_hash("", 10),
user_permission.user,
user_permission.allow,
user_permission.for_value,
doctype,
0,
)
)
if new_user_permissions_list:
frappe.db.sql(
"""
INSERT INTO `tabUser Permission`
(`name`, `user`, `allow`, `for_value`, `applicable_for`, `apply_to_all_doctypes`)
VALUES {}""".format(
", ".join(["%s"] * len(new_user_permissions_list))
), # nosec
tuple(new_user_permissions_list),
)
if user_permissions_to_delete:
frappe.db.sql(
"DELETE FROM `tabUser Permission` WHERE `name` IN ({})".format( # nosec
",".join(["%s"] * len(user_permissions_to_delete))
),
tuple(user_permissions_to_delete),
)

View File

@@ -5,7 +5,7 @@ from frappe.utils.nestedset import rebuild_tree
def execute():
"""assign lft and rgt appropriately"""
frappe.reload_doc("hr", "doctype", "department")
frappe.reload_doc("setup", "doctype", "department")
if not frappe.db.exists("Department", _("All Departments")):
frappe.get_doc(
{"doctype": "Department", "department_name": _("All Departments"), "is_group": 1}

View File

@@ -1,14 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
from frappe import scrub
from frappe.model.utils.rename_field import rename_field
def execute():
for doctype in ("Salary Component", "Salary Detail"):
if "depends_on_lwp" in frappe.db.get_table_columns(doctype):
frappe.reload_doc("Payroll", "doctype", scrub(doctype))
rename_field(doctype, "depends_on_lwp", "depends_on_payment_days")

View File

@@ -1,11 +0,0 @@
import frappe
def execute():
frappe.db.sql(
"""
update `tabSalary Structure` ss, `tabSalary Detail` sd
set sd.docstatus=1
where ss.name=sd.parent and ss.docstatus=1 and sd.parenttype='Salary Structure'
"""
)

View File

@@ -1,100 +0,0 @@
# Copyright (c) 2018, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.utils import getdate, today
def execute():
"""Generates leave ledger entries for leave allocation/application/encashment
for last allocation"""
frappe.reload_doc("HR", "doctype", "Leave Ledger Entry")
frappe.reload_doc("HR", "doctype", "Leave Encashment")
frappe.reload_doc("HR", "doctype", "Leave Type")
if not frappe.get_meta("Leave Allocation").has_field("unused_leaves"):
frappe.reload_doc("HR", "doctype", "Leave Allocation")
update_leave_allocation_fieldname()
generate_allocation_ledger_entries()
generate_application_leave_ledger_entries()
generate_encashment_leave_ledger_entries()
generate_expiry_allocation_ledger_entries()
def update_leave_allocation_fieldname():
"""maps data from old field to the new field"""
frappe.db.sql(
"""
UPDATE `tabLeave Allocation`
SET `unused_leaves` = `carry_forwarded_leaves`
"""
)
def generate_allocation_ledger_entries():
"""fix ledger entries for missing leave allocation transaction"""
allocation_list = get_allocation_records()
for allocation in allocation_list:
if not frappe.db.exists(
"Leave Ledger Entry",
{"transaction_type": "Leave Allocation", "transaction_name": allocation.name},
):
allocation_obj = frappe.get_doc("Leave Allocation", allocation)
allocation_obj.create_leave_ledger_entry()
def generate_application_leave_ledger_entries():
"""fix ledger entries for missing leave application transaction"""
leave_applications = get_leaves_application_records()
for application in leave_applications:
if not frappe.db.exists(
"Leave Ledger Entry",
{"transaction_type": "Leave Application", "transaction_name": application.name},
):
frappe.get_doc("Leave Application", application.name).create_leave_ledger_entry()
def generate_encashment_leave_ledger_entries():
"""fix ledger entries for missing leave encashment transaction"""
leave_encashments = get_leave_encashment_records()
for encashment in leave_encashments:
if not frappe.db.exists(
"Leave Ledger Entry",
{"transaction_type": "Leave Encashment", "transaction_name": encashment.name},
):
frappe.get_doc("Leave Encashment", encashment).create_leave_ledger_entry()
def generate_expiry_allocation_ledger_entries():
"""fix ledger entries for missing leave allocation transaction"""
from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import expire_allocation
allocation_list = get_allocation_records()
for allocation in allocation_list:
if not frappe.db.exists(
"Leave Ledger Entry",
{"transaction_type": "Leave Allocation", "transaction_name": allocation.name, "is_expired": 1},
):
allocation_obj = frappe.get_doc("Leave Allocation", allocation)
if allocation_obj.to_date <= getdate(today()):
expire_allocation(allocation_obj)
def get_allocation_records():
return frappe.get_all(
"Leave Allocation", filters={"docstatus": 1}, fields=["name"], order_by="to_date ASC"
)
def get_leaves_application_records():
return frappe.get_all("Leave Application", filters={"docstatus": 1}, fields=["name"])
def get_leave_encashment_records():
return frappe.get_all("Leave Encashment", filters={"docstatus": 1}, fields=["name"])

View File

@@ -1,12 +0,0 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
def execute():
"""Move from due_advance_amount to pending_amount"""
if frappe.db.has_column("Employee Advance", "due_advance_amount"):
frappe.db.sql(""" UPDATE `tabEmployee Advance` SET pending_amount=due_advance_amount """)

View File

@@ -1,35 +0,0 @@
# Copyright (c) 2018, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
def execute():
"""Delete leave ledger entry created
via leave applications with status != Approved"""
if not frappe.db.a_row_exists("Leave Ledger Entry"):
return
leave_application_list = get_denied_leave_application_list()
if leave_application_list:
delete_denied_leaves_from_leave_ledger_entry(leave_application_list)
def get_denied_leave_application_list():
return frappe.db.sql_list(
""" Select name from `tabLeave Application` where status <> 'Approved' """
)
def delete_denied_leaves_from_leave_ledger_entry(leave_application_list):
if leave_application_list:
frappe.db.sql(
""" Delete
FROM `tabLeave Ledger Entry`
WHERE
transaction_type = 'Leave Application'
AND transaction_name in (%s) """
% (", ".join(["%s"] * len(leave_application_list))), # nosec
tuple(leave_application_list),
)

View File

@@ -1,55 +0,0 @@
# Copyright (c) 2018, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
def execute():
"""Delete duplicate leave ledger entries of type allocation created."""
frappe.reload_doc("hr", "doctype", "leave_ledger_entry")
if not frappe.db.a_row_exists("Leave Ledger Entry"):
return
duplicate_records_list = get_duplicate_records()
delete_duplicate_ledger_entries(duplicate_records_list)
def get_duplicate_records():
"""Fetch all but one duplicate records from the list of expired leave allocation."""
return frappe.db.sql(
"""
SELECT name, employee, transaction_name, leave_type, is_carry_forward, from_date, to_date
FROM `tabLeave Ledger Entry`
WHERE
transaction_type = 'Leave Allocation'
AND docstatus = 1
AND is_expired = 1
GROUP BY
employee, transaction_name, leave_type, is_carry_forward, from_date, to_date
HAVING
count(name) > 1
ORDER BY
creation
"""
)
def delete_duplicate_ledger_entries(duplicate_records_list):
"""Delete duplicate leave ledger entries."""
if not duplicate_records_list:
return
for d in duplicate_records_list:
frappe.db.sql(
"""
DELETE FROM `tabLeave Ledger Entry`
WHERE name != %s
AND employee = %s
AND transaction_name = %s
AND leave_type = %s
AND is_carry_forward = %s
AND from_date = %s
AND to_date = %s
""",
tuple(d),
)

View File

@@ -1,6 +0,0 @@
import frappe
def execute():
frappe.reload_doc("hr", "doctype", "hr_settings")
frappe.db.set_value("HR Settings", None, "payroll_based_on", "Leave")

View File

@@ -1,14 +0,0 @@
import frappe
def execute():
frappe.reload_doc("hr", "doctype", "job_offer")
frappe.db.sql(
"""
UPDATE
`tabJob Offer` AS offer
SET
applicant_email = (SELECT email_id FROM `tabJob Applicant` WHERE name = offer.job_applicant)
"""
)

View File

@@ -1,44 +0,0 @@
import os
import frappe
from frappe import _
def execute():
if not frappe.db.exists("Email Template", _("Interview Reminder")):
base_path = frappe.get_app_path("erpnext", "hr", "doctype")
response = frappe.read_file(
os.path.join(base_path, "interview/interview_reminder_notification_template.html")
)
frappe.get_doc(
{
"doctype": "Email Template",
"name": _("Interview Reminder"),
"response": response,
"subject": _("Interview Reminder"),
"owner": frappe.session.user,
}
).insert(ignore_permissions=True)
if not frappe.db.exists("Email Template", _("Interview Feedback Reminder")):
base_path = frappe.get_app_path("erpnext", "hr", "doctype")
response = frappe.read_file(
os.path.join(base_path, "interview/interview_feedback_reminder_template.html")
)
frappe.get_doc(
{
"doctype": "Email Template",
"name": _("Interview Feedback Reminder"),
"response": response,
"subject": _("Interview Feedback Reminder"),
"owner": frappe.session.user,
}
).insert(ignore_permissions=True)
hr_settings = frappe.get_doc("HR Settings")
hr_settings.interview_reminder_template = _("Interview Reminder")
hr_settings.feedback_reminder_notification_template = _("Interview Feedback Reminder")
hr_settings.flags.ignore_links = True
hr_settings.save()

View File

@@ -1,62 +0,0 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
import erpnext
def execute():
doctypes = [
"salary_component",
"Employee Tax Exemption Declaration",
"Employee Tax Exemption Proof Submission",
"Employee Tax Exemption Declaration Category",
"Employee Tax Exemption Proof Submission Detail",
"gratuity_rule",
"gratuity_rule_slab",
"gratuity_applicable_component",
]
for doctype in doctypes:
frappe.reload_doc("Payroll", "doctype", doctype, force=True)
reports = ["Professional Tax Deductions", "Provident Fund Deductions", "E-Invoice Summary"]
for report in reports:
frappe.reload_doc("Regional", "Report", report)
frappe.reload_doc("Regional", "Report", report)
if erpnext.get_region() == "India":
create_custom_field(
"Salary Component",
dict(
fieldname="component_type",
label="Component Type",
fieldtype="Select",
insert_after="description",
options="\nProvident Fund\nAdditional Provident Fund\nProvident Fund Loan\nProfessional Tax",
depends_on='eval:doc.type == "Deduction"',
),
)
if frappe.db.exists("Salary Component", "Income Tax"):
frappe.db.set_value("Salary Component", "Income Tax", "is_income_tax_component", 1)
if frappe.db.exists("Salary Component", "TDS"):
frappe.db.set_value("Salary Component", "TDS", "is_income_tax_component", 1)
components = frappe.db.sql(
"select name from `tabSalary Component` where variable_based_on_taxable_salary = 1", as_dict=1
)
for component in components:
frappe.db.set_value("Salary Component", component.name, "is_income_tax_component", 1)
if erpnext.get_region() == "India":
if frappe.db.exists("Salary Component", "Provident Fund"):
frappe.db.set_value("Salary Component", "Provident Fund", "component_type", "Provident Fund")
if frappe.db.exists("Salary Component", "Professional Tax"):
frappe.db.set_value(
"Salary Component", "Professional Tax", "component_type", "Professional Tax"
)

View File

@@ -1,44 +0,0 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
from erpnext.setup.install import add_non_standard_user_types
def execute():
doctype_dict = {
"projects": ["Timesheet"],
"payroll": [
"Salary Slip",
"Employee Tax Exemption Declaration",
"Employee Tax Exemption Proof Submission",
"Employee Benefit Application",
"Employee Benefit Claim",
],
"hr": [
"Employee",
"Expense Claim",
"Leave Application",
"Attendance Request",
"Compensatory Leave Request",
"Holiday List",
"Employee Advance",
"Training Program",
"Training Feedback",
"Shift Request",
"Employee Grievance",
"Employee Referral",
"Travel Request",
],
}
for module, doctypes in doctype_dict.items():
for doctype in doctypes:
frappe.reload_doc(module, "doctype", doctype)
frappe.flags.ignore_select_perm = True
frappe.flags.update_select_perm_after_migrate = True
add_non_standard_user_types()

View File

@@ -1,52 +0,0 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
def execute():
frappe.db.sql(
"""UPDATE `tabPrint Format`
SET module = 'Payroll'
WHERE name IN ('Salary Slip Based On Timesheet', 'Salary Slip Standard')"""
)
frappe.db.sql("""UPDATE `tabNotification` SET module='Payroll' WHERE name='Retention Bonus';""")
doctypes_moved = [
"Employee Benefit Application Detail",
"Employee Tax Exemption Declaration Category",
"Salary Component",
"Employee Tax Exemption Proof Submission Detail",
"Income Tax Slab Other Charges",
"Taxable Salary Slab",
"Payroll Period Date",
"Salary Slip Timesheet",
"Payroll Employee Detail",
"Salary Detail",
"Employee Tax Exemption Sub Category",
"Employee Tax Exemption Category",
"Employee Benefit Claim",
"Employee Benefit Application",
"Employee Other Income",
"Employee Tax Exemption Proof Submission",
"Employee Tax Exemption Declaration",
"Employee Incentive",
"Retention Bonus",
"Additional Salary",
"Income Tax Slab",
"Payroll Period",
"Salary Slip",
"Payroll Entry",
"Salary Structure Assignment",
"Salary Structure",
]
for doctype in doctypes_moved:
frappe.delete_doc_if_exists("DocType", doctype)
reports = ["Salary Register", "Bank Remittance"]
for report in reports:
frappe.delete_doc_if_exists("Report", report)

View File

@@ -1,30 +0,0 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
def execute():
data = frappe.db.sql(
"""SELECT *
FROM `tabSingles`
WHERE
doctype = "HR Settings"
AND
field in (
"encrypt_salary_slips_in_emails",
"email_salary_slip_to_employee",
"daily_wages_fraction_for_half_day",
"disable_rounded_total",
"include_holidays_in_total_working_days",
"max_working_hours_against_timesheet",
"payroll_based_on",
"password_policy"
)
""",
as_dict=1,
)
for d in data:
frappe.db.set_value("Payroll Settings", None, d.field, d.value)

View File

@@ -1,135 +0,0 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
def execute():
if not (
frappe.db.table_exists("Payroll Period") and frappe.db.table_exists("Taxable Salary Slab")
):
return
for doctype in (
"income_tax_slab",
"salary_structure_assignment",
"employee_other_income",
"income_tax_slab_other_charges",
):
frappe.reload_doc("Payroll", "doctype", doctype)
standard_tax_exemption_amount_exists = frappe.db.has_column(
"Payroll Period", "standard_tax_exemption_amount"
)
select_fields = "name, start_date, end_date"
if standard_tax_exemption_amount_exists:
select_fields = "name, start_date, end_date, standard_tax_exemption_amount"
for company in frappe.get_all("Company"):
payroll_periods = frappe.db.sql(
"""
SELECT
{0}
FROM
`tabPayroll Period`
WHERE company=%s
ORDER BY start_date DESC
""".format(
select_fields
),
company.name,
as_dict=1,
)
for i, period in enumerate(payroll_periods):
income_tax_slab = frappe.new_doc("Income Tax Slab")
income_tax_slab.name = "Tax Slab:" + period.name
if i == 0:
income_tax_slab.disabled = 0
else:
income_tax_slab.disabled = 1
income_tax_slab.effective_from = period.start_date
income_tax_slab.company = company.name
income_tax_slab.allow_tax_exemption = 1
if standard_tax_exemption_amount_exists:
income_tax_slab.standard_tax_exemption_amount = period.standard_tax_exemption_amount
income_tax_slab.flags.ignore_mandatory = True
income_tax_slab.submit()
frappe.db.sql(
""" UPDATE `tabTaxable Salary Slab`
SET parent = %s , parentfield = 'slabs' , parenttype = "Income Tax Slab"
WHERE parent = %s
""",
(income_tax_slab.name, period.name),
as_dict=1,
)
if i == 0:
frappe.db.sql(
"""
UPDATE
`tabSalary Structure Assignment`
set
income_tax_slab = %s
where
company = %s
and from_date >= %s
and docstatus < 2
""",
(income_tax_slab.name, company.name, period.start_date),
)
# move other incomes to separate document
if not frappe.db.table_exists("Employee Tax Exemption Proof Submission"):
return
migrated = []
proofs = frappe.get_all(
"Employee Tax Exemption Proof Submission",
filters={"docstatus": 1},
fields=["payroll_period", "employee", "company", "income_from_other_sources"],
)
for proof in proofs:
if proof.income_from_other_sources:
employee_other_income = frappe.new_doc("Employee Other Income")
employee_other_income.employee = proof.employee
employee_other_income.payroll_period = proof.payroll_period
employee_other_income.company = proof.company
employee_other_income.amount = proof.income_from_other_sources
try:
employee_other_income.submit()
migrated.append([proof.employee, proof.payroll_period])
except Exception:
pass
if not frappe.db.table_exists("Employee Tax Exemption Declaration"):
return
declerations = frappe.get_all(
"Employee Tax Exemption Declaration",
filters={"docstatus": 1},
fields=["payroll_period", "employee", "company", "income_from_other_sources"],
)
for declaration in declerations:
if (
declaration.income_from_other_sources
and [declaration.employee, declaration.payroll_period] not in migrated
):
employee_other_income = frappe.new_doc("Employee Other Income")
employee_other_income.employee = declaration.employee
employee_other_income.payroll_period = declaration.payroll_period
employee_other_income.company = declaration.company
employee_other_income.amount = declaration.income_from_other_sources
try:
employee_other_income.submit()
except Exception:
pass

View File

@@ -1,21 +0,0 @@
import frappe
from frappe.model.utils.rename_field import rename_field
def execute():
frappe.reload_doc("hr", "doctype", "hr_settings")
try:
# Rename the field
rename_field("HR Settings", "stop_birthday_reminders", "send_birthday_reminders")
# Reverse the value
old_value = frappe.db.get_single_value("HR Settings", "send_birthday_reminders")
frappe.db.set_value(
"HR Settings", "HR Settings", "send_birthday_reminders", 1 if old_value == 0 else 0
)
except Exception as e:
if e.args[0] != 1054:
raise

View File

@@ -1,12 +0,0 @@
import frappe
def execute():
frappe.reload_doc("HR", "doctype", "Leave Allocation")
frappe.reload_doc("HR", "doctype", "Leave Ledger Entry")
frappe.db.sql(
"""update `tabLeave Ledger Entry` as lle set company = (select company from `tabEmployee` where employee = lle.employee)"""
)
frappe.db.sql(
"""update `tabLeave Allocation` as la set company = (select company from `tabEmployee` where employee = la.employee)"""
)

View File

@@ -1,16 +0,0 @@
import frappe
from frappe.query_builder import Case
def execute():
PayrollEntry = frappe.qb.DocType("Payroll Entry")
(
frappe.qb.update(PayrollEntry).set(
"status",
Case()
.when(PayrollEntry.docstatus == 0, "Draft")
.when(PayrollEntry.docstatus == 1, "Submitted")
.else_("Cancelled"),
)
).run()

View File

@@ -1,11 +0,0 @@
import frappe
def execute():
frappe.reload_doc("hr", "doctype", "training_event")
frappe.reload_doc("hr", "doctype", "training_event_employee")
frappe.db.sql("update `tabTraining Event Employee` set `attendance` = 'Present'")
frappe.db.sql(
"update `tabTraining Event Employee` set `is_mandatory` = 1 where `attendance` = 'Mandatory'"
)

View File

@@ -1,29 +0,0 @@
import frappe
def execute():
frappe.reload_doc("hr", "doctype", "employee_advance")
advance = frappe.qb.DocType("Employee Advance")
(
frappe.qb.update(advance)
.set(advance.status, "Returned")
.where(
(advance.docstatus == 1)
& ((advance.return_amount) & (advance.paid_amount == advance.return_amount))
& (advance.status == "Paid")
)
).run()
(
frappe.qb.update(advance)
.set(advance.status, "Partly Claimed and Returned")
.where(
(advance.docstatus == 1)
& (
(advance.claimed_amount & advance.return_amount)
& (advance.paid_amount == (advance.return_amount + advance.claimed_amount))
)
& (advance.status == "Paid")
)
).run()

View File

@@ -1,25 +0,0 @@
import frappe
def execute():
"""
Update Expense Claim status to Paid if:
- the entire required amount is already covered via linked advances
- the claim is partially paid via advances and the rest is reimbursed
"""
ExpenseClaim = frappe.qb.DocType("Expense Claim")
(
frappe.qb.update(ExpenseClaim)
.set(ExpenseClaim.status, "Paid")
.where(
(
(ExpenseClaim.grand_total == 0)
| (ExpenseClaim.grand_total == ExpenseClaim.total_amount_reimbursed)
)
& (ExpenseClaim.approval_status == "Approved")
& (ExpenseClaim.docstatus == 1)
& (ExpenseClaim.total_sanctioned_amount > 0)
)
).run()

View File

@@ -6,7 +6,7 @@ import frappe
def execute():
frappe.reload_doc("hr", "doctype", "employee")
frappe.reload_doc("setup", "doctype", "employee")
if frappe.db.has_column("Employee", "reason_for_resignation"):
frappe.db.sql(

View File

@@ -1,15 +0,0 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
def execute():
frappe.reload_doc("hr", "doctype", "shift_assignment")
if frappe.db.has_column("Shift Assignment", "date"):
frappe.db.sql(
"""update `tabShift Assignment`
set end_date=date, start_date=date
where date IS NOT NULL and start_date IS NULL and end_date IS NULL;"""
)

View File

@@ -1,133 +0,0 @@
# Copyright (c) 2019, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
from frappe import _
from frappe.model.utils.rename_field import rename_field
def execute():
frappe.reload_doc("Accounts", "doctype", "Salary Component Account")
if frappe.db.has_column("Salary Component Account", "default_account"):
rename_field("Salary Component Account", "default_account", "account")
doctype_list = [
{"module": "HR", "doctype": "Employee Advance"},
{"module": "HR", "doctype": "Leave Encashment"},
{"module": "Payroll", "doctype": "Additional Salary"},
{"module": "Payroll", "doctype": "Employee Benefit Application"},
{"module": "Payroll", "doctype": "Employee Benefit Claim"},
{"module": "Payroll", "doctype": "Employee Incentive"},
{"module": "Payroll", "doctype": "Employee Tax Exemption Declaration"},
{"module": "Payroll", "doctype": "Employee Tax Exemption Proof Submission"},
{"module": "Payroll", "doctype": "Income Tax Slab"},
{"module": "Payroll", "doctype": "Payroll Entry"},
{"module": "Payroll", "doctype": "Retention Bonus"},
{"module": "Payroll", "doctype": "Salary Structure"},
{"module": "Payroll", "doctype": "Salary Structure Assignment"},
{"module": "Payroll", "doctype": "Salary Slip"},
]
for item in doctype_list:
frappe.reload_doc(item["module"], "doctype", item["doctype"])
# update company in employee advance based on employee company
for dt in [
"Employee Incentive",
"Leave Encashment",
"Employee Benefit Application",
"Employee Benefit Claim",
]:
frappe.db.sql(
"""
update `tab{doctype}`
set company = (select company from tabEmployee where name=`tab{doctype}`.employee)
""".format(
doctype=dt
)
)
# update exchange rate for employee advance
frappe.db.sql("update `tabEmployee Advance` set exchange_rate=1")
# get all companies and it's currency
all_companies = frappe.db.get_all(
"Company", fields=["name", "default_currency", "default_payroll_payable_account"]
)
for d in all_companies:
company = d.name
company_currency = d.default_currency
default_payroll_payable_account = d.default_payroll_payable_account
if not default_payroll_payable_account:
default_payroll_payable_account = frappe.db.get_value(
"Account",
{
"account_name": _("Payroll Payable"),
"company": company,
"account_currency": company_currency,
"is_group": 0,
},
)
# update currency in following doctypes based on company currency
doctypes_for_currency = [
"Employee Advance",
"Leave Encashment",
"Employee Benefit Application",
"Employee Benefit Claim",
"Employee Incentive",
"Additional Salary",
"Employee Tax Exemption Declaration",
"Employee Tax Exemption Proof Submission",
"Income Tax Slab",
"Retention Bonus",
"Salary Structure",
]
for dt in doctypes_for_currency:
frappe.db.sql(
"""update `tab{doctype}` set currency = %s where company=%s""".format(doctype=dt),
(company_currency, company),
)
# update fields in payroll entry
frappe.db.sql(
"""
update `tabPayroll Entry`
set currency = %s,
exchange_rate = 1,
payroll_payable_account=%s
where company=%s
""",
(company_currency, default_payroll_payable_account, company),
)
# update fields in Salary Structure Assignment
frappe.db.sql(
"""
update `tabSalary Structure Assignment`
set currency = %s,
payroll_payable_account=%s
where company=%s
""",
(company_currency, default_payroll_payable_account, company),
)
# update fields in Salary Slip
frappe.db.sql(
"""
update `tabSalary Slip`
set currency = %s,
exchange_rate = 1,
base_hour_rate = hour_rate,
base_gross_pay = gross_pay,
base_total_deduction = total_deduction,
base_net_pay = net_pay,
base_rounded_total = rounded_total,
base_total_in_words = total_in_words
where company=%s
""",
(company_currency, company),
)

View File

@@ -1,29 +0,0 @@
import os
import frappe
from frappe import _
def execute():
template = frappe.db.exists("Email Template", _("Exit Questionnaire Notification"))
if not template:
base_path = frappe.get_app_path("erpnext", "hr", "doctype")
response = frappe.read_file(
os.path.join(base_path, "exit_interview/exit_questionnaire_notification_template.html")
)
template = frappe.get_doc(
{
"doctype": "Email Template",
"name": _("Exit Questionnaire Notification"),
"response": response,
"subject": _("Exit Questionnaire Notification"),
"owner": frappe.session.user,
}
).insert(ignore_permissions=True)
template = template.name
hr_settings = frappe.get_doc("HR Settings")
hr_settings.exit_questionnaire_notification_template = template
hr_settings.flags.ignore_links = True
hr_settings.save()

View File

@@ -1,5 +0,0 @@
import frappe
def execute():
frappe.delete_doc("DocType", "Employee Transfer Property", ignore_missing=True)

View File

@@ -1,29 +0,0 @@
import frappe
def execute():
frappe.reload_doc("payroll", "doctype", "employee_cost_center")
frappe.reload_doc("payroll", "doctype", "salary_structure_assignment")
employees = frappe.get_all("Employee", fields=["department", "payroll_cost_center", "name"])
employee_cost_center = {}
for d in employees:
cost_center = d.payroll_cost_center
if not cost_center and d.department:
cost_center = frappe.get_cached_value("Department", d.department, "payroll_cost_center")
if cost_center:
employee_cost_center.setdefault(d.name, cost_center)
salary_structure_assignments = frappe.get_all(
"Salary Structure Assignment", filters={"docstatus": ["!=", 2]}, fields=["name", "employee"]
)
for d in salary_structure_assignments:
cost_center = employee_cost_center.get(d.employee)
if cost_center:
assignment = frappe.get_doc("Salary Structure Assignment", d.name)
if not assignment.get("payroll_cost_centers"):
assignment.append("payroll_cost_centers", {"cost_center": cost_center, "percentage": 100})
assignment.save()

View File

@@ -1,19 +0,0 @@
import os
import frappe
from frappe import _
def execute():
base_path = frappe.get_app_path("erpnext", "hr", "doctype")
response = frappe.read_file(
os.path.join(base_path, "leave_application/leave_application_email_template.html")
)
template = frappe.db.exists("Email Template", _("Leave Approval Notification"))
if template:
frappe.db.set_value("Email Template", template, "response", response)
template = frappe.db.exists("Email Template", _("Leave Status Notification"))
if template:
frappe.db.set_value("Email Template", template, "response", response)

View File

@@ -8,12 +8,6 @@ def execute():
if not company:
return
frappe.reload_doc("Payroll", "doctype", "payroll_period")
frappe.reload_doc("Payroll", "doctype", "employee_tax_exemption_declaration")
frappe.reload_doc("Payroll", "doctype", "employee_tax_exemption_proof_submission")
frappe.reload_doc("Payroll", "doctype", "employee_tax_exemption_declaration_category")
frappe.reload_doc("Payroll", "doctype", "employee_tax_exemption_proof_submission_detail")
frappe.reload_doc("accounts", "doctype", "tax_category")
for doctype in ["Sales Invoice", "Delivery Note", "Purchase Invoice"]: