Skip to content

Commit 208e220

Browse files
authored
Merge pull request #52 from Pitastic/docker-deployment
Docker deployment
2 parents 98c51e2 + 4599a5e commit 208e220

38 files changed

Lines changed: 374 additions & 161 deletions

Dockerfile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FROM ubuntu:24.04
2+
3+
RUN apt update && apt install python3.12-venv apache2 apache2-utils libapache2-mod-wsgi-py3 python3-pip -y
4+
5+
COPY . /app
6+
WORKDIR /app
7+
8+
RUN /usr/bin/python3.12 -m venv .venv
9+
RUN . .venv/bin/activate && \
10+
.venv/bin/python3.12 -m pip install --upgrade pip && \
11+
.venv/bin/python3.12 -m pip install -r requirements.txt
12+
13+
RUN sed -i -E s"|(DATABASE_BACKEND = )('tiny').*$|\1'mongo'|" app/config.py
14+
RUN sed -i -E s"|(DATABASE_URI = )('/tmp').*$|\1'mongodb://mongo:27017'|" app/config.py
15+
RUN sed -i -E s"|(DATABASE_NAME = )('testdata.json').*$|\1'pynanceparser'|" app/config.py
16+
17+
RUN cp docker/apache2.conf /etc/apache2/sites-available/pynanceparser.conf
18+
RUN a2ensite pynanceparser && a2dissite 000*
19+
RUN ln -sf /dev/stdout /var/log/apache2/access.log && \
20+
ln -sf /dev/stdout /var/log/apache2/error.log
21+
22+
EXPOSE 80
23+
24+
ENTRYPOINT ["/app/docker/entrypoint.sh"]

Models.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
'uuid': str, # (generated)
3939
'date_tx': int, # (UTC)
4040
'text_tx': str,
41-
'betrag': float,
41+
'amount': float,
4242
'peer': str,
4343
4444
----------- optional -----------
@@ -75,7 +75,7 @@ Klassifiziert das Objekt als Regel für das Parsing.
7575

7676
Frei wählbarer Name der Regel.
7777

78-
#### .regex, r-str (optional)
78+
#### .regex, r-str
7979

8080
Regex String, der auf den Buchungstext angewendet werden soll. Er muss genau eine Matching-Group enthalten. Der Wert dieses Treffers (der Gruppe) wird als Wert mit dem Namen der Regel in der Transaktion als Ergebnis gespeichert.
8181

README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,24 @@ Analyse und Darstellung von Kontoumsätzen bei mehreren Banken.
99

1010
## Get Started
1111

12-
### Setup
12+
Am einfachsten mit Docker:
13+
14+
```
15+
git clone https://github.com/Pitastic/PynanceParser.git
16+
cd PynanceParser
17+
docker compose build
18+
docker compose up -d
19+
```
20+
21+
Bei Updates kann das Docker Image neu gebaut und gestartet werden:
22+
23+
```
24+
git pull
25+
docker compose build
26+
docker compose down && docker compose up -d
27+
```
28+
29+
### Standalone non-Docker Setup
1330

1431
```
1532
python3.12 -m venv .venv
@@ -111,7 +128,7 @@ Für diesen Zweck gibt es die Möglichkeit im Frontend Regeln auszuprobieren, oh
111128

112129
- Erstelle einen Fork des Repositories
113130
- Erstelle Testdaten, auf die die neuen Regeln treffen können
114-
- (am einfachsten ist eine JSON Datei wie `tests/commerzbank.json`)
131+
- (am einfachsten ist eine JSON Datei wie `tests/input_commerzbank.json`)
115132
- Erstelle einen Test wie in (`test_unit_handler_Tags.py`: `test_parsing_regex()`)
116133
- Tests helfen beim entwickeln, können aber auch durch die Maintainer während des Pull Request erstellt werden
117134
- Stelle einen Pull Request

app/config.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
#!/usr/bin/python3
22
"""App Settings zum Zeitpunkt der Initalisierung von PynanceParser"""
33

4-
4+
# Logging (will also log in webserver logs if used via wsgi)
55
LOG_ACCESS_FILE = '/tmp/pynance_access.log'
66
LOG_ERROR_FILE = '/tmp/pynance_error.log'
77

88
# Options:
9-
DATABASE_BACKEND = 'tiny'
10-
#DATABASE_BACKEND = 'mongo'
9+
DATABASE_BACKEND = 'tiny' # or 'mongo'
1110

12-
#DATABASE_URI = 'mongodb://testuser:testpassword@localhost:27017' # For mongo (URI)
13-
DATABASE_URI = '/tmp' # For tiny (/path/to/)
11+
# For tiny: Path to the Folder (/path/to)
12+
# For mongo: MongoDB URI
13+
DATABASE_URI = '/tmp' # or 'mongodb://testuser:testpassword@localhost:27017'
1414

1515
# For tiny: Filename ('testdata.json')
1616
# For mongo: Collection name ('testdata')
17-
DATABASE_NAME = 'testdata.json'
17+
DATABASE_NAME = 'testdata.json' # or 'testdata'

app/routes.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,16 @@ def iban(iban) -> str:
5757
Args (uri):
5858
iban, str: IBAN zu der die Einträge angezeigt werden sollen.
5959
text, str (query): Volltextsuche im Betreff mit RegEx Support
60-
peer, str (query): Volltextsuche im Gegenkonto mit RegEx Support
60+
peer, str (query): Volltextsuche im Gegenkonto mit RegEx Support
6161
startDate, str (query): Startdatum (Y-m-d) für die Anzeige der Einträge
6262
endDate, str (query): Enddatum (Y-m-d) für die Anzeige der Einträge
6363
category, str (query): Kategorie-Filter
6464
tag, str (query): Tag-Filter, einzelner Eintrag oder kommagetrennte Liste
6565
tag_mode, str (query): Vergleichsmodus für Tag-Filter (siehe Models.md)
66-
betrag_min, float (query): Betragsfilter (größer gleich betrag_min)
67-
betrag_max, float (query): Betragsfilter (kleiner gleich betrag_max)
66+
amount_min, float (query): Betragsfilter (größer gleich amount_min)
67+
amount_max, float (query): Betragsfilter (kleiner gleich amount_max)
6868
page, int (query): Seite für die Paginierung (default: 1)
69+
descending, bool (query): Sortierreihenfolge nach Datum (default: True)
6970
Returns:
7071
html: Startseite mit Navigation
7172
"""
@@ -77,7 +78,8 @@ def iban(iban) -> str:
7778

7879
# Table with Transactions
7980
current_app.logger.debug(f"Using condition filter: {condition}")
80-
rows = parent.db_handler.select(iban, condition)
81+
sort_order = request.args.get('descending', 'true').lower() == 'true'
82+
rows = parent.db_handler.select(iban, condition, descending=sort_order)
8183

8284
# If pagination is requested, do not serve the whole page and all metadata
8385
entries_per_page = 50
@@ -168,8 +170,8 @@ def show_stats(iban) -> str:
168170
category, str (query): Kategorie-Filter
169171
tag, str (query): Tag-Filter, einzelner Eintrag oder kommagetrennte Liste
170172
tag_mode, str (query): Vergleichsmodus für Tag-Filter (siehe Models.md)
171-
betrag_min, float (query): Betragsfilter (größer gleich betrag_min)
172-
betrag_max, float (query): Betragsfilter (kleiner gleich betrag_max)
173+
amount_min, float (query): Betragsfilter (größer gleich amount_min)
174+
amount_max, float (query): Betragsfilter (kleiner gleich amount_max)
173175
Returns:
174176
html: Seite mit Grafiken und Statistiken über die slektierten Einträge
175177
(IBAN und optional Query)
@@ -186,12 +188,12 @@ def show_stats(iban) -> str:
186188
# Calculate TOP categories and tags
187189
sums = {'categories': {}, 'tags': {}}
188190
for row in rows:
189-
betrag = row.get('betrag', 0.0)
191+
amount = row.get('amount', 0.0)
190192
cat = row.get('category', 'unkategorisiert')
191193
if cat not in sums['categories']:
192194
sums['categories'][cat] = 0.0
193195

194-
sums['categories'][cat] += betrag
196+
sums['categories'][cat] += amount
195197

196198
tags = row.get('tags', [])
197199
if not tags:
@@ -200,7 +202,7 @@ def show_stats(iban) -> str:
200202
if tag not in sums['tags']:
201203
sums['tags'][tag] = 0.0
202204

203-
sums['tags'][tag] += betrag
205+
sums['tags'][tag] += amount
204206

205207
# Sort Sums
206208
sums['categories'] = dict(sorted(sums['categories'].items(),
@@ -419,7 +421,7 @@ def deleteDatabase(iban):
419421
"""
420422
Leert die Datenbank zu einer IBAN
421423
Args (uri):
422-
iban, str: (optional) IBAN zu der die Datenbank geleert werden soll.
424+
iban, str: IBAN zu der die Datenbank geleert werden soll.
423425
(Default: Primäre IBAN aus der Config)
424426
Returns:
425427
json: Informationen zum Ergebnis des Löschauftrags.

app/server.py

100644100755
Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def create_app(config_path: str) -> Flask:
1818
Returns: FlaskApp
1919
"""
2020
# Logging
21-
loglevel = 'DEBUG'
21+
loglevel = 'INFO'
2222
dictConfig({
2323
'version': 1,
2424
'formatters': {'default': {
@@ -53,10 +53,12 @@ def create_app(config_path: str) -> Flask:
5353

5454
return app
5555

56-
if __name__ == '__main__':
57-
config = os.path.join(
58-
os.path.dirname(os.path.abspath(__file__)),
59-
'config.py'
60-
)
61-
application = create_app(config)
62-
application.run(host='0.0.0.0', port=8110, debug=True)
56+
config = os.path.join(
57+
os.path.dirname(os.path.abspath(__file__)),
58+
'config.py'
59+
)
60+
application = create_app(config)
61+
62+
if __name__ == "__main__":
63+
# Run the application directly if executed as a standalone script
64+
application.run(host='0.0.0.0', port=8000, debug=True)

app/static/css/grid.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
grid-template-rows: 1fr 1fr;
8484
gap: 0.25em;
8585
grid-template-areas:
86-
"checkbox dates category betrag"
86+
"checkbox dates category amount"
8787
"button betreff betreff betreff";
8888
padding: 1em 0;
8989
}
@@ -107,7 +107,7 @@
107107
.transactions tr td:nth-child(4){grid-area: category;}
108108
.transactions tr td:nth-child(6){
109109
padding-right: 0;
110-
grid-area: betrag;
110+
grid-area: amount;
111111
}
112112
.transactions tr td:nth-child(7){
113113
padding-left: 0;

app/static/css/style.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ button.info {
9797
}
9898

9999
/* Tables */
100-
.transactions .betrag {
100+
.transactions .amount {
101101
white-space: nowrap;
102102
text-align: right;
103103
}
@@ -108,7 +108,7 @@ button.info {
108108

109109
/* S : Slim button in transaction table */
110110
@media (max-width: 767px) {
111-
.transactions th.betrag {
111+
.transactions th.amount {
112112
text-align: center;
113113
}
114114
.transactions tr {

app/static/js/functions.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,23 @@ function getFilteredList() {
7474
}
7575
}
7676

77-
let betrag_min = document.getElementById('filter-betrag-min').value;
78-
if (betrag_min) {
79-
betrag_min = betrag_min.replace(',', '.');
80-
query_args = query_args + arg_concat + 'betrag_min=' + betrag_min;
77+
let amount_min = document.getElementById('filter-amount-min').value;
78+
if (amount_min) {
79+
amount_min = amount_min.replace(',', '.');
80+
query_args = query_args + arg_concat + 'amount_min=' + amount_min;
8181
arg_concat = '&';
8282
}
8383

84-
let betrag_max = document.getElementById('filter-betrag-max').value;
85-
if (betrag_max) {
86-
betrag_max = betrag_max.replace(',', '.');
87-
query_args = query_args + arg_concat + 'betrag_max=' + betrag_max;
84+
let amount_max = document.getElementById('filter-amount-max').value;
85+
if (amount_max) {
86+
amount_max = amount_max.replace(',', '.');
87+
query_args = query_args + arg_concat + 'amount_max=' + amount_max;
88+
arg_concat = '&';
89+
}
90+
91+
let sort_order = document.getElementById('filter-descending').value;
92+
if (sort_order) {
93+
query_args = query_args + arg_concat + 'descending=' + sort_order;
8894
arg_concat = '&';
8995
}
9096

app/static/js/iban.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ function fillTxDetails(result) {
115115
td.appendChild(a_link);
116116
}
117117

118-
} else if (key == 'betrag') {
118+
} else if (key == 'amount') {
119119
// Round
120120
td.innerHTML = r[key].toFixed(2);
121121

0 commit comments

Comments
 (0)