I need a client script for frappe that does the following:
There is a doctype called “Disciplinary Action” which has two child tables, “Disciplinary History” and “Disciplinary Charges”.
The “Disciplinary Action” doctype has fields called “accused”, “outcome_date” and “outcome”.
The Child Table called “Disciplinary Charges” has the following two fields: “code_item” and “charge” and is a Table Fild in the “Disciplinary Action” DocType called “final_charges”.
The Child Table called “Disciplinary History” has the following four fields: “disc_action”, “date”, “charges” and “sanction” and is a table field in the “Disciplinary Action” DocType called “previous_disciplinary_outcomes”.
Once the field “accused” in the “Disciplinary Action” DocType has been completed, I want to populate the “Disciplinary History” Child Table in the “Disciplinary Action” DocType with the following data:
“disc_action” should refer to all other documents of the “Disciplinary Action” doctype that has the same “accused”.
“date” should get the “outcome_date” field for each of those documents.
“charges” should list the “charge” fields from the “Disciplinary Charge” Child Table from each of those documents.
“sanction” should list the “outcome” field from each of those documents.
I have written a client script that should do this:
frappe.ui.form.on('Disciplinary Action', {
accused: function(frm) {
// Clear the Disciplinary History table first
frm.clear_table('previous_disciplinary_outcomes');
// Check if accused field is filled
if (frm.doc.accused) {
// Fetch all Disciplinary Action records with the same accused
frappe.call({
method: 'frappe.client.get_list',
args: {
doctype: 'Disciplinary Action',
filters: {
accused: frm.doc.accused,
name: ['!=', frm.doc.name] // Exclude the current document
},
fields: ['name', 'outcome_date', 'outcome']
},
callback: function(response) {
const disciplinary_actions = response.message;
if (disciplinary_actions) {
// Create a promise to handle asynchronous calls
const promises = disciplinary_actions.map(action => {
return new Promise((resolve, reject) => {
// Fetch the charges from Disciplinary Charges child table
frappe.call({
method: 'frappe.client.get_list',
args: {
doctype: 'Disciplinary Charges',
filters: {
parent: action.name
},
fields: ['charge']
},
callback: function(charges_response) {
const charges = charges_response.message.map(charge => charge.charge).join(', ');
// Add a new row to the Disciplinary History table
let new_row = frm.add_child('previous_disciplinary_outcomes');
new_row.disc_action = action.name || '';
new_row.date = action.outcome_date || '';
new_row.charges = charges || '';
new_row.sanction = action.outcome || '';
resolve();
},
error: function(err) {
console.error("Error fetching disciplinary charges: ", err);
frappe.msgprint({
title: __('Error'),
indicator: 'red',
message: __('Error fetching disciplinary charges: ') + err.message
});
reject(err);
}
});
});
});
// Wait for all promises to complete
Promise.all(promises).then(() => {
// Refresh the table once all rows are added
frm.refresh_field('previous_disciplinary_outcomes');
}).catch((err) => {
console.error("Error processing disciplinary actions: ", err);
});
}
},
error: function(err) {
console.error("Error fetching disciplinary actions: ", err);
frappe.msgprint({
title: __('Error'),
indicator: 'red',
message: __('Error fetching disciplinary actions: ') + err.message
});
}
});
}
}
});
When I try and use this DocType, I get permission errors, however I am admin on a development instance and have full privileges, that means somewhere in my script I am exceeding the permissions of Frappe, I need to understand where I am going wrong here.