/** * Check if item exists in main table by prDetailsId * @param {string|number} prDetailsId - The prDetailsId to check * @returns {boolean} True if item exists, false otherwise */ function isItemExistInMainTable(prDetailsId) { if (!poDataTable) return false; const data = poDataTable.data().toArray(); return data.some(item => item.prDetailsId === prDetailsId); } /** * Get all existing prDetailsIds from main table * @returns {Array} Array of existing prDetailsIds */ function getExistingItemIds() { if (!poDataTable) return []; return poDataTable.data().toArray().map(item => item.prDetailsId); } /** * Remove items from PRItemTable that already exist in main table * Call this after adding items to main table */ function removeExistingItemsFromPRTable() { if (!PRItemTable) return; const existingIds = getExistingItemIds(); // Clear selections for existing items existingIds.forEach(prDetailsId => { // Find and remove from selectedProductsMap using the composite key Object.keys(selectedProductsMap).forEach(key => { const item = selectedProductsMap[key]; if (item && item.prDetailsId === prDetailsId) { delete selectedProductsMap[key]; } }); }); // Redraw table to update checkbox states PRItemTable.draw(); // Update the count if (totalSelectedLabel) { totalSelectedLabel.text(getSelectedCount(selectedProductsMap)); } } /** * Enhanced initializeTableSelection with duplicate checking * Add this to your existing initializeTableSelection config when calling it */ function initializeTableSelectionWithDuplicateCheck(config) { const originalConfig = { ...config }; // Enhance the individual checkbox change handler const originalCheckboxHandler = function () { const $row = $(this).closest('tr'); const rowData = originalConfig.dataTable.row($row).data(); if (!rowData) { console.error('No row data found'); return; } // Check for duplicates before allowing selection if ($(this).prop('checked')) { if (isItemExistInMainTable(rowData.prDetailsId)) { // Item already exists, prevent selection $(this).prop('checked', false); alert(`Item ${rowData.itemNo || rowData.prNo} already exists in the main table.`); return; } } const itemId = originalConfig.idKey2 ? `${rowData[originalConfig.idKey]}|${rowData[originalConfig.idKey2] || ''}` : rowData[originalConfig.idKey]; if ($(this).prop('checked')) { $row.addClass(originalConfig.selectedRowClass || 'selected-row'); originalConfig.selectedItemsMap[itemId] = rowData; } else { $row.removeClass(originalConfig.selectedRowClass || 'selected-row'); delete originalConfig.selectedItemsMap[itemId]; } originalConfig.updateCountCallback(); updateSelectAllCheckboxStateWithDuplicateCheck(); }; // Enhanced select all checkbox handler const originalSelectAllHandler = function () { const isChecked = $(this).prop('checked'); const checkboxClass = originalConfig.checkboxClass || '.selected-Item-checkbox'; const selectedRowClass = originalConfig.selectedRowClass || 'selected-row'; $(originalConfig.tableName + ' tbody tr:visible').each(function () { const $row = $(this); const $checkbox = $row.find(checkboxClass); if ($checkbox.length === 0) return; const rowData = originalConfig.dataTable.row($row).data(); if (!rowData) return; // Check for duplicates when selecting all if (isChecked && isItemExistInMainTable(rowData.prDetailsId)) { // Skip items that already exist return; } const itemId = originalConfig.idKey2 ? `${rowData[originalConfig.idKey]}|${rowData[originalConfig.idKey2] || ''}` : rowData[originalConfig.idKey]; $checkbox.prop('checked', isChecked); if (isChecked) { $row.addClass(selectedRowClass); originalConfig.selectedItemsMap[itemId] = rowData; } else { $row.removeClass(selectedRowClass); delete originalConfig.selectedItemsMap[itemId]; } }); originalConfig.updateCountCallback(); updateSelectAllCheckboxStateWithDuplicateCheck(); }; // Enhanced select all state update function function updateSelectAllCheckboxStateWithDuplicateCheck() { const selectAllClass = originalConfig.selectAllClass || '.select-all-checkbox'; const checkboxClass = originalConfig.checkboxClass || '.selected-Item-checkbox'; const $selectAllCheckbox = $(originalConfig.tableName + ' ' + selectAllClass); const $visibleCheckboxes = $(originalConfig.tableName + ' tbody ' + checkboxClass + ':visible'); // Filter out checkboxes for items that already exist in main table const $availableCheckboxes = $visibleCheckboxes.filter(function () { const $row = $(this).closest('tr'); const rowData = originalConfig.dataTable.row($row).data(); return rowData && !isItemExistInMainTable(rowData.prDetailsId); }); const checkedCount = $availableCheckboxes.filter(':checked').length; const totalAvailable = $availableCheckboxes.length; if (totalAvailable === 0) { $selectAllCheckbox.prop('indeterminate', false).prop('checked', false); } else if (checkedCount === totalAvailable) { $selectAllCheckbox.prop('indeterminate', false).prop('checked', true); } else if (checkedCount > 0) { $selectAllCheckbox.prop('indeterminate', true).prop('checked', false); } else { $selectAllCheckbox.prop('indeterminate', false).prop('checked', false); } } // Enhanced row state update function function updateRowStatesWithDuplicateCheck() { const checkboxClass = originalConfig.checkboxClass || '.selected-Item-checkbox'; const selectedRowClass = originalConfig.selectedRowClass || 'selected-row'; $(originalConfig.tableName + ' tbody tr').each(function () { const $row = $(this); const rowData = originalConfig.dataTable.row($row).data(); if (rowData) { const $checkbox = $row.find(checkboxClass); // Check if item exists in main table if (isItemExistInMainTable(rowData.prDetailsId)) { // Disable checkbox and add visual indicator $checkbox.prop('checked', false).prop('disabled', true); $row.addClass('item-already-exists').removeClass(selectedRowClass); // Remove from selection map if it exists const itemId = originalConfig.idKey2 ? `${rowData[originalConfig.idKey]}|${rowData[originalConfig.idKey2] || ''}` : rowData[originalConfig.idKey]; delete originalConfig.selectedItemsMap[itemId]; } else { // Enable checkbox and restore normal state $checkbox.prop('disabled', false); $row.removeClass('item-already-exists'); const itemId = originalConfig.idKey2 ? `${rowData[originalConfig.idKey]}|${rowData[originalConfig.idKey2] || ''}` : rowData[originalConfig.idKey]; if (originalConfig.selectedItemsMap[itemId]) { $checkbox.prop('checked', true); $row.addClass(selectedRowClass); } else { $checkbox.prop('checked', false); $row.removeClass(selectedRowClass); } } } }); } // Call the original initializeTableSelection with enhanced handlers initializeTableSelection(originalConfig); // Replace the handlers with enhanced versions $(originalConfig.tableName).off('change', originalConfig.checkboxClass || '.selected-Item-checkbox'); $(originalConfig.tableName).off('change', originalConfig.selectAllClass || '.select-all-checkbox'); $(originalConfig.tableName).on('change', originalConfig.checkboxClass || '.selected-Item-checkbox', originalCheckboxHandler); $(originalConfig.tableName).on('change', originalConfig.selectAllClass || '.select-all-checkbox', originalSelectAllHandler); // Enhanced draw event handler originalConfig.dataTable.off('draw.tableSelection'); originalConfig.dataTable.on('draw.tableSelection', function () { updateRowStatesWithDuplicateCheck(); updateSelectAllCheckboxStateWithDuplicateCheck(); }); // Initial state update setTimeout(() => { updateRowStatesWithDuplicateCheck(); updateSelectAllCheckboxStateWithDuplicateCheck(); }, 100); } /** * Call this function after successfully adding items to the main table * Example: after your AJAX call that adds selected items to PODataTable */ function afterAddingItemsToMainTable() { // Refresh the main table if (poDataTable) { poDataTable.ajax.reload(null, false); } // Remove existing items from PR table and update states setTimeout(() => { removeExistingItemsFromPRTable(); }, 500); } // Add CSS for visual indication of existing items const duplicateItemStyles = ` `; // Inject styles into head if (!document.querySelector('#duplicate-item-styles')) { const styleElement = document.createElement('style'); styleElement.id = 'duplicate-item-styles'; styleElement.textContent = ` .item-already-exists { background-color: #f8f9fa !important; opacity: 0.6; } .item-already-exists td { color: #6c757d !important; } .item-already-exists input[type="checkbox"]:disabled { opacity: 0.3; } `; document.head.appendChild(styleElement); }