|
|
@@ -19,6 +19,8 @@ from frappe.model import no_value_fields, table_fields |
|
|
|
|
|
|
|
INVALID_VALUES = ["", None] |
|
|
|
MAX_ROWS_IN_PREVIEW = 10 |
|
|
|
INSERT = "Insert New Records" |
|
|
|
UPDATE = "Update Existing Records" |
|
|
|
|
|
|
|
# pylint: disable=R0201 |
|
|
|
class Importer: |
|
|
@@ -38,7 +40,7 @@ class Importer: |
|
|
|
else: |
|
|
|
self.data_import = None |
|
|
|
|
|
|
|
self.import_type = self.import_type or 'Insert New Records' |
|
|
|
self.import_type = self.import_type or INSERT |
|
|
|
|
|
|
|
self.header_row = None |
|
|
|
self.data = None |
|
|
@@ -259,7 +261,7 @@ class Importer: |
|
|
|
"fieldtype": "Data", |
|
|
|
"fieldname": "name", |
|
|
|
"label": "ID", |
|
|
|
"reqd": self.import_type == "Update Existing Records", |
|
|
|
"reqd": self.import_type == UPDATE, |
|
|
|
"parent": doctype, |
|
|
|
} |
|
|
|
) |
|
|
@@ -606,7 +608,7 @@ class Importer: |
|
|
|
|
|
|
|
def parse_doc(doctype, docfields, values, row_number): |
|
|
|
doc = frappe._dict() |
|
|
|
if self.import_type == 'Insert New Records': |
|
|
|
if self.import_type == INSERT: |
|
|
|
# new_doc returns a dict with default values set |
|
|
|
doc = frappe.new_doc(doctype, as_dict=True) |
|
|
|
|
|
|
@@ -622,18 +624,37 @@ class Importer: |
|
|
|
if value: |
|
|
|
doc[df.fieldname] = self.parse_value(value, df) |
|
|
|
|
|
|
|
is_table = frappe.get_meta(doctype).istable |
|
|
|
is_update = self.import_type == UPDATE |
|
|
|
if is_table and is_update and doc.get("name") in INVALID_VALUES: |
|
|
|
# for table rows being inserted in update |
|
|
|
# create a new doc with defaults set |
|
|
|
new_doc = frappe.new_doc(doctype, as_dict=True) |
|
|
|
new_doc.update(doc) |
|
|
|
doc = new_doc |
|
|
|
|
|
|
|
check_mandatory_fields(doctype, doc, row_number) |
|
|
|
return doc |
|
|
|
|
|
|
|
def check_mandatory_fields(doctype, doc, row_number): |
|
|
|
'''If import type is Insert: |
|
|
|
"""If import type is Insert: |
|
|
|
Check for mandatory fields (except table fields) in doc |
|
|
|
if import type is Update: |
|
|
|
Check for name field or autoname field in doc |
|
|
|
''' |
|
|
|
|
|
|
|
if self.import_type == 'Update Existing Records': |
|
|
|
id_field = self.get_id_field() |
|
|
|
""" |
|
|
|
meta = frappe.get_meta(doctype) |
|
|
|
if self.import_type == UPDATE: |
|
|
|
if meta.istable: |
|
|
|
# when updating records with table rows, |
|
|
|
# there are two scenarios: |
|
|
|
# 1. if row 'name' is provided in the template |
|
|
|
# the table row will be updated |
|
|
|
# 2. if row 'name' is not provided |
|
|
|
# then a new row will be added |
|
|
|
# so we dont need to check for mandatory |
|
|
|
return |
|
|
|
|
|
|
|
id_field = self.get_id_field(doctype) |
|
|
|
if doc.get(id_field.fieldname) in INVALID_VALUES: |
|
|
|
self.warnings.append( |
|
|
|
{ |
|
|
@@ -643,7 +664,6 @@ class Importer: |
|
|
|
) |
|
|
|
return |
|
|
|
|
|
|
|
meta = frappe.get_meta(doctype) |
|
|
|
fields = [ |
|
|
|
df |
|
|
|
for df in meta.fields |
|
|
@@ -720,19 +740,17 @@ class Importer: |
|
|
|
) |
|
|
|
elif mandatory_table_fields: |
|
|
|
fields_string = ", ".join([df.label for df in mandatory_table_fields]) |
|
|
|
self.warnings.append( |
|
|
|
{ |
|
|
|
"row": first_row[0], |
|
|
|
"message": _("There should be atleast one row for the following tables: {0}").format(fields_string), |
|
|
|
} |
|
|
|
message = _("There should be atleast one row for the following tables: {0}").format( |
|
|
|
fields_string |
|
|
|
) |
|
|
|
self.warnings.append({"row": first_row[0], "message": message}) |
|
|
|
|
|
|
|
return doc, rows, data[len(rows) :] |
|
|
|
|
|
|
|
def process_doc(self, doc): |
|
|
|
if self.import_type == "Insert New Records": |
|
|
|
if self.import_type == INSERT: |
|
|
|
return self.insert_record(doc) |
|
|
|
elif self.import_type == "Update Existing Records": |
|
|
|
elif self.import_type == UPDATE: |
|
|
|
return self.update_record(doc) |
|
|
|
|
|
|
|
def insert_record(self, doc): |
|
|
@@ -780,7 +798,7 @@ class Importer: |
|
|
|
d.missing_values.remove(link_value) |
|
|
|
|
|
|
|
def update_record(self, doc): |
|
|
|
id_fieldname = self.get_id_fieldname() |
|
|
|
id_fieldname = self.get_id_fieldname(self.doctype) |
|
|
|
id_value = doc[id_fieldname] |
|
|
|
existing_doc = frappe.get_doc(self.doctype, id_value) |
|
|
|
existing_doc.flags.via_data_import = self.data_import.name |
|
|
@@ -837,8 +855,6 @@ class Importer: |
|
|
|
df=col.df, |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_eta(self, current, total, processing_time): |
|
|
|
remaining = total - current |
|
|
|
eta = processing_time * remaining |
|
|
@@ -855,18 +871,14 @@ class Importer: |
|
|
|
mandatory_fields_count += 1 |
|
|
|
return mandatory_fields_count == 1 |
|
|
|
|
|
|
|
def get_id_fieldname(self): |
|
|
|
return self.get_id_field().fieldname |
|
|
|
def get_id_fieldname(self, doctype): |
|
|
|
return self.get_id_field(doctype).fieldname |
|
|
|
|
|
|
|
def get_id_field(self): |
|
|
|
autoname_field = self.get_autoname_field(self.doctype) |
|
|
|
def get_id_field(self, doctype): |
|
|
|
autoname_field = self.get_autoname_field(doctype) |
|
|
|
if autoname_field: |
|
|
|
return autoname_field |
|
|
|
return frappe._dict({ |
|
|
|
'label': 'ID', |
|
|
|
'fieldname': 'name', |
|
|
|
'fieldtype': 'Data' |
|
|
|
}) |
|
|
|
return frappe._dict({"label": "ID", "fieldname": "name", "fieldtype": "Data"}) |
|
|
|
|
|
|
|
def get_autoname_field(self, doctype): |
|
|
|
meta = frappe.get_meta(doctype) |
|
|
|