ERPNext Foundation ERPNext Cloud User Manual Blog Discuss Frappé* Donate

Projects automatic numbering – workaround using client custom script

projects
customization
custom_script

#1

Hi,
we have hundreds of projects and so we need an unique identifier for projects. Manual numbering in project_name field is not very comfortable and can lead to meaningless names like Project1, Project2 etc. If I do it using naming_series in Project doctype, I won’t be able to make updates via bench update, is it right? And this is what I don’t want.

Is there a way or workaround, how to do it without touching project doctype using client side customization?
I thought about creating a custom script, which will set project_name to some auto-incremented value automatically on project creation. Descriptive project name then could be saved in a new custom field, called for example project_title. Is it possible to do it like this? Or is there a better/simpler way?

I have tried to do it using this script, but it didn’t work for me. It will be my first script, could you please outline possible solution?


#2

Any ideas?


#3

You ran ‘bench update’ and had a naming_series problem?

Sorry I am not clear - your problem is theoretical or from actual testing?


#4

Hi @clarkej
problem is both theoretical and practical.

Theoretical part is, that I have read somewhere to not touch doctypes, because it breaks updates.

But I tried it anyway, and came to this message after running bench update:

Cannot proceed with update: You have local changes in app "erpnext" that are not committed.

Here are your choices:

1. Merge the erpnext app manually with "git pull" / "git pull --rebase" and fix conflicts.
1. Temporarily remove your changes with "git stash" or discard them completely
        with "bench update --reset" or for individual repositries "git reset --hard"
2. If your changes are helpful for others, send in a pull request via GitHub and
        wait for them to be merged in the core.

This is where I ended, because I’m not sure what to choose to both keep my changes and have erpnext still upgradable.


#5

ok yes update overwrites your local (server side) code changes.

A search like ‘save local changes’ or ‘git pull or git stash’ will inform your options and steps on what to do and expect.

You can identify your changes with say git status and diff - to learn git basics

To experiment and discover a practice or test environment is best.


#6

Hello @clarkej
thank you for your response, I know something about git, but I don’t know enough about ERPNext.
You are right that to experiment and discovery is best to learn, but some guides and advices can save time…

So bench update is something like git pull & bench migrate? There is not any other magic behind it?

Sorry for asking such general question, but are there any guidelines or best practices, when is reasonable to make changes directly to doctypes and when is better to create separate module/app for these changes?


#7

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


#8

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?


#9

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


#10

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.


I try to make contracts have serial names
#11

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


#12

Thank you very much @clarkej for your effort!

Is there anybody who is able to answer?


#13

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.


#14

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…?


#15

@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.


#16

You mean changing naming_series ?

It is possible to write code for that too.


#17

@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.


#18

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 :


#19

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)


#20

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.