monopyly 1.4.8__py3-none-any.whl → 1.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- monopyly/CHANGELOG.md +7 -0
- monopyly/__init__.py +2 -2
- monopyly/_version.py +2 -2
- monopyly/cli/apps.py +1 -1
- monopyly/cli/launch.py +3 -0
- monopyly/common/forms/_forms.py +56 -2
- monopyly/common/transactions.py +162 -0
- monopyly/credit/actions.py +29 -0
- monopyly/credit/forms.py +25 -0
- monopyly/credit/routes.py +97 -7
- monopyly/credit/transactions/_transactions.py +15 -0
- monopyly/credit/transactions/activity/__init__.py +3 -0
- monopyly/credit/transactions/activity/data.py +161 -0
- monopyly/credit/transactions/activity/parser.py +274 -0
- monopyly/credit/transactions/activity/reconciliation.py +456 -0
- monopyly/database/models.py +6 -0
- monopyly/static/css/style.css +1141 -263
- monopyly/static/img/icons/statement-pair.png +0 -0
- monopyly/static/img/icons/statement-thick.png +0 -0
- monopyly/static/img/icons/statement.png +0 -0
- monopyly/static/js/bind-tag-actions.js +1 -1
- monopyly/static/js/create-balance-chart.js +1 -1
- monopyly/static/js/create-category-chart.js +27 -0
- monopyly/static/js/define-filter.js +1 -1
- monopyly/static/js/expand-transaction.js +10 -0
- monopyly/static/js/highlight-discrepant-transactions.js +124 -0
- monopyly/static/js/modules/expand-transaction.js +12 -3
- monopyly/static/js/modules/form-suggestions.js +60 -0
- monopyly/static/js/modules/manage-overlays.js +1 -3
- monopyly/static/js/show-credit-activity-loader.js +29 -0
- monopyly/static/js/toggle-navigation.js +35 -0
- monopyly/static/js/update-card-status.js +1 -1
- monopyly/static/js/use-suggested-amount.js +11 -0
- monopyly/static/js/use-suggested-merchant.js +11 -0
- monopyly/templates/banking/account_page.html +3 -1
- monopyly/templates/banking/account_summaries.html +1 -1
- monopyly/templates/banking/accounts_page.html +11 -15
- monopyly/templates/banking/transactions_table/expanded_row_content.html +18 -20
- monopyly/templates/common/transaction_form/subtransaction_subform.html +10 -1
- monopyly/templates/common/transactions_table/linked_bank_transaction.html +1 -1
- monopyly/templates/common/transactions_table/linked_credit_transaction.html +1 -1
- monopyly/templates/common/transactions_table/transaction_condensed.html +2 -2
- monopyly/templates/common/transactions_table/transaction_expanded.html +3 -3
- monopyly/templates/common/transactions_table/transactions.html +1 -1
- monopyly/templates/core/credits.html +10 -8
- monopyly/templates/core/index.html +10 -0
- monopyly/templates/core/profile.html +1 -1
- monopyly/templates/credit/statement_page.html +33 -0
- monopyly/templates/credit/statement_reconciliation/discrepant_records.html +25 -0
- monopyly/templates/credit/statement_reconciliation/statement_reconciliation_inquiry.html +23 -0
- monopyly/templates/credit/statement_reconciliation/statement_reconciliation_page.html +86 -0
- monopyly/templates/credit/statement_reconciliation/summary.html +45 -0
- monopyly/templates/credit/statement_reconciliation/unrecorded_activities.html +24 -0
- monopyly/templates/credit/statement_summary.html +2 -2
- monopyly/templates/credit/statements.html +1 -1
- monopyly/templates/credit/transaction_form/transaction_form.html +9 -1
- monopyly/templates/credit/transaction_form/transaction_form_page.html +2 -0
- monopyly/templates/credit/transaction_form/transaction_form_page_update.html +9 -0
- monopyly/templates/credit/transaction_submission_page.html +8 -0
- monopyly/templates/credit/transactions_table/expanded_row_content.html +18 -12
- monopyly/templates/layout.html +35 -27
- {monopyly-1.4.8.dist-info → monopyly-1.5.0.dist-info}/METADATA +2 -1
- {monopyly-1.4.8.dist-info → monopyly-1.5.0.dist-info}/RECORD +67 -51
- monopyly/static/img/icons/statement-pair.svg +0 -281
- monopyly/static/img/icons/statement.svg +0 -294
- {monopyly-1.4.8.dist-info → monopyly-1.5.0.dist-info}/WHEEL +0 -0
- {monopyly-1.4.8.dist-info → monopyly-1.5.0.dist-info}/entry_points.txt +0 -0
- {monopyly-1.4.8.dist-info → monopyly-1.5.0.dist-info}/licenses/COPYING +0 -0
- {monopyly-1.4.8.dist-info → monopyly-1.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{% extends "layout.html" %}
|
|
2
2
|
|
|
3
3
|
{% block content %}
|
|
4
|
+
|
|
4
5
|
{% if session["show_homepage_block"] %}
|
|
5
6
|
<div id="homepage-block">
|
|
6
7
|
<div class="buttons">
|
|
@@ -147,7 +148,16 @@
|
|
|
147
148
|
</div>
|
|
148
149
|
|
|
149
150
|
</div>
|
|
151
|
+
{% else %}
|
|
152
|
+
<div id="homepage-suggestion">
|
|
153
|
+
<p class="login">
|
|
154
|
+
<a href="{{ url_for('auth.login') }}">Login</a> to get started.
|
|
155
|
+
</p>
|
|
156
|
+
<p class="register">
|
|
157
|
+
Not yet registered? <a href="{{ url_for('auth.register') }}">Create an account</a> to begin using the app.
|
|
158
|
+
</p>
|
|
150
159
|
{% endif %}
|
|
160
|
+
|
|
151
161
|
{% endblock %}
|
|
152
162
|
|
|
153
163
|
{% block javascript %}
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
<div class="bank-list box-table">
|
|
42
42
|
{% for bank in banks %}
|
|
43
43
|
|
|
44
|
-
<div class="bank-block box-row update-db-widget" data-bank-id="{{ bank.id }}">
|
|
44
|
+
<div class="bank-block box-row action update-db-widget" data-bank-id="{{ bank.id }}">
|
|
45
45
|
|
|
46
46
|
<div class="widget-text">
|
|
47
47
|
<div class="bank widget-display">{{ bank.bank_name }}</div>
|
|
@@ -28,8 +28,13 @@
|
|
|
28
28
|
{% endwith %}
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
|
+
<div id="category-chart-container">
|
|
32
|
+
<div id="category-chart" class="ct-chart ct-octave"></div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
31
35
|
</div>
|
|
32
36
|
|
|
37
|
+
|
|
33
38
|
</div>
|
|
34
39
|
|
|
35
40
|
{% endblock %}
|
|
@@ -44,6 +49,11 @@
|
|
|
44
49
|
<img class="icon" src="{{ url_for('static', filename='img/icons/plus.png') }}" />
|
|
45
50
|
</a>
|
|
46
51
|
</div>
|
|
52
|
+
<div class="button">
|
|
53
|
+
<div class="action">
|
|
54
|
+
<img id="reconciliation-button" class="icon" src="{{ url_for('static', filename='img/icons/statement-pair.png') }}" />
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
47
57
|
|
|
48
58
|
</div>
|
|
49
59
|
|
|
@@ -53,11 +63,32 @@
|
|
|
53
63
|
{% block javascript %}
|
|
54
64
|
|
|
55
65
|
<script>
|
|
66
|
+
const CREDIT_ACTIVITY_RECONCILIATION_ENDPOINT = "{{ url_for('credit.reconcile_activity', statement_id=statement.id) }}";
|
|
56
67
|
const UPDATE_STATEMENT_DUE_DATE_ENDPOINT = "{{ url_for('credit.update_statement_due_date', statement_id=statement.id) }}";
|
|
57
68
|
const MAKE_PAYMENT_ENDPOINT = "{{ url_for('credit.pay_credit_card', card_id=statement.card_id, statement_id=statement.id) }}";
|
|
58
69
|
const EXPAND_TRANSACTION_ENDPOINT = "{{ url_for('credit.expand_transaction') }}";
|
|
59
70
|
const LINKED_TRANSACTION_ENDPOINT = "{{ url_for('credit.show_linked_transaction') }}";
|
|
60
71
|
</script>
|
|
72
|
+
<script>
|
|
73
|
+
const CATEGORY_CHART_DATA = {
|
|
74
|
+
labels: [
|
|
75
|
+
{% for label in chart_data['labels'] %}
|
|
76
|
+
{% if label == '' %}
|
|
77
|
+
"Other",
|
|
78
|
+
{% else %}
|
|
79
|
+
"{{ label }}",
|
|
80
|
+
{% endif %}
|
|
81
|
+
{% endfor %}
|
|
82
|
+
],
|
|
83
|
+
series: [
|
|
84
|
+
{% for subtotal in chart_data['subtotals'] %}
|
|
85
|
+
{{ subtotal }},
|
|
86
|
+
{% endfor %}
|
|
87
|
+
],
|
|
88
|
+
};
|
|
89
|
+
</script>
|
|
90
|
+
<script type="module" src="{{ url_for('static', filename='js/show-credit-activity-loader.js') }}">
|
|
91
|
+
</script>
|
|
61
92
|
<script type="module" src="{{ url_for('static', filename='js/update-statement-parameters.js') }}">
|
|
62
93
|
</script>
|
|
63
94
|
<script type="module" src="{{ url_for('static', filename='js/make-payment.js') }}">
|
|
@@ -66,6 +97,8 @@
|
|
|
66
97
|
</script>
|
|
67
98
|
<script type="module" src="{{ url_for('static', filename='js/show-linked-transaction.js') }}">
|
|
68
99
|
</script>
|
|
100
|
+
<script type="module" src="{{ url_for('static', filename='js/create-category-chart.js') }}">
|
|
101
|
+
</script>
|
|
69
102
|
|
|
70
103
|
{% endblock %}
|
|
71
104
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<div class="discrepant-activities transactions-table">
|
|
2
|
+
|
|
3
|
+
{% for transaction, activity in discrepant_records.items() %}
|
|
4
|
+
|
|
5
|
+
<div class="reconciliation-activity discrepant-activity" data-transaction-id="{{ transaction.id }}">
|
|
6
|
+
|
|
7
|
+
<div class="activity-info">
|
|
8
|
+
<div class="date">{{ activity.transaction_date }}</div>
|
|
9
|
+
<div class="text">{{ activity.description }}</div>
|
|
10
|
+
<div class="amount">
|
|
11
|
+
<span class="dollar-sign">$</span>
|
|
12
|
+
{{ activity.total|currency }}
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<a class="button" href="{{ url_for('credit.update_transaction', transaction_id=transaction.id, transaction_date=activity.transaction_date, total=activity.total) }}">
|
|
17
|
+
<img class="icon" src="{{ url_for('static', filename='img/icons/edit.png') }}" />
|
|
18
|
+
</a>
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
{% endfor %}
|
|
23
|
+
|
|
24
|
+
</div>
|
|
25
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<div class="overlay">
|
|
2
|
+
<div id="statement-reconciliation" class="modal">
|
|
3
|
+
|
|
4
|
+
<div class="modal-box">
|
|
5
|
+
|
|
6
|
+
<div class="buttons">
|
|
7
|
+
<img class="close button" src="/static/img/icons/x-thick.png">
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<p class="instructions">
|
|
11
|
+
Load a CSV file containing credit activity for comparison against this statement. The CSV file must be located in the <code>Downloads</code> directory on the machine running the Monopyly app.
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<form action="{{ url_for('credit.load_statement_reconciliation_details', statement_id=statement_id) }}" method="post" enctype="multipart/form-data">
|
|
15
|
+
<label for="activity-file-upload">Activity Filename</label>
|
|
16
|
+
<input id="activity-file-upload" type="file" name="activity-file" accept="text/csv" />
|
|
17
|
+
<input class="button" type="submit" value="Reconcile Activity" />
|
|
18
|
+
</form>
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{% extends 'layout.html' %}
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
{% block header %}
|
|
5
|
+
|
|
6
|
+
<h1>
|
|
7
|
+
{% block title %}
|
|
8
|
+
Statement Reconciliation
|
|
9
|
+
{% endblock %}
|
|
10
|
+
</h1>
|
|
11
|
+
|
|
12
|
+
{% endblock %}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
{% block content %}
|
|
16
|
+
{% set highlighted_transactions = statement_transactions|selectattr("highlight")|first %}
|
|
17
|
+
|
|
18
|
+
<div id="credit-statement-reconciliation-details" class="details">
|
|
19
|
+
|
|
20
|
+
<div id="credit-statement-reconciliation-info" class="primary-info">
|
|
21
|
+
|
|
22
|
+
<div id="statement-reconciliation-summary-container" class="summary-container">
|
|
23
|
+
{% include 'credit/statement_reconciliation/summary.html' %}
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div id="statement-transactions-container" class="transactions-container">
|
|
27
|
+
{% if highlighted_transactions %}
|
|
28
|
+
<p class="note">
|
|
29
|
+
<span class="highlight">Highlighted</span> transactions indicate that the transaction was not identified in the reported activity file.
|
|
30
|
+
</p>
|
|
31
|
+
{% endif %}
|
|
32
|
+
|
|
33
|
+
{% with transactions = statement_transactions, full_view = False %}
|
|
34
|
+
{% include 'credit/transactions_table/transactions.html' %}
|
|
35
|
+
{% endwith %}
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
{% endblock %}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
{% block right_sidebar %}
|
|
46
|
+
|
|
47
|
+
<div class="sidebar-menu">
|
|
48
|
+
|
|
49
|
+
<div class="button">
|
|
50
|
+
<a class="action" href="{{ url_for('credit.add_transaction', card_id=statement.card_id, statement_id=statement.id) }}">
|
|
51
|
+
<img class="icon" src="{{ url_for('static', filename='img/icons/plus.png') }}" />
|
|
52
|
+
</a>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="button">
|
|
55
|
+
<a class="action" href="{{ url_for('credit.load_statement_details', statement_id=statement.id) }}">
|
|
56
|
+
<img class="icon" src="{{ url_for('static', filename='img/icons/statement.png') }}" />
|
|
57
|
+
</a>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="button">
|
|
60
|
+
<div class="action">
|
|
61
|
+
<img id="reconciliation-button" class="icon" src="{{ url_for('static', filename='img/icons/statement-pair.png') }}" />
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
{% endblock %}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
{% block javascript %}
|
|
71
|
+
|
|
72
|
+
<script>
|
|
73
|
+
const CREDIT_ACTIVITY_RECONCILIATION_ENDPOINT = "{{ url_for('credit.reconcile_activity', statement_id=statement.id) }}";
|
|
74
|
+
const EXPAND_TRANSACTION_ENDPOINT = "{{ url_for('credit.expand_transaction') }}";
|
|
75
|
+
const LINKED_TRANSACTION_ENDPOINT = "{{ url_for('credit.show_linked_transaction') }}";
|
|
76
|
+
</script>
|
|
77
|
+
<script type="module" src="{{ url_for('static', filename='js/show-credit-activity-loader.js') }}">
|
|
78
|
+
</script>
|
|
79
|
+
<script type="module" src="{{ url_for('static', filename='js/highlight-discrepant-transactions.js') }}">
|
|
80
|
+
</script>
|
|
81
|
+
<script type="module" src="{{ url_for('static', filename='js/expand-transaction.js') }}">
|
|
82
|
+
</script>
|
|
83
|
+
<script type="module" src="{{ url_for('static', filename='js/show-linked-transaction.js') }}">
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
{% endblock %}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<div id="statement-reconciliation-summary" class="summary-box">
|
|
2
|
+
|
|
3
|
+
{% if not (highlighted_transactions or discrepant_records or unrecorded_activities) %}
|
|
4
|
+
|
|
5
|
+
<img class="reconciliation-indicator" src="{{ url_for('static', filename='img/icons/checkmark.png') }}" />
|
|
6
|
+
|
|
7
|
+
{% else %}
|
|
8
|
+
|
|
9
|
+
{% if highlighted_transactions or discrepant_records or unrecorded_activities %}
|
|
10
|
+
<div id="statement-discrepancies-container">
|
|
11
|
+
<h2>Discrepancies</h3>
|
|
12
|
+
|
|
13
|
+
<div class="balance">
|
|
14
|
+
<div class="dollar-sign">$</div>
|
|
15
|
+
<div>{{ discrepant_amount|currency }}</div>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
{% if discrepant_records %}
|
|
19
|
+
<div class="discrepancy-category">
|
|
20
|
+
<h3>Discrepant Records</h3>
|
|
21
|
+
<p class="note">
|
|
22
|
+
{% set plural = discrepant_records|length != 1 %}
|
|
23
|
+
The following {% if plural %}activities were{% else %}activity was{% endif %} reported in the credit activity file and matched in the database, but the charge amount{%if plural %}s do{% else %} does{% endif %} not match:
|
|
24
|
+
</p>
|
|
25
|
+
{% include 'credit/statement_reconciliation/discrepant_records.html' %}
|
|
26
|
+
</div>
|
|
27
|
+
{% endif %}
|
|
28
|
+
|
|
29
|
+
{% if unrecorded_activities %}
|
|
30
|
+
<div class="discrepancy-category">
|
|
31
|
+
<h3>Unrecorded Activity</h3>
|
|
32
|
+
<p class="note">
|
|
33
|
+
{% set plural = unrecorded_activities|length != 1 %}
|
|
34
|
+
The following {% if plural %}activities were{% else %}activity was{% endif %} reported in the credit activity file, but {% if plural %}do{% else %}does{% endif %} not exist in the Monopyly database:
|
|
35
|
+
</p>
|
|
36
|
+
{% include 'credit/statement_reconciliation/unrecorded_activities.html' %}
|
|
37
|
+
</div>
|
|
38
|
+
{% endif %}
|
|
39
|
+
|
|
40
|
+
</div>
|
|
41
|
+
{% endif %}
|
|
42
|
+
|
|
43
|
+
{% endif %}
|
|
44
|
+
|
|
45
|
+
</div>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<div class="unrecorded-activities transactions-table">
|
|
2
|
+
|
|
3
|
+
{% for activity in unrecorded_activities %}
|
|
4
|
+
|
|
5
|
+
<div class="reconciliation-activity unrecorded-activity">
|
|
6
|
+
|
|
7
|
+
<div class=" activity-info">
|
|
8
|
+
<div class="date">{{ activity.transaction_date }}</div>
|
|
9
|
+
<div class="text">{{ activity.description }}</div>
|
|
10
|
+
<div class="amount">
|
|
11
|
+
<span class="dollar-sign">$</span>
|
|
12
|
+
{{ activity.total|currency }}
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<a class="button" href="{{ url_for('credit.add_transaction', card_id=statement.card.id, statement_id=statement.id, transaction_date=activity.transaction_date, total=activity.total, description=activity.description) }}">
|
|
17
|
+
<img class="icon" src="{{ url_for('static', filename='img/icons/plus-thick.png') }}" />
|
|
18
|
+
</a>
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
{% endfor %}
|
|
23
|
+
|
|
24
|
+
</div>
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
|
|
53
53
|
<div class="form-line">
|
|
54
54
|
<div class="dollar-sign">$</div>
|
|
55
|
-
<input id="pay-amount" type="
|
|
56
|
-
<input id="pay-date" type="
|
|
55
|
+
<input id="pay-amount" type="number" name="pay_amount" value="{{ statement.balance }}" />
|
|
56
|
+
<input id="pay-date" type="date" name="pay_date" value="{{ date_today }}" />
|
|
57
57
|
</div>
|
|
58
58
|
|
|
59
59
|
<div class="form-line">
|
|
@@ -23,9 +23,17 @@
|
|
|
23
23
|
{{ form.transaction_date }}
|
|
24
24
|
</div>
|
|
25
25
|
|
|
26
|
-
<div class="form-field merchant-field autocomplete">
|
|
26
|
+
<div class="form-field merchant-field autocomplete suggestable">
|
|
27
27
|
{{ form.merchant.label }}
|
|
28
28
|
{{ form.merchant }}
|
|
29
|
+
|
|
30
|
+
{% if form.suggestions.get('merchant') %}
|
|
31
|
+
<div class="form-suggestion merchant-suggestion">
|
|
32
|
+
<span>Suggested: </span>
|
|
33
|
+
<span class="suggested-value merchant">{{ form.suggestions['merchant'] }}</span>
|
|
34
|
+
</div>
|
|
35
|
+
{% endif %}
|
|
36
|
+
|
|
29
37
|
</div>
|
|
30
38
|
|
|
31
39
|
</div>
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
</script>
|
|
14
14
|
<script type="module" src="{{ url_for('static', filename='js/infer-statement.js') }}">
|
|
15
15
|
</script>
|
|
16
|
+
<script type="module" src="{{ url_for('static', filename='js/use-suggested-merchant.js') }}">
|
|
17
|
+
</script>
|
|
16
18
|
{{ super() }}
|
|
17
19
|
|
|
18
20
|
{% endblock %}
|
|
@@ -81,6 +81,14 @@
|
|
|
81
81
|
<a href="{{ url_for('credit.add_transaction', card_id=transaction.statement.card_id, statement_id=transaction.statement_id) }}">
|
|
82
82
|
Create a new transaction on this statement
|
|
83
83
|
</a>
|
|
84
|
+
{% with reconciliation_info = session.get('reconciliation_info', None) %}
|
|
85
|
+
{% if reconciliation_info %}
|
|
86
|
+
<br>
|
|
87
|
+
<a href="{{ url_for('credit.load_statement_reconciliation_details', statement_id=reconciliation_info[0]) }}">
|
|
88
|
+
Return to the in-progress statement reconciliation
|
|
89
|
+
</a>
|
|
90
|
+
{% endif %}
|
|
91
|
+
{% endwith %}
|
|
84
92
|
{% endif %}
|
|
85
93
|
|
|
86
94
|
</div>
|
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
<div class="setting">
|
|
1
|
+
<div class="setting column">
|
|
2
2
|
|
|
3
3
|
<div class="date column">
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
|
|
5
|
+
<div class="stacked-date">
|
|
6
|
+
<div class="month">
|
|
7
|
+
{{ transaction.transaction_date.strftime('%b')|upper }}
|
|
8
|
+
</div>
|
|
9
|
+
<div class="day">
|
|
10
|
+
{{ transaction.transaction_date.strftime('%d')|upper }}
|
|
11
|
+
</div>
|
|
12
|
+
<div class="year">
|
|
13
|
+
{{ transaction.transaction_date.year }}
|
|
14
|
+
</div>
|
|
12
15
|
</div>
|
|
13
|
-
<div class="full">
|
|
16
|
+
<div class="full-date">
|
|
14
17
|
{{ transaction.transaction_date }}
|
|
15
18
|
</div>
|
|
19
|
+
|
|
16
20
|
</div>
|
|
17
21
|
|
|
18
|
-
<div class="description">
|
|
22
|
+
<div class="description column">
|
|
19
23
|
|
|
20
24
|
<div class="description-header">
|
|
21
25
|
<div class="merchant">
|
|
@@ -31,9 +35,11 @@
|
|
|
31
35
|
</div>
|
|
32
36
|
|
|
33
37
|
</div>
|
|
38
|
+
|
|
34
39
|
</div>
|
|
35
40
|
|
|
36
|
-
|
|
41
|
+
|
|
42
|
+
<div class="payment column">
|
|
37
43
|
|
|
38
44
|
{% if full_view %}
|
|
39
45
|
<div class="statement">
|
monopyly/templates/layout.html
CHANGED
|
@@ -7,34 +7,36 @@
|
|
|
7
7
|
{% if request.path != '/' %} – {% endif %}
|
|
8
8
|
Monopyly
|
|
9
9
|
</title>
|
|
10
|
-
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"
|
|
10
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" />
|
|
11
|
+
<!-- Ensure emulators also display the page properly -->
|
|
12
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
|
|
11
13
|
<!-- ****** faviconit.com favicons ****** -->
|
|
12
|
-
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon/favicon.ico') }}"
|
|
13
|
-
<link rel="icon" sizes="16x16 32x32 64x64" href="{{ url_for('static', filename='favicon/favicon.ico') }}"
|
|
14
|
-
<link rel="icon" type="image/png" sizes="196x196" href="{{ url_for('static', filename='favicon/favicon-192.png') }}"
|
|
15
|
-
<link rel="icon" type="image/png" sizes="160x160" href="{{ url_for('static', filename='favicon/favicon-160.png') }}"
|
|
16
|
-
<link rel="icon" type="image/png" sizes="96x96" href="{{ url_for('static', filename='favicon/favicon-96.png') }}"
|
|
17
|
-
<link rel="icon" type="image/png" sizes="64x64" href="{{ url_for('static', filename='favicon/favicon-64.png') }}"
|
|
18
|
-
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon/favicon-32.png') }}"
|
|
19
|
-
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon/favicon-16.png') }}"
|
|
20
|
-
<link rel="apple-touch-icon" href="{{ url_for('static', filename='favicon/favicon-57.png') }}"
|
|
21
|
-
<link rel="apple-touch-icon" sizes="114x114" href="{{ url_for('static', filename='favicon/favicon-114.png') }}"
|
|
22
|
-
<link rel="apple-touch-icon" sizes="72x72" href="{{ url_for('static', filename='favicon/favicon-72.png') }}"
|
|
23
|
-
<link rel="apple-touch-icon" sizes="144x144" href="{{ url_for('static', filename='favicon/favicon-144.png') }}"
|
|
24
|
-
<link rel="apple-touch-icon" sizes="60x60" href="{{ url_for('static', filename='favicon/favicon-60.png') }}"
|
|
25
|
-
<link rel="apple-touch-icon" sizes="120x120" href="{{ url_for('static', filename='favicon/favicon-120.png') }}"
|
|
26
|
-
<link rel="apple-touch-icon" sizes="76x76" href="{{ url_for('static', filename='favicon/favicon-76.png') }}"
|
|
27
|
-
<link rel="apple-touch-icon" sizes="152x152" href="{{ url_for('static', filename='favicon/favicon-152.png') }}"
|
|
28
|
-
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='favicon/favicon-180.png') }}"
|
|
29
|
-
<meta name="msapplication-TileColor" content="#FFFFFF"
|
|
30
|
-
<meta name="msapplication-TileImage" content="{{ url_for('static', filename='favicon/favicon-144.png') }}"
|
|
31
|
-
<meta name="msapplication-config" content="{{ url_for('static', filename='favicon/browserconfig.xml') }}"
|
|
14
|
+
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon/favicon.ico') }}" />
|
|
15
|
+
<link rel="icon" sizes="16x16 32x32 64x64" href="{{ url_for('static', filename='favicon/favicon.ico') }}" />
|
|
16
|
+
<link rel="icon" type="image/png" sizes="196x196" href="{{ url_for('static', filename='favicon/favicon-192.png') }}" />
|
|
17
|
+
<link rel="icon" type="image/png" sizes="160x160" href="{{ url_for('static', filename='favicon/favicon-160.png') }}" />
|
|
18
|
+
<link rel="icon" type="image/png" sizes="96x96" href="{{ url_for('static', filename='favicon/favicon-96.png') }}" />
|
|
19
|
+
<link rel="icon" type="image/png" sizes="64x64" href="{{ url_for('static', filename='favicon/favicon-64.png') }}" />
|
|
20
|
+
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon/favicon-32.png') }}" />
|
|
21
|
+
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon/favicon-16.png') }}" />
|
|
22
|
+
<link rel="apple-touch-icon" href="{{ url_for('static', filename='favicon/favicon-57.png') }}" />
|
|
23
|
+
<link rel="apple-touch-icon" sizes="114x114" href="{{ url_for('static', filename='favicon/favicon-114.png') }}" />
|
|
24
|
+
<link rel="apple-touch-icon" sizes="72x72" href="{{ url_for('static', filename='favicon/favicon-72.png') }}" />
|
|
25
|
+
<link rel="apple-touch-icon" sizes="144x144" href="{{ url_for('static', filename='favicon/favicon-144.png') }}" />
|
|
26
|
+
<link rel="apple-touch-icon" sizes="60x60" href="{{ url_for('static', filename='favicon/favicon-60.png') }}" />
|
|
27
|
+
<link rel="apple-touch-icon" sizes="120x120" href="{{ url_for('static', filename='favicon/favicon-120.png') }}" />
|
|
28
|
+
<link rel="apple-touch-icon" sizes="76x76" href="{{ url_for('static', filename='favicon/favicon-76.png') }}" />
|
|
29
|
+
<link rel="apple-touch-icon" sizes="152x152" href="{{ url_for('static', filename='favicon/favicon-152.png') }}" />
|
|
30
|
+
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='favicon/favicon-180.png') }}" />
|
|
31
|
+
<meta name="msapplication-TileColor" content="#FFFFFF" />
|
|
32
|
+
<meta name="msapplication-TileImage" content="{{ url_for('static', filename='favicon/favicon-144.png') }}" />
|
|
33
|
+
<meta name="msapplication-config" content="{{ url_for('static', filename='favicon/browserconfig.xml') }}" />
|
|
32
34
|
<!-- ****** faviconit.com favicons ****** -->
|
|
33
35
|
<!-- Use Google JQuery CDN -->
|
|
34
36
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
|
|
35
37
|
<script>window.jQuery || document.write('<script src="{{ url_for('static', filename='jquery-3.7.0.min.js') }}"><\/script>')</script>
|
|
36
38
|
<!-- Use Chartist via CDN -->
|
|
37
|
-
<link rel="stylesheet" href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css"
|
|
39
|
+
<link rel="stylesheet" href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css" />
|
|
38
40
|
<script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
|
|
39
41
|
</head>
|
|
40
42
|
<body>
|
|
@@ -51,9 +53,13 @@
|
|
|
51
53
|
</h1>
|
|
52
54
|
</a>
|
|
53
55
|
|
|
54
|
-
<nav id="
|
|
55
|
-
<
|
|
56
|
-
|
|
56
|
+
<nav id="header-menu">
|
|
57
|
+
<svg class="mobile-menu mobile-menu-rotate toggle-button" viewBox="0 0 100 100">
|
|
58
|
+
<path class="line top" d="m 30,33 h 40 c 3.722839,0 7.5,3.126468 7.5,8.578427 0,5.451959 -2.727029,8.421573 -7.5,8.421573 h -20" />
|
|
59
|
+
<path class="line middle" d="m 30,50 h 40" />
|
|
60
|
+
<path class="line bottom" d="m 70,67 h -40 c 0,0 -7.5,-0.802118 -7.5,-8.365747 0,-7.563629 7.5,-8.634253 7.5,-8.634253 h 20" />
|
|
61
|
+
</svg>
|
|
62
|
+
<ul class="menu-links"></strong>
|
|
57
63
|
<li><a href="{{ url_for('core.index') }}">Home</a></li>
|
|
58
64
|
<li><a href="{{ url_for('core.about') }}">About</a></li>
|
|
59
65
|
{% if g.user %}
|
|
@@ -67,7 +73,6 @@
|
|
|
67
73
|
<li><a href="{{ url_for('auth.register') }}">Register</a></li>
|
|
68
74
|
<li><a href="{{ url_for('auth.login') }}">Log In</a></li>
|
|
69
75
|
{% endif %}
|
|
70
|
-
|
|
71
76
|
</ul></strong>
|
|
72
77
|
</nav>
|
|
73
78
|
|
|
@@ -107,7 +112,10 @@
|
|
|
107
112
|
</p>
|
|
108
113
|
</footer>
|
|
109
114
|
|
|
110
|
-
|
|
115
|
+
<script type="module" src="{{ url_for('static', filename='js/toggle-navigation.js') }}">
|
|
116
|
+
</script>
|
|
117
|
+
{% block javascript %}
|
|
118
|
+
{% endblock %}
|
|
111
119
|
|
|
112
120
|
</body>
|
|
113
121
|
</html>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: monopyly
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: A homemade personal finance manager.
|
|
5
5
|
Project-URL: Download, https://pypi.org/project/monopyly
|
|
6
6
|
Project-URL: Homepage, http://monopyly.com
|
|
@@ -29,6 +29,7 @@ Requires-Dist: flask==3.0.3
|
|
|
29
29
|
Requires-Dist: fuisce==1.0.2
|
|
30
30
|
Requires-Dist: gunicorn==22.0.0
|
|
31
31
|
Requires-Dist: markdown==3.6
|
|
32
|
+
Requires-Dist: nltk==3.8.1
|
|
32
33
|
Requires-Dist: python-dateutil==2.9.0
|
|
33
34
|
Requires-Dist: rich==13.7.1
|
|
34
35
|
Requires-Dist: sqlalchemy==2.0.29
|