NonInventPurchasingSystem/CPRNIMS.WebApps/wwwroot/JsFunctions/Canvass/CanvassPrintingV4.js
2026-01-20 07:44:30 +08:00

413 lines
17 KiB
JavaScript

function debugDataStructure(data) {
console.group('Data Structure Analysis');
console.log('Raw data:', data);
console.log('Type:', typeof data);
console.log('Is Array:', Array.isArray(data));
console.log('Constructor:', data?.constructor?.name);
if (data && typeof data === 'object') {
console.log('Object keys:', Object.keys(data));
// Check if it's a wrapped response
if (data.data) console.log('data.data:', data.data);
if (data.result) console.log('data.result:', data.result);
if (data.items) console.log('data.items:', data.items);
// Sample first element if it's array-like
if (Array.isArray(data) && data.length > 0) {
console.log('First element:', data[0]);
console.log('First element keys:', Object.keys(data[0]));
}
}
console.groupEnd();
}
function viewItemToPrint() {
loader = $('#overlay, #loader').css('z-index', 1090);
$('#viewIteToPrint').modal('show');
$('#viewIteToPrint').css('z-index', 1050);
let PRNo = document.getElementById('label-prNo').innerHTML;
document.getElementById('label-print-prNo').innerHTML = PRNo;
tableName = '#selectPrintTable';
totalSelectedLabel = $('#totalSelectPrint');
clearTableSelection(tableName, selectedProductsMap, () => {
totalSelectedLabel.text(0);
}, 'selected-row', '.select-all-PrintItem-checkbox');
tableElement = $(tableName);
tableDestroy(tableElement);
let IsTagging = true;
var canvassPrinting = tableElement.DataTable({
ajax: $.extend({
url: endpoint.GetCanvassGroupByPRNo,
type: 'POST',
data: { PRNo, IsTagging }
}, beforeComplete(loader)),
language: {
emptyTable: "No record available"
},
initComplete: function () {
initializeTableSelection({
tableName: tableName,
dataTable: canvassPrinting,
selectedItemsMap: selectedProductsMap,
idKey: 'itemNo',
idKey2: 'prDetailsId',
checkboxClass: '.select-PrintItem-checkbox',
selectAllClass: '.select-all-PrintItem-checkbox',
selectedRowClass: 'selected-row',
updateCountCallback: function () {
totalSelectedLabel.text(getSelectedCount(selectedProductsMap));
}
});
},
columns: colCanvassItemToPrint,
error: errorHandler
});
}
function printPRNo(PRNo, IsTagging, AggreItemNo) {
return new Promise((resolve, reject) => {
$('#canvasContent').html('<div class="loading">Loading canvas data...</div>');
$.ajax({
url: endpoint.GetCanvassGroupByPRNo,
type: 'GET',
data: { PRNo, IsTagging, AggreItemNo },
success: function (data) {
try {
generateGroupedTable(data);
resolve();
loader.hide();
} catch (error) {
console.error('Error generating table:', error);
loader.hide();
$('#canvasContent').html(`
<div class="error">
<h4>Error generating table:</h4>
<p><strong>Error:</strong> ${error.message}</p>
<p><strong>Data received:</strong> ${JSON.stringify(data, null, 2)}</p>
<details>
<summary>Full Error Details</summary>
<pre>${error.stack}</pre>
</details>
</div>
`);
reject(error);
}
},
error: function (xhr, status, error) {
console.error('AJAX Error:', error);
$('#canvasContent').html('<div class="error">Error loading data: ' + error + '</div>');
reject(error);
}
});
});
}
function generateGroupedTable(data) {
// Debug: Log the received data to console
/*
console.log('Is Array:', Array.isArray(data));
*/
// Handle different response formats
let processedData = data;
//console.log('Data type:', typeof data);
//console.log('Received data:', data);
// If data is wrapped in an object (common with ASP.NET Core)
if (data && typeof data === 'object' && !Array.isArray(data)) {
if (data.data && Array.isArray(data.data)) {
processedData = data.data;
} else if (data.result && Array.isArray(data.result)) {
processedData = data.result;
} else if (data.items && Array.isArray(data.items)) {
processedData = data.items;
} else {
// Try to find the first array property
for (let key in data) {
if (Array.isArray(data[key])) {
processedData = data[key];
break;
}
}
}
}
// Final validation
if (!Array.isArray(processedData)) {
console.error('Data is not an array:', processedData);
$('#canvasContent').html('<div class="error">Invalid data format received from server. Expected array but got: ' + typeof processedData + '</div>');
return;
}
if (processedData.length === 0) {
$('#canvasContent').html('<div class="error">No data found for the specified PR Number.</div>');
return;
}
// Group data by item (itemName + itemNo)
const groupedData = {};
// Debug: Log each row to see the actual data structure
// console.log('Processing', processedData.length, 'rows');
processedData.forEach((row, index) => {
// console.log(`Row ${index}:`, row);
// Handle different property name formats (camelCase vs PascalCase)
const itemName = row.itemName || row.ItemName || '';
const itemNo = row.itemNo || row.ItemNo || '';
const supplierId = row.supplierId || row.supplierId || 0;
const supplierName = row.supplierName || row.SupplierName || '';
const previousPrice = row.previousPrice || row.PreviousPrice || 0;
const qty = row.qty || row.Qty || 0;
const unit = row.uomName || row.UOMName || 'pcs';
const unitPrice = row.unitPrice || row.UnitPrice || 0;
const discount = row.discount || row.Discount || 0;
const totalAmount = row.totalAmount || row.TotalAmount || 0;
const terms = row.terms || row.Terms || '';
const remarks = row.remarks || row.Remarks || '';
const leadTime = row.leadTime || row.LeadTime || '';
const isVatable = row.isVatable || row.IsVatable || false;
const previousPricePO = row.previousPricePO || row.PreviousPricePO || 0;
// Debug: Log extracted values
/* console.log(`Extracted values for row ${index}:`, {
itemName, itemNo, supplierName, terms, remarks, leadTime, isVatable
});*/
const groupKey = `${itemNo}|${itemName}`;
if (!groupedData[groupKey]) {
groupedData[groupKey] = {
itemName: itemName,
itemNo: itemNo,
previousPricePO: previousPricePO,
suppliers: new Map() // Use Map to avoid duplicates
};
}
// Use supplier name as key to avoid duplicates, but handle empty supplier names
const supplierKey = supplierId ? supplierId : `supplier_${index}`;
if (!groupedData[groupKey].suppliers.has(supplierKey)) {
groupedData[groupKey].suppliers.set(supplierKey, {
supplierName: supplierName,
previousPrice: previousPrice,
qty: qty,
unit: unit,
unitPrice: unitPrice,
discount: discount,
totalAmount: totalAmount,
terms: terms,
remarks: remarks,
leadTime: leadTime,
isVatable: isVatable
});
/* console.log(`Added supplier ${supplierKey} to group ${groupKey}:`, {
terms, remarks, leadTime, isVatable
});*/
} else {
// Handle duplicate supplier case
const existing = groupedData[groupKey].suppliers.get(supplierKey);
if (unitPrice < existing.unitPrice && unitPrice > 0) {
groupedData[groupKey].suppliers.set(supplierKey, {
supplierName: supplierName,
previousPrice: previousPrice,
qty: qty,
unit: unit,
unitPrice: unitPrice,
discount: discount,
totalAmount: totalAmount,
terms: terms,
remarks: remarks,
leadTime: leadTime,
isVatable: isVatable
});
/* console.log(`Updated supplier ${supplierKey} in group ${groupKey}:`, {
terms, remarks, leadTime, isVatable
});*/
}
}
});
// Debug: Log final grouped data
// console.log('Final grouped data:', groupedData);
// Generate HTML
let html = '';
Object.keys(groupedData).sort().forEach(groupKey => {
const group = groupedData[groupKey];
html += `
<div class="item-group">
<div class="item-header">
<div class="item-info">
<h3>Item: ${escapeHtml(group.itemName)}</h3>
<p>ItemCode: ${escapeHtml(group.itemNo)}</p>
</div>
${group.previousPricePO ? `
<div class="previous-price-info">
<span class="label">Previous Price base on latest PO's</span>
<span class="value">${escapeHtml(group.previousPricePO)}</span>
</div>
` : ''}
</div>
<table class="suppliers-table" width="100%" style="table-layout:fixed">
<colgroup>
<col style="width:17%">
<col style="width:7%">
<col style="width:7%">
<col style="width:7%">
<col style="width:7%">
<col style="width:8%">
<col style="width:12%">
<col style="width:7%">
<col style="width:6%">
<col style="width:22%">
</colgroup>
<thead>
<tr>
<th>Supplier</th>
<th>Prev.Price</th>
<th>Qty</th>
<th>UnitPrice</th>
<th>Discount</th>
<th>TotalPrice</th>
<th>Terms</th>
<th>LeadTime</th>
<th>Vatable</th>
<th>Remarks</th>
</tr>
</thead>
<tbody>
`;
// Convert Map to Array and sort suppliers by unit price (ascending)
const suppliersArray = Array.from(group.suppliers.values());
suppliersArray.sort((a, b) => {
// Sort by unit price (ascending), then by supplier name
if (a.unitPrice !== b.unitPrice) {
return (a.unitPrice || 0) - (b.unitPrice || 0);
}
return (a.supplierName || '').localeCompare(b.supplierName || '');
});
suppliersArray.forEach((supplier, supplierIndex) => {
// Auto-compute total amount: qty * unitPrice, or 0 if no offer (unitPrice is 0 or null)
let computedTotal = 0;
if (supplier.unitPrice && supplier.unitPrice > 0 && supplier.qty && supplier.qty > 0) {
computedTotal = parseFloat(supplier.qty) * parseFloat(supplier.unitPrice);
}
// Debug: Log each supplier's data being rendered
/* console.log(`Rendering supplier ${supplierIndex} for group ${groupKey}:`, {
supplierName: supplier.supplierName,
terms: supplier.terms,
remarks: supplier.remarks,
leadTime: supplier.leadTime,
isVatable: supplier.isVatable
});*/
html += `
<tr>
<td style="word-wrap: break-word;max-width: 120px;">${escapeHtml(supplier.supplierName || '')}</td>
<td class="text-center">${formatPrice(supplier.previousPrice)}</td>
<td class="text-center">${formatQuantity(supplier.qty, supplier.unit)}</td>
<td class="text-center">${formatPrice(supplier.unitPrice)}</td>
<td class="text-center">${escapeHtml(supplier.discount || '')}</td>
<td class="text-center">${formatPrice(computedTotal)}</td>
<td style="word-wrap: break-word; max-width: 30px;text-center">${escapeHtml(supplier.terms || '')}</td>
<td class="text-center">${escapeHtml(supplier.leadTime || '')}</td>
<td class="text-center">${supplier.isVatable ? 'YES' : 'NO'}</td>
<td style="word-wrap: break-word; max-width: 120px;text-left">${escapeHtml(supplier.remarks || '')}</td>
</tr>
`;
});
html += `
</tbody>
</table>
</div>
`;
});
$('#canvasContent').html(html);
}
function formatPrice(value) {
if (!value || value === 0) return '0.00';
return parseFloat(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function formatQuantity(qty, unit) {
if (!qty) return '';
return parseFloat(qty).toFixed(0) + ' ' + (unit || 'pcs');
}
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
function printRelatedItem() {
loader = $('#overlay, #loader').css('z-index', 1080);
let PRNo = document.getElementById('label-prNo').innerHTML;
const selectedItems = Object.values(selectedProductsMap);
if (selectedItems.length === 0) {
showToast('warning', 'Please select items for canvass first!', 'warning', 4000);
return;
}
const AggreItemNo = selectedItems.map(item => item.itemNo).join(',');
printPRNo(PRNo, false, AggreItemNo).then(() => {
document.getElementById('print-prNo').innerHTML = PRNo;
const iframe = document.createElement('iframe');
iframe.style.position = 'fixed';
iframe.style.right = '0';
iframe.style.bottom = '0';
iframe.style.width = '0';
iframe.style.height = '0';
iframe.style.border = 'none';
document.body.appendChild(iframe);
const doc = iframe.contentWindow.document;
doc.open();
doc.write('<html><head><title>Print</title>');
document.querySelectorAll('link[rel="stylesheet"]').forEach(sheet => doc.write(sheet.outerHTML));
document.querySelectorAll('style').forEach(style => doc.write(style.outerHTML));
doc.write(`
<style>
@media print {
* { -webkit-print-color-adjust: exact !important; color-adjust: exact !important; print-color-adjust: exact !important; }
}
body { font-family: "Georgia", serif; font-size: 12px; margin: 0; padding: 5px; }
.header { font-size: 12px; font-weight: bold; text-align: center; margin-bottom: 20px; padding: 10px 0; }
.dataTables_length, .dataTables_filter, .dataTables_info, .dataTables_paginate { display: none !important; }
table { width: 100% !important; border-collapse: collapse; font-size: 8px; font-family: "Georgia", serif; }
table th, table td { padding: 1px 2px; line-height: .9; vertical-align: top; border: .5px solid #808080 !important; }
.pr-info-section { font-size: 10px !important; }
.pr-info-section label, .pr-info-section strong { font-size: 9px !important; }
</style>
`);
doc.write('</head><body>');
doc.write('<div class="header">Canvass Report</div>');
const printContent = document.getElementById('printableRelatedItem').cloneNode(true);
doc.write(printContent.outerHTML);
doc.write('</body></html>');
doc.close();
iframe.onload = function () {
iframe.contentWindow.print();
setTimeout(() => document.body.removeChild(iframe), 1000);
};
}).catch(err => {
console.error('Error loading data:', err);
});
}