ERPNext Foundation ERPNext Cloud User Manual Blog Discuss Frappé* Donate

How to prevent deleting a row in child table, based on some conditions?


#1

Hi all,

any hint on how to prevent to delete raw in child table if it’s stored in another doc?

Let’s say i’d like to prevent deleting a raw from Items in Delivery Note if it’s stored in an Packing List Item …how is possible to do?

Thx


Disable "Remove" Button to stop deletion of child table records
#2

@JoEz,

You can use the before_tablefieldname_remove trigger and validate the condition, if conditions are not met then you can just throw an error to prevent the row deletion

Thanks,
Makarand


#3

@makarand_b big big thx!


#4

#5

#6

@makarand_b it seems to be not working properly.

the code i used for items field:

frappe.ui.form.on('Stock Note', {
	before_items_remove: function(frm, cdt, cdn) {
	 	console.log("test");
	}
})

Stock Note is a custom doctype

erpnext 8.6.1
frappe 8.6.0

What’s wrong?

Edit, found the problem …it’s needed to be in child table doctype:

frappe.ui.form.on('Stock Note Item', {
	before_items_remove: function(frm, cdt, cdn) {
	 	console.log("test");
	}
})

#7

#8

@makarand_b sorry for bothering, it seems before_items_remove is triggered but it not prevent the item to be removed from child table, even if a frappe.throw is raised.

See video:

http://recordit.co/USMHt1Tjsm

Here is the code:

frappe.ui.form.on('Quotation Item', {
	before_items_remove: function (frm, cdt, cdn) {
		frappe.call({
			method: "bon_bon_custom.api.check_item_in_picking",
			args: {
				quotation: frm.docname,
				qi_name: cdn
			},
			callback: function (r) {
				if (!r.exc && r.message) {
					if(r.message === "false") {
						frappe.throw(__("Item cannot be deleted"))
					}
				}
			}
		});
	}
});

Any hint on how to prevent row to be removed?


#9

#10

Can’t understand what i’m doing wrong, i found this code for Customize Form Fields and it seems to be working:

before_fields_remove: function(frm, doctype, name) {
		var row = frappe.get_doc(doctype, name);
		if(!(row.is_custom_field || row.__islocal)) {
			frappe.msgprint(__("Cannot delete standard field. You can hide it if you want"));
			throw "cannot delete custom field";
		}
	},

while following it’s not working:

frappe.ui.form.on('Quotation Item', {
	before_items_remove: function (frm, cdt, cdn) {
		frappe.call({
			method: "bon_bon_custom.api.check_item_in_picking",
			args: {
				quotation: frm.docname,
				qi_name: cdn
			},
			callback: function (r) {
				if (!r.exc && r.message) {
					if(r.message === "false") {
						frappe.msgprint(__("Item cannot be deleted"));
						throw "could not delete item";
					}
				}
			}
		});
	}
});

Any hint to find solution?

Thx


#11

I am facing the same problem as you, the trigger is really “triggered” after the row has allready been deleted.

Will check the code that you mention.

Regards


#12

@Pau_Rosello_Van_Scho, any news on this?


#13

For me in v8.6.4 it is failing even in Customize Form Field, the row is deleted before calling the trigger.

This is where the tigger is launched:

And it seems that it is an “asyncronous”, so the next line is executed before the trigger has been completed (as a long-shot I would say that this bug was introduced with the testing framework but I have no confirmation)


#14

Just updated and checked in 8.6.4, I can confirm it is failing on Customization Form Filed as well.

It seems you’re right about next line is executed before the trigger has been completed.

@makarand_b any hint on how to fix it?


#15

@makarand_b same problem here, do you have any news about this point ?


#16

same issue. @nabinhait Is there a solution for this? We want to be able to prevent a child table row from being deleted under certain conditions…


#17

I have been able to make this work with the following code:

frappe.ui.form.on("Team Registration", {
    before_team_table_remove: function(frm, dct, dcn){
      frappe.call({
		method: "avium_tournament.avium_tournament.doctype.registration.registration.check_remove_group_line",
		args: {
			dct: dct,
			dcn: dcn
		},
		always: function(r){
		    if(r.message.code == "st_judged"){
		       	frappe.throw(__("You cannot delete this row, as the template {0} has been judged already.", [r.message.template]))
		    }
		}
	  })
    }
});

Be careful as I am using the always method instead of the usual callback method

Regards!


#18

Thx, I’ll test it on my use case


#19

frappe.ui.form.on(‘Sales Campaign Agencies’,{
sales_agencies_remove:function(frm,cdt,cdn){
frappe.call({
method:‘property_sales.property_sales.doctype.property_sales_campaign.property_sales_campaign.getagencydata’,
freeze: true,
args: {
“parent”: frm.doc.name,
“name”: cdn
},
always: function®{
console.log®
if(r.message.length>1){
frappe.msgprint(“You cannot delete this ro1w”);
frm.reload_doc()

	    }
	}
  })
}

});

use frm.reload_doc() if condition true else item will delete