My use-case is to save the records in the child table based on the field value like below:
Insert: After performing validations , insert those records in the child table
Update: After performing validations , update those records in the child table for the date mentioned in the date field
For this I was able to write the client script but not sure of how to handle this at server side in before_save or save ?
handle_operation: function(frm) {
if (frm.operation === 'Insert') {
frm.trigger("populate_child_rows_insert");
} else if (frm.operation === 'Update') {
frm.trigger("populate_child_rows_update");
}
}
Server side:
def before_save(self):
print("child: ", self.get("child_table_field"))
print("operation: ", self.custom_operation)
for child in self.get("child_table_field"):
if self.custom_operation == "Insert":
print("Inside Insert")
pass
elif self.custom_operation == "Update":
print("Inside Update")
pass
Append with empty braces was not working (going in infinite loop with unsaved child rows in logs) but below code was working. But it is still overriding the existing rows in the child table.
class ParentTable(Document):
def before_save(self):
child_rows = self.get("child_table_field")
print("child rows: ", child_rows)
print("operation: ", self.custom_operation)
if self.custom_operation == "Insert":
insert_childs = []
print("Inside Insert")
for record in child_rows:
print("child row: ", record)
insert_childs.append({
"task": record.task,
"date": record.date
})
self.set('child_table_field', [])
for record in insert_childs:
print("child row insert: ", record)
self.append("child_table_field", record)
elif self.custom_operation == "Update":
self.populate_child_rows_update(child_rows)
print("Inside Update")
pass
A little digging I found below code in document.py. Not sure if it is relevant or not.
Here I see we are deleting the child records before inserting it. Can I modify the ignore_children_type flag somehow in the code to avoid deletion ?
def update_child_table(self, fieldname: str, df: Optional["DocField"] = None):
"""sync child table for given fieldname"""
df: "DocField" = df or self.meta.get_field(fieldname)
all_rows = self.get(df.fieldname)
# delete rows that do not match the ones in the document
# if the doctype isn't in ignore_children_type flag and isn't virtual
if not (
df.options in (self.flags.ignore_children_type or ())
or frappe.get_meta(df.options).is_virtual == 1
):
existing_row_names = [row.name for row in all_rows if row.name and not row.is_new()]
tbl = frappe.qb.DocType(df.options)
qry = (
frappe.qb.from_(tbl)
.where(tbl.parent == self.name)
.where(tbl.parenttype == self.doctype)
.where(tbl.parentfield == fieldname)
.delete()
)
if existing_row_names:
qry = qry.where(tbl.name.notin(existing_row_names))
qry.run()
# update / insert
for d in all_rows:
d: Document
d.db_update()