AttributeError: 'Document' object has no attribute 'make_payment_entry'

Error : AttributeError: ‘Document’ object has no attribute ‘make_payment_entry’

My Code :

cur_frm.cscript.make_bank_entry = function (doc, cdt, cdn) {
if (doc.company && doc.start_date && doc.end_date) {
return frappe.call({
doc: cur_frm.doc,
method: “make_payment_entry”,
callback: function (r) {
if (r.message)
var doc = frappe.model.sync(r.message)[0];
frappe.set_route(“Form”, doc.doctype, doc.name);
}
});

} else {
    frappe.msgprint(__("Company, From Date and To Date is mandatory"));
}

}

You need to give exact location of the method there.
I did like this:

method:"newapp.newapp.payment_entry.set_branch",

set_branch is the function present in payment_entry.py file

Hi @Tushar

Is that class method or whitelist?
If class method then reorder doc and method position, keep doc below the method

cur_frm.cscript.make_bank_entry = function (doc, cdt, cdn) {
if (doc.company && doc.start_date && doc.end_date) {
return frappe.call({
method: "make_payment_entry",
doc: cur_frm.doc,
callback: function (r) {
if (r.message)
var doc = frappe.model.sync(r.message)[0];
frappe.set_route("Form", doc.doctype, doc.name);
}
});

} else {
    frappe.msgprint(__("Company, From Date and To Date is mandatory"));
}
}

Hi @rohit_w
‘make_payment_entry’ is a class method.
I already reordered but not working… getting same error.

also added exact location
method: “erpnext.hr.doctype.employee_payout_process.employee_payout_process.make_payment_entry”,

still not working

Hi @Tushar

Can you share the both JS ad Py files

employee_payout_process.js
=====================

frappe.ui.form.on('Employee Payout Process', {
	onload: function (frm) {
		frm.doc.bank_name = '';
		frm.doc.start_date = '';
		frm.doc.end_date = '';
	},
	refresh: function(frm) {
		frm.doc.bank_name = '';
		frm.doc.start_date = '';
		frm.doc.end_date = '';
		frm.disable_save();
	},
	setup: function(frm) {

	},
	payment_account: function (frm) {
		frm.toggle_display(['make_bank_entry'], (frm.doc.payment_account != "" && frm.doc.payment_account != "undefined" && frm.doc.empdata != ""));
	},
	start_date: function(frm) {
		frm.set_value("bank_name",'');
	},
	end_date: function(frm) {
		frm.set_value("bank_name",'');
	},
	bank_name: function(frm) {
		frm.set_value("payment_account",'');
		frm.events.get_salary_slip_data(frm);
	},
	get_salary_slip_data: function(frm) {
		if(frm.doc.start_date != null && frm.doc.start_date != null && frm.doc.start_date < frm.doc.end_date){
			frappe.call({
				method: "erpnext.hr.doctype.employee_payout_process.employee_payout_process.salary_slip_data",
				args: {
					"bank_name": frm.doc.bank_name,
					"start_date": frm.doc.start_date,
					"end_date": frm.doc.end_date
				},
				callback: function(r,rt)
				{
					frappe.model.clear_table(frm.doc, "empdata");
					if(r.message) {
							$.each(r.message, function(i, d) {
							var row = frappe.model.add_child(frm.doc, "Salary Slip Data", "empdata");
		            row.employee = d.employee;
								row.ifsc_code = d.ifsc_code;
								row.bank_ac_no = d.bank_ac_no;
								row.bank_name = d.bank_name;
								row.net_pay = d.net_pay;
						});
						frm.refresh_field("empdata");
					}else {
						empdata_flag = false
						frappe.msgprint("No data found");
					}
					frm.refresh_field("empdata");
				}
			});
		}else{
			frappe.msgprint("Select valid Start date and End date");
		}
	}
});
cur_frm.cscript.make_bank_entry = function (doc, cdt, cdn) {
	if (doc.company && doc.start_date && doc.end_date) {
		return frappe.call({
			method: 'make_bank_payment_entry',
			doc: cur_frm.doc,
			callback: function (r) {
				if (r.message)
					var doc = frappe.model.sync(r.message)[0];
					frappe.set_route("Form", doc.doctype, doc.name);
				}
			});

		} else {
		    frappe.msgprint(__("Company, From Date and To Date is mandatory"));
	}
}

-------------------------------------------------------------
employee_payout_process.py
=====================

from __future__ import unicode_literals
import frappe
from frappe.utils import getdate
from frappe import _
from erpnext.accounts.utils import get_fiscal_year
from frappe.model.document import Document

class EmployeePayoutProcess(Document):
	def get_sal_slip_list(self, ss_status, as_dict=False):
		"""
			Returns list of salary slips based on selected criteria
		"""
		ss_list = frappe.db.sql("""
			select t1.name, t1.salary_structure from `tabSalary Slip` t1
			where t1.docstatus = %s and t1.start_date >= %s and t1.end_date <= %s
			and (t1.journal_entry is null or t1.journal_entry = "") %s
		""" % (ss_status, self.start_date, self.end_date), as_dict=as_dict)

		print "@@@@@ salary slip list based on selected criteria ss_list"+ss_list
		return ss_list

	def get_total_salary_and_loan_amounts(self):
		"""
			Get total loan principal, loan interest and salary amount from submitted salary slip based on selected criteria
		"""
		totals = frappe.db.sql("""
			select sum(principal_amount) as total_principal_amount, sum(interest_amount) as total_interest_amount,
			sum(total_loan_repayment) as total_loan_repayment, sum(rounded_total) as rounded_total from `tabSalary Slip` t1
			where t1.docstatus = 1 and start_date >= %s and end_date <= %s %s
			""" % (self.start_date, self.end_date), as_dict=True)
		return totals[0]

	def get_default_payroll_payable_account(self):
		payroll_payable_account = frappe.db.get_value("Company",
			{"company_name": self.company}, "default_payroll_payable_account")

		if not payroll_payable_account:
			frappe.throw(_("Please set Default Payroll Payable Account in Company {0}")
				.format(self.company))

		return payroll_payable_account

	def make_bank_payment_entry(self):
		self.check_permission('write')
		total_salary_amount = self.get_total_salary_and_loan_amounts()
		default_payroll_payable_account = self.get_default_payroll_payable_account()

		if total_salary_amount.rounded_total:
			journal_entry = frappe.new_doc('Journal Entry')
			journal_entry.voucher_type = 'Bank Entry'
			journal_entry.user_remark = _('Payment of salary from {0} to {1}').format(self.start_date,
				self.end_date)
			journal_entry.company = self.company
			journal_entry.posting_date = nowdate()

			account_amt_list = []

			account_amt_list.append({
					"account": self.payment_account,
					"credit_in_account_currency": total_salary_amount.rounded_total
				})
			account_amt_list.append({
					"account": default_payroll_payable_account,
					"debit_in_account_currency": total_salary_amount.rounded_total
				})
			journal_entry.set("accounts", account_amt_list)
		return journal_entry.as_dict()

	def update_salary_slip_status(self, jv_name = None):
		ss_list = self.get_sal_slip_list(ss_status=1)
		for ss in ss_list:
			ss_obj = frappe.get_doc("Salary Slip",ss[0])
			frappe.db.set_value("Salary Slip", ss_obj.name, "status", "Paid")
			frappe.db.set_value("Salary Slip", ss_obj.name, "journal_entry", jv_name)

	def set_start_end_dates(self):
		self.update(get_start_end_dates(self.payroll_frequency,
			self.start_date or self.posting_date, self.company))


@frappe.whitelist()
def salary_slip_data(bank_name,start_date,end_date):
	emp_salary_data = []
	emp_data = frappe.get_all('Employee', fields=['employee','bank_name','bank_ac_no','ifsc_code'],filters={"bank_name": bank_name})
	for emp_details in emp_data:
		salary_data = frappe.get_all('Salary Slip', fields=['net_pay','start_date','end_date'],filters={
			"employee": emp_details.employee,
			"start_date":[">=", getdate(start_date)],
			"end_date":["<=", getdate(end_date)]
			})
		for sal_filter in salary_data:
			aaaaa = {
				"employee" : emp_details.employee,
				"bank_name" : emp_details.bank_name,
				"bank_ac_no" : emp_details.bank_ac_no,
				"ifsc_code" : emp_details.ifsc_code,
				"net_pay" : sal_filter.net_pay
			}
			print "@@@@@ aaaaa[] :::::::"+str(aaaaa)
			emp_salary_data.append(aaaaa)
	return emp_salary_data

I faced similar problems when trying to pass the data as a list. It wasn’t working. I then used dictionary.
You can have a look at this : GitHub - royprotim/customapp

can you try doc:doc and check

tried doc:doc, getting same error…

Traceback (most recent call last):
File “/home/youtility2/newbench/apps/frappe/frappe/app.py”, line 55, in application
response = frappe.handler.handle()
File “/home/youtility2/newbench/apps/frappe/frappe/handler.py”, line 21, in handle
data = execute_cmd(cmd)
File “/home/youtility2/newbench/apps/frappe/frappe/handler.py”, line 52, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File “/home/youtility2/newbench/apps/frappe/frappe/init.py”, line 907, in call
return fn(*args, **newargs)
File “/home/youtility2/newbench/apps/frappe/frappe/handler.py”, line 80, in runserverobj
frappe.desk.form.run_method.runserverobj(method, docs=docs, dt=dt, dn=dn, arg=arg, args=args)
File “/home/youtility2/newbench/apps/frappe/frappe/desk/form/run_method.py”, line 33, in runserverobj
fnargs, varargs, varkw, defaults = inspect.getargspec(getattr(doc, method))
AttributeError: ‘Document’ object has no attribute ‘make_bank_payment_entry’

‘make_bank_payment_entry’- maybe it is not whitelisted.

Anyone managed to solve this issue? I’m facing the same problem when trying to call ‘make_payment_entry’ :frowning:

Failed to get method for command erpnext.accounts.utils.make_payment_entry with module ‘erpnext.accounts.utils’ has no attribute ‘make_payment_entry’