Blame | Last modification | View Log | Download
{% extends 'base.html.twig' %}{% import "macros/widgets.html.twig" as widgets %}{% import "macros/datatables.html.twig" as tables %}{% set totalDuration = 0 %}{% set totalRates = {} %}{% set showEmpty = false %}{% if searched %}{% set showEmpty = true %}{% for model in models %}{% if showEmpty %}{% set showEmpty = model.calculator is empty or model.calculator.entries is empty %}{% endif %}{% set totalDuration = totalDuration + model.calculator.timeWorked %}{% set customerCurrency = model.customer.currency %}{% if totalRates[customerCurrency] is not defined %}{% set totalRates = totalRates|merge({(customerCurrency): 0.00}) %}{% endif %}{% set totalRates = totalRates|merge({(customerCurrency): totalRates[customerCurrency] + model.calculator.total}) %}{% endfor %}{% endif %}{% set columns = {'date': {'class': 'alwaysVisible w-min', 'orderBy': false},'project': {'class': 'd-none d-md-table-cell', 'orderBy': false},'description': {'class': 'd-none d-xl-table-cell', 'orderBy': false},'user': {'class': 'd-none d-xl-table-cell w-min', 'orderBy': false},'unit_price': {'class': 'd-none d-sm-table-cell text-end w-min', 'orderBy': false},'amount': {'class': 'd-none d-sm-table-cell text-end w-min', 'orderBy': false},'duration': {'class': 'text-end w-min', 'orderBy': false},'total_rate': {'class': 'text-end alwaysVisible w-min', 'orderBy': false},} %}{% set tableName = 'invoice_create' %}{% block status %}{% from "macros/status.html.twig" import status_duration, status_money %}{% if totalDuration > 0 %}{{ status_duration(totalDuration|duration) }}{% endif %}{% for totalCurrency, totalRate in totalRates %}{{ status_money(totalRate|money(totalCurrency)) }}{% endfor %}{% endblock %}{% block main %}{% embed '@theme/embeds/card.html.twig' %}{% import "macros/search.html.twig" as search %}{% form_theme form 'form/horizontal.html.twig' %}{% block box_title %}{{ 'invoice.filter'|trans }}{% endblock %}{% block box_before %}{{ form_start(form) }}{% endblock %}{% block box_body %}{{ form_errors(form) }}{% if form.searchTerm is defined %}{{ form_row(form.searchTerm, {'row_attr': {'class': 'mb-3 invoice_search_form_row_searchTerm'}}) }}{% endif %}{{ form_row(form.daterange, {'row_attr': {'class': 'mb-3 invoice_search_form_row_daterange'}}) }}{{ form_row(form.customers, {'row_attr': {'class': 'mb-3 invoice_search_form_row_customers'}}) }}{{ form_row(form.projects, {'row_attr': {'class': 'mb-3 invoice_search_form_row_projects'}}) }}{% if form.activities is defined %}{{ form_row(form.activities, {'row_attr': {'class': 'mb-3 invoice_search_form_row_activities'}}) }}{% endif %}{% if form.tags is defined %}{{ form_row(form.tags, {'row_attr': {'class': 'mb-3 invoice_search_form_row_tags'}}) }}{% endif %}{% if form.users is defined %}{{ form_row(form.users, {'row_attr': {'class': 'mb-3 invoice_search_form_row_users'}}) }}{% endif %}{% if form.teams is defined %}{{ form_row(form.teams, {'row_attr': {'class': 'mb-3 invoice_search_form_row_teams'}}) }}{% endif %}{% if form.exported is defined %}{{ form_row(form.exported, {'row_attr': {'class': 'mb-3 invoice_search_form_row_exported'}}) }}{% endif %}<div class="d-none">{{ form_row(form.template, {'row_attr': {'class': 'mb-3 invoice_search_form_row_template'}}) }}{{ form_row(form.invoiceDate, {'row_attr': {'class': 'mb-3 invoice_search_form_row_invoiceDate'}}) }}</div>{% endblock %}{% block box_footer%}{{ search.searchButton(form) }}{% endblock %}{% block box_after %}{{ form_end(form) }}{% endblock %}{% endembed %}{% if showEmpty %}{{ widgets.nothing_found() }}{% endif %}{% if models|length > 0 %}{% embed '@theme/embeds/card.html.twig' %}{% import "macros/widgets.html.twig" as widgets %}{% import "macros/datatables.html.twig" as tables %}{% block box_title %}{{ 'preview'|trans }}{% endblock %}{% block box_attributes %}id="invoice_customer_forms"{% endblock %}{% block box_body_class %}p-0{% endblock %}{% block box_body %}<table class="table dataTable"><thead><tr><th class="d-sm-table-cell d-none"></th><th>{{ 'customer'|trans }}</th><th class="w-min text-end d-sm-table-cell d-none">{{ 'duration'|trans }}</th><th class="w-min text-end d-sm-table-cell d-none">{{ 'total_rate'|trans }}</th><th class="w-min text-center actions alwaysVisible"></th></tr></thead><tbody>{% for model in models %}{% set isDecimal = true %}{% set currency = model.currency %}{% set isEmptyModel = model.calculator is empty or model.calculator.entries is empty %}{% set customerForm = forms[loop.index0] %}<tr><td class="w-min d-sm-table-cell d-none">{% if not isEmptyModel %}{{ widgets.card_tool_button('collapse', {'onclick': "this.parentElement.parentElement.nextElementSibling.classList.toggle('d-none');return false;"}) }}{% endif %}</td><td>{% if is_granted('view', model.customer) %}<a class="text-reset" href="{{ path('customer_details', {id: model.customer.id}) }}">{{ widgets.label_customer(model.customer) }}</a>{% else %}{{ widgets.label_customer(model.customer) }}{% endif %}</td><td class="w-min text-end d-sm-table-cell d-none">{{ model.calculator.timeWorked|duration(isDecimal) }}</td><td class="w-min text-end d-sm-table-cell d-none"><span title="{{ 'vat'|trans }}: {{ model.calculator.tax|money(currency) }}" data-toggle="tooltip">{{ model.calculator.total|money(currency) }}</span></td><td class="w-min text-center actions alwaysVisible">{% for attrs in [{'class': 'd-inline-flex d-md-none'}, {'icon': false, 'class': 'd-none d-md-inline-flex'}] %}{{ widgets.action_button('print', {'url': '#', 'onclick': 'return singleInvoice(this, true)', 'title': 'preview'|trans, 'target': '_blank', 'attr': {'data-customer': model.customer.id, 'data-href': path('invoice_preview', {'customer': model.customer.id, 'token': csrf_token('invoice.preview')})}}|merge(attrs)) }}{{ widgets.action_button('invoice', {'url': '#', 'onclick': 'return singleInvoice(this, false)', 'title': 'action.save'|trans, 'attr': {'data-customer': model.customer.id, 'data-href': path('invoice_create', {'customer': model.customer.id, 'token': csrf_token('invoice.create')})}}|merge(attrs), 'success') }}{% endfor %}</td></tr><tr class="d-none"><td colspan="5" class="p-2">{% if not isEmptyModel %}{% form_theme customerForm 'form/horizontal.html.twig' %}{{ form_start(customerForm) }}{{ form_rest(customerForm) }}{{ form_end(customerForm) }}{% set isDecimal = true %}{% set entries = model.calculator.entries %}{% set currency = model.currency %}{% set itemsAmount = entries|length %}{{ tables.datatable_header(tableName, columns, model.query, {'boxClass': ''}) }}{% if limit_preview %}{% set entries = entries|slice(0, 100) %}{% endif %}{% for entry in entries %}{% set amount = entry.amount %}{% set duration = entry.duration|duration(isDecimal) %}{% set rate = 0 %}{% if entry.fixedRate is not null %}{% set rate = entry.fixedRate %}{% elseif entry.hourlyRate is not null %}{% set rate = entry.hourlyRate %}{% endif %}<tr><td class="{{ tables.data_table_column_class(tableName, columns, 'date') }}">{{ entry.begin|date_short }}</td><td class="{{ tables.data_table_column_class(tableName, columns, 'project') }}">{% if is_granted('view', entry.project) %}<a class="text-reset" href="{{ path('project_details', {id: entry.project.id}) }}">{{ widgets.label_project(entry.project) }}</a>{% else %}{{ widgets.label_project(entry.project) }}{% endif %}{% if entry.activity is not null %}<br><small>{% if is_granted('view', entry.activity) %}<a class="text-reset" href="{{ path('activity_details', {id: entry.activity.id}) }}">{{ widgets.label_activity(entry.activity) }}</a>{% else %}{{ widgets.label_activity(entry.activity) }}{% endif %}</small>{% endif %}</td><td class="{{ tables.data_table_column_class(tableName, columns, 'description') }} timesheet-description">{% if entry.description is not empty %}{{ entry.description|desc2html }}{% endif %}</td><td class="{{ tables.data_table_column_class(tableName, columns, 'user') }}">{{ widgets.label_user(entry.user) }}</td><td class="{{ tables.data_table_column_class(tableName, columns, 'unit_price') }}">{{ rate|money(currency) }}</td><td class="{{ tables.data_table_column_class(tableName, columns, 'amount') }}">{{ amount }}</td><td class="{{ tables.data_table_column_class(tableName, columns, 'duration') }}" data-duration="{{ entry.duration }}">{{ duration }}</td><td class="{{ tables.data_table_column_class(tableName, columns, 'total_rate') }}">{{ entry.rate|money(currency) }}</td></tr>{% endfor %}{% if limit_preview and itemsAmount > 100 %}<tr class="warning"><td colspan="8">» {{ 'preview.skipped_rows'|trans({'%rows%': (itemsAmount - 100)}) }}</td></tr>{% endif %}{{ tables.data_table_footer(entries) }}{% endif %}</td></tr>{% endfor %}</tbody></table><div style="display: none" id="create-token" data-value="{{ csrf_token('invoice.create') }}"></div><div style="display: none" id="preview-token" data-value="{{ csrf_token('invoice.preview') }}"></div>{% endblock %}{% endembed %}{% endif %}{% endblock %}{% block javascripts %}{{ parent() }}{% set formId = form.vars.attr.id %}{% set formSelector = 'form#' ~ formId %}<script type="text/javascript">function singleInvoice(link, preview){const formName = 'customer_' + link.dataset['customer'];const template = document.getElementById(formName + '_template').value;const date = document.getElementById(formName + '_invoiceDate').value;const formPlugin = kimai.getPlugin('form');const overwrites = {'customers[]': link.dataset['customer'], 'template': template, 'invoiceDate': date};const uri = formPlugin.convertFormDataToQueryString(document.getElementById('{{ formId }}'), overwrites);const invoiceUrl = link.dataset['href'] + '?' + uri;if (!preview) {link.classList.toggle('disabled');link.href = 'javascript: void(0)';document.location = invoiceUrl;return false;}link.href = invoiceUrl;return true;}/** @type CustomEvent event */document.addEventListener('kimai.initialized', function(event) {KimaiReloadPageWidget.create('kimai.systemConfigUpdate', true);{% if models|length > 0 %}document.getElementById('{{ form.template.vars.id }}').addEventListener('change', function(event) {document.getElementById('{{ form.vars.attr.id }}').submit();});{% endif %}});</script>{% endblock %}