Error installing custom app having ERPNext custom Doctype in fixtures

Hi there,

i’m trying to add to custom app to a new site, with ERPnext customization as fixtures:

Custom Field, 
Custom Script, 
DocTypes (only custom, and mostly child tables)
Property Setter. 

in the custom app hooks.py, i’ve added:

fixtures = [{
		"doctype": "DocType",
                "filters": { "custom" : ["=", "1"] }
               }, 
        	"Custom Field",
        	"Custom Script",
        	"Property Setter"
           ]

All files are successfully exported in fixtures custom app folder.

Problem comes out when trying to install custom app to the site:

 bench --site testsite.dev install-app test-app

 
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 79, in <module>
        main()
      File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/bench_helper.py", line 16, 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 716, in __call__
        return self.main(*args, **kwargs)
      File "/home/frappe/frappe-bench/env/local/lib/python2.7/site-packages/click/core.py", line 696, in main
        rv = self.invoke(ctx)
      File "/home/frappe/frappe-bench/env/local/lib/python2.7/site-packages/click/core.py", line 1060, 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 1060, 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 889, 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 534, 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 152, in install_app
        _install_app(app, verbose=context.verbose)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/installer.py", line 146, in install_app
        sync_fixtures(name)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/fixtures.py", line 24, in sync_fixtures
        ignore_links=True, overwrite=True)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/core/page/data_import_tool/data_import_tool.py", line 95, in import_doc
        frappe.modules.import_file.import_file_by_path(f, data_import=True, force=True, pre_process=pre_process)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/modules/import_file.py", line 54, in import_file_by_path
        import_doc(doc, force=force, data_import=data_import, pre_process=pre_process)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/modules/import_file.py", line 122, in import_doc
        doc.insert()
      File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 233, in insert
        self.run_post_save_methods()
      File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 779, in run_post_save_methods
        self.run_method("on_update")
      File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 665, in run_method
        out = Document.hook(fn)(self, *args, **kwargs)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 890, in composer
        return composed(self, method, *args, **kwargs)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 873, in runner
        add_to_return_value(self, fn(self, *args, **kwargs))
      File "/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py", line 659, in <lambda>
        fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/custom/doctype/custom_field/custom_field.py", line 46, in on_update
        validate_fields_for_doctype(self.dt)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/core/doctype/doctype/doctype.py", line 264, in validate_fields_for_doctype
        validate_fields(frappe.get_meta(doctype, cached=False))
      File "/home/frappe/frappe-bench/apps/frappe/frappe/core/doctype/doctype/doctype.py", line 462, in validate_fields
        check_link_table_options(d)
      File "/home/frappe/frappe-bench/apps/frappe/frappe/core/doctype/doctype/doctype.py", line 306, in check_link_table_options
        frappe.throw(_("Options must be a valid DocType for field {0} in row {1}").format(d.label, d.idx))
      File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 300, in throw
        msgprint(msg, raise_exception=exc, title=title, indicator='red')
      File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 293, in msgprint
        _raise_exception()
      File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 266, in _raise_exception
        raise raise_exception, encode(msg)
    frappe.exceptions.ValidationError: Options must be a valid DocType for field Warehouse Supplier in row 20 

It seems it’s adding Custom Fields before the custom DocTypes …any hint on how to solve the problem? I’m completely stuck on this

BIG THX in advance

1 Like

I think this is quite clear

@rmehta

well it’s clear, but Warehouse Supplier is defined as a custom doctype inside doctype.json in fixtures folder:

 {
  "_assign": null, 
  "_comments": null, 
  "_last_update": null, 
  "_liked_by": null, 
  "_user_tags": null, 
  "allow_copy": 0, 
  "allow_import": 0, 
  "allow_rename": 0, 
  "app": null, 
  "autoname": null, 
  "beta": 0, 
  "colour": null, 
  "custom": 1, 
  "default_print_format": null, 
  "description": null, 
  "docstatus": 0, 
  "doctype": "DocType", 
  "document_type": "Setup", 
  "editable_grid": 1, 
  "engine": "InnoDB", 
  "fields": [
   {
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "collapsible_depends_on": null, 
    "columns": 0, 
    "default": null, 
    "depends_on": null, 
    "description": null, 
    "fieldname": "supplier", 
    "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Supplier", 
    "length": 0, 
    "no_copy": 0, 
    "oldfieldname": null, 
    "oldfieldtype": null, 
    "options": "Supplier", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
    "print_width": null, 
    "read_only": 0, 
    "report_hide": 0, 
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
    "trigger": null, 
    "unique": 0, 
    "width": null
   }, 
   {
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "collapsible_depends_on": null, 
    "columns": 0, 
    "default": null, 
    "depends_on": null, 
    "description": null, 
    "fieldname": "supplier_warehouse_code", 
    "fieldtype": "Data", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 1, 
    "label": "Supplier Warehouse Code", 
    "length": 0, 
    "no_copy": 0, 
    "oldfieldname": null, 
    "oldfieldtype": null, 
    "options": null, 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
    "print_width": null, 
    "read_only": 0, 
    "report_hide": 0, 
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
    "trigger": null, 
    "unique": 0, 
    "width": null
   }
  ], 
  "hide_heading": 0, 
  "hide_toolbar": 0, 
  "icon": null, 
  "image_field": null, 
  "image_view": 0, 
  "in_create": 0, 
  "in_dialog": 0, 
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
  "menu_index": null, 
  "modified": "2016-06-26 23:16:51.334058", 
  "module": "Stock", 
  "name": "Warehouse Supplier", 
  "name_case": "", 
  "parent_node": null, 
  "permissions": [], 
  "print_outline": null, 
  "quick_entry": 1, 
  "read_only": 0, 
  "read_only_onload": 0, 
  "search_fields": null, 
  "smallicon": null, 
  "sort_field": "modified", 
  "sort_order": "DESC", 
  "subject": null, 
  "tag_fields": null, 
  "timeline_field": null, 
  "title_field": null, 
  "track_seen": 0
 },

having "options": "Supplier" on line 20; this is the screen shot of doctype settings:

Cant understand what’s wrong …

@rmehta i keep getting the same error for different DocType:

frappe.exceptions.ValidationError: Options must be a valid DocType for field Items in row 9

it fail on "options": "Item"

It seems that the custom app installation fail when fields are related to other DocType (aka Link)

For some reason a Validation Exception is raised even if the DocType linked is correctly set.

Any hint on how to solve the problem?

Is there any reason you are creating custom doctypes at all? Why not just create standard doctypes for your app instead? That might solve this issue.

@Ben_Cornwell_Mott well …good question …all the doctypes has been created to extend ERPNext …like Item Barcode, to add ability to have multiple barcode per items …etc …so best way I found is to add doctypes and mark as custom because they will extend ERPNext …is that wrong? What are the best pratics?

Thx in advance

Honestly I’m not quite sure. I’ve stuck with creating doctypes as part of my own Custom module (my app) and been able to reference them with custom fields and scripts.

I’m not sure it’s “better” to do it this way, but if you aren’t able to get Custom doctypes and custom fields working together, it might be a solution.

From your description it sounds like a bug in the order that the fixtures are imported.

@Ben_Cornwell_Mott …i agree with u on “a bug in the order that the fixtures are imported” …any chance to have core team looking at that?

I’ll surely have a test exporting doctype without mark doctype as custom … btw do u have an idea on what’s exactly a custom doctype?

Thx a lot in advance!

I think all it is it tacking on a doctype to any module without affecting the base code. If it’s not custom, it will create the .json file in your ERPNext directory, which means it won’t prevent updates.

The key here if you don’t use custom doctypes is that they need to be in a separate app than ERPNext if you want to be able to continue updating.

@Ben_Cornwell_Mott @rmehta

I finally made it work!

  • I’ve renamed doctype.json to 1_doctype.json so that DocTypes has been imported as first file;
  • Manually edited doctype.json in order to have Link referenced DocType (mainly child tables) to be imported as first.

Basically i think there is a small bug on the sequence with which DocType are exported and written in json file (and thus imported while installing custom app).

As far as i got fixtures import sequence is alphabetical, based on file name, so files are imported in this order:

  1. Custom Field
  2. Custom Script
  3. DocType
  4. Property Setter

Problems:

  • Having a Custom Field as Link to a Custom Doctype import fails.

  • While importing DocType file, having a Link field to a Custom DocType not yet created, import fail.

A possible solution could be, naming file name in a way that the alphabetical sequence will last as:

  1. DocType
  2. Custom Field
  3. Custom Script
  4. Property Setter

i.e.:

1_doctype.json
2_custom_field.json
3_custom_script.json
4_property_setter.json

On DocType export prioritize as:

  1. DocType - order_by istable desc, created asc (or desc?)
  2. Custom DocType - order_by istable desc, created asc (or desc?)

Not sure if it’s best solution …but i think it’s worth to try it

What u think?

EDIT: i’ve slightly modified

https://github.com/frappe/frappe/blob/c1e5e5dabef21969436ec89f931dd5a3850d6135/frappe/core/page/data_import_tool/data_import_tool.py#L63

into order_by="creation desc" to have doctype exported in the right order.

5 Likes