Escape everything that should be escaped. Add nonce checks where needed. Sanitize all inputs. Apply Code style changes across the codebase. Correct many deprecation notices. Optimize load order of many filters.
500 lines
12 KiB
PHP
500 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* Financial Functions
|
|
*
|
|
* @package WP_Ultimo\Functions
|
|
* @since 2.0.0
|
|
*/
|
|
|
|
// Exit if accessed directly
|
|
defined('ABSPATH') || exit;
|
|
|
|
use WP_Ultimo\Database\Payments\Payment_Status;
|
|
use WP_Ultimo\Database\Memberships\Membership_Status;
|
|
|
|
/**
|
|
* Calculates the Monthly Recurring Revenue of the network.
|
|
*
|
|
* @since 2.0.0
|
|
* @return float
|
|
*/
|
|
function wu_calculate_mrr() {
|
|
|
|
$total_mrr = 0;
|
|
|
|
$memberships = wu_get_memberships(
|
|
[
|
|
'recurring' => true,
|
|
'status__in' => [
|
|
Membership_Status::ACTIVE,
|
|
],
|
|
]
|
|
);
|
|
|
|
foreach ($memberships as $membership) {
|
|
$recurring_amount = $membership->get_amount();
|
|
|
|
if ( ! $membership->is_recurring()) {
|
|
continue;
|
|
}
|
|
|
|
$duration = $membership->get_duration() ?: 1;
|
|
|
|
$duration_unit = $membership->get_duration_unit();
|
|
|
|
$normalized_duration_unit = wu_convert_duration_unit_to_month($duration_unit);
|
|
|
|
$mrr = $recurring_amount / ($duration * $normalized_duration_unit);
|
|
|
|
$total_mrr += $mrr;
|
|
}
|
|
|
|
return $total_mrr;
|
|
}
|
|
|
|
/**
|
|
* Converts the duration unit strings such as 'day', 'year' and such into
|
|
* a integer/float representing the amount of monhts.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $duration_unit The duration unit.
|
|
* @return float
|
|
*/
|
|
function wu_convert_duration_unit_to_month($duration_unit) {
|
|
|
|
$months = 1;
|
|
|
|
switch ($duration_unit) {
|
|
case 'day':
|
|
$months = 1 / 30;
|
|
break;
|
|
case 'week':
|
|
$months = 1 / 4;
|
|
break;
|
|
case 'month':
|
|
$months = 1;
|
|
break;
|
|
case 'year':
|
|
$months = 12;
|
|
break;
|
|
default:
|
|
$months = $months;
|
|
break;
|
|
}
|
|
|
|
return $months;
|
|
}
|
|
|
|
/**
|
|
* Calculates the Annual Recurring Revenue.
|
|
*
|
|
* It is basically MRR * 12.
|
|
*
|
|
* @since 2.0.0
|
|
* @return float
|
|
*/
|
|
function wu_calculate_arr() {
|
|
|
|
return wu_calculate_mrr() * 12;
|
|
}
|
|
|
|
/**
|
|
* Calculates the total revenue.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $start_date The start date for the stat.
|
|
* @param string $end_date The end date for the stat.
|
|
* @param boolean $inclusive If true, will include payments on the start and end date.
|
|
* @return float
|
|
*/
|
|
function wu_calculate_revenue($start_date = false, $end_date = false, $inclusive = true) {
|
|
|
|
$total_revenue = 0;
|
|
|
|
$query_args = [
|
|
'fields' => ['total'],
|
|
'date_query' => [],
|
|
'status__in' => [
|
|
Payment_Status::COMPLETED,
|
|
Payment_Status::PARTIAL,
|
|
],
|
|
];
|
|
|
|
if ($start_date) {
|
|
$query_args['date_query']['column'] = 'date_created';
|
|
$query_args['date_query']['after'] = $start_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
if ($end_date) {
|
|
$query_args['date_query']['column'] = 'date_created';
|
|
$query_args['date_query']['before'] = $end_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
$payments = wu_get_payments($query_args);
|
|
|
|
foreach ($payments as $payment) {
|
|
$total_revenue += (float) $payment->total;
|
|
}
|
|
|
|
return $total_revenue;
|
|
}
|
|
|
|
/**
|
|
* Calculates the total refunds.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $start_date The start date for the stat.
|
|
* @param string $end_date The end date for the stat.
|
|
* @param boolean $inclusive If true, will include payments on the start and end date.
|
|
* @return float
|
|
*/
|
|
function wu_calculate_refunds($start_date = false, $end_date = false, $inclusive = true) {
|
|
|
|
$total_revenue = 0;
|
|
|
|
$query_args = [
|
|
'fields' => ['refund_total'],
|
|
'date_query' => [],
|
|
'status__in' => [
|
|
Payment_Status::REFUND,
|
|
Payment_Status::PARTIAL_REFUND,
|
|
],
|
|
];
|
|
|
|
if ($start_date) {
|
|
$query_args['date_query']['column'] = 'date_created';
|
|
$query_args['date_query']['after'] = $start_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
if ($end_date) {
|
|
$query_args['date_query']['column'] = 'date_created';
|
|
$query_args['date_query']['before'] = $end_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
$payments = wu_get_payments($query_args);
|
|
|
|
foreach ($payments as $payment) {
|
|
$total_revenue += -(float) $payment->refund_total;
|
|
}
|
|
|
|
return $total_revenue;
|
|
}
|
|
|
|
/**
|
|
* Calculates the taxes collected grouped by the rate.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $start_date The start date to compile data.
|
|
* @param string $end_date The end date to compile data.
|
|
* @param boolean $inclusive To include or not the start and end date.
|
|
* @return array
|
|
*/
|
|
function wu_calculate_taxes_by_rate($start_date = false, $end_date = false, $inclusive = true) {
|
|
|
|
$query_args = [
|
|
'date_query' => [],
|
|
];
|
|
|
|
if ($start_date) {
|
|
$query_args['date_query']['after'] = $start_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
if ($end_date) {
|
|
$query_args['date_query']['before'] = $end_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
$order = 0;
|
|
|
|
$taxes_paid_list = [];
|
|
|
|
$line_items_groups = \WP_Ultimo\Checkout\Line_Item::get_line_items($query_args);
|
|
|
|
foreach ($line_items_groups as $line_items_group) {
|
|
++$order;
|
|
|
|
foreach ($line_items_group as $line_item) {
|
|
$tax_name = $line_item->get_tax_label();
|
|
|
|
if ($line_item->get_tax_rate() <= 0) {
|
|
continue;
|
|
}
|
|
|
|
if ( ! wu_get_isset($taxes_paid_list, $tax_name)) {
|
|
$taxes_paid_list[ $tax_name ] = [
|
|
'title' => $tax_name,
|
|
'country' => '',
|
|
'state' => '',
|
|
'order_count' => $order,
|
|
'tax_rate' => $line_item->get_tax_rate(),
|
|
'tax_total' => $line_item->get_tax_total(),
|
|
];
|
|
} else {
|
|
$taxes_paid_list[ $tax_name ]['tax_total'] += $line_item->get_tax_total();
|
|
$taxes_paid_list[ $tax_name ]['order_count'] += $order;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $taxes_paid_list;
|
|
}
|
|
|
|
/**
|
|
* Aggregate financial data on a per product basis.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $start_date The start date to compile data.
|
|
* @param string $end_date The end date to compile data.
|
|
* @param boolean $inclusive To include or not the start and end date.
|
|
* @return array
|
|
*/
|
|
function wu_calculate_financial_data_by_product($start_date = false, $end_date = false, $inclusive = true) {
|
|
|
|
$query_args = [
|
|
'date_query' => [],
|
|
'payment_status' => Payment_Status::COMPLETED,
|
|
];
|
|
|
|
if ($start_date) {
|
|
$query_args['date_query']['after'] = $start_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
if ($end_date) {
|
|
$query_args['date_query']['before'] = $end_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
$line_items_groups = \WP_Ultimo\Checkout\Line_Item::get_line_items($query_args);
|
|
|
|
$data = [];
|
|
|
|
$products = wu_get_products();
|
|
|
|
foreach ($products as $product) {
|
|
$data[ $product->get_id() ] = [
|
|
'label' => $product->get_name(),
|
|
'revenue' => 0,
|
|
];
|
|
}
|
|
|
|
foreach ($line_items_groups as $line_items_group) {
|
|
foreach ($line_items_group as $line_item) {
|
|
$product_id = $line_item->get_product_id();
|
|
|
|
if (empty($product_id)) {
|
|
continue;
|
|
}
|
|
|
|
if ( ! wu_get_isset($data, $product_id)) {
|
|
continue;
|
|
}
|
|
|
|
$data[ $product_id ]['revenue'] += $line_item->get_total();
|
|
}
|
|
}
|
|
|
|
uasort($data, fn($a, $b) => wu_sort_by_column($b, $a, 'revenue'));
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Calculates the taxes collected grouped by date.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $start_date The start date to compile data.
|
|
* @param string $end_date The end date to compile data.
|
|
* @param boolean $inclusive To include or not the start and end date.
|
|
* @return array
|
|
*/
|
|
function wu_calculate_taxes_by_day($start_date = false, $end_date = false, $inclusive = true) {
|
|
|
|
$query_args = [
|
|
'date_query' => [],
|
|
];
|
|
|
|
if ($start_date) {
|
|
$query_args['date_query']['after'] = $start_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
if ($end_date) {
|
|
$query_args['date_query']['before'] = $end_date;
|
|
$query_args['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
$line_items_groups = \WP_Ultimo\Checkout\Line_Item::get_line_items($query_args);
|
|
|
|
$data = [];
|
|
|
|
$period = new \DatePeriod(
|
|
new \DateTime($start_date),
|
|
new \DateInterval('P1D'),
|
|
new \DateTime($end_date . ' 23:59:59')
|
|
);
|
|
|
|
$days = array_reverse(iterator_to_array($period));
|
|
|
|
foreach ($days as $day_datetime) {
|
|
$data[ $day_datetime->format('Y-m-d') ] = [
|
|
'order_count' => 0,
|
|
'total' => 0,
|
|
'tax_total' => 0,
|
|
'net_profit' => 0,
|
|
];
|
|
}
|
|
|
|
foreach ($line_items_groups as $line_items_group) {
|
|
foreach ($line_items_group as $line_item) {
|
|
$date = gmdate('Y-m-d', strtotime($line_item->get_date_created()));
|
|
|
|
if ( ! wu_get_isset($data, $date)) {
|
|
$data[ $date ] = [
|
|
'order_count' => 0,
|
|
'total' => $line_item->get_total(),
|
|
'tax_total' => $line_item->get_tax_total(),
|
|
'net_profit' => $line_item->get_total() - $line_item->get_tax_total(),
|
|
];
|
|
} else {
|
|
$data[ $date ]['order_count'] += 1;
|
|
$data[ $date ]['total'] += $line_item->get_total();
|
|
$data[ $date ]['tax_total'] += $line_item->get_tax_total();
|
|
$data[ $date ]['net_profit'] += $line_item->get_total() - $line_item->get_tax_total();
|
|
}
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Calculates the taxes collected this year, segregated by month.
|
|
*
|
|
* @since 2.0.0
|
|
* @return array
|
|
*/
|
|
function wu_calculate_taxes_by_month() {
|
|
|
|
$cache = get_site_transient('wu_tax_monthly_stats');
|
|
|
|
if (is_array($cache)) {
|
|
return $cache;
|
|
}
|
|
|
|
$query_args = [
|
|
'date_query' => [
|
|
'after' => 'first day of January this year',
|
|
'before' => 'last day of December this year',
|
|
'inclusive' => true,
|
|
],
|
|
];
|
|
|
|
$line_items_groups = \WP_Ultimo\Checkout\Line_Item::get_line_items($query_args);
|
|
|
|
$data = [];
|
|
|
|
$period = new \DatePeriod(
|
|
new \DateTime($query_args['date_query']['after']),
|
|
new \DateInterval('P1M'),
|
|
new \DateTime($query_args['date_query']['before'])
|
|
);
|
|
|
|
$months = iterator_to_array($period);
|
|
|
|
foreach ($months as $month_datetime) {
|
|
$data[ $month_datetime->format('n') ] = [
|
|
'order_count' => 0,
|
|
'total' => 0,
|
|
'tax_total' => 0,
|
|
'net_profit' => 0,
|
|
];
|
|
}
|
|
|
|
foreach ($line_items_groups as $line_items_group) {
|
|
foreach ($line_items_group as $line_item) {
|
|
$date = gmdate('n', strtotime((string) $line_item->date_created));
|
|
|
|
if ( ! wu_get_isset($data, $date)) {
|
|
$data[ $date ] = [
|
|
'order_count' => 0,
|
|
'total' => $line_item->get_total(),
|
|
'tax_total' => $line_item->get_tax_total(),
|
|
'net_profit' => $line_item->get_total() - $line_item->get_tax_total(),
|
|
];
|
|
} else {
|
|
$data[ $date ]['order_count'] += 1;
|
|
$data[ $date ]['total'] += $line_item->get_total();
|
|
$data[ $date ]['tax_total'] += $line_item->get_tax_total();
|
|
$data[ $date ]['net_profit'] += $line_item->get_total() - $line_item->get_tax_total();
|
|
}
|
|
}
|
|
}
|
|
|
|
set_site_transient('wu_tax_monthly_stats', $data);
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Returns the number of sign-ups by form slug.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param string $start_date The start date to compile data.
|
|
* @param string $end_date The end date to compile data.
|
|
* @param boolean $inclusive To include or not the start and end date.
|
|
* @return array
|
|
*/
|
|
function wu_calculate_signups_by_form($start_date = false, $end_date = false, $inclusive = true) {
|
|
|
|
global $wpdb;
|
|
|
|
$query = [
|
|
'date_query' => [],
|
|
];
|
|
|
|
if ($start_date) {
|
|
$query['date_query']['after'] = $start_date;
|
|
$query['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
if ($end_date) {
|
|
$query['date_query']['before'] = $end_date;
|
|
$query['date_query']['inclusive'] = $inclusive;
|
|
}
|
|
|
|
$date_query = new \WP_Date_Query($query['date_query']);
|
|
|
|
$date_query_sql = $date_query->get_sql();
|
|
|
|
$date_query_sql = str_replace($wpdb->base_prefix . 'posts.post_date', 'date_registered', $date_query_sql);
|
|
|
|
// phpcs:disable;
|
|
$query_sql = "
|
|
SELECT signup_form, COUNT(id) as count
|
|
FROM {$wpdb->base_prefix}wu_customers as d
|
|
WHERE 1 = 1
|
|
AND signup_form IS NOT NULL
|
|
{$date_query_sql}
|
|
GROUP BY signup_form
|
|
ORDER BY count DESC
|
|
";
|
|
|
|
$results = $wpdb->get_results($query_sql); // phpcs:ignore
|
|
|
|
return $results;
|
|
|
|
}
|