Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions CRM/Pledge/BAO/Pledge.php
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,48 @@ public static function cancel($pledgeID) {
);
}

/**
* Write off a pledge as completed (and any outstanding payments) as cancelled.
*
* @param int $pledgeID
*/
public static function close($pledgeID) {
$paymentIDs = self::findCancelablePayments($pledgeID);

//cancell all Cancel-able Payments
$status = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
$cancelled = array_search('Cancelled', $status);
CRM_Pledge_BAO_PledgePayment::updatePledgePaymentStatus($pledgeID, $paymentIDs, NULL,
$cancelled, 0, FALSE, TRUE
);

if (!empty($paymentIDs)) {
$ids = implode(', ', $paymentIDs);
$query = "
SELECT SUM(payment.scheduled_amount) as amount_due
FROM civicrm_pledge_payment payment
WHERE payment.id IN ($ids)
";

$amount = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', $pledgeID, 'amount') - CRM_Core_DAO::singleValueQuery($query);

//write off the pledge as completed by updating the status
//and the pledge amount
$results = \Civi\Api4\Pledge::update(FALSE)
->addValue('status_id:name', 'Completed')
->addValue('amount', $amount)
->addWhere('id', '=', $pledgeID)
->execute();

$results = \Civi\Api4\Activity::create(FALSE)
->addValue('activity_type_id:label', 'Pledge write-off')
->addValue('target_contact_id', [CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', $pledgeID, 'contact_id')])
->addValue('subject', CRM_Utils_Money::format($amount))
->addValue('source_contact_id', CRM_Core_Session::getLoggedInContactID())
->execute();
}
}

/**
* Find payments which can be safely canceled.
*
Expand Down
7 changes: 7 additions & 0 deletions CRM/Pledge/Page/Tab.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ public function run() {
CRM_Core_Session::setStatus(ts('Pledge has been cancelled and all scheduled (not completed) payments have been cancelled.'));
CRM_Utils_System::redirect($session->popUserContext());
}
elseif ($this->_action & CRM_Core_Action::CLOSE) {
//write off
CRM_Pledge_BAO_Pledge::close($this->_id);
$session = CRM_Core_Session::singleton();
$session->setStatus(ts('Pledge has been written off and all scheduled (not completed) payments have been cancelled and the pledge has been completed.<br />'));
CRM_Utils_System::redirect($session->popUserContext());
}
else {
$this->browse();
}
Expand Down
21 changes: 20 additions & 1 deletion CRM/Pledge/Selector/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ public static function &links() {

$extraParams = ($key) ? "&key={$key}" : NULL;

$closeExtra = ts('Writing off this pledge will also cancel any scheduled (and not completed) pledge payments.') . ' ' . ts('This action cannot be undone.') . ' ' . ts('Do you want to continue?');
$cancelExtra = ts('Cancelling this pledge will also cancel any scheduled (and not completed) pledge payments.') . ' ' . ts('This action cannot be undone.') . ' ' . ts('Do you want to continue?');
self::$_links = [
CRM_Core_Action::VIEW => [
Expand All @@ -190,6 +191,15 @@ public static function &links() {
'weight' => -10,
'is_active' => TRUE,
],
CRM_Core_Action::CLOSE => [
'name' => ts('Write Off'),
'url' => 'civicrm/contact/view/pledge',
'qs' => 'reset=1&action=close&id=%%id%%&cid=%%cid%%&context=%%cxt%%' . $extraParams,
'extra' => 'onclick = "return confirm(\'' . $closeExtra . '\');"',
'title' => ts('Write Off Pledge'),
'weight' => 10,
'is_active' => !in_array('Cancel', $hideOption, TRUE),
],
CRM_Core_Action::DETACH => [
'name' => ts('Cancel'),
'url' => 'civicrm/contact/view/pledge',
Expand All @@ -208,6 +218,15 @@ public static function &links() {
'is_active' => TRUE,
],
];

$status = $args[2] ?? '';
if (in_array($status, [2, 6])) {
self::$_links[CRM_Core_Action::CLOSE]['is_active'] = FALSE;
}
if (in_array($status, [5])) {
self::$_links[CRM_Core_Action::DETACH]['is_active'] = FALSE;
}

return self::$_links;
}

Expand Down Expand Up @@ -325,7 +344,7 @@ public function &getRows($action, $offset, $rowCount, $sort, $output = NULL) {

$row['checkbox'] = CRM_Core_Form::CB_PREFIX . $result->pledge_id;

$row['action'] = CRM_Core_Action::formLink(self::links($hideOption, $this->_key),
$row['action'] = CRM_Core_Action::formLink(self::links($hideOption, $this->_key, $row['pledge_status_id']),
$mask,
[
'id' => $result->pledge_id,
Expand Down
11 changes: 11 additions & 0 deletions CRM/Upgrade/Incremental/sql/6.18.alpha1.mysql.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,14 @@ INSERT IGNORE INTO civicrm_state_province (country_id, abbreviation, name) VALUE
(@country_id, 'F', 'Bolívar'),
(@country_id, 'R', 'Sucre'),
(@country_id, 'Z', 'Amazonas');

-- dev/core#3871 : add activity for 'Write-off' feature for pledges
SELECT @option_group_id_activity_type := max(id) from civicrm_option_group where name = 'activity_type';
SELECT @max_val := MAX(ROUND(op.value)) FROM civicrm_option_value op WHERE op.option_group_id = @option_group_id_activity_type;
SELECT @max_wt := max(weight) from civicrm_option_value where option_group_id=@option_group_id_activity_type;
SELECT @pledgeCompId := id FROM `civicrm_component` where `name` like 'CiviPledge';

INSERT INTO civicrm_option_value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will insert duplicates if the upgrade step is run twice. You could do something like IF NOT EXISTS (SELECT ...), or can always do it in php.

(option_group_id, {localize field='label'}label{/localize}, value, name, weight, filter, component_id)
VALUES
(@option_group_id_activity_type, {localize}'{ts escape="sql"}Pledge write-off{/ts}'{/localize}, @max_val+1, 'Pledge write-off', @max_wt+1, 0, @pledgeCompId);
Loading