diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 499f64be53..61169e91e9 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -17,7 +17,9 @@ from frappe.desk.notifications import delete_notification_count_for from frappe.modules import make_boilerplate, get_doc_path from frappe.model.db_schema import validate_column_name, validate_column_length, type_map from frappe.model.docfield import supports_translation +from frappe.modules.import_file import get_file_path import frappe.website.render +import json # imports - third-party imports import pymysql @@ -390,6 +392,57 @@ class DocType(Document): if naming_series[0].default: make_property_setter(self.name, "naming_series", "default", naming_series[0].default, "Text", validate_fields_for_doctype=False) + def before_export(self, docdict): + # retain order of 'fields' table and change order in 'field_order' + docdict["field_order"] = [f.fieldname for f in self.fields] + + path = get_file_path(self.module, "DocType", self.name) + if os.path.exists(path): + try: + with open(path, 'r') as txtfile: + olddoc = json.loads(txtfile.read()) + + old_field_names = [f['fieldname'] for f in olddoc.get("fields", [])] + if old_field_names: + new_field_dicts = [] + remaining_field_names = [f.fieldname for f in self.fields] + + for fieldname in old_field_names: + field_dict = filter(lambda d: d['fieldname'] == fieldname, docdict['fields']) + if field_dict: + new_field_dicts.append(field_dict[0]) + remaining_field_names.remove(fieldname) + + for fieldname in remaining_field_names: + field_dict = filter(lambda d: d['fieldname'] == fieldname, docdict['fields']) + new_field_dicts.append(field_dict[0]) + + docdict['fields'] = new_field_dicts + except ValueError: + pass + + @staticmethod + def prepare_docdict_for_import(docdict): + # set order of fields from field_order + if docdict.get("field_order"): + new_field_dicts = [] + remaining_field_names = [f['fieldname'] for f in docdict.get('fields', [])] + + for fieldname in docdict.get('field_order'): + field_dict = filter(lambda d: d['fieldname'] == fieldname, docdict.get('fields', [])) + if field_dict: + new_field_dicts.append(field_dict[0]) + remaining_field_names.remove(fieldname) + + for fieldname in remaining_field_names: + field_dict = filter(lambda d: d['fieldname'] == fieldname, docdict.get('fields', [])) + new_field_dicts.append(field_dict[0]) + + docdict['fields'] = new_field_dicts + + if "field_order" in docdict: + del docdict["field_order"] + def export_doc(self): """Export to standard folder `[module]/doctype/[name]/[name].json`.""" from frappe.modules.export_file import export_to_files diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py index 9b097ae1ae..b6e51486f1 100644 --- a/frappe/core/doctype/doctype/test_doctype.py +++ b/frappe/core/doctype/doctype/test_doctype.py @@ -106,7 +106,7 @@ class TestDocType(unittest.TestCase): if condition: self.assertFalse(re.match(pattern, condition)) - def test_load_file_field_order(self): + def test_sync_field_order(self): from frappe.modules.import_file import get_file_path import os diff --git a/frappe/modules/export_file.py b/frappe/modules/export_file.py index 2c6d28d7c2..19e4f0c680 100644 --- a/frappe/modules/export_file.py +++ b/frappe/modules/export_file.py @@ -24,6 +24,7 @@ def export_to_files(record_list=None, record_module=None, verbose=0, create_init def write_document_file(doc, record_module=None, create_init=True): newdoc = doc.as_dict(no_nulls=True) + doc.run_method("before_export", newdoc) # strip out default fields from children for df in doc.meta.get_table_fields(): @@ -39,35 +40,7 @@ def write_document_file(doc, record_module=None, create_init=True): # write the data file fname = scrub(doc.name) - with open(os.path.join(folder, fname + ".json"), 'a+') as txtfile: - # if exporting DocType, retain order of 'fields' table and change order in 'field_order' - if doc.doctype == "DocType": - newdoc["field_order"] = [f.fieldname for f in doc.fields] - - try: - olddoc = json.loads(txtfile.read()) - old_field_names = [f['fieldname'] for f in olddoc.get("fields", [])] - - if old_field_names: - new_field_dicts = [] - remaining_field_names = [f.fieldname for f in doc.fields] - - for fieldname in old_field_names: - field_dict = filter(lambda d: d['fieldname'] == fieldname, newdoc['fields']) - if field_dict: - new_field_dicts.append(field_dict[0]) - remaining_field_names.remove(fieldname) - - for fieldname in remaining_field_names: - field_dict = filter(lambda d: d['fieldname'] == fieldname, newdoc['fields']) - new_field_dicts.append(field_dict[0]) - - newdoc['fields'] = new_field_dicts - except ValueError: - pass - - txtfile.seek(0) - txtfile.truncate() + with open(os.path.join(folder, fname + ".json"), 'w+') as txtfile: txtfile.write(frappe.as_json(newdoc)) def get_module_name(doc): diff --git a/frappe/modules/import_file.py b/frappe/modules/import_file.py index 75bc20eedd..1feb9fba5c 100644 --- a/frappe/modules/import_file.py +++ b/frappe/modules/import_file.py @@ -4,8 +4,9 @@ from __future__ import unicode_literals, print_function import frappe, os, json -from frappe.modules import get_module_path, scrub_dt_dn +from frappe.modules import get_module_path, scrub_dt_dn, load_doctype_module from frappe.utils import get_datetime_str +from frappe.model.base_document import get_controller ignore_values = { "Report": ["disabled", "prepared_report"], @@ -89,27 +90,6 @@ def read_doc_from_file(path): else: raise IOError('%s missing' % path) - # set order of fields from field_order - if doc.get("doctype") == "DocType": - if doc.get("field_order") and doc.get("fields"): - new_field_dicts = [] - remaining_field_names = [f['fieldname'] for f in doc['fields']] - - for fieldname in doc['field_order']: - field_dict = filter(lambda d: d['fieldname'] == fieldname, doc['fields']) - if field_dict: - new_field_dicts.append(field_dict[0]) - remaining_field_names.remove(fieldname) - - for fieldname in remaining_field_names: - field_dict = filter(lambda d: d['fieldname'] == fieldname, doc['fields']) - new_field_dicts.append(field_dict[0]) - - doc['fields'] = new_field_dicts - - if "field_order" in doc: - del doc['field_order'] - return doc ignore_doctypes = [""] @@ -118,8 +98,15 @@ def import_doc(docdict, force=False, data_import=False, pre_process=None, ignore_version=None, reset_permissions=False): frappe.flags.in_import = True docdict["__islocal"] = 1 + + controller = get_controller(docdict['doctype']) + if controller and hasattr(controller, 'prepare_docdict_for_import') and callable(getattr(controller, 'prepare_docdict_for_import')): + controller.prepare_docdict_for_import(docdict) + doc = frappe.get_doc(docdict) + doc.run_method("before_import") + doc.flags.ignore_version = ignore_version if pre_process: pre_process(doc)