BillService::pdf()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.0123

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 4
nop 1
dl 0
loc 14
ccs 8
cts 9
cp 0.8889
crap 3.0123
rs 10
c 0
b 0
f 0
1
<?php
2
3
4
namespace NeptuneSoftware\Invoice\Services;
5
6
use Dompdf\Dompdf;
7
use Illuminate\Database\Eloquent\Collection;
8
use Illuminate\Database\Eloquent\Model;
9
use Illuminate\Database\Query\Builder;
10
use Illuminate\Support\Facades\View;
11
use NeptuneSoftware\Invoice\Interfaces\BillServiceInterface;
12
use NeptuneSoftware\Invoice\Models\Bill;
13
use NeptuneSoftware\Invoice\MoneyFormatter;
14
use NeptuneSoftware\Invoice\Scopes\InvoiceScope;
15
use Symfony\Component\HttpFoundation\Response;
16
17
class BillService implements BillServiceInterface
18
{
19
    /**
20
     * @var Bill $bill
21
     */
22
    private $bill;
23
24
    /**
25
     * @var bool $is_free
26
     */
27
    private $is_free = false;
28
29
    /**
30
     * @var bool $is_comp
31
     */
32
    private $is_comp = false;
33
34
    /**
35
     * @var array $taxes
36
     */
37
    private $taxes = [];
38
39
    /**
40
     * @inheritDoc
41
     */
42 23
    public function create(Model $model, ?array $bill = []): BillServiceInterface
43
    {
44 23
        $this->bill = $model->bills()->create($bill);
45
46 23
        return $this;
47
    }
48
49
    /**
50
     * @inheritDoc
51
     */
52 20
    public function getBill(): Bill
53
    {
54 20
        return $this->bill;
55
    }
56
57
    /**
58
     * @inheritDoc
59
     */
60
    public function getLines(): Collection
61
    {
62
        return $this->getBill()->lines()->get();
63
    }
64
65
    /**
66
     * @inheritDoc
67
     */
68 3
    public function setFree(): BillServiceInterface
69
    {
70 3
        $this->is_free = true;
71 3
        $this->is_comp = false;
72
73 3
        return $this;
74
    }
75
76
    /**
77
     * @inheritDoc
78
     */
79 3
    public function setComplimentary(): BillServiceInterface
80
    {
81 3
        $this->is_comp = true;
82 3
        $this->is_free = false;
83
84 3
        return $this;
85
    }
86
87
    /**
88
     * @inheritDoc
89
     */
90 16
    public function addTaxPercentage(string $identifier, float $taxPercentage = 0): BillServiceInterface
91
    {
92 16
        array_push($this->taxes, [
93 16
            'identifier'     => $identifier,
94
            'tax_fixed'     => null,
95 16
            'tax_percentage' => $taxPercentage,
96
        ]);
97 16
        return $this;
98
    }
99
100
    /**
101
     * @inheritDoc
102
     */
103 6
    public function addTaxFixed(string $identifier, int $taxAmount = 0): BillServiceInterface
104
    {
105 6
        array_unshift($this->taxes, [
106 6
            'identifier'     => $identifier,
107 6
            'tax_fixed'     => $taxAmount,
108
            'tax_percentage' => null,
109
        ]);
110 6
        return $this;
111
    }
112
113
    /**
114
     * @inheritDoc
115
     */
116 8
    public function addAmountExclTax(Model $model, int $amount, string $description): BillServiceInterface
117
    {
118 8
        $tax = 0;
119 8
        foreach ($this->taxes as $each) {
120 8
            $tax += (null === $each['tax_fixed']) ? $amount * $each['tax_percentage'] : $each['tax_fixed'];
121
        }
122
123 8
        $this->bill->lines()->create([
124 8
            'amount'           => $amount + $tax,
125 8
            'description'      => $description,
126 8
            'tax'              => $tax,
127 8
            'tax_details'      => $this->taxes,
128 8
            'invoiceable_id'   => $model->id,
129 8
            'invoiceable_type' => get_class($model),
130 8
            'is_free'          => $this->is_free,
131 8
            'is_complimentary' => $this->is_comp,
132
        ]);
133
134 8
        $this->recalculate();
135
136 8
        return $this;
137
    }
138
139
    /**
140
     * @inheritDoc
141
     */
142 12
    public function addAmountInclTax(Model $model, int $amount, string $description): BillServiceInterface
143
    {
144 12
        $exc = $amount;
145 12
        $tax = 0;
146 12
        foreach ($this->taxes as $each) {
147 12
            if (null !== $each['tax_fixed']) {
148 3
                $exc -= $each['tax_fixed'];
149 3
                $tax += $each['tax_fixed'];
150
            } else {
151 12
                $tax += ($exc * $each['tax_percentage']) / (1 + $each['tax_percentage']);
152
            }
153
        }
154
155 12
        $this->bill->lines()->create([
156 12
            'amount'           => $amount,
157 12
            'description'      => $description,
158 12
            'tax'              => $tax,
159 12
            'tax_details'      => $this->taxes,
160 12
            'invoiceable_id'   => $model->id,
161 12
            'invoiceable_type' => get_class($model),
162 12
            'is_free'          => $this->is_free,
163 12
            'is_complimentary' => $this->is_comp,
164
        ]);
165
166 12
        $this->recalculate();
167
168 12
        return $this;
169
    }
170
171
    /**
172
     * @inheritDoc
173
     */
174 18
    public function recalculate(): Bill
175
    {
176 18
        $lines         = $this->bill->lines()->get();
177 18
        $free          = $lines->where('is_free', true)->toBase();
178 18
        $complimentary = $lines->where('is_complimentary', true)->toBase();
179
        $other         = $lines
180 18
                                       ->where('is_free', false)
181 18
                                       ->where('is_complimentary', false)
182 18
                                       ->toBase();
183
184 18
        $this->bill->total    = $other->sum('amount');
185 18
        $this->bill->tax      = $other->sum('tax');
186 18
        $this->bill->discount = $free->sum('amount') + $complimentary->sum('amount') + $other->sum('discount');
187
188 18
        $this->bill->save();
189
190 18
        $this->is_free = false;
191 18
        $this->is_comp = false;
192 18
        $this->taxes   = [];
193
194 18
        return $this->bill;
195
    }
196
197
    /**
198
     * @inheritDoc
199
     */
200 3
    public function view(array $data = []): \Illuminate\Contracts\View\View
201
    {
202 3
        return View::make('invoice::receipt', array_merge($data, [
203 3
            'invoice' => $this->bill,
204 3
            'moneyFormatter' => new MoneyFormatter(
205 3
                $this->bill->currency,
206 3
                config('invoice.locale')
207
            ),
208
        ]));
209
    }
210
211
    /**
212
     * @inheritDoc
213
     */
214 2
    public function pdf(array $data = []): string
215
    {
216 2
        if (! defined('DOMPDF_ENABLE_AUTOLOAD')) {
217 1
            define('DOMPDF_ENABLE_AUTOLOAD', false);
218
        }
219
220 2
        if (file_exists($configPath = base_path().'/vendor/dompdf/dompdf/dompdf_config.inc.php')) {
221
            require_once $configPath;
222
        }
223
224 2
        $dompdf = new Dompdf;
225 2
        $dompdf->loadHtml($this->view($data)->render());
226 2
        $dompdf->render();
227 2
        return $dompdf->output();
228
    }
229
230
    /**
231
     * @inheritDoc
232
     */
233 1
    public function download(array $data = []): Response
234
    {
235 1
        $filename = $this->bill->reference . '.pdf';
236
237 1
        return new Response($this->pdf($data), 200, [
238 1
            'Content-Description' => 'File Transfer',
239 1
            'Content-Disposition' => 'attachment; filename="'.$filename.'"',
240 1
            'Content-Transfer-Encoding' => 'binary',
241 1
            'Content-Type' => 'application/pdf',
242
        ]);
243
    }
244
245
    /**
246
     * @inheritDoc
247
     */
248 1
    public function findByReference(string $reference): ?Bill
249
    {
250 1
        return Bill::where('reference', $reference)->withoutGlobalScope(InvoiceScope::class)->first();
251
    }
252
253
    /**
254
     * @inheritDoc
255
     */
256 2
    public function findByReferenceOrFail(string $reference): Bill
257
    {
258 2
        return Bill::where('reference', $reference)->withoutGlobalScope(InvoiceScope::class)->firstOrFail();
259
    }
260
261
    /**
262
     * @inheritDoc
263
     */
264 1
    public function findByInvoiceable(Model $model): Collection
265
    {
266
        /*
267
         * In order to receive invoices by polymorphic relationship, we pluck invoice ids to find invoices.
268
         */
269 1
        $bills = $model->invoiceLines()->get('invoice_id')->pluck('invoice_id')->unique();
270
271 1
        return Bill::find($bills);
272
    }
273
274
    /**
275
     * @inheritDoc
276
     */
277 1
    public function findByRelated(Model $model): Collection
278
    {
279 1
        return $model->bills()->get();
280
    }
281
}
282