# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt from __future__ import unicode_literals import webnotes, json from webnotes import _ from webnotes.utils import cstr from webnotes.model import default_fields def get_mapped_doclist(from_doctype, from_docname, table_maps, target_doclist=None, postprocess=None, ignore_permissions=False): if target_doclist is None: target_doclist = [] if isinstance(target_doclist, basestring): target_doclist = json.loads(target_doclist) source = webnotes.bean(from_doctype, from_docname) if not ignore_permissions and not webnotes.has_permission(from_doctype, "read", source.doc): webnotes.msgprint("No Permission", raise_exception=webnotes.PermissionError) source_meta = webnotes.get_doctype(from_doctype) target_meta = webnotes.get_doctype(table_maps[from_doctype]["doctype"]) # main if target_doclist: if isinstance(target_doclist[0], dict): target_doc = webnotes.doc(fielddata=target_doclist[0]) else: target_doc = target_doclist[0] else: target_doc = webnotes.new_doc(table_maps[from_doctype]["doctype"]) map_doc(source.doc, target_doc, table_maps[source.doc.doctype], source_meta, target_meta) if target_doclist: target_doclist[0] = target_doc else: target_doclist = [target_doc] target_doclist = webnotes.doclist(target_doclist) row_exists_for_parentfield = {} # children for source_d in source.doclist[1:]: table_map = table_maps.get(source_d.doctype) if table_map: if "condition" in table_map: if not table_map["condition"](source_d): continue target_doctype = table_map["doctype"] parentfield = target_meta.get({ "parent": target_doc.doctype, "doctype": "DocField", "fieldtype": "Table", "options": target_doctype })[0].fieldname # does row exist for a parentfield? if parentfield not in row_exists_for_parentfield: row_exists_for_parentfield[parentfield] = True if \ webnotes.doclist(target_doclist).get({"parentfield": parentfield}) else False if table_map.get("add_if_empty") and row_exists_for_parentfield.get(parentfield): continue target_d = webnotes.new_doc(target_doctype, target_doc, parentfield) map_doc(source_d, target_d, table_map, source_meta, target_meta, source.doclist[0]) target_d.idx = None target_doclist.append(target_d) target_doclist = webnotes.doclist(target_doclist) if postprocess: new_target_doclist = postprocess(source, target_doclist) if new_target_doclist: target_doclist = new_target_doclist return target_doclist def map_doc(source_doc, target_doc, table_map, source_meta, target_meta, source_parent=None): no_copy_fields = set(\ [d.fieldname for d in source_meta.get({"no_copy": 1, "parent": source_doc.doctype})] \ + [d.fieldname for d in target_meta.get({"no_copy": 1, "parent": target_doc.doctype})] \ + default_fields + table_map.get("field_no_map", [])) if table_map.get("validation"): for key, condition in table_map["validation"].items(): if condition[0]=="=": if source_doc.fields.get(key) != condition[1]: webnotes.msgprint(_("Cannot map because following condition fails: ") + key + "=" + cstr(condition[1]), raise_exception=webnotes.ValidationError) # map same fields target_fields = target_meta.get({"doctype": "DocField", "parent": target_doc.doctype}) for key in [d.fieldname for d in target_fields]: if key not in no_copy_fields: val = source_doc.fields.get(key) if val not in (None, ""): target_doc.fields[key] = val # map other fields field_map = table_map.get("field_map") if field_map: if isinstance(field_map, dict): for source_key, target_key in field_map.items(): val = source_doc.fields.get(source_key) if val not in (None, ""): target_doc.fields[target_key] = val else: for fmap in field_map: val = source_doc.fields.get(fmap[0]) if val not in (None, ""): target_doc.fields[fmap[1]] = val # map idx if source_doc.idx: target_doc.idx = source_doc.idx if "postprocess" in table_map: table_map["postprocess"](source_doc, target_doc, source_parent)