Childtable Data fetch from everyparent doctype to 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.

frappe.ui.form.on('CSP Progress Report', {
    onload(frm) {
        frappe.call({
            method: 'csprr',
            callback: function(response) {
                // Set the generated HTML content in the 'csp_report' field
                frm.set_df_property('csp_report', 'options', response.message);
                frm.refresh_field('csp_report');
            }
        });
    }
});

def generate_csp_report():
    # Fetch all Task records with necessary fields
    tasks = frappe.db.get_list('Task', fields=[
        'name', 'subject', 'custom_country', 'custom_region',
        'custom_type_of_period', 'custom_month', 'custom_week'
    ])
    
    # Initialize the HTML table
    html = """
    <style>
        table {
            width: 100%;
            border-collapse: collapse;
            font-size: 10px;
            border: 1px solid black;
        }
        th, td {
            padding: 10px;
            text-align: left;
            border: 1px solid black;
        }
        th {
            background-color: #003366;
            color: white;
            font-weight: bold;
        }
        tr:nth-child(even) {
            background-color: #f9f9f9;
        }
        tr:hover {
            background-color: #f1f1f1;
        }
        td[colspan] {
            background-color: #f9f9f9;
        }
    </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>
    """
    
    # Loop through each Task record
    for task in tasks:
        # Fetch associated Action Items for the current Task
        action_items = frappe.db.get_list('Action Items', filters={'task': task['name']}, fields=[
            'action_item', 'urgency', 'due_date', 'progress_status', 'remarksif_any', 
            'status', 'responsible_person', 'action_items'
        ])
        
        # For each action item, build the corresponding HTML rows
        for idx, item in enumerate(action_items):
            # Only include task details in the first row for each task
            if idx == 0:
                html += f"""
                <tr>
                    <td>{task['name']}</td>
                    <td>{task['subject']}</td>
                    <td>{task['custom_country']}</td>
                    <td>{task['custom_region']}</td>
                    <td>{task['custom_type_of_period']}</td>
                    <td>{task['custom_month']}</td>
                    <td>{task['custom_week']}</td>
                </tr>
                """
            
            # Add the Action Item details to the table (without repeating Task details)
            responsible_person_name = ''
            if item.get('responsible_person'):
                user = frappe.get_doc('User', item['responsible_person'])
                responsible_person_name = user.full_name if user else ''
            
            html += f"""
            <tr>
                <td></td>  <!-- Empty cell for Task ID -->
                <td></td>  <!-- Empty cell for Subject -->
                <td></td>  <!-- Empty cell for Country -->
                <td></td>  <!-- Empty cell for Region -->
                <td></td>  <!-- Empty cell for Quarter -->
                <td></td>  <!-- Empty cell for Month -->
                <td></td>  <!-- Empty cell for Week -->
                <td>{item.get('action_item', '')}</td>
                <td>{item.get('urgency', '')}</td>
                <td>{item.get('due_date', '')}</td>
                <td>{item.get('progress_status', '')}</td>
                <td>{item.get('remarksif_any', '')}</td>
                <td>{item.get('status', '')}</td>
                <td>{responsible_person_name}</td>
                <td>{item.get('action_items', '')}</td>
            </tr>
            """
    
    # Close the table HTML
    html += "</tbody></table>"
    
    # Return the generated HTML to be used in the form field
    return html

Please check the example: Tutorial: How to add table view of linked documents within form

1 Like

Im using Below code, but not working. I mean not generating the table.

def generate_csp_report_for_task(doc, method):
    html_content = ""

    tasks = frappe.get_all("Task", fields=["name", "subject", "custom_country", "custom_region", 
                                           "custom_type_of_period", "custom_month", "custom_week", 
                                           "status"])

    for task in tasks:
        action_items = frappe.get_all("Action Items", filters={"parent": task.name}, fields=["action_item", 
                                                                                            "urgency", 
                                                                                            "due_date", 
                                                                                            "progress_status", 
                                                                                            "remarksif_any", 
                                                                                            "status", 
                                                                                            "responsible_person", 
                                                                                            "action_items"])

        for index, action_item in enumerate(action_items):
            if index == 0:
                task_html = f"""
                    <tr>
                        <td>{task.name}</td>
                        <td>{task.subject}</td>
                        <td>{task.custom_country}</td>
                        <td>{task.custom_region}</td>
                        <td>{task.custom_type_of_period}</td>
                        <td>{task.custom_month}</td>
                        <td>{task.custom_week}</td>
                        <td>{action_item.action_item}</td>
                        <td>{action_item.urgency}</td>
                        <td>{action_item.due_date}</td>
                        <td>{action_item.progress_status}</td>
                        <td>{action_item.remarksif_any}</td>
                        <td>{action_item.status}</td>
                        <td>{get_user_full_name(action_item.responsible_person)}</td>
                        <td>{action_item.action_items}</td>
                    </tr>
                """
            else:
                task_html = f"""
                    <tr>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td>{action_item.action_item}</td>
                        <td>{action_item.urgency}</td>
                        <td>{action_item.due_date}</td>
                        <td>{action_item.progress_status}</td>
                        <td>{action_item.remarksif_any}</td>
                        <td>{action_item.status}</td>
                        <td>{get_user_full_name(action_item.responsible_person)}</td>
                        <td>{action_item.action_items}</td>
                    </tr>
                """

            html_content += task_html

    final_html = f"""
        <style>
            table {{
                width: 100%;
                border-collapse: collapse;
                font-size: 10px;
                border: 1px solid black;
            }}
            th, td {{
                padding: 10px;
                text-align: left;
                border: 1px solid black;
            }}
            th {{
                background-color: #003366;
                color: white;
                font-weight: bold;
            }}
            tr:nth-child(even) {{
                background-color: #f9f9f9;
            }}
            tr:hover {{
                background-color: #f1f1f1;
            }}
            td[colspan] {{
                background-color: #f9f9f9;
            }}
        </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>
                {html_content}
            </tbody>
        </table>
    """

    csp_report_doc = frappe.get_doc('CSP Progress Report', doc.name)

    found = False
    for report_entry in csp_report_doc.report_data:
        if report_entry.task == doc.name:
            report_entry.html_content = final_html
            found = True
            break

    if not found:
        csp_report_doc.append('report_data', {
            'task': doc.name,
            'html_content': final_html
        })

    csp_report_doc.save()

    return "CSP Report generated and updated successfully."

def get_user_full_name(email_id):
    user = frappe.get_doc('User', email_id)
    return user.full_name if user else ''

It’s the wrong way to define it in the server script. If you use frappe.call, you need to specify the API and method. Some functions may not work properly with the server script doctype. It’s better to use it in a custom app.

But, What is the exact Solution?

When i call the childtable data from every task by using client script. it shows " You dont have enough permission". that’s why im using server script. Above i mentioned both client and server script.