Commit e8e62ca1 authored by Alain M. Lafon's avatar Alain M. Lafon

Merge branch 'getting-ready-for-open-sourcing' into 'master'

getting ready for open sourcing

See merge request !14
parents bd5892c2 68b8f5b2
/.cpcache
/node_modules
.cpcache
.classpath
.lumo_cache/
This diff is collapsed.
* Welcome to EASY - Evented Accounting Sourced from Yaml
** Introductions
[[./easy_logo.png]]
** Introduction
=easy= is a command line utility which generates artifacts typically
used in accounting (but also other fields of business like invoicing)
......@@ -8,18 +10,18 @@ based on events provided as [[https://yaml.org/][YAML]] files.
** Overview
In principle easy is used to transform the business events given in
In principle =easy= is used to transform the business events given in
YAML into other business artifacts like invoices (PDF documents) or
journal files for use with [[https://www.ledger-cli.org/][ledger]] (a command line utility for plain
text accounting.) Processing of events happens in 5 steps:
1. Read input events
2. Check input events against spec
3. Augment input events
3.1. Calculate drived values
3.2. Resolve related events
4. Check augmented event against spec
5. Render event(s) through templates
1. Read input events
2. Check input events against spec
3. Augment input events
1. Calculate derived values
2. Resolve related events
4. Check augmented event against spec
5. Render event(s) through templates
** Inputs
......@@ -65,45 +67,131 @@ like.
** Install
*** lumo via npm
Easy runs on [[http://lumo-cljs.org/][lumo]] and uses node packages available via [[https://www.npmjs.com/][npm]], as well as
ClojureScript packages available via [[https://clojars.org/][clojars]] (maven).
Hence you will need to install the npm dependencies via =npm install=.
*** clojars via Clojure's CLI
ClojureScript dependencies tracked in =deps.edn= are installed via
=clj= (aka. Clojure CLI). Please install =clj= as described [[https://clojure.org/guides/deps_and_cli][here]].
Additionally [[https://github.com/kislyuk/yq][yq]] is like [[https://stedolan.github.io/jq/][jq]] for YAML, it is actually a wrapper around
jq. It comes in really handy if working with multiple YAML files.
*** Debian packages
#+BEGIN_SRC sh
sudo apt install python-pip
pip install yq
#+END_SRC
To render invcoice via latex you need to have at least the follwoing
packages installed (Debian naming):
- texlive-latex-base
- texlive-latex-recommended
** Usage
Easy provides two command line utilities: =easy= itself and =collect=.
Here are some examples on how to use these.
You have to have some files in place in order to use easy. Please find
the example directory of this repo and to run these examples.
*** Examples
Render ledger entries from events and run the through ledger to create
a balance:
=easy ledger example.yml | ledger bal -f -=
=easy ledger -i events/invoices.yml | ledger bal -f -=
Render invoice 18.2.1 to latex:
=easy invoice example.yml 18.2.1=
=easy invoice -i events/invoices.yml -n 1.1.1=
Sidenote: Easy invoice identifiers (invoice-no) are divided into three
segments ~<customer-id>.<invoice-number>.<version>~. In events thei
can be given as =invoice-no= in aggregated form or separately as
=customer=, =number=, and =version=.
Just run a transform to see the transformed events, which is handy for
Run a transform to see the transformed events, which is handy for
writing templates:
=easy transform example.yml=
=easy transform -i events/invoices.yml=
Or, just validate the input and exit:
=easy validate -i events/invoices.yml=
Easy alternatively takes events via STDIN:
=cat events/invoices.yml | easy transform=
This comes in particularly handy, when working with multiple event
sources (i.e. YAML files)
=cat events/*.yml | easy ledger | ledger -f - bal=
(Please be ware that concatinating YAML files for easy only works if
the files lack the YAML's document prefix =---=. The reason for this
is explained in "On Frontmatter Templates". And it doens't really
matter as you won't be using =cat= anyways, just keep reading.)
Finally easy comes with its own utility to collect multiple event
sources into a single event stream. Given a root directory for events
it will find all files matching =*.yml=, load these, annotate each
event with its origin (for locating issues quickly), and outputs a
sorted stream of events.
=collect events | easy ledger -y 2019=
Yes, you guessed it, you can use =-y <year>= to filter events by year.
** On Frontmatter Templates
A typical event source for easy might look like this:
#+BEGIN_SRC yaml
- type: expense
account: Aufwand:6940-Bankspesen
payer: Joint
amount: 5
date: 2018-05-31
description: Bankgebühren
- type: expense
account: Aufwand:6940-Bankspesen
payer: Joint
amount: 5
date: 2018-06-30
description: Bankgebühren
#+END_SRC
Imaging the file going on like this. These are monthly occurring
events with very high redundancy. In these cases you might want to use
=collect='s (and =easy='s) capability to work with frontmatter
templates. This allows you to define common attributes of the list of
events as a template using multiple YAML documents in one YAML file.
That way you store the same information by writing:
#+BEGIN_SRC yaml
---
type: expense
account: Aufwand:6940-Bankspesen
payer: Joint
description: Bankgebühren
---
- date: 2018-05-31
amount: 5
- date: 2018-06-30
amount: 5
#+END_SRC
Neat, isn't it?
** On Resolve & Context
** Resolve & Context
This does only concern you if you are developing easy.
Easy uses a multimethod =transform= to transform events into a
/usable/ form. /Usable/ meaning it has all the details calculated and
associated data added to be used in a template.
/augmented/ form. /Augmented/ meaning it has all the details
calculated and associated data added to be used in a template.
The transformation of a single event might happen within a =context=.
The =context= is the set of all events within a processing run.
......@@ -111,12 +199,13 @@ The =context= is the set of all events within a processing run.
are lists of events and the keys are their corresponding =type=. This
is for convenience because in almost all cases you only want to have
events of a single =type= when using the context to resolve associated
events.)
events. E.g. for a given invoice you want to resolve its settlement,
or the other way round.)
Associated data is added via resolve-fns. The resolve-fns use the
context to lookup other events. As the context contains only "mildy"
and not fully transformed events the resolve-fn will very likely have
to transform the resolved event in order to make it usable. If this
to transform the resolved event in order to make it augmented. If this
would mean that another resolve-fn is triggerd this will likely
trigger an endless recursion of resolves.
......
#!/bin/sh
# the classpath usually doesn't change, hence it can be cached, which
# saves quite some time, because we don't need to fire up a jvm just
# to establish a classpath
BASEDIR=$(dirname "$0")/..
KLASSPATHFILE=./.classpath
if [ ! -f $KLASSPATHFILE ]; then
KLASSPATH=$(cd "$BASEDIR" || exit 1; clj -Spath)
echo "${BASEDIR}/src:${KLASSPATH}" > $KLASSPATHFILE
fi
KLASSPATH=$(cat $KLASSPATHFILE)
export NODE_PATH=$BASEDIR/node_modules
exec $BASEDIR/node_modules/.bin/lumo -K -c "$KLASSPATH" -m easy.collect $@
......@@ -15,4 +15,4 @@ fi
KLASSPATH=$(cat $KLASSPATHFILE)
export NODE_PATH=$BASEDIR/node_modules
exec lumo -K -c "$KLASSPATH" -m easy.core $@
exec $BASEDIR/node_modules/.bin/lumo -K -c "$KLASSPATH" -m easy.core $@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24.318129mm"
height="24.318129mm"
viewBox="0 0 24.318129 24.318129"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="easy_logo.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.2708281"
inkscape:cx="455.73674"
inkscape:cy="-92.546847"
inkscape:document-units="mm"
inkscape:current-layer="text4487"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="2556"
inkscape:window-height="1381"
inkscape:window-x="2560"
inkscape:window-y="57"
inkscape:window-maximized="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-38.849343,-129.73373)">
<g
aria-label="easy"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:125%;font-family:Consolas;-inkscape-font-specification:Consolas;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text4487">
<path
d="m 43.365807,139.29104 q 0.518143,0 0.953603,0.17087 0.43546,0.16537 0.749653,0.48507 0.314192,0.3142 0.490581,0.77722 0.176389,0.46302 0.176389,1.05833 0,0.15985 -0.01654,0.26458 -0.01654,0.0992 -0.05512,0.15986 -0.03307,0.0606 -0.09922,0.0882 -0.06063,0.022 -0.15434,0.022 h -3.274219 q 0.03307,0.39687 0.143316,0.68902 0.110243,0.29214 0.292144,0.47955 0.181902,0.18742 0.429948,0.28112 0.248047,0.0882 0.551216,0.0882 0.303168,0 0.523654,-0.0717 0.225998,-0.0772 0.391363,-0.15985 0.170877,-0.0882 0.303168,-0.15985 0.132292,-0.0772 0.259072,-0.0772 0.15434,0 0.253559,0.12678 l 0.402387,0.51814 q -0.225998,0.26458 -0.501606,0.44097 -0.275608,0.17088 -0.573264,0.27561 -0.292144,0.0992 -0.595312,0.14331 -0.303169,0.0441 -0.584289,0.0441 -0.567751,0 -1.058333,-0.18741 -0.490582,-0.18742 -0.854384,-0.55673 -0.363802,-0.37483 -0.573264,-0.92053 -0.203949,-0.55121 -0.203949,-1.27331 0,-0.55672 0.181901,-1.04731 0.181901,-0.49609 0.518142,-0.85989 0.341754,-0.36932 0.826823,-0.58429 0.48507,-0.21497 1.096918,-0.21497 z m 0.02756,0.9977 q -0.534679,0 -0.837847,0.31419 -0.303168,0.30868 -0.391363,0.87643 h 2.315104 q 0,-0.23702 -0.06614,-0.452 -0.06063,-0.21497 -0.198438,-0.38033 -0.132292,-0.16537 -0.336241,-0.25908 -0.20395,-0.0992 -0.48507,-0.0992 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:11.28888893px;font-family:Carlito;-inkscape-font-specification:Carlito;fill:#ff0000;stroke-width:0.26458332px"
id="path4529" />
<path
d="m 50.432388,144.8528 q -0.198438,0 -0.303169,-0.0551 -0.104731,-0.0606 -0.165364,-0.23703 l -0.121268,-0.3638 q -0.209462,0.1819 -0.402387,0.31971 -0.192925,0.1378 -0.402387,0.23151 -0.20395,0.0937 -0.440972,0.1378 -0.231511,0.0496 -0.518143,0.0496 -0.352777,0 -0.644922,-0.0937 -0.292144,-0.0992 -0.507118,-0.28663 -0.209461,-0.18741 -0.325217,-0.46302 -0.115755,-0.28112 -0.115755,-0.64492 0,-0.30317 0.15434,-0.60634 0.154341,-0.30317 0.523655,-0.5457 0.374826,-0.24805 0.992187,-0.4079 0.622874,-0.16536 1.548915,-0.18741 v -0.29215 q 0,-0.52916 -0.220486,-0.77721 -0.220486,-0.24805 -0.633897,-0.24805 -0.308681,0 -0.51263,0.0717 -0.198438,0.0717 -0.352778,0.15985 -0.154341,0.0827 -0.286632,0.15434 -0.132292,0.0717 -0.297656,0.0717 -0.143316,0 -0.248047,-0.0717 -0.09922,-0.0772 -0.159853,-0.1819 l -0.253559,-0.44097 q 0.474045,-0.44097 1.047309,-0.65595 0.573264,-0.21497 1.240235,-0.21497 0.479557,0 0.859895,0.15985 0.380339,0.15434 0.644922,0.44097 0.264584,0.28112 0.402387,0.67249 0.137804,0.39136 0.137804,0.85989 v 3.4451 z m -1.91823,-0.87092 q 0.374827,0 0.644922,-0.13229 0.275608,-0.13781 0.545703,-0.41893 v -0.88194 q -0.545703,0.0221 -0.909505,0.0937 -0.35829,0.0661 -0.573264,0.17638 -0.214974,0.10473 -0.30868,0.24805 -0.08819,0.14332 -0.08819,0.30868 0,0.33073 0.181901,0.46853 0.187414,0.13781 0.507118,0.13781 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:11.28888893px;font-family:Carlito;-inkscape-font-specification:Carlito;fill:#ff0000;stroke-width:0.26458332px"
id="path4531" />
<path
d="m 55.520104,140.48166 q -0.05512,0.0937 -0.121267,0.13229 -0.06063,0.0331 -0.154341,0.0331 -0.09922,0 -0.209461,-0.0496 -0.104731,-0.0551 -0.237023,-0.11576 -0.126779,-0.0661 -0.292144,-0.11575 -0.165365,-0.0551 -0.380339,-0.0551 -0.330729,0 -0.51263,0.15434 -0.181901,0.14883 -0.181901,0.40239 0,0.17088 0.104731,0.28663 0.104731,0.11025 0.275608,0.19844 0.176389,0.0827 0.391363,0.15434 0.220486,0.0717 0.451996,0.15434 0.23151,0.0827 0.446484,0.19844 0.220487,0.11024 0.391363,0.27561 0.176389,0.16536 0.28112,0.40238 0.104731,0.23703 0.104731,0.56776 0,0.39687 -0.137804,0.73311 -0.137804,0.33624 -0.407899,0.57878 -0.264583,0.24253 -0.661458,0.38034 -0.391363,0.1378 -0.909506,0.1378 -0.264583,0 -0.523654,-0.0496 -0.259071,-0.0496 -0.496094,-0.1378 -0.237023,-0.0937 -0.446484,-0.21498 -0.20395,-0.12126 -0.352778,-0.26458 l 0.325217,-0.52917 q 0.06063,-0.0937 0.143316,-0.14882 0.08268,-0.0551 0.214974,-0.0551 0.121267,0 0.225998,0.0661 0.110243,0.0661 0.237023,0.14883 0.126779,0.0772 0.303168,0.14331 0.176389,0.0662 0.440972,0.0662 0.198438,0 0.336242,-0.0496 0.143316,-0.0496 0.225998,-0.13229 0.08819,-0.0882 0.126779,-0.19844 0.0441,-0.11024 0.0441,-0.226 0,-0.24253 -0.181901,-0.37482 -0.181901,-0.13781 -0.457509,-0.23703 -0.275608,-0.0992 -0.595313,-0.20395 -0.314192,-0.10473 -0.5898,-0.28663 -0.275608,-0.1819 -0.457509,-0.47955 -0.181901,-0.29766 -0.181901,-0.78824 0,-0.34176 0.12678,-0.64492 0.126779,-0.30869 0.374826,-0.5402 0.253559,-0.23151 0.622874,-0.36931 0.374826,-0.1378 0.87092,-0.1378 0.270095,0 0.523654,0.0496 0.253559,0.0496 0.474045,0.14331 0.225999,0.0882 0.4079,0.21498 0.187413,0.12678 0.330729,0.2756 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:11.28888893px;font-family:Carlito;-inkscape-font-specification:Carlito;fill:#ff0000;stroke-width:0.26458332px"
id="path4533" />
<path
d="m 58.557301,146.33557 q -0.06063,0.14331 -0.159853,0.21497 -0.09371,0.0772 -0.286631,0.0772 h -1.052822 l 0.975651,-2.20486 -2.033984,-5.04362 h 1.22921 q 0.170877,0 0.253559,0.0772 0.08819,0.0772 0.132292,0.17639 l 0.915017,2.70647 q 0.06063,0.14882 0.104731,0.29765 0.0441,0.14883 0.08819,0.29766 0.0441,-0.15434 0.09371,-0.30317 0.04961,-0.15434 0.110243,-0.30317 l 0.854384,-2.69544 q 0.03858,-0.11024 0.143316,-0.1819 0.104731,-0.0717 0.23151,-0.0717 h 1.118967 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:11.28888893px;font-family:Carlito;-inkscape-font-specification:Carlito;fill:#ff0000;stroke-width:0.26458332px"
id="path4535" />
</g>
<circle
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path4489"
cx="51.008408"
cy="141.89279"
r="11.659064" />
<path
style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 42.55422,137.72885 H 59.662547"
id="path4491"
inkscape:connector-curvature="0" />
<path
style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 42.55927,146.49918 H 55.605896"
id="path4491-0"
inkscape:connector-curvature="0" />
</g>
</svg>
---
customers: customers.yml
coverage-tolerance: 0.02
respect-tax-rate:
- rate: 0.077
vat-tax-rate-in:
- rate: 0.08
until: 2017-12-31
- rate: 0.077
since: 2018-01-01
vat-tax-rate-out:
- rate: 0.061
until: 2017-12-31
- rate: 0.059
since: 2018-01-01
templates:
ledger:
invoice: templates/invoice.dat.hbs
settlement: templates/settlement.dat.hbs
output:
overview: templates/overview.txt.hbs
invoice:
report:
template: templates/report.txt.hbs
latex:
template: templates/invoice.tex.hbs
directory: 'customers/{{customer.name}}'
filename: '{{iso-date}}_{{replace invoice-no "." "_"}}.tex'
# this is where the .lco files are
texinputs-directory: templates
* Example
The following command should create an invoice (PDF) in
=customers/schaf=.
#+BEGIN_SRC shell
../bin/collect events | ../bin/easy invoice -n 1.1.1
#+END_SRC
And this will show the balance:
#+BEGIN_SRC shell
../bin/collect events | ../bin/easy -y 2019 ledger | ledger -f - bal
#+END_SRC
---
# - `name` is used for the path to store files associated with a
# customer.
# - `year` is the year the customer received its first invoice.
# - `number` is a running sequence.
# - `contact` is the primary contact for the given customer
# and is used to select a preset for the invoices.
- name: schaf
year: 2019
number: 1
address: |
Familie Schaf
Auf der grünen Weide 1
54321 Schäferhausen
contact: info
- type: invoice
date: 2019-01-18
description: "Interne Beschreibung"
invoice-no: 1.1.1
items:
- rate: 200.0
hours: 8.0
beneficiary: Coworker1
header: >-
Bitte zahlt bald!
footer: >-
Uns geht das Geld aus.
deadline: 14
- type: settlement
date: 2019-02-18
description: Interne Beschreibung
invoice-no: 1.1.1
amount: 1723.20
; -*- mode: ledger -*-
; «utf8», file: {{ledger-template}}
{{iso-date}} * ({{uuid}}) {{#if deferral}}TA{{/if}} > R-{{invoice-no}} {{description}}
Ertrag:3400-Dienstleistungsertrag:T-{{tax-period}}:P-{{period}}
Aktiva:1100-Forderungen-aus-Lieferungen-und-Leistungen {{gross-total}}
{{#if deferral}}
; the invoice is not yet settled, hence we will make temporary
; bookings for profit centers, but we will only book 90% to account
; for "Delkredere"
{{#each items}}
{{../iso-date}} * ({{uuid}}) R-{{../invoice-no}}/{{beneficiary}} ({{hours}}x{{rate}}) prov. 90%
(ProfitCenter:{{beneficiary}}) {{amount-with-delcredere}}
{{/each}}
{{iso-date}} * ({{uuid}}) TP R-{{invoice-no}} Verbindl. Mwst
Ertrag:3809-Saldosteuer {{tax-out}}
Passiva:2300-Passive-Rechnungsabgrenzung
{{/if}}
\documentclass[letter_{{customer.contact}}]{scrlttr2}
\setkomavar{yourref}{}
\setkomavar{yourmail}{}
\setkomavar{myref}{}
\setkomavar{customer}{ {{~customer.year-number~}} }
\setkomavar{invoice}{ {{~invoice-no~}} }
%\setkomavar{specialmail}{Einschreiben}
\setkomavar{date}{ {{~iso-date~}} }
\setkomavar{subject}{Rechnung}
\setlength{\parindent}{0pt}
\begin{document}
\begin{letter}
{ {{~customer.address-for-latex~}} }
\opening{}
{{#if header}}{{{header}}}\bigskip{{/if}}
{
\renewcommand{\arraystretch}{1}
\begin{tabularx}{\textwidth}{rlXlr}
Nr. & Datum & Leistung & Einheit & Betrag\\
\hline
\hline
{{#each items}}
{{add @index 1}} &
{{../iso-date}} &
Beratung {{beneficiary}} ({{rate}} CHF/Std.) &
{{hours}} Std. &
CHF {{toFixed amount 2}}\\
{{/each}}
\hline
& & Summe & & CHF {{toFixed net-total 2}}\\
{{#if discount}}
& & Rabatt & {{discount}}\% & CHF -{{toFixed discount-amount 2}}\\
& & Zwischensumme & & CHF {{toFixed sub-total 2}}\\
{{/if}}
& & MwSt Betrag & {{multiply tax-rate-in 100}}\% & CHF {{toFixed tax-in 2}} \\
\hline
& & \textbf{Rechnungstotal} & & \textbf{CHF {{toFixed gross-total 2 ~}} }\\
\end{tabularx}
}
\vspace{5mm}
Zahlungsfrist: {{deadline}} Tage
\vspace{5mm}
{{{footer}}}
{{#each items}}
{{#if timesheet-prepared}}
\begin{minipage}{\textwidth}
\textbf{Beratung {{beneficiary~}} }
\begin{center}
\begin{tabularx}{\textwidth}{rXr}
Datum & Beschreibung & Std.\\
\hline
{{#each timesheet-prepared}}
{{./date}} &
{{{description}}} &
{{duration}}\\
{{/each}}
\hline
& Gesamt & {{sum-hours}}\\
\end{tabularx}
\quad\vspace{1cm}
\end{center}
\end{minipage}
{{/if}}
{{/each}}
\closing{Mit freundlichen Grüssen}
\end{letter}
\end{document}
\ProvidesFile{brief.lco}[2002/07/09 v0.9a LaTeX2e unsupported letter-class-option]
\usepackage{graphicx}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage{lmodern}
\usepackage{tabularx}
\setkomavar{fromname}{Hausverwaltung Raffzahn GmbH}
\newcommand\addrsecrow{}
\newcommand\rechtsform{}
\setkomavar{fromaddress}{Abzocker-Str. 666\\XX-12345 Fassohneboden}
%\setkomavar{fromphone}{Tel: +1 555 555 55 55}
\setkomavar{fromfax}{}
\setkomavar{fromemail}{info@example.com}
%\setkomavar{signature}{}
\newcommand\ustid{XXX-666.666.666 MWST}
\setkomavar{frombank}{Bankverbindung\\
Finanzkrisebank\\
%Bankenclearing-Nr. (BC-Nr.) ???\\
Bankkonto-Nr. 66-666666-6\\
IBAN XX66 0000 0000 0000 6666 6
}
%\KOMAoptions{fromlogo=true}
%\setkomavar{fromlogo}{\includegraphics[width=5in,height=1cm]{200ok_logo.png}}
%\pagestyle{myheadings}
%\@addtoplength{firstfootvpos}{1mm}
%\@setplength{firstheadvpos}{12mm}
%\addtolength{\textheight}{15mm}
\@addtoplength{firstfootvpos}{-8mm}
\setkomafont{backaddress}{\scriptsize}
\typeout{\scdefault}
\DeclareFixedFont{\fa}{\encodingdefault}{cmr}{m}{\scdefault}{8}
\DeclareFixedFont{\cc}{\encodingdefault}{cmr}{m}{\scdefault}{30}
\firsthead{\hfill Logo}
\firstfoot{
\scriptsize{
\parbox{\useplength{firstfootwidth}}{
\rule{170mm}{0.5pt}
\begin{tabular}{ll}
\usekomavar{fromname}\\
%\rechtsform\\
\usekomavar{fromaddress}\\
\end{tabular}\hfill
\begin{tabular}{cc}
\usekomavar{fromemail}\\
\usekomavar{fromphone}\\
\usekomavar{fromfax}\\
\ustid
\end{tabular}\hfill
\begin{tabular}{rr}
\usekomavar{frombank}\\
\end{tabular}
}}
}
\nextfoot{
\parbox{\useplength{firstfootwidth}}{
\begin{tabular}{ll}
\usekomavar{fromname}
\end{tabular}\hfill
\begin{tabular}{cc}
\today
\end{tabular}\hfill
\begin{tabular}{rr}
\thepage
\end{tabular}
}
}
\endinput
Easy generated invoice: {{invoice-no}}
DETAILS
Customer name: {{customer.name}}
Customer number: {{customer.year-number}}
Customer contact: {{customer.contact}}
Invoice date: {{iso-date}}
Period: {{period}}
Payment deadline: {{deadline}}
{{#if items}}
Items
{{#each items}}
{{hours}}h x {{rate}} CHF/h {{beneficiary}} CHF {{amount}}
{{/each}}
{{/if}}
Net total: CHF {{net-total}}
Tax (Incoming): CHF {{tax-in}}
Gross total: CHF {{gross-total}}
ARTIFACTS
TEX: {{latex-directory}}/{{latex-filename}}
PDF: {{latex-directory}}/{{replace latex-filename ".tex" ".pdf"}}
COMMANDS
{{{pdflatex-cmd}}}
; -*- mode: ledger -*-
; «utf8», file: {{ledger-template}}
{{iso-date}} * ({{uuid}}) < R-{{invoice-no}} {{invoice/description}}
Aktiva:1100-Forderungen-aus-Lieferungen-und-Leistungen
Aktiva:1010-Postfinance {{amount}}
(ProfitCenter:Eingang) {{amount}}
{{iso-date}} * ({{uuid}}) R-{{invoice-no}} {{invoice/description}}
Passiva:2201-Abrechnungskonto-MWST:{{period}}:MWST
Ertrag:3809-Saldosteuer {{tax-out}}
{{iso-date}} * ({{uuid}}) Verbindlichkeit Mwst
[ProfitCenter:Eingang]
[ProfitCenter:Steuer] {{tax-out}}
{{#if tax-win}}
{{iso-date}} * ({{uuid}}) Profit d. Saldoverfahren
[ProfitCenter:Eingang]
[ProfitCenter:Research] {{tax-win}}
{{/if}}
{{#each distribution}}
{{../iso-date}} * ({{uuid}}) R-{{../invoice-no}}/{{beneficiary}} ({{hours}}x{{rate}})
[ProfitCenter:Eingang]
[ProfitCenter:{{beneficiary}}] {{amount}}
{{/each}}
{{#if remaining}}
{{iso-date}} * ({{uuid}}) Abweichung R-{{invoice-no}}
Aktiva:1100-Forderungen-aus-Lieferungen-und-Leistungen
Ertrag:3800-Verluste-Forderungen {{remaining}}
{{/if}}
......@@ -1055,6 +1055,12 @@
"log-utils": "^0.2.1"
}
},
"lumo-cljs": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/lumo-cljs/-/lumo-cljs-1.10.1.tgz",
"integrity": "sha512-pqgygbEEnzOjFUxejr/jK7gRhuQx0acd3PLyJwkz4ZyVHWyzGGhUxwzgYX/df4wKm7Zixfp73G0S0PFXiNHULQ==",
"dev": true
},
"map-cache": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
......
......@@ -21,5 +21,8 @@
"js-yaml": "^3.12.0",
"sprintf-js": "^1.1.2",
"sync-exec": "^0.6.2"
},
"devDependencies": {
"lumo-cljs": "^1.10.1"
}
}
(ns easy.collect
(:require [lumo.util :as lumo]
[easy.util :as util]
[easy.log :as log]
[clojure.tools.cli :refer [parse-opts]]
[cljs.pprint :refer [pprint]]
[cljs.spec.alpha :as s]
[clojure.string :refer [join]]))
(def cli-options
[;; ["-d" "--debug" "Debug output"]
])
(defn- read-and-parse
"Reads & parses YAML files (incl. applying any frontmatter event
templates & source annotation)."
[path]
(-> path
util/slurp
util/parse-yaml
(util/annotate path)))
(defn- harmonize [events]
(map (partial util/harmonize-date-field :date) events))
(defn -main
[& args]
(let [cli (parse-opts args cli-options)
path (or (-> cli :arguments first) ".")
options (-> cli :options)]
(->> path
lumo/file-seq
(filter #(re-matches #".+\.yml$" %))
(map read-and-parse)
(apply concat)
harmonize
(sort-by :date)
util/write-yaml
println)))
......@@ -10,63 +10,50 @@
(def match-iso-date (partial re-matches #"^\d{4}-\d\d-\d\d$"))