diff --git a/phpstan.neon b/phpstan.neon index c06a4aef..929e7167 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -4830,16 +4830,6 @@ parameters: count: 1 path: src/Form/Type/EntityMetaDefinitionType.php - - - message: "#^Parameter \\#1 \\$string of function strtolower expects string, string\\|null given\\.$#" - count: 1 - path: src/Form/Type/InvoiceRendererType.php - - - - message: "#^Parameter \\#1 \\$string of function ucfirst expects string, string\\|null given\\.$#" - count: 1 - path: src/Form/Type/InvoiceRendererType.php - - message: "#^PHPDoc tag @var for variable \\$collection contains generic class Doctrine\\\\Common\\\\Collections\\\\ArrayCollection but does not specify its types\\: TKey, T$#" count: 1 diff --git a/src/Constants.php b/src/Constants.php index cd03da8d..4b56ffa4 100644 --- a/src/Constants.php +++ b/src/Constants.php @@ -17,11 +17,11 @@ class Constants /** * The current release version */ - public const VERSION = '2.0.5'; + public const VERSION = '2.0.6'; /** * The current release: major * 10000 + minor * 100 + patch */ - public const VERSION_ID = 20005; + public const VERSION_ID = 20006; /** * The software name */ diff --git a/src/Controller/InvoiceController.php b/src/Controller/InvoiceController.php index 82767014..1eb1b20f 100644 --- a/src/Controller/InvoiceController.php +++ b/src/Controller/InvoiceController.php @@ -109,7 +109,7 @@ final class InvoiceController extends AbstractController $total += \count($model->getCalculator()->getEntries()); $values = [ - 'invoiceDate' => $query->getInvoiceDate(), + 'invoiceDate' => null, 'template' => $customerTpl ]; @@ -364,10 +364,10 @@ final class InvoiceController extends AbstractController $table->addColumn('mf_' . $metaColumn->getName(), ['title' => $metaColumn->getLabel(), 'class' => 'd-none', 'orderBy' => false]); } - $table->addColumn('invoice_number', ['class' => 'd-none d-md-table-cell w-min', 'title' => 'invoice.number', 'orderBy' => false]); + $table->addColumn('invoice_number', ['class' => 'd-none d-md-table-cell w-min', 'title' => 'invoice.number', 'orderBy' => 'invoice.number']); $table->addColumn('due_date', ['class' => 'd-none w-min', 'title' => 'invoice.due_days', 'orderBy' => false]); $table->addColumn('payment_date', ['class' => 'd-none w-min', 'title' => 'invoice.payment_date', 'orderBy' => false]); - $table->addColumn('status', ['class' => 'd-none d-sm-table-cell w-min', 'orderBy' => false]); + $table->addColumn('status', ['class' => 'd-none d-sm-table-cell w-min', 'orderBy' => 'status']); $table->addColumn('subtotal', ['class' => 'd-none text-end w-min', 'title' => 'invoice.subtotal', 'orderBy' => false]); $table->addColumn('tax', ['class' => 'd-none text-end w-min', 'title' => 'invoice.tax']); $table->addColumn('total_rate', ['class' => 'd-none d-md-table-cell text-end w-min']); diff --git a/src/Form/Type/InvoiceRendererType.php b/src/Form/Type/InvoiceRendererType.php index 762c24cb..c3bbed18 100644 --- a/src/Form/Type/InvoiceRendererType.php +++ b/src/Form/Type/InvoiceRendererType.php @@ -61,13 +61,16 @@ final class InvoiceRendererType extends AbstractType $type = array_pop($parts); + if (!\is_string($type)) { + return 'programmatic'; + } + return match (strtolower($type)) { 'json', 'txt', 'xml' => 'programmatic', - 'pdf' => 'PDF', 'docx', 'doc' => 'Word', 'xls', 'xlsx' => 'Excel', 'ods' => 'LibreOffice', - default => ucfirst($type), + default => strtoupper($type), }; } diff --git a/src/Invoice/Renderer/AbstractSpreadsheetRenderer.php b/src/Invoice/Renderer/AbstractSpreadsheetRenderer.php index ffe1c147..10143b18 100644 --- a/src/Invoice/Renderer/AbstractSpreadsheetRenderer.php +++ b/src/Invoice/Renderer/AbstractSpreadsheetRenderer.php @@ -101,7 +101,7 @@ abstract class AbstractSpreadsheetRenderer extends AbstractRenderer if (\is_string($content) && str_starts_with($content, '=')) { $contentLooksLikeFormula = true; } - $value = str_replace($searchKey, $content, $value); + $value = str_replace($searchKey, $content ?? '', $value); } if ($contentLooksLikeFormula && $firstReplacerPos === 0) { diff --git a/src/Repository/InvoiceRepository.php b/src/Repository/InvoiceRepository.php index b6565432..a193e218 100644 --- a/src/Repository/InvoiceRepository.php +++ b/src/Repository/InvoiceRepository.php @@ -204,7 +204,7 @@ class InvoiceRepository extends EntityRepository case 'date': $orderBy = 'i.createdAt'; break; - case 'number': + case 'invoice.number': $orderBy = 'i.invoiceNumber'; break; case 'payed': @@ -213,9 +213,11 @@ class InvoiceRepository extends EntityRepository case 'total_rate': $orderBy = 'i.total'; break; - case 'tax': case 'status': - $orderBy = 'i.' . $orderBy; + $orderBy = 'i.status'; + break; + case 'tax': + $orderBy = 'i.tax'; break; } diff --git a/src/Repository/Query/InvoiceArchiveQuery.php b/src/Repository/Query/InvoiceArchiveQuery.php index ea0ad191..79caf0be 100644 --- a/src/Repository/Query/InvoiceArchiveQuery.php +++ b/src/Repository/Query/InvoiceArchiveQuery.php @@ -21,9 +21,9 @@ class InvoiceArchiveQuery extends BaseQuery use DateRangeTrait; public const INVOICE_ARCHIVE_ORDER_ALLOWED = [ - 'date', 'total_rate', + 'date', 'invoice.number', 'status', 'total_rate' // TODO other fields have a problem with translation - // 'number', 'tax', 'payed', 'status' + // , 'tax', 'payed' ]; /** diff --git a/templates/invoice/renderer/timesheet.html.twig b/templates/invoice/renderer/timesheet.html.twig index 14b2ff0a..66d0d716 100644 --- a/templates/invoice/renderer/timesheet.html.twig +++ b/templates/invoice/renderer/timesheet.html.twig @@ -1,130 +1,142 @@ -{% import "macros/widgets.html.twig" as widgets %} -{% extends 'invoice/layout.html.twig' %} - -{% block invoice %} - {% set isDecimal = true %} - {% set project = model.query.project %} - {% set activity = model.query.activity %} -
-
- -
-
- -
-
- - - - - - - - - - - - - - {% if project is not null %} - - - - - {% endif %} - {% if activity is not null %} - - - - - {% endif %} -
{{ 'invoice.from'|trans }} - {% if model.query.user is not empty %} - {{ widgets.username(model.query.user) }} - {% else %} - {{ model.template.company }} - {% endif %} -
{{ 'date'|trans }} - {% if model.query.begin|date('m') != model.query.end|date('m') or model.query.begin|date('Y') != model.query.end|date('Y') %} - {{ model.query.begin|date_short }} - {{ model.query.end|date_short }} - {% else %} - {{ model.query.end|month_name }} {{ model.query.end|date('Y') }} - {% endif %} -
{{ 'customer'|trans }} - {% if model.customer.number is not empty %}[{{ model.customer.number }}]{% endif %} - {{ model.customer.name }}{% if model.customer.contact is not empty %} / {{ model.customer.contact }}{% endif %} -
{{ 'project'|trans }} - {{ project.name }} - {% if project.orderNumber is not empty %} - ({{ 'orderNumber'|trans }}: {{ project.orderNumber }}) - {% endif %} -
{{ 'activity'|trans }} - {{ activity.name }} -
-
-
- -
-
- - - - - {% if model.query.user is empty %} - - {% endif %} - - - - - - {% for entry in model.calculator.entries %} - - - {% if model.query.user is empty %} - - {% endif %} - - - - {% endfor %} - - - - - {% if model.query.user is empty %} - - {% endif %} - - - - -
{{ 'date'|trans }}{{ 'user'|trans }}{{ 'activity'|trans }}{{ 'hours'|trans }}
{{ entry.begin|date_short }}{{ widgets.username(entry.user) }} - {% if entry.description is not empty %} - {{ entry.description|nl2br }} - {% else %} - {% if entry.activity is not null %}{{ entry.activity.name }} / {% endif %}{{ entry.project.name }} - {% endif %} - {{ entry.duration|duration(isDecimal) }}
{{ 'invoice.total_working_time'|trans }}{{ model.calculator.timeWorked|duration(isDecimal) }}
-
-
- -
-
- {% if model.template.paymentTerms is not empty %} -

{{ 'payment_terms'|trans }}

- -

- {{ model.template.paymentTerms|trim|nl2br }} -

- {% endif %} - -
-

{{ 'invoice.signature_user'|trans }}

-

{{ 'invoice.signature_customer'|trans }}

+ +{% set fallback = app.request is not null ? app.request.locale : 'en' %} +{% set language = model.template.language|default(fallback) %} +{% set isDecimal = true %} +{% set project = model.query.project %} +{% set activity = model.query.activity %} + + + + + + {{ model.invoiceNumber }}-{{ model.customer.company|default(model.customer.name)|u.snake }} + + + +
+
+
+
+ +
-
+
+
+ + + + + + + + + + + + + + {% if project is not null %} + + + + + {% endif %} + {% if activity is not null %} + + + + + {% endif %} +
{{ 'invoice.from'|trans }} + {% if model.query.user is not empty %} + {{ model.query.user.displayName }} + {% else %} + {{ model.template.company }} + {% endif %} +
{{ 'date'|trans }} + {% if model.query.begin|date('m') != model.query.end|date('m') or model.query.begin|date('Y') != model.query.end|date('Y') %} + {{ model.query.begin|date_short }} - {{ model.query.end|date_short }} + {% else %} + {{ model.query.end|month_name }} {{ model.query.end|date('Y') }} + {% endif %} +
{{ 'customer'|trans }} + {% if model.customer.number is not empty %}[{{ model.customer.number }}]{% endif %} + {{ model.customer.name }}{% if model.customer.contact is not empty %} / {{ model.customer.contact }}{% endif %} +
{{ 'project'|trans }} + {{ project.name }} + {% if project.orderNumber is not empty %} + ({{ 'orderNumber'|trans }}: {{ project.orderNumber }}) + {% endif %} +
{{ 'activity'|trans }} + {{ activity.name }} +
+
+
+
+
+ + + + + {% if model.query.user is empty %} + + {% endif %} + + + + + + {% for entry in model.calculator.entries %} + + + {% if model.query.user is empty %} + + {% endif %} + + + + {% endfor %} + + + + + {% if model.query.user is empty %} + + {% endif %} + + + + +
{{ 'date'|trans }}{{ 'user'|trans }}{{ 'activity'|trans }}{{ 'hours'|trans }}
{{ entry.begin|date_short }}{{ entry.user.displayName }} + {% if entry.description is not empty %} + {{ entry.description|nl2br }} + {% else %} + {% if entry.activity is not null %}{{ entry.activity.name }} / {% endif %}{{ entry.project.name }} + {% endif %} + {{ entry.duration|duration(isDecimal) }}
{{ 'invoice.total_working_time'|trans }}{{ model.calculator.timeWorked|duration(isDecimal) }}
+
+
+
+
+ {% if model.template.paymentTerms is not empty %} +

{{ 'payment_terms'|trans }}

+ +

+ {{ model.template.paymentTerms|trim|nl2br }} +

+ {% endif %} + +
+

{{ 'invoice.signature_user'|trans }}

+

{{ 'invoice.signature_customer'|trans }}

+
+
+
+
-{% endblock %} \ No newline at end of file + + diff --git a/templates/macros/widgets.html.twig b/templates/macros/widgets.html.twig index 35095d67..0fbabbc2 100644 --- a/templates/macros/widgets.html.twig +++ b/templates/macros/widgets.html.twig @@ -284,33 +284,33 @@ {% endmacro %} {% macro form_type_value(type, value, entity) %} - {% if '\\ColorPickerType' in type or '\\ColorChoiceType' in type %} + {% if 'ColorPickerType' in type or 'ColorChoiceType' in type %} {% if value is not empty %} {% endif %} - {% elseif '\\DurationType' in type %} + {% elseif 'DurationType' in type %} {{ value|duration }} - {% elseif '\\YesNoType' in type or '\\CheckBoxType' in type %} + {% elseif 'YesNoType' in type or 'CheckBoxType' in type %} {{ _self.label_boolean(value) }} - {% elseif '\\DatePickerType' in type %} + {% elseif 'DatePickerType' in type %} {{ value|date_short }} - {% elseif '\\DateTimePickerType' in type %} + {% elseif 'DateTimePickerType' in type %} {{ value|date_time }} - {% elseif '\\CountryType' in type %} + {% elseif 'CountryType' in type %} {{ value|country_name }} - {% elseif '\\CurrencyType' in type %} + {% elseif 'CurrencyType' in type %} {{ value|currency_name }} - {% elseif '\\LanguageType' in type %} + {% elseif 'LanguageType' in type %} {{ value|locale_name }} - {% elseif '\\TagsType' in type %} + {% elseif 'TagsType' in type %} {% for tag in value|split(',') %} {% if tag is not empty %} {{ _self.badge(tag, null|colorize(tag)) }} {% endif %} {% endfor %} - {% elseif '\\MoneyType' in type %} + {% elseif 'MoneyType' in type %} {% set classname = class_name(entity) %} {% if entity is null %} {{ value }} @@ -325,11 +325,11 @@ {% else %} {{ value }} {% endif %} - {% elseif '\\TextareaType' in type %} + {% elseif 'TextareaType' in type %} {{ value|nl2br }} - {% elseif '\\EmailType' in type %} + {% elseif 'EmailType' in type %} {{ value }} - {% elseif '\\UrlType' in type %} + {% elseif 'UrlType' in type %} {{ value }} {% else %} {{ value }} diff --git a/templates/timesheet/export.html.twig b/templates/timesheet/export.html.twig index fce53104..4cc3853b 100644 --- a/templates/timesheet/export.html.twig +++ b/templates/timesheet/export.html.twig @@ -1,99 +1,110 @@ -{% extends 'invoice/layout.html.twig' %} -{% import "macros/widgets.html.twig" as widgets %} + {% import "macros/datatables.html.twig" as tables %} +{% set language = app.request is not null ? app.request.locale : 'en' %} +{% set decimal = false %} +{% set showUserColumn = true %} +{% if query.user %} + {% set showUserColumn = false %} +{% endif %} + + + + + + {{ 'export'|trans }} + + + +
+
-{% block title %}{{ 'export'|trans }}{% endblock %} -{% block invoice %} - {% set decimal = decimal|default(false) %} - {% set showUserColumn = true %} - {% if query.user %} - {% set showUserColumn = false %} - {% endif %} - -
-
- -
-
- -
-
- - - - - {% if showUserColumn %} - +
+
+
- {% for field in timesheetMetaFields %} - - {% endfor %} - - - - - {% set timeWorked = 0 %} - {% for entry in entries %} - {% set timeWorked = timeWorked + entry.duration %} + {% if query.begin is not empty %} + {{ query.begin|date_short }} + {% else %} + {% set last = entries|last %} + {{ last.begin|date_short }} + {% endif %} + – + {% if query.end is not empty %} + {{ query.end|date_short }} + {% else %} + {% set first = entries|first %} + {{ first.end|date_short }} + {% endif %} + + + + +
+
+
{{ 'date'|trans }}{{ 'username'|trans }}{{ 'description'|trans }}{{ field.label|trans }}{{ 'hours'|trans }}
+ - + {% if showUserColumn %} - + {% endif %} - + {% for field in timesheetMetaFields %} + + {% endfor %} + + + + + {% set timeWorked = 0 %} + {% for entry in entries %} + {% set timeWorked = timeWorked + entry.duration %} + + + {% if showUserColumn %} + {% endif %} - + - {% for field in timesheetMetaFields %} - - {% endfor %} - - - {% endfor %} - - - - - {% if showUserColumn %} - - {% endif %} - {% for field in timesheetMetaFields %} - + + {% for field in timesheetMetaFields %} + + {% endfor %} + + {% endfor %} - - - - -
{{ entry.begin|date_short }}{{ 'date'|trans }}{{ widgets.username(entry.user) }}{{ 'username'|trans }} - {% if entry.description is not empty %} -
- {{ entry.description|desc2html }} -
+
{{ 'description'|trans }}{{ field.label|trans }}{{ 'hours'|trans }}
{{ entry.begin|date_short }}{{ entry.user.displayName }} + {% if entry.description is not empty %} +
+ {{ entry.description|desc2html }} +
+ {% endif %} + {% if entry.activity is not null %}{{ 'activity'|trans }}: {{ entry.activity.name }} |{% endif %} - {{ 'project'|trans }}: {{ entry.project.name }} | + {{ 'project'|trans }}: {{ entry.project.name }} | {{ 'customer'|trans }}: {{ entry.project.customer.name }} -
{{ tables.datatable_meta_column(entry, field) }}{{ entry.duration|duration(decimal) }}
{{ tables.datatable_meta_column(entry, field) }}{{ entry.duration|duration(decimal) }}
{{ 'invoice.total_working_time'|trans }}{{ timeWorked|duration(decimal) }}
+ + + + + {% if showUserColumn %} + + {% endif %} + {% for field in timesheetMetaFields %} + + {% endfor %} + {{ 'invoice.total_working_time'|trans }} + {{ timeWorked|duration(decimal) }} + + + +
-
-{% endblock %} - -{% block print_button %}{% endblock %} \ No newline at end of file + +
+ + diff --git a/tests/Invoice/templates/default.pdf.twig b/tests/Invoice/templates/default.pdf.twig index 93b8b4c3..99fffdfe 100644 --- a/tests/Invoice/templates/default.pdf.twig +++ b/tests/Invoice/templates/default.pdf.twig @@ -1,147 +1,157 @@ -{% extends 'invoice/layout.html.twig' %} -{% set language = model.template.language|default(app.request.locale) %} -{% set isDecimal = model.template.decimalDuration|default(false) %} + +{% set fallback = app.request is not null ? app.request.locale : 'en' %} +{% set language = model.template.language|default(fallback) %} {% set currency = model.currency %} - -{% block invoice %} -
-
- -
-
- -
-
- {{ 'invoice.from'|trans({}, 'messages', language) }} -
- {{ model.template.company }}
- {{ model.template.address|trim|nl2br }} - {% if model.template.vatId is not empty %} -
- {{ 'vat_id'|trans({}, 'messages', language) }}: - {{ model.template.vatId }} - {% endif %} -
-
-
-
- {{ 'invoice.to'|trans({}, 'messages', language) }} -
- {{ model.customer.company|default(model.customer.name) }}
- {{ model.customer.address|nl2br }} - {% if model.customer.vatId is not empty %} -
- {{ 'vat_id'|trans({}, 'messages', language) }}: {{ model.customer.vatId }} - {% endif %} - {% if model.customer.number is not empty %} -
- {{ 'number'|trans({}, 'messages', language) }}: {{ model.customer.number }} - {% endif %} - {% if model.query.project is not empty and model.query.project.orderNumber is not empty %} -
- {{ 'orderNumber'|trans({}, 'messages', language) }}: {{ model.query.project.orderNumber }} - {% endif %} -
-
-
- -
-
-

- {{ 'invoice.number'|trans({}, 'messages', language) }}: - {{ model.invoiceNumber }} - -
- {{ 'invoice.due_days'|trans({}, 'messages', language) }}: - {{ model.dueDate|date_short }} -

-
-
-
- -
-
- - - - - - - - - - - - {% for entry in model.calculator.entries %} - {% set duration = entry.duration|duration(isDecimal) %} - {% if entry.fixedRate %} - {% set rate = entry.fixedRate %} - {% set duration = entry.amount|amount %} - {% else %} - {% set rate = entry.hourlyRate %} - {% endif %} - - - - - - - - {% endfor %} - - - - - - - - - - - - - - - -
{{ 'date'|trans({}, 'messages', language) }}{{ 'description'|trans({}, 'messages', language) }}{{ 'unit_price'|trans({}, 'messages', language) }}{{ 'amount'|trans({}, 'messages', language) }}{{ 'total_rate'|trans({}, 'messages', language) }}
{{ entry.begin|date_short }} - {% if entry.description is not empty %} - {{ entry.description|nl2br }} - {% else %} - {% if entry.activity is not null %}{{ entry.activity.name }} / {% endif %}{{ entry.project.name }} - {% endif %} - {{ rate|money(currency) }}{{ duration }}{{ entry.rate|money(currency) }}
- {{ 'invoice.subtotal'|trans({}, 'messages', language) }} - {{ model.calculator.subtotal|money(currency) }}
- {{ 'invoice.tax'|trans({}, 'messages', language) }} ({{ model.calculator.vat }}%) - {{ model.calculator.tax|money(currency) }}
- {{ 'invoice.total'|trans({}, 'messages', language) }} - - {{ model.calculator.total|money(currency) }} -
-
-
- -
-
- {% if model.template.paymentTerms is not empty %} -
- {{ model.template.paymentTerms|nl2br|md2html }} + + + + + + +
+
+
+
+ +
- {% endif %} -
+ +
+
+ {{ 'invoice.from'|trans({}, 'messages', language) }} +
+ {{ model.template.company }}
+ {{ model.template.address|trim|nl2br }} + {% if model.template.vatId is not empty %} +
+ {{ 'vat_id'|trans({}, 'messages', language) }}: + {{ model.template.vatId }} + {% endif %} +
+
+
+
+ {{ 'invoice.to'|trans({}, 'messages', language) }} +
+ {{ model.customer.company|default(model.customer.name) }}
+ {{ model.customer.address|nl2br }} + {% if model.customer.vatId is not empty %} +
+ {{ 'vat_id'|trans({}, 'messages', language) }}: {{ model.customer.vatId }} + {% endif %} + {% if model.customer.number is not empty %} +
+ {{ 'number'|trans({}, 'messages', language) }}: {{ model.customer.number }} + {% endif %} + {% if model.query.project is not empty and model.query.project.orderNumber is not empty %} +
+ {{ 'orderNumber'|trans({}, 'messages', language) }}: {{ model.query.project.orderNumber }} + {% endif %} +
+
+
+ +
+
+

+ {{ 'invoice.number'|trans({}, 'messages', language) }}: + {{ model.invoiceNumber }} + +
+ {{ 'invoice.due_days'|trans({}, 'messages', language) }}: + {{ model.dueDate|date_short }} +

+
+
+
+ +
+
+ + + + + + + + + + + + {% for entry in model.calculator.entries %} + {% set duration = entry.duration|duration(true) %} + {% if entry.fixedRate %} + {% set rate = entry.fixedRate %} + {% set duration = entry.amount|amount %} + {% else %} + {% set rate = entry.hourlyRate %} + {% endif %} + + + + + + + + {% endfor %} + + + + + + + + + + + + + + + +
{{ 'date'|trans({}, 'messages', language) }}{{ 'description'|trans({}, 'messages', language) }}{{ 'unit_price'|trans({}, 'messages', language) }}{{ 'amount'|trans({}, 'messages', language) }}{{ 'total_rate'|trans({}, 'messages', language) }}
{{ entry.begin|date_short }} + {% if entry.description is not empty %} + {{ entry.description|nl2br }} + {% else %} + {% if entry.activity is not null %}{{ entry.activity.name }} / {% endif %}{{ entry.project.name }} + {% endif %} + {{ rate|money(currency) }}{{ duration }}{{ entry.rate|money(currency) }}
+ {{ 'invoice.subtotal'|trans({}, 'messages', language) }} + {{ model.calculator.subtotal|money(currency) }}
+ {{ 'invoice.tax'|trans({}, 'messages', language) }} ({{ model.calculator.vat }}%) + {{ model.calculator.tax|money(currency) }}
+ {{ 'invoice.total'|trans({}, 'messages', language) }} + + {{ model.calculator.total|money(currency) }} +
+
+
+ +
+
+ {% if model.template.paymentTerms is not empty %} +
+ {{ model.template.paymentTerms|nl2br|md2html }} +
+ {% endif %} +
+
+ +
+

+ {{ 'address'|trans({}, 'messages', language) }}: {{ model.template.company }} – {{ model.template.address|replace({"\n": ' – ', "\r\n": ' – ', "\r": ' – '})|raw }} +
+ {{ 'invoice_bank_account'|trans({}, 'messages', language) }}: {{ model.template.paymentDetails|replace({"\n": ' – ', "\r\n": ' – ', "\r": ' – '})|raw }} +
+ {{ 'contact'|trans({}, 'messages', language) }}: {{ model.template.contact|replace({"\n": ' – ', "\r\n": ' – ', "\r": ' – '})|raw }} +

+
+
- -
-

- {{ 'address'|trans({}, 'messages', language) }}: {{ model.template.company }} – {{ model.template.address|replace({"\n": ' – ', "\r\n": ' – ', "\r": ' – '})|raw }} -
- {{ 'invoice_bank_account'|trans({}, 'messages', language) }}: {{ model.template.paymentDetails|replace({"\n": ' – ', "\r\n": ' – ', "\r": ' – '})|raw }} -
- {{ 'contact'|trans({}, 'messages', language) }}: {{ model.template.contact|replace({"\n": ' – ', "\r\n": ' – ', "\r": ' – '})|raw }} -

-
- -{% endblock %} \ No newline at end of file + + diff --git a/translations/invoice-renderer.ar.xlf b/translations/invoice-renderer.ar.xlf index dec65c88..e45fd025 100644 --- a/translations/invoice-renderer.ar.xlf +++ b/translations/invoice-renderer.ar.xlf @@ -18,10 +18,6 @@ service-date مستقل - - Html - HTML (للطباعة عبر المتصفح) - default فاتورة diff --git a/translations/invoice-renderer.cs.xlf b/translations/invoice-renderer.cs.xlf index d651e09b..d1b0577d 100644 --- a/translations/invoice-renderer.cs.xlf +++ b/translations/invoice-renderer.cs.xlf @@ -26,10 +26,6 @@ programmatic K dalšímu zpracování - - Html - HTMP (pro tisk pomocí prohlížeče) - default Faktura diff --git a/translations/invoice-renderer.de.xlf b/translations/invoice-renderer.de.xlf index 4c442dd9..cc9f0871 100644 --- a/translations/invoice-renderer.de.xlf +++ b/translations/invoice-renderer.de.xlf @@ -19,10 +19,6 @@ programmatic Zur Weiterverarbeitung - - Html - HTML (zum Drucken via Browser) - invoice diff --git a/translations/invoice-renderer.el.xlf b/translations/invoice-renderer.el.xlf index 611057a1..e05e2419 100644 --- a/translations/invoice-renderer.el.xlf +++ b/translations/invoice-renderer.el.xlf @@ -15,10 +15,6 @@ programmatic Για περαιτέρω επεξεργασία - - Html - HTML (για εκτύπωση μέσω προγράμματος περιήγησης) - invoice diff --git a/translations/invoice-renderer.en.xlf b/translations/invoice-renderer.en.xlf index d6365806..255c4dba 100644 --- a/translations/invoice-renderer.en.xlf +++ b/translations/invoice-renderer.en.xlf @@ -19,10 +19,6 @@ programmatic For further processing - - Html - HTML (for printing via Browser) - invoice diff --git a/translations/invoice-renderer.es.xlf b/translations/invoice-renderer.es.xlf index c8ee51eb..d036f647 100644 --- a/translations/invoice-renderer.es.xlf +++ b/translations/invoice-renderer.es.xlf @@ -26,10 +26,6 @@ programmatic Para su procesamiento posterior - - Html - HTML (impresión por Navegador) - default Factura diff --git a/translations/invoice-renderer.fa.xlf b/translations/invoice-renderer.fa.xlf index fc4df4fd..d899fb26 100644 --- a/translations/invoice-renderer.fa.xlf +++ b/translations/invoice-renderer.fa.xlf @@ -15,10 +15,6 @@ programmatic برای پردازش بیشتر - - Html - HTML (برای چاپ از طریق مرورگر) - invoice diff --git a/translations/invoice-renderer.fi.xlf b/translations/invoice-renderer.fi.xlf index cca6896f..d1212fd2 100644 --- a/translations/invoice-renderer.fi.xlf +++ b/translations/invoice-renderer.fi.xlf @@ -15,10 +15,6 @@ programmatic Jatko käsittelyä varten - - Html - HTML (tulostukseen selaimen kautta) - invoice diff --git a/translations/invoice-renderer.fr.xlf b/translations/invoice-renderer.fr.xlf index 8a7a06db..e992add3 100644 --- a/translations/invoice-renderer.fr.xlf +++ b/translations/invoice-renderer.fr.xlf @@ -18,10 +18,6 @@ service-date Freelancer - - Html - HTML (pour l'impression via le navigateur) - help.upload Attention : les fichiers existants seront écrasés. Les types de fichiers autorisés sont : %extensions%. diff --git a/translations/invoice-renderer.he.xlf b/translations/invoice-renderer.he.xlf index 921ddf66..b337bb71 100644 --- a/translations/invoice-renderer.he.xlf +++ b/translations/invoice-renderer.he.xlf @@ -26,10 +26,6 @@ programmatic לעיבוד נוסף - - Html - HTML (להדפסה דרך הדפדפן) - default חשבונית diff --git a/translations/invoice-renderer.hr.xlf b/translations/invoice-renderer.hr.xlf index 7ec5f10d..b0096cba 100644 --- a/translations/invoice-renderer.hr.xlf +++ b/translations/invoice-renderer.hr.xlf @@ -15,10 +15,6 @@ programmatic Za daljnju obradu - - Html - HTML (za ispis putem preglednika) - invoice diff --git a/translations/invoice-renderer.hu.xlf b/translations/invoice-renderer.hu.xlf index 62a3179e..ff1ae751 100644 --- a/translations/invoice-renderer.hu.xlf +++ b/translations/invoice-renderer.hu.xlf @@ -26,10 +26,6 @@ programmatic További feldolgozáshoz - - Html - HTML (böngészőn keresztüli nyomtatáshoz) - default Számla diff --git a/translations/invoice-renderer.ko.xlf b/translations/invoice-renderer.ko.xlf index 88ab9831..1dfe7c08 100644 --- a/translations/invoice-renderer.ko.xlf +++ b/translations/invoice-renderer.ko.xlf @@ -22,10 +22,6 @@ help.upload 주의: 기존 파일을 덮어씁니다. 허용되는 파일 형식은 %extensions%입니다. - - Html - HTML (브라우저를 통한 인쇄용) - text 텍스트 diff --git a/translations/invoice-renderer.nb_NO.xlf b/translations/invoice-renderer.nb_NO.xlf index b6b95801..486de350 100644 --- a/translations/invoice-renderer.nb_NO.xlf +++ b/translations/invoice-renderer.nb_NO.xlf @@ -15,10 +15,6 @@ programmatic For videre behandling - - Html - HTML (for utskrift via nettleser) - invoice diff --git a/translations/invoice-renderer.nl.xlf b/translations/invoice-renderer.nl.xlf index cbd7ef64..b2ada47c 100644 --- a/translations/invoice-renderer.nl.xlf +++ b/translations/invoice-renderer.nl.xlf @@ -15,10 +15,6 @@ programmatic Voor verdere verwerking - - Html - HTML (voor afdrukken via de Browser) - invoice diff --git a/translations/invoice-renderer.pl.xlf b/translations/invoice-renderer.pl.xlf index 850ad6b6..3d0bb99c 100644 --- a/translations/invoice-renderer.pl.xlf +++ b/translations/invoice-renderer.pl.xlf @@ -26,10 +26,6 @@ programmatic Do dalszego przetwarzania - - Html - HTML (do wydruku przez przeglądarkę) - default Faktura diff --git a/translations/invoice-renderer.pt.xlf b/translations/invoice-renderer.pt.xlf index 44e78bd2..dd06c4f7 100644 --- a/translations/invoice-renderer.pt.xlf +++ b/translations/invoice-renderer.pt.xlf @@ -15,10 +15,6 @@ programmatic Para processamento posterior - - Html - HTML (para impressão via navegador web) - invoice diff --git a/translations/invoice-renderer.pt_BR.xlf b/translations/invoice-renderer.pt_BR.xlf index ff02e3b0..e26bcb28 100644 --- a/translations/invoice-renderer.pt_BR.xlf +++ b/translations/invoice-renderer.pt_BR.xlf @@ -22,10 +22,6 @@ help.upload Atenção: os arquivos já existentes serão substituídos. Os tipos dos arquivos permitidos são: %extensions%. - - Html - HTML (para impressão via navegador) - programmatic Para processamento posterior diff --git a/translations/invoice-renderer.ro.xlf b/translations/invoice-renderer.ro.xlf index f0c0393b..e5be994d 100644 --- a/translations/invoice-renderer.ro.xlf +++ b/translations/invoice-renderer.ro.xlf @@ -26,10 +26,6 @@ programmatic Pentru prelucrare ulterioară - - Html - HTML (pentru imprimare prin browser) - default Factură diff --git a/translations/invoice-renderer.sv.xlf b/translations/invoice-renderer.sv.xlf index 7744f233..8e895dc7 100644 --- a/translations/invoice-renderer.sv.xlf +++ b/translations/invoice-renderer.sv.xlf @@ -26,10 +26,6 @@ programmatic För ytterligare bearbetning - - Html - HTML (för utskrift från webbläsare) - default Faktura diff --git a/translations/invoice-renderer.tr.xlf b/translations/invoice-renderer.tr.xlf index 6964110a..d11c3420 100644 --- a/translations/invoice-renderer.tr.xlf +++ b/translations/invoice-renderer.tr.xlf @@ -30,10 +30,6 @@ help.upload Dikkat: mevcut dosyaların üzerine yazılacaktır. İzin verilen dosya türleri: %extensions%. - - Html - HTML (Tarayıcı ile yazdırmak için) - text Metin diff --git a/translations/invoice-renderer.uk.xlf b/translations/invoice-renderer.uk.xlf index d0efb766..1b0ca981 100644 --- a/translations/invoice-renderer.uk.xlf +++ b/translations/invoice-renderer.uk.xlf @@ -15,10 +15,6 @@ programmatic Для подальшої обробки - - Html - HTML (для друку через браузер) - invoice diff --git a/translations/invoice-renderer.vi.xlf b/translations/invoice-renderer.vi.xlf index cdd56f96..1d09bb3d 100644 --- a/translations/invoice-renderer.vi.xlf +++ b/translations/invoice-renderer.vi.xlf @@ -26,10 +26,6 @@ programmatic Để xử lý thêm - - Html - HTML (Để in qua Trình duyệt) - default Hóa đơn diff --git a/translations/invoice-renderer.zh_CN.xlf b/translations/invoice-renderer.zh_CN.xlf index 9cd5260a..a7da5f81 100644 --- a/translations/invoice-renderer.zh_CN.xlf +++ b/translations/invoice-renderer.zh_CN.xlf @@ -18,10 +18,6 @@ service-date 兼职人员 - - Html - HTML(用于通过浏览器打印) - default 发票 diff --git a/translations/tasks.ar.xlf b/translations/tasks.ar.xlf index 3685db50..556e8027 100644 --- a/translations/tasks.ar.xlf +++ b/translations/tasks.ar.xlf @@ -58,10 +58,6 @@ tasks.my مهامي - - task.delete - هل تريد حذف المهمة؟ لن يتم حذف سجلات الوقت! - task.help.end يجب إنجاز المهمة إلى غاية هذا التاريخ diff --git a/translations/tasks.cs.xlf b/translations/tasks.cs.xlf index e9916164..a03c81eb 100644 --- a/translations/tasks.cs.xlf +++ b/translations/tasks.cs.xlf @@ -94,10 +94,6 @@ tasks.pending Nevyřízené úkoly - - task.delete - Smazat úkol? Časové záznamy nebudou smazány! - task.help.user Přiřaďte tuto úlohu uživateli diff --git a/translations/tasks.de.xlf b/translations/tasks.de.xlf index d86b2047..370f518a 100644 --- a/translations/tasks.de.xlf +++ b/translations/tasks.de.xlf @@ -53,10 +53,6 @@ tasks.my Meine Aufgaben - - task.delete - Aufgabe löschen? Aufgezeichnete Zeiten werden nicht gelöscht! - task.help.title Eine kurze Beschreibung der Aufgabe diff --git a/translations/tasks.en.xlf b/translations/tasks.en.xlf index a62e3562..cbc67a91 100644 --- a/translations/tasks.en.xlf +++ b/translations/tasks.en.xlf @@ -53,10 +53,6 @@ tasks.my My tasks - - task.delete - Delete task? Time records will not be deleted! - task.help.title A short description of the task diff --git a/translations/tasks.es.xlf b/translations/tasks.es.xlf index da59b2c7..22243ebd 100644 --- a/translations/tasks.es.xlf +++ b/translations/tasks.es.xlf @@ -78,10 +78,6 @@ task.help.title Una breve descripción de la tarea - - task.delete - ¿Eliminar tarea? ¡Los registros de tiempo no se borrarán! - task.help.user Asignar esta tarea a un usuario diff --git a/translations/tasks.fi.xlf b/translations/tasks.fi.xlf index 3ed72a16..247b92e1 100644 --- a/translations/tasks.fi.xlf +++ b/translations/tasks.fi.xlf @@ -53,10 +53,6 @@ tasks.my Tehtäväni - - task.delete - Poista tehtävä? Työaikoja ei poisteta! - task.help.title Lyhyt kuvaus tehtävälle diff --git a/translations/tasks.fr.xlf b/translations/tasks.fr.xlf index a13cc00b..f8bb0218 100644 --- a/translations/tasks.fr.xlf +++ b/translations/tasks.fr.xlf @@ -53,10 +53,6 @@ tasks.my Mes tâches - - task.delete - Effacer la tâche? Les temps assignés ne seront pas supprimés! - task.help.title Une description courte de la tâche diff --git a/translations/tasks.he.xlf b/translations/tasks.he.xlf index 1bd65c0a..3f6892d0 100644 --- a/translations/tasks.he.xlf +++ b/translations/tasks.he.xlf @@ -53,10 +53,6 @@ tasks.my המשימות שלי - - task.delete - למחוק משימה? רשומות השעות לא תימחקנה! - task.help.title תיאור קצר של המשימה diff --git a/translations/tasks.nb_NO.xlf b/translations/tasks.nb_NO.xlf index 04f577af..edd1b3f7 100644 --- a/translations/tasks.nb_NO.xlf +++ b/translations/tasks.nb_NO.xlf @@ -50,10 +50,6 @@ task.assign Tildel til meg - - task.delete - Slett gjøremål? Tidssedelene vil ikke bli slettet. - task.help.end Gjøremålet må utføres før denne datoen diff --git a/translations/tasks.pt_BR.xlf b/translations/tasks.pt_BR.xlf index ae51129d..de9f62ea 100644 --- a/translations/tasks.pt_BR.xlf +++ b/translations/tasks.pt_BR.xlf @@ -73,10 +73,6 @@ task.widget_rows Quantidade de tarefas por página na ferramenta do painel - - task.delete - Excluir a tarefa? Os registros de tempo não serão apagados! - task.help.estimation Tempo necessário estimado para completar a tarefa em hh:mm diff --git a/translations/tasks.tr.xlf b/translations/tasks.tr.xlf index 7235cd13..1322901c 100644 --- a/translations/tasks.tr.xlf +++ b/translations/tasks.tr.xlf @@ -18,10 +18,6 @@ task.stop İşlemeyi duraklat - - task.delete - Görev silinsin mi? Zaman kayıtları silinmeyecektir! - Tasks Görevler