PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.16.9
GiveWP – Donation Plugin and Fundraising Platform v4.16.9
4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 All 255 releases
give / src / Subscriptions / Actions / CalculateProjectedAnnualRevenue.php

CalculateProjectedAnnualRevenue.php in GiveWP – Donation Plugin and Fundraising Platform 4.16.9, at src/Subscriptions/Actions/CalculateProjectedAnnualRevenue.php

104 lines 3.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Give\Subscriptions\Actions;
6
7 use DateTime;
8 use Exception;
9 use Give\DonationForms\DonationQuery;
10 use Give\Donations\ValueObjects\DonationStatus;
11 use Give\Donations\ValueObjects\DonationMetaKeys;
12 use Give\Framework\QueryBuilder\QueryBuilder;
13 use Give\Framework\Support\ValueObjects\Money;
14 use Give\Subscriptions\Models\Subscription;
15 use Give\Subscriptions\ValueObjects\SubscriptionPeriod;
16
17 /**
18 * Calculates the projected annual revenue for a subscription based on completed donations
19 * from the current year and estimated remaining donations until the end of the year.
20 *
21 * @since 4.8.0
22 */
23 class CalculateProjectedAnnualRevenue
24 {
25 /**
26 * Calculate the projected annual revenue for a subscription.
27 *
28 * @param Subscription $subscription
29 * @return Money
30 */
31 public function __invoke(Subscription $subscription): Money
32 {
33 try {
34 $currentYear = (int) date('Y');
35 $yearStart = new DateTime("January 1st, {$currentYear}");
36 $yearEnd = new DateTime("December 31st, {$currentYear} 23:59:59");
37
38 // Get completed donations from January 1st of current year to now
39 $completedAmount = (new DonationQuery())
40 ->whereIn("post_status", [
41 DonationStatus::COMPLETE,
42 DonationStatus::RENEWAL
43 ])
44 ->whereIn("ID", function (QueryBuilder $builder) use ($subscription) {
45 $builder
46 ->select("donation_id")
47 ->from("give_donationmeta")
48 ->where("meta_key", DonationMetaKeys::SUBSCRIPTION_ID)
49 ->where("meta_value", $subscription->id);
50 })
51 ->between(
52 $yearStart->format("Y-m-d H:i:s"),
53 $yearEnd->format("Y-m-d H:i:s")
54 )
55 ->sumIntendedAmount();
56
57 $completedAmount = Money::fromDecimal($completedAmount, $subscription->amount->getCurrency()->getCode());
58
59 // Calculate projected amount based on remaining donations this year
60 $remainingInstallments = $this->calculateRemainingInstallmentsUntilEndOfYear($subscription);
61
62 $projectedAmount = $subscription->intendedAmount()->multiply($remainingInstallments);
63
64 return $completedAmount->add($projectedAmount);
65 } catch (Exception $e) {
66 // Return zero Money object on error
67 return new Money(0, $subscription->amount->getCurrency()->getCode());
68 }
69 }
70
71 /**
72 * Calculate the remaining installments until the end of the current year.
73 *
74 * @since 4.8.0
75 */
76 private function calculateRemainingInstallmentsUntilEndOfYear(Subscription $subscription): int
77 {
78 $nextRenewal = clone $subscription->renewsAt;
79 $currentYear = (new DateTime())->format('Y');
80 $yearEnd = new DateTime('last day of December ' . $currentYear . ' 23:59:59');
81 $modifier = $subscription->period->isQuarter()
82 ? ($subscription->frequency * 3) . ' ' . SubscriptionPeriod::MONTH
83 : $subscription->frequency . ' ' . $subscription->period->getValue();
84
85 $installments = 0;
86
87 while ($nextRenewal <= $yearEnd) {
88 if ($nextRenewal->format('Y') === $currentYear) {
89 $installments++;
90 }
91
92 $nextRenewal->modify($modifier);
93 }
94
95 if ($subscription->installments > 0) {
96 $paidInstallments = $subscription->donations()->count();
97 $remainingInstallments = max(0, $subscription->installments - $paidInstallments);
98 $installments = min($installments, $remainingInstallments);
99 }
100
101 return $installments;
102 }
103 }
104