Skip to content

Instantly share code, notes, and snippets.

@mattallan
Last active November 21, 2017 03:04
Show Gist options
  • Save mattallan/9faf640bc2371b56ef61d0a1a5de6f66 to your computer and use it in GitHub Desktop.
Save mattallan/9faf640bc2371b56ef61d0a1a5de6f66 to your computer and use it in GitHub Desktop.
Estimate billing periods between two timestamps (for WCS Resource) + unit tests
<?php
/**
* Estimate the billing periods between two timestamps
*
* @since 1.0
* @param int $from_timestamp
* @param int $to_timestamp
* @param string $billing_period
* @param string $billing_interval
* @return array
*/
public function estimate_resource_billing_periods_between( $from_timestamp, $to_timestamp, $billing_period, $billing_interval ) {
$billing_periods_between = array();
$counter = 0;
while ( $from_timestamp < $to_timestamp && $counter < 100 ) {
$current_billing_period = array( 'from_timestamp' => $from_timestamp );
$next_timestamp = wcs_add_time( $billing_interval, $billing_period, $from_timestamp ); // use the same function used to calculate subscription billing periods to work out the exact billing
if ( $to_timestamp < $next_timestamp ) {
$current_billing_period['to_timestamp'] = $to_timestamp;
$current_billing_period['period_fraction'] = round( ( $from_timestamp - $to_timestamp ) / ( $from_timestamp - $next_timestamp ), 2);
} else {
$current_billing_period['to_timestamp'] = ( $to_timestamp - $next_timestamp > DAY_IN_SECONDS ) ? $next_timestamp : $to_timestamp;
$current_billing_period['period_fraction'] = 1;
}
$from_timestamp = $next_timestamp;
$billing_periods_between[] = $current_billing_period;
if ( $to_timestamp - $from_timestamp < DAY_IN_SECONDS ) {
break;
}
$counter++;
}
return $billing_periods_between;
}
public function provider_get_resource_billing_periods_between() {
return array(
// from and to timestamps exactly 1 month
0 => array(
'from_timestamp' => strtotime( '2017-09-01 14:21:40' ),
'to_timestamp' => strtotime( '2017-10-01 14:21:40' ),
'billing_period' => 'month',
'billing_interval' => 1,
'expected_result' => array(
array(
'from_timestamp' => strtotime( '2017-09-01 14:21:40' ),
'to_timestamp' => strtotime( '2017-10-01 14:21:40' ),
'period_fraction' => 1
)
),
),
// from and to timstamps just over 1 month (20mins over)
1 => array(
'from_timestamp' => strtotime( '2017-09-01 14:21:40' ),
'to_timestamp' => strtotime( '2017-10-01 14:40:40' ),
'billing_period' => 'month',
'billing_interval' => 1,
'expected_result' => array(
array(
'from_timestamp' => strtotime( '2017-09-01 14:21:40' ),
'to_timestamp' => strtotime( '2017-10-01 14:40:40' ),
'period_fraction' => 1
)
),
),
// ~1.5 billing periods found between the two dates
2 => array(
'from_timestamp' => strtotime( '2017-09-14 14:21:40' ),
'to_timestamp' => strtotime( '2017-11-01 14:40:40' ),
'billing_period' => 'month',
'billing_interval' => 1,
'expected_result' => array(
array(
'from_timestamp' => strtotime( '2017-09-14 14:21:40' ),
'to_timestamp' => strtotime( '2017-10-14 14:21:40' ),
'period_fraction' => 1
),
array(
'from_timestamp' => strtotime( '2017-10-14 14:21:40' ),
'to_timestamp' => strtotime( '2017-11-01 14:40:40' ),
'period_fraction' => 0.58
),
),
),
// If for some reason the renewal is triggered 1 hour early - the billing period should still be 1
3 => array(
'from_timestamp' => strtotime( '2017-09-14 14:21:40' ),
'to_timestamp' => strtotime( '2017-10-14 12:40:40' ),
'billing_period' => 'month',
'billing_interval' => 1,
'expected_result' => array(
array(
'from_timestamp' => strtotime( '2017-09-14 14:21:40' ),
'to_timestamp' => strtotime( '2017-10-14 12:40:40' ),
'period_fraction' => 1
),
),
),
// If the billing period is only 15 days but the subscription renews monthly
4 => array(
'from_timestamp' => strtotime( '2017-09-01 14:21:40' ),
'to_timestamp' => strtotime( '2017-09-16 12:40:40' ),
'billing_period' => 'month',
'billing_interval' => 1,
'expected_result' => array(
array(
'from_timestamp' => strtotime( '2017-09-01 14:21:40' ),
'to_timestamp' => strtotime( '2017-09-16 12:40:40' ),
'period_fraction' => 0.5
),
),
),
);
}
/**
* Make sure get_days_in_period() is calculating the number of days properly
*
*
* @dataProvider provider_get_resource_billing_periods_between
* @group billing_periods_between
*/
public function test_get_resource_billing_periods_between( $from_timestamp, $to_timestamp, $billing_period, $billing_interval, $expected_result ) {
$resource_mock = $this->getMockBuilder( 'WCSR_Resource' )->setMethods( array( 'get_date_created' ) )->disableOriginalConstructor()->getMock();
$this->assertEquals( $expected_result, $resource_mock->get_resource_billing_periods_between( $from_timestamp, $to_timestamp, $billing_period, $billing_interval ) );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment