diff --git a/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.json b/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.json index a20ab76b0b..e5304bdb45 100644 --- a/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.json +++ b/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.json @@ -7,15 +7,13 @@ "field_order": [ "local_fieldname", "remote_fieldname", - "has_default_value", "default_value", "column_break_5", - "is_child_table", - "child_table_mapping" + "mapping_type", + "mapping" ], "fields": [ { - "depends_on": "eval:!doc.has_default_value;", "fieldname": "remote_fieldname", "fieldtype": "Data", "in_list_view": 1, @@ -28,40 +26,32 @@ "label": "Local Fieldname", "reqd": 1 }, - { - "default": "0", - "fieldname": "is_child_table", - "fieldtype": "Check", - "label": "Is Child Table" - }, - { - "depends_on": "eval: doc.is_child_table == 1", - "fieldname": "child_table_mapping", - "fieldtype": "Link", - "label": "Child Table Mapping", - "options": "Document Type Mapping" - }, { "fieldname": "column_break_5", "fieldtype": "Column Break" }, { - "default": "0", - "description": "Check this If the value of the field is a default value and not to be fetched from the remote DocType's field", - "fieldname": "has_default_value", - "fieldtype": "Check", - "label": "Has Default Value" - }, - { - "depends_on": "eval:doc.has_default_value;", "fieldname": "default_value", "fieldtype": "Data", "label": "Default Value" + }, + { + "fieldname": "mapping_type", + "fieldtype": "Select", + "label": "Mapping Type", + "options": "\nChild Table\nDocument" + }, + { + "depends_on": "eval:doc.mapping_type;", + "fieldname": "mapping", + "fieldtype": "Link", + "label": "Mapping", + "options": "Document Type Mapping" } ], "istable": 1, "links": [], - "modified": "2020-03-16 13:42:41.104161", + "modified": "2020-03-16 14:54:33.546135", "modified_by": "Administrator", "module": "Event Streaming", "name": "Document Type Field Mapping", diff --git a/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py b/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py index e61f2d67d6..5a7d55bc81 100644 --- a/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py +++ b/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py @@ -9,27 +9,52 @@ from frappe.model.document import Document class DocumentTypeMapping(Document): - def get_mapped_doc(self, update): - doc = frappe._dict(json.loads(update)) + def get_mapped_update(self, doc, producer_site): remote_fields = [] + # list of tuples (local_fieldname, dependent_doc) + dependencies = [] + for mapping in self.field_mapping: if doc.get(mapping.remote_fieldname): - if mapping.is_child_table: - doc[mapping.local_fieldname] = self.get_mapped_child_table_docs(mapping.child_table_mapping, doc[mapping.remote_fieldname]) + if mapping.mapping_type == 'Document': + dependency = self.get_mapped_dependency(mapping, producer_site, doc.get(mapping.remote_fieldname), mapping.remote_fieldname) + dependencies.append((mapping.local_fieldname, dependency)) + + if mapping.mapping_type == 'Child Table': + doc[mapping.local_fieldname] = self.get_mapped_child_table_docs(mapping.child_table_mapping, doc[mapping.remote_fieldname]) else: # copy value into local fieldname key and remove remote fieldname key doc[mapping.local_fieldname] = doc[mapping.remote_fieldname] remote_fields.append(mapping.remote_fieldname) - elif mapping.has_default_value: + if not doc.get(mapping.local_fieldname) and mapping.default_value: doc[mapping.local_fieldname] = mapping.default_value #remove the remote fieldnames for field in remote_fields: doc.pop(field, None) - doc['doctype'] = self.local_doctype - return frappe.as_json(doc) + + mapped_update = {'doc': frappe.as_json(doc)} + if len(dependencies): + mapped_update['dependencies'] = dependencies + return mapped_update + + + def get_mapped_dependency(self, mapping, producer_site, dependent_field_val, dependent_field): + inner_mapping = frappe.get_doc('Document Type Mapping', mapping.mapping) + filters = {} + for pair in inner_mapping.field_mapping: + if pair.remote_fieldname == dependent_field: + filters[pair.remote_fieldname] = dependent_field_val + break + + matching_docs = producer_site.get_doc(inner_mapping.remote_doctype, filters=filters) + if len(matching_docs): + remote_docname = matching_docs[0].get('name') + remote_doc = producer_site.get_doc(inner_mapping.remote_doctype, remote_docname) + doc = inner_mapping.get_mapped_update(remote_doc, producer_site).get('doc') + return doc def get_mapped_child_table_docs(child_map, table_entries): diff --git a/frappe/event_streaming/doctype/event_producer/event_producer.py b/frappe/event_streaming/doctype/event_producer/event_producer.py index 6298e6389b..ca0dbc098c 100644 --- a/frappe/event_streaming/doctype/event_producer/event_producer.py +++ b/frappe/event_streaming/doctype/event_producer/event_producer.py @@ -93,6 +93,7 @@ class EventProducer(Document): if self.is_producer_online(): producer_site = get_producer_site(self.producer_url) event_consumer = producer_site.get_doc('Event Consumer', get_url()) + event_consumer = frappe._dict(event_consumer) if event_consumer: config = event_consumer.consumer_doctypes event_consumer.consumer_doctypes = [] @@ -172,7 +173,7 @@ def pull_from_node(event_producer): mapping = mapping_config.get(update.ref_doctype) if mapping: update.mapping = mapping - update = get_mapped_update(update) + update = get_mapped_update(update, producer_site) if not update.update_type == 'Delete': update.data = json.loads(update.data) @@ -225,8 +226,13 @@ def set_insert(update, producer_site, event_producer): return doc = frappe.get_doc(update.data) - if not update.mapping: + if update.mapping: + dependencies_created = sync_mapped_dependencies(update.dependencies, producer_site) + for fieldname, value in iteritems(dependencies_created): + doc.update({ fieldname : value }) + else: sync_dependencies(doc, producer_site) + if update.use_same_name: doc.insert(set_name=update.docname, set_child_names=False) else: @@ -346,6 +352,7 @@ def sync_dependencies(document, producer_site): child_table = doc.get(df.fieldname) for entry in child_table: child_doc = producer_site.get_doc(entry.doctype, entry.name) + child_doc = frappe._dict(child_doc) set_dependencies(child_doc, frappe.get_meta(entry.doctype).get_link_fields(), producer_site) def sync_link_dependencies(doc, link_fields, producer_site): @@ -397,6 +404,15 @@ def sync_dependencies(document, producer_site): dependencies[document] = False +def sync_mapped_dependencies(dependencies, producer_site): + dependencies_created = {} + for entry in dependencies: + doc = frappe._dict(json.loads(entry[1])) + doc = frappe.get_doc(doc).insert(set_child_names=False) + dependencies_created[entry[0]] = doc.name + + return dependencies_created + def log_event_sync(update, event_producer, sync_status, error=None): """Log event update received with the sync_status as Synced or Failed""" doc = frappe.new_doc('Event Sync Log') @@ -417,11 +433,15 @@ def log_event_sync(update, event_producer, sync_status, error=None): doc.insert() -def get_mapped_update(update): +def get_mapped_update(update, producer_site): """get the new update document with mapped fields""" mapping = frappe.get_doc('Document Type Mapping', update.mapping) if update.update_type != 'Delete': - update.data = mapping.get_mapped_doc(update.data) + doc = frappe._dict(json.loads(update.data)) + mapped_update = mapping.get_mapped_update(doc, producer_site) + update.data = mapped_update.get('doc') + update.dependencies = mapped_update.get('dependencies', None) + update.ref_doctype = mapping.local_doctype return update diff --git a/frappe/frappeclient.py b/frappe/frappeclient.py index b4bb9e0dc9..92ec8edf14 100644 --- a/frappe/frappeclient.py +++ b/frappe/frappeclient.py @@ -199,8 +199,9 @@ class FrappeClient(object): res = self.session.get(self.url + "/api/resource/" + doctype + "/" + name, params=params, verify=self.verify, headers=self.headers) + print('==================res', res.text, filters) - return frappe._dict(self.post_process(res)) + return self.post_process(res) def rename_doc(self, doctype, old_name, new_name): '''Rename remote document