Last active
June 8, 2023 21:19
-
-
Save KristaButler/022599bc1f7bc013e3d76a1752223f85 to your computer and use it in GitHub Desktop.
Mepr Proration Tweaks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
add_filter('mepr-allow-multiple-upgrades-downgrades', function($allow, $user, $sub_in_group, $product) { | |
return true; | |
}, 10, 4); | |
add_filter( 'mepr-proration', function ( $prorations, $old_amount, $new_amount, $old_period, $new_period, $old_days_left, $old_sub, $new_sub, $reset_period ) { | |
//This only works for recurring to recurring upgrades during a prorate trial, | |
//so if that's not the case - just return the usual proration and skip all this. | |
//NOTE: If the old sub had a trial that the proration was applied to - this won't work | |
if ( isset( $old_sub ) && isset( $new_sub ) && $new_sub->is_upgrade() && $old_sub->prorated_trial && $old_sub->in_trial() ) { | |
//We want to allow upgrade during proration period - so basically the only difference is that | |
//Instead of using the amount of the last trasaction - we need to the total of all previous transactions. | |
//My thinking: A - first subscription, B - first upgrade, C - this upgrade | |
//The left over amount from A was applied when purchasing B, so the user did pay the full price of B | |
//So if we use the full price for B when we upgrade C we *should* get the correct amount using the | |
//same math. | |
$old_amount = $old_sub->price; | |
$old_period = $old_sub->days_in_this_period(); //Resetting this just in case | |
if ($old_days_left > $old_period) { //This is a fix to avoid weird prorations on if the upgrade on the same day. | |
$old_days_left = $old_period; | |
} | |
// By default days left in the new sub are equal to the days left in the old | |
$new_days_left = $old_days_left; | |
if(is_numeric($old_period) && is_numeric($new_period) && $new_sub !== false && $old_amount > 0) { | |
// recurring to recurring | |
if($old_days_left > $new_period || $reset_period) { | |
// What if the days left exceed the $new_period? | |
// And the new outstanding amount is greater? | |
// Days left should be reset to the new period | |
$new_days_left = $new_period; | |
} | |
$old_per_day_amount = $old_amount / $old_period; | |
$new_per_day_amount = $new_amount / $new_period; | |
$old_outstanding_amount = $old_per_day_amount * $old_days_left; | |
$new_outstanding_amount = $new_per_day_amount * $new_days_left; | |
$proration = $new_outstanding_amount - $old_outstanding_amount; | |
$days = $new_days_left; | |
if($proration < 0) { | |
$proration = 0; | |
if($new_per_day_amount > 0 && $old_outstanding_amount > 0) { | |
$days = $old_outstanding_amount / $new_per_day_amount; | |
} | |
else { | |
$days = ($new_amount > 0 ? ((abs($proration)+$new_amount)/$new_amount)*$new_days_left : 0); | |
} | |
} | |
} | |
elseif(is_numeric($old_period) && is_numeric($old_days_left) && ($new_period == 'lifetime' || $new_sub === false) && $old_amount > 0) { | |
// recurring to lifetime | |
// apply outstanding amount to lifetime purchase | |
// calculate amount of money left on old sub | |
$old_outstanding_amount = (($old_amount / $old_period) * $old_days_left); | |
$proration = max($new_amount - $old_outstanding_amount, 0.00); | |
$days = 0; // we just do this thing | |
} | |
elseif($old_period == 'lifetime' && is_numeric($new_period) && $old_amount > 0) { | |
// lifetime to recurring{ | |
$proration = max($new_amount - $old_amount, 0.00); | |
$days = $new_period; //(is_numeric($old_days_left) && !$reset_period)?$old_days_left:$new_period; | |
} | |
elseif($old_period == 'lifetime' && $new_period == 'lifetime' && $old_amount > 0) { | |
// lifetime to lifetime | |
$proration = max(($new_amount - $old_amount), 0.00); | |
$days = 0; // We be lifetime brah | |
} | |
else { | |
// Default | |
$proration = 0; | |
$days = 0; | |
} | |
// Don't allow amounts that are less than a dollar but greater than zero | |
$proration = (($proration > 0.00 && $proration < 1.00) ? 1.00 : $proration); | |
$days = ceil($days); | |
$proration = MeprUtils::format_float($proration); | |
//Make sure we don't do more than 1 year on days | |
if($days > 365) { $days = 365; } | |
$prorations = (object)compact('proration', 'days'); | |
} | |
return $prorations; | |
}, 10, 9 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment