diff --git a/main.py b/main.py deleted file mode 100644 index 44cfd5b..0000000 --- a/main.py +++ /dev/null @@ -1,29 +0,0 @@ -import csv -#this opens the csv file and then maps each line to a dictionary with the column headers as the keys. -with open ('./DataFiles/Transactions2014.csv', mode = 'r') as file: - Transactions2014 = csv.DictReader(file) - accountsList = [] - #loops through transactions adding all names to a list of accounts - for lines in Transactions2014: - accountsList.append(lines['From']) - accountsList.append(lines['To']) - #removes duplicates - accountsList = list(set(accountsList)) - accountsDict = {} - #sets balance to 0 in account dictionary - for account in accountsList: - accountsDict[account] = 0 - -#i am unsure why it requires me to open a with block again -#adds the transactions to the accounts in the dictionary -with open ('./DataFiles/Transactions2014.csv', mode = 'r') as file: - Transactions2014 = csv.DictReader(file) - for lines in Transactions2014: - accountsDict[lines['From']] -= float(lines['Amount']) - accountsDict[lines['To']] += float(lines['Amount']) - - -print(accountsList) -print(accountsDict) - -#TODO deal with rounding errors \ No newline at end of file diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..999da36 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,144 @@ +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. + +[[package]] +name = "black" +version = "25.1.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, + {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, + {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, + {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, + {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, + {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, + {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, + {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, + {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, + {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, + {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, + {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, + {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, + {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, + {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, + {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, + {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, + {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, + {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, + {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, + {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, + {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.10)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "click" +version = "8.2.1" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b"}, + {file = "click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +markers = "platform_system == \"Windows\"" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, +] + +[[package]] +name = "packaging" +version = "25.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + +[[package]] +name = "platformdirs" +version = "4.3.8" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, + {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] + +[[package]] +name = "poetry-core" +version = "2.1.3" +description = "Poetry PEP 517 Build Backend" +optional = false +python-versions = "<4.0,>=3.9" +groups = ["main"] +files = [ + {file = "poetry_core-2.1.3-py3-none-any.whl", hash = "sha256:2c704f05016698a54ca1d327f46ce2426d72eaca6ff614132c8477c292266771"}, + {file = "poetry_core-2.1.3.tar.gz", hash = "sha256:0522a015477ed622c89aad56a477a57813cace0c8e7ff2a2906b7ef4a2e296a4"}, +] + +[metadata] +lock-version = "2.1" +python-versions = "^3.13" +content-hash = "030ac4bc503940959814905e3dc89a14c83db26b6422776f69dd4946792cf0c8" diff --git a/pyproject.toml b/pyproject.toml index dce8eb1..f6f31bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,19 @@ requires-python = ">=3.13" dependencies = [ ] +[tool.poetry] +package-mode = false + +[tool.poetry.dependencies] +python = "^3.13" +poetry-core = ">=2.0.0,<3.0.0" + +[tool.poetry.group.dev.dependencies] +black = "^25.1.0" [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.poetry.scripts] +supportbank = "main:main" \ No newline at end of file diff --git a/supportbank/DataFiles/DodgyTransactions2015.csv b/supportbank/DataFiles/DodgyTransactions2015.csv new file mode 100644 index 0000000..e443ddf --- /dev/null +++ b/supportbank/DataFiles/DodgyTransactions2015.csv @@ -0,0 +1,52 @@ +Date,From,To,Narrative,Amount +01/01/2015,Laura B,Sarah T,Misc Morale,10.54 +04/01/2015,Stephen S,Gergana I,Lunch,3.22 +07/01/2015,Ben B,Jon A,Fantasy Football,9.93 +11/01/2015,Ben B,Todd,Lunch,7.33 +12/01/2015,Laura B,Ben B,Beers,8.94 +15/01/2015,Todd,Rob S,Beers,10.19 +16/01/2015,Laura B,Jon A,Lego Assistance,0.69 +18/01/2015,Jon A,Sarah T,Coffee,10.73 +22/01/2015,Gergana I,Todd,Coffee,0.8 +24/01/2015,Gergana I,Chris W,Coffee,8.49 +27/01/2015,Laura B,Tim L,Jenkins Fees,0.52 +29/01/2015,Sam N,Chris W,Lunch,9.01 +01/02/2015,Stephen S,Laura B,Coffee,7.53 +02/02/2015,Stephen S,Rob S,Fantasy Football,7.43 +04/02/2015,Rob S,Stephen S,Fantasy Football,5.78 +06/02/2015,Dan W,Gergana I,Automated Testing Services,10.29 +07/02/2015,Jon A,Chris W,Rails Consultancy,7.37 +10/02/2015,Sam N,Gergana I,Sandbox Help,9.84 +11/02/2015,Chris W,Stephen S,Misc Morale,0.68 +13/02/2015,Laura B,Gergana I,Beers,6.56 +16/02/2015,Chris W,Dan W,Jenkins Fees,1.28 +17/02/2015,Sarah T,Dan W,Sandbox Help,11.48 +18/02/2015,Stephen S,Rob S,Lego Assistance,4.83 +21/02/2015,Dan W,Ben B,Pokemon Training,0.5 +24/02/2015,Todd,Gergana I,Coffee,9.08 +26/02/2015,Stephen S,Jon A,Pokemon Training,4.23 +01/03/2015,Ben B,Sam N,Lunch,One Cheeseburger +02/03/2015,Todd,Chris W,Sandbox Help,1.92 +04/03/2015,Laura B,Jon A,Sandcastle Help,9.09 +06/03/2015,Stephen S,Gergana I,Lego Assistance,9.4 +08/03/2015,Ben B,Sam N,Pokemon Training,11.32 +11/03/2015,Stephen S,Jon A,Sandcastle Help,11.57 +15/03/2015,Todd,Sam N,Pokemon Training,2.29 +19/03/2015,Laura B,Chris W,Coffee,9.96 +21/03/2015,Jon A,Gergana I,Beers,7.54 +25/03/2015,Gergana I,Ben B,Automated Testing Services,2.39 +28/03/2015,Stephen S,Tim L,Lunch,5.83 +29/03/2015,Gergana I,Ben B,Audit and Other Financial Services,10.85 +30/03/2015,Tim L,Todd,Pokemon Training,8.6 +02/04/2015,Stephen S,Chris W,Pokemon Training,1.11 +05/04/2015,Chris W,Ben B,Lunch,0.96 +09/04/2015,Chris W,Rob S,Audit and Other Financial Services,11.79 +12/04/2015,Gergana I,Laura B,Stationary Items,8.37 +13/04/2015,Laura B,Tim L,Services Rendered,1.27 +15/04/2015,Ben B,Sam N,Lego Assistance,8.5 +19/04/2015,Stephen S,Chris W,White Water Rafting,8.91 +23/04/2015,Tim L,Todd,Misc Morale,8.1 +24/04/2015,Tim L,Sarah T,Arcade Social,6.38 +26/04/2015,Jon A,Todd,Stationary Items,8.44 +27/04/2015,Ben B,Jon A,Pokemon Training,10.91 +Last Thursday,Sarah T,Dan W,Beers,5.42 diff --git a/supportbank/DataFiles/Transactions2012.xml b/supportbank/DataFiles/Transactions2012.xml new file mode 100644 index 0000000..10c4487 --- /dev/null +++ b/supportbank/DataFiles/Transactions2012.xml @@ -0,0 +1,1195 @@ + + + + Snooker Night + 9.22 + + Gergana I + Jon A + + + + Coffee + 6.98 + + Sam N + Dan W + + + + Lunch + 10.67 + + Stephen S + Sarah T + + + + Misc Morale + 7.19 + + Rob S + Sarah T + + + + Fantasy Football + 10.73 + + Tim L + Chris W + + + + Automated Testing Services + 10.1 + + Tim L + Rob S + + + + Beers + 1.79 + + Sarah T + Sam N + + + + Beers + 11.1 + + Dan W + Todd + + + + Coffee + 10.89 + + Chris W + Ben B + + + + Pokemon Training + 3.12 + + Chris W + Tim L + + + + Snooker Night + 2.29 + + Rob S + Tim L + + + + Spline Reticulation + 7.32 + + Chris W + Rob S + + + + Stationary Items + 6.1 + + Stephen S + Gergana I + + + + Lunch + 7.72 + + Stephen S + Todd + + + + Misc Morale + 5.2 + + Stephen S + Laura B + + + + Pokemon Training + 4.67 + + Sam N + Rob S + + + + Coffee + 11.72 + + Ben B + Chris W + + + + Pokemon Training + 6.45 + + Rob S + Jon A + + + + Sandcastle Help + 8.46 + + Todd + Ben B + + + + Lunch + 10.36 + + Laura B + Todd + + + + Pokemon Training + 3.88 + + Chris W + Stephen S + + + + Beers + 9.81 + + Sam N + Dan W + + + + Lunch + 3.67 + + Gergana I + Rob S + + + + Lunch + 0.63 + + Dan W + Tim L + + + + Jenkins Fees + 2.61 + + Tim L + Ben B + + + + Coffee + 4.85 + + Rob S + Ben B + + + + Lunch + 3.14 + + Stephen S + Gergana I + + + + Arcade Social + 9.01 + + Gergana I + Chris W + + + + Lego Assistance + 6.33 + + Gergana I + Rob S + + + + Misc Morale + 11.84 + + Dan W + Stephen S + + + + Spline Reticulation + 9.1 + + Jon A + Sarah T + + + + Coffee + 8.41 + + Stephen S + Dan W + + + + Lunch + 2.38 + + Stephen S + Tim L + + + + Snooker Night + 1.9 + + Gergana I + Laura B + + + + Sandcastle Help + 1.89 + + Sarah T + Gergana I + + + + Stationary Items + 3.8 + + Laura B + Dan W + + + + Fantasy Football + 11.63 + + Dan W + Chris W + + + + Misc Morale + 7.32 + + Dan W + Todd + + + + Audit and Other Financial Services + 6.06 + + Sam N + Chris W + + + + Arcade Social + 11.17 + + Tim L + Chris W + + + + Lego Assistance + 5.49 + + Sarah T + Dan W + + + + Git-Fu Rendered + 0.8 + + Gergana I + Jon A + + + + Lunch + 5.43 + + Sam N + Todd + + + + Lunch + 10.46 + + Laura B + Dan W + + + + Beers + 11.7 + + Laura B + Rob S + + + + Pokemon Training + 11.09 + + Stephen S + Ben B + + + + Audit and Other Financial Services + 8.44 + + Todd + Dan W + + + + Fantasy Football + 0.93 + + Laura B + Sam N + + + + Jenkins Fees + 8.17 + + Laura B + Ben B + + + + Automated Testing Services + 4.79 + + Jon A + Tim L + + + + Snooker Night + 8.24 + + Sarah T + Laura B + + + + Coffee + 9.17 + + Gergana I + Ben B + + + + Pokemon Training + 11.4 + + Todd + Sam N + + + + Sandbox Help + 1.55 + + Sam N + Dan W + + + + Lunch + 4.3 + + Chris W + Rob S + + + + Automated Testing Services + 8.6 + + Rob S + Sam N + + + + Fantasy Football + 10.88 + + Todd + Chris W + + + + Misc Morale + 5.19 + + Sarah T + Chris W + + + + White Water Rafting + 10.73 + + Tim L + Ben B + + + + Arcade Social + 10.73 + + Gergana I + Tim L + + + + Spline Reticulation + 10.84 + + Chris W + Jon A + + + + Coffee + 3.51 + + Laura B + Jon A + + + + Automated Testing Services + 1.78 + + Sarah T + Dan W + + + + Lunch + 3.11 + + Dan W + Stephen S + + + + Lego Assistance + 3.75 + + Sarah T + Chris W + + + + Misc Morale + 4.15 + + Todd + Stephen S + + + + Stationary Items + 9.43 + + Laura B + Chris W + + + + Golf Bets + 1.45 + + Ben B + Chris W + + + + Lunch + 8.71 + + Laura B + Sam N + + + + Lunch + 4.8 + + Stephen S + Todd + + + + Misc Morale + 6.57 + + Dan W + Jon A + + + + Sandcastle Help + 10.78 + + Chris W + Stephen S + + + + Poker Winnings + 0.52 + + Laura B + Jon A + + + + Pokemon Training + 10.86 + + Stephen S + Tim L + + + + Snooker Night + 7.98 + + Jon A + Dan W + + + + Jenkins Fees + 7.6 + + Sarah T + Ben B + + + + Git-Fu Rendered + 7.73 + + Laura B + Rob S + + + + Misc Morale + 9.1 + + Tim L + Ben B + + + + Golf Bets + 1.2 + + Jon A + Laura B + + + + Pokemon Training + 3.57 + + Tim L + Todd + + + + Services Rendered + 1.33 + + Ben B + Chris W + + + + Coffee + 8.55 + + Stephen S + Jon A + + + + Lego Assistance + 10.01 + + Jon A + Rob S + + + + Beers + 5.83 + + Jon A + Sam N + + + + Coffee + 10.52 + + Rob S + Todd + + + + Jenkins Fees + 11.59 + + Todd + Dan W + + + + Coffee + 9.47 + + Jon A + Chris W + + + + Misc Morale + 4.34 + + Rob S + Sam N + + + + Lunch + 10.41 + + Stephen S + Sam N + + + + Sandbox Help + 2.12 + + Tim L + Sam N + + + + Snooker Night + 1.74 + + Laura B + Dan W + + + + Misc Morale + 1.92 + + Chris W + Laura B + + + + Rails Consultancy + 3.2 + + Chris W + Dan W + + + + Beers + 5.38 + + Chris W + Todd + + + + Automated Testing Services + 8.57 + + Todd + Tim L + + + + White Water Rafting + 8.85 + + Sarah T + Stephen S + + + + Misc Morale + 11.22 + + Laura B + Stephen S + + + + Coffee + 0.58 + + Dan W + Gergana I + + + + Audit and Other Financial Services + 10.69 + + Sarah T + Rob S + + + + Coffee + 7.72 + + Sarah T + Dan W + + + + Services Rendered + 9.11 + + Tim L + Sam N + + + + Fantasy Football + 8.65 + + Tim L + Jon A + + + + Coffee + 8.36 + + Sarah T + Dan W + + + + Snooker Night + 3.57 + + Todd + Sam N + + + + Pokemon Training + 10.2 + + Dan W + Tim L + + + + Jenkins Fees + 7.89 + + Stephen S + Chris W + + + + Lunch + 4.41 + + Sarah T + Chris W + + + + Git-Fu Rendered + 10.89 + + Todd + Tim L + + + + Lunch + 0.64 + + Stephen S + Jon A + + + + Beers + 10.25 + + Sam N + Jon A + + + + Sandcastle Help + 4.73 + + Rob S + Gergana I + + + + Golf Bets + 11.83 + + Todd + Chris W + + + + Lunch + 4.42 + + Tim L + Stephen S + + + + Coffee + 3.66 + + Jon A + Ben B + + + + Lunch + 10.25 + + Laura B + Todd + + + + Lunch + 2.48 + + Chris W + Chris W + + + + Lunch + 10.62 + + Laura B + Dan W + + + + Misc Morale + 9.01 + + Jon A + Gergana I + + + + Audit and Other Financial Services + 10.6 + + Ben B + Laura B + + + + Beers + 4.34 + + Todd + Dan W + + + + Sandcastle Help + 10.4 + + Todd + Ben B + + + + Coffee + 2.13 + + Sam N + Laura B + + + + Beers + 6.22 + + Dan W + Sam N + + + + Coffee + 9.29 + + Gergana I + Chris W + + + + Coffee + 11.07 + + Dan W + Sam N + + + + Coffee + 7.83 + + Ben B + Todd + + + + Golf Bets + 5.18 + + Sarah T + Tim L + + + + Beers + 6.66 + + Sam N + Sarah T + + + + Pokemon Training + 3.74 + + Tim L + Sarah T + + + + Coffee + 11.93 + + Tim L + Dan W + + + + Lunch + 2.99 + + Jon A + Tim L + + + + Automated Testing Services + 5.95 + + Stephen S + Chris W + + + + Coffee + 7.08 + + Dan W + Rob S + + + + Git-Fu Rendered + 6.63 + + Rob S + Ben B + + + + Lego Assistance + 0.92 + + Dan W + Gergana I + + + + Coffee + 1.49 + + Rob S + Todd + + + + Services Rendered + 10.78 + + Chris W + Todd + + + + Git-Fu Rendered + 4.53 + + Chris W + Sarah T + + + + Misc Morale + 2.92 + + Gergana I + Sarah T + + + + Jenkins Fees + 7.88 + + Jon A + Tim L + + + + Coffee + 9.31 + + Tim L + Sarah T + + + + Rails Consultancy + 2.44 + + Sam N + Laura B + + + + Stationary Items + 8.89 + + Sarah T + Jon A + + + + Spline Reticulation + 8.73 + + Tim L + Stephen S + + + + Lunch + 10.28 + + Sarah T + Laura B + + + + Lego Assistance + 6.07 + + Stephen S + Sarah T + + + + Coffee + 6.28 + + Tim L + Jon A + + + + Automated Testing Services + 10.98 + + Rob S + Chris W + + + + Services Rendered + 0.77 + + Tim L + Todd + + + \ No newline at end of file diff --git a/supportbank/DataFiles/Transactions2013.json b/supportbank/DataFiles/Transactions2013.json new file mode 100644 index 0000000..760e217 --- /dev/null +++ b/supportbank/DataFiles/Transactions2013.json @@ -0,0 +1,1017 @@ +[ + { + "Date": "2013-01-01T00:00:00", + "FromAccount": "Jon A", + "ToAccount": "Gergana I", + "Narrative": "Sandbox Help", + "Amount": 2.14 + }, + { + "Date": "2013-01-04T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Dan W", + "Narrative": "Coffee", + "Amount": 10.53 + }, + { + "Date": "2013-01-05T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Tim L", + "Narrative": "Sandcastle Help", + "Amount": 10.57 + }, + { + "Date": "2013-01-09T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Rob S", + "Narrative": "Coffee", + "Amount": 8.19 + }, + { + "Date": "2013-01-13T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Sarah T", + "Narrative": "Coffee", + "Amount": 1.01 + }, + { + "Date": "2013-01-15T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Laura B", + "Narrative": "Golf Bets", + "Amount": 2.71 + }, + { + "Date": "2013-01-18T00:00:00", + "FromAccount": "Laura B", + "ToAccount": "Tim L", + "Narrative": "Jenkins Fees", + "Amount": 7.17 + }, + { + "Date": "2013-01-22T00:00:00", + "FromAccount": "Dan W", + "ToAccount": "Rob S", + "Narrative": "Sandcastle Help", + "Amount": 11.12 + }, + { + "Date": "2013-01-25T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Jon A", + "Narrative": "Coffee", + "Amount": 4.86 + }, + { + "Date": "2013-01-28T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Ben B", + "Narrative": "Services Rendered", + "Amount": 1.92 + }, + { + "Date": "2013-01-30T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Todd", + "Narrative": "Jenkins Fees", + "Amount": 11.95 + }, + { + "Date": "2013-01-31T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Chris W", + "Narrative": "Poker Winnings", + "Amount": 7.55 + }, + { + "Date": "2013-02-04T00:00:00", + "FromAccount": "Sam N", + "ToAccount": "Sarah T", + "Narrative": "Arcade Social", + "Amount": 5.52 + }, + { + "Date": "2013-02-06T00:00:00", + "FromAccount": "Dan W", + "ToAccount": "Rob S", + "Narrative": "Snooker Night", + "Amount": 8.07 + }, + { + "Date": "2013-02-07T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Laura B", + "Narrative": "Beers", + "Amount": 7.63 + }, + { + "Date": "2013-02-10T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Todd", + "Narrative": "Snooker Night", + "Amount": 10.4 + }, + { + "Date": "2013-02-12T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Chris W", + "Narrative": "Misc Morale", + "Amount": 5.76 + }, + { + "Date": "2013-02-15T00:00:00", + "FromAccount": "Sam N", + "ToAccount": "Chris W", + "Narrative": "Lunch", + "Amount": 1.54 + }, + { + "Date": "2013-02-18T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Sam N", + "Narrative": "Coffee", + "Amount": 6.98 + }, + { + "Date": "2013-02-22T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Tim L", + "Narrative": "Lunch", + "Amount": 8.77 + }, + { + "Date": "2013-02-26T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Stephen S", + "Narrative": "Audit and Other Financial Services", + "Amount": 5.94 + }, + { + "Date": "2013-02-27T00:00:00", + "FromAccount": "Jon A", + "ToAccount": "Chris W", + "Narrative": "Rails Consultancy", + "Amount": 10.58 + }, + { + "Date": "2013-03-02T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Stephen S", + "Narrative": "Audit and Other Financial Services", + "Amount": 1.73 + }, + { + "Date": "2013-03-06T00:00:00", + "FromAccount": "Laura B", + "ToAccount": "Sam N", + "Narrative": "Stationary Items", + "Amount": 7.26 + }, + { + "Date": "2013-03-08T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Sarah T", + "Narrative": "Pokemon Training", + "Amount": 6.2 + }, + { + "Date": "2013-03-12T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Jon A", + "Narrative": "Automated Testing Services", + "Amount": 0.9 + }, + { + "Date": "2013-03-14T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Chris W", + "Narrative": "Rails Consultancy", + "Amount": 8.97 + }, + { + "Date": "2013-03-17T00:00:00", + "FromAccount": "Dan W", + "ToAccount": "Chris W", + "Narrative": "Audit and Other Financial Services", + "Amount": 3.34 + }, + { + "Date": "2013-03-20T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Rob S", + "Narrative": "Stationary Items", + "Amount": 2.85 + }, + { + "Date": "2013-03-22T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Laura B", + "Narrative": "Git-Fu Rendered", + "Amount": 4.15 + }, + { + "Date": "2013-03-24T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Stephen S", + "Narrative": "Coffee", + "Amount": 2.39 + }, + { + "Date": "2013-03-27T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Dan W", + "Narrative": "Jenkins Fees", + "Amount": 7.82 + }, + { + "Date": "2013-03-28T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Stephen S", + "Narrative": "Sandbox Help", + "Amount": 6.36 + }, + { + "Date": "2013-04-01T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Tim L", + "Narrative": "Coffee", + "Amount": 4.77 + }, + { + "Date": "2013-04-03T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Stephen S", + "Narrative": "Lunch", + "Amount": 2.64 + }, + { + "Date": "2013-04-05T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Chris W", + "Narrative": "Coffee", + "Amount": 3.4 + }, + { + "Date": "2013-04-08T00:00:00", + "FromAccount": "Tim L", + "ToAccount": "Todd", + "Narrative": "Jenkins Fees", + "Amount": 4.27 + }, + { + "Date": "2013-04-09T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Gergana I", + "Narrative": "Misc Morale", + "Amount": 2.6 + }, + { + "Date": "2013-04-11T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Sarah T", + "Narrative": "Lunch", + "Amount": 3 + }, + { + "Date": "2013-04-15T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Chris W", + "Narrative": "Coffee", + "Amount": 5.49 + }, + { + "Date": "2013-04-18T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Ben B", + "Narrative": "Lunch", + "Amount": 9.07 + }, + { + "Date": "2013-04-21T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Sarah T", + "Narrative": "Sandcastle Help", + "Amount": 5.32 + }, + { + "Date": "2013-04-24T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Tim L", + "Narrative": "Fantasy Football", + "Amount": 1.15 + }, + { + "Date": "2013-04-25T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Jon A", + "Narrative": "Coffee", + "Amount": 2.47 + }, + { + "Date": "2013-04-26T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Jon A", + "Narrative": "Misc Morale", + "Amount": 9.1 + }, + { + "Date": "2013-04-27T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Chris W", + "Narrative": "Rails Consultancy", + "Amount": 9.91 + }, + { + "Date": "2013-05-01T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Dan W", + "Narrative": "Git-Fu Rendered", + "Amount": 9.85 + }, + { + "Date": "2013-05-04T00:00:00", + "FromAccount": "Laura B", + "ToAccount": "Dan W", + "Narrative": "Coffee", + "Amount": 1.34 + }, + { + "Date": "2013-05-05T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Ben B", + "Narrative": "Beers", + "Amount": 0.51 + }, + { + "Date": "2013-05-06T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Dan W", + "Narrative": "Git-Fu Rendered", + "Amount": 4.92 + }, + { + "Date": "2013-05-08T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Tim L", + "Narrative": "Coffee", + "Amount": 5.94 + }, + { + "Date": "2013-05-09T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Tim L", + "Narrative": "White Water Rafting", + "Amount": 2.27 + }, + { + "Date": "2013-05-13T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Ben B", + "Narrative": "Coffee", + "Amount": 11.07 + }, + { + "Date": "2013-05-14T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Dan W", + "Narrative": "Rails Consultancy", + "Amount": 9.96 + }, + { + "Date": "2013-05-18T00:00:00", + "FromAccount": "Laura B", + "ToAccount": "Sarah T", + "Narrative": "Lunch", + "Amount": 11.94 + }, + { + "Date": "2013-05-22T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Sam N", + "Narrative": "Pokemon Training", + "Amount": 9.24 + }, + { + "Date": "2013-05-25T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Chris W", + "Narrative": "Sandbox Help", + "Amount": 2.85 + }, + { + "Date": "2013-05-29T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Ben B", + "Narrative": "Audit and Other Financial Services", + "Amount": 1.51 + }, + { + "Date": "2013-06-02T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Ben B", + "Narrative": "Golf Bets", + "Amount": 11.83 + }, + { + "Date": "2013-06-03T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Rob S", + "Narrative": "Lunch", + "Amount": 2.16 + }, + { + "Date": "2013-06-05T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Dan W", + "Narrative": "Golf Bets", + "Amount": 1.96 + }, + { + "Date": "2013-06-06T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Jon A", + "Narrative": "Pokemon Training", + "Amount": 1.06 + }, + { + "Date": "2013-06-10T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Gergana I", + "Narrative": "Lego Assistance", + "Amount": 10.81 + }, + { + "Date": "2013-06-12T00:00:00", + "FromAccount": "Jon A", + "ToAccount": "Ben B", + "Narrative": "Sandcastle Help", + "Amount": 6.75 + }, + { + "Date": "2013-06-13T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Sarah T", + "Narrative": "Poker Winnings", + "Amount": 5.15 + }, + { + "Date": "2013-06-16T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Dan W", + "Narrative": "Misc Morale", + "Amount": 9.24 + }, + { + "Date": "2013-06-19T00:00:00", + "FromAccount": "Laura B", + "ToAccount": "Jon A", + "Narrative": "Coffee", + "Amount": 3.68 + }, + { + "Date": "2013-06-21T00:00:00", + "FromAccount": "Dan W", + "ToAccount": "Todd", + "Narrative": "Lunch", + "Amount": 5.43 + }, + { + "Date": "2013-06-22T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Tim L", + "Narrative": "Stationary Items", + "Amount": 0.98 + }, + { + "Date": "2013-06-23T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Jon A", + "Narrative": "Audit and Other Financial Services", + "Amount": 6.12 + }, + { + "Date": "2013-06-26T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Sarah T", + "Narrative": "Lunch", + "Amount": 8.39 + }, + { + "Date": "2013-06-27T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Ben B", + "Narrative": "Beers", + "Amount": 10.41 + }, + { + "Date": "2013-06-30T00:00:00", + "FromAccount": "Tim L", + "ToAccount": "Laura B", + "Narrative": "Lunch", + "Amount": 6.51 + }, + { + "Date": "2013-07-01T00:00:00", + "FromAccount": "Tim L", + "ToAccount": "Jon A", + "Narrative": "Misc Morale", + "Amount": 1.48 + }, + { + "Date": "2013-07-04T00:00:00", + "FromAccount": "Tim L", + "ToAccount": "Chris W", + "Narrative": "Poker Winnings", + "Amount": 5.63 + }, + { + "Date": "2013-07-05T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Sam N", + "Narrative": "Lunch", + "Amount": 6.73 + }, + { + "Date": "2013-07-07T00:00:00", + "FromAccount": "Jon A", + "ToAccount": "Rob S", + "Narrative": "Lunch", + "Amount": 6.69 + }, + { + "Date": "2013-07-10T00:00:00", + "FromAccount": "Dan W", + "ToAccount": "Sarah T", + "Narrative": "Lunch", + "Amount": 3.88 + }, + { + "Date": "2013-07-13T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Tim L", + "Narrative": "Misc Morale", + "Amount": 2.08 + }, + { + "Date": "2013-07-16T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Gergana I", + "Narrative": "Coffee", + "Amount": 6.95 + }, + { + "Date": "2013-07-19T00:00:00", + "FromAccount": "Dan W", + "ToAccount": "Stephen S", + "Narrative": "Arcade Social", + "Amount": 3.21 + }, + { + "Date": "2013-07-23T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Stephen S", + "Narrative": "Services Rendered", + "Amount": 11.17 + }, + { + "Date": "2013-07-27T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Tim L", + "Narrative": "Coffee", + "Amount": 4.29 + }, + { + "Date": "2013-07-30T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Todd", + "Narrative": "Beers", + "Amount": 0.69 + }, + { + "Date": "2013-07-31T00:00:00", + "FromAccount": "Dan W", + "ToAccount": "Sam N", + "Narrative": "Pokemon Training", + "Amount": 1.2 + }, + { + "Date": "2013-08-01T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Todd", + "Narrative": "Lunch", + "Amount": 11.18 + }, + { + "Date": "2013-08-05T00:00:00", + "FromAccount": "Laura B", + "ToAccount": "Tim L", + "Narrative": "Jenkins Fees", + "Amount": 11.34 + }, + { + "Date": "2013-08-07T00:00:00", + "FromAccount": "Jon A", + "ToAccount": "Rob S", + "Narrative": "Poker Winnings", + "Amount": 10.78 + }, + { + "Date": "2013-08-08T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Stephen S", + "Narrative": "Lunch", + "Amount": 10.07 + }, + { + "Date": "2013-08-11T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Chris W", + "Narrative": "Lunch", + "Amount": 7.27 + }, + { + "Date": "2013-08-13T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Chris W", + "Narrative": "Sandcastle Help", + "Amount": 9.96 + }, + { + "Date": "2013-08-16T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Ben B", + "Narrative": "Misc Morale", + "Amount": 10.91 + }, + { + "Date": "2013-08-19T00:00:00", + "FromAccount": "Tim L", + "ToAccount": "Sam N", + "Narrative": "Coffee", + "Amount": 7.51 + }, + { + "Date": "2013-08-22T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Laura B", + "Narrative": "Misc Morale", + "Amount": 7.05 + }, + { + "Date": "2013-08-23T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Sam N", + "Narrative": "Beers", + "Amount": 0.6 + }, + { + "Date": "2013-08-26T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Rob S", + "Narrative": "Lunch", + "Amount": 3.85 + }, + { + "Date": "2013-08-27T00:00:00", + "FromAccount": "Sam N", + "ToAccount": "Gergana I", + "Narrative": "Fantasy Football", + "Amount": 5.45 + }, + { + "Date": "2013-08-28T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Chris W", + "Narrative": "Jenkins Fees", + "Amount": 11.13 + }, + { + "Date": "2013-08-31T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Laura B", + "Narrative": "Pokemon Training", + "Amount": 5.54 + }, + { + "Date": "2013-09-03T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Ben B", + "Narrative": "Coffee", + "Amount": 9.48 + }, + { + "Date": "2013-09-05T00:00:00", + "FromAccount": "Dan W", + "ToAccount": "Tim L", + "Narrative": "Lunch", + "Amount": 10.58 + }, + { + "Date": "2013-09-07T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Laura B", + "Narrative": "Lunch", + "Amount": 3.32 + }, + { + "Date": "2013-09-10T00:00:00", + "FromAccount": "Tim L", + "ToAccount": "Ben B", + "Narrative": "Misc Morale", + "Amount": 8.68 + }, + { + "Date": "2013-09-12T00:00:00", + "FromAccount": "Tim L", + "ToAccount": "Laura B", + "Narrative": "Lego Assistance", + "Amount": 2.53 + }, + { + "Date": "2013-09-13T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Laura B", + "Narrative": "Services Rendered", + "Amount": 1.96 + }, + { + "Date": "2013-09-16T00:00:00", + "FromAccount": "Sam N", + "ToAccount": "Rob S", + "Narrative": "Beers", + "Amount": 2.81 + }, + { + "Date": "2013-09-19T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Gergana I", + "Narrative": "Beers", + "Amount": 5.52 + }, + { + "Date": "2013-09-22T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Dan W", + "Narrative": "Sandbox Help", + "Amount": 9.28 + }, + { + "Date": "2013-09-23T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Dan W", + "Narrative": "Coffee", + "Amount": 5.13 + }, + { + "Date": "2013-09-27T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Sarah T", + "Narrative": "Stationary Items", + "Amount": 7.05 + }, + { + "Date": "2013-10-01T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Tim L", + "Narrative": "Coffee", + "Amount": 10.13 + }, + { + "Date": "2013-10-04T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Ben B", + "Narrative": "Coffee", + "Amount": 5.96 + }, + { + "Date": "2013-10-08T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Laura B", + "Narrative": "Lunch", + "Amount": 5.33 + }, + { + "Date": "2013-10-11T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Rob S", + "Narrative": "Lunch", + "Amount": 10.62 + }, + { + "Date": "2013-10-12T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Chris W", + "Narrative": "Jenkins Fees", + "Amount": 7.78 + }, + { + "Date": "2013-10-16T00:00:00", + "FromAccount": "Laura B", + "ToAccount": "Rob S", + "Narrative": "Arcade Social", + "Amount": 5.71 + }, + { + "Date": "2013-10-17T00:00:00", + "FromAccount": "Laura B", + "ToAccount": "Jon A", + "Narrative": "Arcade Social", + "Amount": 7.71 + }, + { + "Date": "2013-10-20T00:00:00", + "FromAccount": "Sam N", + "ToAccount": "Sarah T", + "Narrative": "Lunch", + "Amount": 10.6 + }, + { + "Date": "2013-10-23T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Todd", + "Narrative": "Lego Assistance", + "Amount": 3.42 + }, + { + "Date": "2013-10-27T00:00:00", + "FromAccount": "Sam N", + "ToAccount": "Dan W", + "Narrative": "Misc Morale", + "Amount": 6.89 + }, + { + "Date": "2013-10-29T00:00:00", + "FromAccount": "Dan W", + "ToAccount": "Rob S", + "Narrative": "Misc Morale", + "Amount": 9.99 + }, + { + "Date": "2013-11-01T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Laura B", + "Narrative": "Lunch", + "Amount": 7.01 + }, + { + "Date": "2013-11-05T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Rob S", + "Narrative": "Spline Reticulation", + "Amount": 8.3 + }, + { + "Date": "2013-11-07T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Sarah T", + "Narrative": "Lunch", + "Amount": 10.09 + }, + { + "Date": "2013-11-09T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Tim L", + "Narrative": "Stationary Items", + "Amount": 11 + }, + { + "Date": "2013-11-12T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Sam N", + "Narrative": "Misc Morale", + "Amount": 1.25 + }, + { + "Date": "2013-11-15T00:00:00", + "FromAccount": "Jon A", + "ToAccount": "Tim L", + "Narrative": "Sandbox Help", + "Amount": 9.13 + }, + { + "Date": "2013-11-18T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Dan W", + "Narrative": "Services Rendered", + "Amount": 9.4 + }, + { + "Date": "2013-11-21T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Chris W", + "Narrative": "Misc Morale", + "Amount": 2.53 + }, + { + "Date": "2013-11-24T00:00:00", + "FromAccount": "Tim L", + "ToAccount": "Sam N", + "Narrative": "Rails Consultancy", + "Amount": 7.59 + }, + { + "Date": "2013-11-28T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Todd", + "Narrative": "Golf Bets", + "Amount": 2.15 + }, + { + "Date": "2013-11-29T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Sam N", + "Narrative": "Pokemon Training", + "Amount": 4.01 + }, + { + "Date": "2013-12-01T00:00:00", + "FromAccount": "Sam N", + "ToAccount": "Sarah T", + "Narrative": "Lunch", + "Amount": 6.35 + }, + { + "Date": "2013-12-02T00:00:00", + "FromAccount": "Jon A", + "ToAccount": "Todd", + "Narrative": "Misc Morale", + "Amount": 10.19 + }, + { + "Date": "2013-12-05T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Sam N", + "Narrative": "Coffee", + "Amount": 9 + }, + { + "Date": "2013-12-09T00:00:00", + "FromAccount": "Laura B", + "ToAccount": "Tim L", + "Narrative": "Rails Consultancy", + "Amount": 9.39 + }, + { + "Date": "2013-12-12T00:00:00", + "FromAccount": "Chris W", + "ToAccount": "Tim L", + "Narrative": "Coffee", + "Amount": 11.44 + }, + { + "Date": "2013-12-13T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Tim L", + "Narrative": "Misc Morale", + "Amount": 9.19 + }, + { + "Date": "2013-12-17T00:00:00", + "FromAccount": "Sarah T", + "ToAccount": "Ben B", + "Narrative": "Pokemon Training", + "Amount": 8.72 + }, + { + "Date": "2013-12-19T00:00:00", + "FromAccount": "Todd", + "ToAccount": "Ben B", + "Narrative": "Pokemon Training", + "Amount": 8.72 + }, + { + "Date": "2013-12-22T00:00:00", + "FromAccount": "Gergana I", + "ToAccount": "Sam N", + "Narrative": "Lunch", + "Amount": 1.32 + }, + { + "Date": "2013-12-24T00:00:00", + "FromAccount": "Ben B", + "ToAccount": "Rob S", + "Narrative": "Snooker Night", + "Amount": 10.14 + }, + { + "Date": "2013-12-27T00:00:00", + "FromAccount": "Stephen S", + "ToAccount": "Todd", + "Narrative": "Spline Reticulation", + "Amount": 4.34 + }, + { + "Date": "2013-12-28T00:00:00", + "FromAccount": "Jon A", + "ToAccount": "Chris W", + "Narrative": "Beers", + "Amount": 5.99 + }, + { + "Date": "2013-12-30T00:00:00", + "FromAccount": "Rob S", + "ToAccount": "Sam N", + "Narrative": "Misc Morale", + "Amount": 2.54 + } +] \ No newline at end of file diff --git a/DataFiles/Transactions2014.csv b/supportbank/DataFiles/Transactions2014.csv similarity index 100% rename from DataFiles/Transactions2014.csv rename to supportbank/DataFiles/Transactions2014.csv diff --git a/supportbank/__init__.py b/supportbank/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/supportbank/main.py b/supportbank/main.py new file mode 100644 index 0000000..032aab2 --- /dev/null +++ b/supportbank/main.py @@ -0,0 +1,217 @@ +import csv +import json +import logging +import os +from datetime import datetime +import xml.etree.ElementTree as ET + +# Logging setup +logging.basicConfig(filename="SupportBank.log", filemode="w", level=logging.DEBUG) +logger = logging.getLogger() +logger.info("Logging started.") + + +class Transaction: + def __init__(self, data): + raw_date = data.get("Date") or data.get("date") + self.date = self.normalize_date(raw_date) + self.from_account = data.get("From") or data.get("fromAccount") or data.get("FromAccount") + self.to_account = data.get("To") or data.get("toAccount") or data.get("ToAccount") + self.narrative = data.get("Narrative") or data.get("narrative") or "No Narrative" + amount = data.get("Amount") or data.get("amount") or "0" + self.amount = float(amount) + + @staticmethod + def normalize_date(date_str): + known_formats = [ + "%d/%m/%Y", + "%Y-%m-%d", + "%Y-%m-%dT%H:%M:%S", + "%Y-%m-%dT%H:%M:%S.%f", + ] + for fmt in known_formats: + try: + dt = datetime.strptime(date_str, fmt) + return dt.strftime("%d/%m/%Y") + except (ValueError, TypeError): + continue + return "01/01/1970" # fallback + + +class Account: + def __init__(self, name): + self.name = name + self.balance = 0 + self.transactions = [] + + def apply_transaction(self, tx): + if tx.from_account == self.name: + self.balance -= int(tx.amount * 100) + if tx.to_account == self.name: + self.balance += int(tx.amount * 100) + self.transactions.append(tx) + + +def read_transactions(filepath): + transactions = [] + try: + if filepath.endswith(".json"): + with open(filepath, "r") as f: + data = json.load(f) + for item in data: + try: + transactions.append(Transaction(item)) + except Exception as e: + logger.warning(f"Invalid transaction in JSON: {item} — {e}") + elif filepath.endswith(".csv"): + with open(filepath, "r", newline='') as f: + reader = csv.DictReader(f) + for row in reader: + try: + transactions.append(Transaction(row)) + except Exception as e: + logger.warning(f"Invalid transaction in CSV: {row} — {e}") + elif filepath.endswith(".xml"): + tree = ET.parse(filepath) + root = tree.getroot() + for elem in root.findall(".//SupportTransaction"): + try: + transaction_data = { + "Date": elem.find("Date").text, + "From": elem.find("Parties/From").text, + "To": elem.find("Parties/To").text, + "Narrative": elem.find("Description").text, + "Amount": elem.find("Value").text, + } + transactions.append(Transaction(transaction_data)) + except Exception as e: + logger.warning(f"Invalid transaction in XML: {ET.tostring(elem)} — {e}") + else: + logger.warning(f"Unsupported file type: {filepath}") + except Exception as e: + logger.error(f"Failed to read file {filepath}: {e}") + return transactions + + +def list_all(transactions): + accounts = {} + for tx in transactions: + for name in [tx.from_account, tx.to_account]: + if name and name not in accounts: + accounts[name] = Account(name) + if tx.from_account: + accounts[tx.from_account].apply_transaction(tx) + if tx.to_account: + accounts[tx.to_account].apply_transaction(tx) + + print("\nAccount Balances:") + for account in accounts.values(): + print(f"{account.name}: £{account.balance / 100:.2f}") + + +def list_transactions(account_name, transactions): + found = False + relevant = [tx for tx in transactions if tx.from_account == account_name or tx.to_account == account_name] + relevant.sort(key=lambda tx: datetime.strptime(tx.date, "%d/%m/%Y")) + + for tx in relevant: + print(f"{tx.date} | From: {tx.from_account} | To: {tx.to_account} | {tx.narrative} | £{tx.amount:.2f}") + found = True + + if not found: + print(f"No transactions found for account: {account_name}") + + +def list_available_data_files(): + try: + data_dir = "./DataFiles" + files = [f for f in os.listdir(data_dir) if f.endswith((".csv", ".json", ".xml"))] + if not files: + print("No data files found.") + return files + except FileNotFoundError: + print("The ./DataFiles directory does not exist.") + return [] + + +def main(): + print("Welcome to SupportBank") + while True: + print("\n1. List all balances from a single file") + print("2. List transactions for an account from a single file") + print("3. List all balances across all data files") + print("4. List all transactions for an account across all data files") + print("5. Quit") + choice = input("Enter your choice: ").strip() + + if choice == "1": + files = list_available_data_files() + if not files: + continue + filename = input("Enter filename: ").strip() + transactions = read_transactions(f"./DataFiles/{filename}") + list_all(transactions) + + elif choice == "2": + files = list_available_data_files() + if not files: + continue + filename = input("Enter filename: ").strip() + account = input("Enter account name: ").strip() + transactions = read_transactions(f"./DataFiles/{filename}") + list_transactions(account, transactions) + + elif choice == "3": + files = list_available_data_files() + all_transactions = [] + for filename in files: + all_transactions.extend(read_transactions(f"./DataFiles/{filename}")) + list_all(all_transactions) + + elif choice == "4": + files = list_available_data_files() + all_transactions = [] + for filename in files: + all_transactions.extend(read_transactions(f"./DataFiles/{filename}")) + + account_names = set() + for tx in all_transactions: + if tx.from_account: + account_names.add(tx.from_account) + if tx.to_account: + account_names.add(tx.to_account) + + if not account_names: + print("No accounts found.") + continue + + sorted_accounts = sorted(account_names) + for i, name in enumerate(sorted_accounts, 1): + print(f"{i}. {name}") + + selection = input("Select an account by number or name: ").strip() + if selection.isdigit(): + idx = int(selection) + if 1 <= idx <= len(sorted_accounts): + account = sorted_accounts[idx - 1] + else: + print("Invalid number.") + continue + else: + account = selection if selection in account_names else None + if not account: + print("Invalid account.") + continue + + print(f"\nAll transactions for '{account}':") + list_transactions(account, all_transactions) + + elif choice == "5": + print("Goodbye!") + break + else: + print("Invalid choice. Try again.") + + +if __name__ == "__main__": + main()