monopyly 1.5.2__py3-none-any.whl → 1.6.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 +15 -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 +3 -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 +1 -2
- monopyly/common/forms/fields.py +0 -2
- monopyly/common/forms/utils.py +1 -1
- monopyly/common/transactions.py +72 -7
- monopyly/core/actions.py +2 -1
- monopyly/core/blueprint.py +2 -0
- 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/forms.py +3 -5
- 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 +35 -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_page.html +15 -16
- monopyly/templates/banking/account_summaries.html +2 -2
- monopyly/templates/banking/account_summary.html +1 -1
- monopyly/templates/banking/accounts_page.html +2 -2
- 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 +7 -3
- 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 +112 -101
- monopyly/templates/core/profile.html +1 -1
- monopyly/templates/credit/statement_page.html +2 -2
- monopyly/templates/credit/statement_reconciliation/statement_reconciliation_page.html +3 -3
- monopyly/templates/credit/statement_summary.html +2 -2
- monopyly/templates/credit/transaction_submission_page.html +3 -3
- monopyly/templates/credit/transactions_page.html +19 -3
- 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 +9 -4
- {monopyly-1.5.2.dist-info → monopyly-1.6.0.dist-info}/METADATA +5 -5
- {monopyly-1.5.2.dist-info → monopyly-1.6.0.dist-info}/RECORD +83 -77
- monopyly-1.6.0.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.0.dist-info}/WHEEL +0 -0
- {monopyly-1.5.2.dist-info → monopyly-1.6.0.dist-info}/licenses/COPYING +0 -0
- {monopyly-1.5.2.dist-info → monopyly-1.6.0.dist-info}/licenses/LICENSE +0 -0
monopyly/credit/forms.py
CHANGED
|
@@ -2,20 +2,18 @@
|
|
|
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
8
|
FieldList,
|
|
9
9
|
FormField,
|
|
10
10
|
IntegerField,
|
|
11
11
|
RadioField,
|
|
12
|
-
StringField,
|
|
13
12
|
SubmitField,
|
|
14
13
|
)
|
|
15
14
|
from wtforms.validators import DataRequired, Optional
|
|
16
15
|
|
|
17
|
-
from ..banking.
|
|
18
|
-
from ..banking.forms import BankSelectField, BankSubform
|
|
16
|
+
from ..banking.forms import BankSubform
|
|
19
17
|
from ..common.forms import AcquisitionSubform, EntryForm, EntrySubform, TransactionForm
|
|
20
18
|
from ..common.forms.fields import (
|
|
21
19
|
CustomChoiceSelectField,
|
|
@@ -335,7 +333,7 @@ class CreditTransactionForm(TransactionForm):
|
|
|
335
333
|
"""Gather data for the form from the given database entry."""
|
|
336
334
|
if isinstance(entry, CreditTransactionView):
|
|
337
335
|
data = self._gather_transaction_data(entry)
|
|
338
|
-
statement_info = entry.
|
|
336
|
+
statement_info = entry.statement_view
|
|
339
337
|
elif isinstance(entry, (CreditCard, CreditStatementView)):
|
|
340
338
|
data = {}
|
|
341
339
|
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
|
|
monopyly/database/__init__.py
CHANGED
monopyly/database/models.py
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import datetime
|
|
2
|
-
from typing import List, Optional
|
|
3
2
|
|
|
4
3
|
from dry_foundation.database.models import AuthorizedAccessMixin, Model
|
|
5
|
-
from sqlalchemy import Column,
|
|
6
|
-
from sqlalchemy.ext.hybrid import hybrid_property
|
|
4
|
+
from sqlalchemy import Column, ForeignKey, Integer, Table
|
|
7
5
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
8
6
|
|
|
9
7
|
|
|
@@ -15,7 +13,7 @@ class User(Model):
|
|
|
15
13
|
password: Mapped[str]
|
|
16
14
|
# Relationships
|
|
17
15
|
banks: Mapped["Bank"] = relationship(back_populates="user", cascade="all, delete")
|
|
18
|
-
|
|
16
|
+
bank_account_type_views: Mapped[list["BankAccountTypeView"]] = relationship(
|
|
19
17
|
back_populates="user", viewonly=True
|
|
20
18
|
)
|
|
21
19
|
|
|
@@ -25,16 +23,23 @@ class InternalTransaction(Model):
|
|
|
25
23
|
# Columns
|
|
26
24
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
27
25
|
# Relationships
|
|
28
|
-
bank_transactions: Mapped[
|
|
26
|
+
bank_transactions: Mapped[list["BankTransaction"]] = relationship(
|
|
29
27
|
back_populates="internal_transaction"
|
|
30
28
|
)
|
|
31
|
-
|
|
29
|
+
bank_transaction_views: Mapped[list["BankTransactionView"]] = relationship(
|
|
30
|
+
back_populates="internal_transaction", viewonly=True
|
|
31
|
+
)
|
|
32
|
+
credit_transactions: Mapped[list["CreditTransaction"]] = relationship(
|
|
32
33
|
back_populates="internal_transaction"
|
|
33
34
|
)
|
|
35
|
+
credit_transaction_views: Mapped[list["CreditTransactionView"]] = relationship(
|
|
36
|
+
back_populates="internal_transaction", viewonly=True
|
|
37
|
+
)
|
|
34
38
|
|
|
39
|
+
@property
|
|
40
|
+
def transaction_views(self):
|
|
41
|
+
return self.bank_transaction_views + self.credit_transaction_views
|
|
35
42
|
|
|
36
|
-
# Not sure why these tables are necessary, because they should already be reflected;
|
|
37
|
-
# perhaps explore or wait until sqlalchemy 2.0
|
|
38
43
|
|
|
39
44
|
bank_tag_link_table = Table(
|
|
40
45
|
"bank_tag_links",
|
|
@@ -62,20 +67,21 @@ credit_tag_link_table = Table(
|
|
|
62
67
|
|
|
63
68
|
class TransactionTag(AuthorizedAccessMixin, Model):
|
|
64
69
|
__tablename__ = "transaction_tags"
|
|
70
|
+
_alt_authorized_ids = (0,)
|
|
65
71
|
# Columns
|
|
66
72
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
67
73
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
|
|
68
|
-
parent_id: Mapped[
|
|
74
|
+
parent_id: Mapped[int | None] = mapped_column(ForeignKey("transaction_tags.id"))
|
|
69
75
|
tag_name: Mapped[str]
|
|
70
76
|
# Relationships
|
|
71
77
|
parent: Mapped["TransactionTag"] = relationship(
|
|
72
78
|
back_populates="children", remote_side=[id]
|
|
73
79
|
)
|
|
74
|
-
children: Mapped[
|
|
75
|
-
bank_subtransactions: Mapped[
|
|
80
|
+
children: Mapped[list["TransactionTag"]] = relationship(back_populates="parent")
|
|
81
|
+
bank_subtransactions: Mapped[list["BankSubtransaction"]] = relationship(
|
|
76
82
|
back_populates="tags", secondary=bank_tag_link_table
|
|
77
83
|
)
|
|
78
|
-
credit_subtransactions: Mapped[
|
|
84
|
+
credit_subtransactions: Mapped[list["CreditSubtransaction"]] = relationship(
|
|
79
85
|
back_populates="tags", secondary=credit_tag_link_table
|
|
80
86
|
)
|
|
81
87
|
|
|
@@ -95,10 +101,10 @@ class Bank(AuthorizedAccessMixin, Model):
|
|
|
95
101
|
bank_name: Mapped[str]
|
|
96
102
|
# Relationships
|
|
97
103
|
user: Mapped["User"] = relationship(back_populates="banks")
|
|
98
|
-
|
|
104
|
+
bank_account_views: Mapped[list["BankAccountView"]] = relationship(
|
|
99
105
|
back_populates="bank", cascade="all, delete", viewonly=True
|
|
100
106
|
)
|
|
101
|
-
credit_accounts: Mapped[
|
|
107
|
+
credit_accounts: Mapped[list["CreditAccount"]] = relationship(
|
|
102
108
|
back_populates="bank", cascade="all, delete"
|
|
103
109
|
)
|
|
104
110
|
|
|
@@ -110,7 +116,7 @@ class BankAccountType(AuthorizedAccessMixin, Model):
|
|
|
110
116
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
111
117
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
|
|
112
118
|
type_name: Mapped[str]
|
|
113
|
-
type_abbreviation: Mapped[
|
|
119
|
+
type_abbreviation: Mapped[str | None]
|
|
114
120
|
# Relationships
|
|
115
121
|
view: Mapped["BankAccountTypeView"] = relationship(
|
|
116
122
|
back_populates="account_type", uselist=False, viewonly=True
|
|
@@ -124,13 +130,13 @@ class BankAccountTypeView(AuthorizedAccessMixin, Model):
|
|
|
124
130
|
id = mapped_column(Integer, ForeignKey("bank_account_types.id"), primary_key=True)
|
|
125
131
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
|
|
126
132
|
type_name: Mapped[str]
|
|
127
|
-
type_abbreviation: Mapped[
|
|
133
|
+
type_abbreviation: Mapped[str | None]
|
|
128
134
|
type_common_name: Mapped[str]
|
|
129
135
|
# Relationships
|
|
130
136
|
account_type: Mapped["BankAccountType"] = relationship(back_populates="view")
|
|
131
|
-
user: Mapped["User"] = relationship(back_populates="
|
|
132
|
-
|
|
133
|
-
back_populates="
|
|
137
|
+
user: Mapped["User"] = relationship(back_populates="bank_account_type_views")
|
|
138
|
+
account_views: Mapped[list["BankAccountView"]] = relationship(
|
|
139
|
+
back_populates="account_type_view", viewonly=True
|
|
134
140
|
)
|
|
135
141
|
|
|
136
142
|
|
|
@@ -166,12 +172,12 @@ class BankAccountView(AuthorizedAccessMixin, Model):
|
|
|
166
172
|
projected_balance: Mapped[float]
|
|
167
173
|
# Relationships
|
|
168
174
|
account: Mapped["BankAccount"] = relationship(back_populates="view")
|
|
169
|
-
bank: Mapped["Bank"] = relationship(back_populates="
|
|
170
|
-
|
|
171
|
-
back_populates="
|
|
175
|
+
bank: Mapped["Bank"] = relationship(back_populates="bank_account_views")
|
|
176
|
+
account_type_view: Mapped["BankAccountTypeView"] = relationship(
|
|
177
|
+
back_populates="account_views", viewonly=True
|
|
172
178
|
)
|
|
173
|
-
|
|
174
|
-
back_populates="
|
|
179
|
+
transaction_views: Mapped[list["BankTransactionView"]] = relationship(
|
|
180
|
+
back_populates="account_view", viewonly=True
|
|
175
181
|
)
|
|
176
182
|
|
|
177
183
|
|
|
@@ -182,16 +188,19 @@ class BankTransaction(AuthorizedAccessMixin, Model):
|
|
|
182
188
|
subtype = "bank"
|
|
183
189
|
# Columns
|
|
184
190
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
185
|
-
internal_transaction_id: Mapped[
|
|
191
|
+
internal_transaction_id: Mapped[int | None] = mapped_column(
|
|
186
192
|
ForeignKey("internal_transactions.id")
|
|
187
193
|
)
|
|
188
194
|
account_id: Mapped[int] = mapped_column(ForeignKey("bank_accounts_view.id"))
|
|
189
195
|
transaction_date: Mapped[datetime.date]
|
|
190
|
-
merchant: Mapped[
|
|
196
|
+
merchant: Mapped[str | None]
|
|
191
197
|
# Relationships
|
|
192
198
|
view: Mapped["BankTransactionView"] = relationship(
|
|
193
199
|
back_populates="transaction", uselist=False, viewonly=True
|
|
194
200
|
)
|
|
201
|
+
internal_transaction: Mapped["InternalTransaction"] = relationship(
|
|
202
|
+
back_populates="bank_transactions"
|
|
203
|
+
)
|
|
195
204
|
|
|
196
205
|
|
|
197
206
|
class BankTransactionView(AuthorizedAccessMixin, Model):
|
|
@@ -203,23 +212,25 @@ class BankTransactionView(AuthorizedAccessMixin, Model):
|
|
|
203
212
|
id: Mapped[int] = mapped_column(
|
|
204
213
|
ForeignKey("bank_transactions.id"), primary_key=True
|
|
205
214
|
)
|
|
206
|
-
internal_transaction_id: Mapped[
|
|
215
|
+
internal_transaction_id: Mapped[int | None] = mapped_column(
|
|
207
216
|
ForeignKey("internal_transactions.id")
|
|
208
217
|
)
|
|
209
218
|
account_id: Mapped[int] = mapped_column(ForeignKey("bank_accounts_view.id"))
|
|
210
219
|
transaction_date: Mapped[datetime.date]
|
|
211
|
-
merchant: Mapped[
|
|
220
|
+
merchant: Mapped[str | None]
|
|
212
221
|
total: Mapped[float]
|
|
213
|
-
notes: Mapped[
|
|
222
|
+
notes: Mapped[str | None]
|
|
214
223
|
balance: Mapped[float]
|
|
215
224
|
# Relationships
|
|
216
225
|
transaction: Mapped["BankTransaction"] = relationship(back_populates="view")
|
|
217
226
|
internal_transaction: Mapped["InternalTransaction"] = relationship(
|
|
218
|
-
back_populates="
|
|
227
|
+
back_populates="bank_transaction_views"
|
|
228
|
+
)
|
|
229
|
+
account_view: Mapped["BankAccountView"] = relationship(
|
|
230
|
+
back_populates="transaction_views", viewonly=True
|
|
219
231
|
)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
back_populates="transaction", lazy="selectin"
|
|
232
|
+
subtransactions: Mapped[list["BankSubtransaction"]] = relationship(
|
|
233
|
+
back_populates="transaction_view", lazy="selectin", cascade="all, delete"
|
|
223
234
|
)
|
|
224
235
|
|
|
225
236
|
|
|
@@ -232,10 +243,10 @@ class BankSubtransaction(AuthorizedAccessMixin, Model):
|
|
|
232
243
|
subtotal: Mapped[float]
|
|
233
244
|
note: Mapped[str]
|
|
234
245
|
# Relationships
|
|
235
|
-
|
|
246
|
+
transaction_view: Mapped["BankTransactionView"] = relationship(
|
|
236
247
|
back_populates="subtransactions", viewonly=True
|
|
237
248
|
)
|
|
238
|
-
tags: Mapped[
|
|
249
|
+
tags: Mapped[list["TransactionTag"]] = relationship(
|
|
239
250
|
back_populates="bank_subtransactions",
|
|
240
251
|
secondary=bank_tag_link_table,
|
|
241
252
|
lazy="selectin",
|
|
@@ -253,7 +264,7 @@ class CreditAccount(AuthorizedAccessMixin, Model):
|
|
|
253
264
|
# ((Should probably have an 'active' field))
|
|
254
265
|
# Relationships
|
|
255
266
|
bank: Mapped["Bank"] = relationship(back_populates="credit_accounts")
|
|
256
|
-
cards: Mapped[
|
|
267
|
+
cards: Mapped[list["CreditCard"]] = relationship(
|
|
257
268
|
back_populates="account", cascade="all, delete"
|
|
258
269
|
)
|
|
259
270
|
|
|
@@ -268,7 +279,7 @@ class CreditCard(AuthorizedAccessMixin, Model):
|
|
|
268
279
|
active: Mapped[int]
|
|
269
280
|
# Relationships
|
|
270
281
|
account: Mapped["CreditAccount"] = relationship(back_populates="cards")
|
|
271
|
-
|
|
282
|
+
statement_views: Mapped[list["CreditStatementView"]] = relationship(
|
|
272
283
|
back_populates="card", viewonly=True
|
|
273
284
|
)
|
|
274
285
|
|
|
@@ -301,9 +312,9 @@ class CreditStatementView(AuthorizedAccessMixin, Model):
|
|
|
301
312
|
payment_date: Mapped[datetime.date]
|
|
302
313
|
# Relationships
|
|
303
314
|
statement: Mapped["CreditStatement"] = relationship(back_populates="view")
|
|
304
|
-
card: Mapped["CreditCard"] = relationship(back_populates="
|
|
305
|
-
|
|
306
|
-
back_populates="
|
|
315
|
+
card: Mapped["CreditCard"] = relationship(back_populates="statement_views")
|
|
316
|
+
transaction_views: Mapped[list["CreditTransactionView"]] = relationship(
|
|
317
|
+
back_populates="statement_view", viewonly=True
|
|
307
318
|
)
|
|
308
319
|
|
|
309
320
|
|
|
@@ -314,7 +325,7 @@ class CreditTransaction(AuthorizedAccessMixin, Model):
|
|
|
314
325
|
subtype = "credit"
|
|
315
326
|
# Columns
|
|
316
327
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
317
|
-
internal_transaction_id: Mapped[
|
|
328
|
+
internal_transaction_id: Mapped[int | None] = mapped_column(
|
|
318
329
|
ForeignKey("internal_transactions.id")
|
|
319
330
|
)
|
|
320
331
|
statement_id: Mapped[int] = mapped_column(ForeignKey("credit_statements_view.id"))
|
|
@@ -324,6 +335,9 @@ class CreditTransaction(AuthorizedAccessMixin, Model):
|
|
|
324
335
|
view: Mapped["CreditTransactionView"] = relationship(
|
|
325
336
|
back_populates="transaction", uselist=False, viewonly=True
|
|
326
337
|
)
|
|
338
|
+
internal_transaction: Mapped["InternalTransaction"] = relationship(
|
|
339
|
+
back_populates="credit_transactions"
|
|
340
|
+
)
|
|
327
341
|
|
|
328
342
|
|
|
329
343
|
class CreditTransactionView(AuthorizedAccessMixin, Model):
|
|
@@ -335,7 +349,7 @@ class CreditTransactionView(AuthorizedAccessMixin, Model):
|
|
|
335
349
|
id: Mapped[int] = mapped_column(
|
|
336
350
|
ForeignKey("credit_transactions.id"), primary_key=True
|
|
337
351
|
)
|
|
338
|
-
internal_transaction_id: Mapped[
|
|
352
|
+
internal_transaction_id: Mapped[int | None] = mapped_column(
|
|
339
353
|
ForeignKey("internal_transactions.id")
|
|
340
354
|
)
|
|
341
355
|
statement_id: Mapped[int] = mapped_column(ForeignKey("credit_statements_view.id"))
|
|
@@ -348,13 +362,13 @@ class CreditTransactionView(AuthorizedAccessMixin, Model):
|
|
|
348
362
|
back_populates="view", uselist=False
|
|
349
363
|
)
|
|
350
364
|
internal_transaction: Mapped["InternalTransaction"] = relationship(
|
|
351
|
-
back_populates="
|
|
365
|
+
back_populates="credit_transaction_views"
|
|
352
366
|
)
|
|
353
|
-
|
|
354
|
-
back_populates="
|
|
367
|
+
statement_view: Mapped["CreditStatementView"] = relationship(
|
|
368
|
+
back_populates="transaction_views", viewonly=True
|
|
355
369
|
)
|
|
356
|
-
subtransactions: Mapped[
|
|
357
|
-
back_populates="
|
|
370
|
+
subtransactions: Mapped[list["CreditSubtransaction"]] = relationship(
|
|
371
|
+
back_populates="transaction_view", lazy="selectin", cascade="all, delete"
|
|
358
372
|
)
|
|
359
373
|
|
|
360
374
|
|
|
@@ -375,10 +389,10 @@ class CreditSubtransaction(AuthorizedAccessMixin, Model):
|
|
|
375
389
|
subtotal: Mapped[float]
|
|
376
390
|
note: Mapped[str]
|
|
377
391
|
# Relationships
|
|
378
|
-
|
|
392
|
+
transaction_view: Mapped["CreditTransactionView"] = relationship(
|
|
379
393
|
back_populates="subtransactions", viewonly=True
|
|
380
394
|
)
|
|
381
|
-
tags: Mapped[
|
|
395
|
+
tags: Mapped[list["TransactionTag"]] = relationship(
|
|
382
396
|
back_populates="credit_subtransactions",
|
|
383
397
|
secondary=credit_tag_link_table,
|
|
384
398
|
lazy="selectin",
|
monopyly/database/preloads.sql
CHANGED
|
@@ -4,7 +4,12 @@ INSERT INTO users
|
|
|
4
4
|
VALUES
|
|
5
5
|
(0, 'global', 'n/a');
|
|
6
6
|
|
|
7
|
-
/* Set
|
|
7
|
+
/* Set a default transaction tag for credit payments */
|
|
8
|
+
INSERT INTO transaction_tags
|
|
9
|
+
(user_id, parent_id, tag_name)
|
|
10
|
+
VALUES (0, NULL, 'Credit payments');
|
|
11
|
+
|
|
12
|
+
/* Set some default account types */
|
|
8
13
|
INSERT INTO bank_account_types
|
|
9
14
|
(user_id, type_name, type_abbreviation)
|
|
10
15
|
VALUES
|