diff --git a/VERSION.txt b/VERSION.txt index ffd041c1c1..fc0b8577dd 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.11.23 \ No newline at end of file +5.11.24 \ No newline at end of file diff --git a/app/Helpers/SwissQr/SwissQrGenerator.php b/app/Helpers/SwissQr/SwissQrGenerator.php index 242a6250df..47f9ae4f3c 100644 --- a/app/Helpers/SwissQr/SwissQrGenerator.php +++ b/app/Helpers/SwissQr/SwissQrGenerator.php @@ -172,6 +172,7 @@ class SwissQrGenerator ->setPrintable(false) ->getPaymentPart(); + // return $html; return htmlspecialchars($html); } catch (\Exception $e) { diff --git a/app/Http/Controllers/ClientPortal/InvoiceController.php b/app/Http/Controllers/ClientPortal/InvoiceController.php index 60a58a4e40..a7a3105a98 100644 --- a/app/Http/Controllers/ClientPortal/InvoiceController.php +++ b/app/Http/Controllers/ClientPortal/InvoiceController.php @@ -106,14 +106,14 @@ class InvoiceController extends Controller break; } - usleep(200000); + usleep(300000); } $invitation = false; match($data['entity_type'] ?? 'invoice') { - 'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']), + 'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']), //@todo - sometimes this is false!! 'quote' => $invitation = QuoteInvitation::withTrashed()->find($data['invitation_id']), 'credit' => $invitation = CreditInvitation::withTrashed()->find($data['invitation_id']), 'recurring_invoice' => $invitation = RecurringInvoiceInvitation::withTrashed()->find($data['invitation_id']), diff --git a/app/Http/Requests/Company/UpdateCompanyRequest.php b/app/Http/Requests/Company/UpdateCompanyRequest.php index 8aa24ffacb..63fb67815b 100644 --- a/app/Http/Requests/Company/UpdateCompanyRequest.php +++ b/app/Http/Requests/Company/UpdateCompanyRequest.php @@ -195,7 +195,10 @@ class UpdateCompanyRequest extends Request if (Ninja::isHosted()) { foreach ($this->protected_input as $protected_var) { - $settings[$protected_var] = str_replace("script", "", $settings[$protected_var]); + + if(isset($settings[$protected_var])) { + $settings[$protected_var] = str_replace("script", "", $settings[$protected_var]); + } } } diff --git a/app/Http/Requests/RecurringInvoice/StoreRecurringInvoiceRequest.php b/app/Http/Requests/RecurringInvoice/StoreRecurringInvoiceRequest.php index d02046b40b..ab60e55d2e 100644 --- a/app/Http/Requests/RecurringInvoice/StoreRecurringInvoiceRequest.php +++ b/app/Http/Requests/RecurringInvoice/StoreRecurringInvoiceRequest.php @@ -13,7 +13,6 @@ namespace App\Http\Requests\RecurringInvoice; use App\Http\Requests\Request; use App\Http\ValidationRules\Project\ValidProjectForClient; -use App\Http\ValidationRules\Recurring\UniqueRecurringInvoiceNumberRule; use App\Models\Client; use App\Models\RecurringInvoice; use App\Utils\Traits\CleanLineItems; @@ -68,7 +67,7 @@ class StoreRecurringInvoiceRequest extends Request $rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())]; - $rules['number'] = new UniqueRecurringInvoiceNumberRule($this->all()); + $rules['number'] = ['bail', 'nullable', \Illuminate\Validation\Rule::unique('recurring_invoices')->where('company_id', $user->company()->id)]; $rules['tax_rate1'] = 'bail|sometimes|numeric'; $rules['tax_rate2'] = 'bail|sometimes|numeric'; diff --git a/app/Http/Requests/RecurringQuote/StoreRecurringQuoteRequest.php b/app/Http/Requests/RecurringQuote/StoreRecurringQuoteRequest.php index 657b96d0bb..ef9c13c301 100644 --- a/app/Http/Requests/RecurringQuote/StoreRecurringQuoteRequest.php +++ b/app/Http/Requests/RecurringQuote/StoreRecurringQuoteRequest.php @@ -12,7 +12,6 @@ namespace App\Http\Requests\RecurringQuote; use App\Http\Requests\Request; -use App\Http\ValidationRules\Recurring\UniqueRecurringQuoteNumberRule; use App\Models\Client; use App\Models\RecurringQuote; use App\Utils\Traits\CleanLineItems; @@ -63,7 +62,7 @@ class StoreRecurringQuoteRequest extends Request $rules['frequency_id'] = 'required|integer|digits_between:1,12'; - $rules['number'] = new UniqueRecurringQuoteNumberRule($this->all()); + $rules['number'] = ['bail', 'nullable', \Illuminate\Validation\Rule::unique('recurring_quotes')->where('company_id', $user->company()->id)]; return $rules; } diff --git a/app/Http/ValidationRules/Recurring/UniqueRecurringInvoiceNumberRule.php b/app/Http/ValidationRules/Recurring/UniqueRecurringInvoiceNumberRule.php deleted file mode 100644 index b7865a0b51..0000000000 --- a/app/Http/ValidationRules/Recurring/UniqueRecurringInvoiceNumberRule.php +++ /dev/null @@ -1,67 +0,0 @@ -input = $input; - } - - /** - * @param string $attribute - * @param mixed $value - * @return bool - */ - public function passes($attribute, $value) - { - return $this->checkIfInvoiceNumberUnique(); //if it exists, return false! - } - - /** - * @return string - */ - public function message() - { - return ctrans('texts.recurring_invoice_number_taken', ['number' => $this->input['number']]); - } - - /** - * @return bool - */ - private function checkIfInvoiceNumberUnique(): bool - { - if (empty($this->input['number'])) { - return true; - } - - $invoice = RecurringInvoice::query()->where('client_id', $this->input['client_id']) - ->where('number', $this->input['number']) - ->withTrashed() - ->exists(); - - if ($invoice) { - return false; - } - - return true; - } -} diff --git a/app/Http/ValidationRules/Recurring/UniqueRecurringQuoteNumberRule.php b/app/Http/ValidationRules/Recurring/UniqueRecurringQuoteNumberRule.php deleted file mode 100644 index 29693a067d..0000000000 --- a/app/Http/ValidationRules/Recurring/UniqueRecurringQuoteNumberRule.php +++ /dev/null @@ -1,67 +0,0 @@ -input = $input; - } - - /** - * @param string $attribute - * @param mixed $value - * @return bool - */ - public function passes($attribute, $value) - { - return $this->checkIfQuoteNumberUnique(); //if it exists, return false! - } - - /** - * @return string - */ - public function message() - { - return ctrans('texts.recurring_quote_number_taken', ['number' => $this->input['number']]); - } - - /** - * @return bool - */ - private function checkIfQuoteNumberUnique(): bool - { - if (empty($this->input['number'])) { - return true; - } - - $invoice = RecurringQuote::query()->where('client_id', $this->input['client_id']) - ->where('number', $this->input['number']) - ->withTrashed() - ->exists(); - - if ($invoice) { - return false; - } - - return true; - } -} diff --git a/app/Jobs/Mail/NinjaMailerJob.php b/app/Jobs/Mail/NinjaMailerJob.php index 8414df5df3..a78861f221 100644 --- a/app/Jobs/Mail/NinjaMailerJob.php +++ b/app/Jobs/Mail/NinjaMailerJob.php @@ -515,7 +515,7 @@ class NinjaMailerJob implements ShouldQueue private function checkValidSendingUser($user) { /* Always ensure the user is set on the correct account */ - if ($user->account_id != $this->company->account_id) { + if (!$user ||($user->account_id != $this->company->account_id)) { $this->nmo->settings->email_sending_method = 'default'; return $this->setMailDriver(); } diff --git a/app/Livewire/Flow2/InvoicePay.php b/app/Livewire/Flow2/InvoicePay.php index 79c303a119..a434dbf7c4 100644 --- a/app/Livewire/Flow2/InvoicePay.php +++ b/app/Livewire/Flow2/InvoicePay.php @@ -141,6 +141,9 @@ class InvoicePay extends Component $company_gateway = CompanyGateway::query()->find($company_gateway_id); + if(!$company_gateway) + return $this->required_fields = false; + $this->checkRequiredFields($company_gateway); } diff --git a/app/PaymentDrivers/Authorize/AuthorizeTransaction.php b/app/PaymentDrivers/Authorize/AuthorizeTransaction.php index abd81d1f21..a49e65985c 100644 --- a/app/PaymentDrivers/Authorize/AuthorizeTransaction.php +++ b/app/PaymentDrivers/Authorize/AuthorizeTransaction.php @@ -119,6 +119,10 @@ class AuthorizeTransaction $transactionRequestType->setOrder($order); $transactionRequestType->addToTransactionSettings($duplicateWindowSetting); + $solution = new \net\authorize\api\contract\v1\SolutionType(); + $solution->setId($this->authorize->company_gateway->getConfigField('testMode') ? 'AAA100303' : 'AAA172036'); + $transactionRequestType->setSolution($solution); + $transactionRequestType->setPayment($paymentOne); $transactionRequestType->setCurrencyCode($this->authorize->client->currency()->code); diff --git a/app/PaymentDrivers/Authorize/ChargePaymentProfile.php b/app/PaymentDrivers/Authorize/ChargePaymentProfile.php index 144350a8fa..28af2875c5 100644 --- a/app/PaymentDrivers/Authorize/ChargePaymentProfile.php +++ b/app/PaymentDrivers/Authorize/ChargePaymentProfile.php @@ -92,6 +92,10 @@ class ChargePaymentProfile $transactionRequestType->setProfile($profileToCharge); $transactionRequestType->setCurrencyCode($this->authorize->client->currency()->code); + $solution = new \net\authorize\api\contract\v1\SolutionType(); + $solution->setId($this->authorize->company_gateway->getConfigField('testMode') ? 'AAA100303' : 'AAA172036'); + $transactionRequestType->setSolution($solution); + $request = new CreateTransactionRequest(); $request->setMerchantAuthentication($this->authorize->merchant_authentication); $request->setRefId($refId); diff --git a/app/PaymentDrivers/Authorize/RefundTransaction.php b/app/PaymentDrivers/Authorize/RefundTransaction.php index a543d867e5..41bc2fd3ad 100644 --- a/app/PaymentDrivers/Authorize/RefundTransaction.php +++ b/app/PaymentDrivers/Authorize/RefundTransaction.php @@ -83,6 +83,10 @@ class RefundTransaction $transactionRequest->setPayment($paymentOne); $transactionRequest->setRefTransId($payment->transaction_reference); + $solution = new \net\authorize\api\contract\v1\SolutionType(); + $solution->setId($this->authorize->company_gateway->getConfigField('testMode') ? 'AAA100303' : 'AAA172036'); + $transactionRequest->setSolution($solution); + $request = new CreateTransactionRequest(); $request->setMerchantAuthentication($this->authorize->merchant_authentication); $request->setRefId($refId); diff --git a/app/Services/Email/Email.php b/app/Services/Email/Email.php index 9a9f618647..8fb90f0c7a 100644 --- a/app/Services/Email/Email.php +++ b/app/Services/Email/Email.php @@ -691,7 +691,7 @@ class Email implements ShouldQueue private function checkValidSendingUser($user) { /* Always ensure the user is set on the correct account */ - if ($user->account_id != $this->company->account_id) { + if (!$user || ($user->account_id != $this->company->account_id)) { $this->email_object->settings->email_sending_method = 'default'; return $this->setMailDriver(); diff --git a/app/Services/Pdf/PdfBuilder.php b/app/Services/Pdf/PdfBuilder.php index c46251ce08..d5d29f5f11 100644 --- a/app/Services/Pdf/PdfBuilder.php +++ b/app/Services/Pdf/PdfBuilder.php @@ -352,7 +352,7 @@ class PdfBuilder $outstanding = $this->service->options['invoices']->sum('balance'); return [ - ['element' => 'p', 'content' => '$outstanding_label: ' . $this->service->config->formatMoney($outstanding)], + ['element' => 'div', 'content' => '$outstanding_label: ' . $this->service->config->formatMoney($outstanding)], ]; } @@ -402,7 +402,7 @@ class PdfBuilder $outstanding = $this->service->options['credits']->sum('balance'); return [ - ['element' => 'p', 'content' => '$credit.balance_label: ' . $this->service->config->formatMoney($outstanding)], + ['element' => 'div', 'content' => '$credit.balance_label: ' . $this->service->config->formatMoney($outstanding)], ]; } @@ -474,7 +474,7 @@ class PdfBuilder } } } - + return [ ['element' => 'thead', 'elements' => $this->buildTableHeader('statement_payment')], ['element' => 'tbody', 'elements' => $tbody], @@ -500,9 +500,9 @@ class PdfBuilder $payment = $this->service->options['payments']->first(); return [ - ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.amount_paid'), $this->service->config->formatMoney($this->payment_amount_total))], - ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_method'), $payment->translatedType())], - ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_date'), $this->translateDate($payment->date, $this->service->config->date_format, $this->service->config->locale) ?: ' ')], + ['element' => 'div', 'content' => \sprintf('%s: %s', ctrans('texts.amount_paid'), $this->service->config->formatMoney($this->payment_amount_total))], + ['element' => 'div', 'content' => \sprintf('%s: %s', ctrans('texts.payment_method'), $payment->translatedType())], + ['element' => 'div', 'content' => \sprintf('%s: %s', ctrans('texts.payment_date'), $this->translateDate($payment->date, $this->service->config->date_format, $this->service->config->locale) ?: ' ')], ]; } @@ -520,9 +520,9 @@ class PdfBuilder $payment = $this->service->options['unapplied']->first(); return [ - ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_balance'), $this->service->config->formatMoney($this->unapplied_total))], - ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_method'), $payment->translatedType())], - ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_date'), $this->translateDate($payment->date, $this->service->config->date_format, $this->service->config->locale) ?: ' ')], + ['element' => 'div', 'content' => \sprintf('%s: %s', ctrans('texts.payment_balance'), $this->service->config->formatMoney($this->unapplied_total))], + ['element' => 'div', 'content' => \sprintf('%s: %s', ctrans('texts.payment_method'), $payment->translatedType())], + ['element' => 'div', 'content' => \sprintf('%s: %s', ctrans('texts.payment_date'), $this->translateDate($payment->date, $this->service->config->date_format, $this->service->config->locale) ?: ' ')], ]; } @@ -866,7 +866,6 @@ class PdfBuilder $element['elements'][$last_visible]['properties']['class'] .= ' right-radius'; } } - // Then, filter the elements array $element['elements'] = array_map(function ($el) { @@ -1405,7 +1404,7 @@ class PdfBuilder ['element' => 'span', 'content' => strtr(str_replace(["labels", "values"], ["",""], $_variables['values']['$entity.public_notes']), $_variables)] ]], ['element' => 'div', 'content' => '', 'properties' => ['style' => 'text-align: left; display: flex; flex-direction: column; page-break-inside: auto;'], 'elements' => [ - ['element' => 'span', 'content' => '$entity.terms_label: ', 'properties' => ['data-ref' => 'total_table-terms-label', 'style' => "text-align: left; margin-top: 1rem; {$show_terms_label}"]], + ['element' => 'span', 'content' => '$entity.terms_label: ', 'properties' => ['data-ref' => 'total_table-terms-label', 'style' => "font-weight:bold; text-align: left; margin-top: 1rem; {$show_terms_label}"]], ['element' => 'span', 'content' => strtr(str_replace("labels", "", $_variables['values']['$entity.terms']), $_variables['labels']), 'properties' => ['data-ref' => 'total_table-terms', 'style' => 'text-align: left;']], ]], ['element' => 'img', 'properties' => ['style' => 'max-width: 50%; height: auto;', 'src' => '$contact.signature', 'id' => 'contact-signature']], @@ -1761,20 +1760,20 @@ class PdfBuilder } $elements = [ - ['element' => 'p', 'content' => ctrans('texts.delivery_note'), 'properties' => ['data-ref' => 'delivery_note-label', 'style' => 'font-weight: bold; text-transform: uppercase']], - ['element' => 'p', 'content' => $this->service->config->client->name, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.name']], - ['element' => 'p', 'content' => $this->service->config->client->shipping_address1, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.shipping_address1']], - ['element' => 'p', 'content' => $this->service->config->client->shipping_address2, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.shipping_address2']], - ['element' => 'p', 'show_empty' => false, 'elements' => [ + ['element' => 'div', 'content' => ctrans('texts.delivery_note'), 'properties' => ['data-ref' => 'delivery_note-label', 'style' => 'font-weight: bold; text-transform: uppercase']], + ['element' => 'div', 'content' => $this->service->config->client->name, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.name']], + ['element' => 'div', 'content' => $this->service->config->client->shipping_address1, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.shipping_address1']], + ['element' => 'div', 'content' => $this->service->config->client->shipping_address2, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.shipping_address2']], + ['element' => 'div', 'show_empty' => false, 'elements' => [ ['element' => 'span', 'content' => "{$this->service->config->client->shipping_city} ", 'properties' => ['ref' => 'delivery_note-client.shipping_city']], ['element' => 'span', 'content' => "{$this->service->config->client->shipping_state} ", 'properties' => ['ref' => 'delivery_note-client.shipping_state']], ['element' => 'span', 'content' => "{$this->service->config->client->shipping_postal_code} ", 'properties' => ['ref' => 'delivery_note-client.shipping_postal_code']], ]], - ['element' => 'p', 'content' => optional($this->service->config->client->shipping_country)->name, 'show_empty' => false], + ['element' => 'div', 'content' => optional($this->service->config->client->shipping_country)->name, 'show_empty' => false], ]; if (!is_null($this->service->config->contact)) { - $elements[] = ['element' => 'p', 'content' => $this->service->config->contact->email, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-contact.email']]; + $elements[] = ['element' => 'div', 'content' => $this->service->config->contact->email, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-contact.email']]; } return $elements; @@ -1796,7 +1795,7 @@ class PdfBuilder $variables = $this->service->config->pdf_variables['client_details']; foreach ($variables as $variable) { - $elements[] = ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'client_details-' . substr($variable, 1)]]; + $elements[] = ['element' => 'div', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'client_details-' . substr($variable, 1)]]; } return $elements; @@ -1811,16 +1810,16 @@ class PdfBuilder } $elements = [ - ['element' => 'p', 'content' => ctrans('texts.shipping_address'), 'properties' => ['data-ref' => 'shipping_address-label', 'style' => 'font-weight: bold; text-transform: uppercase']], - // ['element' => 'p', 'content' => $this->service->config->client->name, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.name']], - ['element' => 'p', 'content' => $this->service->config->client->shipping_address1, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.shipping_address1']], - ['element' => 'p', 'content' => $this->service->config->client->shipping_address2, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.shipping_address2']], - ['element' => 'p', 'show_empty' => false, 'elements' => [ + ['element' => 'div', 'content' => ctrans('texts.shipping_address'), 'properties' => ['data-ref' => 'shipping_address-label', 'style' => 'font-weight: bold; text-transform: uppercase']], + // ['element' => 'div', 'content' => $this->service->config->client->name, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.name']], + ['element' => 'div', 'content' => $this->service->config->client->shipping_address1, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.shipping_address1']], + ['element' => 'div', 'content' => $this->service->config->client->shipping_address2, 'show_empty' => false, 'properties' => ['data-ref' => 'shipping_address-client.shipping_address2']], + ['element' => 'div', 'show_empty' => false, 'elements' => [ ['element' => 'span', 'content' => "{$this->service->config->client->shipping_city} ", 'properties' => ['ref' => 'shipping_address-client.shipping_city']], ['element' => 'span', 'content' => "{$this->service->config->client->shipping_state} ", 'properties' => ['ref' => 'shipping_address-client.shipping_state']], ['element' => 'span', 'content' => "{$this->service->config->client->shipping_postal_code} ", 'properties' => ['ref' => 'shipping_address-client.shipping_postal_code']], ]], - ['element' => 'p', 'content' => optional($this->service->config->client->shipping_country)->name, 'show_empty' => false], + ['element' => 'div', 'content' => optional($this->service->config->client->shipping_country)->name, 'show_empty' => false], ]; return $elements; @@ -1899,7 +1898,7 @@ class PdfBuilder $elements = []; foreach ($variables as $variable) { - $elements[] = ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'company_details-' . substr($variable, 1)]]; + $elements[] = ['element' => 'div', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'company_details-' . substr($variable, 1)]]; } return $elements; @@ -1919,7 +1918,7 @@ class PdfBuilder $elements = []; foreach ($variables as $variable) { - $elements[] = ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'company_address-' . substr($variable, 1)]]; + $elements[] = ['element' => 'div', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'company_address-' . substr($variable, 1)]]; } return $elements; @@ -1939,7 +1938,7 @@ class PdfBuilder $variables = $this->service->config->pdf_variables['vendor_details']; foreach ($variables as $variable) { - $elements[] = ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'vendor_details-' . substr($variable, 1)]]; + $elements[] = ['element' => 'div', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'vendor_details-' . substr($variable, 1)]]; } return $elements; @@ -1997,23 +1996,49 @@ class PdfBuilder public function createElementContent($element, $children): self { foreach ($children as $child) { + $contains_html = false; + $contains_markdown = false; + $child['content'] = $child['content'] ?? ''; - if ($child['element'] !== 'script') { - if ($this->service->company->markdown_enabled && array_key_exists('content', $child)) { - $child['content'] = str_replace('
', "\r", ($child['content'] ?? '')); - $child['content'] = $this->commonmark->convert($child['content'] ?? ''); //@phpstan-ignore-line - } - } + $lines = explode("\n", $child['content']); + $contains_markdown = false; - if (isset($child['content'])) { - if (isset($child['is_empty']) && $child['is_empty'] === true) { + foreach ($lines as $line) { + $trimmed = ltrim($line); + if (empty($trimmed)) { continue; } - $contains_html = preg_match('#(?<=<)\w+(?=[^<]*?>)#', $child['content'], $m) != 0; + $first_char = substr($trimmed, 0, 1); + + if ( + $first_char === '#' || // Headers + $first_char === '>' || // Blockquotes + $first_char === '-' || // Lists + $first_char === '*' || // Lists/Bold + $first_char === '_' || // Italic + $first_char === '`' || // Code + $first_char === '[' || // Links + str_contains($trimmed, '**') // Bold (special case) + ) { + $contains_markdown = true; + break; + } } + if ($this->service->company->markdown_enabled && $contains_markdown && $child['element'] !== 'script') { + $child['content'] = str_ireplace('
', "\r", $child['content']); + $child['content'] = $this->commonmark->convert($child['content']); //@phpstan-ignore-line + } + + if (isset($child['is_empty']) && $child['is_empty'] === true) { + continue; + } + + $contains_html = str_contains($child['content'], '<') && str_contains($child['content'], '>'); + + if ($contains_html) { // If the element contains the HTML, we gonna display it as is. Backend is going to @@ -2030,7 +2055,7 @@ class PdfBuilder // .. in case string doesn't contain any HTML, we'll just return // raw $content - $_child = $this->document->createElement($child['element'], isset($child['content']) ? htmlspecialchars($child['content']) : ''); + $_child = $this->document->createElement($child['element'], htmlspecialchars($child['content'])); } $element->appendChild($_child); diff --git a/app/Services/PdfMaker/Design.php b/app/Services/PdfMaker/Design.php index d5234e0908..3e05054ed5 100644 --- a/app/Services/PdfMaker/Design.php +++ b/app/Services/PdfMaker/Design.php @@ -241,7 +241,7 @@ class Design extends BaseDesign $elements = []; foreach ($variables as $variable) { - $elements[] = ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'company_details-' . substr($variable, 1)]]; + $elements[] = ['element' => 'div', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'company_details-' . substr($variable, 1)]]; } return $elements; @@ -254,7 +254,7 @@ class Design extends BaseDesign $elements = []; foreach ($variables as $variable) { - $elements[] = ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'company_address-' . substr($variable, 1)]]; + $elements[] = ['element' => 'div', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'company_address-' . substr($variable, 1)]]; } return $elements; @@ -271,7 +271,7 @@ class Design extends BaseDesign $variables = $this->context['pdf_variables']['vendor_details']; foreach ($variables as $variable) { - $elements[] = ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'vendor_details-' . substr($variable, 1)]]; + $elements[] = ['element' => 'div', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'vendor_details-' . substr($variable, 1)]]; } return $elements; @@ -301,12 +301,12 @@ class Design extends BaseDesign })->map(function ($variable) { $variable = str_replace('$client.', '$client.shipping_', $variable); - return ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => "client_details-shipping-" . substr($variable, 1)]]; + return ['element' => 'div', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => "client_details-shipping-" . substr($variable, 1)]]; })->toArray(); $header = []; - $header[] = ['element' => 'p', 'content' => ctrans('texts.shipping_address'), 'properties' => ['data-ref' => 'shipping_address-label', 'style' => 'font-weight: bold; text-transform: uppercase']]; + $header[] = ['element' => 'div', 'content' => ctrans('texts.shipping_address'), 'properties' => ['data-ref' => 'shipping_address-label', 'style' => 'font-weight: bold; text-transform: uppercase']]; return array_merge($header, $elements); @@ -322,20 +322,20 @@ class Design extends BaseDesign if ($this->type == self::DELIVERY_NOTE) { $elements = [ - ['element' => 'p', 'content' => ctrans('texts.delivery_note'), 'properties' => ['data-ref' => 'delivery_note-label', 'style' => 'font-weight: bold; text-transform: uppercase']], - ['element' => 'p', 'content' => $this->client->name, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.name']], - ['element' => 'p', 'content' => $this->client->shipping_address1, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.shipping_address1']], - ['element' => 'p', 'content' => $this->client->shipping_address2, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.shipping_address2']], - ['element' => 'p', 'show_empty' => false, 'elements' => [ + ['element' => 'div', 'content' => ctrans('texts.delivery_note'), 'properties' => ['data-ref' => 'delivery_note-label', 'style' => 'font-weight: bold; text-transform: uppercase']], + ['element' => 'div', 'content' => $this->client->name, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.name']], + ['element' => 'div', 'content' => $this->client->shipping_address1, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.shipping_address1']], + ['element' => 'div', 'content' => $this->client->shipping_address2, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-client.shipping_address2']], + ['element' => 'div', 'show_empty' => false, 'elements' => [ ['element' => 'span', 'content' => "{$this->client->shipping_city} ", 'properties' => ['ref' => 'delivery_note-client.shipping_city']], ['element' => 'span', 'content' => "{$this->client->shipping_state} ", 'properties' => ['ref' => 'delivery_note-client.shipping_state']], ['element' => 'span', 'content' => "{$this->client->shipping_postal_code} ", 'properties' => ['ref' => 'delivery_note-client.shipping_postal_code']], ]], - ['element' => 'p', 'content' => optional($this->client->shipping_country)->name, 'show_empty' => false], + ['element' => 'div', 'content' => optional($this->client->shipping_country)->name, 'show_empty' => false], ]; if (!is_null($this->context['contact'])) { - $elements[] = ['element' => 'p', 'content' => $this->context['contact']->email, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-contact.email']]; + $elements[] = ['element' => 'div', 'content' => $this->context['contact']->email, 'show_empty' => false, 'properties' => ['data-ref' => 'delivery_note-contact.email']]; } return $elements; @@ -344,7 +344,7 @@ class Design extends BaseDesign $variables = $this->context['pdf_variables']['client_details']; foreach ($variables as $variable) { - $elements[] = ['element' => 'p', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'client_details-' . substr($variable, 1)]]; + $elements[] = ['element' => 'div', 'content' => $variable, 'show_empty' => false, 'properties' => ['data-ref' => 'client_details-' . substr($variable, 1)]]; } return $elements; @@ -553,7 +553,7 @@ class Design extends BaseDesign $outstanding = $this->invoices->sum('balance'); return [ - ['element' => 'p', 'content' => '$outstanding_label: ' . Number::formatMoney($outstanding, $this->client)], + ['element' => 'div', 'content' => '$outstanding_label: ' . Number::formatMoney($outstanding, $this->client)], ]; } @@ -682,7 +682,7 @@ class Design extends BaseDesign $outstanding = $this->credits->sum('balance'); return [ - ['element' => 'p', 'content' => '$credit.balance_label: ' . Number::formatMoney($outstanding, $this->client)], + ['element' => 'div', 'content' => '$credit.balance_label: ' . Number::formatMoney($outstanding, $this->client)], ]; } @@ -699,8 +699,8 @@ class Design extends BaseDesign $payment = $this->payments->first(); return [ - // ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.amount_paid'), Number::formatMoney($this->payments->sum('amount'), $this->client))], - ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.amount_paid'), Number::formatMoney($this->payment_amount_total, $this->client))], + // ['element' => 'div', 'content' => \sprintf('%s: %s', ctrans('texts.amount_paid'), Number::formatMoney($this->payments->sum('amount'), $this->client))], + ['element' => 'div', 'content' => \sprintf('%s: %s', ctrans('texts.amount_paid'), Number::formatMoney($this->payment_amount_total, $this->client))], ]; } @@ -716,7 +716,7 @@ class Design extends BaseDesign } return [ - ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_balance_on_file'), Number::formatMoney($this->unapplied_total, $this->client))], + ['element' => 'div', 'content' => \sprintf('%s: %s', ctrans('texts.payment_balance_on_file'), Number::formatMoney($this->unapplied_total, $this->client))], ]; } @@ -1127,10 +1127,10 @@ class Design extends BaseDesign $elements = [ ['element' => 'div', 'properties' => ['style' => 'display: flex; flex-direction: column;'], 'elements' => [ - ['element' => 'p', 'properties' => ['data-ref' => 'total_table-public_notes', 'style' => 'text-align: left;'], 'elements' => [ + ['element' => 'div', 'properties' => ['data-ref' => 'total_table-public_notes', 'style' => 'text-align: left;'], 'elements' => [ ['element' => 'span', 'content' => strtr(str_replace(["labels", "values"], ["",""], $_variables['values']['$entity.public_notes']), $_variables)] ]], - ['element' => 'p', 'content' => '', 'properties' => ['style' => 'text-align: left; display: flex; flex-direction: column; page-break-inside: auto;'], 'elements' => [ + ['element' => 'div', 'content' => '', 'properties' => ['style' => 'text-align: left; display: flex; flex-direction: column; page-break-inside: auto;'], 'elements' => [ ['element' => 'span', 'content' => '$entity.terms_label: ', 'properties' => ['data-ref' => 'total_table-terms-label', 'style' => "font-weight: bold; text-align: left; margin-top: 1rem; {$show_terms_label}"]], ['element' => 'span', 'content' => strtr(str_replace("labels", "", $_variables['values']['$entity.terms']), $_variables['labels']), 'properties' => ['data-ref' => 'total_table-terms', 'style' => 'text-align: left;']], ]], diff --git a/app/Services/PdfMaker/PdfMakerUtilities.php b/app/Services/PdfMaker/PdfMakerUtilities.php index cf7b98c557..1ff942749a 100644 --- a/app/Services/PdfMaker/PdfMakerUtilities.php +++ b/app/Services/PdfMaker/PdfMakerUtilities.php @@ -91,22 +91,46 @@ trait PdfMakerUtilities { foreach ($children as $child) { $contains_html = false; + $contains_markdown = false; + $child['content'] = $child['content'] ?? ''; - if ($child['element'] !== 'script') { - if (array_key_exists('process_markdown', $this->data) && array_key_exists('content', $child) && $this->data['process_markdown']) { - $child['content'] = str_replace('
', "\r", ($child['content'] ?? '')); - $child['content'] = $this->commonmark->convert($child['content'] ?? ''); //@phpstan-ignore-line - } - } + $lines = explode("\n", $child['content']); + $contains_markdown = false; - if (isset($child['content'])) { - if (isset($child['is_empty']) && $child['is_empty'] === true) { + foreach ($lines as $line) { + $trimmed = ltrim($line); + if (empty($trimmed)) { continue; } - $contains_html = preg_match('#(?<=<)\w+(?=[^<]*?>)#', $child['content'], $m) != 0; + $first_char = substr($trimmed, 0, 1); + + if ( + $first_char === '#' || // Headers + $first_char === '>' || // Blockquotes + $first_char === '-' || // Lists + $first_char === '*' || // Lists/Bold + $first_char === '_' || // Italic + $first_char === '`' || // Code + $first_char === '[' || // Links + str_contains($trimmed, '**') // Bold (special case) + ) { + $contains_markdown = true; + break; + } } + if (isset($this->data['process_markdown']) && $this->data['process_markdown'] && $contains_markdown &&$child['element'] !== 'script') { + $child['content'] = str_replace('
', "\r", $child['content']); + $child['content'] = $this->commonmark->convert($child['content']); //@phpstan-ignore-line + } + + if (isset($child['is_empty']) && $child['is_empty'] === true) { + continue; + } + + $contains_html = str_contains($child['content'], '<') && str_contains($child['content'], '>'); + if ($contains_html) { // If the element contains the HTML, we gonna display it as is. Backend is going to // encode it for us, preventing any errors on the processing stage. @@ -118,9 +142,7 @@ trait PdfMakerUtilities $_child->nodeValue = htmlspecialchars($child['content']); } else { // .. in case string doesn't contain any HTML, we'll just return - // raw $content. - - $_child = $this->document->createElement($child['element'], isset($child['content']) ? htmlspecialchars($child['content']) : ''); + $_child = $this->document->createElement($child['element'], htmlspecialchars($child['content'])); } $element->appendChild($_child); diff --git a/app/Services/Template/TemplateService.php b/app/Services/Template/TemplateService.php index 83efda5e05..51f88e3cb5 100644 --- a/app/Services/Template/TemplateService.php +++ b/app/Services/Template/TemplateService.php @@ -68,7 +68,7 @@ class TemplateService private ?Vendor $vendor = null; - private Invoice | Quote | Credit | PurchaseOrder | RecurringInvoice | Task | Project $entity; + private Invoice | Quote | Credit | PurchaseOrder | RecurringInvoice | Task | Project | Payment $entity; private Payment $payment; @@ -1575,23 +1575,14 @@ class TemplateService foreach ($children as $child) { $contains_html = false; + $child['content'] = $child['content'] ?? ''; - //06-11-2023 for some reason this parses content as HTML - // if ($child['element'] !== 'script') { - // if ($this->company->markdown_enabled && array_key_exists('content', $child)) { - // $child['content'] = str_replace('
', "\r", $child['content']); - // $child['content'] = $this->commonmark->convert($child['content'] ?? ''); - // } - // } - - if (isset($child['content'])) { - if (isset($child['is_empty']) && $child['is_empty'] === true) { - continue; - } - - $contains_html = preg_match('#(?<=<)\w+(?=[^<]*?>)#', $child['content'], $m) != 0; + if (isset($child['is_empty']) && $child['is_empty'] === true) { + continue; } + $contains_html = str_contains($child['content'], '<') && str_contains($child['content'], '>'); + if ($contains_html) { // If the element contains the HTML, we gonna display it as is. Backend is going to // encode it for us, preventing any errors on the processing stage. @@ -1605,7 +1596,7 @@ class TemplateService } else { // .. in case string doesn't contain any HTML, we'll just return // raw $content. - $_child = $this->document->createElement($child['element'], isset($child['content']) ? $child['content'] : ''); + $_child = $this->document->createElement($child['element'], $child['content']); } $element->appendChild($_child); diff --git a/app/Utils/Traits/ClientGroupSettingsSaver.php b/app/Utils/Traits/ClientGroupSettingsSaver.php index e049886bab..ae7937b762 100644 --- a/app/Utils/Traits/ClientGroupSettingsSaver.php +++ b/app/Utils/Traits/ClientGroupSettingsSaver.php @@ -46,12 +46,14 @@ trait ClientGroupSettingsSaver unset($settings[$field]); } + $company_settings_stub = new CompanySettings(); + /* * for clients and group settings, if a field is not set or is set to a blank value, * we unset it from the settings object */ foreach ($settings as $key => $value) { - if (! isset($settings->{$key}) || empty($settings->{$key}) || (! is_object($settings->{$key}) && strlen($settings->{$key}) == 0)) { + if (! isset($settings->{$key}) || empty($settings->{$key}) || !property_exists($company_settings_stub, $key) || (! is_object($settings->{$key}) && strlen($settings->{$key}) == 0)) { unset($settings->{$key}); } } diff --git a/app/Utils/Traits/Pdf/PdfMaker.php b/app/Utils/Traits/Pdf/PdfMaker.php index 926692467a..ccaf0a10aa 100644 --- a/app/Utils/Traits/Pdf/PdfMaker.php +++ b/app/Utils/Traits/Pdf/PdfMaker.php @@ -94,7 +94,8 @@ trait PdfMaker } $html = str_ireplace(['file:/', 'iframe', ''], '', $html); - + + // nlog($html); $generated = $pdf ->setHtml($html) ->generate(); diff --git a/config/ninja.php b/config/ninja.php index 9120d5835b..fd6beadec5 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -17,8 +17,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION', '5.11.23'), - 'app_tag' => env('APP_TAG', '5.11.23'), + 'app_version' => env('APP_VERSION', '5.11.24'), + 'app_tag' => env('APP_TAG', '5.11.24'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false), diff --git a/lang/de/texts.php b/lang/de/texts.php index fb6f3ae89f..993e67fd13 100644 --- a/lang/de/texts.php +++ b/lang/de/texts.php @@ -28,7 +28,7 @@ $lang = array( 'invoice' => 'Rechnung', 'client' => 'Kunde', 'invoice_number' => 'Rechnungsnummer', - 'invoice_number_short' => 'Re-Nr.', + 'invoice_number_short' => 'Rechnung ', 'po_number' => 'Bestellnummer', 'po_number_short' => 'Best.-Nr.', 'frequency_id' => 'Wie oft', @@ -1536,8 +1536,8 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese 'country_Kazakhstan' => 'Kasachstan', 'country_Jordan' => 'Jordanien', 'country_Kenya' => 'Kenia', - 'country_Korea, Democratic People\'s Republic of' => 'Korea, Democratic People\'s Republic of', - 'country_Korea, Republic of' => 'Korea, Republic of', + 'country_Korea, Democratic People\'s Republic of' => 'Nordkorea', + 'country_Korea, Republic of' => 'Südkorea', 'country_Kuwait' => 'Kuwait', 'country_Kyrgyzstan' => 'Kirgisistan', 'country_Lao People\'s Democratic Republic' => 'Lao People\'s Democratic Republic', @@ -1562,7 +1562,7 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese 'country_Mexico' => 'Mexiko', 'country_Monaco' => 'Monaco', 'country_Mongolia' => 'Mongolei', - 'country_Moldova, Republic of' => 'Moldova, Republic of', + 'country_Moldova, Republic of' => 'Moldau', 'country_Montenegro' => 'Montenegro', 'country_Montserrat' => 'Montserrat', 'country_Morocco' => 'Marokko', @@ -1625,7 +1625,7 @@ Sobald Sie die Beträge erhalten haben, kommen Sie bitte wieder zurück zu diese 'country_Singapore' => 'Singapur', 'country_Slovakia' => 'Slowakei', 'country_Viet Nam' => 'Vietnam', - 'country_Slovenia' => 'Slovenien', + 'country_Slovenia' => 'Slowenien', 'country_Somalia' => 'Somalia', 'country_South Africa' => 'Südafrika', 'country_Zimbabwe' => 'Simbabwe', @@ -4035,7 +4035,7 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting', 'connect_google' => 'Google-Konto verbinden', 'disconnect_google' => 'Google-Konto entfernen', 'disable_two_factor' => 'Zwei-Faktor-Authentifizierung deaktivieren', - 'invoice_task_datelog' => 'In Aufgabe erfasste Daten in Rechnungen ausweisen', + 'invoice_task_datelog' => 'In Aufgabe erfasstes Datum in Rechnungen ausweisen', 'invoice_task_datelog_help' => 'Zeigt Datumsdetails in den Rechnungspositionen an', 'promo_code' => 'Gutscheincode', 'recurring_invoice_issued_to' => 'Wiederkehrende Rechnung ausgestellt an', @@ -4932,7 +4932,7 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting', 'oauth_mail' => 'OAuth / E-Mail', 'preferences' => 'Einstellungen', 'analytics' => 'Analytik', - 'reduced_rate' => 'Reduzierte Rate', + 'reduced_rate' => 'Reduzierter Preis', 'tax_all' => 'Alles besteuern', 'tax_selected' => 'Steuer ausgewählt', 'version' => 'Ausführung', @@ -4987,7 +4987,7 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting', 'enable_auto_bill' => 'Automatische Bezahlung aktivieren', 'email_count_invoices' => ':count Rechnungen versenden', 'invoice_task_item_description' => 'Rechnungspositionsbeschreibung', - 'invoice_task_item_description_help' => 'Element-Beschreibung zu den Rechnungs-Positionen hinzufügen', + 'invoice_task_item_description_help' => 'Element-Beschreibung zu den Rechnungspositionen hinzufügen', 'next_send_time' => 'Nächster Versandzeitpunkt', 'uploaded_certificate' => 'Das Zertifikat wurde erfolgreich hochgeladen', 'certificate_set' => 'Zertifikat hochgeladen', @@ -5141,6 +5141,8 @@ Leistungsempfängers', 'nordigen_handler_error_contents_institution_invalid' => 'Die angegebene Institutions-ID ist ungültig oder nicht mehr gültig.', 'nordigen_handler_error_heading_ref_invalid' => 'Ungültige Referenz', 'nordigen_handler_error_contents_ref_invalid' => 'GoCardless hat keine gültige Referenz angegeben. Bitte führen Sie Flow erneut aus und wenden Sie sich an den Support, wenn das Problem weiterhin besteht.', + 'nordigen_handler_error_heading_eua_failure' => 'EUA Fehler', + 'nordigen_handler_error_contents_eua_failure' => 'Beim Erstellen der Endbenutzervereinbarung (EUA) ist ein Fehler aufgetreten:', 'nordigen_handler_error_heading_not_found' => 'Ungültige Anforderung', 'nordigen_handler_error_contents_not_found' => 'GoCardless hat keine gültige Referenz angegeben. Bitte führen Sie Flow erneut aus und wenden Sie sich an den Support, wenn das Problem weiterhin besteht.', 'nordigen_handler_error_heading_requisition_invalid_status' => 'Nicht bereit', @@ -5370,7 +5372,7 @@ Leistungsempfängers', 'peppol_plan_warning' => 'Für die Nutzung der elektronischen Rechnungsstellung über das PEPPOL-Netzwerk ist ein Enterprise-Tarif erforderlich.', 'peppol_credits_info' => 'Zum Senden und Empfangen von E-Rechnungen sind E-Credits erforderlich. Diese werden pro Dokument berechnet.', 'buy_credits' => 'E Credits kaufen', - 'peppol_successfully_configured' => 'PEPPOL erfolgreich konfiguriert.', + 'peppol_successfully_configured' => 'PEPPOL erfolgreich konfiguriert.', 'peppol_not_paid_message' => 'Für PEPPOL ist ein Enterprise-Tarif erforderlich. Bitte aktualisieren Sie Ihren Plan.', 'peppol_country_not_supported' => 'Das PEPPOL-Netzwerk ist für dieses Land noch nicht verfügbar.', 'peppol_disconnect' => 'Trennen Sie die Verbindung zum PEPPOL-Netzwerk', @@ -5382,24 +5384,24 @@ Leistungsempfängers', 'hidden_taxes_warning' => 'Einige Steuern sind aufgrund der aktuellen Steuereinstellungen ausgeblendet. :link', 'tax3' => 'Dritte Steuer', 'negative_payment_warning' => 'Möchten Sie wirklich eine negative Zahlung erstellen? Diese kann nicht als Gutschrift oder Zahlung verwendet werden.', - 'currency_Bermudian_Dollar' => 'Bermuda-Dollar', - 'currency_Central_African_CFA_Franc' => 'Zentralafrikanischer CFA-Franc', - 'currency_Congolese_Franc' => 'Kongolesischer Franc', - 'currency_Djiboutian_Franc' => 'Dschibuti-Franc', - 'currency_Eritrean_Nakfa' => 'Eritreischer Nakfa', - 'currency_Falkland_Islands_Pound' => 'Falklandinseln Pfund', - 'currency_Guinean_Franc' => 'Guinea-Franc', - 'currency_Iraqi_Dinar' => 'Irakischer Dinar', - 'currency_Lesotho_Loti' => 'Lesothischer Loti', - 'currency_Mongolian_Tugrik' => 'Mongolischer Tugrik', - 'currency_Seychellois_Rupee' => 'Seychellen-Rupie', - 'currency_Solomon_Islands_Dollar' => 'Salomonen-Dollar', - 'currency_Somali_Shilling' => 'Somalischer Schilling', - 'currency_South_Sudanese_Pound' => 'Südsudanesisches Pfund', - 'currency_Sudanese_Pound' => 'Sudanesisches Pfund', - 'currency_Tajikistani_Somoni' => 'Tadschikischer Somoni', - 'currency_Turkmenistani_Manat' => 'Turkmenistan-Manat', - 'currency_Uzbekistani_Som' => 'Usbekischer Som', + 'currency_bermudian_dollar' => 'Bermuda-Dollar', + 'currency_central_african_cfa_franc' => 'Zentralafrikanischer CFA-Franc', + 'currency_congolese_franc' => 'Kongolesisches Franc', + 'currency_djiboutian_franc' => 'Dschibuti-Franc', + 'currency_eritrean_nakfa' => 'Eritreische Nakia', + 'currency_falkland_islands_pound' => 'Falklandinseln Pfund', + 'currency_guinean_franc' => 'Guinea-Franc', + 'currency_iraqi_dinar' => 'Irakischer Dinar', + 'currency_lesotho_loti' => 'Lesotho Loti', + 'currency_mongolian_tugrik' => 'Mongolian Tugrik', + 'currency_seychellois_rupee' => 'Seychellois Rupee', + 'currency_solomon_islands_dollar' => 'Solomon Islands Dollar', + 'currency_somali_shilling' => 'Somali Shilling', + 'currency_south_sudanese_pound' => 'South Sudanese Pound', + 'currency_sudanese_pound' => 'Sudanese Pound', + 'currency_tajikistani_somoni' => 'Tajikistani Somoni', + 'currency_turkmenistani_manat' => 'Turkmenistani Manat', + 'currency_uzbekistani_som' => 'Uzbekistani Som', 'payment_status_changed' => 'Bitte beachten Sie, dass der Status Ihrer Zahlung aktualisiert wurde. Wir empfehlen, die Seite zu aktualisieren, um die aktuellste Version anzuzeigen.', 'credit_status_changed' => 'Bitte beachten Sie, dass der Status Ihres Guthabens aktualisiert wurde. Wir empfehlen, die Seite zu aktualisieren, um die aktuellste Version anzuzeigen.', 'credit_updated' => 'Kredit- aktualisiert', @@ -5481,15 +5483,14 @@ Leistungsempfängers', 'download_ready' => 'Ihr Download ist jetzt bereit! [:message]', 'notification_quote_reminder1_sent_subject' => 'Erste Erinnerung für Angebot :invoice wurde an :client gesendet', 'custom_reminder_sent' => 'Benutzerdefinierte Erinnerung wurde an :client gesendet', - 'use_system_fonts' => 'Use System Fonts', - 'use_system_fonts_help' => 'Override the standard fonts with those from the web browser', - 'active_tasks' => 'Active Tasks', - 'enable_public_notifications_1' => 'Hallo! Sie können jetzt Echtzeitbenachrichtigungen von Invoice Ninja erhalten!', - 'enable_public_notifications_2' => 'Dies bedeutet, dass Sie mit den offiziellen Invoice Ninja-Servern verbunden werden. Wir möchten Sie daher nach Ihrer Präferenz fragen.', - 'enable_public_notifications_3' => 'Bitte beachten Sie, dass Sie dieses Modal nur einmal sehen. Wenn Sie Ihre Einstellungen ändern möchten, können Sie dies im Einstellungsmenü tun.', + 'use_system_fonts' => 'Verwende Systemschriftarten', + 'use_system_fonts_help' => 'Überschreibe die Standardschriftarten mit denen aus dem Webbrowser', + 'active_tasks' => 'Aktive Aufgaben', 'enable_notifications' => 'Aktiviere Benachrichtigungen', 'enable_public_notifications' => 'Aktiviere öffentliche Benachrichtigungen', - 'navigate' => 'Navigate', + 'enable_public_notifications_help' => 'Aktivieren Sie Echtzeitbenachrichtigungen von Invoice Ninja.', + 'navigate' => 'Navigiere', + 'calculate_taxes_warning' => 'Mit dieser Aktion werden Einzelpostensteuern aktiviert und Gesamtsteuern deaktiviert. Eventuell offene Rechnungen können mit den neuen Einstellungen neu berechnet werden!', ); return $lang; diff --git a/lang/fr_CA/texts.php b/lang/fr_CA/texts.php index 7c36fd80a1..c35f724ea1 100644 --- a/lang/fr_CA/texts.php +++ b/lang/fr_CA/texts.php @@ -5134,6 +5134,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'nordigen_handler_error_contents_institution_invalid' => 'L\'identifiant d\'institution fourni n\'est pas ou n\'est plus valide.', 'nordigen_handler_error_heading_ref_invalid' => 'Référence non valide', 'nordigen_handler_error_contents_ref_invalid' => 'GoCardless n\'a pas fourni une référence valide. Veuillez relancer le processus et contacter le support si le problème persiste.', + 'nordigen_handler_error_heading_eua_failure' => 'Échec du CLUF', + 'nordigen_handler_error_contents_eua_failure' => 'Erreur lors de la création du CLUF :', 'nordigen_handler_error_heading_not_found' => 'Réquisition non valide', 'nordigen_handler_error_contents_not_found' => 'GoCardless n\'a pas fourni une référence valide. Veuillez relancer le processus et contacter le support si le problème persiste.', 'nordigen_handler_error_heading_requisition_invalid_status' => 'Pas prêt', @@ -5364,7 +5366,7 @@ Développe automatiquement la section des notes dans le tableau de produits pour 'peppol_plan_warning' => 'Un plan Entreprise est requis pour utiliser la facturation électronique sur le réseau PEPPOL.', 'peppol_credits_info' => 'Des crédits électroniques (Ecredits) sont nécessaires pour envoyer et recevoir des factures électroniques. Ils sont facturés par document.', 'buy_credits' => 'Acheter des Ecredits', - 'peppol_successfully_configured' => 'PEPPOL a été configuré correctement', + 'peppol_successfully_configured' => 'PEPPOL a été configuré correctement', 'peppol_not_paid_message' => 'Un plan Entreprise est requis pour PEPPOL. Veuillez mettre à niveau votre plan.', 'peppol_country_not_supported' => 'Le réseau PEPPOL n\'est pas encore disponible pour ce pays.', 'peppol_disconnect' => 'Se déconnecter du réseau PEPPOL', @@ -5376,24 +5378,24 @@ Développe automatiquement la section des notes dans le tableau de produits pour 'hidden_taxes_warning' => 'Certaines taxes sont masquées en raison des paramètres de taxes actuels.', 'tax3' => 'Troisième taxe', 'negative_payment_warning' => 'Êtes-vous sûr de vouloir créer un paiement négatif? Cela ne peut pas être utilisé comme crédit ou paiement.', - 'currency_Bermudian_Dollar' => 'Dollar bermudien', - 'currency_Central_African_CFA_Franc' => 'Franc CFA de l\'Afrique centrale', - 'currency_Congolese_Franc' => 'Franc congolais', - 'currency_Djiboutian_Franc' => 'Franc Djiboutien', - 'currency_Eritrean_Nakfa' => 'Nakfa érythréen', - 'currency_Falkland_Islands_Pound' => 'Livre des Îles Malouines', - 'currency_Guinean_Franc' => 'Franc guinéen', - 'currency_Iraqi_Dinar' => 'Dinar irakien', - 'currency_Lesotho_Loti' => 'Loti lésothien', - 'currency_Mongolian_Tugrik' => 'Tugrik mongolien', - 'currency_Seychellois_Rupee' => 'Roupie seychelloise', - 'currency_Solomon_Islands_Dollar' => 'Dollar des Salomon', - 'currency_Somali_Shilling' => 'Shilling somalien', - 'currency_South_Sudanese_Pound' => 'Livre sud-soudanaise', - 'currency_Sudanese_Pound' => 'Livre soudanaise', - 'currency_Tajikistani_Somoni' => 'Somoni Tadjik', - 'currency_Turkmenistani_Manat' => 'Manat turkmène', - 'currency_Uzbekistani_Som' => 'Sum Ouzbek', + 'currency_bermudian_dollar' => 'Dollar bermudien', + 'currency_central_african_cfa_franc' => 'Franc CFA centrafricain', + 'currency_congolese_franc' => 'Franc congolais', + 'currency_djiboutian_franc' => 'Franc Djibouti', + 'currency_eritrean_nakfa' => 'Nakfa érythréen', + 'currency_falkland_islands_pound' => 'Livre des Îles Malouines', + 'currency_guinean_franc' => 'Franc guinéen', + 'currency_iraqi_dinar' => 'Dinar irakien', + 'currency_lesotho_loti' => 'Loti Lesotho', + 'currency_mongolian_tugrik' => 'Tugrik mongol', + 'currency_seychellois_rupee' => 'Roupie seychelloise', + 'currency_solomon_islands_dollar' => 'Dollar des Salomon', + 'currency_somali_shilling' => 'Shilling somalien', + 'currency_south_sudanese_pound' => 'Livre sud-soudanaise', + 'currency_sudanese_pound' => 'Livre soudanaise', + 'currency_tajikistani_somoni' => 'Somoni Tadjik', + 'currency_turkmenistani_manat' => 'Manat turkmène', + 'currency_uzbekistani_som' => 'Sum Ouzbek', 'payment_status_changed' => 'Veuillez noter que le statut de votre paiement a été mis à jour. Nous vous recommandons de rafraîchir la page pour voir la version la plus récente.', 'credit_status_changed' => 'Veuillez noter que le statut de votre crédit a été mis à jour. Nous vous recommandons de rafraîchir la page pour voir la version la plus récente.', 'credit_updated' => 'Crédit mis à jour', @@ -5478,12 +5480,11 @@ Développe automatiquement la section des notes dans le tableau de produits pour 'use_system_fonts' => 'Utiliser les polices de caractères du système', 'use_system_fonts_help' => 'Remplacer les polices standard par celles du navigateur web', 'active_tasks' => 'Tâches actives', - 'enable_public_notifications_1' => 'Bonjour ! Vous pouvez maintenant recevoir des notifications en temps réel d\'Invoice Ninja !', - 'enable_public_notifications_2' => 'Cela signifie que vous serez connecté aux serveurs officiels d\'Invoice Ninja, nous aimerions donc connaître votre préférence.', - 'enable_public_notifications_3' => 'Veuillez noter que vous ne verrez cette fenêtre modale qu\'une seule fois. Si vous souhaitez modifier vos paramètres, vous pouvez le faire dans le menu des paramètres.', 'enable_notifications' => 'Activer les notifications', 'enable_public_notifications' => 'Activer les notifications publiques', + 'enable_public_notifications_help' => 'Activer les notifications en temps réel de Invoice Ninja.', 'navigate' => 'Naviguer', + 'calculate_taxes_warning' => 'Cette action activera les taxes par ligne et désactivera les taxes totales. Toutes les factures ouvertes peuvent être recalculées avec les nouveaux paramètres !', ); return $lang; diff --git a/lang/vi/texts.php b/lang/vi/texts.php index bf1a37d77a..175a37b77a 100644 --- a/lang/vi/texts.php +++ b/lang/vi/texts.php @@ -738,7 +738,7 @@ $lang = array( 'activity_7' => ':contact đã xem hóa đơn :invoice gửi đến :client', 'activity_8' => ':user hóa đơn lưu trữ :invoice', 'activity_9' => ':user đã xóa hóa đơn :invoice', - 'activity_10' => ':user đã nhập thanh toán :payment bởi :payment _số tiền trên hóa đơn :invoice cho :client', + 'activity_10' => ':user đã nhập thanh toán :payment bởi :payment số tiền trên hóa đơn :invoice cho :client', 'activity_11' => ':user cập nhật thanh toán :payment', 'activity_12' => ':user thanh toán đã lưu trữ :payment', 'activity_13' => ':user đã xóa thanh toán :payment', @@ -2132,7 +2132,7 @@ $lang = array( 'purge_data_message' => 'Cảnh báo: Thao tác này sẽ xóa vĩnh viễn dữ liệu của bạn, không thể hoàn tác.', 'contact_phone' => 'Điện thoại liên hệ', 'contact_email' => 'Email liên hệ', - 'reply_to_email' => 'Trả lời Email', + 'reply_to_email' => 'Địa chỉ mail', 'reply_to_email_help' => 'Chỉ định địa chỉ trả lời cho email của khách hàng.', 'bcc_email_help' => 'Bao gồm riêng địa chỉ này vào email của khách hàng.', 'import_complete' => 'Quá trình nhập của bạn đã hoàn tất thành công.', @@ -2188,7 +2188,7 @@ $lang = array( 'host' => 'Chủ nhà', 'database' => 'Cơ sở dữ liệu', 'test_connection' => 'Kiểm tra kết nối', - 'from_name' => 'Từ Tên', + 'from_name' => 'Người gửi', 'from_address' => 'Từ Địa chỉ', 'port' => 'Cảng', 'encryption' => 'Mã hóa', @@ -2903,7 +2903,7 @@ $lang = array( 'local_part_available' => 'Name available', 'local_part_invalid' => 'Tên không hợp lệ (chỉ chữ số, không có khoảng trắng', 'local_part_help' => 'Tùy chỉnh phần địa phương của email hỗ trợ đến của bạn, ví dụ: YOUR_NAME@support.invoiceninja.com', - 'from_name_help' => 'Từ tên là người gửi có thể nhận dạng được hiển thị thay cho địa chỉ email, tức là Trung tâm hỗ trợ', + 'from_name_help' => 'Người gửi là người gửi có thể nhận dạng được hiển thị thay cho địa chỉ email, tức là Trung tâm hỗ trợ', 'local_part_placeholder' => 'YOUR_NAME', 'from_name_placeholder' => 'Trung tâm hỗ trợ', 'attachments' => 'Đính kèm', @@ -3981,7 +3981,7 @@ $lang = array( 'converted_paid_to_date' => 'Đã chuyển đổi thanh toán', 'converted_credit_balance' => 'Số dư tín dụng đã chuyển đổi', 'converted_total' => 'Tổng số đã chuyển đổi', - 'reply_to_name' => 'Trả lời tên', + 'reply_to_name' => 'Soạn thư', 'payment_status_-2' => 'Một phần chưa áp dụng', 'color_theme' => 'Chủ đề màu sắc', 'start_migration' => 'Bắt đầu di chuyển', @@ -4527,7 +4527,7 @@ $lang = array( 'connect_email' => 'Kết nối Email', 'disconnect_email' => 'Ngắt kết nối Email', 'use_web_app_to_connect_microsoft' => 'Vui lòng sử dụng ứng dụng web để kết nối với Microsoft', - 'email_provider' => 'Nhà cung cấp email', + 'email_provider' => 'Email', 'connect_microsoft' => 'Kết nối Microsoft', 'disconnect_microsoft' => 'Ngắt kết nối Microsoft', 'connected_microsoft' => 'Đã kết nối thành công Microsoft', @@ -5137,6 +5137,8 @@ $lang = array( 'nordigen_handler_error_contents_institution_invalid' => 'Mã số tổ chức được cung cấp không hợp lệ hoặc không còn hợp lệ.', 'nordigen_handler_error_heading_ref_invalid' => 'Tham chiếu không hợp lệ', 'nordigen_handler_error_contents_ref_invalid' => 'GoCardless không cung cấp tham chiếu hợp lệ. Vui lòng chạy lại luồng và liên hệ với bộ phận hỗ trợ nếu sự cố này vẫn tiếp diễn.', + 'nordigen_handler_error_heading_eua_failure' => 'Lỗi EUA', + 'nordigen_handler_error_contents_eua_failure' => 'Đã xảy ra lỗi trong quá trình tạo Thỏa thuận kết thúc Người dùng :', 'nordigen_handler_error_heading_not_found' => 'Yêu cầu không hợp lệ', 'nordigen_handler_error_contents_not_found' => 'GoCardless không cung cấp tham chiếu hợp lệ. Vui lòng chạy lại luồng và liên hệ với bộ phận hỗ trợ nếu sự cố này vẫn tiếp diễn.', 'nordigen_handler_error_heading_requisition_invalid_status' => 'Chưa sẵn sàng', @@ -5366,7 +5368,7 @@ $lang = array( 'peppol_plan_warning' => 'Cần có gói doanh nghiệp đến sử dụng hóa đơn điện tử qua mạng PEPPOL.', 'peppol_credits_info' => 'Cần có Ecredit đến gửi và nhận hóa đơn điện tử. Chúng được tính phí theo từng chứng từ.', 'buy_credits' => 'Mua tín dụng E', - 'peppol_successfully_configured' => 'PEPPOL đã được cấu hình thành công.', + 'peppol_successfully_configured' => 'PEPPOL đã được cấu hình thành công.', 'peppol_not_paid_message' => 'Cần có gói Enterprise cho PEPPOL. Vui lòng nâng cấp gói của bạn.', 'peppol_country_not_supported' => 'Mạng PEPPOL hiện chưa khả dụng ở quốc gia này.', 'peppol_disconnect' => 'Ngắt kết nối khỏi mạng PEPPOL', @@ -5378,24 +5380,24 @@ $lang = array( 'hidden_taxes_warning' => 'Một số loại thuế bị ẩn Quá hạn đến Cài đặt thuế hiện hành . :link', 'tax3' => 'Thuế thứ ba', 'negative_payment_warning' => 'Bạn có chắc chắn đến Tạo một Sự chi trả giá âm ? Điều này không thể được sử dụng như một khoản tín dụng hoặc Sự chi trả .', - 'currency_Bermudian_Dollar' => 'Đô la Bermuda', - 'currency_Central_African_CFA_Franc' => 'Franc CFA Trung Phi', - 'currency_Congolese_Franc' => 'Franc Congo', - 'currency_Djiboutian_Franc' => 'Franc Djibouti', - 'currency_Eritrean_Nakfa' => 'Nakfa Eritrea', - 'currency_Falkland_Islands_Pound' => 'Bảng Anh Quần đảo Falkland', - 'currency_Guinean_Franc' => 'Franc Guinea', - 'currency_Iraqi_Dinar' => 'Dinar Iraq', - 'currency_Lesotho_Loti' => 'Loti Lesotho', - 'currency_Mongolian_Tugrik' => 'Tugrik Mông Cổ', - 'currency_Seychellois_Rupee' => 'Rupee Seychelles', - 'currency_Solomon_Islands_Dollar' => 'Đô la Quần đảo Solomon', - 'currency_Somali_Shilling' => 'Shilling Somali', - 'currency_South_Sudanese_Pound' => 'Bảng Nam Sudan', - 'currency_Sudanese_Pound' => 'Bảng Sudan', - 'currency_Tajikistani_Somoni' => 'Somoni Tajikistan', - 'currency_Turkmenistani_Manat' => 'Đồng Manat Turkmenistan', - 'currency_Uzbekistani_Som' => 'Som Uzbekistan', + 'currency_bermudian_dollar' => 'Đô la Bermuda', + 'currency_central_african_cfa_franc' => 'Franc CFA Trung Phi', + 'currency_congolese_franc' => 'Franc Congo', + 'currency_djiboutian_franc' => 'Franc Djibouti', + 'currency_eritrean_nakfa' => 'Nakfa Eritrea', + 'currency_falkland_islands_pound' => 'Bảng Anh Quần đảo Falkland', + 'currency_guinean_franc' => 'Franc Guinea', + 'currency_iraqi_dinar' => 'Dinar Iraq', + 'currency_lesotho_loti' => 'Loti Lesotho', + 'currency_mongolian_tugrik' => 'Tugrik Mông Cổ', + 'currency_seychellois_rupee' => 'Rupee Seychelles', + 'currency_solomon_islands_dollar' => 'Đô la Quần đảo Solomon', + 'currency_somali_shilling' => 'Shilling Somali', + 'currency_south_sudanese_pound' => 'Bảng Nam Sudan', + 'currency_sudanese_pound' => 'Bảng Sudan', + 'currency_tajikistani_somoni' => 'Somoni Tajikistan', + 'currency_turkmenistani_manat' => 'Đồng Manat Turkmenistan', + 'currency_uzbekistani_som' => 'Som Uzbekistan', 'payment_status_changed' => 'Xin Ghi chú rằng trạng thái Sự chi trả của bạn đã được đã cập nhật . Chúng tôi khuyên bạn nên làm mới trang đến Xem phiên bản mới nhất.', 'credit_status_changed' => 'Vui lòng Ghi chú rằng trạng thái tín dụng của bạn đã được đã cập nhật . Chúng tôi khuyên bạn nên làm mới trang đến Xem phiên bản mới nhất.', 'credit_updated' => 'đã cập nhật tín dụng', @@ -5480,12 +5482,11 @@ $lang = array( 'use_system_fonts' => 'Sử dụng Phông chữ Hệ thống', 'use_system_fonts_help' => 'Ghi đè phông chữ chuẩn bằng phông chữ từ trình duyệt web', 'active_tasks' => 'Nhiệm vụ đang hoạt động', - 'enable_public_notifications_1' => 'Xin chào! Bây giờ bạn có thể nhận thông báo theo thời gian thực từ Hóa đơn Ninja!', - 'enable_public_notifications_2' => 'Điều này có nghĩa là bạn sẽ được kết nối đến máy chủ Hóa đơn Ninja chính thức, vì vậy chúng tôi muốn hỏi ý kiến đến về sở thích của bạn.', - 'enable_public_notifications_3' => 'Vui lòng Ghi chú , bạn sẽ chỉ nhìn thấy phương thức này một lần. Nếu bạn muốn đến đổi Cài đặt của mình, bạn có thể làm như vậy trong menu Cài đặt .', 'enable_notifications' => 'Bật thông báo', 'enable_public_notifications' => 'Bật thông báo công khai', + 'enable_public_notifications_help' => 'Bật thông báo thời gian thực từ Invoice Ninja.', 'navigate' => 'Điều hướng', + 'calculate_taxes_warning' => 'Hành động này sẽ kích hoạt thuế mục hàng và vô hiệu hóa thuế Tổng cộng . Mọi Hóa đơn đang mở có thể được tính toán lại bằng Cài đặt mới !', ); return $lang; diff --git a/resources/views/pdf-designs/bold.html b/resources/views/pdf-designs/bold.html index 8fe4d7678f..e83bc9d3c9 100644 --- a/resources/views/pdf-designs/bold.html +++ b/resources/views/pdf-designs/bold.html @@ -58,7 +58,10 @@ #header, #header-spacer { height: 160px; - padding: 2rem; + padding-top: 2rem; + padding-bottom: 2rem; + padding-left: 1rem; + padding-right: 1rem; margin-bottom: 1rem; } .company-logo { @@ -129,7 +132,7 @@ min-width: 100%; table-layout: fixed; overflow-wrap: break-word; - margin-top: 0rem; + margin-top: 0.5rem; margin-bottom: 0px; } @@ -181,8 +184,8 @@ display: grid; grid-template-columns: 2fr 1fr; padding-top: .5rem; - padding-left: 3rem; - padding-right: 3rem; + padding-left: 1rem; + padding-right: 1rem; gap: 80px; } @@ -248,7 +251,7 @@ #footer, #footer-spacer { height: 160px; - padding: 1rem 3rem; + padding: 1rem 1rem; margin-top: 1rem; } @@ -257,8 +260,8 @@ } [data-ref="footer_content"]{ - padding-right: 2rem; - margin-right: 2rem; + padding-right: 1rem; + margin-right: 1rem; } table { @@ -309,7 +312,10 @@ width: 10%; } - [data-ref='product_table-product.unit_cost-th'], + [data-ref='product_table-product.unit_cost-th']{ + width: 10%; + } + [data-ref='product_table-product.quantity-th'], [data-ref='product_table-product.product1-th'], [data-ref='product_table-product.product2-th'], @@ -323,9 +329,12 @@ } [data-ref='product_table-product.line_total-th'], - [data-ref='product_table-product.line_total-td'] { - width: 8%; - text-align: right; + [data-ref='product_table-product.line_total-td'], + [data-ref='task_table-task.line_total-th'], + [data-ref='task_table-task.line_total-td'] { + width: 10%; + text-align: right !important; + padding-right: 1rem !important; } [data-ref='task_table-task.description-th'] { @@ -352,11 +361,6 @@ width: 6%; } - [data-ref='task_table-task.line_total-th'], - [data-ref='task_table-task.line_total-td'] { - width: 8%; - text-align: right !important; - } .left-radius { padding-left: 1rem; diff --git a/resources/views/pdf-designs/business.html b/resources/views/pdf-designs/business.html index 9015c381ee..0bfc39c494 100644 --- a/resources/views/pdf-designs/business.html +++ b/resources/views/pdf-designs/business.html @@ -254,18 +254,18 @@ [data-ref="totals_table-outstanding-label"]{ background-color: var(--secondary-color); color: white; - padding-top: 7px; - padding-bottom: 7px; - padding-right: 7px; + font-size:120%; + font-weight:bold; + padding: 1rem; border-top-left-radius: 7px; border-bottom-left-radius: 7px; } [data-ref="totals_table-outstanding"] { background-color: var(--secondary-color); color: white; - padding-top: 7px; - padding-bottom: 7px; - padding-right: 7px; + font-size:120%; + font-weight:bold; + padding: 1rem; border-top-right-radius: 7px; border-bottom-right-radius: 7px; } diff --git a/resources/views/pdf-designs/clean.html b/resources/views/pdf-designs/clean.html index 989333266e..f819f4ffd8 100644 --- a/resources/views/pdf-designs/clean.html +++ b/resources/views/pdf-designs/clean.html @@ -267,7 +267,7 @@ [data-ref='product_table-product.item-th'], [data-ref='product_table-product.unit_cost-th'], [data-ref='product_table-product.quantity-th'] { - width: 10%; + width: 12%; } [data-ref='product_table-product.tax1-th'] { @@ -289,7 +289,7 @@ [data-ref='task_table-task.discount-th'], [data-ref='task_table-task.cost-th'], [data-ref='task_table-task.quantity-th'] { - width: 10%; + width: 12%; } [data-ref='task_table-task.tax1-th'] { diff --git a/resources/views/pdf-designs/creative.html b/resources/views/pdf-designs/creative.html index 45209e744e..6ff4a6afd3 100644 --- a/resources/views/pdf-designs/creative.html +++ b/resources/views/pdf-designs/creative.html @@ -145,6 +145,53 @@ color: grey; } + + [data-ref='product_table-product.description-th'], + [data-ref='product_table-product.description-td'] { + min-width: 150px !important; + overflow-wrap: break-word; + } + + [data-ref='product_table-product.item-td']{ + color: var(--primary-color); + } + + [data-ref='product_table-product.item-th'], + [data-ref='product_table-product.unit_cost-th'], + [data-ref='product_table-product.quantity-th'] { + width: 12%; + } + + [data-ref='product_table-product.tax1-th'] { + width: 6%; + } + + [data-ref='product_table-product.line_total-th'] { + width: 10%; + } + + [data-ref='task_table-task.description-th'], + [data-ref='task_table-task.description-td'] { + min-width: 100px !important; + overflow-wrap: break-word; + } + + [data-ref='task_table-task.hours-th'], + [data-ref='task_table-task.service-th'], + [data-ref='task_table-task.discount-th'], + [data-ref='task_table-task.cost-th'], + [data-ref='task_table-task.quantity-th'] { + width: 12%; + } + + [data-ref='task_table-task.tax1-th'] { + width: 6%; + } + + [data-ref='task_table-task.line_total-th'] { + width: 10%; + } + [data-ref="table"] > thead { text-align: left; } diff --git a/resources/views/pdf-designs/hipster.html b/resources/views/pdf-designs/hipster.html index f9234c8e26..b5e051a49f 100644 --- a/resources/views/pdf-designs/hipster.html +++ b/resources/views/pdf-designs/hipster.html @@ -242,7 +242,7 @@ #table-totals > * > :last-child { text-align: right; - padding-right: 1rem; + padding-right: 0rem; } #footer { @@ -255,7 +255,14 @@ margin-bottom: 0; } - [data-ref='product_table-product.description-td'] { + [data-ref='task_table-task.service-th'], + [data-ref='product_table-product.item-th'] { + padding-left:1rem !important; + width:14%; + } + + [data-ref='product_table-product.description-td'], + [data-ref="task_table-task.description-td"] { min-width:100px; overflow-wrap: break-word; } @@ -266,17 +273,21 @@ } [data-ref="product_table-product.unit_cost-td"], - [data-ref="product_table-product.unit_cost-th"]{ - text-align: center; + [data-ref="product_table-product.unit_cost-th"], + [data-ref='task_table-task.cost-th'], + [data-ref='task_table-task.cost-td']{ + text-align: center !important; width: 10%; - padding-left:0 !important; + padding-left:0 !important; padding-right:0 !important; } [data-ref="product_table-product.quantity-th"], - [data-ref="product_table-product.quantity-td"]{ + [data-ref="product_table-product.quantity-td"], + [data-ref='task_table-task.hours-th'], + [data-ref='task_table-task.hours-td'] { width: 10%; - text-align: center; + text-align: center !important; padding-left:0 !important; padding-right:0 !important; } @@ -295,21 +306,8 @@ width: 13%; } - [data-ref='task_table-task.hours-th'], - [data-ref='task_table-task.hours-td'] { - text-align: center; - padding-left:0 !important; - padding-right:0 !important; - width: 6%; - } - - [data-ref='task_table-task.cost-th'], - [data-ref='task_table-task.cost-td'] { - text-align: center; - padding-left:0 !important; - padding-right:0 !important; - width: 8%; - } + + [data-ref="task_table-task.line_total-th"], [data-ref="task_table-task.line_total-td"] { @@ -317,7 +315,16 @@ width: 13%; } - [data-ref="totals_table-outstanding"] { color: var(--primary-color); } + [data-ref="totals_table-outstanding-label"] { + font-weight:bold; + font-size:120%; + } + + [data-ref="totals_table-outstanding"] { + color: var(--primary-color); + font-weight:bold; + font-size:120%; + } [data-ref="statement-totals"] { margin-top: 1rem; @@ -344,8 +351,6 @@ bottom: 0; } - - .stamp { transform: rotate(12deg); color: #555; @@ -487,18 +492,18 @@ > -
-
-
-
-
-
-
-
-
-
-
-
$status_logo
+
+
+
+
+
+
+
+
+
+
+
+
$status_logo
diff --git a/resources/views/pdf-designs/modern.html b/resources/views/pdf-designs/modern.html index 0d8dad88cd..56306ded28 100644 --- a/resources/views/pdf-designs/modern.html +++ b/resources/views/pdf-designs/modern.html @@ -173,31 +173,36 @@ margin-top: 0rem; } - .footer-content { + .footer-content { display: flex; - gap: 10px; - width: 100%; - /* grid-template-columns: 1fr 1fr 1fr; */ + width: calc(100% - 2rem); + margin: 0 1rem; color: #fff4e9; - max-height: 140px; justify-content: space-between; - margin-top: 0.5rem; - margin-left: 0.5rem; - } + align-items: flex-start; + } - .footer-company-details-address-wrapper { - display: flex; - gap: 0px; - margin-right: 60px; - } + /* Main footer text area */ + .footer-content > div:first-child { + width: 50%; + margin-right: 2rem; + } - #company-address, - #company-details { + /* Company details/address wrapper */ + .footer-company-details-address-wrapper { + width: 50%; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; + margin-top: 1rem; + } + + #company-details, + #company-address { display: flex; flex-direction: column; - margin-top: 0.5rem; - margin-bottom: 0rem; - } + gap: 0.5rem; + } #company-address > *, #company-details > * { @@ -302,25 +307,7 @@ [data-ref='product_table-product.product1-th'], [data-ref='product_table-product.product2-th'], [data-ref='product_table-product.product3-th'], - [data-ref='product_table-product.product4-th'] { - width: 8%; - } - - [data-ref='product_table-product.tax1-th'] { - width: 6%; - } - - [data-ref='product_table-product.line_total-th'], - [data-ref='product_table-product.line_total-td'] { - width: 8%; - text-align: right; - } - - [data-ref='task_table-task.description-th'] { - overflow-wrap: break-word; - min-width: 100px !important; - } - + [data-ref='product_table-product.product4-th'], [data-ref='task_table-task.hours-th'], [data-ref='task_table-task.discount-th'], [data-ref='task_table-task.cost-th'], @@ -329,7 +316,24 @@ [data-ref='task_table-task.task2-th'], [data-ref='task_table-task.task3-th'], [data-ref='task_table-task.task4-th'] { - width: 8%; + width: 10%; + } + + [data-ref='product_table-product.tax1-th'] { + width: 6%; + } + + [data-ref='product_table-product.line_total-th'], + [data-ref='product_table-product.line_total-td'], + [data-ref='task_table-task.line_total-th'], + [data-ref='task_table-task.line_total-td'] { + width: 12%; + text-align: right; + } + + [data-ref='task_table-task.description-th'] { + overflow-wrap: break-word; + min-width: 100px !important; } [data-ref='task_table-task.service-th']{ @@ -340,13 +344,6 @@ width: 6%; } - [data-ref='task_table-task.line_total-th'], - [data-ref='task_table-task.line_total-td'] { - width: 8%; - text-align: right !important; - } - - .stamp { transform: rotate(12deg); color: #555; @@ -483,10 +480,8 @@ $entity_images