Projects automatic numbering – workaround using client custom script

With general questions the devil is in the details…does this help What is the best practice for custom scripts?

Hello @clarkej,
thank you for helping me, I have followed the link with some searching around and I found some stuff that have moved me forward. After a lot of reading and trying I suppose, that the best way will be to keep changes in one place = in separate app. I have found this guide which was very helpful (thanks to @root13F) .

But I still have two, this time very specific, questions to which I didn’t find clear answer:

How to pair changes I have made with available fixture types? I found this list of fixtures
fixtures = [‘Report’, ‘Role Profile’, ‘Role’, ‘Custom Field’, ‘Custom Script’, ‘Property Setter’, ‘Workflow’, ‘Workflow State’, ‘Workflow Action’]
I suppose that if I have made changes for example in Sales order via Customize form, the correct fixture is Custom Field (no matter if I added or modified fields?). But what if I made changes directly to DocType via editing it in DocType form in developer mode(adding fields there or changing naming series)? Will exporting fixtures of Custom Field type reflect also these changes? I have tried it on test site and custom_field.json file looked exactly the same before and after direct modifying of DocType.
If it is not possible to export changes made to DocTypes this way, is there any other way, how to move changes made to existing DocTypes to separate app?

And another question is, if I export fixtures to separate app, does it “undoes” all the changes I have made to erpnext? In other words, is it move or copy?

Your research study has you on the right track martin42 -

For answers to all that you ask I urge you to experiment, that is the ideal way to learn.

edit: Create a new field with an App - how-to wanted

Thank you @clarkej, I have already read the topic you added, it was very useful for me, but there are still some question.

The reason why I’m asking here is not because I’m lazy to learn, test or experiment. I know that I have to practice and experiment… believe me I have read a lot of posts, guides and manuals here, watched videos, I even already tried to write my own app, which worked. Now I only need an answer to absolutely crucial question for me - if it is even possible to go the way I plan to go, if it makes sense to experiment with it. It can help me (and I not only to me) to learn faster and more effective way, and also save some time. And this is why I’m asking here, because I supposed that is why this forum is here…

May I ask you (or anyone else who is willing to help) only one simple question, if it is possible to move to separate app direct changes to Doctype, made in developer mode - for example change of numbering of Projects? I mean changes, that was not done by Customizing forms or by Custom scripts.

Yes to be clear a custom app is the prescribed means to separate and preserve server side code changes from core code in erpnext and frappe since these are subject to updates.

Someone more experienced can advise you in your precise case here

Thank you very much @clarkej for your effort!

Is there anybody who is able to answer?

It is possible. You will have to redo it via Customize Form on a new master installation. Then you can export your fixtures to custom app.

Any new functionality you add that does not change the existing JS / Python code can be added to the custom app.

1 Like

Hello @root13F,
thank you for an answer. But what if I need to make change, what is not possible to be done via Customize Form, like for example change auto naming of Projects, which has to be done in DocType Form…?

@martin42 I understand what you want to do and want to do the same thing. Most probably the answer is why don’t we follow what’s out of the box, or we should develop something and ask for a PR.

You mean changing naming_series ?

It is possible to write code for that too.

@root13F Yes, that was my question, if it is possible to move the change of project naming series to separate app to have ERPNext still upgradable. If so, is there any example of such code?

@aakvatech You are right that it is not easy to start with ERPNext, even if you are developer. You have to overcome the initial barrier and learn the basics before you even make the decision if is ERPnext suitable for your needs, you have to spend a lot of time with try&error style. This can discourage a lot of people. If you are not at least IT-positive and there are no local consultants in you country, you have no chance. As I write above, from my point of view is this a blocker of spreading ERPNext to another countries.

2 Likes

See this reply and try to do the same for your case in projects, it would probably look like this:

def autoname(doc, method):
    doc.name = doc.project_name

Also, don’t forget to update your hooks file with the correct event for the correct doctype. Here’s an example:

doc_events = {
    "Project":{
        "autoname": "myapp.myapp.validations.validations.autoname"
    }
 }

If it is possible via Customize Form, I don’t know about it.

Also use this app for reference if you get lost somewhere :

Thank you @root13F for really helpful answer. I looked at linked topic and it pushed me forward. But question is, if I have to write my own autoname function when it is already there and only thing I need is to activate it by setting autoname to “naming_series:”. What should I do to have it activated by my custom app? Shall I add project.json file with content like this? Will it override default settings? And where to put it?

{
“autoname”: “naming_series:”
}

I wanted to test it, but I was not able to install my custom app. I got an error when I was installing my custom app, even without project doctype modification, only with customizations exported by export-fixtures.
These are steps what I followed:
I started with erpnext installation with some customization via customize form and also with some data already entered.

  1. created an app - bench new-app myapp
  2. added fixtures = [¨Custom Field¨, ¨Property Setter¨] to hooks.py
  3. bench --site site1.local install-app myapp
  4. with bench export-fixtures succesfully exported customizations
  5. made fresh install of erpnext on another virtual machine
  6. copied myapp directory to app directory on machine created in step 6
  7. ran bench --site site1.local install-app myapp and got this error.

What I did wrong?

frappe@ubusrv16:~/frappe-bench$ bench --site site1.local install-app myapp
Traceback (most recent call last):
File “/usr/lib/python2.7/runpy.py”, line 174, in _run_module_as_main
main”, fname, loader, pkg_name)
File “/usr/lib/python2.7/runpy.py”, line 72, in _run_code
exec code in run_globals
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/bench_helper.py”, line 94, in
main()
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/bench_helper.py”, line 18, in main
click.Group(commands=commands)(prog_name=‘bench’)
File “/home/frappe/frappe-bench/env/local/lib/python2.7/site-packages/click/core.py”, line 764, in call
return self.main(*args, **kwargs)
File “/home/frappe/frappe-bench/env/local/lib/python2.7/site-packages/click/core.py”, line 717, in main
rv = self.invoke(ctx)
File “/home/frappe/frappe-bench/env/local/lib/python2.7/site-packages/click/core.py”, line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File “/home/frappe/frappe-bench/env/local/lib/python2.7/site-packages/click/core.py”, line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File “/home/frappe/frappe-bench/env/local/lib/python2.7/site-packages/click/core.py”, line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File “/home/frappe/frappe-bench/env/local/lib/python2.7/site-packages/click/core.py”, line 555, in invoke
return callback(*args, **kwargs)
File “/home/frappe/frappe-bench/env/local/lib/python2.7/site-packages/click/decorators.py”, line 17, in new_func
return f(get_current_context(), *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/commands/init.py”, line 24, in _func
ret = f(frappe._dict(ctx.obj), *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/commands/site.py”, line 162, in install_app
frappe.init(site=site)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 135, in init
local.conf = _dict(get_site_config())
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 189, in get_site_config
config.update(get_file_json(site_config))
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 896, in get_file_json
return json.load(f)
File “/usr/lib/python2.7/json/init.py”, line 291, in load
**kw)
File “/usr/lib/python2.7/json/init.py”, line 339, in loads
return _default_decoder.decode(s)
File “/usr/lib/python2.7/json/decoder.py”, line 364, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File “/usr/lib/python2.7/json/decoder.py”, line 380, in raw_decode
obj, end = self.scan_once(s, idx)
ValueError: Expecting , delimiter: line 4 column 21 (char 91)

No this is not the correct way. You created a JSON.

I’ll give you a walkthrough.

Step 1 : Write your function autoname as mentioned in the previous comment in a seperate Python file in your custom app. Name it appropriately.

Step 2 : In your custom app, locate the hooks.py file where you edited the fixtures list. I repeat it should be your custom app’s hook file not ERPNext or frappe’s hooks.py

Step 3 : In the file you will find doc_events

# Document Events
# ---------------
# Hook on document methods and events

# doc_events = {
# 	"*": {
# 		"on_update": "method",
# 		"on_cancel": "method",
# 		"on_trash": "method"
#	}
# }

Step 4: Uncomment it, and add the correct doctype and event and hook it to the correct function in your custom app (assuming your app name is myapp). Like this:

# Document Events
# ---------------
# Hook on document methods and events

 doc_events = {
 	"Project": {
 		"autoname": "myapp.myapp.validations.validations.autoname"
	}
 }

Now how to correctly note this path :

./frappe-dev/apps/myapp/myapp/myapp/validations
├── __init__.py
├── __init__.pyc
├── validations.py
└── validations.pyc

First correct it in your original instance.

1 Like

Thank you @root13F, I have it done, followed exactly the steps you described. But Im still geting error mentioned above when trying to install that app.
I have erpnext installed as production and then switched to development mode by entry in site_config.json. Erpnext path is /home/frappe/frappe-bench/apps/erpnext and my custom app path is /home/frappe/frappe-bench/apps/myapp.
App is created by bench new-app and there are only exported fixtures and that autoname function. I tried it also with custom app when there were only exported fixtures, before adding autoname function, and it also didnt work, so the problem is probably not related to that function.

please post your site_config.json

I think the error arises from how you added the developer_mode

This is my site_config.json

{
“db_name”: “xxxxxx”,
“db_password”: “xxxxxx”,
“developer_mode”: 1
}

EDIT: deleted old site_config.json and rewrited it manually and now Im getting this

frappe@ubusrv16:~/frappe-bench$ bench --site site1.local install-app myapp
Could not find app “myapp”
frappe@ubusrv16:~/frappe-bench$ ll apps/
total 28
drwxr-xr-x 7 frappe frappe 4096 Dec 23 16:19 ./
drwxr-xr-x 8 frappe frappe 4096 Dec 22 19:37 …/
drwxr-xr-x 8 frappe frappe 4096 Dec 22 19:40 erpnext/
drwxr-xr-x 6 frappe frappe 4096 Dec 22 19:45 foundation/
drwxr-xr-x 9 frappe frappe 4096 Dec 22 19:35 frappe/
drwxr-xr-x 5 frappe frappe 4096 Dec 22 19:37 frappe_io/
drwxr-xr-x 4 frappe frappe 4096 Dec 23 15:54 myapp/

You are finding your way - this post I happened on may help Custom Doctype Naming Series Code Snippet

@root13F
I gave up installing it for another instance for the moment and trying to make it work locally. I have made some progress, but now I’m getting this message, what arises when I try to save project - ImportError: No module named validations.validations

This is content of my validations.py file:

import frappe
from frappe.model.naming import make_autoname
def autoname(doc, method):
doc.name = make_autoname(“PROJ”+‘-.#####’)

I get this message no matter what my autoname function contains:

Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/app.py”, line 62, in application
response = frappe.handler.handle()
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 22, in handle
data = execute_cmd(cmd)
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 53, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 939, in call
return fn(*args, **newargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/client.py”, line 143, in insert
doc = frappe.get_doc(doc).insert()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 215, in insert
self.set_new_name()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 375, in set_new_name
set_new_name(self)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/naming.py”, line 38, in set_new_name
doc.run_method(“autoname”)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 757, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 1023, in composer
hooks.append(frappe.get_attr(handler))
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 919, in get_attr
return getattr(get_module(modulename), methodname)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 704, in get_module
return importlib.import_module(modulename)
File “/usr/lib/python2.7/importlib/init.py”, line 37, in import_module
import(name)
ImportError: No module named validations.validations

@clarkej
Than you for a link, but if I use that snippets, I get the same error as above.

This is in v7 but there’s a weird workaround that frappe/erpnext doesn’t encourage: editing the naming series using the Property Setter doctype. :smiley:

This is exported as a fixture (via export-fixtures) .

I managed to change the Stock Ledger Entry naming series by manually adding an entry for Stock Ledger Entry-naming_series-default. It worked. :laughing:

PS:

The page specifically tells you:

Please don't update it as it can mess up your form. 
Use the Customize Form View and Custom Fields to set properties!

…which is reasonable. So please do this at your own risk and make necessary preparations (eg. do a backup) before hand.

1 Like