Example #1
0
def get_doc(arg1, arg2=None):
    """returns a frappe.model.Document object.

	:param arg1: Document dict or DocType name.
	:param arg2: [optional] document name.

	There are two ways to call `get_doc`

		# will fetch the latest user object (with child table) from the database
		user = get_doc("User", "*****@*****.**")

		# create a new object
		user = get_doc({
			"doctype":"User"
			"email_id": "*****@*****.**",
			"user_roles: [
				{"role": "System Manager"}
			]
		})
	"""
    if isinstance(arg1, BaseDocument):
        return arg1
    elif isinstance(arg1, basestring):
        doctype = arg1
    else:
        doctype = arg1.get("doctype")

    controller = get_controller(doctype)
    if controller:
        return controller(arg1, arg2)

    raise ImportError, arg1
Example #2
0
def import_doc(docdict, force=False, data_import=False, pre_process=None, ignore_version=None, reset_permissions=False, path=None):
	frappe.flags.in_import = True
	docdict["__islocal"] = 1

	controller = get_controller(docdict["doctype"])
	if controller and hasattr(controller, "prepare_for_import") and callable(getattr(controller, "prepare_for_import")):
		controller.prepare_for_import(docdict)

	doc = frappe.get_doc(docdict)

	reset_tree_properties(doc)
	load_code_properties(doc, path)

	doc.run_method("before_import")

	doc.flags.ignore_version = ignore_version
	if pre_process:
		pre_process(doc)

	if frappe.db.exists(doc.doctype, doc.name):
		delete_old_doc(doc, reset_permissions)

	doc.flags.ignore_links = True
	if not data_import:
		doc.flags.ignore_validate = True
		doc.flags.ignore_permissions = True
		doc.flags.ignore_mandatory = True

	doc.insert()

	frappe.flags.in_import = False

	return doc
Example #3
0
def get_doc(arg1, arg2=None):
	"""returns a frappe.model.Document object.

	:param arg1: Document dict or DocType name.
	:param arg2: [optional] document name.

	There are two ways to call `get_doc`

		# will fetch the latest user object (with child table) from the database
		user = get_doc("User", "*****@*****.**")

		# create a new object
		user = get_doc({
			"doctype":"User"
			"email_id": "*****@*****.**",
			"user_roles: [
				{"role": "System Manager"}
			]
		})
	"""
	if isinstance(arg1, BaseDocument):
		return arg1
	elif isinstance(arg1, basestring):
		doctype = arg1
	else:
		doctype = arg1.get("doctype")

	controller = get_controller(doctype)
	if controller:
		return controller(arg1, arg2)

	raise ImportError, arg1
Example #4
0
def load_desktop_data(bootinfo):
	from frappe.config import get_modules_from_all_apps_for_user
	from frappe.desk.desktop import get_desk_sidebar_items
	bootinfo.allowed_modules = get_modules_from_all_apps_for_user()
	bootinfo.allowed_workspaces = get_desk_sidebar_items(flatten=True, cache=False)
	bootinfo.module_page_map = get_controller("Desk Page").get_module_page_map()
	bootinfo.dashboards = frappe.get_all("Dashboard")
Example #5
0
def load_desktop_data(bootinfo):
    from frappe.desk.desktop import get_desk_sidebar_items

    bootinfo.allowed_workspaces = get_desk_sidebar_items()
    bootinfo.module_page_map = get_controller(
        "Workspace").get_module_page_map()
    bootinfo.dashboards = frappe.get_all("Dashboard")
Example #6
0
def get():
	args = get_form_params()
	# If virtual doctype get data from controller het_list method
	if frappe.db.get_value("DocType", filters={"name": args.doctype}, fieldname="is_virtual"):
		controller = get_controller(args.doctype)
		data = compress(controller(args.doctype).get_list(args))
	else:
		data = compress(execute(**args), args=args)
	return data
Example #7
0
def get():
    args = get_form_params()
    # If virtual doctype get data from controller het_list method
    if is_virtual_doctype(args.doctype):
        controller = get_controller(args.doctype)
        data = compress(controller(args.doctype).get_list(args))
    else:
        data = compress(execute(**args), args=args)
    return data
Example #8
0
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_for_import') and callable(
            getattr(controller, 'prepare_for_import')):
        controller.prepare_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)

    ignore = []

    if frappe.db.exists(doc.doctype, doc.name):

        old_doc = frappe.get_doc(doc.doctype, doc.name)

        if doc.doctype in ignore_values:
            # update ignore values
            for key in ignore_values.get(doc.doctype) or []:
                doc.set(key, old_doc.get(key))

        # update ignored docs into new doc
        for df in doc.meta.get_table_fields():
            if df.options in ignore_doctypes and not reset_permissions:
                doc.set(df.fieldname, [])
                ignore.append(df.options)

        # delete old
        frappe.delete_doc(doc.doctype,
                          doc.name,
                          force=1,
                          ignore_doctypes=ignore,
                          for_reload=True)

    doc.flags.ignore_children_type = ignore
    doc.flags.ignore_links = True
    if not data_import:
        doc.flags.ignore_validate = True
        doc.flags.ignore_permissions = True
        doc.flags.ignore_mandatory = True

    doc.insert()

    frappe.flags.in_import = False
Example #9
0
	def validate_website(self):
		"""Ensure that website generator has field 'route'"""
		from frappe.model.base_document import get_controller
		try:
			controller = get_controller(self.name)
		except:
			controller = None

		if controller and getattr(controller, 'website', None):
			if not 'route' in [d.fieldname for d in self.fields]:
				frappe.throw('Field "route" is mandatory for Website Generator pages', title='Missing Field')
Example #10
0
def get_list():
    args = get_form_params()

    if is_virtual_doctype(args.doctype):
        controller = get_controller(args.doctype)
        data = controller(args.doctype).get_list(args)
    else:
        # uncompressed (refactored from frappe.model.db_query.get_list)
        data = execute(**args)

    return data
Example #11
0
	def validate_website(self):
		"""Ensure that website generator has field 'route'"""
		from frappe.model.base_document import get_controller
		try:
			controller = get_controller(self.name)
		except:
			controller = None

		if controller and getattr(controller, 'website', None):
			if not 'route' in [d.fieldname for d in self.fields]:
				frappe.throw('Field "route" is mandatory for Website Generator pages', title='Missing Field')
Example #12
0
def get_sidebar_stats(stats, doctype, filters=None):
    if filters is None:
        filters = []

    if is_virtual_doctype(doctype):
        controller = get_controller(doctype)
        args = {"stats": stats, "filters": filters}
        data = controller(doctype).get_stats(args)
    else:
        data = get_stats(stats, doctype, filters)

    return {"stats": data}
Example #13
0
def get_doc(*args, **kwargs):
	"""returns a frappe.model.Document object.

	:param arg1: Document dict or DocType name.
	:param arg2: [optional] document name.
	:param for_update: [optional] select document for update.

	There are multiple ways to call `get_doc`

		# will fetch the latest user object (with child table) from the database
		user = get_doc("User", "*****@*****.**")

		# create a new object
		user = get_doc({
			"doctype":"User"
			"email_id": "*****@*****.**",
			"roles: [
				{"role": "System Manager"}
			]
		})

		# create new object with keyword arguments
		user = get_doc(doctype='User', email_id='*****@*****.**')

		# select a document for update
		user = get_doc("User", "*****@*****.**", for_update=True)
	"""
	if args:
		if isinstance(args[0], BaseDocument):
			# already a document
			return args[0]
		elif isinstance(args[0], string_types):
			doctype = args[0]

		elif isinstance(args[0], dict):
			# passed a dict
			kwargs = args[0]

		else:
			raise ValueError('First non keyword argument must be a string or dict')

	if len(args) < 2 and kwargs:
		if 'doctype' in kwargs:
			doctype = kwargs['doctype']
		else:
			raise ValueError('"doctype" is a required key')

	controller = get_controller(doctype)
	if controller:
		return controller(*args, **kwargs)

	raise ImportError(doctype)
Example #14
0
def get_count():
    args = get_form_params()

    if is_virtual_doctype(args.doctype):
        controller = get_controller(args.doctype)
        data = controller(args.doctype).get_count(args)
    else:
        distinct = "distinct " if args.distinct == "true" else ""
        args.fields = [
            f"count({distinct}`tab{args.doctype}`.name) as total_count"
        ]
        data = execute(**args)[0].get("total_count")

    return data
Example #15
0
	def validate_naming(doc):
		autoname = frappe.get_meta(doctype).autoname
		if autoname:
			if autoname[0:5] == 'field':
				autoname = autoname[6:]
			elif autoname == 'naming_series:':
				autoname = 'naming_series'
			else:
				return True

			if (autoname not in doc) or (not doc[autoname]):
				from frappe.model.base_document import get_controller
				if not hasattr(get_controller(doctype), "autoname"):
					frappe.throw(_("{0} is a mandatory field".format(autoname)))
		return True
Example #16
0
	def validate_naming(doc):
		autoname = frappe.get_meta(doctype).autoname
		if autoname:
			if autoname[0:5] == 'field':
				autoname = autoname[6:]
			elif autoname == 'naming_series:':
				autoname = 'naming_series'
			else:
				return True

			if (autoname not in doc) or (not doc[autoname]):
				from frappe.model.base_document import get_controller
				if not hasattr(get_controller(doctype), "autoname"):
					frappe.throw(_("{0} is a mandatory field").format(autoname))
		return True
Example #17
0
def get_doc(*args, **kwargs):
	"""returns a frappe.model.Document object.

	:param arg1: Document dict or DocType name.
	:param arg2: [optional] document name.

	There are multiple ways to call `get_doc`

		# will fetch the latest user object (with child table) from the database
		user = get_doc("User", "*****@*****.**")

		# create a new object
		user = get_doc({
			"doctype":"User"
			"email_id": "*****@*****.**",
			"roles: [
				{"role": "System Manager"}
			]
		})

		# create new object with keyword arguments
		user = get_doc(doctype='User', email_id='*****@*****.**')
	"""
	if args:
		if isinstance(args[0], BaseDocument):
			# already a document
			return args[0]
		elif isinstance(args[0], string_types):
			doctype = args[0]

		elif isinstance(args[0], dict):
			# passed a dict
			kwargs = args[0]

		else:
			raise ValueError('First non keyword argument must be a string or dict')

	if kwargs:
		if 'doctype' in kwargs:
			doctype = kwargs['doctype']
		else:
			raise ValueError('"doctype" is a required key')

	controller = get_controller(doctype)
	if controller:
		return controller(*args, **kwargs)

	raise ImportError(doctype)
Example #18
0
def update_routes(doctypes):
	"""Patch old routing system"""
	for d in doctypes:
		frappe.reload_doctype(d)
		c = get_controller(d)

		condition = ''
		if c.website.condition_field:
			condition = 'where {0}=1'.format(c.website.condition_field)

		try:
			frappe.db.sql("""update ignore `tab{0}` set route = concat(ifnull(parent_website_route, ""),
				if(ifnull(parent_website_route, "")="", "", "/"), page_name) {1}""".format(d, condition))

		except Exception as e:
			if e.args[0]!=1054: raise
Example #19
0
	def test_rename_controllers(self):
		"""Rename doctypes with controller code paths"""
		# check if module exists exists;
		# if custom, get_controller will return Document class
		# if not custom, a different class will be returned
		self.assertNotEqual(get_controller(self.doctype.old), frappe.model.document.Document)

		old_doctype_path = get_doc_path("Custom", "DocType", self.doctype.old)

		# rename doc via wrapper API accessible via /desk
		frappe.rename_doc("DocType", self.doctype.old, self.doctype.new)

		# check if database and controllers are updated
		self.assertTrue(frappe.db.exists("DocType", self.doctype.new))
		self.assertFalse(frappe.db.exists("DocType", self.doctype.old))
		self.assertFalse(os.path.exists(old_doctype_path))
Example #20
0
	def validate_field_name_conflicts(self):
		"""Check if field names dont conflict with controller properties and methods"""
		core_doctypes = [
			"Custom DocPerm",
			"DocPerm",
			"Custom Field",
			"Customize Form Field",
			"DocField",
		]

		if self.name in core_doctypes:
			return

		try:
			controller = get_controller(self.name)
		except ImportError:
			controller = Document

		available_objects = {x for x in dir(controller) if isinstance(x, str)}
		property_set = {
			x for x in available_objects if isinstance(getattr(controller, x, None), property)
		}
		method_set = {
			x for x in available_objects if x not in property_set and callable(getattr(controller, x, None))
		}

		for docfield in self.get("fields") or []:
			if docfield.fieldtype in no_value_fields:
				continue

			conflict_type = None
			field = docfield.fieldname
			field_label = docfield.label or docfield.fieldname

			if docfield.fieldname in method_set:
				conflict_type = "controller method"
			if docfield.fieldname in property_set:
				conflict_type = "class property"

			if conflict_type:
				frappe.throw(
					_("Fieldname '{0}' conflicting with a {1} of the name {2} in {3}")
						.format(field_label, conflict_type, field, self.name)
				)
Example #21
0
def import_doc(
	docdict,
	force=False,
	data_import=False,
	pre_process=None,
	ignore_version=None,
	reset_permissions=False,
	path=None,
):
	frappe.flags.in_import = True
	docdict["__islocal"] = 1

	controller = get_controller(docdict["doctype"])
	if (
		controller
		and hasattr(controller, "prepare_for_import")
		and callable(getattr(controller, "prepare_for_import"))
	):
		controller.prepare_for_import(docdict)

	doc = frappe.get_doc(docdict)

	# Note on Tree DocTypes:
	# The tree structure is maintained in the database via the fields "lft" and
	# "rgt". They are automatically set and kept up-to-date. Importing them
	# would destroy any existing tree structure.
	if getattr(doc.meta, "is_tree", None) and any([doc.lft, doc.rgt]):
		print('Ignoring values of `lft` and `rgt` for {} "{}"'.format(doc.doctype, doc.name))
		doc.lft = None
		doc.rgt = None

	doc.run_method("before_import")

	doc.flags.ignore_version = ignore_version
	if pre_process:
		pre_process(doc)

	ignore = []

	if frappe.db.exists(doc.doctype, doc.name):

		old_doc = frappe.get_doc(doc.doctype, doc.name)

		if doc.doctype in ignore_values:
			# update ignore values
			for key in ignore_values.get(doc.doctype) or []:
				doc.set(key, old_doc.get(key))

		# update ignored docs into new doc
		for df in doc.meta.get_table_fields():
			if df.options in ignore_doctypes and not reset_permissions:
				doc.set(df.fieldname, [])
				ignore.append(df.options)

		# delete old
		frappe.delete_doc(doc.doctype, doc.name, force=1, ignore_doctypes=ignore, for_reload=True)

	doc.flags.ignore_children_type = ignore
	doc.flags.ignore_links = True
	if not data_import:
		doc.flags.ignore_validate = True
		doc.flags.ignore_permissions = True
		doc.flags.ignore_mandatory = True

	doc.insert()

	frappe.flags.in_import = False
Example #22
0
def rebuild_for_doctype(doctype):
	'''Rebuild entries of doctype's documents in __global_search on change of
		searchable fields
	:param doctype: Doctype '''

	def _get_filters():
		filters = frappe._dict({ "docstatus": ["!=", 2] })
		if meta.has_field("enabled"):
			filters.enabled = 1
		if meta.has_field("disabled"):
			filters.disabled = 0

		return filters

	meta = frappe.get_meta(doctype)
	if cint(meta.istable) == 1:
		parent_doctypes = frappe.get_all("DocField", fields="parent", filters={
			"fieldtype": "Table",
			"options": doctype
		})
		for p in parent_doctypes:
			rebuild_for_doctype(p.parent)

		return

	# Delete records
	delete_global_search_records_for_doctype(doctype)

	parent_search_fields = meta.get_global_search_fields()
	fieldnames = get_selected_fields(meta, parent_search_fields)

	# Get all records from parent doctype table
	all_records = frappe.get_all(doctype, fields=fieldnames, filters=_get_filters())

	# Children data
	all_children, child_search_fields = get_children_data(doctype, meta)
	all_contents = []

	for doc in all_records:
		content = []
		for field in parent_search_fields:
			value = doc.get(field.fieldname)
			if value:
				content.append(get_formatted_value(value, field))

		# get children data
		for child_doctype, records in all_children.get(doc.name, {}).items():
			for field in child_search_fields.get(child_doctype):
				for r in records:
					if r.get(field.fieldname):
						content.append(get_formatted_value(r.get(field.fieldname), field))

		if content:
			# if doctype published in website, push title, route etc.
			published = 0
			title, route = "", ""
			try:
				if hasattr(get_controller(doctype), "is_website_published") and meta.allow_guest_to_view:
					d = frappe.get_doc(doctype, doc.name)
					published = 1 if d.is_website_published() else 0
					title = d.get_title()
					route = d.get("route")
			except ImportError:
				# some doctypes has been deleted via future patch, hence controller does not exists
				pass

			all_contents.append({
				"doctype": frappe.db.escape(doctype),
				"name": frappe.db.escape(doc.name),
				"content": frappe.db.escape(' ||| '.join(content or '')),
				"published": published,
				"title": frappe.db.escape(title or ''),
				"route": frappe.db.escape(route or '')
			})
	if all_contents:
		insert_values_for_multiple_docs(all_contents)
Example #23
0
def rebuild_for_doctype(doctype):
	'''Rebuild entries of doctype's documents in __global_search on change of
		searchable fields
	:param doctype: Doctype '''

	def _get_filters():
		filters = frappe._dict({ "docstatus": ["!=", 2] })
		if meta.has_field("enabled"):
			filters.enabled = 1
		if meta.has_field("disabled"):
			filters.disabled = 0

		return filters

	meta = frappe.get_meta(doctype)
	if cint(meta.istable) == 1:
		parent_doctypes = frappe.get_all("DocField", fields="parent", filters={
			"fieldtype": "Table",
			"options": doctype
		})
		for p in parent_doctypes:
			rebuild_for_doctype(p.parent)

		return

	# Delete records
	delete_global_search_records_for_doctype(doctype)

	parent_search_fields = meta.get_global_search_fields()
	fieldnames = get_selected_fields(meta, parent_search_fields)

	# Get all records from parent doctype table
	all_records = frappe.get_all(doctype, fields=fieldnames, filters=_get_filters())

	# Children data
	all_children, child_search_fields = get_children_data(doctype, meta)
	all_contents = []

	for doc in all_records:
		content = []
		for field in parent_search_fields:
			value = doc.get(field.fieldname)
			if value:
				content.append(get_formatted_value(value, field))

		# get children data
		for child_doctype, records in all_children.get(doc.name, {}).items():
			for field in child_search_fields.get(child_doctype):
				for r in records:
					if r.get(field.fieldname):
						content.append(get_formatted_value(r.get(field.fieldname), field))

		if content:
			# if doctype published in website, push title, route etc.
			published = 0
			title, route = "", ""
			try:
				if hasattr(get_controller(doctype), "is_website_published") and meta.allow_guest_to_view:
					d = frappe.get_doc(doctype, doc.name)
					published = 1 if d.is_website_published() else 0
					title = d.get_title()
					route = d.get("route")
			except ImportError:
				# some doctypes has been deleted via future patch, hence controller does not exists
				pass

			all_contents.append({
				"doctype": frappe.db.escape(doctype),
				"name": frappe.db.escape(doc.name),
				"content": frappe.db.escape(' ||| '.join(content or '')),
				"published": published,
				"title": frappe.db.escape(title or ''),
				"route": frappe.db.escape(route or '')
			})
	if all_contents:
		insert_values_for_multiple_docs(all_contents)