Skip to content

Commit

Permalink
FOSFASPRT-9: Fix pro rata calculation for membership payment plan
Browse files Browse the repository at this point in the history
  • Loading branch information
Muhammad Shahrukh committed Jun 12, 2024
1 parent 3a33e5e commit 9199088
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ protected function getInstalmentAmountCalculator(array $membershipTypes, $period
}

$instalmentAmountCalculator = new InstalmentAmountCalculator($calculator);
$instalmentAmountCalculator->getCalculator()->calculate();
$isNotQuickConfig = $this->getLineItemCount() > 1;
$instalmentAmountCalculator->getCalculator()->calculate(!$this->isUsingPriceSet() || $isNotQuickConfig);

return $instalmentAmountCalculator;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,4 +319,10 @@ public function setContributionToPayLater() {
}
}

protected function getLineItemCount(): int {
$lineItems = CRM_Utils_Array::value('line_item', $this->params, []);

return !empty($lineItems) ? count(array_values($lineItems)[0]) : 1;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,8 @@ private function handleNonMembershipTypeLineItem() {
}
}

protected function getLineItemCount(): int {
return CRM_Utils_Array::value('lineItemCount', $this->params, 1);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,15 @@ private function calculateProRatedAmount($amount, $duration, $diff) {
/**
* @throws Exception
*/
public function calculate() {
public function calculate(bool $calculateProRated = TRUE) {
foreach ($this->membershipTypes as $membershipType) {
$settings = CRM_MembershipExtras_SettingsManager::getMembershipTypeSettings($membershipType->id);
$membershipAmount = $membershipType->minimum_fee;
$taxAmount = $this->instalmentTaxAmountCalculator->calculateByMembershipType($membershipType, $membershipAmount);

$skipProRataUntilSetting = $settings[SettingField::ANNUAL_PRORATA_SKIP_ELEMENT] ?? NULL;
if (!empty($skipProRataUntilSetting) && !empty($skipProRataUntilSetting['M']) && $this->isWithinMembershipTypeProRataSkipPeriod($skipProRataUntilSetting)) {
if ((!empty($skipProRataUntilSetting) && !empty($skipProRataUntilSetting['M']) && $this->isWithinMembershipTypeProRataSkipPeriod($skipProRataUntilSetting))
|| !$calculateProRated) {
$amount = $membershipAmount;
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

interface CRM_MembershipExtras_Service_MembershipPeriodType_PeriodTypeCalculatorInterface {

public function calculate();
public function calculate(bool $calculateProRated = TRUE);

public function getAmount();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(array $membershipTypes) {
*
* @throws Exception
*/
public function calculate() {
public function calculate(bool $calculateProRated = TRUE) {
foreach ($this->membershipTypes as $membershipType) {
$amount = $membershipType->minimum_fee;
$taxAmount = $this->instalmentTaxAmountCalculator->calculateByMembershipType($membershipType, $membershipType->minimum_fee);
Expand Down
8 changes: 8 additions & 0 deletions membershipextras.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ function membershipextras_civicrm_pre($op, $objectName, $id, &$params) {
* options for now.
*/
static $contributionID = NULL;
static $lineItemCount = [];
if ($op === 'edit' && $objectName === 'Contribution') {
$contributionID = $id;
}
Expand All @@ -135,6 +136,10 @@ function membershipextras_civicrm_pre($op, $objectName, $id, &$params) {
static $isFirstPaymentPlanContribution = TRUE;
$isPaymentPlanPayment = CRM_MembershipExtras_Helper_InstalmentSchedule::isPaymentPlanPayment();
$isContributionCreation = ($objectName === 'Contribution' && $op === 'create');
if ($isContributionCreation) {
$lineItems = CRM_Utils_Array::value('line_item', $params, []);
$lineItemCount[] = !empty($lineItems) ? count(array_values($lineItems)[0]) : 1;
}
if ($isContributionCreation && $isPaymentPlanPayment && $isFirstPaymentPlanContribution) {
$paymentPlanProcessor = new CRM_MembershipExtras_Hook_Pre_MembershipPaymentPlanProcessor_Contribution($params);
$paymentPlanProcessor->createPaymentPlan();
Expand All @@ -146,6 +151,9 @@ function membershipextras_civicrm_pre($op, $objectName, $id, &$params) {
$lineItemContributionCreation = $objectName === 'LineItem' && $op === 'create' && !empty($params['contribution_id']);
$firstPaymentPlanContributionLineItemCreation = ($lineItemContributionCreation && (empty($firstPaymentPlanContributionId) || $firstPaymentPlanContributionId == $params['contribution_id']));
if ($firstPaymentPlanContributionLineItemCreation && $isPaymentPlanPayment) {
if (isset($lineItemCount[0])) {
$params['lineItemCount'] = $lineItemCount[0];
}
$paymentPlanProcessor = new CRM_MembershipExtras_Hook_Pre_MembershipPaymentPlanProcessor_LineItem($params);
$paymentPlanProcessor->alterLineItemParameters();
$firstPaymentPlanContributionId = $params['contribution_id'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,14 @@ class CRM_MembershipExtras_Hook_Pre_MembershipPaymentPlanProcessor_LineItemTest
*
* @throws Exception
*/
public function testProRatedPriceSetContributionLineItemOnCalculationByMonthFixedMembershipType() {
public function testProRatedPriceSetContributionLineItemOnCalculationWithModifiedMembershipFee() {
$params = $this->mockParams('fixed', 'year', FixedPeriodCalculator::BY_MONTHS);
//Since we test price set, line item amount can be different
//from membership type that attached to price field value
//the line total is changed here to test if the hook
//is working correct with different price.
$params['line_total'] = 240;

$memTypeObj = CRM_Member_BAO_MembershipType::findById($params['membership_type_id']);
$membershipTypeDurationCalculator = new MembershipTypeDurationCalculator($memTypeObj, new MembershipTypeDatesCalculator());
$diffInMonths = $membershipTypeDurationCalculator->calculateMonthsBasedOnDates(new DateTime($this->membership['start_date']));
$expectedLineToTal = MoneyUtilities::roundToPrecision($params['line_total'] / 12 * $diffInMonths, 2);
$expectedLineToTal = $params['line_total'];
$expectedTaxAmount = MoneyUtilities::roundToPrecision(($params['tax_rate'] / 100) * $expectedLineToTal, 2);

$_REQUEST['price_set_id'] = $this->priceSet['id'];
Expand All @@ -64,11 +60,7 @@ public function testProRatedPriceSetContributionLineItemOnCalculationByMonthFixe
*/
public function testProRatedPriceSetContributionLineItemOnCalculationByDaysFixedMembershipType() {
$params = $this->mockParams('fixed', 'year', FixedPeriodCalculator::BY_DAYS);
$memTypeObj = CRM_Member_BAO_MembershipType::findById($params['membership_type_id']);
$membershipTypeDurationCalculator = new MembershipTypeDurationCalculator($memTypeObj, new MembershipTypeDatesCalculator());
$membershipTypeDurationInDays = $membershipTypeDurationCalculator->calculateOriginalInDays();
$diffInDays = $membershipTypeDurationCalculator->calculateDaysBasedOnDates(new DateTime($this->membership['start_date']));
$expectedLineToTal = MoneyUtilities::roundToPrecision(($params['line_total'] / $membershipTypeDurationInDays) * $diffInDays, 2);
$expectedLineToTal = $params['line_total'];
$expectedTaxAmount = MoneyUtilities::roundToPrecision(($params['tax_rate'] / 100) * $expectedLineToTal, 2);

$_REQUEST['price_set_id'] = $this->priceSet['id'];
Expand Down

0 comments on commit 9199088

Please sign in to comment.