2024-06-12 16:14:24 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Invoice Ninja (https://invoiceninja.com).
|
|
|
|
*
|
|
|
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
|
|
*
|
|
|
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
|
|
|
*
|
|
|
|
* @license https://www.elastic.co/licensing/elastic-license
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace App\Services\EDocument\Imports;
|
|
|
|
|
|
|
|
use App\Factory\ExpenseFactory;
|
|
|
|
use App\Factory\VendorFactory;
|
|
|
|
use App\Jobs\Util\UploadFile;
|
2024-06-12 16:17:24 +02:00
|
|
|
use App\Models\Country;
|
2024-06-12 16:14:24 +02:00
|
|
|
use App\Models\Currency;
|
|
|
|
use App\Models\Expense;
|
|
|
|
use App\Models\Vendor;
|
2024-06-26 19:24:57 +02:00
|
|
|
use App\Models\VendorContact;
|
2024-06-12 16:14:24 +02:00
|
|
|
use App\Services\AbstractService;
|
|
|
|
use App\Utils\TempFile;
|
2024-06-22 18:04:35 +02:00
|
|
|
use App\Utils\Traits\SavesDocuments;
|
2024-06-12 16:14:24 +02:00
|
|
|
use Exception;
|
2024-08-28 07:02:43 +02:00
|
|
|
use App\Models\Company;
|
2024-10-16 23:46:53 +02:00
|
|
|
use App\Repositories\ExpenseRepository;
|
2024-10-16 23:56:21 +02:00
|
|
|
use App\Repositories\VendorContactRepository;
|
|
|
|
use App\Repositories\VendorRepository;
|
2024-06-12 16:14:24 +02:00
|
|
|
use horstoeko\zugferd\ZugferdDocumentReader;
|
|
|
|
use horstoeko\zugferdvisualizer\ZugferdVisualizer;
|
2024-08-18 23:42:49 +02:00
|
|
|
use horstoeko\zugferdvisualizer\renderer\ZugferdVisualizerLaravelRenderer;
|
2024-06-22 18:52:25 +02:00
|
|
|
use Illuminate\Http\UploadedFile;
|
2024-06-12 16:14:24 +02:00
|
|
|
|
2024-06-22 18:04:35 +02:00
|
|
|
class ZugferdEDocument extends AbstractService
|
|
|
|
{
|
|
|
|
use SavesDocuments;
|
2024-06-12 16:14:24 +02:00
|
|
|
public ZugferdDocumentReader|string $document;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
2024-08-28 07:02:43 +02:00
|
|
|
public function __construct(public UploadedFile $file, public Company $company)
|
2024-06-12 16:14:24 +02:00
|
|
|
{
|
|
|
|
# curl -X POST http://localhost:8000/api/v1/edocument/upload -H "Content-Type: multipart/form-data" -H "X-API-TOKEN: 7tdDdkz987H3AYIWhNGXy8jTjJIoDhkAclCDLE26cTCj1KYX7EBHC66VEitJwWhn" -H "X-Requested-With: XMLHttpRequest" -F _method=PUT -F documents[]=@einvoice.xml
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function run(): Expense
|
|
|
|
{
|
2024-07-02 10:36:53 +02:00
|
|
|
/** @var \App\Models\User $user */
|
2024-08-18 23:42:49 +02:00
|
|
|
$user = $this->company->owner();
|
2024-06-26 19:24:57 +02:00
|
|
|
|
2024-08-28 09:29:11 +02:00
|
|
|
$this->document = ZugferdDocumentReader::readAndGuessFromContent($this->file->get());
|
2024-06-12 16:14:24 +02:00
|
|
|
$this->document->getDocumentInformation($documentno, $documenttypecode, $documentdate, $invoiceCurrency, $taxCurrency, $documentname, $documentlanguage, $effectiveSpecifiedPeriod);
|
|
|
|
$this->document->getDocumentSummation($grandTotalAmount, $duePayableAmount, $lineTotalAmount, $chargeTotalAmount, $allowanceTotalAmount, $taxBasisTotalAmount, $taxTotalAmount, $roundingAmount, $totalPrepaidAmount);
|
|
|
|
|
2024-06-28 07:16:08 +02:00
|
|
|
/** @var \App\Models\Expense $expense */
|
2024-08-18 23:42:49 +02:00
|
|
|
$expense = Expense::where("company_id", $this->company->id)->where('amount', $grandTotalAmount)->where("transaction_reference", $documentno)->whereDate("date", $documentdate)->first();
|
2024-06-28 07:16:08 +02:00
|
|
|
if (!$expense) {
|
2024-06-12 16:14:24 +02:00
|
|
|
// The document does not exist as an expense
|
|
|
|
// Handle accordingly
|
|
|
|
$visualizer = new ZugferdVisualizer($this->document);
|
|
|
|
$visualizer->setDefaultTemplate();
|
2024-06-12 16:17:24 +02:00
|
|
|
$visualizer->setRenderer(app(ZugferdVisualizerLaravelRenderer::class));
|
2024-06-12 16:14:24 +02:00
|
|
|
$visualizer->setPdfFontDefault("arial");
|
|
|
|
$visualizer->setPdfPaperSize('A4-P');
|
2024-06-12 16:17:24 +02:00
|
|
|
$visualizer->setTemplate('edocument.xinvoice');
|
2024-06-12 16:14:24 +02:00
|
|
|
|
2024-08-18 23:42:49 +02:00
|
|
|
$expense = ExpenseFactory::create($this->company->id, $user->id);
|
2024-06-12 16:14:24 +02:00
|
|
|
$expense->date = $documentdate;
|
|
|
|
$expense->public_notes = $documentno;
|
2024-08-18 23:42:49 +02:00
|
|
|
$expense->currency_id = Currency::whereCode($invoiceCurrency)->first()->id ?? $this->company->settings->currency_id;
|
2024-06-12 16:14:24 +02:00
|
|
|
$expense->save();
|
|
|
|
|
2024-06-23 09:32:51 +02:00
|
|
|
$documents = [$this->file];
|
2024-06-22 18:52:25 +02:00
|
|
|
if ($this->file->getExtension() == "xml")
|
|
|
|
array_push($documents, TempFile::UploadedFileFromRaw($visualizer->renderPdf(), $documentno . "_visualiser.pdf", "application/pdf"));
|
|
|
|
$this->saveDocuments($documents, $expense);
|
2024-08-28 07:02:43 +02:00
|
|
|
|
2024-06-12 16:14:24 +02:00
|
|
|
$expense->save();
|
2024-06-22 18:04:35 +02:00
|
|
|
|
2024-06-12 16:14:24 +02:00
|
|
|
if ($taxCurrency && $taxCurrency != $invoiceCurrency) {
|
|
|
|
$expense->private_notes = ctrans("texts.tax_currency_mismatch");
|
|
|
|
}
|
2024-08-22 08:45:06 +02:00
|
|
|
$expense->uses_inclusive_taxes = true;
|
2024-06-12 16:14:24 +02:00
|
|
|
$expense->amount = $grandTotalAmount;
|
|
|
|
$counter = 1;
|
|
|
|
if ($this->document->firstDocumentTax()) {
|
|
|
|
do {
|
|
|
|
$this->document->getDocumentTax($categoryCode, $typeCode, $basisAmount, $calculatedAmount, $rateApplicablePercent, $exemptionReason, $exemptionReasonCode, $lineTotalBasisAmount, $allowanceChargeBasisAmount, $taxPointDate, $dueDateTypeCode);
|
|
|
|
$expense->{"tax_amount$counter"} = $calculatedAmount;
|
|
|
|
$expense->{"tax_rate$counter"} = $rateApplicablePercent;
|
2024-10-16 23:46:53 +02:00
|
|
|
$expense->{"tax_name$counter"} = $typeCode;
|
2024-06-12 16:14:24 +02:00
|
|
|
$counter++;
|
|
|
|
} while ($this->document->nextDocumentTax());
|
|
|
|
}
|
|
|
|
$this->document->getDocumentSeller($name, $buyer_id, $buyer_description);
|
|
|
|
$this->document->getDocumentSellerContact($person_name, $person_department, $contact_phone, $contact_fax, $contact_email);
|
2024-06-12 16:17:24 +02:00
|
|
|
$this->document->getDocumentSellerAddress($address_1, $address_2, $address_3, $postcode, $city, $country, $subdivision);
|
2024-06-12 16:14:24 +02:00
|
|
|
$this->document->getDocumentSellerTaxRegistration($taxtype);
|
2024-06-26 19:24:57 +02:00
|
|
|
|
2024-06-12 16:14:24 +02:00
|
|
|
$taxid = null;
|
|
|
|
if (array_key_exists("VA", $taxtype)) {
|
|
|
|
$taxid = $taxtype["VA"];
|
|
|
|
}
|
|
|
|
|
2024-08-30 02:57:43 +02:00
|
|
|
$vendor = Vendor::query()
|
2024-09-02 05:07:01 +02:00
|
|
|
->where("company_id", $this->company->id)
|
2024-08-30 02:57:43 +02:00
|
|
|
->where(function ($q) use($taxid, $person_name, $contact_email){
|
|
|
|
$q->when(!is_null($taxid), function ($when_query) use($taxid){
|
|
|
|
$when_query->orWhere('vat_number', $taxid);
|
|
|
|
})
|
|
|
|
->orWhere("name", $person_name)
|
|
|
|
->orWhereHas('contacts', function ($qq) use ($contact_email){
|
|
|
|
$qq->where("email", $contact_email);
|
|
|
|
});
|
|
|
|
})->first();
|
|
|
|
|
|
|
|
if ($vendor) {
|
2024-06-12 16:14:24 +02:00
|
|
|
$expense->vendor_id = $vendor->id;
|
|
|
|
} else {
|
2024-08-18 23:42:49 +02:00
|
|
|
$vendor = VendorFactory::create($this->company->id, $user->id);
|
2024-06-12 16:14:24 +02:00
|
|
|
$vendor->name = $name;
|
|
|
|
if ($taxid != null) {
|
|
|
|
$vendor->vat_number = $taxid;
|
|
|
|
}
|
2024-07-02 10:36:53 +02:00
|
|
|
$vendor->currency_id = Currency::query()->where('code', $invoiceCurrency)->first()->id;
|
2024-06-12 16:17:24 +02:00
|
|
|
$vendor->phone = $contact_phone;
|
|
|
|
$vendor->address1 = $address_1;
|
|
|
|
$vendor->address2 = $address_2;
|
|
|
|
$vendor->city = $city;
|
|
|
|
$vendor->postal_code = $postcode;
|
2024-07-31 07:59:26 +02:00
|
|
|
|
2024-06-26 17:34:32 +02:00
|
|
|
$country = app('countries')->first(function ($c) use ($country) {
|
2024-09-23 05:36:12 +02:00
|
|
|
/** @var \App\Models\Country $c */
|
2024-06-26 17:34:32 +02:00
|
|
|
return $c->iso_3166_2 == $country || $c->iso_3166_3 == $country;
|
|
|
|
});
|
|
|
|
if ($country)
|
|
|
|
$vendor->country_id = $country->id;
|
2024-06-12 16:14:24 +02:00
|
|
|
|
2024-10-16 23:56:21 +02:00
|
|
|
$vendor_repo = new VendorRepository(new VendorContactRepository());
|
|
|
|
$vendor = $vendor_repo->save([], $vendor);
|
|
|
|
|
2024-06-12 16:14:24 +02:00
|
|
|
$expense->vendor_id = $vendor->id;
|
|
|
|
}
|
|
|
|
$expense->transaction_reference = $documentno;
|
2024-06-22 18:04:35 +02:00
|
|
|
} else {
|
2024-06-12 16:14:24 +02:00
|
|
|
// The document exists as an expense
|
|
|
|
// Handle accordingly
|
2024-10-19 04:43:22 +02:00
|
|
|
nlog("Zugferd: Document already exists {$expense->hashed_id}");
|
2024-06-12 16:14:24 +02:00
|
|
|
$expense->private_notes = $expense->private_notes . ctrans("texts.edocument_import_already_exists", ["date" => time()]);
|
|
|
|
}
|
2024-10-16 23:46:53 +02:00
|
|
|
|
|
|
|
$expense_repo = new ExpenseRepository();
|
|
|
|
$expense = $expense_repo->save([],$expense);
|
|
|
|
|
2024-06-12 16:14:24 +02:00
|
|
|
return $expense;
|
|
|
|
}
|
|
|
|
}
|