akaunting/app/Traits/Documents.php

274 lines
7.7 KiB
PHP
Raw Permalink Normal View History

2020-12-24 01:28:38 +03:00
<?php
namespace App\Traits;
2023-04-29 01:43:48 +03:00
use App\Interfaces\Utility\DocumentNumber;
2020-12-24 01:28:38 +03:00
use App\Models\Document\Document;
2022-06-01 10:15:55 +03:00
use App\Abstracts\View\Components\Documents\Document as DocumentComponent;
use App\Utilities\Date;
use App\Traits\Transactions;
use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Validation\DNSCheckValidation;
use Egulias\EmailValidator\Validation\MultipleValidationWithAnd;
use Egulias\EmailValidator\Validation\RFCValidation;
2020-12-24 01:28:38 +03:00
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
trait Documents
{
2022-06-01 10:15:55 +03:00
use Transactions;
public function isRecurringDocument(): bool
{
$type = $this->type ?? $this->document->type ?? $this->model->type ?? 'invoice';
return Str::endsWith($type, '-recurring');
}
public function isNotRecurringDocument(): bool
{
return ! $this->isRecurring();
}
public function getRecurringDocumentTypes() : array
{
$types = array_keys(config('type.document'));
$recurring_types = [];
foreach ($types as $type) {
if (Str::endsWith($type, '-recurring')) {
$recurring_types[] = $type;
}
}
return $recurring_types;
}
2023-04-28 17:38:49 +02:00
/**
2023-04-29 01:43:48 +03:00
* Deprecated. Use the DocumentNumber::getNextNumber() method instead.
2023-04-28 17:38:49 +02:00
*
* @deprecated This method is deprecated and will be removed in future versions.
*/
2020-12-24 01:28:38 +03:00
public function getNextDocumentNumber(string $type): string
{
2023-04-29 01:43:48 +03:00
return app(DocumentNumber::class)->getNextNumber($type, null);
2020-12-24 01:28:38 +03:00
}
2023-04-28 17:38:49 +02:00
/**
2023-04-29 01:43:48 +03:00
* Deprecated. Use the DocumentNumber::increaseNextNumber() method instead.
2023-04-28 17:38:49 +02:00
*
* @deprecated This method is deprecated and will be removed in future versions.
*/
2020-12-24 01:28:38 +03:00
public function increaseNextDocumentNumber(string $type): void
{
2023-04-29 01:43:48 +03:00
app(DocumentNumber::class)->increaseNextNumber($type, null);
2020-12-24 01:28:38 +03:00
}
public function getDocumentStatuses(string $type): Collection
{
$list = [
'invoice' => [
'draft',
'sent',
'viewed',
'approved',
'partial',
'paid',
'overdue',
'unpaid',
'cancelled',
],
'bill' => [
'draft',
'received',
'partial',
'paid',
'overdue',
'unpaid',
'cancelled',
],
];
2021-01-11 11:10:30 +03:00
// @todo get dynamic path
//$trans_key = $this->getTextDocumentStatuses($type);
$trans_key = 'documents.statuses.';
$statuses = collect($list[$type])->each(function ($code) use ($type, $trans_key) {
2020-12-24 01:28:38 +03:00
$item = new \stdClass();
$item->code = $code;
2021-01-11 11:10:30 +03:00
$item->name = trans($trans_key . $code);
2020-12-24 01:28:38 +03:00
return $item;
});
return $statuses;
}
2022-06-01 10:15:55 +03:00
public function getDocumentStatusesForFuture()
{
return [
'draft',
'sent',
'received',
'viewed',
'partial',
];
}
2020-12-24 01:28:38 +03:00
public function getDocumentFileName(Document $document, string $separator = '-', string $extension = 'pdf'): string
{
return $this->getSafeDocumentNumber($document, $separator) . $separator . time() . '.' . $extension;
}
public function getSafeDocumentNumber(Document $document, string $separator = '-'): string
{
return Str::slug($document->document_number, $separator, language()->getShortCode());
}
2021-01-11 11:10:30 +03:00
protected function getTextDocumentStatuses($type)
{
2022-06-01 10:15:55 +03:00
$default_key = config('type.document.' . $type . '.translation.prefix') . '.statuses.';
2021-01-11 11:10:30 +03:00
$translation = DocumentComponent::getTextFromConfig($type, 'document_status', $default_key);
if (!empty($translation)) {
return $translation;
}
2022-06-01 10:15:55 +03:00
$alias = config('type.document.' . $type . '.alias');
2021-01-11 11:10:30 +03:00
if (!empty($alias)) {
2022-06-01 10:15:55 +03:00
$translation = $alias . '::' . config('type.document.' . $type . '.translation.prefix') . '.statuses';
2021-01-11 11:10:30 +03:00
2021-01-11 16:28:16 +03:00
if (is_array(trans($translation))) {
2021-01-11 11:10:30 +03:00
return $translation . '.';
}
}
return 'documents.statuses.';
}
// This function will be remoed in the future
protected function getSettingKey($type, $setting_key)
{
return $this->getDocumentSettingKey($type, $setting_key);
}
protected function getDocumentSettingKey($type, $setting_key)
{
$key = '';
2022-06-01 10:15:55 +03:00
$alias = config('type.document.' . $type . '.alias');
2022-06-01 10:15:55 +03:00
if (! empty($alias)) {
$key .= $alias . '.';
}
2022-06-01 10:15:55 +03:00
$prefix = config('type.document.' . $type . '.setting.prefix');
2023-03-09 14:07:27 +03:00
if (! empty($prefix)) {
$key .= $prefix . '.' . $setting_key;
} else {
$key .= $setting_key;
}
return $key;
}
2021-04-29 18:12:37 +03:00
public function storeDocumentPdfAndGetPath($document)
2021-04-29 18:12:37 +03:00
{
event(new \App\Events\Document\DocumentPrinting($document));
2021-04-29 18:12:37 +03:00
$view = view($document->template_path, ['invoice' => $document, 'document' => $document])->render();
2021-04-29 18:12:37 +03:00
$html = mb_convert_encoding($view, 'HTML-ENTITIES', 'UTF-8');
$pdf = app('dompdf.wrapper');
$pdf->loadHTML($html);
$file_name = $this->getDocumentFileName($document);
2021-04-29 18:12:37 +03:00
2023-08-24 15:44:10 +03:00
$pdf_path = get_storage_path('app/temp/' . $file_name);
2021-04-29 18:12:37 +03:00
// Save the PDF file into temp folder
$pdf->save($pdf_path);
return $pdf_path;
}
2022-06-01 10:15:55 +03:00
public function getTotalsForFutureDocuments($type = 'invoice', $documents = null)
{
$totals = [
'overdue' => 0,
'open' => 0,
'draft' => 0,
];
$today = Date::today()->toDateString();
$documents = $documents ?: Document::type($type)->with('transactions')->future();
$documents->each(function ($document) use (&$totals, $today) {
if (!in_array($document->status, $this->getDocumentStatusesForFuture())) {
return;
}
$payments = 0;
if ($document->status == 'draft') {
$totals['draft'] += $document->getAmountConvertedToDefault();
return;
}
if ($document->status == 'partial') {
foreach ($document->transactions as $transaction) {
$payments += $transaction->getAmountConvertedToDefault();
}
}
// Check if the document is open or overdue
if ($document->due_at > $today) {
$totals['open'] += $document->getAmountConvertedToDefault() - $payments;
} else {
$totals['overdue'] += $document->getAmountConvertedToDefault() - $payments;
}
});
return $totals;
}
public function canNotifyTheContactOfDocument(Document $document): bool
{
$config = config('type.document.' . $document->type . '.notification');
if (! $config['notify_contact']) {
return false;
}
if (! $document->contact || ($document->contact->enabled == 0)) {
return false;
}
if (empty($document->contact_email)) {
return false;
}
// Check if ietf.org has MX records signaling a server with email capabilites
$validator = new EmailValidator();
$validations = new MultipleValidationWithAnd([
new RFCValidation(),
new DNSCheckValidation(),
]);
if (! $validator->isValid($document->contact_email, $validations)) {
return false;
}
return true;
}
public function getRealTypeOfRecurringDocument(string $recurring_type): string
{
return Str::replace('-recurring', '', $recurring_type);
}
2020-12-24 01:28:38 +03:00
}