diff --git a/container/plugins/finance/example.bash b/container/plugins/finance/example.bash index b0d55b2..66f1ac3 100755 --- a/container/plugins/finance/example.bash +++ b/container/plugins/finance/example.bash @@ -38,9 +38,12 @@ [ -z "$DOCKER_FINANCE_CONTAINER_REPO" ] && exit 1 source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/lib_finance.bash" +[[ -z "$global_parent_profile" || -z "$global_arg_delim_1" || -z "$global_child_profile" ]] && lib_utils::die_fatal +instance="${global_parent_profile}${global_arg_delim_1}${global_child_profile}" + # Initialize "constructor" -[[ -z "$global_parent_profile" || -z "$global_arg_delim_1" || -z "$global_child_profile" ]] && exit 1 -lib_finance::finance "${global_parent_profile}${global_arg_delim_1}${global_child_profile}" +# NOTE: "constructor" only needed if calling library directly +lib_finance::finance "$instance" || lib_utils::die_fatal # # Implementation @@ -48,14 +51,14 @@ lib_finance::finance "${global_parent_profile}${global_arg_delim_1}${global_chil function main() { - echo -e " + local -r _example=" This container's environment: $(printenv | grep ^DOCKER_FINANCE | sort) This plugin's caller profile: - ${global_parent_profile}${global_arg_delim_1}${global_child_profile} + $instance This plugin's path is: @@ -66,10 +69,11 @@ This plugin's arguments: '${*}' Showing total current BTC balance: + + $(lib_finance::ledger bal assets liabilities cur:BTC | tail -n1) + " - echo -n " " - lib_finance::ledger bal assets liabilities cur:BTC | tail -n1 - echo + lib_utils::print_custom "$_example" } main "$@" diff --git a/container/plugins/finance/timew_to_timeclock.bash b/container/plugins/finance/timew_to_timeclock.bash new file mode 100755 index 0000000..cd7cced --- /dev/null +++ b/container/plugins/finance/timew_to_timeclock.bash @@ -0,0 +1,116 @@ +#!/usr/bin/env bash + +# docker-finance | modern accounting for the power-user +# +# Copyright (C) 2024 Aaron Fiore (Founder, Evergreen Crypto LLC) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation either version 3 of the License or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not see . + +# +# "Libraries" +# + +[ -z "$DOCKER_FINANCE_CONTAINER_REPO" ] && exit 1 +source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/lib_finance.bash" + +[[ -z "$global_parent_profile" || -z "$global_arg_delim_1" || -z "$global_child_profile" ]] && lib_utils::die_fatal +instance="${global_parent_profile}${global_arg_delim_1}${global_child_profile}" + +# Initialize "constructor" +lib_finance::finance "$instance" || lib_utils::die_fatal + +# +# Implementation +# + +lib_utils::deps_check "jq" # *should* be provided by dependency `yq` + +function __format_time() +{ + [[ -z "$1" || -z "$2" ]] && lib_utils::die_fatal + + local -r _direction="$1" + local -r _timestamp="$2" + + # Expects timewarrior *exported* time format + echo -n "$_direction $(echo ${_timestamp:0:4}-${_timestamp:4:2}-${_timestamp:6:2} ${_timestamp:9:2}:${_timestamp:11:2}:${_timestamp:13:2})" +} + +# - Converts exported timewarrior JSON schema into hledger timeclock format +# - Expects the following timewarrior style tags in the format of `key=value` +# +# desc="My Description" +# comment="My Comment" +# tag:type=value +# tag:... +# +# TODO: optimize: export only needed once if the majority of parsing is done within gawk +function main() +{ + # Stop tracking or else format breaks + lib_finance::times stop &>/dev/null + + # Commands and timeclock entries + local -r _cmd=("lib_finance::times" "export") + local -r _count=$("${_cmd[@]}" | jq '. | length') + local _id _start _end _tags + + # Cycle through total count of timewarrior entries + for ((_i = 1; _i <= _count; _i++)); do + + # Parse timewarrior format + local _array=() + while read _line; do + _array+=("$_line") + done < <("${_cmd[@]}" | jq -Mer ".[${_i}-1] | .id,.start,.end") + + local _id="${_array[0]}" + local _start="${_array[1]}" + local _end="${_array[2]}" + + local _tags + _tags="$("${_cmd[@]}" | jq -Mer ".[${_i}-1] | .tags.[]")" + + # Print parsed as timeclock format + __format_time "i" "$_start" + echo "$_tags" \ + | grep -E "(^profile=|^desc=|^comment=|^tag:)" \ + | gawk -F'=' -v _id="$_id" '{ + switch ($1) + { + case "profile": + account=$2 + break + case "desc": + description=$2 + break + case "comment": + comment=$2 + break + default: + # All others are considered "real" tags + tags=substr($0, 5) + sub(/=/, ":", tags) # Reconstruct to hledger tag format + # TODO: push to an array for more tags + break + } + } END { printf " " account " " description " ; " comment ", id:" _id ", " tags "\n"}' + __format_time "o" "$_end" + echo + done +} + +main "$@" + +# vim: sw=2 sts=2 si ai et