monopyly 1.4.4__tar.gz → 1.4.6__tar.gz

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.
Files changed (205) hide show
  1. {monopyly-1.4.4 → monopyly-1.4.6}/PKG-INFO +7 -7
  2. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/__init__.py +2 -1
  3. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/_version.py +2 -2
  4. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/auth/blueprint.py +1 -0
  5. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/auth/routes.py +1 -0
  6. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/auth/tools.py +1 -0
  7. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/banking/accounts.py +2 -1
  8. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/banking/actions.py +1 -0
  9. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/banking/banks.py +1 -0
  10. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/banking/blueprint.py +1 -0
  11. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/banking/filters.py +1 -0
  12. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/banking/forms.py +2 -1
  13. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/banking/routes.py +1 -0
  14. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/banking/transactions.py +1 -0
  15. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/cli/apps.py +1 -0
  16. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/common/forms/_forms.py +11 -10
  17. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/common/forms/fields.py +10 -0
  18. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/common/forms/utils.py +2 -1
  19. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/common/forms/validators.py +1 -0
  20. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/common/transactions.py +2 -1
  21. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/common/utils.py +1 -0
  22. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/config/default_settings.py +1 -0
  23. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/config/settings.py +1 -0
  24. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/core/actions.py +1 -0
  25. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/core/blueprint.py +1 -0
  26. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/core/context_processors.py +1 -0
  27. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/core/filters.py +3 -2
  28. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/core/internal_transactions.py +1 -0
  29. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/core/routes.py +1 -0
  30. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/credit/accounts.py +1 -0
  31. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/credit/actions.py +30 -2
  32. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/credit/blueprint.py +1 -0
  33. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/credit/cards.py +1 -0
  34. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/credit/forms.py +14 -6
  35. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/credit/routes.py +3 -5
  36. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/credit/statements.py +22 -1
  37. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/credit/transactions/__init__.py +1 -0
  38. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/credit/transactions/_transactions.py +1 -0
  39. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/database/__init__.py +2 -1
  40. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/database/models.py +14 -0
  41. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/css/style.css +4 -0
  42. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/auth/login.html +1 -1
  43. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/auth/register.html +1 -1
  44. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/account_summaries.html +1 -1
  45. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/account_summary.html +1 -1
  46. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transaction_form/transaction_form.html +1 -1
  47. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transactions_table/expanded_row_content.html +1 -1
  48. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/card_graphic/card_back.html +1 -1
  49. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/statement_summary.html +3 -3
  50. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/index.html +1 -1
  51. {monopyly-1.4.4 → monopyly-1.4.6}/pyproject.toml +6 -6
  52. {monopyly-1.4.4 → monopyly-1.4.6}/.gitignore +0 -0
  53. {monopyly-1.4.4 → monopyly-1.4.6}/COPYING +0 -0
  54. {monopyly-1.4.4 → monopyly-1.4.6}/LICENSE +0 -0
  55. {monopyly-1.4.4 → monopyly-1.4.6}/README.md +0 -0
  56. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/README.md +0 -0
  57. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/auth/actions.py +0 -0
  58. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/cli/run.py +0 -0
  59. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/common/forms/__init__.py +0 -0
  60. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/config/__init__.py +0 -0
  61. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/database/preloads.sql +0 -0
  62. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/database/schema.sql +0 -0
  63. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/database/views.sql +0 -0
  64. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/browserconfig.xml +0 -0
  65. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-114.png +0 -0
  66. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-120.png +0 -0
  67. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-144.png +0 -0
  68. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-150.png +0 -0
  69. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-152.png +0 -0
  70. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-16.png +0 -0
  71. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-160.png +0 -0
  72. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-180.png +0 -0
  73. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-192.png +0 -0
  74. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-310.png +0 -0
  75. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-32.png +0 -0
  76. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-57.png +0 -0
  77. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-60.png +0 -0
  78. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-64.png +0 -0
  79. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-70.png +0 -0
  80. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-72.png +0 -0
  81. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-76.png +0 -0
  82. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon-96.png +0 -0
  83. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon.ico +0 -0
  84. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/favicon/favicon.png +0 -0
  85. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/about/bank-account-details.png +0 -0
  86. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/about/bank-account-summaries.png +0 -0
  87. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/about/bank-accounts.png +0 -0
  88. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/about/credit-account-details.png +0 -0
  89. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/about/credit-transactions.png +0 -0
  90. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/about/homepage-user.png +0 -0
  91. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/about/homepage.png +0 -0
  92. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/about/statement-details.png +0 -0
  93. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/cards/chase-card.png +0 -0
  94. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/cards/discover-card.png +0 -0
  95. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/cards/new-card.png +0 -0
  96. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/cards/template-card.png +0 -0
  97. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/arrow-down.png +0 -0
  98. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/arrow-left.png +0 -0
  99. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/arrow-up.png +0 -0
  100. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/checkmark.png +0 -0
  101. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/delete-orange-thick.png +0 -0
  102. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/delete-orange.png +0 -0
  103. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/delete-thick.png +0 -0
  104. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/delete.png +0 -0
  105. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/edit.png +0 -0
  106. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/link.png +0 -0
  107. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/minus-thick.png +0 -0
  108. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/minus.png +0 -0
  109. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/plus-thick.png +0 -0
  110. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/plus.png +0 -0
  111. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/refresh.png +0 -0
  112. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/save.png +0 -0
  113. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/sort-asc.png +0 -0
  114. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/sort-desc.png +0 -0
  115. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/statement-pair.svg +0 -0
  116. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/statement.png +0 -0
  117. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/statement.svg +0 -0
  118. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/icons/x-thick.png +0 -0
  119. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/img/statement.png +0 -0
  120. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/jquery-3.7.0.min.js +0 -0
  121. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/add-subtransaction.js +0 -0
  122. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/add-transfer.js +0 -0
  123. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/autocomplete-transaction.js +0 -0
  124. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/bind-tag-actions.js +0 -0
  125. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/create-balance-chart.js +0 -0
  126. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/define-filter.js +0 -0
  127. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/display-new-account-type-inputs.js +0 -0
  128. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/display-new-bank-inputs.js +0 -0
  129. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/display-new-credit-account-inputs.js +0 -0
  130. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/expand-bank-account.js +0 -0
  131. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/expand-bank.js +0 -0
  132. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/expand-transaction.js +0 -0
  133. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/flip-card.js +0 -0
  134. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/hide-homepage-block.js +0 -0
  135. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/infer-card.js +0 -0
  136. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/infer-statement.js +0 -0
  137. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/make-payment.js +0 -0
  138. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/modules/ajax.js +0 -0
  139. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/modules/autocomplete-input.js +0 -0
  140. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/modules/expand-box-row.js +0 -0
  141. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/modules/expand-transaction.js +0 -0
  142. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/modules/manage-acquisition-form.js +0 -0
  143. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/modules/manage-overlays.js +0 -0
  144. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/modules/manage-subforms.js +0 -0
  145. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/modules/update-database-widget.js +0 -0
  146. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/modules/update-display-ajax.js +0 -0
  147. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/show-linked-transaction.js +0 -0
  148. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/update-account-statement-parameters.js +0 -0
  149. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/update-bank-name.js +0 -0
  150. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/update-card-status.js +0 -0
  151. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/update-statement-parameters.js +0 -0
  152. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/update-statements-display.js +0 -0
  153. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/static/js/update-transactions-display.js +0 -0
  154. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/account_form/account_form.html +0 -0
  155. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/account_form/account_form_page_new.html +0 -0
  156. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/account_page.html +0 -0
  157. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/account_summaries_page.html +0 -0
  158. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/accounts_page.html +0 -0
  159. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transaction_form/bank_info_form.html +0 -0
  160. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transaction_form/transaction_form_page.html +0 -0
  161. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transaction_form/transaction_form_page_new.html +0 -0
  162. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transaction_form/transaction_form_page_update.html +0 -0
  163. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transaction_form/transfer_form.html +0 -0
  164. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transactions_table/condensed_row_content.html +0 -0
  165. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transactions_table/transaction_field_titles.html +0 -0
  166. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/banking/transactions_table/transactions.html +0 -0
  167. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/form_page.html +0 -0
  168. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transaction_form/subform.html +0 -0
  169. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transaction_form/subtransaction_subform.html +0 -0
  170. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transaction_form/transaction_form_page.html +0 -0
  171. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transactions_table/linked_bank_transaction.html +0 -0
  172. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transactions_table/linked_credit_transaction.html +0 -0
  173. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transactions_table/linked_transaction_overlay.html +0 -0
  174. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transactions_table/subtransactions.html +0 -0
  175. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transactions_table/transaction_condensed.html +0 -0
  176. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transactions_table/transaction_expanded.html +0 -0
  177. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/common/transactions_table/transactions.html +0 -0
  178. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/account_page.html +0 -0
  179. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/card_form/card_form.html +0 -0
  180. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/card_form/card_form_page_new.html +0 -0
  181. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/card_form/transfer_statement_inquiry.html +0 -0
  182. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/card_graphic/card_front.html +0 -0
  183. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/card_submission_page.html +0 -0
  184. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/cards.html +0 -0
  185. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/cards_page.html +0 -0
  186. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/statement_page.html +0 -0
  187. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/statements.html +0 -0
  188. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/statements_page.html +0 -0
  189. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/tag_tree/subtag_tree.html +0 -0
  190. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/tag_tree/tag_tree.html +0 -0
  191. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/tags_page.html +0 -0
  192. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transaction_form/transaction_form.html +0 -0
  193. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transaction_form/transaction_form_page.html +0 -0
  194. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transaction_form/transaction_form_page_new.html +0 -0
  195. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transaction_form/transaction_form_page_update.html +0 -0
  196. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transaction_submission_page.html +0 -0
  197. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transactions_page.html +0 -0
  198. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transactions_table/condensed_row_content.html +0 -0
  199. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transactions_table/expanded_row_content.html +0 -0
  200. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transactions_table/transaction_field_titles.html +0 -0
  201. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credit/transactions_table/transactions.html +0 -0
  202. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/credits.html +0 -0
  203. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/layout.html +0 -0
  204. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/profile.html +0 -0
  205. {monopyly-1.4.4 → monopyly-1.4.6}/monopyly/templates/story.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: monopyly
3
- Version: 1.4.4
3
+ Version: 1.4.6
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
@@ -25,13 +25,13 @@ Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
25
25
  Requires-Python: <3.11,>=3.10
26
26
  Requires-Dist: authanor==1.1.0
27
27
  Requires-Dist: flask-wtf==1.2.1
28
- Requires-Dist: flask==3.0.0
28
+ Requires-Dist: flask==3.0.3
29
29
  Requires-Dist: fuisce==1.0.2
30
- Requires-Dist: gunicorn==21.2.0
31
- Requires-Dist: markdown==3.5.1
32
- Requires-Dist: python-dateutil==2.8.2
33
- Requires-Dist: rich==13.7.0
34
- Requires-Dist: sqlalchemy==2.0.23
30
+ Requires-Dist: gunicorn==22.0.0
31
+ Requires-Dist: markdown==3.6
32
+ Requires-Dist: python-dateutil==2.9.0
33
+ Requires-Dist: rich==13.7.1
34
+ Requires-Dist: sqlalchemy==2.0.29
35
35
  Description-Content-Type: text/markdown
36
36
 
37
37
  <div id="header">
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Run a development server for the Monopyly app.
3
3
  """
4
+
4
5
  from flask import Flask
5
6
 
6
7
  from monopyly.config import DevelopmentConfig, ProductionConfig
@@ -38,7 +39,7 @@ def register_blueprints(app):
38
39
  """
39
40
  Register blueprints with the app.
40
41
 
41
- Note
42
+ Notes
42
43
  -----
43
44
  Blueprints are imported in this function to avoid loading modules
44
45
  that require database models before those models have been set up
@@ -1,4 +1,4 @@
1
1
  # file generated by setuptools_scm
2
2
  # don't change, don't track in version control
3
- __version__ = version = '1.4.4'
4
- __version_tuple__ = version_tuple = (1, 4, 4)
3
+ __version__ = version = '1.4.6'
4
+ __version_tuple__ = version_tuple = (1, 4, 6)
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Flask blueprint for site authentication.
3
3
  """
4
+
4
5
  from flask import Blueprint
5
6
 
6
7
  # Define the blueprint
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Routes for site authentication.
3
3
  """
4
+
4
5
  from flask import (
5
6
  current_app,
6
7
  flash,
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Tools for dealing with the authorization blueprint.
3
3
  """
4
+
4
5
  import functools
5
6
 
6
7
  from flask import current_app, g, redirect, session, url_for
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Tools for interacting with bank accounts in the database.
3
3
  """
4
+
4
5
  import sqlalchemy.sql.functions as sql_func
5
6
  from authanor.database.handler import DatabaseViewHandler
6
7
  from werkzeug.exceptions import abort
@@ -57,7 +58,7 @@ class BankAccountTypeHandler(
57
58
  query = query.join(BankAccount).join(Bank).distinct()
58
59
  # Get only types for the specified bank
59
60
  query = query.where(Bank.id == bank_id)
60
- account_types = cls._db.session.execute(query).scalars()
61
+ account_types = cls._db.session.scalars(query)
61
62
  return account_types
62
63
 
63
64
  @classmethod
@@ -1,4 +1,5 @@
1
1
  """Module describing logical banking actions (to be used in routes)."""
2
+
2
3
  from ..common.utils import convert_date_to_midnight_timestamp
3
4
  from .accounts import BankAccountHandler, BankAccountTypeHandler
4
5
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Tools for interacting with banks in the database.
3
3
  """
4
+
4
5
  from authanor.database.handler import DatabaseHandler
5
6
 
6
7
  from ..database.models import Bank
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Flask blueprint for bank financials.
3
3
  """
4
+
4
5
  from flask import Blueprint
5
6
 
6
7
  # Define the blueprint
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Filters defined for the banking blueprint.
3
3
  """
4
+
4
5
  from .blueprint import bp
5
6
 
6
7
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Generate banking forms for the user to complete.
3
3
  """
4
+
4
5
  from wtforms.fields import BooleanField, FieldList, FormField, StringField, SubmitField
5
6
  from wtforms.validators import DataRequired, Optional
6
7
 
@@ -162,7 +163,7 @@ class BankTransactionForm(TransactionForm):
162
163
  last_four_digits = LastFourDigitsField(
163
164
  "Last Four Digits", validators=[DataRequired()]
164
165
  )
165
- type_name = StringField("AccountType", validators=[DataRequired()])
166
+ type_name = StringField("Account Type", validators=[DataRequired()])
166
167
 
167
168
  def get_account(self):
168
169
  """Get the bank account described by the form data."""
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Routes for banking financials.
3
3
  """
4
+
4
5
  from flask import jsonify, redirect, render_template, request, url_for
5
6
  from fuisce.database import db_transaction
6
7
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Tools for interacting with the bank transactions in the database.
3
3
  """
4
+
4
5
  from authanor.database.handler import DatabaseViewHandler
5
6
 
6
7
  from ..common.forms.utils import execute_on_form_validation
@@ -1,4 +1,5 @@
1
1
  """Application objects for running the app via the CLI."""
2
+
2
3
  import multiprocessing
3
4
  import subprocess
4
5
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  General form constructions.
3
3
  """
4
+
4
5
  from abc import ABC, abstractmethod
5
6
 
6
7
  from flask_wtf import FlaskForm
@@ -33,16 +34,6 @@ class EntryForm(FlaskForm, metaclass=AbstractEntryFormMixinMeta):
33
34
  """
34
35
  Generate a duplicate prepopulated form.
35
36
 
36
- Note
37
- ----
38
- WTForms requires that a form be instantiated in order to be
39
- able to properly introspect fields. Because of this, this method
40
- will only return a duplicate form matching the type of the
41
- form instance used to call it. Using the form's process method
42
- will not properly handle enumeration of field lists, so it
43
- can not be used as a replacement for populating an existing
44
- form.
45
-
46
37
  Parameters
47
38
  ----------
48
39
  entry : database.models.Model
@@ -54,6 +45,16 @@ class EntryForm(FlaskForm, metaclass=AbstractEntryFormMixinMeta):
54
45
  form : EntryForm
55
46
  A duplicate form, prepopulated with the collected database
56
47
  information.
48
+
49
+ Notes
50
+ -----
51
+ WTForms requires that a form be instantiated in order to be
52
+ able to properly introspect fields. Because of this, this method
53
+ will only return a duplicate form matching the type of the
54
+ form instance used to call it. Using the form's process method
55
+ will not properly handle enumeration of field lists, so it
56
+ can not be used as a replacement for populating an existing
57
+ form.
57
58
  """
58
59
  data = self.gather_entry_data(entry)
59
60
  return self.__class__(data=data)
@@ -1,6 +1,7 @@
1
1
  """
2
2
  General form constructions.
3
3
  """
4
+
4
5
  from abc import ABC, abstractmethod
5
6
 
6
7
  from flask_wtf import FlaskForm
@@ -25,6 +26,15 @@ class DateField(wtforms_fields.DateField):
25
26
  super().__init__(*args, filters=filters, **kwargs)
26
27
 
27
28
 
29
+ class OptionalDateField(DateField):
30
+ """A date field where the field value is optional."""
31
+
32
+ def process_formdata(self, valuelist):
33
+ """Process data from the form, ignoring an ommitted value."""
34
+ if valuelist != [""]:
35
+ super().process_formdata(valuelist)
36
+
37
+
28
38
  class CurrencyField(wtforms_fields.DecimalField):
29
39
  """A decimal field with currency-specific customizations."""
30
40
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  General utility objects for handling forms.
3
3
  """
4
+
4
5
  from functools import wraps
5
6
 
6
7
  from flask import current_app, flash
@@ -73,7 +74,7 @@ class Autocompleter:
73
74
  """Get autocomplete suggestions for a field."""
74
75
  # Get information from the database to use for autocompletion
75
76
  query = model.select_for_user(getattr(model, field))
76
- values = current_app.db.session.execute(query).scalars()
77
+ values = current_app.db.session.scalars(query)
77
78
  suggestions = sort_by_frequency([value for value in values])
78
79
  return suggestions
79
80
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Commonly shared form validators.
3
3
  """
4
+
4
5
  from wtforms.validators import ValidationError
5
6
 
6
7
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Tools for building a common transaction interface.
3
3
  """
4
+
4
5
  from abc import abstractmethod
5
6
 
6
7
  from authanor.database.handler import DatabaseHandler, DatabaseViewHandler
@@ -248,7 +249,7 @@ class TransactionTagHandler(DatabaseHandler, model=TransactionTag):
248
249
  # Filter the query to get only subtags of the given tag
249
250
  parent_id = tag.id if tag else None
250
251
  query = query.where(cls.model.parent_id == parent_id)
251
- subtags = cls._db.session.execute(query).scalars()
252
+ subtags = cls._db.session.scalars(query)
252
253
  return subtags
253
254
 
254
255
  @classmethod
@@ -1,6 +1,7 @@
1
1
  """
2
2
  General utility objects.
3
3
  """
4
+
4
5
  import datetime
5
6
  from collections import Counter
6
7
  from datetime import timezone
@@ -1,4 +1,5 @@
1
1
  """Default configuration settings."""
2
+
2
3
  import json
3
4
  from pathlib import Path
4
5
 
@@ -1,4 +1,5 @@
1
1
  """A module containing objects with various configuration settings."""
2
+
2
3
  import warnings
3
4
  from pathlib import Path
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Module describing logical core actions (to be used in routes)."""
2
+
2
3
  from datetime import datetime
3
4
 
4
5
  import markdown
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Flask blueprint for core functionality.
3
3
  """
4
+
4
5
  from flask import Blueprint
5
6
 
6
7
  # Define the blueprint
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Filters defined for the application.
3
3
  """
4
+
4
5
  from datetime import date
5
6
  from importlib import import_module
6
7
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Filters defined for the application.
3
3
  """
4
+
4
5
  from .blueprint import bp
5
6
 
6
7
 
@@ -29,8 +30,8 @@ def make_ordinal(integer):
29
30
  - 21 => 21st
30
31
  - 101 => 101st
31
32
 
32
- Note
33
- ----
33
+ Notes
34
+ -----
34
35
  This function is an adaptation of the one proposed by Stack Overflow user
35
36
  Florian Brucker (https://stackoverflow.com/a/50992575/8754471).
36
37
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Tools for interacting with internal transactions in the database.
3
3
  """
4
+
4
5
  from flask import current_app
5
6
  from sqlalchemy import insert
6
7
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Routes for core functionality.
3
3
  """
4
+
4
5
  from pathlib import Path
5
6
 
6
7
  from flask import g, render_template, render_template_string, session
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Tools for interacting with credit accounts in the database.
3
3
  """
4
+
4
5
  from authanor.database.handler import DatabaseHandler
5
6
 
6
7
  from ..database.models import CreditAccount
@@ -1,4 +1,5 @@
1
1
  """Module describing logical credit actions (to be used in routes)."""
2
+
2
3
  from ..banking.transactions import record_new_transfer
3
4
  from ..common.forms.utils import execute_on_form_validation
4
5
  from .cards import CreditCardHandler
@@ -12,7 +13,7 @@ def get_card_statement_grouping(cards):
12
13
 
13
14
  Parameters
14
15
  ----------
15
- cards : list of sqlite3.Row
16
+ cards : list of database.models.CreditCard
16
17
  The database card entries for which to get statements.
17
18
 
18
19
  Returns
@@ -30,6 +31,33 @@ def get_card_statement_grouping(cards):
30
31
  return card_statements
31
32
 
32
33
 
34
+ def get_statement_and_transactions(statement_id, transaction_sort_order="DESC"):
35
+ """
36
+ Given a statement ID, get the corresponding statement and transactions.
37
+
38
+ Parameters
39
+ ----------
40
+ statement_id : int
41
+ The ID of the statement to acquire.
42
+ transaction_sort_order : str
43
+ The order to sort transactions returned for the statement. The
44
+ default is 'DESC' for transactions sorted in descending order.
45
+
46
+ Returns
47
+ -------
48
+ statement : database.models.CreditStatementView
49
+ The statement with the given ID.
50
+ transactions : list of database.models.CreditTransactionView
51
+ All transactions on the statement with the given ID.
52
+ """
53
+ statement = CreditStatementHandler.get_entry(statement_id)
54
+ transactions = CreditTransactionHandler.get_transactions(
55
+ statement_ids=(statement_id,),
56
+ sort_order=transaction_sort_order,
57
+ )
58
+ return statement, transactions.all()
59
+
60
+
33
61
  def get_potential_preceding_card(card):
34
62
  """
35
63
  Get the card that this new card may be intended to replace (if any).
@@ -41,7 +69,7 @@ def get_potential_preceding_card(card):
41
69
 
42
70
  Parameters
43
71
  ----------
44
- card : sqlite3.Row
72
+ card : database.models.CreditCard
45
73
  The new card being added to the database.
46
74
 
47
75
  Returns
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Flask blueprint for credit card financials.
3
3
  """
4
+
4
5
  from flask import Blueprint
5
6
 
6
7
  # Define the blueprint
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Tools for interacting with credit cards in the database.
3
3
  """
4
+
4
5
  from authanor.database.handler import DatabaseHandler
5
6
 
6
7
  from ..common.forms.utils import execute_on_form_validation
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Generate credit card forms for the user to complete.
3
3
  """
4
+
4
5
  from werkzeug.exceptions import abort
5
6
  from wtforms.fields import (
6
7
  BooleanField,
@@ -18,8 +19,8 @@ from ..banking.forms import BankSelectField, BankSubform
18
19
  from ..common.forms import AcquisitionSubform, EntryForm, EntrySubform, TransactionForm
19
20
  from ..common.forms.fields import (
20
21
  CustomChoiceSelectField,
21
- DateField,
22
22
  LastFourDigitsField,
23
+ OptionalDateField,
23
24
  StringField,
24
25
  )
25
26
  from ..common.forms.utils import Autocompleter
@@ -69,13 +70,20 @@ class CreditCardForm(EntryForm):
69
70
  statement_issue_day = IntegerField("Statement Issue Day", [Optional()])
70
71
  statement_due_day = IntegerField("Statement Due Day", [Optional()])
71
72
 
72
- def validate(self, *args, **kwargs):
73
- """Validate the subform."""
74
- # Unset subform `CustomChoiceSelectField` values will be invalid
73
+ def validate(self, extra_validators=None):
74
+ """
75
+ Validate the subform.
76
+
77
+ Notes
78
+ -----
79
+ Unset values on the ``CustomChoiceSelectField`` will take a
80
+ default value that will be considered to be invalid. They
81
+ must be replaced (after processing) with the inferred value.
82
+ """
75
83
  if self.bank_info.bank_id.data == -1:
76
84
  account = self.get_account()
77
85
  self.bank_info.bank_id.data = account.bank.id
78
- return super().validate(*args, **kwargs)
86
+ return super().validate(extra_validators=extra_validators)
79
87
 
80
88
  def get_account(self):
81
89
  return self._produce_entry_from_field("account_id")
@@ -185,7 +193,7 @@ class CreditTransactionForm(TransactionForm):
185
193
  # Fields to identify the card/bank information for the statement
186
194
  card_info = FormField(CardSubform)
187
195
  # Fields pertaining to the statement
188
- issue_date = DateField("Statement Date")
196
+ issue_date = OptionalDateField("Statement Date")
189
197
 
190
198
  def get_statement(self, transaction_date):
191
199
  """Get the credit card statement described by the form data."""
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Routes for credit card financials.
3
3
  """
4
+
4
5
  from itertools import islice
5
6
 
6
7
  from flask import flash, g, jsonify, redirect, render_template, request, url_for
@@ -21,6 +22,7 @@ from .accounts import CreditAccountHandler
21
22
  from .actions import (
22
23
  get_card_statement_grouping,
23
24
  get_potential_preceding_card,
25
+ get_statement_and_transactions,
24
26
  make_payment,
25
27
  transfer_credit_card_statement,
26
28
  )
@@ -176,11 +178,7 @@ def update_statements_display():
176
178
  @bp.route("/statement/<int:statement_id>")
177
179
  @login_required
178
180
  def load_statement_details(statement_id):
179
- statement = CreditStatementHandler.get_entry(statement_id)
180
- transactions = CreditTransactionHandler.get_transactions(
181
- statement_ids=(statement_id,),
182
- sort_order="DESC",
183
- )
181
+ statement, transactions = get_statement_and_transactions(statement_id)
184
182
  # Get bank accounts for potential payments
185
183
  bank_accounts = BankAccountHandler.get_accounts()
186
184
  return render_template(
@@ -1,7 +1,9 @@
1
1
  """
2
2
  Tools for interacting with the credit statements in the database.
3
3
  """
4
+
4
5
  from authanor.database.handler import DatabaseViewHandler
6
+ from dateutil.relativedelta import relativedelta
5
7
 
6
8
  from ..common.utils import get_next_occurrence_of_day
7
9
  from ..database.models import (
@@ -135,7 +137,7 @@ class CreditStatementHandler(
135
137
 
136
138
  Returns
137
139
  -------
138
- statement : database.models.CreditStatementView
140
+ statement : database.models.CreditStatement
139
141
  The inferred statement entry for the transaction.
140
142
  """
141
143
  issue_day = card.account.statement_issue_day
@@ -145,6 +147,25 @@ class CreditStatementHandler(
145
147
  statement = cls.add_statement(card, issue_date)
146
148
  return statement
147
149
 
150
+ @classmethod
151
+ @DatabaseViewHandler.view_query
152
+ def get_prior_statement(cls, statement):
153
+ """
154
+ Given a statement, get the immediately preceding statement.
155
+
156
+ Parameters
157
+ ----------
158
+ statement : database.models.CreditStatement
159
+ The statement for which to find the preceding statement.
160
+
161
+ Returns
162
+ -------
163
+ statement : database.models.CreditStatementView
164
+ The statement immediately preceding the given statement.
165
+ """
166
+ issue_date = statement.issue_date + relativedelta(months=-1)
167
+ return cls.find_statement(statement.card.id, issue_date=issue_date)
168
+
148
169
  @classmethod
149
170
  def add_statement(cls, card, issue_date, due_date=None):
150
171
  """Add a statement to the database."""
@@ -1,4 +1,5 @@
1
1
  """
2
2
  Tools for interacting with the credit transactions in the database.
3
3
  """
4
+
4
5
  from ._transactions import CreditTagHandler, CreditTransactionHandler, save_transaction
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Tools for interacting with the credit transactions in the database.
3
3
  """
4
+
4
5
  from authanor.database.handler import DatabaseHandler, DatabaseViewHandler
5
6
 
6
7
  from ...common.forms.utils import execute_on_form_validation
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Expose commonly used database functionality to the rest of the package.
3
3
  """
4
+
4
5
  import sqlite3
5
6
  from pathlib import Path
6
7
 
@@ -49,7 +50,7 @@ class SQLAlchemy(_SQLAlchemy):
49
50
  super().initialize(app)
50
51
 
51
52
 
52
- SQLAlchemy.create_default_interface()
53
+ SQLAlchemy.create_default_interface(echo_engine=False)
53
54
 
54
55
 
55
56
  @click.command("init-db")