#!/bin/sh # file: rechnung.sh # date: 02.05.2021 # user: bernd@nr18.space # desc: Liest verschiedene Kunden und Dienstleistungen aus der Datei # rechnung.ini und erstellt daraus Rechnungen mit Hilfe eines # Latex-Templates. set -u set -e # Benötigte Programme # ------------------- TR_BIN=$(which tr 2>/dev/null || echo "tr") BC_BIN=$(which bc 2>/dev/null || echo "bc") SED_BIN=$(which sed 2>/dev/null || echo "sed") CUT_BIN=$(which cut 2>/dev/null || echo "cut") DATE_BIN=$(which date 2>/dev/null || echo "date") TPUT_BIN=$(which tput 2>/dev/null || echo "tput") PDFLATEX_BIN=$(which pdflatex 2>/dev/null || echo "pdflatex") RUBBER_BIN=$(which rubber 2>/dev/null || echo "rubber") EXECUTABLES_TO_CHECK="$BC_BIN $TR_BIN $SED_BIN $CUT_BIN $TPUT_BIN $DATE_BIN $PDFLATEX_BIN $RUBBER_BIN" GENPDF="" if [ -x "$RUBBER_BIN" ]; then GENPDF="$RUBBER_BIN -d " else GENPDF="$PDFLATEX_BIN -halt-on-error " fi # Variablen definieren # -------------------- PROGRAMM_NAME=$0 PROGRAMM_VERSION="0.0.1" VERBOSITY=0 RECHNUNGSFILE="rechnung.ini" TEMPLATEFILE="template.ltx" SEDFILE="sed.txt" LINE_BUFFER="" KEY_BUFFER="" VALUE_BUFFER="" ERROR=0 KUNDE="" ADRESSE="" ANREDE="" ANZAHL="" POSITION="" SHORT="" BETRAG="" LFDNR="" # Farben definieren # ----------------- NUMBER_OF_COLORS=$($TPUT_BIN colors) COLORED_OUTPUT=0 RED="\\033[1;31m" GREEN="\\033[1;32m" YELLOW="\\033[1;33m" BLUE="\\033[1;34m" NORMAL="\\033[0;39m" # Diverse Checks # -------------- check_readable() { printf "\n[+] Datei \"$1\" ist lesbar ..." if [ -f "$1" ] && [ -r "$1" ] then print_ok else print_failed quit 1 fi } check_binaries() { program="" binaries=$* for program in $binaries; do printf "\n[+] Suche nach Programm $program ..." if [ ! -x "$program" ]; then print_failed printf "\n[-] Das Programm \"$program\" wird benötigt, aber nicht gefunden." quit 3 else print_ok fi done } is_option() ( line="$*" if [ "${line#*=}" != "$line" ]; then return 0 else return 1 fi ) # Ausgaben im Terminal # -------------------- print_failed() { if [ "$COLORED_OUTPUT" -eq 1 ]; then printf "$RED Failed$NORMAL" else printf " Failed" fi } print_ok() { if [ "$COLORED_OUTPUT" -eq 1 ]; then printf "$GREEN OK$NORMAL" else printf " OK" fi } print_warn() { msg=$* if [ "$COLORED_OUTPUT" -eq 1 ]; then echo -e "$YELLOW[-]$NORMAL $msg" else echo -e "[-] $msg" fi } # Whitespaces entfernen # --------------------- trim_line() { set -f set -- "$*" LINE_BUFFER=$(printf '%s' "$*") set +f } trim_key() { set -f set -- "$*" KEY_BUFFER=$(printf '%s' "$*") set +f } trim_value() { set -f set -- "$*" VALUE_BUFFER=$(printf '%s' "$*") set +f } reset_values() { echo -e "\n[+] Initialisiere Felder für Rechnung neu." LINE_BUFFER="" KEY_BUFFER="" VALUE_BUFFER="" ERROR=0 KUNDE="" ADRESSE="" ANREDE="" ANZAHL="" POSITION="" SHORT="" BETRAG="" LFDNR="" } set_value() { key=$(echo "$*" | $CUT_BIN -d "=" -f1) value=$(echo "$*" | $CUT_BIN -d "=" -f2) trim_key "$key" trim_value "$value" case $KEY_BUFFER in kunde) KUNDE="$VALUE_BUFFER";; adresse) ADRESSE="$VALUE_BUFFER";; anrede) ANREDE="$VALUE_BUFFER";; anzahl) ANZAHL="$VALUE_BUFFER";; position) POSITION="$VALUE_BUFFER";; betrag) BETRAG="$VALUE_BUFFER";; lfdnr) LFDNR="$VALUE_BUFFER";; short) SHORT="$VALUE_BUFFER";; *) print_warn "Unbekanntes Feld: $KEY_BUFFER"; ERROR=1;; esac } make_invoice() { dead_days="14" if [ $(date +%u) -gt 5 ]; then dead_days="16" fi month_ascii=$(date '+%B') inv_day=$(date '+%j') inv_date=$(date '+%Y%m%d') inv_dead=$(date -d "+${dead_days}days" '+%d.\\\\,%m.\\\\,%Y') rechnungsnummer="$inv_date--$LFDNR" subject="Rechnung zu $SHORT" filename="$(date '+%Y%m%d')_Rechnung_$(echo "$month_ascii")_$(echo "$KUNDE" | $TR_BIN " " "_").ltx" buffer="$KUNDE; $ADRESSE" anschrift="$(echo "$buffer" | sed 's/; /\\\\\\\\\\\\\\ /g')" echo "[+] Erstelle Rechnung: $filename" echo -n "s!#SUBJECT#!" >$SEDFILE; echo "$subject!" >>$SEDFILE echo -n "s!#ANREDE#!" >>$SEDFILE; echo "$ANREDE!" >>$SEDFILE echo -n "s!#ANSCHRIFT#!" >>$SEDFILE; echo "$anschrift!" >>$SEDFILE echo -n "s!#RECHNUNGSNUMMER#!" >>$SEDFILE; echo "$rechnungsnummer!" >>$SEDFILE echo -n "s!#ANZAHL#!" >>$SEDFILE; echo "$ANZAHL!" >>$SEDFILE echo -n "s!#POSITION#!" >>$SEDFILE; echo "$POSITION!" >>$SEDFILE echo -n "s!#BETRAG#!" >>$SEDFILE; echo "$BETRAG!" >>$SEDFILE echo -n "s!#DEADLINE#!" >>$SEDFILE; echo "$inv_dead!" >>$SEDFILE cp "$TEMPLATEFILE" "$filename" $SED_BIN -i -f "$SEDFILE" "$filename" $GENPDF "$filename" if [ -x "$RUBBER_BIN" ]; then "$RUBBER_BIN" --clean "$filename" fi if [ $? -eq 0 ]; then echo "[+] Rechnung erfolgreich erstellt" else echo "[-] Rechnung fehlgeschlagen" fi } proced_ini_line() { line=$* first=$(echo "$line" | cut -c1-1) # leerzeilen ignorieren if [ "$line" = "" ]; then return # kommentarzeilen ignorieren elif [ "$first" = "#" ]; then return # start einer neuen rechnung elif [ "$line" = "[start]" ]; then reset_values # ende einer rechnung elif [ "$line" = "[ende]" ]; then if [ $ERROR -ne 0 ]; then print_warn "Kunde \"$KUNDE\" enthält einen Fehler. Erstelle keine Rechung." return else make_invoice fi # alle anderen zeilen else is_option "$line" if [ $? -eq 0 ] then set_value "$line" else print_warn "Invalid syntax: $line" fi fi } quit() { printf "\n$BLUE" printf "[-] Exit$NORMAL\n" exit 1 } # --- Programmstart --- # # --------------------- # echo "===================" echo "= Rechnung v$PROGRAMM_VERSION =" echo "===================" # Verschiedene Basic Checks if [ -n "$NUMBER_OF_COLORS" ] && [ "$NUMBER_OF_COLORS" -ge 8 ]; then COLORED_OUTPUT=1 fi if [ "$(id -u)" -eq 0 ]; then echo "$0: Das Skript darf nicht als Root ausgeführt werden." exit 1 fi check_binaries "$EXECUTABLES_TO_CHECK" check_readable "$RECHNUNGSFILE" check_readable "$TEMPLATEFILE" printf "\n" # Kundendatei einlesen und rechnungen erstellen while IFS= read -r rawline do trim_line "$rawline" proced_ini_line "$LINE_BUFFER" done < "$RECHNUNGSFILE"