How to extend core code using custom app

Hi,

I want to extend Journal Entry python code using custom app so i can update it in future,
what is the best and short practice?

Anybody??

To start with, what are you aware of - you have found nothing?

I tried by creating new file in custom app, having some function then i called it in hooks.py of custom app

doc_events = {
    "Journal Entry": {
        "validate": "custom_app.custom_app.testing.test",
    }
}

then function is not working while saving journal entry.

def test():
        frappe.throw("There")
def test(self):
      frappe.throw("There")

getting below error:

TypeError: test() takes 1 positional argument but 2 were given

what is the second argument?

It is a string with the hook action, for example: 'validate'. This is not mentioned in the current hooks documentation (it was at one time, which is how I know this) and is not often used when actually writing a document hook. It fits the use case where you might want to trigger the same action on ‘validate’ and ‘update’. A better and more explicit way to do this is to link to that same function with the ‘validate’ and ‘update’ keys instead of ‘*’.

2 Likes
def test(self):
      frappe.throw("There")

Also, the convention for this in Frappe apps is to not use self to refer to the object. It isn’t wrong per se, but you’re writing a function that acts as a class method but is not a class method. Use doc instead of self.

def test(doc, method):
      frappe.throw("There" + method + " : " + doc.name)
2 Likes

Thanks @tmatteson it works,
now most cases i need add custom function in between or top of builtin validate method,
then how can i run custom function before or after specific function.

For example:

Journal Entry validate function runs many functions in it.

def validate(self):
		if not self.is_opening:
			self.is_opening='No'
		self.clearance_date = None

		self.validate_party()
		self.validate_entries_for_advance()
		self.validate_multi_currency()
		self.set_amounts_in_company_currency()
		self.validate_total_debit_and_credit()
		self.validate_against_jv()
		self.validate_reference_doc()
		self.set_against_account()
		self.create_remarks()
		self.set_print_format_fields()
		self.validate_expense_claim()
		self.validate_credit_debit_note()
		self.validate_empty_accounts_table()
		self.set_account_and_party_balance()
		self.validate_inter_company_accounts()
		if not self.title:
			self.title = self.get_title()

What if i want to run my custom function after create_remarks() function.

For what its worth, I know nothing about your specific use case and I think that makes this a better question.

“Between other methods”: if this is a requirement rather than a convenience, that means editing core code. Have a look at all the things that run inside of _validate at the document level.

My recommendation is that you find an alternative to the “when” part of this question. You could potentially solve this with a runtime patch, but that should be the solution of extreme last resort, for several reasons:

  1. Your DRY-ethos or business logic is probably not important enough to break ERPNext’s tested, community-used and documented behavior, especially as it relates to financial documents. This is not just a risk that you might be taking on with providing faulty code, but you are exposing your business/ customer to the potential of audit problems and/or fines, depending on local jurisdiction.
  2. There may be downstream consequences of ‘messing’ with the GL; it’s the second most important table in ERPNext after the Stock Ledger. By that I mean that reports or other functionality that rely on predicable behavior from the GL no longer function correctly.
  3. Considering any of the methods that come after create_remarks, which of those would it be acceptable to override, bypass or break? All of them offer a potential opening for fraud.

Just be careful.

2 Likes

@tmatteson thank you so much for your time. :+1: