mirror of
https://github.com/Findus23/invoices.git
synced 2024-09-19 15:13:47 +02:00
first working version
This commit is contained in:
commit
634ba875b3
5 changed files with 572 additions and 0 deletions
327
.gitignore
vendored
Normal file
327
.gitignore
vendored
Normal file
|
@ -0,0 +1,327 @@
|
|||
|
||||
# Created by https://www.gitignore.io/api/latex,python
|
||||
|
||||
### LaTeX ###
|
||||
## Core latex/pdflatex auxiliary files:
|
||||
*.aux
|
||||
*.lof
|
||||
*.log
|
||||
*.lot
|
||||
*.fls
|
||||
*.out
|
||||
*.toc
|
||||
*.fmt
|
||||
*.fot
|
||||
*.cb
|
||||
*.cb2
|
||||
|
||||
## Intermediate documents:
|
||||
*.dvi
|
||||
*.xdv
|
||||
*-converted-to.*
|
||||
|
||||
*.pdf
|
||||
|
||||
## Bibliography auxiliary files (bibtex/biblatex/biber):
|
||||
*.bbl
|
||||
*.bcf
|
||||
*.blg
|
||||
*-blx.aux
|
||||
*-blx.bib
|
||||
*.run.xml
|
||||
|
||||
## Build tool auxiliary files:
|
||||
*.fdb_latexmk
|
||||
*.synctex
|
||||
*.synctex(busy)
|
||||
*.synctex.gz
|
||||
*.synctex.gz(busy)
|
||||
*.pdfsync
|
||||
*Notes.bib
|
||||
|
||||
## Auxiliary and intermediate files from other packages:
|
||||
# algorithms
|
||||
*.alg
|
||||
*.loa
|
||||
|
||||
# achemso
|
||||
acs-*.bib
|
||||
|
||||
# amsthm
|
||||
*.thm
|
||||
|
||||
# beamer
|
||||
*.nav
|
||||
*.pre
|
||||
*.snm
|
||||
*.vrb
|
||||
|
||||
# changes
|
||||
*.soc
|
||||
|
||||
# cprotect
|
||||
*.cpt
|
||||
|
||||
# elsarticle (documentclass of Elsevier journals)
|
||||
*.spl
|
||||
|
||||
# endnotes
|
||||
*.ent
|
||||
|
||||
# fixme
|
||||
*.lox
|
||||
|
||||
# feynmf/feynmp
|
||||
*.mf
|
||||
*.mp
|
||||
*.t[1-9]
|
||||
*.t[1-9][0-9]
|
||||
*.tfm
|
||||
|
||||
#(r)(e)ledmac/(r)(e)ledpar
|
||||
*.end
|
||||
*.?end
|
||||
*.[1-9]
|
||||
*.[1-9][0-9]
|
||||
*.[1-9][0-9][0-9]
|
||||
*.[1-9]R
|
||||
*.[1-9][0-9]R
|
||||
*.[1-9][0-9][0-9]R
|
||||
*.eledsec[1-9]
|
||||
*.eledsec[1-9]R
|
||||
*.eledsec[1-9][0-9]
|
||||
*.eledsec[1-9][0-9]R
|
||||
*.eledsec[1-9][0-9][0-9]
|
||||
*.eledsec[1-9][0-9][0-9]R
|
||||
|
||||
# glossaries
|
||||
*.acn
|
||||
*.acr
|
||||
*.glg
|
||||
*.glo
|
||||
*.gls
|
||||
*.glsdefs
|
||||
|
||||
# gnuplottex
|
||||
*-gnuplottex-*
|
||||
|
||||
# gregoriotex
|
||||
*.gaux
|
||||
*.gtex
|
||||
|
||||
# hyperref
|
||||
*.brf
|
||||
|
||||
# knitr
|
||||
*-concordance.tex
|
||||
# TODO Comment the next line if you want to keep your tikz graphics files
|
||||
*.tikz
|
||||
*-tikzDictionary
|
||||
|
||||
# listings
|
||||
*.lol
|
||||
|
||||
# makeidx
|
||||
*.idx
|
||||
*.ilg
|
||||
*.ind
|
||||
*.ist
|
||||
|
||||
# minitoc
|
||||
*.maf
|
||||
*.mlf
|
||||
*.mlt
|
||||
*.mtc[0-9]*
|
||||
*.slf[0-9]*
|
||||
*.slt[0-9]*
|
||||
*.stc[0-9]*
|
||||
|
||||
# minted
|
||||
_minted*
|
||||
*.pyg
|
||||
|
||||
# morewrites
|
||||
*.mw
|
||||
|
||||
# nomencl
|
||||
*.nlo
|
||||
|
||||
# pax
|
||||
*.pax
|
||||
|
||||
# pdfpcnotes
|
||||
*.pdfpc
|
||||
|
||||
# sagetex
|
||||
*.sagetex.sage
|
||||
*.sagetex.py
|
||||
*.sagetex.scmd
|
||||
|
||||
# scrwfile
|
||||
*.wrt
|
||||
|
||||
# sympy
|
||||
*.sout
|
||||
*.sympy
|
||||
sympy-plots-for-*.tex/
|
||||
|
||||
# pdfcomment
|
||||
*.upa
|
||||
*.upb
|
||||
|
||||
# pythontex
|
||||
*.pytxcode
|
||||
pythontex-files-*/
|
||||
|
||||
# thmtools
|
||||
*.loe
|
||||
|
||||
# TikZ & PGF
|
||||
*.dpth
|
||||
*.md5
|
||||
*.auxlock
|
||||
|
||||
# todonotes
|
||||
*.tdo
|
||||
|
||||
# easy-todo
|
||||
*.lod
|
||||
|
||||
# xindy
|
||||
*.xdy
|
||||
|
||||
# xypic precompiled matrices
|
||||
*.xyc
|
||||
|
||||
# endfloat
|
||||
*.ttt
|
||||
*.fff
|
||||
|
||||
# Latexian
|
||||
TSWLatexianTemp*
|
||||
|
||||
## Editors:
|
||||
# WinEdt
|
||||
*.bak
|
||||
*.sav
|
||||
|
||||
# Texpad
|
||||
.texpadtmp
|
||||
|
||||
# Kile
|
||||
*.backup
|
||||
|
||||
# KBibTeX
|
||||
*~[0-9]*
|
||||
|
||||
# auto folder when using emacs and auctex
|
||||
/auto/*
|
||||
|
||||
# expex forward references with \gathertags
|
||||
*-tags.tex
|
||||
|
||||
### Python ###
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
.pytest_cache/
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule.*
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
|
||||
output*
|
||||
*.yaml
|
||||
!*.example.yaml
|
||||
!strings.yaml
|
||||
.idea/
|
75
create.py
Normal file
75
create.py
Normal file
|
@ -0,0 +1,75 @@
|
|||
import os
|
||||
import subprocess
|
||||
|
||||
import jinja2
|
||||
|
||||
from utils import load_yaml, remove_tmp_files
|
||||
|
||||
env = jinja2.Environment(
|
||||
block_start_string='\BLOCK{',
|
||||
block_end_string='}',
|
||||
variable_start_string='\VAR{',
|
||||
variable_end_string='}',
|
||||
comment_start_string='\#{',
|
||||
comment_end_string='}',
|
||||
line_statement_prefix='%#',
|
||||
line_comment_prefix='%%',
|
||||
trim_blocks=True,
|
||||
autoescape=False,
|
||||
loader=jinja2.FileSystemLoader(os.path.abspath('.'))
|
||||
)
|
||||
|
||||
DATA = {
|
||||
"invoice_id": 1234,
|
||||
"invoice_date": "01.03.2018"
|
||||
}
|
||||
|
||||
DATA["from"] = load_yaml("from.yaml")
|
||||
DATA["to"] = load_yaml("recipents/{id}.yaml".format(id="innocraft"))
|
||||
|
||||
# invoice = {
|
||||
# "mode": "single",
|
||||
# "description": "TESTOBJEKT",
|
||||
# "timerange": "18.12.2016 - 28.02.2017",
|
||||
# "price": 400,
|
||||
# "locale": "de"
|
||||
# }
|
||||
invoice = {
|
||||
"mode": "hourly",
|
||||
"title": "Example Invoice",
|
||||
"description": "Example",
|
||||
"timerange": "18.12.2016 - 28.02.2017",
|
||||
"hours": 35,
|
||||
"per_hour": 21,
|
||||
"locale": "en"
|
||||
}
|
||||
|
||||
invoice["total"] = invoice["per_hour"] * invoice["hours"]
|
||||
|
||||
DATA["invoice"] = invoice
|
||||
|
||||
strings = load_yaml("strings.yaml")
|
||||
|
||||
|
||||
def translate(key):
|
||||
if key in strings:
|
||||
return strings[key][invoice["locale"]]
|
||||
else:
|
||||
print("Translation key for '{key}' is missing".format(key=key))
|
||||
exit()
|
||||
|
||||
|
||||
def format_digit(integer):
|
||||
string = "{0:.2f}".format(integer)
|
||||
if invoice["locale"] == "de":
|
||||
string = string.replace(".", ",")
|
||||
return string
|
||||
|
||||
|
||||
env.filters['formatdigit'] = format_digit
|
||||
env.filters['t'] = translate
|
||||
with open("output.tex", "w") as fh:
|
||||
template = env.get_template('template.tex')
|
||||
fh.write(template.render(section1='Long Form', section2='Short Form', **DATA))
|
||||
subprocess.check_call(['pdflatex', 'output.tex'])
|
||||
remove_tmp_files("output")
|
24
strings.yaml
Normal file
24
strings.yaml
Normal file
|
@ -0,0 +1,24 @@
|
|||
invoice:
|
||||
de: Rechnung
|
||||
en: Invoice
|
||||
descr:
|
||||
de: Beschreibung
|
||||
en: Description
|
||||
period:
|
||||
de: Leistungszeitraum
|
||||
en: Period
|
||||
total:
|
||||
de: Gesamtpreis
|
||||
en: Total
|
||||
per_hour:
|
||||
de: Stundensatz
|
||||
en: Hourly Rate
|
||||
hours:
|
||||
de: Stunden
|
||||
en: Hours
|
||||
taxexception:
|
||||
de: Umsatzsteuerfrei aufgrund der Kleinunternehmerregelung gemäß §6(1)27 UStG
|
||||
en: VAT-exempt because of small-business regulation (§6(1)27 UStG)
|
||||
transfer:
|
||||
de: Ich bitte Sie, den Gesamtbetrag innerhalb der nächsten 10 Tage auf folgendes Konto zu überweisen
|
||||
en: Please transfer the due invoice amount to the following account
|
133
template.tex
Normal file
133
template.tex
Normal file
|
@ -0,0 +1,133 @@
|
|||
\documentclass[
|
||||
a4paper,
|
||||
12pt,
|
||||
version=last,
|
||||
fromalign=right,
|
||||
% foldmarks=p, % keine mittlere Faltmarke
|
||||
foldmarks=off,
|
||||
enlargefirstpage,
|
||||
fromemail,
|
||||
fromphone,
|
||||
fromcity,
|
||||
fromlogo,
|
||||
fromrule,
|
||||
backaddress,
|
||||
]{scrlttr2}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\BLOCK{if invoice.locale =="de"}
|
||||
\usepackage[ngerman]{babel}
|
||||
\BLOCK{else}
|
||||
\usepackage[english]{babel}
|
||||
\BLOCK{endif}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{lmodern}
|
||||
\usepackage{mathpazo}
|
||||
\usepackage[left]{eurosym}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{microtype}
|
||||
\usepackage{tabularx}
|
||||
|
||||
\usepackage{color}
|
||||
\definecolor{LightGray}{rgb}{0.7,0.7,0.7}
|
||||
\definecolor{Gray}{rgb}{0.5,0.5,0.5}
|
||||
\setkomafont{fromrule}{\color{LightGray}}
|
||||
\setkomafont{fromaddress}{\sffamily} % Sans Serif
|
||||
\setkomafont{fromname}{\sffamily\bfseries} % and bold
|
||||
\setkomafont{pagefoot}{\sffamily\bfseries}
|
||||
|
||||
\usepackage{graphicx}
|
||||
|
||||
\newcommand{\separ}{~\textperiodcentered~}
|
||||
|
||||
\hyphenpenalty=10000
|
||||
|
||||
\newcommand{\VAR}[1]{\LaTeX} % Just a placeholder (will never be used)
|
||||
|
||||
\newcommand{\BLOCK}[1]{\LaTeX} % Just a placeholder (will never be used)
|
||||
|
||||
\newcommand{\Name}{\VAR{from.name}}
|
||||
\setkomavar{fromname}{\Name}
|
||||
\newcommand{\Address}{\VAR{from.address}}
|
||||
\newcommand{\ZIP}{\VAR{from.zip}}
|
||||
\newcommand{\City}{\VAR{from.city}}
|
||||
\newcommand{\CityShort}{\VAR{from.cityShort}}
|
||||
|
||||
\setkomavar{fromaddress}{\Address\\\ZIP~\City
|
||||
\BLOCK{if to.country!="Austria"}\\\VAR{from.country}\BLOCK{endif}}
|
||||
\setkomavar{fromphone}[]{\VAR{from.phone}}
|
||||
\setkomavar{fromemail}[]{\VAR{from.email}}
|
||||
\setkomavar{fromurl}[]{\VAR{from.url}}
|
||||
%\setkomavar{fromlogo}{\includegraphics[height=3.2cm]{template/header.jpg}}
|
||||
|
||||
|
||||
\setkomavar{frombank}{Sparkasse Krems\separ IBAN: \VAR{from.IBAN}\separ BIC: \VAR{from.BIC}}
|
||||
%TODO: Linie über
|
||||
\setkomavar{firstfoot}{\centering\color{Gray}\scriptsize\Name\separ\Address\separ\ZIP~\City\\
|
||||
\usekomavar{fromphone}\separ\usekomavar{fromemail}\separ\usekomavar{fromurl}\\\usekomavar{frombank}}
|
||||
|
||||
\setkomavar{invoice}{\VAR{invoice_id}}
|
||||
\setkomavar{date}{\VAR{invoice_date}}
|
||||
|
||||
\pdfinfo{
|
||||
/Author (\Name)
|
||||
/Title (\VAR{"invoice" |t} \VAR{from.name} (\VAR{rechnungsDatum}))
|
||||
/Subject (\VAR{"invoice" |t} \VAR{from.name} (\VAR{rechnungsDatum}))
|
||||
/Keywords (\VAR{"invoice" |t})
|
||||
}
|
||||
|
||||
\setkomavar{backaddress}{\usekomavar{fromname}, \Address, \ZIP~\CityShort}
|
||||
|
||||
% Begin document
|
||||
\begin{document}
|
||||
\begin{letter}{\VAR{to.name} \\ \VAR{to.address} \\ \VAR{to.plz}~\VAR{to.ort}
|
||||
\BLOCK{if to.country!="Austria"}\\\VAR{to.country}\BLOCK{endif}}
|
||||
\setkomavar{title}{\VAR{invoice.title}}
|
||||
\opening{}
|
||||
|
||||
\BLOCK{if invoice.mode=="single"}
|
||||
\begin{tabular}{ll}
|
||||
\VAR{"descr"|t}:& \VAR{invoice.description} \\
|
||||
\VAR{"period"|t}: & \VAR{invoice.timerange} \\
|
||||
\VAR{"total"|t}: & \EUR{\VAR{invoice.price | formatdigit }} \\
|
||||
|
||||
\vspace{0.5cm}
|
||||
|
||||
\end{tabular}
|
||||
\BLOCK{elif invoice.mode=="hourly"}
|
||||
|
||||
\vspace{0.5cm}
|
||||
\begin{tabularx}{\textwidth}{Xrrr}
|
||||
\VAR{"descr"|t} & \VAR{"per_hour"|t} & \VAR{"hours"|t} & \VAR{"total"|t} \\ \midrule
|
||||
|
||||
\VAR{invoice.description} &
|
||||
\EUR{\VAR{invoice.per_hour | formatdigit }} &
|
||||
\VAR{invoice.hours} &
|
||||
\EUR{\VAR{invoice.total | formatdigit }} \\
|
||||
|
||||
|
||||
|
||||
\midrule %\cmidrule{4-4}
|
||||
|
||||
|
||||
& & & \EUR{\VAR{invoice.total | formatdigit }} \\
|
||||
\end{tabularx}
|
||||
|
||||
\BLOCK{endif}
|
||||
|
||||
\vspace{0.5cm}
|
||||
\noindent \VAR{"taxexception"|t}
|
||||
|
||||
\vspace{0.5cm}
|
||||
\noindent \VAR{"transfer"|t}:
|
||||
|
||||
\vspace{0.5cm}
|
||||
|
||||
\begin{tabular}{@{}ll}
|
||||
Bank: &\VAR{from.bank}\\
|
||||
IBAN:& \VAR{from.IBAN}\\
|
||||
BIC:& \VAR{from.BIC}
|
||||
\end{tabular}
|
||||
|
||||
|
||||
\end{letter}
|
||||
\end{document}
|
13
utils.py
Normal file
13
utils.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
import os
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
def load_yaml(filename):
|
||||
with open(filename, 'r') as stream:
|
||||
return yaml.load(stream)
|
||||
|
||||
|
||||
def remove_tmp_files(base):
|
||||
for ext in ["aux", "log"]:
|
||||
os.remove(base + "." + ext)
|
Loading…
Reference in a new issue