From ab37350acb661d81280d675857960b7679d6c60f Mon Sep 17 00:00:00 2001 From: liyin Date: Thu, 13 Aug 2026 15:53:45 +0800 Subject: [PATCH 1/3] Refs #47462,feat:trxn_id repeat bug --- CRM/Event/Form/Participant.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CRM/Event/Form/Participant.php b/CRM/Event/Form/Participant.php index 6c05ac6b7c..d65f39d5df 100644 --- a/CRM/Event/Form/Participant.php +++ b/CRM/Event/Form/Participant.php @@ -1022,6 +1022,36 @@ public static function formRule($values, $files, $self) { $errorMsg['contribution_status_id'] = ts("Please select a valid payment status before updating."); } + // validate trxn_id uniqueness when record_contribution is checked (AC-1, AC-2, AC-3) + if (CRM_Utils_Array::value('record_contribution', $values) && + !empty($values['trxn_id']) + ) { + $trxnId = $values['trxn_id']; + $excludeContributionId = NULL; + + // AC-3: When editing a participant that already has a payment linked, + // exclude that participant's own contribution from the duplicate check. + if ($self->_id && $self->_paymentId) { + $excludeContributionId = CRM_Core_DAO::getFieldValue( + 'CRM_Event_DAO_ParticipantPayment', + $self->_id, + 'contribution_id', + 'participant_id' + ); + } + + $dupQuery = "SELECT id FROM civicrm_contribution WHERE trxn_id = %1"; + $dupParams = [1 => [$trxnId, 'String']]; + if ($excludeContributionId) { + $dupQuery .= " AND id != %2"; + $dupParams[2] = [$excludeContributionId, 'Integer']; + } + $dupDao = CRM_Core_DAO::executeQuery($dupQuery, $dupParams); + if ($dupDao->fetch()) { + $errorMsg['trxn_id'] = ts('此交易編號已存在於資料庫。'); + } + } + // do the amount validations. //skip for update mode since amount is freeze, CRM-6052 if (( From 48c39e3bdceee9fa03fb70408457fcc1617705f7 Mon Sep 17 00:00:00 2001 From: liyin Date: Mon, 31 Aug 2026 19:55:23 +0800 Subject: [PATCH 2/3] Refs #47462, feat: change to english --- CRM/Event/Form/Participant.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CRM/Event/Form/Participant.php b/CRM/Event/Form/Participant.php index d65f39d5df..8c49ac38ba 100644 --- a/CRM/Event/Form/Participant.php +++ b/CRM/Event/Form/Participant.php @@ -1048,7 +1048,7 @@ public static function formRule($values, $files, $self) { } $dupDao = CRM_Core_DAO::executeQuery($dupQuery, $dupParams); if ($dupDao->fetch()) { - $errorMsg['trxn_id'] = ts('此交易編號已存在於資料庫。'); + $errorMsg['trxn_id'] = ts('Transaction ID already exists in Database.'); } } From 3a641e2c584cc57530db714374a341f4e6f0184f Mon Sep 17 00:00:00 2001 From: liyin Date: Mon, 31 Aug 2026 19:56:41 +0800 Subject: [PATCH 3/3] Refs #47462,feat: remove comment --- CRM/Event/Form/Participant.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/CRM/Event/Form/Participant.php b/CRM/Event/Form/Participant.php index 8c49ac38ba..cc3f9c0b55 100644 --- a/CRM/Event/Form/Participant.php +++ b/CRM/Event/Form/Participant.php @@ -1022,14 +1022,12 @@ public static function formRule($values, $files, $self) { $errorMsg['contribution_status_id'] = ts("Please select a valid payment status before updating."); } - // validate trxn_id uniqueness when record_contribution is checked (AC-1, AC-2, AC-3) if (CRM_Utils_Array::value('record_contribution', $values) && !empty($values['trxn_id']) ) { $trxnId = $values['trxn_id']; $excludeContributionId = NULL; - // AC-3: When editing a participant that already has a payment linked, // exclude that participant's own contribution from the duplicate check. if ($self->_id && $self->_paymentId) { $excludeContributionId = CRM_Core_DAO::getFieldValue(