Passed
Push — master ( 49de82...9f1fc0 )
by James
35:45 queued 23:44
created

TransactionStoreRequest::getTransactionData()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 92
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 55
dl 0
loc 92
rs 8.9818
c 0
b 0
f 0
cc 2
nc 2
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * TransactionStoreRequest.php
5
 * Copyright (c) 2019 [email protected]
6
 *
7
 * This file is part of Firefly III (https://github.com/firefly-iii).
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
declare(strict_types=1);
24
25
namespace FireflyIII\Api\V1\Requests;
26
27
use FireflyIII\Rules\BelongsUser;
28
use FireflyIII\Rules\IsBoolean;
29
use FireflyIII\Rules\IsDateOrTime;
30
use FireflyIII\Support\NullArrayObject;
31
use FireflyIII\Validation\TransactionValidation;
32
use Illuminate\Validation\Validator;
33
34
35
/**
36
 * Class TransactionStoreRequest
37
 */
38
class TransactionStoreRequest extends Request
39
{
40
    use TransactionValidation;
0 ignored issues
show
introduced by James Cole
The trait FireflyIII\Validation\TransactionValidation requires some properties which are not provided by FireflyIII\Api\V1\Requests\TransactionStoreRequest: $name, $sourceError, $destError, $transactionType, $account_id, $account, $type
Loading history...
41
42
    /**
43
     * Authorize logged in users.
44
     *
45
     * @return bool
46
     */
47
    public function authorize(): bool
48
    {
49
        // Only allow authenticated users
50
        return auth()->check();
51
    }
52
53
    /**
54
     * Get all data. Is pretty complex because of all the ??-statements.
55
     *
56
     * @return array
57
     */
58
    public function getAll(): array
59
    {
60
        $data = [
61
            'group_title'  => $this->string('group_title'),
62
            'transactions' => $this->getTransactionData(),
63
        ];
64
65
        return $data;
66
    }
67
68
    /**
69
     * The rules that the incoming request must be matched against.
70
     *
71
     * @return array
72
     */
73
    public function rules(): array
74
    {
75
        $rules = [
76
            // basic fields for group:
77
            'group_title'                          => 'between:1,1000|nullable',
78
79
            // transaction rules (in array for splits):
80
            'transactions.*.type'                  => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
81
            'transactions.*.date'                  => ['required', new IsDateOrTime],
82
            'transactions.*.order'                 => 'numeric|min:0',
83
84
            // currency info
85
            'transactions.*.currency_id'           => 'numeric|exists:transaction_currencies,id|nullable',
86
            'transactions.*.currency_code'         => 'min:3|max:3|exists:transaction_currencies,code|nullable',
87
            'transactions.*.foreign_currency_id'   => 'numeric|exists:transaction_currencies,id|nullable',
88
            'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code|nullable',
89
90
            // amount
91
            'transactions.*.amount'                => 'required|numeric|more:0',
92
            'transactions.*.foreign_amount'        => 'numeric|more:0',
93
94
            // description
95
            'transactions.*.description'           => 'nullable|between:1,1000',
96
97
            // source of transaction
98
            'transactions.*.source_id'             => ['numeric', 'nullable', new BelongsUser],
99
            'transactions.*.source_name'           => 'between:1,255|nullable',
100
            'transactions.*.source_iban'           => 'between:1,255|nullable|iban',
101
            'transactions.*.source_number'         => 'between:1,255|nullable',
102
            'transactions.*.source_bic'            => 'between:1,255|nullable|bic',
103
104
            // destination of transaction
105
            'transactions.*.destination_id'        => ['numeric', 'nullable', new BelongsUser],
106
            'transactions.*.destination_name'      => 'between:1,255|nullable',
107
            'transactions.*.destination_iban'      => 'between:1,255|nullable|iban',
108
            'transactions.*.destination_number'    => 'between:1,255|nullable',
109
            'transactions.*.destination_bic'       => 'between:1,255|nullable|bic',
110
111
            // budget, category, bill and piggy
112
            'transactions.*.budget_id'             => ['mustExist:budgets,id', new BelongsUser],
113
            'transactions.*.budget_name'           => ['between:1,255', 'nullable', new BelongsUser],
114
            'transactions.*.category_id'           => ['mustExist:categories,id', new BelongsUser],
115
            'transactions.*.category_name'         => 'between:1,255|nullable',
116
            'transactions.*.bill_id'               => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser],
117
            'transactions.*.bill_name'             => ['between:1,255', 'nullable', new BelongsUser],
118
            'transactions.*.piggy_bank_id'         => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser],
119
            'transactions.*.piggy_bank_name'       => ['between:1,255', 'nullable', new BelongsUser],
120
121
            // other interesting fields
122
            'transactions.*.reconciled'            => [new IsBoolean],
123
            'transactions.*.notes'                 => 'min:1,max:50000|nullable',
124
            'transactions.*.tags'                  => 'between:0,255',
125
126
            // meta info fields
127
            'transactions.*.internal_reference'    => 'min:1,max:255|nullable',
128
            'transactions.*.external_id'           => 'min:1,max:255|nullable',
129
            'transactions.*.recurrence_id'         => 'min:1,max:255|nullable',
130
            'transactions.*.bunq_payment_id'       => 'min:1,max:255|nullable',
131
132
            // SEPA fields:
133
            'transactions.*.sepa_cc'               => 'min:1,max:255|nullable',
134
            'transactions.*.sepa_ct_op'            => 'min:1,max:255|nullable',
135
            'transactions.*.sepa_ct_id'            => 'min:1,max:255|nullable',
136
            'transactions.*.sepa_db'               => 'min:1,max:255|nullable',
137
            'transactions.*.sepa_country'          => 'min:1,max:255|nullable',
138
            'transactions.*.sepa_ep'               => 'min:1,max:255|nullable',
139
            'transactions.*.sepa_ci'               => 'min:1,max:255|nullable',
140
            'transactions.*.sepa_batch_id'         => 'min:1,max:255|nullable',
141
142
            // dates
143
            'transactions.*.interest_date'         => 'date|nullable',
144
            'transactions.*.book_date'             => 'date|nullable',
145
            'transactions.*.process_date'          => 'date|nullable',
146
            'transactions.*.due_date'              => 'date|nullable',
147
            'transactions.*.payment_date'          => 'date|nullable',
148
            'transactions.*.invoice_date'          => 'date|nullable',
149
        ];
150
151
        return $rules;
152
153
154
    }
155
156
    /**
157
     * Configure the validator instance.
158
     *
159
     * @param Validator $validator
160
     *
161
     * @return void
162
     */
163
    public function withValidator(Validator $validator): void
164
    {
165
        $validator->after(
166
            function (Validator $validator) {
167
                // must submit at least one transaction.
168
                $this->validateOneTransaction($validator);
169
170
                // all journals must have a description
171
                $this->validateDescriptions($validator);
172
173
                // all transaction types must be equal:
174
                $this->validateTransactionTypes($validator);
175
176
                // validate foreign currency info
177
                $this->validateForeignCurrencyInformation($validator);
178
179
                // validate all account info
180
                $this->validateAccountInformation($validator);
181
182
                // validate source/destination is equal, depending on the transaction journal type.
183
                $this->validateEqualAccounts($validator);
184
185
                // the group must have a description if > 1 journal.
186
                $this->validateGroupDescription($validator);
187
188
            }
189
        );
190
    }
191
192
    /**
193
     * Get transaction data.
194
     *
195
     * @return array
196
     */
197
    private function getTransactionData(): array
198
    {
199
        $return = [];
200
        /**
201
         * @var int   $index
202
         * @var array $transaction
203
         */
204
        foreach ($this->get('transactions') as $index => $transaction) {
205
            $object   = new NullArrayObject($transaction);
206
            $return[] = [
207
                'type'  => $this->stringFromValue($object['type']),
208
                'date'  => $this->dateFromValue($object['date']),
209
                'order' => $this->integerFromValue((string)$object['order']),
210
211
                'currency_id'           => $this->integerFromValue((string)$object['currency_id']),
212
                'currency_code'         => $this->stringFromValue($object['currency_code']),
213
214
                // foreign currency info:
215
                'foreign_currency_id'   => $this->integerFromValue((string)$object['foreign_currency_id']),
216
                'foreign_currency_code' => $this->stringFromValue($object['foreign_currency_code']),
217
218
                // amount and foreign amount. Cannot be 0.
219
                'amount'                => $this->stringFromValue((string)$object['amount']),
220
                'foreign_amount'        => $this->stringFromValue((string)$object['foreign_amount']),
221
222
                // description.
223
                'description'           => $this->stringFromValue($object['description']),
224
225
                // source of transaction. If everything is null, assume cash account.
226
                'source_id'             => $this->integerFromValue((string)$object['source_id']),
227
                'source_name'           => $this->stringFromValue($object['source_name']),
228
                'source_iban'           => $this->stringFromValue($object['source_iban']),
229
                'source_number'         => $this->stringFromValue($object['source_number']),
230
                'source_bic'            => $this->stringFromValue($object['source_bic']),
231
232
                // destination of transaction. If everything is null, assume cash account.
233
                'destination_id'        => $this->integerFromValue((string)$object['destination_id']),
234
                'destination_name'      => $this->stringFromValue($object['destination_name']),
235
                'destination_iban'      => $this->stringFromValue($object['destination_iban']),
236
                'destination_number'    => $this->stringFromValue($object['destination_number']),
237
                'destination_bic'       => $this->stringFromValue($object['destination_bic']),
238
239
                // budget info
240
                'budget_id'             => $this->integerFromValue((string)$object['budget_id']),
241
                'budget_name'           => $this->stringFromValue($object['budget_name']),
242
243
                // category info
244
                'category_id'           => $this->integerFromValue((string)$object['category_id']),
245
                'category_name'         => $this->stringFromValue($object['category_name']),
246
247
                // journal bill reference. Optional. Will only work for withdrawals
248
                'bill_id'               => $this->integerFromValue((string)$object['bill_id']),
249
                'bill_name'             => $this->stringFromValue($object['bill_name']),
250
251
                // piggy bank reference. Optional. Will only work for transfers
252
                'piggy_bank_id'         => $this->integerFromValue((string)$object['piggy_bank_id']),
253
                'piggy_bank_name'       => $this->stringFromValue($object['piggy_bank_name']),
254
255
                // some other interesting properties
256
                'reconciled'            => $this->convertBoolean((string)$object['reconciled']),
257
                'notes'                 => $this->nlStringFromValue($object['notes']),
258
                'tags'                  => $this->arrayFromValue($object['tags']),
259
260
                // all custom fields:
261
                'internal_reference'    => $this->stringFromValue($object['internal_reference']),
262
                'external_id'           => $this->stringFromValue($object['external_id']),
263
                'original_source'       => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
264
                'recurrence_id'         => $this->integerFromValue($object['recurrence_id']),
265
                'bunq_payment_id'       => $this->stringFromValue($object['bunq_payment_id']),
266
267
                'sepa_cc'       => $this->stringFromValue($object['sepa_cc']),
268
                'sepa_ct_op'    => $this->stringFromValue($object['sepa_ct_op']),
269
                'sepa_ct_id'    => $this->stringFromValue($object['sepa_ct_id']),
270
                'sepa_db'       => $this->stringFromValue($object['sepa_db']),
271
                'sepa_country'  => $this->stringFromValue($object['sepa_country']),
272
                'sepa_ep'       => $this->stringFromValue($object['sepa_ep']),
273
                'sepa_ci'       => $this->stringFromValue($object['sepa_ci']),
274
                'sepa_batch_id' => $this->stringFromValue($object['sepa_batch_id']),
275
276
277
                // custom date fields. Must be Carbon objects. Presence is optional.
278
                'interest_date' => $this->dateFromValue($object['interest_date']),
279
                'book_date'     => $this->dateFromValue($object['book_date']),
280
                'process_date'  => $this->dateFromValue($object['process_date']),
281
                'due_date'      => $this->dateFromValue($object['due_date']),
282
                'payment_date'  => $this->dateFromValue($object['payment_date']),
283
                'invoice_date'  => $this->dateFromValue($object['invoice_date']),
284
285
            ];
286
        }
287
288
        return $return;
289
    }
290
}
291