Passed
Push — main ( 7be313...891842 )
by Thierry
19:01 queued 53s
created

EventTrait::sessionSynced()   B

Complexity

Conditions 7
Paths 16

Size

Total Lines 42
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 22
c 1
b 0
f 0
nc 16
nop 2
dl 0
loc 42
rs 8.6346
1
<?php
2
3
namespace Siak\Tontine\Service\Traits;
4
5
use DateTime;
6
use Illuminate\Database\Eloquent\Builder;
7
use Siak\Tontine\Model\Bill;
8
use Siak\Tontine\Model\TontineBill;
9
use Siak\Tontine\Model\RoundBill;
10
use Siak\Tontine\Model\SessionBill;
11
use Siak\Tontine\Model\Charge;
12
use Siak\Tontine\Model\Member;
13
use Siak\Tontine\Model\Pool;
14
use Siak\Tontine\Model\Round;
15
use Siak\Tontine\Model\Session;
16
use Siak\Tontine\Model\Tontine;
17
18
use function now;
19
20
trait EventTrait
21
{
22
    /**
23
     * @param Charge $charge
24
     * @param DateTime $today
25
     *
26
     * @return Bill
27
     */
28
    private function createBill(Charge $charge, DateTime $today): Bill
29
    {
30
        return Bill::create([
31
            'charge' => $charge->name,
32
            'amount' => $charge->amount,
33
            'lendable' => $charge->lendable,
34
            'issued_at' => $today,
35
        ]);
36
    }
37
38
    /**
39
     * @param Charge $charge
40
     * @param Member $member
41
     * @param DateTime $today
42
     *
43
     * @return void
44
     */
45
    private function createTontineBill(Charge $charge, Member $member, DateTime $today)
46
    {
47
        $bill = $this->createBill($charge, $today);
48
        $tontineBill = new TontineBill();
49
        $tontineBill->bill()->associate($bill);
50
        $tontineBill->charge()->associate($charge);
51
        $tontineBill->member()->associate($member);
52
        $tontineBill->save();
53
    }
54
55
    /**
56
     * @param Charge $charge
57
     * @param Member $member
58
     * @param Round $round
59
     * @param DateTime $today
60
     *
61
     * @return void
62
     */
63
    private function createRoundBill(Charge $charge, Member $member, Round $round, DateTime $today)
64
    {
65
        $bill = $this->createBill($charge, $today);
66
        $roundBill = new RoundBill();
67
        $roundBill->bill()->associate($bill);
68
        $roundBill->charge()->associate($charge);
69
        $roundBill->member()->associate($member);
70
        $roundBill->round()->associate($round);
71
        $roundBill->save();
72
    }
73
74
    /**
75
     * @param Charge $charge
76
     * @param Member $member
77
     * @param Session $session
78
     * @param DateTime $today
79
     *
80
     * @return void
81
     */
82
    private function createSessionBill(Charge $charge, Member $member, Session $session, DateTime $today)
83
    {
84
        $bill = $this->createBill($charge, $today);
85
        $sessionBill = new SessionBill();
86
        $sessionBill->bill()->associate($bill);
87
        $sessionBill->charge()->associate($charge);
88
        $sessionBill->member()->associate($member);
89
        $sessionBill->session()->associate($session);
90
        $sessionBill->save();
91
    }
92
93
    /**
94
     * @param Tontine $tontine
95
     * @param Charge $charge
96
     *
97
     * @return void
98
     */
99
    protected function chargeCreated(Tontine $tontine, Charge $charge)
100
    {
101
        if(!$charge->period_once)
102
        {
103
            return;
104
        }
105
        $today = now();
106
        // Create a tontine bill for each member
107
        foreach($tontine->members()->get() as $member)
108
        {
109
            $this->createTontineBill($charge, $member, $today);
110
        }
111
    }
112
113
    /**
114
     * @param Tontine $tontine
115
     * @param Member $member
116
     *
117
     * @return void
118
     */
119
    protected function memberCreated(Tontine $tontine, Member $member)
120
    {
121
        $today = now();
122
        // Create a tontine bill for each charge
123
        foreach($tontine->charges()->active()->once()->get() as $charge)
124
        {
125
            $this->createTontineBill($charge, $member, $today);
126
        }
127
    }
128
129
    /**
130
     * @param Tontine $tontine
131
     * @param Round $round
132
     *
133
     * @return void
134
     */
135
    protected function roundSynced(Tontine $tontine, Round $round)
136
    {
137
        $today = now();
138
        $members = $tontine->members()->with([
139
            'tontine_bills',
140
            'round_bills' => function($query) use($round) {
141
                $query->where('round_id', $round->id);
142
            },
143
        ])->get();
144
        $roundCharges = $tontine->charges()->active()->round()->get();
145
        // Create a round bill for each member
146
        foreach($members as $member)
147
        {
148
            foreach($roundCharges as $charge)
149
            {
150
                $count = $member->round_bills->filter(function($bill) use($charge) {
151
                    return $bill->charge_id = $charge->id;
152
                })->count();
153
                if($count === 0)
154
                {
155
                    $this->createRoundBill($charge, $member, $round, $today);
156
                }
157
            }
158
        }
159
        $tontineCharges = $tontine->charges()->active()->once()->get();
160
        // Create a tontine bill for each member
161
        foreach($members as $member)
162
        {
163
            foreach($tontineCharges as $charge)
164
            {
165
                $count = $member->tontine_bills->filter(function($bill) use($charge) {
166
                    return $bill->charge_id = $charge->id;
167
                })->count();
168
                if($count === 0)
169
                {
170
                    $this->createTontineBill($charge, $member, $today);
171
                }
172
            }
173
        }
174
    }
175
176
    /**
177
     * @param Tontine $tontine
178
     * @param Session $session
179
     *
180
     * @return void
181
     */
182
    protected function sessionSynced(Tontine $tontine, Session $session)
183
    {
184
        // Make sure the round is also opened.
185
        $this->roundSynced($tontine, $session->round);
186
187
        $today = now();
188
        $members = $tontine->members()->with([
189
            'session_bills' => function($query) use($session) {
190
                $query->where('session_id', $session->id);
191
            },
192
        ])->get();
193
        $sessionCharges = $tontine->charges()->active()->session()->get();
194
195
        // Sync the session bills for each member and each session charge
196
        foreach($sessionCharges as $charge)
197
        {
198
            foreach($members as $member)
199
            {
200
                $count = $member->session_bills->filter(function($bill) use($charge) {
201
                    return $bill->charge_id = $charge->id;
202
                })->count();
203
                if($count === 0)
204
                {
205
                    $this->createSessionBill($charge, $member, $session, $today);
206
                }
207
            }
208
        };
209
210
        // Sync the receivables for each subscription on each pool
211
        /** @var array<Pool> */
212
        $pools = Pool::ofSession($session)->get();
213
        foreach($pools as $pool)
214
        {
215
            if($session->enabled($pool))
216
            {
217
                $subscriptions = $pool->subscriptions()
218
                    ->whereDoesntHave('receivables', function(Builder $query) use($session) {
219
                        return $query->where('session_id', $session->id);
220
                    });
221
                foreach($subscriptions->get() as $subscription)
222
                {
223
                    $subscription->receivables()->create(['session_id' => $session->id]);
224
                }
225
            }
226
        }
227
    }
228
}
229