Need Help on Document Event Hooks for Standard DocTypes

Finally I learned to create a new app and execute scheduled jobs.

Now I want to trigger a function “on_submit” of erpnext’s existing doctype “Purchase Invoice”. I tried adding Document Events to hooks.py file. But doesn’t seem to work.

I am supposing that inorder to trigger something “on_submit” of “Purchase Invoice”, I will have to add the event to “erpnext/hoops.py” and the function inside “doctype/purchase_invoice”. Am I correct?

If I do so, will it not be as if I am editing the core files?
And while upgrading or migrating will the functionality remain?
How can I include this within the newly created custom app itself?

Hi @Azhar_Umar, Great to see you that you achieved something big.
If you edit in the erpnext/hooks.py or doctype/purchase_invoice... , it means you are editing the core, it is not the correct approach, it will fail update of erpnext and migration.

You can do all those things by adding events in hooks of your custom app.
This is the complete Developer API documentation
Here you can see the Hooks
Here you can find the Controllers(Controller Hooks)

1 Like

Hi @jamsheer Thanks for the appreciation and the helpful links. I have been going through the same documentation for one week now, but somehow I cannot get the event hooks work. I am missing something.

Without being a coder I managed to do some interesting stuff through pandas and python. I even did API integration. But this has eaten up my time :frowning:

I found a similar discussion in another topic. Let me go through it.

There are many repos on github from where you can find reference on how to do things.

You can add your py file anywhere in your app, just have to provide the correct path.

1 Like

This is my code in hooks.py my app

doc_events = {"Sales Order": {"validate":"razorpayx.tasks.test"}}

Directory of this file: /home/frappe/frappe-bench/apps/razorpayx/razorpayx/hooks.py

This is my code in tasks.py

import frappe
import time
import json

import requests
from requests.auth import HTTPBasicAuth
from requests.exceptions import HTTPError

def test(doc, method=None):
    frappe.throw(_("Hello World"))
    print("Hellow Wrold")

Directory of tasks.py : /home/frappe/frappe-bench/apps/razorpayx/razorpayx/tasks.py

I ran the following commands after updating the code, just to make sure:
bench migrate
bench restart
bench start

Nothing gets triggered when I save or submit Sales Order. What am I doing wrong?

Is this because I am trying to modify or trigger a standard doctype? In that case, I event tried the steps in https://frappeframework.com/docs/v13/user/en/python-api/hooks#override-doctype-class

But triggered nothing.

Not able to find any issue in the code!!

1 Like

Thanks for validating brother. @jamsheer

I rebooted the entire server and now I guess the event is getting triggered. But this error occurs:

"exception": "NameError: name '_' is not defined"

Detailed error report:

### App Versions

{
	"erpnext": "13.41.1",
	"frappe": "13.43.2",
	"indiamart_integration": "0.0.1",
	"inventory_management": "0.0.1",
	"razorpayx": "0.0.1",
	"woocommerceconnector": "1.7.0",
	"zarnik": "0.0.1"
}

### Route

Form/Sales Order/new-sales-order-1

### Trackeback

Traceback (most recent call last):
  File "apps/frappe/frappe/app.py", line 69, in application
    response = frappe.api.handle()
  File "apps/frappe/frappe/api.py", line 55, in handle
    return frappe.handler.handle()
  File "apps/frappe/frappe/handler.py", line 38, in handle
    data = execute_cmd(cmd)
  File "apps/frappe/frappe/handler.py", line 76, in execute_cmd
    return frappe.call(method, **frappe.form_dict)
  File "apps/frappe/frappe/__init__.py", line 1457, in call
    return fn(*args, **newargs)
  File "apps/frappe/frappe/desk/form/save.py", line 24, in savedocs
    doc.save()
  File "apps/frappe/frappe/model/document.py", line 310, in save
    return self._save(*args, **kwargs)
  File "apps/frappe/frappe/model/document.py", line 347, in _save
    self.run_before_save_methods()
  File "apps/frappe/frappe/model/document.py", line 1052, in run_before_save_methods
    self.run_method("validate")
  File "apps/frappe/frappe/model/document.py", line 941, in run_method
    out = Document.hook(fn)(self, *args, **kwargs)
  File "apps/frappe/frappe/model/document.py", line 1264, in composer
    return composed(self, method, *args, **kwargs)
  File "apps/frappe/frappe/model/document.py", line 1248, in runner
    add_to_return_value(self, f(self, method, *args, **kwargs))
  File "apps/razorpayx/razorpayx/tasks.py", line 184, in test
    doc.submit()
NameError: name '_' is not defined


### Request Data

{
	"type": "POST",
	"args": {
		"doc": "{****
*
*
*
*
*
*
*
*
		"action": "Save"
	},
	"btn": {
		"jQuery224068332973973893731": {
			"events": {
				"click": [
					{
						"type": "click",
						"origType": "click",
						"guid": 2540,
						"namespace": ""
					}
				]
			}
		}
	},
	"freeze": true,
	"headers": {},
	"error_handlers": {},
	"url": "/api/method/frappe.desk.form.save.savedocs"
}
### Response Data
{
	"exception": "NameError: name '_' is not defined"
}

Hi @Azhar_Umar ,

In the Frappe Framework, the authors created a function named '_'
The purpose is to translate text into other languages.

To use it, you must import it, like this:

from frappe import _

Below is a screenshot of your code, showing where this ‘_’ function is called.

3 Likes

Finally did it.

It took me a lot of time. But finally figured out.

I have to reboot the server every time I change doc_events in hooks.py. Just bench migrate is not sufficient. Maybe an issue with my server. Or there maybe a better fix.

Thanks @brian_pond for helping me with NameError
Thanks @jamsheer and @rtdany10

1 Like

These commands also worked, instead of rebooting the server.

sudo -i service supervisor stop

sudo -i service supervisor start

I agree, sometimes the web server does not immediately recognize our edits.

Whenever I deploy code, I perform the following steps to help make it successful:

  1. Stop the web server.
  2. Import my new code.
  3. Clear the Redis cache database:
    bench clear-cache
    
  4. Delete all Python bytecode files:
    sudo find . -name "*.pyc" -delete
    
  5. Synchronize the MariaDB database:
     bench migrate
    
  6. If I’ve made JavaScript changes, especially to Frappe Framework? Then I run:
    bench build
    
  7. Restart the web server.

To make this easier, on all my servers, I create Bash scripts that perform the steps above. Then when I deploy code, it’s just a 1-line command (plus entering GitHub credentials)

2 Likes

You seem to be on production mode, just run the following command after you make any change:
bench restart --web --supervisor

thank you @rtdany10. That was really helpful.

1 Like