rechnung/rechnung.sh
2021-05-03 12:56:43 +02:00

303 lines
6.4 KiB
Bash
Executable file

#!/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 -o posix
# 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")
LATEX_BIN=$(which pdflatex 2>/dev/null || echo "pdflatex")
EXECUTABLES_TO_CHECK="$BC_BIN $TR_BIN $SED_BIN $CUT_BIN $TPUT_BIN $DATE_BIN $LATEX_BIN"
# 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() {
local program=""
local 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() (
local 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() {
local 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() {
local key=$(echo "$*" | $CUT_BIN -d "=" -f1)
local 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() {
local month_ascii=$(date '+%B')
local inv_day=$(date '+%j')
local inv_date=$(date '+%Y%m%d')
local inv_dead=$(date -d '+14days' +%d.%m.%Y)
local rechnungsnummer="$inv_date-$LFDNR"
local subject="Rechnung zu $SHORT"
local filename="$(date '+%Y%m%d')_Rechnung_$(echo "$month_ascii")_$(echo "$KUNDE" | $TR_BIN " " "_").ltx"
local buffer="$KUNDE; $ADRESSE"
local 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
$LATEX_BIN -halt-on-error $filename
$LATEX_BIN -halt-on-error $filename
if [ $? -eq 0 ]; then
echo "[+] Rechnung erfolgreich erstellt"
else
echo "[-] Rechnung fehlgeschlagen"
fi
}
proced_ini_line() {
local line=$*
local 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 [ "$EUID" -eq 0 ]; then
echo "$0: Das Skript muss nicht als Root ausfegührt werden."
quit 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