feat: templates & timetracking improvements

This commit is contained in:
2023-07-04 17:32:49 +00:00
parent c778ef4a58
commit 2fa76b1e0f
3 changed files with 196 additions and 2 deletions

View File

@@ -0,0 +1,170 @@
<!DOCTYPE html>
<html lang="{{ invoice['invoice.language'] }}">
<head>
<meta charset="utf-8">
<title>{% block title %}{{ invoice['invoice.number'] }}-{{ invoice['customer.company']|default(invoice['customer.name'])|u.snake }}{% endblock %}</title>
<style>
{{ encore_entry_css_source('invoice')|raw }}
</style>
</head>
<body class="invoice_print">
<div class="wrapper">
<section class="invoice">
{% set isDecimal = model.template.decimalDuration|default(false) %}
{% set currency = model.currency %}
<div class="row">
<div class="col-xs-12">
<h2 class="page-header">
<span contenteditable="true">{{ model.template.title }}</span>
<small class="pull-right">{{ 'date'|trans }}: {{ model.invoiceDate|date_short }}</small>
</h2>
</div>
</div>
<div class="row">
<div class="col-sm-7">
{{ 'invoice.to'|trans }}
<address contenteditable="true">
<strong>{{ model.customer.company|default(model.customer.name) }}</strong><br>
{{ model.customer.address|nl2br }}
{% if model.customer.vatId is not empty %}
<br>
{{ 'vat_id'|trans }}: {{ model.customer.vatId }}
{% endif %}
{% if model.customer.number is not empty %}
<br>
{{ 'label.number'|trans }}: {{ model.customer.number }}
{% endif %}
{% if model.query.project is not empty and model.query.project.orderNumber is not empty %}
<br>
{{ 'label.orderNumber'|trans }}: {{ model.query.project.orderNumber }}
{% endif %}
</address>
</div>
<!--- <div class="col-sm-1"></div> --->
<div class="col-sm-5">
{{ 'invoice.from'|trans }}
<address contenteditable="true">
<strong>{{ model.template.company }}</strong><br>
{{ model.template.address|trim|nl2br }}
{% if model.template.vatId is not empty %}
<br>
{{ 'vat_id'|trans }}:
{{ model.template.vatId }}
{% endif %}
<br>
Steuernummer: 218/135/30020
</address>
</div>
</div>
<div class="row" style="margin-top: 20px; margin-bottom: 20px;">
<div class="col-sm-10">
<p contenteditable="true">
<strong>{{ 'invoice.number'|trans }}:</strong>
{{ model.invoiceNumber }}
<br>
<strong>Leistungszeitraum:</strong>
{{ invoice['query.begin'] }} - {{ invoice['query.end'] }}
<br>
<strong>{{ 'invoice.due_days'|trans }}:</strong>
{{ model.dueDate|date_short }}
</p>
</div>
<div class="col-sm-2"></div>
</div>
<div class="row invoice-items">
<div class="col-xs-12 table-responsive">
<table class="table">
<thead>
<tr>
<th>{{ 'description'|trans }}</th>
<th></th>
<th class="text-right">Stundensatz</th>
<th class="text-right">Stunden</th>
<th class="text-right">{{ 'total_rate'|trans }}</th>
</tr>
</thead>
<tbody>
{% 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 %}
<tr>
<!---
<td nowrap class="text-nowrap">{{ entry.begin|date_short }}</td>
--->
<td contenteditable="true">
{% if entry.description is not empty %}
{{ entry.description|nl2br }}
{% else %}
{% if entry.activity is not null %}{{ entry.activity.name }} / {% endif %}{{ entry.project.name }}
{% endif %}
</td>
<td nowrap class="text-nowrap text-right"></td>
<td nowrap class="text-nowrap text-right">{{ rate|money(currency) }}</td>
<td nowrap class="text-nowrap text-right">{{ duration }}</td>
<td nowrap class="text-nowrap text-right">{{ entry.rate|money(currency) }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
{% if model.calculator.tax > 0 or not model.isHideZeroTax() %}
<tr>
<td colspan="4" class="text-right">
{{ 'invoice.subtotal'|trans }}
</td>
<td class="text-right">{{ model.calculator.subtotal|money(currency) }}</td>
</tr>
<tr>
<td colspan="4" class="text-right">
{{ 'invoice.tax'|trans }} ({{ model.calculator.vat }}%)
</td>
<td class="text-right">{{ model.calculator.tax|money(currency) }}</td>
</tr>
{% endif %}
<tr>
<td colspan="4" class="text-right text-nowrap">
<strong>{{ 'invoice.total'|trans }}</strong>
</td>
<td class="text-right">
<strong>{{ model.calculator.total|money(currency) }}</strong>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
<div class="row">
<div class="col-xs-12">
{% if model.template.paymentTerms is not empty %}
<div contenteditable="true" class="paymentTerms">
{{ model.template.paymentTerms|md2html }}
</div>
{% endif %}
</div>
</div>
<footer class="footer">
<p>
<strong>{{ 'address'|trans }}</strong>: {{ model.template.company }} &ndash; {{ model.template.address|nl2str(' &ndash; ') }}
<br>
<strong>{{ 'invoice_bank_account'|trans }}</strong>: {{ model.template.paymentDetails|nl2str(' &ndash; ') }}
<br>
<strong>{{ 'contact'|trans }}</strong>: {{ model.template.contact|nl2str(' &ndash; ') }}
</p>
</footer>
</section>
</div>
</body>
</html>

View File

@@ -1,9 +1,31 @@
- name: Create Kimai compose directories
file:
state: directory
path: "{{ item }}"
owner: www-data
with_items:
- /data/kimai-invoice-templates/
- name: Copy Potaris twig Invoice Template
copy:
src: invoice-potaris.html.twig
dest: /data/kimai-invoice-templates/
owner: www-data
- name: Create Kimai mysql-directory
file:
state: directory
path: "{{ item }}"
owner: 999
group: root
with_items:
- /data/timetracking-mysql/
- name: Create Kimai compose directories
file:
state: directory
path: "{{ item }}"
with_items:
- /opt/timetracking-mysql/
- /opt/kimai/
- name: Deploy Kimai Compose file

View File

@@ -11,7 +11,7 @@ services:
ports:
- 3306:3306
volumes:
- /opt/timetracking-mysql/:/var/lib/mysql
- /data/timetracking-mysql/:/var/lib/mysql
kimai:
image: kimai/kimai2:apache
restart: always
@@ -19,5 +19,7 @@ services:
DATABASE_URL: "mysql://kimai:kimai@mysql:3306/kimai"
TRUSTED_HOSTS: timetracking.atlantishq.de,localhost,127.0.0.1
APP_ENV: prod
volumes:
- /data/kimai-invoice-templates/:/opt/kimai/var/invoices/
ports:
- 8080:8001