improved invoices with new renderer (#306)

* added docx renderer and demo template
* added csv renderer and demo template
* added xlsx renderer and demo template
* added ods renderer and demo template
* added user calculator
* added invoice documentation
This commit is contained in:
Kevin Papst
2018-09-21 01:27:56 +02:00
committed by GitHub
parent b035fc9ebd
commit 53f82a808b
121 changed files with 4094 additions and 770 deletions

View File

@@ -18,10 +18,33 @@
{% block main %}
{% if model.entries is empty or action is empty %}
{% if model.entries is empty %}
{{ widgets.callout('warning', 'invoice.select_filter') }}
{% else %}
{{ render(controller(action, {'model': model, 'appRequest': app.request})) }}
{{ include('invoice/preview.html.twig') }}
<div class="row no-print">
<div class="col-xs-12">
<button type="button" id="print-invoice-button" class="btn btn-success pull-right">
<i class="{{ 'print'|icon }}"></i> {{ 'button.print'|trans }}
</button>
</div>
</div>
{% endif %}
{% endblock %}
{% block javascripts %}
<script type="text/javascript">
$(document).ready(function () {
$( "#print-invoice-button" ).click(function() {
var prevAction = $( "#invoice-print-form" ).attr('action');
$( "#invoice-print-form" ).attr('target', '_blank').attr('action', '{{ path('invoice_print') }}');
$( "#invoice-print-form" ).submit();
$( "#invoice-print-form" ).removeAttr('target').attr('action', prevAction);
});
});
</script>
{% endblock %}

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="{{ app.request.locale }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<link rel="stylesheet" href="{{ asset('build/app.css') }}">
<script src="{{ asset('build/app.js') }}"></script>
</head>
<body class="invoice_print">
<div class="wrapper">
<section class="invoice">
{% block invoice %}{% endblock %}
</section>
{% block print_button %}
<div class="row no-print">
<div class="col-xs-12">
<button type="button" class="btn btn-success pull-right" onclick="window.print();return false;">
<i class="{{ 'print'|icon }}"></i> {{ 'button.print'|trans }}
</button>
</div>
</div>
{% endblock %}
</div>
</body>
</html>

View File

@@ -0,0 +1,52 @@
{% import "macros/widgets.html.twig" as widgets %}
{{ widgets.callout('success', 'invoice.preview') }}
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>{{ 'label.date'|trans }}</th>
<th class="hidden-xs hidden-sm">{{ 'label.user'|trans }}</th>
<th class="hidden-xs hidden-sm">{{ 'label.activity'|trans }}</th>
<th class="text-center">{{ 'invoice.unit_price'|trans }}</th>
<th class="text-center">{{ 'invoice.amount'|trans }}</th>
<th class="text-right">{{ 'invoice.total_rate'|trans }}</th>
</tr>
</thead>
<tbody>
{% for entry in model.calculator.entries %}
{% set duration = entry.duration|duration() %}
{% if entry.fixedRate is not null %}
{% set rate = entry.fixedRate %}
{% set duration = 1 %}
{% elseif entry.hourlyRate is not null %}
{% set rate = entry.hourlyRate %}
{% else %}
{% set rate = app.user.getPreferenceValue('hourly_rate') %}
{% endif %}
<tr>
<td>{{ entry.begin|date_short }}</td>
<td class="hidden-xs hidden-sm">{{ widgets.username(entry.user) }}</td>
<td class="hidden-xs hidden-sm timesheet-description">
{% if entry.description is not empty %}
{{ entry.description|desc2html }}
{% else %}
{{ entry.activity.name }} / {{ entry.activity.project.name }}
{% endif %}
</td>
<td class="text-center" contenteditable="true">
{{ rate|money(model.calculator.currency) }}
</td>
<td class="text-center">
{{ duration }}
</td>
<td class="text-right">{{ entry.rate|money(model.calculator.currency) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>

Binary file not shown.

View File

@@ -1,3 +1,6 @@
{% extends 'invoice/layout.html.twig' %}
{% block invoice %}
<div class="row">
<div class="col-xs-12">
<h2 class="page-header">
@@ -108,11 +111,4 @@
</div>
</div>
</div>
<div class="row no-print">
<div class="col-xs-12">
<button type="button" class="btn btn-success pull-right" onclick="window.print();return false;">
<i class="{{ 'print'|icon }}"></i> {{ 'button.print'|trans }}
</button>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,2 @@
start_date,start_timestamp,end_date,end_timestamp,duration,username,description,rate,amount,total
${entry.begin},${entry.begin_timestamp},${entry.end},${entry.end_timestamp},${entry.duration},${entry.user_name},${entry.description},${entry.rate},${entry.amount},${entry.total}
1 start_date start_timestamp end_date end_timestamp duration username description rate amount total
2 ${entry.begin} ${entry.begin_timestamp} ${entry.end} ${entry.end_timestamp} ${entry.duration} ${entry.user_name} ${entry.description} ${entry.rate} ${entry.amount} ${entry.total}

View File

@@ -1,5 +1,10 @@
{% import "macros/widgets.html.twig" as widgets %}
{# You can overrwite these settings in your config/packages.local.yaml under the key "twig.globals.company" #}
{% extends 'invoice/layout.html.twig' %}
{% block invoice %}
{# You can overwrite these settings in your config/packages.local.yaml under the key "twig.globals.company" #}
{% set company = company|default({
name: 'Kimai Inc.',
homepage: 'www.kimai.org',
@@ -137,11 +142,4 @@
</footer>
</div>
</div>
<div class="row no-print">
<div class="col-xs-12">
<button type="button" class="btn btn-success pull-right" onclick="window.print();return false;">
<i class="{{ 'print'|icon }}"></i> {{ 'button.print'|trans }}
</button>
</div>
</div>
{% endblock %}

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,7 @@
{% import "macros/widgets.html.twig" as widgets %}
{% extends 'invoice/layout.html.twig' %}
{% block invoice %}
<div class="row">
<div class="col-xs-12">
<h2 class="page-header">
@@ -23,7 +25,13 @@
</tr>
<tr>
<th style="width:50%">{{ 'label.date'|trans }}</th>
<td contenteditable="true">{{ model.query.end|month_name|trans }} {{ model.query.end|date('Y') }}</td>
<td contenteditable="true">
{% 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|trans }} {{ model.query.end|date('Y') }}
{% endif %}
</td>
</tr>
<tr>
<th>{{ 'label.customer'|trans }}</th>
@@ -50,6 +58,9 @@
<thead>
<tr>
<th>{{ 'label.date'|trans }}</th>
{% if model.query.user is empty %}
<th>{{ 'label.user'|trans }}</th>
{% endif %}
<th>{{ 'label.activity'|trans }}</th>
<th>{{ 'label.hours'|trans }}</th>
</tr>
@@ -58,6 +69,9 @@
{% for entry in model.calculator.entries %}
<tr>
<td>{{ entry.begin|date_short }}</td>
{% if model.query.user is empty %}
<td>{{ widgets.username(entry.user) }}</td>
{% endif %}
<td>{{ entry.activity.name }} / {{ entry.activity.project.name }}</td>
<td>{{ entry.duration|duration }}</td>
</tr>
@@ -99,11 +113,4 @@
</div>
</div>
</div>
<div class="row no-print">
<div class="col-xs-12">
<button type="button" class="btn btn-success pull-right" onclick="window.print();return false;">
<i class="{{ 'print'|icon }}"></i> {{ 'button.print'|trans }}
</button>
</div>
</div>
{% endblock %}

View File

@@ -16,7 +16,6 @@
'title': '',
'due_days': 'hidden-xs',
'vat': 'hidden-xs',
'invoice_renderer': 'hidden-xs',
'actions': 'alwaysVisible',
}) }}
@@ -26,7 +25,6 @@
<td>{{ entry.title }}</td>
<td class="hidden-xs hidden-sm">{{ entry.dueDays }}</td>
<td class="hidden-xs hidden-sm">{{ entry.vat }}</td>
<td class="hidden-xs hidden-sm">{{ "invoice_renderer.#{entry.renderer}"|trans }}</td>
<td>
{% set actionButtons = {'edit': path('admin_invoice_template_edit', {'id' : entry.id, 'page': page})} %}
{% set actionButtons = actionButtons|merge({'trash': path('admin_invoice_template_delete', {'id' : entry.id, 'page': page})}) %}