Skip to content

Instantly share code, notes, and snippets.

@KristaButler
Last active June 8, 2023 21:19
Show Gist options
  • Save KristaButler/022599bc1f7bc013e3d76a1752223f85 to your computer and use it in GitHub Desktop.
Save KristaButler/022599bc1f7bc013e3d76a1752223f85 to your computer and use it in GitHub Desktop.
Mepr Proration Tweaks
<?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