Childtable Data Fetching in HTML field

Hi Community !!

I have created one doctype called “CSP Progress Report”. In that doctype, i have added one html field called “csp_report”. I have Task doctype, In that doctype , i have added one childtable called “Action Items” with fieldname “custom_action_item”. Now, i want the list of task data and their childtable data should be shown as a table in “CSP Progress Report” doctype html field “csp_report”. for eg: In task doctype, there are 3 tasks , each tasks has 2 rows in childtable. so it should show like 1st row show task 1 with ChildT row 1 and 2nd row childT row 2 but row 2 dont repeat the task 1 details. next 3rd row task 2 details with their ct row 1, etcc… . I used server script for call the datas from Task doctype.because there is permission issue when i use only client script.

I attached a below code for reference. Please suggest me any solution ASAP !!!.

Client Script:

frappe.ui.form.on('CSP Progress Report', {
    onload(frm) {
        // Call the server script to generate the task report
        frappe.call({
            method: 'cspr',
            args: {
                csp_report_name: frm.doc.name
            },
            callback: function(response) {
                // Set the HTML report content in the 'csp_report' field
                frm.set_df_property('csp_report', 'options', response.message);
                frm.refresh_field('csp_report');
            }
        });
    }
});

Server Script:


def generate_task_report(csp_report_name):
    # Fetch the CSP Progress Report document to get its context
    csp_report = frappe.get_doc('CSP Progress Report', csp_report_name)
    
    # Query Tasks and include their child table data (custom_action_item)
    tasks = frappe.get_all('Task', fields=['name', 'subject', 'custom_country', 'custom_region', 
                                            'custom_type_of_period', 'custom_month', 'custom_week'], 
                           filters={'docstatus': 1})  # Assuming you want only submitted tasks

    # Initialize the HTML content
    html = '''
    <style>
        table {
            width: 100%;
            border-collapse: collapse;
            font-size: 10px;
            border: 1px solid black; 
        }
        th, td {
            padding: 8px 10px;
            text-align: left;
            border: 1px solid black;
            word-wrap: break-word;
        }
        th {
            background-color: #003366;
            color: white;
            font-weight: bold;
            text-transform: uppercase;
            font-size: 12px;
        }
        tr:nth-child(even) {
            background-color: #f9f9f9;
        }
        tr:hover {
            background-color: #f1f1f1;
        }
        td[colspan] {
            background-color: #f9f9f9;
        }
        .empty-cell {
            text-align: center;
            color: #777;
        }
    </style>
    <table>
        <thead>
            <tr>
                <th>Task ID</th>
                <th>Subject</th>
                <th>Country</th>
                <th>Region</th>
                <th>Quarter</th>
                <th>Month</th>
                <th>Week</th>
                <th>Action Item</th>
                <th>Urgency</th>
                <th>Due Date</th>
                <th>Progress Status</th>
                <th>Remarks</th>
                <th>Status</th>
                <th>Responsible Person</th>
                <th>Action Items</th>
            </tr>
        </thead>
        <tbody>
    '''

    # Iterate through each task and fetch its child table (action items)
    for task in tasks:
        # Fetch the child table data (custom_action_item)
        child_data = frappe.get_all('Action Items', filters={'parent': task['name']}, fields=['action_item', 'urgency', 'due_date', 
                                                                                                  'progress_status', 'remarksif_any', 'status', 'responsible_person', 'action_items'])

        # Add the task data in the first row, then add each action item for that task
        for index, item in enumerate(child_data):
            html += f'''
            <tr>
                {f'<td>{task["name"]}</td>' if index == 0 else '<td class="empty-cell"></td>'}
                {f'<td>{task["subject"]}</td>' if index == 0 else '<td class="empty-cell"></td>'}
                {f'<td>{task["custom_country"]}</td>' if index == 0 else '<td class="empty-cell"></td>'}
                {f'<td>{task["custom_region"]}</td>' if index == 0 else '<td class="empty-cell"></td>'}
                {f'<td>{task["custom_type_of_period"]}</td>' if index == 0 else '<td class="empty-cell"></td>'}
                {f'<td>{task["custom_month"]}</td>' if index == 0 else '<td class="empty-cell"></td>'}
                {f'<td>{task["custom_week"]}</td>' if index == 0 else '<td class="empty-cell"></td>'}
                <td>{item['action_item']}</td>
                <td>{item['urgency']}</td>
                <td>{item['due_date']}</td>
                <td>{item['progress_status']}</td>
                <td>{item['remarksif_any']}</td>
                <td>{item['status']}</td>
                <td>{item['responsible_person']}</td>
                <td>{item['action_items']}</td>
            </tr>
            '''
    
    # Close the table tag
    html += '</tbody></table>'

    # Update the CSP Progress Report document with the generated HTML
    csp_report.csp_report = html
    csp_report.save()

    return csp_report.csp_report  # Return the HTML content to display it if needed

below image shows CSP Progress Report Doctype. Added only one field.

When i use html field inside the task doctype , it should show their particular document data. but the client asking to show full report that contains all the tasks. below image is only show that particular document details inside the task doctype.

Task = CSP , i changed the label.

frappe.ui.form.on(‘Parent Doc’, {
refresh: function(frm) {
// Call the function to fetch and display data from the child table
display_child_table_data(frm);
}
});

function display_child_table_data(frm) {
// Prepare the HTML structure
let html = <table class="table table-bordered"> <thead> <tr> <th>Item Name</th> <th>Quantity</th> <th>Amount</th> </tr> </thead> <tbody>;

// Loop through the child table rows and populate HTML
frm.doc.child_table_fieldname.forEach(row => {
    html += `<tr>
        <td>${row.item_name || ''}</td>
        <td>${row.qty || ''}</td>
        <td>${row.amount || ''}</td>
    </tr>`;
});

html += `</tbody></table>`;

// Set the HTML in the custom HTML field
frm.fields_dict.custom_html_field.$wrapper.html(html);

}