diff --git a/ui/src/pages/ProductionProductCostingHasCostDetail.vue b/ui/src/pages/ProductionProductCostingHasCostDetail.vue index f719e86..5cf14f2 100644 --- a/ui/src/pages/ProductionProductCostingHasCostDetail.vue +++ b/ui/src/pages/ProductionProductCostingHasCostDetail.vue @@ -5094,43 +5094,86 @@ async function copyTPDTFromSelectedCost () { trace_id: traceId.value }) const sourceGroups = normalizeDetailGroups(sourceData).filter(group => isTPDTGroupName(group?.sAciklama3)) - const populatedGroups = new Set( - flatDetailRows.value - .filter(row => isTPDTGroupName(row?.sAciklama3)) - .map(row => normalizeGroupName(row?.sAciklama3)) + const currentTPDTRows = flatDetailRows.value.filter(row => isTPDTGroupName(row?.sAciklama3)) + const isIncompleteTPDTRow = row => ( + Boolean(row?.requiredPlaceholder) || + !String(row?.sKodu || '').trim() || + !String(row?.sAciklama || '').trim() || + !(parseMoneyInput(row?.inputPrice ?? row?.fiyat_girilen) > 0) ) - const groupsToCopy = sourceGroups.filter(group => !populatedGroups.has(normalizeGroupName(group?.sAciklama3))) - const sourceRows = groupsToCopy.flatMap(group => ( - (Array.isArray(group?.items) ? group.items : []).map(row => ({ group, row })) - )) - if (sourceRows.length === 0) { - firmCostHistoryError.value = populatedGroups.has('TP') && populatedGroups.has('DT') - ? 'Mevcut maliyette TP ve DT gruplari zaten dolu. Hicbir satir degistirilmedi.' - : 'Secilen maliyette bos gruplari dolduracak TP/DT satiri bulunamadi.' - return + const availableTargets = currentTPDTRows.filter(isIncompleteTPDTRow) + const usedTargetKeys = new Set() + let filledRowCount = 0 + let addedRowCount = 0 + const copiedGroupNames = new Set() + + const findTargetRow = (sourceRow, groupName) => { + const sourceHNo = normalizeHammaddeNo(sourceRow?.nHammaddeTuruNo) + const sourceMT = parseInt(String(sourceRow?.nUrtMTBolumID ?? sourceRow?.NUrtMTBolumID ?? '0'), 10) || 0 + const sourcePart = normalizeGroupName(sourceRow?.sParcaAdi || '') + return availableTargets + .filter(target => !usedTargetKeys.has(target?.__rowKey)) + .filter(target => normalizeGroupName(target?.sAciklama3) === groupName) + .filter(target => normalizeHammaddeNo(target?.nHammaddeTuruNo) === sourceHNo) + .filter(target => { + const targetMT = parseInt(String(target?.nUrtMTBolumID ?? target?.NUrtMTBolumID ?? '0'), 10) || 0 + const targetPart = normalizeGroupName(target?.sParcaAdi || '') + if (sourceMT > 0 && targetMT > 0) return sourceMT === targetMT + if (sourcePart && targetPart) return sourcePart === targetPart + return true + }) + .map(target => { + const targetMT = parseInt(String(target?.nUrtMTBolumID ?? target?.NUrtMTBolumID ?? '0'), 10) || 0 + const targetPart = normalizeGroupName(target?.sParcaAdi || '') + let score = 1 + if (sourceMT > 0 && targetMT === sourceMT) score += 4 + if (sourcePart && targetPart === sourcePart) score += 2 + return { target, score } + }) + .sort((left, right) => right.score - left.score)[0]?.target } - sourceRows.forEach(({ group, row }) => { - newRowSequence.value += 1 - const copiedRow = recalculateDetailRow({ - ...row, - __rowKey: `firm-history-copy-${sourceOnMLNo}-${newRowSequence.value}`, - isNew: true, - nOnMLNo: detailHeader.value?.nOnMLNo || onMLNo.value || '', - nOnMLDetNo: getNextDetailNo(), - sAciklama3: normalizeGroupName(group?.sAciklama3 || row?.sAciklama3), - requiredPlaceholder: false, - draftChanged: true, - __copiedFromOnMLNo: sourceOnMLNo - }, { - preserveInputs: true, - priceType: 'COPY', - updateState: 'firm-history-copy', - markChanged: true + sourceGroups.forEach(group => { + const groupName = normalizeGroupName(group?.sAciklama3) + const groupCurrentRows = currentTPDTRows.filter(row => normalizeGroupName(row?.sAciklama3) === groupName) + const groupSourceRows = Array.isArray(group?.items) ? group.items : [] + groupSourceRows.forEach(row => { + const target = findTargetRow(row, groupName) + if (!target && groupCurrentRows.length > 0) return + + newRowSequence.value += 1 + const copiedRow = recalculateDetailRow({ + ...row, + __rowKey: target?.__rowKey || `firm-history-copy-${sourceOnMLNo}-${newRowSequence.value}`, + isNew: target ? Boolean(target?.isNew) : true, + nOnMLNo: detailHeader.value?.nOnMLNo || onMLNo.value || '', + nOnMLDetNo: target?.nOnMLDetNo || getNextDetailNo(), + sAciklama3: groupName, + requiredPlaceholder: false, + draftChanged: true, + __copiedFromOnMLNo: sourceOnMLNo + }, { + preserveInputs: true, + priceType: 'COPY', + updateState: 'firm-history-copy', + markChanged: true + }) + if (target) { + usedTargetKeys.add(target.__rowKey) + filledRowCount += 1 + } else { + addedRowCount += 1 + } + copiedGroupNames.add(groupName) + applyEditorRowToGroups(copiedRow) }) - applyEditorRowToGroups(copiedRow) }) + if (filledRowCount + addedRowCount === 0) { + firmCostHistoryError.value = 'Secilen maliyette mevcut bos TP/DT satirlariyla eslesen malzeme bulunamadi. Dolu satirlar degistirilmedi.' + return + } + recalculateAllDetailRows() syncAllGroupsOpen() schedulePersistLocalDraft() @@ -5138,7 +5181,7 @@ async function copyTPDTFromSelectedCost () { firmCostHistoryDialogOpen.value = false $q.notify({ type: 'positive', - message: `${groupsToCopy.map(group => normalizeGroupName(group?.sAciklama3)).join(' ve ')} gruplarindaki ${sourceRows.length} satir ${source?.UrunKodu || ''} maliyetinden tum ozellikleriyle eklendi. Kaydet butonu ile onaylayabilirsiniz.`, + message: `${Array.from(copiedGroupNames).join(' ve ')} gruplarinda ${filledRowCount} bos satir dolduruldu${addedRowCount > 0 ? `, ${addedRowCount} satir eklendi` : ''}. Kaydet butonu ile onaylayabilirsiniz.`, position: 'top-right', timeout: 5000 })