Completed
Push — develop ( 783309...516d96 )
by Ravan
01:22
created

Shipping::addVolume()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
namespace Axado;
3
4
use Axado\Exception\QuotationNotFoundException;
5
use Axado\Exception\ShippingException;
6
use Axado\Formatter\FormatterInterface;
7
use Axado\Formatter\JsonFormatter;
8
use Axado\Volume\VolumeInterface;
9
10
class Shipping
11
{
12
    /**
13
     * Requires fields in Shipping.
14
     *
15
     * @var array
16
     */
17
    public static $requiredFields = [
18
        'cep_origem',
19
        'cep_destino',
20
        'valor_notafiscal',
21
    ];
22
23
    /**
24
     * Token string to Axado.
25
     *
26
     * @var string
27
     */
28
    public static $token;
29
30
    /**
31
     * All attributes.
32
     *
33
     * @var array
34
     */
35
    protected $attributes = [];
36
37
    /**
38
     * Quotation used.
39
     *
40
     * @var Quotation
41
     */
42
    protected $electedQuotation;
43
44
    /**
45
     * Quotation string.
46
     *
47
     * @var string
48
     */
49
    protected $quotationToken;
50
51
    /**
52
     * All volumes objects.
53
     *
54
     * @var array
55
     */
56
    protected $volumes = [];
57
58
    /**
59
     * FormatterInterface instance.
60
     *
61
     * @var FormatterInterface
62
     */
63
    protected $formatter;
64
65
    /**
66
     * Axado\Request instance.
67
     *
68
     * @var Request
69
     */
70
    protected $request;
71
72
    /**
73
     * Axado\Response instance.
74
     *
75
     * @var Response
76
     */
77
    protected $response;
78
79
    /**
80
     * Constructor
81
     *
82
     * @param \Axado\Formatter\FormatterInterface $formatter
83
     */
84
    public function __construct(FormatterInterface $formatter = null)
85
    {
86
        $this->formatter = $formatter ?: new JsonFormatter();
87
    }
88
89
    /**
90
     * Get the first quotation and return the price.
91
     *
92
     * @return string|null
93
     */
94
    public function getCosts()
95
    {
96
        return $this->firstQuotation()->getCosts();
97
    }
98
99
    /**
100
     * Returns the first quotation.
101
     *
102
     * @throws QuotationNotFoundException
103
     *
104
     * @return Quotation
105
     */
106
    public function firstQuotation(): Quotation
107
    {
108
        $quotations = (array) $this->quotations();
109
110
        if (! isset($quotations[0])) {
111
            throw new QuotationNotFoundException(
112
                sprintf(
113
                    'No quotations were found to the given CEP: %s',
114
                    $this->getPostalCodeDestination()
115
                )
116
            );
117
        }
118
119
        $this->electedQuotation = $quotations[0];
120
121
        return $quotations[0];
122
    }
123
124
    /**
125
     * Consult this shipping through api.
126
     *
127
     * @throws ShippingException
128
     *
129
     * @return array
130
     */
131
    public function quotations()
132
    {
133
        if (! $this->isValid()) {
134
            throw new ShippingException(
135
                'This shipping was not filled correctly',
136
                1
137
            );
138
        }
139
140
        if (! $this->response) {
141
            $request = $this->newRequest(static::$token);
142
            $this->response = $request->consultShipping($this->toJson());
143
            $this->quotationToken = $this->response->getQuotationToken();
144
        }
145
146
        return $this->response->quotations();
147
    }
148
149
    /**
150
     * Verify is this instance is Valid.
151
     *
152
     * @return bool
153
     */
154
    protected function isValid(): bool
155
    {
156
        foreach (static::$requiredFields as $field) {
157
            if (! isset($this->attributes[$field]) || ! $this->attributes[$field]) {
158
                return false;
159
            }
160
        }
161
162
        return (bool) $this->volumes;
163
    }
164
165
    /**
166
     * Returns a new instance of Request.
167
     *
168
     * @param string $token
169
     *
170
     * @return Request
171
     */
172
    protected function newRequest(string $token): Request
173
    {
174
        return new Request($token);
175
    }
176
177
    /**
178
     * Return this object in json format.
179
     *
180
     * @return string
181
     */
182
    protected function toJson(): string
183
    {
184
        $this->formatter->setInstance($this);
185
186
        return $this->formatter->format();
187
    }
188
189
    /**
190
     * Getter of postal code destination
191
     *
192
     * @return string|null
193
     */
194
    protected function getPostalCodeDestination()
195
    {
196
        return $this->attributes['cep_destino'] ?? null;
197
    }
198
199
    /**
200
     * Get the first quotation and return the price.
201
     *
202
     * @return string|null
203
     */
204
    public function getDeadline()
205
    {
206
        return $this->firstQuotation()->getDeadline();
207
    }
208
209
    /**
210
     * Getter for quotation elected.
211
     *
212
     * @return Quotation
213
     */
214
    public function getElectedQuotation()
215
    {
216
        return $this->electedQuotation;
217
    }
218
219
    /**
220
     * Return the attributes.
221
     *
222
     * @return array
223
     */
224
    public function getAttributes(): array
225
    {
226
        return $this->attributes;
227
    }
228
229
    /**
230
     * Setter to Postal Code origin.
231
     *
232
     * @param string $cep
233
     */
234
    public function setPostalCodeOrigin($cep)
235
    {
236
        $this->attributes['cep_origem'] = (string) $cep;
237
    }
238
239
    /**
240
     * Setter to Postal Code destination.
241
     *
242
     * @param string $cep
243
     */
244
    public function setPostalCodeDestination($cep)
245
    {
246
        $this->attributes['cep_destino'] = (string) $cep;
247
    }
248
249
    /**
250
     * Setter to Total price of sale.
251
     *
252
     * @param float $price
253
     */
254
    public function setTotalPrice($price)
255
    {
256
        $this->attributes['valor_notafiscal'] = (float) $price;
257
258
        $this->setAdditionalPrice($this->getAdditionalPrice());
259
    }
260
261
    /**
262
     * Setter to Additional price to add to shipping costs.
263
     *
264
     * @param float $price
265
     */
266
    public function setAdditionalPrice($price)
267
    {
268
        $additionalPrice = $this->calculateAdditionalPrice($price);
269
270
        $this->attributes['preco_adicional'] = $additionalPrice;
271
    }
272
273
    /**
274
     * Calculate the additional price.
275
     *
276
     * @param  string $price
277
     *
278
     * @return float
279
     */
280
    public function calculateAdditionalPrice($price)
281
    {
282
        $tempPrice = $price;
283
        $totalPrice = $this->getTotalPrice();
284
285
        if (preg_match('/%/', $price) && (float) $price && $totalPrice) {
286
            if ($price = (float) $price) {
287
                $price = $totalPrice * $price / 100;
288
            } else {
289
                $price = $tempPrice;
290
            }
291
        } else {
292
            $price = $tempPrice;
293
        }
294
295
        return $price;
296
    }
297
298
    /**
299
     * Getter to Total price of sale.
300
     *
301
     * @return float|null
302
     */
303
    public function getTotalPrice()
304
    {
305
        return $this->attributes['valor_notafiscal'] ?? null;
306
    }
307
308
    /**
309
     * Getter to of Additional price.
310
     *
311
     * @return float|null
312
     */
313
    public function getAdditionalPrice()
314
    {
315
        return $this->attributes['preco_adicional'] ?? null;
316
    }
317
318
    /**
319
     * Setter to additional days.
320
     *
321
     * @param int $days
322
     */
323
    public function setAdditionalDays($days)
324
    {
325
        $this->attributes['prazo_adicional'] = (int) $days;
326
    }
327
328
    /**
329
     * Add a volume object to send through Axado api.
330
     *
331
     * @param VolumeInterface $volume
332
     */
333
    public function addVolume(VolumeInterface $volume)
334
    {
335
        $this->volumes[] = $volume;
336
    }
337
338
    /**
339
     * Return all volumes at this instance.
340
     *
341
     * @return array
342
     */
343
    public function allVolumes(): array
344
    {
345
        return $this->volumes;
346
    }
347
348
    /**
349
     * Clean all volumes.
350
     */
351
    public function clearVolumes()
352
    {
353
        $this->volumes = [];
354
    }
355
}
356