diff --git a/src/DonationForms/DataTransferObjects/DonationFormGoalData.php b/src/DonationForms/DataTransferObjects/DonationFormGoalData.php index 77f3ab5fc9..44e4660406 100644 --- a/src/DonationForms/DataTransferObjects/DonationFormGoalData.php +++ b/src/DonationForms/DataTransferObjects/DonationFormGoalData.php @@ -4,6 +4,7 @@ use Give\DonationForms\Properties\FormSettings; use Give\DonationForms\Repositories\DonationFormRepository; +use Give\DonationForms\ValueObjects\GoalProgressType; use Give\DonationForms\ValueObjects\GoalType; use Give\Framework\Support\Contracts\Arrayable; @@ -32,6 +33,18 @@ class DonationFormGoalData implements Arrayable * @var int */ public $targetAmount; + /** + * @var GoalProgressType + */ + public $goalProgressType; + /** + * @var string|null + */ + public $goalStartDate; + /** + * @var string|null + */ + public $goalEndDate; /** * @since 3.0.0 @@ -43,6 +56,9 @@ public function __construct(int $formId, FormSettings $formSettings) $this->isEnabled = $formSettings->enableDonationGoal ?? false; $this->goalType = $formSettings->goalType ?? GoalType::AMOUNT(); $this->targetAmount = $this->formSettings->goalAmount ?? 0; + $this->goalProgressType = $this->formSettings->goalProgressType ?? GoalProgressType::ALL_TIME(); + $this->goalStartDate = $this->formSettings->goalStartDate ?? null; + $this->goalEndDate = $this->formSettings->goalEndDate ?? null; } /** @@ -68,7 +84,9 @@ public function getCurrentAmount() return $donationFormRepository->getTotalNumberOfDonorsFromSubscriptions($this->formId); case GoalType::AMOUNT(): default: - return $donationFormRepository->getTotalRevenue($this->formId); + return $this->goalProgressType->isAllTime() + ? $donationFormRepository->getTotalRevenue($this->formId) + : $donationFormRepository->getTotalRevenueForDateRange($this->formId,$this->goalStartDate, $this->goalEndDate); endswitch; } diff --git a/src/DonationForms/DonationQuery.php b/src/DonationForms/DonationQuery.php new file mode 100644 index 0000000000..b4ed4ac58f --- /dev/null +++ b/src/DonationForms/DonationQuery.php @@ -0,0 +1,79 @@ +form(1816) + * ->between('2024-02-00', '2024-02-23') + * ->sumIntendedAmount(); + */ +class DonationQuery extends QueryBuilder +{ + /** + * @unreleased + */ + public function __construct() + { + $this->from('posts', 'donation'); + } + + /** + * An opinionated join method for the donation meta table. + * @unreleased + */ + public function joinMeta($key, $alias) + { + $this->join(function (JoinQueryBuilder $builder) use ($key, $alias) { + $builder + ->leftJoin('give_donationmeta', $alias) + ->on('donation.ID', $alias . '.donation_id') + ->andOn($alias . '.meta_key', $key, true); + }); + return $this; + } + + /** + * An opinionated where method for the donation form ID meta field. + * @unreleased + */ + public function form($formId) + { + $this->joinMeta('_give_payment_form_id', 'formId'); + $this->where('formId.meta_value', $formId); + return $this; + } + + /** + * An opinionated whereBetween method for the completed date meta field. + * @unreleased + */ + public function between($startDate, $endDate) + { + $this->joinMeta('_give_completed_date', 'completed'); + $this->whereBetween('completed.meta_value', $startDate, $endDate); + return $this; + } + + /** + * Returns a calculated sum of the intended amounts (without recovered fees) for the donations. + * @unreleased + * @return int|float + */ + public function sumIntendedAmount() + { + $this->joinMeta('_give_payment_total', 'amount'); + $this->joinMeta('_give_fee_donation_amount', 'intendedAmount'); + return $this->sum( + 'COALESCE(intendedAmount.meta_value, amount.meta_value)' + ); + } +} diff --git a/src/DonationForms/Repositories/DonationFormRepository.php b/src/DonationForms/Repositories/DonationFormRepository.php index 352cd0c17c..60229fbe38 100644 --- a/src/DonationForms/Repositories/DonationFormRepository.php +++ b/src/DonationForms/Repositories/DonationFormRepository.php @@ -4,6 +4,7 @@ use Closure; use Give\DonationForms\Actions\ConvertDonationFormBlocksToFieldsApi; +use Give\DonationForms\DonationQuery; use Give\DonationForms\Models\DonationForm; use Give\DonationForms\ValueObjects\DonationFormMetaKeys; use Give\Donations\ValueObjects\DonationMetaKeys; @@ -393,10 +394,16 @@ public function getTotalNumberOfDonorsFromSubscriptions(int $formId): int */ public function getTotalNumberOfDonations(int $formId): int { - return DB::table('posts') - ->leftJoin('give_donationmeta', 'ID', 'donation_id') - ->where('meta_key', DonationMetaKeys::FORM_ID) - ->where('meta_value', $formId) + return (new DonationQuery) + ->form($formId) + ->count(); + } + + public function getTotalNumberOfDonationsForDateRange(int $formId, string $startDate, string $endDate): int + { + return (new DonationQuery) + ->form($formId) + ->between($startDate, $endDate) ->count(); } @@ -411,21 +418,25 @@ public function getTotalNumberOfSubscriptions(int $formId): int } /** + * @unreleased Update query to use intended amounts (without recovered fees). * @since 3.0.0 */ public function getTotalRevenue(int $formId): int { - $query = DB::table('give_formmeta') - ->select('meta_value as totalRevenue') - ->where('form_id', $formId) - ->where('meta_key', '_give_form_earnings') - ->get(); - - if (!$query) { - return 0; - } + return (int) (new DonationQuery) + ->form($formId) + ->sumIntendedAmount(); + } - return (int)$query->totalRevenue; + /** + * @unreleased + */ + public function getTotalRevenueForDateRange(int $formId, string $startDate, string $endDate): int + { + return (int) (new DonationQuery) + ->form($formId) + ->between($startDate, $endDate) + ->sumIntendedAmount(); } /** diff --git a/src/DonationForms/ViewModels/DonationFormViewModel.php b/src/DonationForms/ViewModels/DonationFormViewModel.php index ada297efb4..f56fc1da47 100644 --- a/src/DonationForms/ViewModels/DonationFormViewModel.php +++ b/src/DonationForms/ViewModels/DonationFormViewModel.php @@ -6,6 +6,7 @@ use Give\DonationForms\Actions\GenerateDonateRouteUrl; use Give\DonationForms\Actions\GenerateDonationFormValidationRouteUrl; use Give\DonationForms\DataTransferObjects\DonationFormGoalData; +use Give\DonationForms\DonationQuery; use Give\DonationForms\Properties\FormSettings; use Give\DonationForms\Repositories\DonationFormRepository; use Give\DonationForms\ValueObjects\GoalType; @@ -181,14 +182,18 @@ private function formStatsData(): array { $goalType = $this->goalType(); - $totalRevenue = $this->getTotalRevenue($goalType); - $totalCountValue = $this->getTotalCountValue($goalType); - $totalCountLabel = $this->getCountLabel($goalType); + $donationQuery = (new DonationQuery)->form($this->donationFormId); + + if($this->formSettings->goalProgressType->isCustom()) { + $donationQuery->between($this->formSettings->goalStartDate, $this->formSettings->goalEndDate); + } return [ - 'totalRevenue' => $totalRevenue, - 'totalCountValue' => $totalCountValue, - 'totalCountLabel' => $totalCountLabel, + 'totalRevenue' => $donationQuery->sumIntendedAmount(), + 'totalCountValue' => $goalType->isDonations() || $goalType->isAmount() + ? $donationQuery->count() + : $this->getTotalCountValue($goalType), + 'totalCountLabel' => $this->getCountLabel($goalType), ]; }