Passed
Push — main ( c89920...e11349 )
by Thierry
05:00
created

SettlementService::createAllSettlements()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 9
nc 2
nop 2
dl 0
loc 15
rs 9.9666
c 1
b 0
f 0
1
<?php
2
3
namespace Siak\Tontine\Service\Meeting\Charge;
4
5
use Illuminate\Support\Facades\DB;
6
use Siak\Tontine\Exception\MessageException;
7
use Siak\Tontine\Model\Bill;
8
use Siak\Tontine\Model\Charge;
9
use Siak\Tontine\Model\Session;
10
use Siak\Tontine\Model\Settlement;
11
use Siak\Tontine\Service\TenantService;
12
13
use function trans;
14
15
class SettlementService
16
{
17
    /**
18
     * @var TenantService
19
     */
20
    protected TenantService $tenantService;
21
22
    /**
23
     * @param TenantService $tenantService
24
     */
25
    public function __construct(TenantService $tenantService)
26
    {
27
        $this->tenantService = $tenantService;
28
    }
29
30
    /**
31
     * Get a single session.
32
     *
33
     * @param int $sessionId    The session id
34
     *
35
     * @return Session|null
36
     */
37
    public function getSession(int $sessionId): ?Session
38
    {
39
        return $this->tenantService->getSession($sessionId);
40
    }
41
42
    /**
43
     * Get a single charge.
44
     *
45
     * @param int $chargeId    The charge id
46
     *
47
     * @return Charge|null
48
     */
49
    public function getCharge(int $chargeId): ?Charge
50
    {
51
        return $this->tenantService->tontine()->charges()->find($chargeId);
52
    }
53
54
    /**
55
     * @param Charge $charge
56
     * @param Session $session
57
     *
58
     * @return mixed
59
     */
60
    private function getQuery(Charge $charge, Session $session)
61
    {
62
        // The select('bills.*') is important here, otherwise Eloquent overrides the
63
        // Bill model id fields with those of another model, then making the dataset incorrect.
64
        $query = Bill::select('bills.*');
65
        if($charge->is_variable)
66
        {
67
            return $query->join('fine_bills', 'fine_bills.bill_id', '=', 'bills.id')
68
                ->where('fine_bills.charge_id', $charge->id)
69
                ->where('fine_bills.session_id', $session->id);
70
        }
71
        if($charge->period_session)
72
        {
73
            return $query->join('session_bills', 'session_bills.bill_id', '=', 'bills.id')
74
                ->where('session_bills.charge_id', $charge->id)
75
                ->where('session_bills.session_id', $session->id);
76
        }
77
        if($charge->period_round)
78
        {
79
            return $query->join('round_bills', 'round_bills.bill_id', '=', 'bills.id')
80
                ->where('round_bills.charge_id', $charge->id);
81
        }
82
        // if($charge->period_once)
83
        return $query->join('tontine_bills', 'tontine_bills.bill_id', '=', 'bills.id')
84
            ->where('tontine_bills.charge_id', $charge->id);
85
    }
86
87
    /**
88
     * Create a settlement
89
     *
90
     * @param Charge $charge
91
     * @param Session $session
92
     * @param int $Id
93
     *
94
     * @return void
95
     */
96
    public function createSettlement(Charge $charge, Session $session, int $billId): void
97
    {
98
        $bill = $this->getQuery($charge, $session)->with('settlement')->find($billId);
99
        // Return if the bill is not found or the bill is already settled.
100
        if(!$bill || ($bill->settlement))
0 ignored issues
show
Bug introduced by
The property settlement does not seem to exist on Illuminate\Database\Eloq...elations\HasManyThrough.
Loading history...
Bug introduced by
The property settlement does not seem to exist on Illuminate\Database\Eloq...Relations\HasOneThrough.
Loading history...
101
        {
102
            throw new MessageException(trans('tontine.bill.errors.not_found'));
103
        }
104
        $settlement = new Settlement();
105
        $settlement->bill()->associate($bill);
106
        $settlement->session()->associate($session);
107
        $settlement->save();
108
    }
109
110
    /**
111
     * Delete a settlement
112
     *
113
     * @param Charge $charge
114
     * @param Session $session
115
     * @param int $Id
116
     *
117
     * @return void
118
     */
119
    public function deleteSettlement(Charge $charge, Session $session, int $billId): void
120
    {
121
        $bill = $this->getQuery($charge, $session)->with('settlement')->find($billId);
122
        // Return if the bill is not found or the bill is not settled.
123
        if(!$bill || !($bill->settlement))
0 ignored issues
show
Bug introduced by
The property settlement does not seem to exist on Illuminate\Database\Eloq...elations\HasManyThrough.
Loading history...
Bug introduced by
The property settlement does not seem to exist on Illuminate\Database\Eloq...Relations\HasOneThrough.
Loading history...
124
        {
125
            throw new MessageException(trans('tontine.bill.errors.not_found'));
126
        }
127
        if(($bill->settlement->online))
128
        {
129
            throw new MessageException(trans('tontine.bill.errors.online'));
130
        }
131
        $bill->settlement()->where('session_id', $session->id)->delete();
132
    }
133
134
    /**
135
     * Create a settlement for all unpaid bills
136
     *
137
     * @param Charge $charge
138
     * @param Session $session
139
     *
140
     * @return void
141
     */
142
    public function createAllSettlements(Charge $charge, Session $session): void
143
    {
144
        $bills = $this->getQuery($charge, $session)->whereDoesntHave('settlement')->get();
145
        if($bills->count() === 0)
146
        {
147
            return;
148
        }
149
150
        DB::transaction(function() use($bills, $session) {
151
            foreach($bills as $bill)
152
            {
153
                $settlement = new Settlement();
154
                $settlement->bill()->associate($bill);
155
                $settlement->session()->associate($session);
156
                $settlement->save();
157
            }
158
        });
159
    }
160
161
    /**
162
     * Delete all settlements
163
     *
164
     * @param Charge $charge
165
     * @param Session $session
166
     *
167
     * @return void
168
     */
169
    public function deleteAllSettlements(Charge $charge, Session $session): void
170
    {
171
        $bills = $this->getQuery($charge, $session)
172
            ->whereHas('settlement')
173
            ->get()
174
            ->filter(function($bill) {
175
                return !$bill->settlement->online;
176
            });
177
        if($bills->count() === 0)
178
        {
179
            return;
180
        }
181
        DB::transaction(function() use($bills, $session) {
182
            foreach($bills as $bill)
183
            {
184
                $bill->settlement()->where('session_id', $session->id)->delete();
185
            }
186
        });
187
    }
188
189
    /**
190
     * @param Charge $charge
191
     * @param Session $session
192
     *
193
     * @return object
194
     */
195
    public function getSettlement(Charge $charge, Session $session): object
196
    {
197
        if($charge->is_variable)
198
        {
199
            return DB::table('settlements')
200
                ->select(DB::raw('count(*) as total'), DB::raw('sum(bills.amount) as amount'))
201
                ->join('bills', 'settlements.bill_id', '=', 'bills.id')
202
                ->join('fine_bills', 'fine_bills.bill_id', '=', 'bills.id')
203
                ->where('settlements.session_id', $session->id)
204
                ->where('fine_bills.charge_id', $charge->id)
205
                ->first();
206
        }
207
        if($charge->period_session)
208
        {
209
            return DB::table('settlements')
210
                ->select(DB::raw('count(*) as total'), DB::raw('sum(bills.amount) as amount'))
211
                ->join('bills', 'settlements.bill_id', '=', 'bills.id')
212
                ->join('session_bills', 'session_bills.bill_id', '=', 'bills.id')
213
                ->where('settlements.session_id', $session->id)
214
                ->where('session_bills.charge_id', $charge->id)
215
                ->first();
216
        }
217
        if($charge->period_round)
218
        {
219
            return DB::table('settlements')
220
                ->select(DB::raw('count(*) as total'), DB::raw('sum(bills.amount) as amount'))
221
                ->join('bills', 'settlements.bill_id', '=', 'bills.id')
222
                ->join('round_bills', 'round_bills.bill_id', '=', 'bills.id')
223
                ->where('settlements.session_id', $session->id)
224
                ->where('round_bills.charge_id', $charge->id)
225
                ->first();
226
        }
227
        return DB::table('settlements')
228
            ->select(DB::raw('count(*) as total'), DB::raw('sum(bills.amount) as amount'))
229
            ->join('bills', 'settlements.bill_id', '=', 'bills.id')
230
            ->join('tontine_bills', 'tontine_bills.bill_id', '=', 'bills.id')
231
            ->where('settlements.session_id', $session->id)
232
            ->where('tontine_bills.charge_id', $charge->id)
233
            ->first();
234
    }
235
}
236