Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
27.08% |
13 / 48 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
| ReleaseInvoiceService | |
27.08% |
13 / 48 |
|
0.00% |
0 / 4 |
67.83 | |
0.00% |
0 / 1 |
| release | |
61.90% |
13 / 21 |
|
0.00% |
0 / 1 |
7.99 | |||
| verifyInvoiceItemHasLinkPurchaseItem | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
20 | |||
| processActivetyLog | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 | |||
| validateHasPOInvoiceItemAutomatic | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace Domain\Invoice\Services; |
| 4 | |
| 5 | use App\Events\ServiceProcessed; |
| 6 | use App\Models\Invoice\Invoice; |
| 7 | use App\Models\PurchaseOrder\PurchaseOrderInvoiceItem; |
| 8 | use App\Models\User; |
| 9 | use Domain\Invoice\DTOs\StoreInvoiceActivityLogDTO; |
| 10 | use Domain\Invoice\Enums\InvoiceActivetyLogOperationEnum; |
| 11 | use Domain\Invoice\Enums\InvoiceItemStatusEnum; |
| 12 | use Domain\Invoice\Enums\InvoicePurchaseOrderStatusEnum; |
| 13 | use Domain\Invoice\Enums\InvoiceStatusEnum; |
| 14 | use Domain\Invoice\Exceptions\InvoiceItemNoHasLinkPurchaseItemException; |
| 15 | use Domain\Invoice\Exceptions\InvoiceReleasedException; |
| 16 | use Domain\PurchaseOrder\Enums\PurchaseOrderInvoiceItemStatusEnum; |
| 17 | use Illuminate\Support\Facades\DB; |
| 18 | use Throwable; |
| 19 | |
| 20 | readonly class ReleaseInvoiceService |
| 21 | { |
| 22 | /** |
| 23 | * @throws Throwable |
| 24 | */ |
| 25 | public function release(Invoice $invoice, User $user): void |
| 26 | { |
| 27 | try { |
| 28 | DB::beginTransaction(); |
| 29 | |
| 30 | if ($invoice->isReleased()) { |
| 31 | throw new InvoiceReleasedException(__('Invoice has already been released')); |
| 32 | } |
| 33 | |
| 34 | $invoiceOldJson = json_encode($invoice->getAttributes()); |
| 35 | |
| 36 | $invoicePurchaseOrderStatus = $invoice->getAttribute('purchase_order_status'); |
| 37 | |
| 38 | if ($invoicePurchaseOrderStatus != InvoicePurchaseOrderStatusEnum::VALIDATED) { |
| 39 | if ($invoicePurchaseOrderStatus == InvoicePurchaseOrderStatusEnum::AUTOMATIC && |
| 40 | $this->validateHasPOInvoiceItemAutomatic($invoice)) { |
| 41 | $invoice->setAttribute('purchase_order_status', InvoicePurchaseOrderStatusEnum::VALIDATED); |
| 42 | } else { |
| 43 | throw new InvoiceReleasedException( |
| 44 | __('Is not possible to release the invoice when purchase order status is different of validated') |
| 45 | ); |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | $this->verifyInvoiceItemHasLinkPurchaseItem($invoice); |
| 50 | |
| 51 | $invoice->setAttribute('status', InvoiceStatusEnum::RELEASED); |
| 52 | $invoice->save(); |
| 53 | |
| 54 | $this->processActivetyLog($invoice, $user, $invoiceOldJson); |
| 55 | |
| 56 | DB::commit(); |
| 57 | } catch (Throwable $exception) { |
| 58 | DB::rollBack(); |
| 59 | throw $exception; |
| 60 | } |
| 61 | |
| 62 | ServiceProcessed::dispatch(self::class, $user); |
| 63 | } |
| 64 | |
| 65 | /** |
| 66 | * @throws InvoiceItemNoHasLinkPurchaseItemException |
| 67 | */ |
| 68 | private function verifyInvoiceItemHasLinkPurchaseItem(Invoice $invoice) |
| 69 | { |
| 70 | foreach ($invoice->invoiceItem as $invoiceItem) { |
| 71 | $purchaseOrderInvoiceItem = PurchaseOrderInvoiceItem::query() |
| 72 | ->where('invoice_item_id', $invoiceItem->getKey()) |
| 73 | ->where('status', PurchaseOrderInvoiceItemStatusEnum::VALIDATED) |
| 74 | ->first(); |
| 75 | |
| 76 | if ( |
| 77 | is_null($purchaseOrderInvoiceItem) || |
| 78 | $invoiceItem->getAttribute('status') !== InvoiceItemStatusEnum::VALIDATED |
| 79 | ) { |
| 80 | throw new InvoiceItemNoHasLinkPurchaseItemException( |
| 81 | __('The invoice item is not linked to a purchase order item. Invoice Item: :invoiceItem', |
| 82 | ['invoiceItem' => $invoiceItem->getKey(), |
| 83 | ]) |
| 84 | ); |
| 85 | } |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | private function processActivetyLog(Invoice $invoice, User $user, $details) |
| 90 | { |
| 91 | $invoiceActivityLogDTO = new StoreInvoiceActivityLogDTO([ |
| 92 | 'entity_type' => Invoice::class, |
| 93 | 'entity_id' => $invoice->getKey(), |
| 94 | 'operation' => InvoiceActivetyLogOperationEnum::UPDATE, |
| 95 | 'user' => $user, |
| 96 | 'detail' => $details, |
| 97 | 'observation' => 'Nota fiscal liberada.', |
| 98 | ]); |
| 99 | |
| 100 | (new InvoiceActivityLogStoreService)->store($invoiceActivityLogDTO, $invoice, $user); |
| 101 | } |
| 102 | |
| 103 | private function validateHasPOInvoiceItemAutomatic(Invoice $invoice): bool |
| 104 | { |
| 105 | $purchaseOrderInvoiceItemExists = PurchaseOrderInvoiceItem::query() |
| 106 | ->join('invoice_items', 'invoice_items.id', '=', 'purchase_order_invoice_items.invoice_item_id') |
| 107 | ->where('invoice_items.invoice_id', $invoice->getKey()) |
| 108 | ->where('purchase_order_invoice_items.status', PurchaseOrderInvoiceItemStatusEnum::AUTOMATIC) |
| 109 | ->exists(); |
| 110 | |
| 111 | return ! $purchaseOrderInvoiceItemExists; |
| 112 | } |
| 113 | } |