예제 #1
0
def get_fetch_fields(doctype, linked_to, ignore_doctypes=None):
    """
	doctype = Master DocType in which the changes are being made
	linked_to = DocType name of the field thats being updated in Master
	This function fetches list of all DocType where both doctype and linked_to is found
	as link fields.
	Forms a list of dict in the form -
	        [{doctype: , master_fieldname: , linked_to_fieldname: ]
	where
	        doctype = DocType where changes need to be made
	        master_fieldname = Fieldname where options = doctype
	        linked_to_fieldname = Fieldname where options = linked_to
	"""

    out = []
    master_list = get_link_fields(doctype)
    linked_to_list = get_link_fields(linked_to)
    product_list = product(master_list, linked_to_list)

    for d in product_list:
        linked_doctype_info = frappe._dict()
        if (d[0]["parent"] == d[1]["parent"] and
            (not ignore_doctypes or d[0]["parent"] not in ignore_doctypes)
                and not d[1]["issingle"]):
            linked_doctype_info.doctype = d[0]["parent"]
            linked_doctype_info.master_fieldname = d[0]["fieldname"]
            linked_doctype_info.linked_to_fieldname = d[1]["fieldname"]
            out.append(linked_doctype_info)

    return out
예제 #2
0
def check_if_doc_is_linked(doc, method="Delete"):
    """
		Raises excption if the given doc(dt, dn) is linked in another record.
	"""
    from frappe.model.rename_doc import get_link_fields
    link_fields = get_link_fields(doc.doctype)
    link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']]
                   for lf in link_fields]

    for link_dt, link_field, issingle in link_fields:
        if not issingle:
            item = frappe.db.get_value(
                link_dt, {link_field: doc.name},
                ["name", "parent", "parenttype", "docstatus"],
                as_dict=True)

            if item and item.parent != doc.name and (
                (method == "Delete" and item.docstatus < 2) or
                (method == "Cancel" and item.docstatus == 1)):
                # raise exception only if
                # linked to an non-cancelled doc when deleting
                # or linked to a submitted doc when cancelling
                frappe.throw(
                    _("Cannot delete or cancel because {0} {1} is linked with {2} {3}"
                      ).format(doc.doctype, doc.name,
                               item.parenttype if item.parent else link_dt,
                               item.parent or item.name),
                    frappe.LinkExistsError)
예제 #3
0
def check_if_doc_is_linked(doc, method="Delete"):
    """
		Raises excption if the given doc(dt, dn) is linked in another record.
	"""
    from frappe.model.rename_doc import get_link_fields
    link_fields = get_link_fields(doc.doctype)
    link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']]
                   for lf in link_fields]

    for link_dt, link_field, issingle in link_fields:
        if not issingle:
            for item in frappe.db.get_values(
                    link_dt, {link_field: doc.name},
                ["name", "parent", "parenttype", "docstatus"],
                    as_dict=True):
                linked_doctype = item.parenttype if item.parent else link_dt
                if linked_doctype in ("Communication", "ToDo", "DocShare",
                                      "Email Unsubscribe", 'File', 'Version'):
                    # don't check for communication and todo!
                    continue

                if item and ((item.parent or item.name) != doc.name) \
                  and ((method=="Delete" and item.docstatus<2) or (method=="Cancel" and item.docstatus==1)):
                    # raise exception only if
                    # linked to an non-cancelled doc when deleting
                    # or linked to a submitted doc when cancelling
                    frappe.throw(
                        _('Cannot delete or cancel because {0} <a href="#Form/{0}/{1}">{1}</a> is linked with {2} <a href="#Form/{2}/{3}">{3}</a>'
                          ).format(doc.doctype, doc.name, linked_doctype,
                                   item.parent or item.name),
                        frappe.LinkExistsError)
예제 #4
0
파일: delete_doc.py 프로젝트: hrwX/frappe
def check_if_doc_is_linked(doc, method="Delete"):
	"""
		Raises excption if the given doc(dt, dn) is linked in another record.
	"""
	from frappe.model.rename_doc import get_link_fields
	link_fields = get_link_fields(doc.doctype)
	link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']] for lf in link_fields]

	for link_dt, link_field, issingle in link_fields:
		if not issingle:
			for item in frappe.db.get_values(link_dt, {link_field:doc.name},
				["name", "parent", "parenttype", "docstatus"], as_dict=True):
				linked_doctype = item.parenttype if item.parent else link_dt
				if linked_doctype in ("Communication", "ToDo", "DocShare", "Email Unsubscribe", 'File', 'Version', "Activity Log", 'Comment'):
					# don't check for communication and todo!
					continue

				if not item:
					continue
				elif (method != "Delete" or item.docstatus == 2) and (method != "Cancel" or item.docstatus != 1):
					# don't raise exception if not
					# linked to a non-cancelled doc when deleting or to a submitted doc when cancelling
					continue
				elif link_dt == doc.doctype and (item.parent or item.name) == doc.name:
					# don't raise exception if not
					# linked to same item or doc having same name as the item
					continue
				else:
					reference_docname = item.parent or item.name
					raise_link_exists_exception(doc, linked_doctype, reference_docname)

		else:
			if frappe.db.get_value(link_dt, None, link_field) == doc.name:
				raise_link_exists_exception(doc, link_dt, link_dt)
예제 #5
0
def check_if_doc_is_linked(doc, method="Delete"):
    """
		Raises excption if the given doc(dt, dn) is linked in another record.
	"""
    from frappe.model.rename_doc import get_link_fields
    link_fields = get_link_fields(doc.doctype)
    link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']]
                   for lf in link_fields]

    for link_dt, link_field, issingle in link_fields:
        if not issingle:
            for item in frappe.db.get_values(
                    link_dt, {link_field: doc.name},
                ["name", "parent", "parenttype", "docstatus"],
                    as_dict=True):
                linked_doctype = item.parenttype if item.parent else link_dt
                if linked_doctype in ("Communication", "ToDo", "DocShare",
                                      "Email Unsubscribe", 'File', 'Version'):
                    # don't check for communication and todo!
                    continue

                if item and ((item.parent or item.name) != doc.name) \
                  and ((method=="Delete" and item.docstatus<2) or (method=="Cancel" and item.docstatus==1)):
                    # raise exception only if
                    # linked to an non-cancelled doc when deleting
                    # or linked to a submitted doc when cancelling
                    reference_docname = item.parent or item.name
                    raise_link_exists_exception(doc, linked_doctype,
                                                reference_docname)
        else:
            if frappe.db.get_value(link_dt, None, link_field) == doc.name:
                raise_link_exists_exception(doc, link_dt, link_dt)
예제 #6
0
def check_if_doc_is_linked(doc, method="Delete"):
	"""
		Raises excption if the given doc(dt, dn) is linked in another record.
	"""
	from frappe.model.rename_doc import get_link_fields
	link_fields = get_link_fields(doc.doctype)
	link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']] for lf in link_fields]

	for link_dt, link_field, issingle in link_fields:
		if not issingle:
			for item in frappe.db.get_values(link_dt, {link_field:doc.name},
				["name", "parent", "parenttype", "docstatus"], as_dict=True):
				linked_doctype = item.parenttype if item.parent else link_dt
				if linked_doctype in ("Communication", "ToDo", "DocShare", "Email Unsubscribe", 'File', 'Version'):
					# don't check for communication and todo!
					continue

				if item and ((item.parent or item.name) != doc.name) \
						and ((method=="Delete" and item.docstatus<2) or (method=="Cancel" and item.docstatus==1)):
					# raise exception only if
					# linked to an non-cancelled doc when deleting
					# or linked to a submitted doc when cancelling
					frappe.throw(_('Cannot delete or cancel because {0} <a href="#Form/{0}/{1}">{1}</a> is linked with {2} <a href="#Form/{2}/{3}">{3}</a>')
						.format(doc.doctype, doc.name, linked_doctype,
						item.parent or item.name), frappe.LinkExistsError)
예제 #7
0
def check_if_doc_is_linked(doc, method="Delete"):
	"""
		Raises excption if the given doc(dt, dn) is linked in another record.
	"""
	from frappe.model.rename_doc import get_link_fields
	link_fields = get_link_fields(doc.doctype)
	link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']] for lf in link_fields]

	for link_dt, link_field, issingle in link_fields:
		if not issingle:
			for item in frappe.db.get_values(link_dt, {link_field:doc.name},
				["name", "parent", "parenttype", "docstatus"], as_dict=True):
				linked_doctype = item.parenttype if item.parent else link_dt
				if linked_doctype in ("Communication", "ToDo", "DocShare", "Email Unsubscribe", 'File', 'Version', "Activity Log"):
					# don't check for communication and todo!
					continue

				if item and ((item.parent or item.name) != doc.name) \
						and ((method=="Delete" and item.docstatus<2) or (method=="Cancel" and item.docstatus==1)):
					# raise exception only if
					# linked to an non-cancelled doc when deleting
					# or linked to a submitted doc when cancelling
					reference_docname = item.parent or item.name
					raise_link_exists_exception(doc, linked_doctype, reference_docname)
		else:
			if frappe.db.get_value(link_dt, None, link_field) == doc.name:
				raise_link_exists_exception(doc, link_dt, link_dt)
예제 #8
0
def update_for_linked_docs(timeline_doctype):
	for df in get_link_fields(timeline_doctype):
		if df.issingle:
			continue

		reference_doctype = df.parent

		if not is_valid_timeline_doctype(reference_doctype, timeline_doctype):
			continue

		for doc in frappe.get_all(reference_doctype, fields=["name", df.fieldname]):
			timeline_name = doc.get(df.fieldname)
			update_communication(timeline_doctype, timeline_name, reference_doctype, doc.name)
예제 #9
0
def update_for_linked_docs(timeline_doctype):
    for df in get_link_fields(timeline_doctype):
        if df.issingle:
            continue

        reference_doctype = df.parent

        if not is_valid_timeline_doctype(reference_doctype, timeline_doctype):
            continue

        for doc in frappe.get_all(reference_doctype,
                                  fields=["name", df.fieldname]):
            timeline_name = doc.get(df.fieldname)
            update_communication(timeline_doctype, timeline_name,
                                 reference_doctype, doc.name)
예제 #10
0
def check_if_doc_is_linked(doc, method="Delete"):
    """
	Raises excption if the given doc(dt, dn) is linked in another record.
	"""
    from frappe.model.rename_doc import get_link_fields

    link_fields = get_link_fields(doc.doctype)
    link_fields = [[lf["parent"], lf["fieldname"], lf["issingle"]]
                   for lf in link_fields]

    for link_dt, link_field, issingle in link_fields:
        if not issingle:
            for item in frappe.db.get_values(
                    link_dt, {link_field: doc.name},
                ["name", "parent", "parenttype", "docstatus"],
                    as_dict=True):
                linked_doctype = item.parenttype if item.parent else link_dt

                ignore_linked_doctypes = doc.get(
                    "ignore_linked_doctypes") or []

                if linked_doctype in doctypes_to_skip or (
                        linked_doctype in ignore_linked_doctypes
                        and method == "Cancel"):
                    # don't check for communication and todo!
                    continue

                if not item:
                    continue
                elif method != "Delete" and (method != "Cancel"
                                             or item.docstatus != 1):
                    # don't raise exception if not
                    # linked to a non-cancelled doc when deleting or to a submitted doc when cancelling
                    continue
                elif link_dt == doc.doctype and (item.parent
                                                 or item.name) == doc.name:
                    # don't raise exception if not
                    # linked to same item or doc having same name as the item
                    continue
                else:
                    reference_docname = item.parent or item.name
                    raise_link_exists_exception(doc, linked_doctype,
                                                reference_docname)

        else:
            if frappe.db.get_value(link_dt, None, link_field) == doc.name:
                raise_link_exists_exception(doc, link_dt, link_dt)
예제 #11
0
def check_if_doc_is_linked(doc, method="Delete"):
	"""
		Raises excption if the given doc(dt, dn) is linked in another record.
	"""
	from frappe.model.rename_doc import get_link_fields
	link_fields = get_link_fields(doc.doctype)
	link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']] for lf in link_fields]

	for link_dt, link_field, issingle in link_fields:
		if not issingle:
			item = frappe.db.get_value(link_dt, {link_field:doc.name},
				["name", "parent", "parenttype", "docstatus"], as_dict=True)

			if item and item.parent != doc.name and ((method=="Delete" and item.docstatus<2) or
					(method=="Cancel" and item.docstatus==1)):
				frappe.throw(_("Cannot delete or cancel because {0} {1} is linked with {2} {3}").format(_(doc.doctype),
					doc.name, _(item.parent) or item.name, item.parenttype if item.parent else _(link_dt)),
					frappe.LinkExistsError)
예제 #12
0
def check_if_doc_is_linked(doc, method="Delete"):
	"""
		Raises excption if the given doc(dt, dn) is linked in another record.
	"""
	from frappe.model.rename_doc import get_link_fields
	link_fields = get_link_fields(doc.doctype)
	link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']] for lf in link_fields]

	for link_dt, link_field, issingle in link_fields:
		if not issingle:
			for item in frappe.db.get_values(link_dt, {link_field:doc.name},
				["name", "parent", "parenttype", "docstatus"], as_dict=True):
				if item and ((item.parent or item.name) != doc.name) \
						and ((method=="Delete" and item.docstatus<2) or (method=="Cancel" and item.docstatus==1)):
					# raise exception only if
					# linked to an non-cancelled doc when deleting
					# or linked to a submitted doc when cancelling
					frappe.throw(_("Cannot delete or cancel because {0} {1} is linked with {2} {3}")
						.format(doc.doctype, doc.name, item.parenttype if item.parent else link_dt,
						item.parent or item.name), frappe.LinkExistsError)
예제 #13
0
def check_if_doc_is_linked(dt, dn, method="Delete"):
    """
		Raises excption if the given doc(dt, dn) is linked in another record.
	"""
    from frappe.model.rename_doc import get_link_fields
    link_fields = get_link_fields(dt)
    link_fields = [[lf['parent'], lf['fieldname'], lf['issingle']]
                   for lf in link_fields]

    for link_dt, link_field, issingle in link_fields:
        if not issingle:
            item = frappe.db.get_value(
                link_dt, {link_field: dn},
                ["name", "parent", "parenttype", "docstatus"],
                as_dict=True)

            if item and item.parent != dn and (method == "Delete" or
                                               (method == "Cancel"
                                                and item.docstatus == 1)):
                frappe.msgprint(method + " " + _("Error") + ":"+\
                 ("%s (%s) " % (dn, dt)) + _("is linked in") + (" %s (%s)") %
                 (item.parent or item.name, item.parent and item.parenttype or link_dt),
                 raise_exception=LinkExistsError)
예제 #14
0
def convert_item_to_batched(item_code):
	"""
	-	how is batch defined ? where is the qty details of the batch stored ?
		where is it fetched ? and on move where is it taken ?
		--> no qty info stored in tabBatch
			everything from stock ledger
			
	- One batch per item ?
		yes

	- How is reference to an item tracked on deletion ?
		- check_if_doc_is_linked		`from frappe.model.rename_doc import get_link_fields(doctype)`
			-	parent doctype is obtained
				if doctype contains field batch_no:
					update;
					--> obtain field list
						`frappe.db.get_table(doctype)`
		- check_if_doc_is_dynamically_linked

	create new batch named 'x' for item y with total qty = total incoming qty
	total qty = sum(positive actual_qty from tabStock Ledger Entry)
	- no need to update the qtys anywhere
		all such details comes from stock ledger entries
	"""
	
	if frappe.db.get_value("Item", item_code, "has_batch_no"):
		print("Already batched item.")
		return
	
	frappe.db.begin()
	
	try:
		frappe.db.set_value("Item", item_code, "has_batch_no", 1)
		frappe.db.set_value("Item", item_code, "create_new_batch", 1)
		
		batch_doc = frappe.new_doc("Batch")
		temp = None
		while not temp:
			temp = frappe.generate_hash()[:7].upper()
			if frappe.db.exists("Batch", temp):
				temp = None
		
		batch_doc.batch_id = temp		
		batch_doc.item = item_code
		batch_doc.description = "Auto Generated - Console ERP Solutions"
		batch_doc.insert()
		
		# static links
		# ignoring dynamic links
		# refer frappe.model.delete_doc.check_if_doc_is_dynamically_linked
		from frappe.model.rename_doc import get_link_fields
		links = get_link_fields("Item")
		for link_field in links:
			if link_field.issingle:
				continue
			
			columns = frappe.db.get_table_columns(link_field.parent)
			
			if not "item_code" in columns or not "batch_no" in columns:
				continue
				
			frappe.db.sql("UPDATE `%s` SET batch_no=%s where item_code=%s;" % ('tab' + link_field.parent, "%s", "%s"),
					(batch_doc.batch_id, item_code), debug=1)
					
		
		frappe.db.sql("UPDATE `tabStock Ledger Entry` SET batch_no=%s WHERE item_code=%s;",
					(batch_doc.batch_id, item_code), debug=1)		
		
		from frappe.sessions import clear_cache
		
		print("Successfully converted")
	
	except Exception:
		frappe.db.rollback()
		raise
	else:
		frappe.db.commit()