Merge branch 'develop' into coa-importer-validate-fix

This commit is contained in:
Saqib 2021-04-08 11:25:29 +05:30 committed by GitHub
commit f10d107a0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 216 additions and 137 deletions

View File

@ -21,6 +21,7 @@ class LoanRepayment(AccountsController):
def validate(self): def validate(self):
amounts = calculate_amounts(self.against_loan, self.posting_date) amounts = calculate_amounts(self.against_loan, self.posting_date)
self.set_missing_values(amounts) self.set_missing_values(amounts)
self.check_future_entries()
self.validate_amount() self.validate_amount()
self.allocate_amounts(amounts) self.allocate_amounts(amounts)
@ -69,6 +70,13 @@ class LoanRepayment(AccountsController):
if amounts.get('due_date'): if amounts.get('due_date'):
self.due_date = amounts.get('due_date') self.due_date = amounts.get('due_date')
def check_future_entries(self):
future_repayment_date = frappe.db.get_value("Loan Repayment", {"posting_date": (">", self.posting_date),
"docstatus": 1, "against_loan": self.against_loan}, 'posting_date')
if future_repayment_date:
frappe.throw("Repayment already made till date {0}".format(getdate(future_repayment_date)))
def validate_amount(self): def validate_amount(self):
precision = cint(frappe.db.get_default("currency_precision")) or 2 precision = cint(frappe.db.get_default("currency_precision")) or 2
@ -307,7 +315,9 @@ def create_repayment_entry(loan, applicant, company, posting_date, loan_type,
return lr return lr
def get_accrued_interest_entries(against_loan): def get_accrued_interest_entries(against_loan, posting_date=None):
if not posting_date:
posting_date = getdate()
unpaid_accrued_entries = frappe.db.sql( unpaid_accrued_entries = frappe.db.sql(
""" """
@ -318,12 +328,13 @@ def get_accrued_interest_entries(against_loan):
`tabLoan Interest Accrual` `tabLoan Interest Accrual`
WHERE WHERE
loan = %s loan = %s
AND posting_date <= %s
AND (interest_amount - paid_interest_amount > 0 OR AND (interest_amount - paid_interest_amount > 0 OR
payable_principal_amount - paid_principal_amount > 0) payable_principal_amount - paid_principal_amount > 0)
AND AND
docstatus = 1 docstatus = 1
ORDER BY posting_date ORDER BY posting_date
""", (against_loan), as_dict=1) """, (against_loan, posting_date), as_dict=1)
return unpaid_accrued_entries return unpaid_accrued_entries
@ -335,7 +346,7 @@ def get_amounts(amounts, against_loan, posting_date):
against_loan_doc = frappe.get_doc("Loan", against_loan) against_loan_doc = frappe.get_doc("Loan", against_loan)
loan_type_details = frappe.get_doc("Loan Type", against_loan_doc.loan_type) loan_type_details = frappe.get_doc("Loan Type", against_loan_doc.loan_type)
accrued_interest_entries = get_accrued_interest_entries(against_loan_doc.name) accrued_interest_entries = get_accrued_interest_entries(against_loan_doc.name, posting_date)
pending_accrual_entries = {} pending_accrual_entries = {}

View File

@ -70,7 +70,9 @@
{ {
"fieldname": "loan_repayment_entry", "fieldname": "loan_repayment_entry",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 1,
"label": "Loan Repayment Entry", "label": "Loan Repayment Entry",
"no_copy": 1,
"options": "Loan Repayment", "options": "Loan Repayment",
"read_only": 1 "read_only": 1
}, },
@ -83,9 +85,10 @@
"read_only": 1 "read_only": 1
} }
], ],
"index_web_pages_for_search": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2020-04-16 13:17:04.798335", "modified": "2021-03-14 20:47:11.725818",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Loan Management", "module": "Loan Management",
"name": "Salary Slip Loan", "name": "Salary Slip Loan",

View File

@ -133,45 +133,59 @@ frappe.ui.form.on('Payroll Entry', {
} }
}; };
}); });
frm.set_query('employee', 'employees', () => {
if (!frm.doc.company) {
frappe.msgprint(__("Please set a Company"));
return [];
}
return {
query: "erpnext.payroll.doctype.payroll_entry.payroll_entry.employee_query",
filters: frm.events.get_employee_filters(frm)
};
});
},
get_employee_filters: function (frm) {
let filters = {};
filters['company'] = frm.doc.company;
filters['start_date'] = frm.doc.start_date;
filters['end_date'] = frm.doc.end_date;
if (frm.doc.department) {
filters['department'] = frm.doc.department;
}
if (frm.doc.branch) {
filters['branch'] = frm.doc.branch;
}
if (frm.doc.designation) {
filters['designation'] = frm.doc.designation;
}
if (frm.doc.employees) {
filters['employees'] = frm.doc.employees.filter(d => d.employee).map(d => d.employee);
}
return filters;
}, },
payroll_frequency: function (frm) { payroll_frequency: function (frm) {
frm.trigger("set_start_end_dates").then( ()=> { frm.trigger("set_start_end_dates").then( ()=> {
frm.events.clear_employee_table(frm); frm.events.clear_employee_table(frm);
frm.events.get_employee_with_salary_slip_and_set_query(frm);
});
},
employee_filters: function (frm, emp_list) {
frm.set_query('employee', 'employees', () => {
return {
filters: {
name: ["not in", emp_list]
}
};
});
},
get_employee_with_salary_slip_and_set_query: function (frm) {
frappe.db.get_list('Salary Slip', {
filters: {
start_date: frm.doc.start_date,
end_date: frm.doc.end_date,
docstatus: 1,
},
fields: ['employee']
}).then((emp) => {
var emp_list = [];
emp.forEach((employee_data) => {
emp_list.push(Object.values(employee_data)[0]);
});
frm.events.employee_filters(frm, emp_list);
}); });
}, },
company: function (frm) { company: function (frm) {
frm.events.clear_employee_table(frm); frm.events.clear_employee_table(frm);
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype); erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
frm.trigger("set_payable_account_and_currency");
},
set_payable_account_and_currency: function (frm) {
frappe.db.get_value("Company", {"name": frm.doc.company}, "default_currency", (r) => {
frm.set_value('currency', r.default_currency);
});
frappe.db.get_value("Company", {"name": frm.doc.company}, "default_payroll_payable_account", (r) => {
frm.set_value('payroll_payable_account', r.default_payroll_payable_account);
});
}, },
currency: function (frm) { currency: function (frm) {
@ -345,11 +359,3 @@ let render_employee_attendance = function (frm, data) {
}) })
); );
}; };
frappe.ui.form.on('Payroll Employee Detail', {
employee: function(frm) {
if (!frm.doc.payroll_frequency) {
frappe.throw(__("Please set a Payroll Frequency"));
}
}
});

View File

@ -10,16 +10,17 @@ from frappe.utils import cint, flt, add_days, getdate, add_to_date, DATE_FORMAT,
from frappe import _ from frappe import _
from erpnext.accounts.utils import get_fiscal_year from erpnext.accounts.utils import get_fiscal_year
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
from frappe.desk.reportview import get_match_cond, get_filters_cond
class PayrollEntry(Document): class PayrollEntry(Document):
def onload(self): def onload(self):
if not self.docstatus==1 or self.salary_slips_submitted: if not self.docstatus==1 or self.salary_slips_submitted:
return return
# check if salary slips were manually submitted # check if salary slips were manually submitted
entries = frappe.db.count("Salary Slip", {'payroll_entry': self.name, 'docstatus': 1}, ['name']) entries = frappe.db.count("Salary Slip", {'payroll_entry': self.name, 'docstatus': 1}, ['name'])
if cint(entries) == len(self.employees): if cint(entries) == len(self.employees):
self.set_onload("submitted_ss", True) self.set_onload("submitted_ss", True)
def validate(self): def validate(self):
self.number_of_employees = len(self.employees) self.number_of_employees = len(self.employees)
@ -59,16 +60,16 @@ class PayrollEntry(Document):
condition = """and payroll_frequency = '%(payroll_frequency)s'"""% {"payroll_frequency": self.payroll_frequency} condition = """and payroll_frequency = '%(payroll_frequency)s'"""% {"payroll_frequency": self.payroll_frequency}
sal_struct = frappe.db.sql_list(""" sal_struct = frappe.db.sql_list("""
select select
name from `tabSalary Structure` name from `tabSalary Structure`
where where
docstatus = 1 and docstatus = 1 and
is_active = 'Yes' is_active = 'Yes'
and company = %(company)s and company = %(company)s
and currency = %(currency)s and and currency = %(currency)s and
ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s
{condition}""".format(condition=condition), {condition}""".format(condition=condition),
{"company": self.company, "currency": self.currency, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet}) {"company": self.company, "currency": self.currency, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet})
if sal_struct: if sal_struct:
cond += "and t2.salary_structure IN %(sal_struct)s " cond += "and t2.salary_structure IN %(sal_struct)s "
@ -176,15 +177,15 @@ class PayrollEntry(Document):
""" """
Returns list of salary slips based on selected criteria Returns list of salary slips based on selected criteria
""" """
cond = self.get_filter_condition()
ss_list = frappe.db.sql(""" ss_list = frappe.db.sql("""
select t1.name, t1.salary_structure, t1.payroll_cost_center from `tabSalary Slip` t1 select t1.name, t1.salary_structure, t1.payroll_cost_center from `tabSalary Slip` t1
where t1.docstatus = %s and t1.start_date >= %s and t1.end_date <= %s where t1.docstatus = %s and t1.start_date >= %s and t1.end_date <= %s and t1.payroll_entry = %s
and (t1.journal_entry is null or t1.journal_entry = "") and ifnull(salary_slip_based_on_timesheet,0) = %s %s and (t1.journal_entry is null or t1.journal_entry = "") and ifnull(salary_slip_based_on_timesheet,0) = %s
""" % ('%s', '%s', '%s','%s', cond), (ss_status, self.start_date, self.end_date, self.salary_slip_based_on_timesheet), as_dict=as_dict) """, (ss_status, self.start_date, self.end_date, self.name, self.salary_slip_based_on_timesheet), as_dict=as_dict)
return ss_list return ss_list
@frappe.whitelist()
def submit_salary_slips(self): def submit_salary_slips(self):
self.check_permission('write') self.check_permission('write')
ss_list = self.get_sal_slip_list(ss_status=0) ss_list = self.get_sal_slip_list(ss_status=0)
@ -270,26 +271,26 @@ class PayrollEntry(Document):
exchange_rate, amt = self.get_amount_and_exchange_rate_for_journal_entry(acc_cc[0], amount, company_currency, currencies) exchange_rate, amt = self.get_amount_and_exchange_rate_for_journal_entry(acc_cc[0], amount, company_currency, currencies)
payable_amount += flt(amount, precision) payable_amount += flt(amount, precision)
accounts.append({ accounts.append({
"account": acc_cc[0], "account": acc_cc[0],
"debit_in_account_currency": flt(amt, precision), "debit_in_account_currency": flt(amt, precision),
"exchange_rate": flt(exchange_rate), "exchange_rate": flt(exchange_rate),
"party_type": '', "party_type": '',
"cost_center": acc_cc[1] or self.cost_center, "cost_center": acc_cc[1] or self.cost_center,
"project": self.project "project": self.project
}) })
# Deductions # Deductions
for acc_cc, amount in deductions.items(): for acc_cc, amount in deductions.items():
exchange_rate, amt = self.get_amount_and_exchange_rate_for_journal_entry(acc_cc[0], amount, company_currency, currencies) exchange_rate, amt = self.get_amount_and_exchange_rate_for_journal_entry(acc_cc[0], amount, company_currency, currencies)
payable_amount -= flt(amount, precision) payable_amount -= flt(amount, precision)
accounts.append({ accounts.append({
"account": acc_cc[0], "account": acc_cc[0],
"credit_in_account_currency": flt(amt, precision), "credit_in_account_currency": flt(amt, precision),
"exchange_rate": flt(exchange_rate), "exchange_rate": flt(exchange_rate),
"cost_center": acc_cc[1] or self.cost_center, "cost_center": acc_cc[1] or self.cost_center,
"party_type": '', "party_type": '',
"project": self.project "project": self.project
}) })
# Payable amount # Payable amount
exchange_rate, payable_amt = self.get_amount_and_exchange_rate_for_journal_entry(payroll_payable_account, payable_amount, company_currency, currencies) exchange_rate, payable_amt = self.get_amount_and_exchange_rate_for_journal_entry(payroll_payable_account, payable_amount, company_currency, currencies)
@ -335,10 +336,9 @@ class PayrollEntry(Document):
def make_payment_entry(self): def make_payment_entry(self):
self.check_permission('write') self.check_permission('write')
cond = self.get_filter_condition()
salary_slip_name_list = frappe.db.sql(""" select t1.name from `tabSalary Slip` t1 salary_slip_name_list = frappe.db.sql(""" select t1.name from `tabSalary Slip` t1
where t1.docstatus = 1 and start_date >= %s and end_date <= %s %s where t1.docstatus = 1 and start_date >= %s and end_date <= %s and t1.payroll_entry = %s
""" % ('%s', '%s', cond), (self.start_date, self.end_date), as_list = True) """, (self.start_date, self.end_date, self.name), as_list = True)
if salary_slip_name_list and len(salary_slip_name_list) > 0: if salary_slip_name_list and len(salary_slip_name_list) > 0:
salary_slip_total = 0 salary_slip_total = 0
@ -370,20 +370,20 @@ class PayrollEntry(Document):
exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry(self.payment_account, je_payment_amount, company_currency, currencies) exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry(self.payment_account, je_payment_amount, company_currency, currencies)
accounts.append({ accounts.append({
"account": self.payment_account, "account": self.payment_account,
"bank_account": self.bank_account, "bank_account": self.bank_account,
"credit_in_account_currency": flt(amount, precision), "credit_in_account_currency": flt(amount, precision),
"exchange_rate": flt(exchange_rate), "exchange_rate": flt(exchange_rate),
}) })
exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry(payroll_payable_account, je_payment_amount, company_currency, currencies) exchange_rate, amount = self.get_amount_and_exchange_rate_for_journal_entry(payroll_payable_account, je_payment_amount, company_currency, currencies)
accounts.append({ accounts.append({
"account": payroll_payable_account, "account": payroll_payable_account,
"debit_in_account_currency": flt(amount, precision), "debit_in_account_currency": flt(amount, precision),
"exchange_rate": flt(exchange_rate), "exchange_rate": flt(exchange_rate),
"reference_type": self.doctype, "reference_type": self.doctype,
"reference_name": self.name "reference_name": self.name
}) })
if len(currencies) > 1: if len(currencies) > 1:
multi_currency = 1 multi_currency = 1
@ -409,6 +409,7 @@ class PayrollEntry(Document):
self.update(get_start_end_dates(self.payroll_frequency, self.update(get_start_end_dates(self.payroll_frequency,
self.start_date or self.posting_date, self.company)) self.start_date or self.posting_date, self.company))
@frappe.whitelist()
def validate_employee_attendance(self): def validate_employee_attendance(self):
employees_to_mark_attendance = [] employees_to_mark_attendance = []
days_in_payroll, days_holiday, days_attendance_marked = 0, 0, 0 days_in_payroll, days_holiday, days_attendance_marked = 0, 0, 0
@ -424,7 +425,7 @@ class PayrollEntry(Document):
employees_to_mark_attendance.append({ employees_to_mark_attendance.append({
"employee": employee_detail.employee, "employee": employee_detail.employee,
"employee_name": employee_detail.employee_name "employee_name": employee_detail.employee_name
}) })
return employees_to_mark_attendance return employees_to_mark_attendance
def get_count_holidays_of_employee(self, employee, start_date): def get_count_holidays_of_employee(self, employee, start_date):
@ -441,11 +442,11 @@ class PayrollEntry(Document):
def get_count_employee_attendance(self, employee, start_date): def get_count_employee_attendance(self, employee, start_date):
marked_days = 0 marked_days = 0
attendances = frappe.get_all("Attendance", attendances = frappe.get_all("Attendance",
fields = ["count(*)"], fields = ["count(*)"],
filters = { filters = {
"employee": employee, "employee": employee,
"attendance_date": ('between', [start_date, self.end_date]) "attendance_date": ('between', [start_date, self.end_date])
}, as_list=1) }, as_list=1)
if attendances and attendances[0][0]: if attendances and attendances[0][0]:
marked_days = attendances[0][0] marked_days = attendances[0][0]
return marked_days return marked_days
@ -553,6 +554,7 @@ def payroll_entry_has_bank_entries(name):
def create_salary_slips_for_employees(employees, args, publish_progress=True): def create_salary_slips_for_employees(employees, args, publish_progress=True):
salary_slips_exists_for = get_existing_salary_slips(employees, args) salary_slips_exists_for = get_existing_salary_slips(employees, args)
count=0 count=0
salary_slips_not_created = []
for emp in employees: for emp in employees:
if emp not in salary_slips_exists_for: if emp not in salary_slips_exists_for:
args.update({ args.update({
@ -566,33 +568,24 @@ def create_salary_slips_for_employees(employees, args, publish_progress=True):
frappe.publish_progress(count*100/len(set(employees) - set(salary_slips_exists_for)), frappe.publish_progress(count*100/len(set(employees) - set(salary_slips_exists_for)),
title = _("Creating Salary Slips...")) title = _("Creating Salary Slips..."))
else: else:
salary_slip_name = frappe.db.sql( salary_slips_not_created.append(emp)
'''SELECT
name
FROM `tabSalary Slip`
WHERE company=%s
AND start_date >= %s
AND end_date <= %s
AND employee = %s
''', (args.company, args.start_date, args.end_date, emp), as_dict=True)
salary_slip_doc = frappe.get_doc('Salary Slip', salary_slip_name[0].name)
salary_slip_doc.exchange_rate = args.exchange_rate
salary_slip_doc.set_totals()
salary_slip_doc.db_update()
payroll_entry = frappe.get_doc("Payroll Entry", args.payroll_entry) payroll_entry = frappe.get_doc("Payroll Entry", args.payroll_entry)
payroll_entry.db_set("salary_slips_created", 1) payroll_entry.db_set("salary_slips_created", 1)
payroll_entry.notify_update() payroll_entry.notify_update()
if salary_slips_not_created:
frappe.msgprint(_("Salary Slips already exists for employees {}, and will not be processed by this payroll.")
.format(frappe.bold(", ".join([emp for emp in salary_slips_not_created]))) , title=_("Message"), indicator="orange")
def get_existing_salary_slips(employees, args): def get_existing_salary_slips(employees, args):
return frappe.db.sql_list(""" return frappe.db.sql_list("""
select distinct employee from `tabSalary Slip` select distinct employee from `tabSalary Slip`
where docstatus!= 2 and company = %s where docstatus!= 2 and company = %s and payroll_entry = %s
and start_date >= %s and end_date <= %s and start_date >= %s and end_date <= %s
and employee in (%s) and employee in (%s)
""" % ('%s', '%s', '%s', ', '.join(['%s']*len(employees))), """ % ('%s', '%s', '%s', '%s', ', '.join(['%s']*len(employees))),
[args.company, args.start_date, args.end_date] + employees) [args.company, args.payroll_entry, args.start_date, args.end_date] + employees)
def submit_salary_slips_for_employees(payroll_entry, salary_slips, publish_progress=True): def submit_salary_slips_for_employees(payroll_entry, salary_slips, publish_progress=True):
submitted_ss = [] submitted_ss = []
@ -644,3 +637,61 @@ def get_payroll_entries_for_jv(doctype, txt, searchfield, start, page_len, filte
'txt': "%%%s%%" % frappe.db.escape(txt), 'txt': "%%%s%%" % frappe.db.escape(txt),
'start': start, 'page_len': page_len 'start': start, 'page_len': page_len
}) })
def get_employee_with_existing_salary_slip(start_date, end_date, company):
return frappe.db.sql_list("""
select employee from `tabSalary Slip`
where
(start_date between %(start_date)s and %(end_date)s
or
end_date between %(start_date)s and %(end_date)s
or
%(start_date)s between start_date and end_date)
and company = %(company)s
and docstatus = 1
""", {'start_date': start_date, 'end_date': end_date, 'company': company})
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def employee_query(doctype, txt, searchfield, start, page_len, filters):
filters = frappe._dict(filters)
conditions = []
exclude_employees = []
emp_cond = ''
if filters.start_date and filters.end_date:
employee_list = get_employee_with_existing_salary_slip(filters.start_date, filters.end_date, filters.company)
emp = filters.get('employees')
filters.pop('start_date')
filters.pop('end_date')
if filters.employees is not None:
filters.pop('employees')
if employee_list:
exclude_employees.extend(employee_list)
if emp:
exclude_employees.extend(emp)
if exclude_employees:
emp_cond += 'and employee not in %(exclude_employees)s'
return frappe.db.sql("""select name, employee_name from `tabEmployee`
where status = 'Active'
and docstatus < 2
and ({key} like %(txt)s
or employee_name like %(txt)s)
{emp_cond}
{fcond} {mcond}
order by
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
if(locate(%(_txt)s, employee_name), locate(%(_txt)s, employee_name), 99999),
idx desc,
name, employee_name
limit %(start)s, %(page_len)s""".format(**{
'key': searchfield,
'fcond': get_filters_cond(doctype, filters, conditions),
'mcond': get_match_cond(doctype),
'emp_cond': emp_cond
}), {
'txt': "%%%s%%" % txt,
'_txt': txt.replace("%", ""),
'start': start,
'page_len': page_len,
'exclude_employees': exclude_employees})

View File

@ -51,7 +51,7 @@ class TestPayrollEntry(unittest.TestCase):
company_doc = frappe.get_doc('Company', company) company_doc = frappe.get_doc('Company', company)
salary_structure = make_salary_structure("_Test Multi Currency Salary Structure", "Monthly", company=company, currency='USD') salary_structure = make_salary_structure("_Test Multi Currency Salary Structure", "Monthly", company=company, currency='USD')
create_salary_structure_assignment(employee, salary_structure.name, company=company) create_salary_structure_assignment(employee, salary_structure.name, company=company, currency='USD')
frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""",(frappe.db.get_value("Employee", {"user_id": "test_muti_currency_employee@payroll.com"}))) frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""",(frappe.db.get_value("Employee", {"user_id": "test_muti_currency_employee@payroll.com"})))
salary_slip = get_salary_slip("test_muti_currency_employee@payroll.com", "Monthly", "_Test Multi Currency Salary Structure") salary_slip = get_salary_slip("test_muti_currency_employee@payroll.com", "Monthly", "_Test Multi Currency Salary Structure")
dates = get_start_end_dates('Monthly', nowdate()) dates = get_start_end_dates('Monthly', nowdate())
@ -62,10 +62,11 @@ class TestPayrollEntry(unittest.TestCase):
salary_slip.load_from_db() salary_slip.load_from_db()
payroll_je = salary_slip.journal_entry payroll_je = salary_slip.journal_entry
payroll_je_doc = frappe.get_doc('Journal Entry', payroll_je) if payroll_je:
payroll_je_doc = frappe.get_doc('Journal Entry', payroll_je)
self.assertEqual(salary_slip.base_gross_pay, payroll_je_doc.total_debit) self.assertEqual(salary_slip.base_gross_pay, payroll_je_doc.total_debit)
self.assertEqual(salary_slip.base_gross_pay, payroll_je_doc.total_credit) self.assertEqual(salary_slip.base_gross_pay, payroll_je_doc.total_credit)
payment_entry = frappe.db.sql(''' payment_entry = frappe.db.sql('''
Select ifnull(sum(je.total_debit),0) as total_debit, ifnull(sum(je.total_credit),0) as total_credit from `tabJournal Entry` je, `tabJournal Entry Account` jea Select ifnull(sum(je.total_debit),0) as total_debit, ifnull(sum(je.total_credit),0) as total_credit from `tabJournal Entry` je, `tabJournal Entry Account` jea

View File

@ -39,7 +39,8 @@ frappe.ui.form.on("Salary Slip", {
frm.set_query("employee", function() { frm.set_query("employee", function() {
return { return {
query: "erpnext.controllers.queries.employee_query" query: "erpnext.controllers.queries.employee_query",
filters: frm.doc.company
}; };
}); });
}, },
@ -93,28 +94,31 @@ frappe.ui.form.on("Salary Slip", {
}, },
set_exchange_rate: function(frm, company_currency) { set_exchange_rate: function(frm, company_currency) {
if (frm.doc.currency) { if (frm.doc.docstatus === 0) {
var from_currency = frm.doc.currency; if (frm.doc.currency) {
if (from_currency != company_currency) { var from_currency = frm.doc.currency;
frm.events.hide_loan_section(frm); if (from_currency != company_currency) {
frappe.call({ frm.events.hide_loan_section(frm);
method: "erpnext.setup.utils.get_exchange_rate", frappe.call({
args: { method: "erpnext.setup.utils.get_exchange_rate",
from_currency: from_currency, args: {
to_currency: company_currency, from_currency: from_currency,
}, to_currency: company_currency,
callback: function(r) { },
frm.set_value("exchange_rate", flt(r.message)); callback: function(r) {
frm.set_df_property("exchange_rate", "hidden", 0); if (r.message) {
frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency frm.set_value("exchange_rate", flt(r.message));
+ " = [?] " + company_currency); frm.set_df_property('exchange_rate', 'hidden', 0);
} frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency
}); + " = [?] " + company_currency);
} else { }
frm.set_value("exchange_rate", 1.0); }
frm.set_df_property("exchange_rate", "hidden", 1); });
frm.set_df_property("exchange_rate", "description", ""); } else {
} frm.set_value("exchange_rate", 1.0);
frm.set_df_property('exchange_rate', 'hidden', 1);
frm.set_df_property("exchange_rate", "description", "" );
}
} }
}, },

View File

@ -124,9 +124,12 @@ class SalarySlip(TransactionBase):
def check_existing(self): def check_existing(self):
if not self.salary_slip_based_on_timesheet: if not self.salary_slip_based_on_timesheet:
cond = ""
if self.payroll_entry:
cond += "and payroll_entry = '{0}'".format(self.payroll_entry)
ret_exist = frappe.db.sql("""select name from `tabSalary Slip` ret_exist = frappe.db.sql("""select name from `tabSalary Slip`
where start_date = %s and end_date = %s and docstatus != 2 where start_date = %s and end_date = %s and docstatus != 2
and employee = %s and name != %s""", and employee = %s and name != %s {0}""".format(cond),
(self.start_date, self.end_date, self.employee, self.name)) (self.start_date, self.end_date, self.employee, self.name))
if ret_exist: if ret_exist:
self.employee = '' self.employee = ''
@ -1053,7 +1056,7 @@ class SalarySlip(TransactionBase):
repayment_entry.save() repayment_entry.save()
repayment_entry.submit() repayment_entry.submit()
loan.loan_repayment_entry = repayment_entry.name frappe.db.set_value("Salary Slip Loan", loan.name, "loan_repayment_entry", repayment_entry.name)
def cancel_loan_repayment_entry(self): def cancel_loan_repayment_entry(self):
for loan in self.loans: for loan in self.loans: