To achieve this, we added a checkbox “Print Timesheets” to the sales invoice and included this HTML snippet in the print format:
<br>
<div style="page-break-after: always"></div>
{% if doc.timesheets and doc.print_timesheets -%}
<h4>{{ _("Timesheets") }}</h4>
<table class="table table-bordered table-condensed">
<thead>
<tr>
<th style="width: 40px" class="table-sr">{{ _("Sr"} }}</th>
<th style="width: 150px;">
{{ _("Date") }}</th>
<th style="width: 300px;">
{{ _("Note") }}</th>
<th style="width: 80px;" class="text-right">
{{ _("Hours") }}</th>
</tr>
</thead>
<tbody>
{% for ts in doc.timesheets %}
<tr>
<td class="table-sr">{{ loop.index }}</td>
<td>
<div class="value">
{{ frappe.utils.formatdate(ts.start_date) }}
</div>
</td>
<td>
<div class="value">
{{ ts.note }}
</div>
</td>
<td class="text-right">
<div class="value">
{{ ts.billing_hours | round(2, 'ceil') }}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}