Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
ExpireTrialsAction
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
1 / 1
 execute
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Billing\Application\Actions;
6
7use ImovelZapAi\Organizations\Domain\Enums\SubscriptionStatus;
8use ImovelZapAi\Organizations\Infrastructure\Persistence\Eloquent\OrganizationSubscriptionModel;
9
10final class ExpireTrialsAction
11{
12    /**
13     * Encerra trials vencidos sem pagamento e marca past_due com grace quando há preapproval pendente.
14     *
15     * @return array{canceled: int, past_due: int}
16     */
17    public function execute(): array
18    {
19        $canceled = 0;
20        $pastDue = 0;
21        $graceDays = (int) config('billing.grace_days', 3);
22
23        $expired = OrganizationSubscriptionModel::query()
24            ->where('status', SubscriptionStatus::Trialing)
25            ->whereNotNull('trial_ends_at')
26            ->where('trial_ends_at', '<', now())
27            ->get();
28
29        foreach ($expired as $subscription) {
30            if (filled($subscription->mp_preapproval_id)) {
31                $subscription->forceFill([
32                    'status' => SubscriptionStatus::PastDue,
33                    'grace_ends_at' => now()->addDays($graceDays),
34                ])->save();
35                $pastDue++;
36
37                continue;
38            }
39
40            $subscription->forceFill([
41                'status' => SubscriptionStatus::Canceled,
42                'canceled_at' => now(),
43            ])->save();
44            $canceled++;
45        }
46
47        // Encerra grace expirado
48        OrganizationSubscriptionModel::query()
49            ->where('status', SubscriptionStatus::PastDue)
50            ->whereNotNull('grace_ends_at')
51            ->where('grace_ends_at', '<', now())
52            ->update([
53                'status' => SubscriptionStatus::Canceled->value,
54                'canceled_at' => now(),
55            ]);
56
57        return [
58            'canceled' => $canceled,
59            'past_due' => $pastDue,
60        ];
61    }
62}