monopyly 1.5.2__py3-none-any.whl → 1.6.1__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 +22 -0
- monopyly/README.md +1 -1
- monopyly/__init__.py +1 -1
- monopyly/_version.py +2 -2
- monopyly/auth/blueprint.py +2 -0
- monopyly/auth/routes.py +1 -2
- monopyly/banking/accounts.py +4 -4
- monopyly/banking/actions.py +20 -17
- monopyly/banking/blueprint.py +2 -0
- monopyly/banking/filters.py +6 -6
- monopyly/banking/forms.py +7 -5
- monopyly/banking/routes.py +71 -9
- monopyly/banking/transactions.py +2 -3
- monopyly/common/forms/__init__.py +8 -0
- monopyly/common/forms/_forms.py +6 -16
- monopyly/common/forms/fields.py +0 -11
- monopyly/common/forms/utils.py +4 -4
- monopyly/common/transactions.py +72 -7
- monopyly/core/actions.py +2 -1
- monopyly/core/blueprint.py +2 -0
- monopyly/core/context_processors.py +3 -21
- monopyly/core/filters.py +0 -2
- monopyly/core/routes.py +1 -1
- monopyly/credit/actions.py +4 -5
- monopyly/credit/blueprint.py +2 -0
- monopyly/credit/cards.py +1 -1
- monopyly/credit/forms.py +9 -7
- monopyly/credit/routes.py +37 -62
- monopyly/credit/transactions/__init__.py +2 -0
- monopyly/credit/transactions/_transactions.py +1 -4
- monopyly/credit/transactions/activity/__init__.py +6 -0
- monopyly/credit/transactions/activity/parser.py +0 -1
- monopyly/credit/transactions/activity/reconciliation.py +5 -3
- monopyly/database/__init__.py +0 -3
- monopyly/database/models.py +63 -49
- monopyly/database/preloads.sql +6 -1
- monopyly/scripts/screenshot_application.py +100 -0
- monopyly/static/chartist-1.5.0.min.js +8 -0
- monopyly/static/css/style.css +39 -14
- monopyly/static/img/about/bank-account-details.png +0 -0
- monopyly/static/img/about/bank-account-summaries.png +0 -0
- monopyly/static/img/about/bank-accounts.png +0 -0
- monopyly/static/img/about/credit-account-details.png +0 -0
- monopyly/static/img/about/credit-statement-details.png +0 -0
- monopyly/static/img/about/credit-transactions.png +0 -0
- monopyly/static/img/about/homepage-user.png +0 -0
- monopyly/static/img/about/homepage.png +0 -0
- monopyly/static/jquery-3.7.1.min.js +2 -0
- monopyly/static/js/add-transfer.js +8 -9
- monopyly/static/js/bind-tag-actions.js +6 -0
- monopyly/static/js/create-balance-chart.js +1 -1
- monopyly/static/js/create-category-chart.js +1 -1
- monopyly/static/js/load-more-transactions.js +27 -0
- monopyly/static/js/modules/expand-transaction.js +7 -6
- monopyly/static/js/modules/update-display-ajax.js +20 -1
- monopyly/static/js/update-transactions-display.js +8 -2
- monopyly/templates/banking/account_form/account_form_page_new.html +10 -8
- monopyly/templates/banking/account_page.html +32 -33
- monopyly/templates/banking/account_summaries.html +2 -2
- monopyly/templates/banking/account_summary.html +1 -1
- monopyly/templates/banking/accounts_page.html +10 -8
- monopyly/templates/banking/transactions_table/table.html +3 -0
- monopyly/templates/banking/transactions_table/transactions.html +0 -1
- monopyly/templates/common/tag_tree.html +25 -0
- monopyly/templates/{credit → common}/tags_page.html +17 -13
- monopyly/templates/common/transactions_table/linked_bank_transaction.html +2 -2
- monopyly/templates/common/transactions_table/table.html +6 -0
- monopyly/templates/common/transactions_table/transactions.html +9 -15
- monopyly/templates/core/index.html +124 -109
- monopyly/templates/core/profile.html +19 -20
- monopyly/templates/credit/account_page.html +17 -17
- monopyly/templates/credit/card_form/card_form_page_new.html +8 -5
- monopyly/templates/credit/statement_page.html +45 -46
- monopyly/templates/credit/statement_reconciliation/statement_reconciliation_page.html +22 -22
- monopyly/templates/credit/statement_summary.html +2 -2
- monopyly/templates/credit/statements_page.html +13 -13
- monopyly/templates/credit/transaction_form/transaction_form_page_update.html +9 -9
- monopyly/templates/credit/transaction_submission_page.html +3 -3
- monopyly/templates/credit/transactions_page.html +38 -22
- monopyly/templates/credit/transactions_table/condensed_row_content.html +2 -2
- monopyly/templates/credit/transactions_table/expanded_row_content.html +5 -5
- monopyly/templates/credit/transactions_table/table.html +3 -0
- monopyly/templates/credit/transactions_table/transactions.html +0 -1
- monopyly/templates/layout.html +16 -9
- {monopyly-1.5.2.dist-info → monopyly-1.6.1.dist-info}/METADATA +8 -8
- {monopyly-1.5.2.dist-info → monopyly-1.6.1.dist-info}/RECORD +90 -84
- monopyly-1.6.1.dist-info/entry_points.txt +3 -0
- monopyly/static/jquery-3.7.0.min.js +0 -2
- monopyly/templates/credit/tag_tree/subtag_tree.html +0 -22
- monopyly/templates/credit/tag_tree/tag_tree.html +0 -13
- monopyly-1.5.2.dist-info/entry_points.txt +0 -2
- {monopyly-1.5.2.dist-info → monopyly-1.6.1.dist-info}/WHEEL +0 -0
- {monopyly-1.5.2.dist-info → monopyly-1.6.1.dist-info}/licenses/COPYING +0 -0
- {monopyly-1.5.2.dist-info → monopyly-1.6.1.dist-info}/licenses/LICENSE +0 -0
monopyly/core/blueprint.py
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
Filters defined for the application.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
from importlib import import_module
|
|
5
|
+
from dry_foundation.utils import define_basic_template_global_variables
|
|
7
6
|
|
|
8
7
|
from .actions import determine_summary_balance_svg_viewbox_width
|
|
9
8
|
from .blueprint import bp
|
|
@@ -11,13 +10,8 @@ from .blueprint import bp
|
|
|
11
10
|
|
|
12
11
|
@bp.app_context_processor
|
|
13
12
|
def inject_global_template_variables():
|
|
14
|
-
"""Inject template
|
|
15
|
-
|
|
16
|
-
"app_version": _display_version(),
|
|
17
|
-
"copyright_statement": f"© {date.today().year}",
|
|
18
|
-
"date_today": date.today(),
|
|
19
|
-
}
|
|
20
|
-
return template_globals
|
|
13
|
+
"""Inject template variables globally into the template context."""
|
|
14
|
+
return define_basic_template_global_variables("monopyly._version")
|
|
21
15
|
|
|
22
16
|
|
|
23
17
|
@bp.app_context_processor
|
|
@@ -27,15 +21,3 @@ def inject_utility_functions():
|
|
|
27
21
|
"calculate_summary_balance_width": determine_summary_balance_svg_viewbox_width,
|
|
28
22
|
}
|
|
29
23
|
return utility_functions
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def _display_version():
|
|
33
|
-
"""Show the version (without commit information)."""
|
|
34
|
-
try:
|
|
35
|
-
version = import_module("monopyly._version").version
|
|
36
|
-
except ModuleNotFoundError:
|
|
37
|
-
# Fallback action in case Hatch VCS fails
|
|
38
|
-
display_version = ""
|
|
39
|
-
else:
|
|
40
|
-
display_version = version.split("+")[0]
|
|
41
|
-
return display_version
|
monopyly/core/filters.py
CHANGED
monopyly/core/routes.py
CHANGED
monopyly/credit/actions.py
CHANGED
|
@@ -94,9 +94,8 @@ def get_potential_preceding_card(card):
|
|
|
94
94
|
card_ids=(other_card.id,),
|
|
95
95
|
)
|
|
96
96
|
latest_statement = statements.first()
|
|
97
|
-
if latest_statement:
|
|
98
|
-
|
|
99
|
-
return other_card
|
|
97
|
+
if latest_statement and latest_statement.balance > 0:
|
|
98
|
+
return other_card
|
|
100
99
|
# Card does not meet all of these conditions
|
|
101
100
|
return None
|
|
102
101
|
|
|
@@ -110,8 +109,8 @@ def transfer_credit_card_statement(form, card_id, prior_card_id):
|
|
|
110
109
|
statements = CreditStatementHandler.get_statements(card_ids=(prior_card_id,))
|
|
111
110
|
latest_statement = statements.first()
|
|
112
111
|
CreditStatementHandler.update_entry(latest_statement.id, card_id=card_id)
|
|
113
|
-
# Deactivate the old card
|
|
114
|
-
|
|
112
|
+
# Deactivate the old card (after ensuring it exists and is accessible)
|
|
113
|
+
CreditCardHandler.get_entry(prior_card_id)
|
|
115
114
|
CreditCardHandler.update_entry(prior_card_id, active=0)
|
|
116
115
|
|
|
117
116
|
|
monopyly/credit/blueprint.py
CHANGED
monopyly/credit/cards.py
CHANGED
|
@@ -137,7 +137,7 @@ def save_card(form, card_id=None):
|
|
|
137
137
|
|
|
138
138
|
Parameters
|
|
139
139
|
----------
|
|
140
|
-
form :
|
|
140
|
+
form : CreditCardForm
|
|
141
141
|
The form beign used to provide the data being saved.
|
|
142
142
|
card_id : int
|
|
143
143
|
The ID of hte card to be saved. If provided, the named card will
|
monopyly/credit/forms.py
CHANGED
|
@@ -2,25 +2,23 @@
|
|
|
2
2
|
Generate credit card forms for the user to complete.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from flask import abort
|
|
6
6
|
from wtforms.fields import (
|
|
7
7
|
BooleanField,
|
|
8
|
+
DateField,
|
|
8
9
|
FieldList,
|
|
9
10
|
FormField,
|
|
10
11
|
IntegerField,
|
|
11
12
|
RadioField,
|
|
12
|
-
StringField,
|
|
13
13
|
SubmitField,
|
|
14
14
|
)
|
|
15
15
|
from wtforms.validators import DataRequired, Optional
|
|
16
16
|
|
|
17
|
-
from ..banking.
|
|
18
|
-
from ..banking.forms import BankSelectField, BankSubform
|
|
17
|
+
from ..banking.forms import BankSubform
|
|
19
18
|
from ..common.forms import AcquisitionSubform, EntryForm, EntrySubform, TransactionForm
|
|
20
19
|
from ..common.forms.fields import (
|
|
21
20
|
CustomChoiceSelectField,
|
|
22
21
|
LastFourDigitsField,
|
|
23
|
-
OptionalDateField,
|
|
24
22
|
StringField,
|
|
25
23
|
)
|
|
26
24
|
from ..common.forms.utils import Autocompleter
|
|
@@ -154,6 +152,10 @@ class CardStatementTransferForm(EntryForm):
|
|
|
154
152
|
transfer = RadioField("transfer", choices=[("yes", "Yes"), ("no", "No")])
|
|
155
153
|
submit = SubmitField("Continue")
|
|
156
154
|
|
|
155
|
+
def gather_entry_data(self, entry):
|
|
156
|
+
"""Gather data for the form from the given database entry."""
|
|
157
|
+
raise NotImplementedError
|
|
158
|
+
|
|
157
159
|
|
|
158
160
|
class CreditTransactionForm(TransactionForm):
|
|
159
161
|
"""Form to input/edit credit card transactions."""
|
|
@@ -195,7 +197,7 @@ class CreditTransactionForm(TransactionForm):
|
|
|
195
197
|
# Fields to identify the card/bank information for the statement
|
|
196
198
|
card_info = FormField(CardSubform)
|
|
197
199
|
# Fields pertaining to the statement
|
|
198
|
-
issue_date =
|
|
200
|
+
issue_date = DateField("Statement Date", [Optional()])
|
|
199
201
|
|
|
200
202
|
def get_statement(self, transaction_date):
|
|
201
203
|
"""Get the credit card statement described by the form data."""
|
|
@@ -335,7 +337,7 @@ class CreditTransactionForm(TransactionForm):
|
|
|
335
337
|
"""Gather data for the form from the given database entry."""
|
|
336
338
|
if isinstance(entry, CreditTransactionView):
|
|
337
339
|
data = self._gather_transaction_data(entry)
|
|
338
|
-
statement_info = entry.
|
|
340
|
+
statement_info = entry.statement_view
|
|
339
341
|
elif isinstance(entry, (CreditCard, CreditStatementView)):
|
|
340
342
|
data = {}
|
|
341
343
|
statement_info = entry
|
monopyly/credit/routes.py
CHANGED
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
Routes for credit card financials.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from itertools import islice
|
|
6
|
-
|
|
7
5
|
from dry_foundation.database import db_transaction
|
|
8
6
|
from flask import (
|
|
7
|
+
abort,
|
|
9
8
|
flash,
|
|
10
|
-
g,
|
|
11
9
|
jsonify,
|
|
12
10
|
redirect,
|
|
13
11
|
render_template,
|
|
@@ -16,21 +14,17 @@ from flask import (
|
|
|
16
14
|
url_for,
|
|
17
15
|
)
|
|
18
16
|
from sqlalchemy.exc import MultipleResultsFound
|
|
19
|
-
from werkzeug.exceptions import abort
|
|
20
|
-
from wtforms.validators import ValidationError
|
|
21
17
|
|
|
22
18
|
from ..auth.tools import login_required
|
|
23
19
|
from ..banking.accounts import BankAccountHandler
|
|
24
20
|
from ..banking.banks import BankHandler
|
|
25
|
-
from ..banking.transactions import BankTransactionHandler
|
|
26
|
-
from ..common.forms import form_err_msg
|
|
27
21
|
from ..common.forms.utils import extend_field_list_for_ajax
|
|
28
22
|
from ..common.transactions import (
|
|
29
23
|
categorize,
|
|
30
24
|
get_linked_transaction,
|
|
31
25
|
highlight_unmatched_transactions,
|
|
32
26
|
)
|
|
33
|
-
from ..common.utils import dedelimit_float, parse_date
|
|
27
|
+
from ..common.utils import dedelimit_float, parse_date
|
|
34
28
|
from .accounts import CreditAccountHandler
|
|
35
29
|
from .actions import (
|
|
36
30
|
get_card_statement_grouping,
|
|
@@ -44,13 +38,16 @@ from .blueprint import bp
|
|
|
44
38
|
from .cards import CreditCardHandler, save_card
|
|
45
39
|
from .forms import CardStatementTransferForm, CreditCardForm, CreditTransactionForm
|
|
46
40
|
from .statements import CreditStatementHandler
|
|
47
|
-
from .transactions import
|
|
41
|
+
from .transactions import CreditTransactionHandler, save_transaction
|
|
48
42
|
from .transactions.activity import (
|
|
49
43
|
ActivityMatchmaker,
|
|
50
44
|
TransactionActivities,
|
|
51
45
|
parse_transaction_activity_file,
|
|
52
46
|
)
|
|
53
47
|
|
|
48
|
+
# Set a limit on the number of transactions loaded at one time for certain routes
|
|
49
|
+
TRANSACTION_LIMIT = 100
|
|
50
|
+
|
|
54
51
|
|
|
55
52
|
@bp.route("/cards")
|
|
56
53
|
@login_required
|
|
@@ -206,7 +203,7 @@ def load_statement_details(statement_id):
|
|
|
206
203
|
return render_template(
|
|
207
204
|
"credit/statement_page.html",
|
|
208
205
|
statement=statement,
|
|
209
|
-
|
|
206
|
+
transactions=transactions,
|
|
210
207
|
bank_accounts=bank_accounts,
|
|
211
208
|
chart_data=categories.assemble_chart_data(exclude=["Credit payments"]),
|
|
212
209
|
)
|
|
@@ -261,7 +258,7 @@ def pay_credit_card(card_id, statement_id):
|
|
|
261
258
|
bank_accounts=bank_accounts,
|
|
262
259
|
)
|
|
263
260
|
transactions_table_template = render_template(
|
|
264
|
-
"credit/transactions_table/
|
|
261
|
+
"credit/transactions_table/table.html",
|
|
265
262
|
transactions=transactions,
|
|
266
263
|
)
|
|
267
264
|
return jsonify((summary_template, transactions_table_template))
|
|
@@ -299,7 +296,7 @@ def load_statement_reconciliation_details(statement_id):
|
|
|
299
296
|
return render_template(
|
|
300
297
|
"credit/statement_reconciliation/statement_reconciliation_page.html",
|
|
301
298
|
statement=statement,
|
|
302
|
-
|
|
299
|
+
transactions=transactions,
|
|
303
300
|
discrepant_records=matchmaker.match_discrepancies,
|
|
304
301
|
discrepant_amount=abs(statement_transaction_balance - activities.total),
|
|
305
302
|
unrecorded_activities=matchmaker.unmatched_activities,
|
|
@@ -345,14 +342,38 @@ def load_transactions(card_id):
|
|
|
345
342
|
# Get all of the user's transactions for the selected cards
|
|
346
343
|
sort_order = "DESC"
|
|
347
344
|
transactions = CreditTransactionHandler.get_transactions(
|
|
348
|
-
card_ids=selected_card_ids, sort_order=sort_order
|
|
349
|
-
)
|
|
345
|
+
card_ids=selected_card_ids, sort_order=sort_order
|
|
346
|
+
).all()
|
|
350
347
|
return render_template(
|
|
351
348
|
"credit/transactions_page.html",
|
|
352
349
|
filter_cards=cards,
|
|
353
350
|
selected_card_ids=selected_card_ids,
|
|
354
351
|
sort_order=sort_order,
|
|
355
|
-
transactions=transactions,
|
|
352
|
+
transactions=transactions[:TRANSACTION_LIMIT],
|
|
353
|
+
total_transactions=len(transactions),
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
@bp.route("/_extra_transactions", methods=("POST",))
|
|
358
|
+
@login_required
|
|
359
|
+
def load_more_transactions():
|
|
360
|
+
# Get info about the transactions being displayed from the AJAX request
|
|
361
|
+
post_args = request.get_json()
|
|
362
|
+
selected_card_ids = map(int, post_args["selected_card_ids"])
|
|
363
|
+
sort_order = "ASC" if post_args["sort_order"] == "asc" else "DESC"
|
|
364
|
+
block_index = post_args["block_count"] - 1
|
|
365
|
+
full_view = post_args["full_view"]
|
|
366
|
+
# Get a subset of the remaining transactions to load
|
|
367
|
+
more_transactions = CreditTransactionHandler.get_transactions(
|
|
368
|
+
card_ids=selected_card_ids,
|
|
369
|
+
sort_order=sort_order,
|
|
370
|
+
offset=block_index * TRANSACTION_LIMIT,
|
|
371
|
+
limit=TRANSACTION_LIMIT,
|
|
372
|
+
)
|
|
373
|
+
return render_template(
|
|
374
|
+
"credit/transactions_table/transactions.html",
|
|
375
|
+
transactions=more_transactions,
|
|
376
|
+
full_view=full_view,
|
|
356
377
|
)
|
|
357
378
|
|
|
358
379
|
|
|
@@ -368,7 +389,7 @@ def update_transactions_display():
|
|
|
368
389
|
card_ids=card_ids, sort_order=sort_order, limit=100
|
|
369
390
|
)
|
|
370
391
|
return render_template(
|
|
371
|
-
"credit/transactions_table/
|
|
392
|
+
"credit/transactions_table/table.html",
|
|
372
393
|
sort_order=sort_order,
|
|
373
394
|
transactions=transactions,
|
|
374
395
|
full_view=True,
|
|
@@ -507,52 +528,6 @@ def delete_transaction(transaction_id):
|
|
|
507
528
|
return redirect(url_for("credit.load_transactions"))
|
|
508
529
|
|
|
509
530
|
|
|
510
|
-
@bp.route("/tags")
|
|
511
|
-
@login_required
|
|
512
|
-
def load_tags():
|
|
513
|
-
# Get the tag hierarchy from the database
|
|
514
|
-
hierarchy = CreditTagHandler.get_hierarchy()
|
|
515
|
-
return render_template("credit/tags_page.html", tags_hierarchy=hierarchy)
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
@bp.route("/_add_tag", methods=("POST",))
|
|
519
|
-
@login_required
|
|
520
|
-
@db_transaction
|
|
521
|
-
def add_tag():
|
|
522
|
-
# Get the new tag (and potentially parent category) from the AJAX request
|
|
523
|
-
post_args = request.get_json()
|
|
524
|
-
tag_name = post_args["tag_name"]
|
|
525
|
-
parent_name = post_args.get("parent")
|
|
526
|
-
# Check that the tag name does not already exist
|
|
527
|
-
if CreditTagHandler.get_tags(tag_names=(tag_name,)):
|
|
528
|
-
raise ValueError("The given tag name already exists. Tag names must be unique.")
|
|
529
|
-
if parent_name:
|
|
530
|
-
parent_id = CreditTagHandler.find_tag(parent_name).id
|
|
531
|
-
else:
|
|
532
|
-
parent_id = None
|
|
533
|
-
tag = CreditTagHandler.add_entry(
|
|
534
|
-
parent_id=parent_id,
|
|
535
|
-
user_id=g.user.id,
|
|
536
|
-
tag_name=tag_name,
|
|
537
|
-
)
|
|
538
|
-
return render_template(
|
|
539
|
-
"credit/tag_tree/subtag_tree.html", tag=tag, tags_hierarchy={}
|
|
540
|
-
)
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
@bp.route("/_delete_tag", methods=("POST",))
|
|
544
|
-
@login_required
|
|
545
|
-
@db_transaction
|
|
546
|
-
def delete_tag():
|
|
547
|
-
# Get the tag to be deleted from the AJAX request
|
|
548
|
-
post_args = request.get_json()
|
|
549
|
-
tag_name = post_args["tag_name"]
|
|
550
|
-
tag = CreditTagHandler.find_tag(tag_name)
|
|
551
|
-
# Remove the tag from the database
|
|
552
|
-
CreditTagHandler.delete_entry(tag.id)
|
|
553
|
-
return ""
|
|
554
|
-
|
|
555
|
-
|
|
556
531
|
@bp.route("/_suggest_transaction_autocomplete", methods=("POST",))
|
|
557
532
|
@login_required
|
|
558
533
|
def suggest_transaction_autocomplete():
|
|
@@ -2,15 +2,12 @@
|
|
|
2
2
|
Tools for interacting with the credit transactions in the database.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from dry_foundation.database.handler import
|
|
5
|
+
from dry_foundation.database.handler import DatabaseViewHandler
|
|
6
6
|
|
|
7
7
|
from ...common.forms.utils import execute_on_form_validation
|
|
8
8
|
from ...common.transactions import TransactionHandler, TransactionTagHandler
|
|
9
9
|
from ...database.models import (
|
|
10
|
-
Bank,
|
|
11
|
-
CreditAccount,
|
|
12
10
|
CreditCard,
|
|
13
|
-
CreditStatementView,
|
|
14
11
|
CreditSubtransaction,
|
|
15
12
|
CreditTransaction,
|
|
16
13
|
CreditTransactionView,
|
|
@@ -5,7 +5,6 @@ from abc import ABC, abstractmethod
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
from flask import abort, current_app
|
|
8
|
-
from werkzeug.utils import secure_filename
|
|
9
8
|
|
|
10
9
|
from ....common.utils import parse_date
|
|
11
10
|
from .data import ActivityLoadingError, TransactionActivities, TransactionActivityLoader
|
|
@@ -113,9 +113,11 @@ class _Matchmaker(ABC):
|
|
|
113
113
|
|
|
114
114
|
def includes_activity(self, activity):
|
|
115
115
|
for value in self.values():
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
same_activity = activity == value
|
|
117
|
+
same_group = (
|
|
118
|
+
isinstance(value, TransactionActivityGroup) and activity in value
|
|
119
|
+
)
|
|
120
|
+
if same_activity or same_group:
|
|
119
121
|
return True
|
|
120
122
|
return False
|
|
121
123
|
|