This repository was archived by the owner on May 3, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
147 lines (128 loc) · 7.09 KB
/
app.py
File metadata and controls
147 lines (128 loc) · 7.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import argparse
import inspect
import logging
import sys
from datetime import datetime
from src.utils.env_mapper import EnvMapper
from src.firefly_sync_cli import FireflySyncCli
from src.firefly_sync_daemon import FireflySyncDaemon
def init_logging(env_mapper: EnvMapper):
class LoggingModuleNameFilter(logging.Filter):
def filter(self, record):
frame = inspect.currentframe().f_back
while frame is not None:
module = inspect.getmodule(frame)
if module and module != logging:
record.name = module.__name__
break
frame = frame.f_back
return True
handler = logging.StreamHandler(sys.stdout)
handler.addFilter(LoggingModuleNameFilter())
logging.basicConfig(format='[%(asctime)s %(name)s-%(threadName)s %(levelname)s] %(message)s',
level=logging.INFO,
handlers=[handler])
logging_def_str = env_mapper.get('LOGGING')
if logging_def_str is None:
return
logging_def_list = [tuple(item.split(':')) for item in logging_def_str.split(',') if len(item.split(':')) == 2]
for logger_name, level in logging_def_list:
logging.getLogger(logger_name).setLevel(level)
def get_help_format(prog):
class MyFormatter(argparse.HelpFormatter):
"""
Corrected _max_action_length for the indenting of subactions
"""
def add_argument(self, action):
if action.help is not argparse.SUPPRESS:
# find all invocations
get_invocation = self._format_action_invocation
invocations = [get_invocation(action)]
current_indent = self._current_indent
for subaction in self._iter_indented_subactions(action):
# compensate for the indent that will be added
indent_chg = self._current_indent - current_indent
added_indent = 'x'*indent_chg
invocations.append(added_indent+get_invocation(subaction))
invocation_length = max([len(s) for s in invocations])
action_length = invocation_length + self._current_indent
self._action_max_length = max(self._action_max_length, action_length)
# add the item to the list
self._add_item(self._format_action, [action])
return MyFormatter(prog, max_help_position=100)
if __name__ == "__main__":
init_logging(EnvMapper())
parser = argparse.ArgumentParser(formatter_class=get_help_format)
parser.add_argument("--dry-run",
action='store_true',
help="Execute the job as dry-run (it will not persist anything)",
default=False)
jobs = parser.add_subparsers(title='required argument', dest='job', metavar='job', required=True)
# Run as a daemon (used for Dockerfile especially)
parser_daemon = jobs.add_parser('daemon',
help="File watcher listening for transaction files from banks",
formatter_class=get_help_format)
parser_daemon.add_argument("--no-firefly-cron-job",
action='store_true',
help="Prevents Firefly III cron from being executed",
default=False)
parser_daemon.add_argument("--no-stock-cron-job",
action='store_true',
help="Prevents stock accounts to update value. Cron job will not execute",
default=False)
jobs.add_parser('update-stocks',
help="Update all stock accounts",
formatter_class=get_help_format)
# Import a file from your bank
parser_file = jobs.add_parser('tx-import',
help="Import a transaction file from a bank",
formatter_class=get_help_format)
parser_file.add_argument('file', type=str, help='File to be imported')
# Link transactions between banks as transfer
parser_tx_link = jobs.add_parser('tx-link',
help="Links transfer operation between existing accounts (interactive)",
formatter_class=get_help_format)
parser_tx_link.add_argument('--start-date',
help="Specific the start-date to link accounts (format: YYYY-MM-DD)",
type=lambda s: datetime.strptime(s, '%Y-%m-%d'))
parser_tx_link.add_argument('--end-date',
help="Specific the end-date to link accounts (format: YYYY-MM-DD)",
type=lambda s: datetime.strptime(s, '%Y-%m-%d'))
parser_tx_link.add_argument('--amount-diff',
type=float,
help="Acceptable transaction amount difference (in percentage) to link transactions")
parser_tx_link.add_argument('--date-diff',
help="Acceptable transaction date difference (in days) to link transactions",
type=int)
# Categorize transactions
parser_tx_category = jobs.add_parser('tx-category', help="Categorize existing transactions (interactive)")
parser_tx_category.add_argument('--start-date',
help="Specific the start-date to categorize accounts (format: YYYY-MM-DD)",
type=lambda s: datetime.strptime(s, '%Y-%m-%d'))
parser_tx_category.add_argument('--end-date',
help="Specific the end-date to categorize accounts (format: YYYY-MM-DD)",
type=lambda s: datetime.strptime(s, '%Y-%m-%d'))
parser_tx_category.add_argument('--account-ids',
type=str,
help="Account IDs separated by comma (e.g: 3,4,7)",
default="")
args = parser.parse_args()
firefly_sync_cli = FireflySyncCli(args.dry_run)
if args.job == 'daemon':
firefly_sync_daemon = FireflySyncDaemon(firefly_sync_cli, args.no_firefly_cron_job, args.no_stock_cron_job)
firefly_sync_daemon.start()
elif args.job == 'tx-import':
firefly_sync_cli.import_file(args.file)
elif args.job == 'tx-link':
firefly_sync_cli.link_identical_transactions(start_date=args.start_date, end_date=args.end_date,
amount_diff_percentage=args.amount_diff,
date_diff_days=args.date_diff)
elif args.job == 'update-stocks':
firefly_sync_cli.update_stock_accounts()
elif args.job == 'tx-category':
firefly_sync_cli.categorize(
start_date=args.start_date, end_date=args.end_date,
account_ids=[account_id
for account_ids in args.account_ids
for account_id in account_ids.split(',')
if account_id])