feat: enrich card transaction descriptions and add duplicate warning
Build full description from operationName, fullRemark, shortRemark, and description fields for card statement transactions. Show a warning banner when card transactions are present since duplicate detection across card and account statements is not possible due to different reference numbers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
677c1492e7
commit
dd5ffc0bed
|
|
@ -1412,6 +1412,14 @@ def get_card_statement_transactions(from_date, to_date, card_account_number, log
|
|||
# Purpose (operationName serves as both purpose and counterparty description)
|
||||
operation_name = (txn.get("operationName") or "").strip()
|
||||
|
||||
# Build enriched description from all available remark fields
|
||||
desc_parts = [operation_name] if operation_name else []
|
||||
for field in ("fullRemark", "shortRemark", "description"):
|
||||
val = (txn.get(field) or "").strip()
|
||||
if val and val not in desc_parts:
|
||||
desc_parts.append(val)
|
||||
full_description = " || ".join(desc_parts)
|
||||
|
||||
transactions.append({
|
||||
"ref_no": txn_id,
|
||||
"date": str(parsed_date),
|
||||
|
|
@ -1421,6 +1429,7 @@ def get_card_statement_transactions(from_date, to_date, card_account_number, log
|
|||
"currency": currency,
|
||||
"drcr": dr_cr,
|
||||
"purpose": operation_name,
|
||||
"full_description": full_description,
|
||||
"source_type": "card",
|
||||
"source_label": f"Card: {pan}",
|
||||
})
|
||||
|
|
@ -2202,7 +2211,7 @@ def _import_one_bank_transaction(txn_data, settings, voen_to_party, name_to_part
|
|||
bt.deposit = amount if dr_cr == "C" else 0
|
||||
bt.withdrawal = amount if dr_cr == "D" else 0
|
||||
bt.currency = currency
|
||||
bt.description = purpose
|
||||
bt.description = txn_data.get("full_description") or purpose
|
||||
bt.reference_number = ref_no
|
||||
bt.transaction_id = ref_no
|
||||
bt.company = settings.default_company
|
||||
|
|
|
|||
|
|
@ -527,7 +527,16 @@ KBBTImport.import = {
|
|||
},
|
||||
|
||||
showTransactionSelection: function(txns) {
|
||||
let txnTable = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered kb-bt-txn-table" style="width: 100%; table-layout: fixed;">';
|
||||
const hasCardTxns = txns.some(t => t.source_type === 'card');
|
||||
|
||||
let txnTable = '';
|
||||
if (hasCardTxns) {
|
||||
txnTable += '<div style="margin-bottom: 10px; padding: 10px 12px; background: var(--red-50, #fff5f5); border: 1px solid var(--red-200, #fecaca); border-radius: var(--border-radius); font-size: var(--text-base); color: var(--red-600, #dc2626);">';
|
||||
txnTable += '⚠️ ' + __('Card transactions may already be imported from other accounts. The bank uses different reference numbers for card and account statements, so duplicates cannot be detected automatically.');
|
||||
txnTable += '</div>';
|
||||
}
|
||||
|
||||
txnTable += '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered kb-bt-txn-table" style="width: 100%; table-layout: fixed;">';
|
||||
txnTable += '<thead style="position: sticky; top: 0; z-index: 1; background: var(--bg-color, #fff);"><tr>' +
|
||||
'<th style="width: 4%;"><input type="checkbox" class="kb-bt-select-all-txns"></th>' +
|
||||
'<th style="width: 14%;">' + __('Ref No') + '</th>' +
|
||||
|
|
@ -555,7 +564,7 @@ KBBTImport.import = {
|
|||
'<td style="word-break: break-word;">' + (txn.counterparty || '') + '</td>' +
|
||||
'<td style="text-align: right;">' + amountFmt + ' ' + (txn.currency || '') + '</td>' +
|
||||
'<td style="text-align: center;">' + drcrLabel + '</td>' +
|
||||
'<td style="word-break: break-word; font-size: 0.9em;">' + (txn.purpose || '') + '</td>' +
|
||||
'<td style="word-break: break-word; font-size: 0.9em;">' + (txn.full_description || txn.purpose || '') + '</td>' +
|
||||
'</tr>';
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -485,7 +485,16 @@ KBImport.import = {
|
|||
},
|
||||
|
||||
showTransactionSelection: function(txns) {
|
||||
let txnTable = '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered kb-txn-table" style="width: 100%; table-layout: fixed;">';
|
||||
const hasCardTxns = txns.some(t => t.source_type === 'card');
|
||||
|
||||
let txnTable = '';
|
||||
if (hasCardTxns) {
|
||||
txnTable += '<div style="margin-bottom: 10px; padding: 10px 12px; background: var(--red-50, #fff5f5); border: 1px solid var(--red-200, #fecaca); border-radius: var(--border-radius); font-size: var(--text-base); color: var(--red-600, #dc2626);">';
|
||||
txnTable += '⚠️ ' + __('Card transactions may already be imported from other accounts. The bank uses different reference numbers for card and account statements, so duplicates cannot be detected automatically.');
|
||||
txnTable += '</div>';
|
||||
}
|
||||
|
||||
txnTable += '<div style="max-height: 500px; overflow-y: auto;"><table class="table table-bordered kb-txn-table" style="width: 100%; table-layout: fixed;">';
|
||||
txnTable += '<thead style="position: sticky; top: 0; z-index: 1; background: var(--bg-color, #fff);"><tr>' +
|
||||
'<th style="width: 4%;"><input type="checkbox" class="kb-select-all-txns"></th>' +
|
||||
'<th style="width: 14%;">' + __('Ref No') + '</th>' +
|
||||
|
|
@ -513,7 +522,7 @@ KBImport.import = {
|
|||
'<td style="word-break: break-word;">' + (txn.counterparty || '') + '</td>' +
|
||||
'<td style="text-align: right;">' + amountFmt + ' ' + (txn.currency || '') + '</td>' +
|
||||
'<td style="text-align: center;">' + drcrLabel + '</td>' +
|
||||
'<td style="word-break: break-word; font-size: 0.9em;">' + (txn.purpose || '') + '</td>' +
|
||||
'<td style="word-break: break-word; font-size: 0.9em;">' + (txn.full_description || txn.purpose || '') + '</td>' +
|
||||
'</tr>';
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue