invoice = $invoice; } /** * Execute the job. * * * @return void */ public function handle() { $invoice = $this->invoice; $company = $invoice->company; $client = $invoice->client; $ubl_invoice = new UBLInvoice(); // invoice $ubl_invoice->setId($invoice->number); $ubl_invoice->setIssueDate(date_create($invoice->date)); $ubl_invoice->setInvoiceTypeCode($invoice->amount < 0 ? self::INVOICE_TYPE_CREDIT : self::INVOICE_TYPE_STANDARD); $supplier_party = $this->createParty($company, $invoice->user); $ubl_invoice->setAccountingSupplierParty($supplier_party); $customer_party = $this->createParty($client, $client->contacts[0]); $ubl_invoice->setAccountingCustomerParty($customer_party); // line items $invoice_lines = []; $taxable = $this->getTaxable(); foreach ($invoice->line_items as $index => $item) { $itemTaxable = $this->getItemTaxable($item, $taxable); $invoice_lines[] = $this->createInvoiceLine($index, $item, $itemTaxable); } $ubl_invoice->setInvoiceLines($invoice_lines); $taxtotal = new TaxTotal(); $taxAmount1 = $taxAmount2 = 0; $taxAmount1 = $this->createTaxRate($taxtotal, $taxable, $invoice->tax_rate1, $invoice->tax_name1); if ($invoice->tax_name2 || floatval($invoice->tax_rate2)) { $taxAmount2 = $this->createTaxRate($taxtotal, $taxable, $invoice->tax_rate2, $invoice->tax_name2); } $taxtotal->setTaxAmount($taxAmount1 + $taxAmount2); $ubl_invoice->setTaxTotal($taxtotal); $ubl_invoice->setLegalMonetaryTotal((new LegalMonetaryTotal()) //->setLineExtensionAmount() ->setTaxExclusiveAmount($taxable) ->setPayableAmount($invoice->balance)); try { return Generator::invoice($ubl_invoice, $invoice->client->getCurrencyCode()); } catch (\Exception $exception) { return false; } } private function createParty($company, $user) { $party = new Party(); $party->setName($company->present()->name); $address = (new Address()) ->setCityName($company->city) ->setStreetName($company->address1) ->setBuildingNumber($company->address2) ->setPostalZone($company->postal_code); if ($company->country_id) { $country = new Country(); $country->setIdentificationCode($company->country->iso_3166_2); $address->setCountry($country); } $party->setPostalAddress($address); $party->setPhysicalLocation($address); $contact = new Contact(); $contact->setElectronicMail($user->email); $party->setContact($contact); return $party; } private function createInvoiceLine($index, $item, $taxable) { $invoiceLine = (new InvoiceLine()) ->setId($index + 1) ->setInvoicedQuantity($item->quantity) ->setLineExtensionAmount($this->costWithDiscount($item)) ->setItem((new Item()) ->setName($item->product_key) ->setDescription($item->notes)); //->setSellersItemIdentification("1ABCD")); $taxtotal = new TaxTotal(); $itemTaxAmount1 = $itemTaxAmount2 = $itemTaxAmount3 = 0; $itemTaxAmount1 = $this->createTaxRate($taxtotal, $taxable, $item->tax_rate1, $item->tax_name1); if ($item->tax_name2 || floatval($item->tax_rate2)) { $itemTaxAmount2 = $this->createTaxRate($taxtotal, $taxable, $item->tax_rate2, $item->tax_name2); } if ($item->tax_name3 || floatval($item->tax_rate3)) { $itemTaxAmount3 = $this->createTaxRate($taxtotal, $taxable, $item->tax_rate3, $item->tax_name3); } $taxtotal->setTaxAmount($itemTaxAmount1 + $itemTaxAmount2 + $itemTaxAmount3); $invoiceLine->setTaxTotal($taxtotal); return $invoiceLine; } private function createTaxRate(&$taxtotal, $taxable, $taxRate, $taxName) { $invoice = $this->invoice; $taxAmount = $this->taxAmount($taxable, $taxRate); $taxScheme = ((new TaxScheme()))->setId($taxName); $taxtotal->addTaxSubTotal((new TaxSubTotal()) ->setTaxAmount($taxAmount) ->setTaxableAmount($taxable) ->setTaxCategory((new TaxCategory()) ->setId($taxName) ->setName($taxName) ->setTaxScheme($taxScheme) ->setPercent($taxRate))); return $taxAmount; } /** * @param $invoiceItem * @param $invoiceTotal * * @return float|int */ private function getItemTaxable($item, $invoice_total) { $total = $item->quantity * $item->cost; if ($this->invoice->discount != 0) { if ($this->invoice->is_amount_discount) { if ($invoice_total + $this->invoice->discount != 0) { $total -= $invoice_total ? ($total / ($invoice_total + $this->invoice->discount) * $this->invoice->discount) : 0; } } else { $total *= (100 - $this->invoice->discount) / 100; } } if ($item->discount != 0) { if ($this->invoice->is_amount_discount) { $total -= $item->discount; } else { $total -= $total * $item->discount / 100; } } return round($total, 2); } /** * @return float|int|mixed */ private function getTaxable() { $total = 0; foreach ($this->invoice->line_items as $item) { $line_total = $item->quantity * $item->cost; if ($item->discount != 0) { if ($this->invoice->is_amount_discount) { $line_total -= $item->discount; } else { $line_total -= $line_total * $item->discount / 100; } } $total += $line_total; } if ($this->invoice->discount > 0) { if ($this->invoice->is_amount_discount) { $total -= $this->invoice->discount; } else { $total *= (100 - $this->invoice->discount) / 100; $total = round($total, 2); } } if ($this->invoice->custom_surcharge1 && $this->invoice->custom_surcharge_tax1) { $total += $this->invoice->custom_surcharge1; } if ($this->invoice->custom_surcharge2 && $this->invoice->custom_surcharge_tax2) { $total += $this->invoice->custom_surcharge2; } if ($this->invoice->custom_surcharge3 && $this->invoice->custom_surcharge_tax3) { $total += $this->invoice->custom_surcharge3; } if ($this->invoice->custom_surcharge4 && $this->invoice->custom_surcharge_tax4) { $total += $this->invoice->custom_surcharge4; } return $total; } public function costWithDiscount($item) { $cost = $item->cost; if ($item->discount != 0) { if ($this->invoice->is_amount_discount) { $cost -= $item->discount / $item->quantity; } else { $cost -= $cost * $item->discount / 100; } } return $cost; } public function taxAmount($taxable, $rate) { if ($this->invoice->uses_inclusive_taxes) { return round($taxable - ($taxable / (1 + ($rate / 100))), 2); } else { return round($taxable * ($rate / 100), 2); } } }