Try ERPNext Try Frappe Cloud Buy Support Partners Foundation

Child Table Else If conditions

  1. I have a Doctype called : Plan Management Invoice
  2. On Invoice there is a child table called : Services Support List
  3. Services Support list has 7 fields:
    1. Select Price type ( A select field with Strings as options e.g “Price Limit
      National Non Remote MMM 1 to 5”)
    2. Enter Quantity (Float type)
    3. Total (Currency Type)
    4. Select Service (Link type field - Linked to a doctype “Service” with Price
      Types)
    5. Price Limit National Non Remote MMM 1 to 5 ( A currency field fetched from Doctype “Service” - Fetches Perfectly fine)
    6. Price Limit National Non Remote MMM 1 to 6 (similar to field 5 - a currency field fetched from doctype “Service”)
    7. There are multiple similar fields like 5 and 6 of currency types which are being fetched from the doctype “Service”. They all fetch perfectly fine.

Now what I wanted to do was to add a script, which would choose a rate based on what the user selects Price type i.e (a basic algo - not the actual code)

if (doc.price_type == “Price Limit National Non Remote MMM 1 to 5”){
doc.rate = doc.price_limit_nt_satas_wa_mmm_1_to_5;
}

What this would do is make rate = price_limit_nt_satas_wa_mmm_1_to_5 (the fetched price).

However my code does not work, Any help is appreciated. Here is my code:

 frappe.ui.form.on("Services Support List", {
    rate:function(frm, cdt, cdn){
    var d = locals[cdt][cdn];
    var total = 0;
    frappe.model.set_value(d.doctype, d.name, "total_delivered", d.quantity * d.rate);
    frm.doc.services_support_list.forEach(function(d) {
    		if (d.price_limit_type == "Price Limit NT SATAS WA MMM 1 to 5"){
    				 d.rate = d.price_limit_nt_satas_wa_mmm_1_to_5;
    		 }
    		 else if (d.price_limit_type == "Price Limit ACT NSWQLD VIC MMM 1 to 5"){
    				 d.rate = d.price_limit_act_nswqld_vic_mmm_1_to_5;
    		 }
    	 else if (d.price_limit_type == "Price Limit National Non Remote MMM 1 to 5"){
    				 d.rate = d.price_limit_national_non_remote_mmm_1_to_5;

    	 }
    	 else if (d.price_limit_type == "Price Limit National Remote MMM 6"){
    				 d.rate = d.price_limit_national_remote_mmm_6;

    	 }
    	 else{
    				 d.rate = d.price_limit_national_very_remote_mmm_7;}
    				 total += d.total_delivered;
    			 });
    frm.set_value('grand_total', total);

rate : rate field in child table
total_delivered: field in child table (found by rate * quantity)
grand_total: field in parent table which is the sum of all total_delivered from child table

Here are my attached screenshots

Hello.

If you want to change child table’s rate, use frappe.model.set_value.

Regards,

Ivan

frappe.model.set_value(d.doctype, d.name, "total_delivered", d.quantity * d.rate);

It’s already in the code

first make sure the code is in file name plan_management_ invoice.js or in custom script assigned to doctype Plan Management Invoice

update the code as below

frappe.ui.form.on("Services Support List", {
    price_limit_type:function(frm, cdt, cdn){
		var d = locals[cdt][cdn];
		var total = 0;
		frm.doc.services_support_list.forEach(function(d) {
			if (d.price_limit_type == "Price Limit NT SATAS WA MMM 1 to 5"){
				d.rate = d.price_limit_nt_satas_wa_mmm_1_to_5;
			}
			else if (d.price_limit_type == "Price Limit ACT NSWQLD VIC MMM 1 to 5"){
				d.rate = d.price_limit_act_nswqld_vic_mmm_1_to_5;
			}
			else if (d.price_limit_type == "Price Limit National Non Remote MMM 1 to 5"){
				d.rate = d.price_limit_national_non_remote_mmm_1_to_5;
			}
			else if (d.price_limit_type == "Price Limit National Remote MMM 6"){
				d.rate = d.price_limit_national_remote_mmm_6;
			}
			else{
				d.rate = d.price_limit_national_very_remote_mmm_7;
			}
			frappe.model.set_value(d.doctype, d.name, "total_delivered", d.quantity * d.rate);
			total += d.total_delivered;
		});			
		frm.set_value('grand_total', total);
	}
})

It is

Doesn’t work. It does not calculate the total_delivered for the child table, nor the grand_total

is it possible to provide the following screenshot?

  1. doctype definition, especially the fields definition of the header and child , the json file also okay
  2. the script file or custom script code. if custom script provide the screen shot also.

also make sure the browser refreshed.

maybe the final resolution is to grant temporary system access.

The problem lies elsewhere. I made a simple doctype with two fields:

  1. select_type (a select type field with 3 options (A,B,C)
  2. selected_type (a data field to show select_type in)

I wrote this custom script:

frappe.ui.form.on("Script Test Doctype", {
	refresh(frm) {
		if (doc.select_type == "A" ){
		    doc.selected_type = "Type A selected";
		}
		else if (doc.select_type == "B" ){
		    doc.selected_type = "Type B selected";
		}
		else if (doc.select_type == "C" ){
		    doc.selected_type = "Type C selected";
		}
		else{
		    doc.selected_type = "No type selected";
		}
	}
});

This doesn’t work either. I’m guessing the way it’s validating the IF condition is flawed. It does not validate the IF condition. Here’s how I know this, I wrote the following code to check if the IF condition validates i.e : if (doc.select ==“A”)

code:

frappe.ui.form.on("Script Test Doctype", {
	refresh(frm) {
		if (doc.select_type == "A" ){
		    frappe.msgprint(__("Field A Selected"));
		}
		else if (doc.select_type == "B" ){
		    frappe.msgprint(__("Field B Selected"));
		}
		else if (doc.select_type == "C" ){
		    frappe.msgprint(__("Field C Selected"));
		}
		else{
		    frappe.msgprint(__("No Field Selected"));
		    }
	}
});

This does not work either, implying that the fault lies in the IF condition validation . Kinda wanna bash my laptop in the wall :slight_smile:

I read the whole thread. According to that logic I can define the IF conditions in the parent doctype and fetch into the other doctype from there. Here is what I did:

I created a doctype with the name “Delete” with the following fields:

  1. select_type (select field with 3 options (A,B,C)
  2. selected_type (data field to set value to - made as read only)
  3. chosen1 (a data field)
  4. chosen2 (another data field)
  5. chosen3 (another data field)
  6. nonechosen (another data field)

This is the code I wrote for the doctype :

frappe.ui.form.on("Delete", {
	refresh(frm) {
		if (frm.doc.select_type == "A" ){
		    cur_frm.set_value("selected_type", chosen1);
		}
		else if (frm.doc.select_type == "B" ){
		   cur_frm.set_value("selected_type", chosen2);
		}
		else if (frm.doc.select_type == "C" ){
		   cur_frm.set_value("selected_type", chosen3);
		}
		else{
		    cur_frm.set_value("selected_type", nonechosen);
		    }
	}
}); 

Now even after creating a document and populating the fields, it was not setting the value of selected_type to any of the fields. The issue lies in the condition validation as i’ve shown in examples before this.

A workaround i’ve figured is to use Switches instead of IF conditions. The switches work for a parent doctype i.e:

frappe.ui.form.on("Delete", {
    refresh(frm) {
        switch(frm.doc.select_type) {
            case 'A':
                frm.set_value('selected_type', frm.doc.chosen1);
                break;
            case 'B':
                frm.set_value('selected_type', frm.doc.chosen2);
                break;
            case 'C':
                frm.set_value('selected_type', frm.doc.chosen3); 
        }
    }
    
    
});
  1. Doctype is called delete
  2. select_type is the select field (options: A,B,C)
  3. chosen1, chosen2, chosen3 are three currency fields (I populated the data)
  4. selected_type is the field the values are set based on select_type.

This works for a parent doctype, however as soon as create a child table(which links to Doctype “Delete” and fetches all necessary fields) and add it to another Parent the code doesn’t work.

Here is my code for the Parent doctype called (Delete Switch Test), child table which links to Delete is (Switch Test Delete) :

frappe.ui.form.on("Delete Switch Test", {
	refresh(frm) {
		// your code here
	}
});

frappe.ui.form.on("Switch Test Child", {
	rate:function(frm, cdt, cdn){
		var d = locals[cdt][cdn];
		frm.doc.switch_test_child.forEach(function(d) {
		    switch(d.select_type) {
            case 'A':
                frappe.model.set_value(d.doctype, d.name, "money_selected", d.type_1);
                break;
            case 'B':
               frappe.model.set_value(d.doctype, d.name, "money_selected", d.type_2);
                break;
            case 'C':
                frappe.model.set_value(d.doctype, d.name, "money_selected", d.type_3);
                break;
        }
		});
	}
});

Not much but this is something to work with. Is there any way I can get this to work with a child table ?

As a general rule, when I find myself with too many conditionals, I prefer to use function lookup:

// Functions
const do_A_stuff = (ctx) => `Did A's stuff with '${ctx.parm}'.`
const do_B_or_C_stuff = (ctx) => `Did B or C's stuff with '${ctx.parm}'.`

// Look up
const dependsOn = {
  A: do_A_stuff,
  "B or C": do_B_or_C_stuff
}

// Using look up
const work = (status, context) => {
  //   Stuff done   depends on status with context
  const stuffDone = dependsOn[status](context)
  console.log(stuffDone)
}

// Testing different cases
const test = () => {
  work('A', { parm: 'foo'})
  work('B or C', { parm: 'bar'})
}

Output:

"Did A's stuff with 'foo'."
"Did B or C's stuff with 'bar'."

I find this much more readable, especially if I play with name hacks like “Stuff done depends on status with context”.

Possibly this will help with your case. I’ll be interested to know.