332 lines
14 KiB
XML
Executable File
332 lines
14 KiB
XML
Executable File
<odoo>
|
|
<record id="action_report_spenco" model="ir.actions.report">
|
|
<field name="name">SPENCO Report</field>
|
|
<field name="model">sos_case_diary</field>
|
|
<field name="report_type">qweb-html</field>
|
|
<field name="report_name">sos_sales.report_spenco</field>
|
|
<field name="report_file">sos_sales.report_spenco</field>
|
|
<field name="binding_model_id" eval="False"/>
|
|
<field name="binding_type">report</field>
|
|
</record>
|
|
<template id="report_spenco">
|
|
<t t-call="web.html_container">
|
|
<t t-call="web.basic_layout">
|
|
<script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script>
|
|
<script src="http://cdn.datatables.net/2.2.2/js/dataTables.min.js"></script>
|
|
<link rel="stylesheet" href="/sos_inventory/static/src/css/style.css?v=7" />
|
|
<link rel="stylesheet" href="http://cdn.datatables.net/2.2.2/css/dataTables.dataTables.min.css"/>
|
|
<div class="page">
|
|
<script type="text/javascript">
|
|
setTimeout(function() {
|
|
// Check if DataTable is already initialized and destroy it before reinitializing
|
|
if ($.fn.DataTable.isDataTable('#myTable')) {
|
|
$('#myTable').DataTable().destroy();
|
|
}
|
|
|
|
// Initialize DataTable
|
|
let table = new DataTable('#myTable', {
|
|
columnDefs: [
|
|
{ width: '20%', targets: 2 },
|
|
{ width: '12%', targets: 1 },
|
|
{ width: '5%', targets: 0 },
|
|
{ width: '8%', targets: 4},
|
|
{ width: '8%', targets: 5},
|
|
{ width: '8%', targets: 6},
|
|
{ orderable: false, targets: [7, 8, 9, 10, 11, 12] }
|
|
],
|
|
paging: true, // Ensure pagination is enabled
|
|
pageLength: 10,
|
|
ordering: true, // Sorting is enabled (with specific columns disabled via columnDefs)
|
|
drawCallback: function(settings) {
|
|
var api = this.api();
|
|
var pageInfo = api.page.info();
|
|
// Show tfoot only on the last page
|
|
if (pageInfo.page === pageInfo.pages - 1) {
|
|
$('#myTable tfoot.datatable-footer').show();
|
|
} else {
|
|
$('#myTable tfoot.datatable-footer').hide();
|
|
}
|
|
}
|
|
});
|
|
|
|
// Function to update footer totals based on visible rows
|
|
function updateFooterTotals() {
|
|
let prospectsTotal = 0, engagedTotal = 0, negotiationTotal = 0, commercialOrderTotal = 0, expectedOrderTotal = 0;
|
|
|
|
// Loop through only visible rows in DataTable
|
|
table.rows({ filter: 'applied' }).every(function() {
|
|
let row = $(this.node());
|
|
|
|
// Extract values from respective columns (based on column index)
|
|
let prospects = parseFloat(row.find("td:eq(8)").text().replace(/[₹,]/g, '')) || 0;
|
|
let engaged = parseFloat(row.find("td:eq(9)").text().replace(/[₹,]/g, '')) || 0;
|
|
let negotiation = parseFloat(row.find("td:eq(10)").text().replace(/[₹,]/g, '')) || 0;
|
|
let commercialOrder = parseFloat(row.find("td:eq(11)").text().replace(/[₹,]/g, '')) || 0;
|
|
let expectedOrder = parseFloat(row.find("td:eq(12)").text().replace(/[₹,]/g, '')) || 0;
|
|
|
|
// Sum the filtered values
|
|
prospectsTotal += prospects;
|
|
engagedTotal += engaged;
|
|
negotiationTotal += negotiation;
|
|
commercialOrderTotal += commercialOrder;
|
|
expectedOrderTotal += expectedOrder;
|
|
});
|
|
|
|
// Update footer values dynamically
|
|
$("#myTable tfoot td:eq(1)").text("₹ " + prospectsTotal.toFixed(2));
|
|
$("#myTable tfoot td:eq(2)").text("₹ " + engagedTotal.toFixed(2));
|
|
$("#myTable tfoot td:eq(3)").text("₹ " + negotiationTotal.toFixed(2));
|
|
$("#myTable tfoot td:eq(4)").text("₹ " + commercialOrderTotal.toFixed(2));
|
|
$("#myTable tfoot td:eq(5)").text("₹ " + expectedOrderTotal.toFixed(2));
|
|
}
|
|
|
|
// Run updateFooterTotals when the table is drawn (filtered, paginated, sorted, etc.)
|
|
table.on('draw', function() {
|
|
updateFooterTotals();
|
|
});
|
|
|
|
// Initial update in case data is preloaded
|
|
updateFooterTotals();
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
</script>
|
|
<style>
|
|
.table-container {
|
|
width: 100%;
|
|
overflow: hidden;
|
|
border: 1px solid #ddd;
|
|
position: relative;
|
|
}
|
|
|
|
.table-container table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.table-container thead {
|
|
position: sticky;
|
|
top: 0;
|
|
background-color: lavender;
|
|
z-index: 100;
|
|
}
|
|
|
|
.table-scroll {
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
|
|
.table-scroll table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
td, th {
|
|
border: 1px solid #ddd;
|
|
padding: 8px;
|
|
text-align: center;
|
|
}
|
|
|
|
th {
|
|
background-color: lavender;
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 2;
|
|
}
|
|
|
|
.final-row {
|
|
background-color: lavender;
|
|
font-weight: bold;
|
|
}
|
|
|
|
|
|
.table_custom tfoot {
|
|
position: sticky;
|
|
bottom: 0;
|
|
z-index: 10;
|
|
}
|
|
.datatable-footer {
|
|
display: none;
|
|
}
|
|
|
|
</style>
|
|
<br/>
|
|
<h5 style="text-align:center">SPENCO REPORT</h5>
|
|
<div style="box-shadow: 0px 8px 24px rgba(27, 46, 94, 0.12) !important;
|
|
padding: 12px;
|
|
border: solid 1px #ccc;
|
|
border-radius: 20px;">
|
|
<t t-if="from_date or to_date">
|
|
<div>
|
|
<p><b>Report Period is From</b> <t t-esc="from_date or 'N/A'"/> To <t t-esc="to_date or 'N/A'"/>.</p>
|
|
</div>
|
|
</t>
|
|
<span><b>Note: Values In Lakhs</b></span>
|
|
<t t-if="sales_person">
|
|
<div>
|
|
<p><b>Sales Executive : </b><t t-esc="sales_person.name or 'N/A'"/></p>
|
|
</div>
|
|
</t>
|
|
|
|
<div class="table-container">
|
|
<t t-if="sales_person">
|
|
<table class="table_custom display" id="myTable">
|
|
<thead>
|
|
<tr>
|
|
<th rowspan="2">S.No</th>
|
|
<th rowspan="2">Quote No</th>
|
|
<th rowspan="2">Customer/End Customer</th>
|
|
<th rowspan="2">City</th>
|
|
<th rowspan="2">Start Date</th>
|
|
<th rowspan="2">Status Changed On</th>
|
|
<th rowspan="2">Product</th>
|
|
<th rowspan="2">Qty</th>
|
|
<th colspan="4">Order Booking </th>
|
|
<th rowspan="2">Order Value Probability</th>
|
|
</tr>
|
|
<tr>
|
|
<th>P</th>
|
|
<th>E</th>
|
|
<th>N</th>
|
|
<th>CO</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<t t-set="last_sales_person" t-value="False"/>
|
|
<t t-set="row_index" t-value="0"/>
|
|
<t t-foreach="case_diary_data" t-as="case">
|
|
<!-- <t t-if="case['sales_person'] != last_sales_person">
|
|
<tr style="background-color: #f0f0f0; font-weight: bold;">
|
|
<td colspan="13"><t t-esc="case['sales_person']"/></td>
|
|
</tr>
|
|
<t t-set="last_sales_person" t-value="case['sales_person']"/>
|
|
</t> -->
|
|
<tr>
|
|
<td><t t-esc="row_index + 1"/></td>
|
|
<td><t t-esc="case['quote_no']"/></td>
|
|
<td>
|
|
<a t-att-href="'/web#id=%d&model=sos_case_diary&view_type=form' % case['record_id']" target="_blank">
|
|
<t t-esc="case['customer_name']"/>
|
|
<t t-if="case['end_customer_name']">/<t t-esc="case['end_customer_name']"/></t>
|
|
</a>
|
|
</td>
|
|
|
|
<td><t t-esc="case['customer_city']"/></td>
|
|
<td><t t-esc="case['account_start_date']"/></td>
|
|
<td><t t-esc="case['status_changed_on']"/></td>
|
|
<td><t t-esc="case['products']"/></td>
|
|
<td><t t-esc="case['quantity']"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(case['current_state_value'])" t-if="case['spenco_status'] == 'Prospects'"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(case['current_state_value'])" t-if="case['spenco_status'] == 'Engaged'"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(case['current_state_value'])" t-if="case['spenco_status'] == 'Negotiation'"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(case['current_state_value'])" t-if="case['spenco_status'] == 'Commercial Order'"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(float(case['expected_order_value']))"/></td>
|
|
</tr>
|
|
<t t-set="row_index" t-value="row_index + 1"/>
|
|
</t>
|
|
</tbody>
|
|
<tfoot class="datatable-footer">
|
|
<tr class="final-row">
|
|
<td colspan="8">Final Value:</td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Prospects'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Engaged'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Negotiation'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Commercial Order'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['expected_order_value'] for case in case_diary_data))"/></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</t>
|
|
<t t-else="sales_person">
|
|
|
|
<table class="table_custom display" id="myTable">
|
|
<thead>
|
|
<tr>
|
|
<th rowspan="2">S.No</th>
|
|
<th rowspan="2">Quote No</th>
|
|
<th rowspan="2">Customer</th>
|
|
<th rowspan="2">City</th>
|
|
<th rowspan="2">Sales Person</th>
|
|
<th rowspan="2">Start Date</th>
|
|
<th rowspan="2">Status Changed On</th>
|
|
<th rowspan="2">Product</th>
|
|
<th rowspan="2">Qty</th>
|
|
<th colspan="4">Order Booking </th>
|
|
<th rowspan="2">Order Value </th>
|
|
</tr>
|
|
<tr>
|
|
<th>Prospects</th>
|
|
<th>Engaged</th>
|
|
<th>Negotiation</th>
|
|
<th>Commercial Order</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<t t-set="last_sales_person" t-value="False"/>
|
|
<t t-set="row_index" t-value="0"/>
|
|
<t t-foreach="case_diary_data" t-as="case">
|
|
<!-- <t t-if="case['sales_person'] != last_sales_person">
|
|
<tr style="background-color: #f0f0f0; font-weight: bold;">
|
|
<td colspan="13"><t t-esc="case['sales_person']"/></td>
|
|
</tr>
|
|
<t t-set="last_sales_person" t-value="case['sales_person']"/>
|
|
</t> -->
|
|
<tr>
|
|
<td><t t-esc="row_index + 1"/></td>
|
|
<td><t t-esc="case['quote_no']"/></td>
|
|
<td><a t-att-href="'/web#id=%d&model=sos_case_diary&view_type=form' % case['record_id']" target="_blank"><t t-esc="case['customer_name']"/></a></td>
|
|
<td><t t-esc="case['customer_city']"/></td>
|
|
<td><t t-esc="case['sales_person']"/></td>
|
|
<td><t t-esc="case['account_start_date']"/></td>
|
|
<td><t t-esc="case['status_changed_on']"/></td>
|
|
<td><t t-esc="case['products']"/></td>
|
|
<td><t t-esc="case['quantity']"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(case['current_state_value'])" t-if="case['spenco_status'] == 'Prospects'"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(case['current_state_value'])" t-if="case['spenco_status'] == 'Engaged'"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(case['current_state_value'])" t-if="case['spenco_status'] == 'Negotiation'"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(case['current_state_value'])" t-if="case['spenco_status'] == 'Commercial Order'"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(float(case['expected_order_value']))"/></td>
|
|
</tr>
|
|
<t t-set="row_index" t-value="row_index + 1"/>
|
|
</t>
|
|
</tbody>
|
|
<tfoot class="datatable-footer">
|
|
<tr class="final-row">
|
|
<td colspan="8">Final Value:</td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Prospects'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Engaged'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Negotiation'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Commercial Order'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['expected_order_value'] for case in case_diary_data))"/></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</t>
|
|
<t t-if="report_type == 'pdf'">
|
|
<table class="table_custom" style="width: 100%; margin-top: 20px;">
|
|
<tr class="final-row">
|
|
<td colspan="8"><strong>Final Value</strong></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Prospects'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Engaged'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Negotiation'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['current_state_value'] for case in case_diary_data if case['spenco_status'] == 'Commercial Order'))"/></td>
|
|
<td><t t-esc="'₹ {:.2f}'.format(sum(case['expected_order_value'] for case in case_diary_data))"/></td>
|
|
</tr>
|
|
</table>
|
|
</t>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</t>
|
|
</t>
|
|
</template>
|
|
|
|
|
|
</odoo>
|