major: refactoring

Refactored most imports to relative paths and made some experimental
changes to angular.
This commit is contained in:
Lunaresk 2023-06-19 23:41:40 +02:00
parent b21284f640
commit dceda1446f
79 changed files with 3699 additions and 1637 deletions

View File

@ -17,7 +17,8 @@ pyjwt = "*"
python-dotenv = "*" python-dotenv = "*"
pymupdf = "*" pymupdf = "*"
sqlalchemy-utils = "*" sqlalchemy-utils = "*"
marshmallow = "*" flask-marshmallow = "*"
marshmallow-sqlalchemy = "*"
[dev-packages] [dev-packages]

318
backend/Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "6d99fbd50f22f90168dc9a4ad2b5f7de8526492506f37f34f57ca913ada7f896" "sha256": "169ec66627d3f31fa9a4febd856585fc3cd588f747428f772544d3ca77f54664"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -19,11 +19,11 @@
"default": { "default": {
"alembic": { "alembic": {
"hashes": [ "hashes": [
"sha256:32a69b13a613aeb7e8093f242da60eff9daed13c0df02fff279c1b06c32965d2", "sha256:6a810a6b012c88b33458fceb869aef09ac75d6ace5291915ba7fae44de372c01",
"sha256:b2e0a6cfd3a8ce936a1168320bcbe94aefa3f4463cd773a968a55071beb3cd37" "sha256:dc871798a601fab38332e38d6ddb38d5e734f60034baeb8e2db5b642fccd8ab8"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==1.10.3" "version": "==1.11.1"
}, },
"blinker": { "blinker": {
"hashes": [ "hashes": [
@ -59,27 +59,27 @@
}, },
"dominate": { "dominate": {
"hashes": [ "hashes": [
"sha256:520101360892ebf9d0553f67d37e359ff92403d8a1e33814030503088a05da49", "sha256:1a916479c45b95fedba0d077b081d77c2d2e0f0f484ac827105087af23661d73",
"sha256:5fe4258614687c6d3de67b0bbd881ed435a93a19742ae187344055db17052402" "sha256:4c90c3befaf88e612b71f4b39af7bcbef8977acfa855cec957225a8fbf504007"
], ],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.7.0" "version": "==2.8.0"
}, },
"email-validator": { "email-validator": {
"hashes": [ "hashes": [
"sha256:49a72f5fa6ed26be1c964f0567d931d10bf3fdeeacdf97bc26ef1cd2a44e0bda", "sha256:1ff6e86044200c56ae23595695c54e9614f4a9551e0e393614f764860b3d7900",
"sha256:d178c5c6fa6c6824e9b04f199cf23e79ac15756786573c190d2ad13089411ad2" "sha256:2466ba57cda361fb7309fd3d5a225723c788ca4bbad32a0ebd5373b99730285c"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.3.1" "version": "==2.0.0.post2"
}, },
"flask": { "flask": {
"hashes": [ "hashes": [
"sha256:7eb373984bf1c770023fce9db164ed0c3353cd0b53f130f4693da0ca756a2e6d", "sha256:77fd4e1249d8c9923de34907236b747ced06e5467ecac1a7bb7115ae0e9670b0",
"sha256:c0bec9477df1cb867e5a67c9e1ab758de9cb4a3e52dd70681f59fa40a62b3f2d" "sha256:8c2f9abd47a9e8df7f0c3f091ce9497d011dc3b31effcf4c85a6e2b50f4114ef"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.2.3" "version": "==2.3.2"
}, },
"flask-bootstrap": { "flask-bootstrap": {
"hashes": [ "hashes": [
@ -103,6 +103,14 @@
"index": "pypi", "index": "pypi",
"version": "==0.9.1" "version": "==0.9.1"
}, },
"flask-marshmallow": {
"hashes": [
"sha256:2083ae55bebb5142fff98c6bbd483a2f5dbc531a8bc1be2180ed5f75e7f3fccc",
"sha256:ce08a153f74da6ebfffd8065d1687508b0179df37fff7fc0c8f28ccfb64f1b56"
],
"index": "pypi",
"version": "==0.15.0"
},
"flask-migrate": { "flask-migrate": {
"hashes": [ "hashes": [
"sha256:73293d40b10ac17736e715b377e7b7bde474cb8105165d77474df4c3619b10b3", "sha256:73293d40b10ac17736e715b377e7b7bde474cb8105165d77474df4c3619b10b3",
@ -227,68 +235,76 @@
}, },
"markupsafe": { "markupsafe": {
"hashes": [ "hashes": [
"sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed", "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e",
"sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc", "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e",
"sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2", "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431",
"sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460", "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686",
"sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7", "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559",
"sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0", "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc",
"sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1", "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c",
"sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa", "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0",
"sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03", "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4",
"sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323", "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9",
"sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65", "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575",
"sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013", "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba",
"sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036", "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d",
"sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f", "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3",
"sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4", "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00",
"sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419", "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155",
"sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2", "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac",
"sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619", "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52",
"sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a", "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f",
"sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a", "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8",
"sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd", "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b",
"sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7", "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24",
"sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666", "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea",
"sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65", "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198",
"sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859", "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0",
"sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625", "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee",
"sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff", "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be",
"sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156", "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2",
"sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd", "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707",
"sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba", "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6",
"sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f", "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58",
"sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1", "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779",
"sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094", "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636",
"sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a", "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c",
"sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513", "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad",
"sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed", "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee",
"sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d", "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc",
"sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3", "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2",
"sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147", "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48",
"sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c", "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7",
"sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603", "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e",
"sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601", "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b",
"sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a", "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa",
"sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1", "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5",
"sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d", "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e",
"sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3", "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb",
"sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54", "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9",
"sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2", "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57",
"sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6", "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc",
"sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58" "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==2.1.2" "version": "==2.1.3"
}, },
"marshmallow": { "marshmallow": {
"hashes": [ "hashes": [
"sha256:90032c0fd650ce94b6ec6dc8dfeb0e3ff50c144586462c389b81a07205bedb78", "sha256:90032c0fd650ce94b6ec6dc8dfeb0e3ff50c144586462c389b81a07205bedb78",
"sha256:93f0958568da045b0021ec6aeb7ac37c81bfcccbb9a0e7ed8559885070b3a19b" "sha256:93f0958568da045b0021ec6aeb7ac37c81bfcccbb9a0e7ed8559885070b3a19b"
], ],
"index": "pypi", "markers": "python_version >= '3.7'",
"version": "==3.19.0" "version": "==3.19.0"
}, },
"marshmallow-sqlalchemy": {
"hashes": [
"sha256:3523a774390ef0c1c0f7c708a7519809c5396cf608720f14f55c36f74ff5bbec",
"sha256:3cee0bf61ed10687c0a41448e1916649b28222334a02f7b937c39d1c69c18bee"
],
"index": "pypi",
"version": "==0.29.0"
},
"packaging": { "packaging": {
"hashes": [ "hashes": [
"sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61",
@ -367,47 +383,47 @@
}, },
"pyjwt": { "pyjwt": {
"hashes": [ "hashes": [
"sha256:69285c7e31fc44f68a1feb309e948e0df53259d579295e6cfe2b1792329f05fd", "sha256:ba2b425b15ad5ef12f200dc67dd56af4e26de2331f965c5439994dad075876e1",
"sha256:d83c3d892a77bbb74d3e1a2cfa90afaadb60945205d1095d9221f04466f64c14" "sha256:bd6ca4a3c4285c1a2d4349e5a035fdf8fb94e04ccd0fcbe6ba289dae9cc3e074"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.6.0" "version": "==2.7.0"
}, },
"pymupdf": { "pymupdf": {
"hashes": [ "hashes": [
"sha256:06528ee7a6897044898a137114e9b5c15d8fe0ee37d924377e89a492dc178a7b", "sha256:01daa4e3c2c1b93d357ba0d747d713ad40e0123b9bdca2395bf166f62dd8f703",
"sha256:26f64ade0a0e6e4c508b65a4d72bd875691cf51bb15a2a6051288f6d33816450", "sha256:07d171255964f5a382e280a95a3148c08fc4ec20bf7907e040cf423cf29afe30",
"sha256:363a71e70cff1a7607d7b24dda8ea9c8fb85c147026c934c7ecf6f7c30d2159b", "sha256:0a2040351a1279fafa1db82e5af50a785eb01dc4e1adb3c98e0abfd6e0a4995f",
"sha256:3f5cdef73744c6c30d08a9a44d02eec0d4ca78231657f270995b81e439f66dde", "sha256:0aff7ba35eb2cc285efea87500dd5ee0aaf94f4bb23a79187f0a74101aba7964",
"sha256:4812abe23d489ae1526d2b907930251ed2b23b5ef3c8bb335b89770f56a8b3f1", "sha256:13e90a5301990dafc5bba6bfa32aafca1f35809497c274c9d4af4f4bac2d8870",
"sha256:4d7e1357636b40c12d45d53a8503b30acabe9af4ba9da984ef5a726572523cb0", "sha256:1f00097e8d2bc46dacdb776aeb810b1c760949f6353abdf6d12e8aefdc95dd35",
"sha256:5266cb749873ece1e1e268d6ea693e98088d68482e1ff2279c022f88e2b6b69f", "sha256:201c7aecf9530c3a5aa33cd3d6b68e36492ff9ac48cb270d8f18e66654744419",
"sha256:559e0853124e758e1742bc927acc89448ba6b716e05f6211d64e328cbde90784", "sha256:46c7fab408ae4d55c4181f95a76bc4f365f5ead3291f67274d6fe90f1b90c479",
"sha256:55afc0d990e62ded4475b7a8aea94f08a3a32bcb4d5965f13f75b0c1faa1d460", "sha256:48ece127e202470209dc63ad8fa85f3e19ce302f5af02d38c7fc0b5798b9bfa6",
"sha256:5e55ce8ff69ac28b28db926bed381ca4e97afdeb95ec0b21161bdacfd4056bec", "sha256:4c037d5752efd562ac72e74295dfcc8d8dd406c0f6849054b29d2cbc32237ae0",
"sha256:6e1694e5c0cd8b92d503a506ee8e4ba1bed768528de586889d3ec90e9dc4a7d3", "sha256:4d2422dffdb4f1c2c8128e6d151f4de5e722388df276ac165572ad5290ad228a",
"sha256:7643045803d91a3933590f7980bd5df876a4f30c9254cc16fdf310a6a4db70a3", "sha256:4e0904c9bffdfbb527f4fe293986d74477780f0c98f59fa5b42a95e3e441e1f4",
"sha256:8bd082616fcbfc20187da4941307cca719d8a6426b0d907698d4211654be6ee0", "sha256:5932564a713bd7d576418070c3dd926cb5800edb4411f48813f7694af7386d3e",
"sha256:982ffa5bf1298cda7dde4d4274535ef05cb16bb37877b0cb743aa4236118a5c6", "sha256:5ecd928e96e63092571020973aa145b57b75707f3a3df97c742e563112615891",
"sha256:9ee55e821d740fb83f16b50c8429f4d9df7bbdaf35ea0ac5c8cb4cfe57315995", "sha256:60db199553fc9c88cb9f2afba35f9cd54c042e7a6ea2b151ddcc542e6e75ac61",
"sha256:a3e7f369b4dba0f554caf2ee6dfb118c2e1bdc63f0e663d68ba44f974b2eebde", "sha256:6eddb0975ddd0bcf39812616b5675c26d740f83b12a39c3b5c4425f02c3da754",
"sha256:af1d0b0c3ca2fc82e5cfdd8ab511658dc99ee801ee429e7c50cf0077df88cb40", "sha256:90950b328603a83b26c2eb2af0cf5498582fbbab84e86074bbb0ae44d745e2a3",
"sha256:b5d1fe167cd558b34f6ceae424d826b993e2c1e6cc8ace10e9bfab9cde1737f5", "sha256:932747941ed4973410244376ba77693253e4387e8e09cf2458bc9133348fc16e",
"sha256:b7cb8b367a552f33af4806d8d451c8afc94368ff16e16a3779d360a2f54d22c8", "sha256:9aaf3352d9c443ad7622e70b0ff9124079b09c16a1a1aa3f3dde9ba0e19f32a2",
"sha256:c6c1eaa52ae17950b9970b5da1b5b5aaaab7f11681314a41530e2c1f5e10e4ec", "sha256:9d9bccfb29cbe3962a858c200376d54e7ba64d6f64c0b972ed5b68ff20157b06",
"sha256:ca09707352e506307a47aef69ecdcc340cb56720d5325390d4cfafadb6f05f9c", "sha256:a58af441ce454f33f75a4c93a5f76e4659f2c7c849036180f24ab4b84d9e512f",
"sha256:cabd8c508b41f32b504251abe7f866a6000e188d5022ac690f838cad1cbeacbf", "sha256:a67f2b12120ce9fe5c3f7cb192643134af2c4e28773a2cd5d56cbe1cae66d1b9",
"sha256:d18c7eee58ab67ef78f6efcee09f4cd0f3d4416a6ce1b15d962320ba76f462e6", "sha256:be0803be2709285f17c932ee11d4b7f6d11d3e74e1888094e6310c55e9543673",
"sha256:d86816439954e015e59340a699845d98b88affd64b70e2e94de6cb1383772486", "sha256:bf275e5dbf332554f98b469899e5a0928b91cb574a5319aeecf1b7e8075cf4b7",
"sha256:d962e99eefce970f3122534bec960c77201675297aefe1ca386b7479fa57b477", "sha256:d4ea7b016c4561004b48143b8879e1d888e5ba3a1440e6558ea9a47f0d2e6f65",
"sha256:e1a83d1f2909fc9765bd6c504af8a5e4e0465df7ea8084993fcdea76e995f8af", "sha256:d4f38ecb9518ba2dc12f5f35f33c64ec5466faf20b833f4ac21a2a4190ffef93",
"sha256:e2245a0ba4ce522a5c8812b4b8dac83a43b63e8f4286cd55a80eef932547b019", "sha256:dbffc6cabb0cb20033870bde954bbed1436cf9fce33a14682e283bc893767250",
"sha256:e31ce3675cd92fe2bc585892f31ddf8bf8b5ffeb1a8a1579515d766f06f32ac2", "sha256:e344632215882b49fd2e28ffb848f55b1b34db6b5389917e4865b4d779cbdb4a",
"sha256:e8bb785bcb790d99d989e3a8306189bb7183536e57ef6b30d0669cde931159a5", "sha256:ed4a624ffc9bebe5c67fc80e16798300d404089585bcdac14448034bd38c5072",
"sha256:f20897200a01e967aa9fe87fd9f80786c73c4cae78e9fa4d3e73c9c23e6360d6" "sha256:fa934c1a02f1f3bb04e447b95ef5b19d03cb2575fee76d23cb7a6d0c526444e2"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.22.0" "version": "==1.22.3"
}, },
"python-dotenv": { "python-dotenv": {
"hashes": [ "hashes": [
@ -419,66 +435,66 @@
}, },
"sqlalchemy": { "sqlalchemy": {
"hashes": [ "hashes": [
"sha256:07950fc82f844a2de67ddb4e535f29b65652b4d95e8b847823ce66a6d540a41d", "sha256:0db6734cb5644c55d0262a813b764c6e2cda1e66e939a488b3d6298cdc7344c2",
"sha256:0a865b5ec4ba24f57c33b633b728e43fde77b968911a6046443f581b25d29dd9", "sha256:0e4645b260cfe375a0603aa117f0a47680864cf37833129da870919e88b08d8f",
"sha256:0b49f1f71d7a44329a43d3edd38cc5ee4c058dfef4487498393d16172007954b", "sha256:131f0c894c6572cb1bdcf97c92d999d3128c4ff1ca13061296057072f61afe13",
"sha256:13f984a190d249769a050634b248aef8991acc035e849d02b634ea006c028fa8", "sha256:1e2caba78e7d1f5003e88817b7a1754d4e58f4a8f956dc423bf8e304c568ab09",
"sha256:1b69666e25cc03c602d9d3d460e1281810109e6546739187044fc256c67941ef", "sha256:2de1477af7f48c633b8ecb88245aedd811dca88e88aee9e9d787b388abe74c44",
"sha256:1d06e119cf79a3d80ab069f064a07152eb9ba541d084bdaee728d8a6f03fd03d", "sha256:2f3b6c31b915159b96b68372212fa77f69230b0a32acab40cf539d2823954f5a",
"sha256:246712af9fc761d6c13f4f065470982e175d902e77aa4218c9cb9fc9ff565a0c", "sha256:3ef876615ff4b53e2033022195830ec4941a6e21068611f8d77de60203b90a98",
"sha256:34eb96c1de91d8f31e988302243357bef3f7785e1b728c7d4b98bd0c117dafeb", "sha256:43e69c8c1cea0188b7094e22fb93ae1a1890aac748628b7e925024a206f75368",
"sha256:4c3020afb144572c7bfcba9d7cce57ad42bff6e6115dffcfe2d4ae6d444a214f", "sha256:53081c6fce0d49bb36d05f12dc87e008c9b0df58a163b792c5fc4ac638925f98",
"sha256:4f759eccb66e6d495fb622eb7f4ac146ae674d829942ec18b7f5a35ddf029597", "sha256:5a934eff1a2882137be3384826f997db8441d43b61fda3094923e69fffe474be",
"sha256:68ed381bc340b4a3d373dbfec1a8b971f6350139590c4ca3cb722fdb50035777", "sha256:5e8522b49e0e640287308b68f71cc338446bbe1c226c8f81743baa91b0246e92",
"sha256:6b72dccc5864ea95c93e0a9c4e397708917fb450f96737b4a8395d009f90b868", "sha256:61f2035dea56ff1a429077e481496f813378beb02b823d2e3e7eb05bc1a7a8ca",
"sha256:6e84ab63d25d8564d7a8c05dc080659931a459ee27f6ed1cf4c91f292d184038", "sha256:63ea36c08792a7a8a08958bc806ecff6b491386feeaf14607c3d9d2d9325e67f",
"sha256:734805708632e3965c2c40081f9a59263c29ffa27cba9b02d4d92dfd57ba869f", "sha256:6e85e315725807c127ad8ba3d628fdb861cf9ebfb0e10c39a97c01e257cdd71b",
"sha256:78612edf4ba50d407d0eb3a64e9ec76e6efc2b5d9a5c63415d53e540266a230a", "sha256:7641f6ed2682de84d77c4894cf2e43700f3cf7a729361d7f9cac98febf3d8614",
"sha256:7e472e9627882f2d75b87ff91c5a2bc45b31a226efc7cc0a054a94fffef85862", "sha256:7be04dbe3470fe8dd332fdb48c979887c381ef6c635eddf2dec43d2766111be4",
"sha256:865392a50a721445156809c1a6d6ab6437be70c1c2599f591a8849ed95d3c693", "sha256:81d867c1be5abd49f7e547c108391f371a9d980ba7ec34666c50d683f782b754",
"sha256:8d118e233f416d713aac715e2c1101e17f91e696ff315fc9efbc75b70d11e740", "sha256:8544c6e62eacb77d5106e2055ef10f2407fc0dbd547e879f8745b2032eefd2bc",
"sha256:8d3ece5960b3e821e43a4927cc851b6e84a431976d3ffe02aadb96519044807e", "sha256:8d3cbdb2f07fb0e4b897dc1df39166735e194fb946f28f26f4c9f9801c8b24f7",
"sha256:93c78d42c14aa9a9e0866eacd5b48df40a50d0e2790ee377af7910d224afddcf", "sha256:8d6ef848e5afcd1bda3e9a843751f845c0ca888b61e669237680e913d84ec206",
"sha256:95719215e3ec7337b9f57c3c2eda0e6a7619be194a5166c07c1e599f6afc20fa", "sha256:8e2569dac4e3cb85365b91ab569d06a221e0e17e65ce59949d00c3958946282b",
"sha256:9838bd247ee42eb74193d865e48dd62eb50e45e3fdceb0fdef3351133ee53dcf", "sha256:90d320fde566b864adbc19abb40ecb80f4e25d6f084639969bb972d5cca16858",
"sha256:aa5c270ece17c0c0e0a38f2530c16b20ea05d8b794e46c79171a86b93b758891", "sha256:91eb8f89fcce8f709f8a4d65d265bc48a80264ee14c7c9e955f3222f19b4b39c",
"sha256:ac6a0311fb21a99855953f84c43fcff4bdca27a2ffcc4f4d806b26b54b5cddc9", "sha256:a08a791c75d6154d46914d1e23bd81d9455f2950ec1de81f2723848c593d2c8b",
"sha256:ad5363a1c65fde7b7466769d4261126d07d872fc2e816487ae6cec93da604b6b", "sha256:a2e9f50a906d0b81292576a9fb458f8cace904c81a67088f4a2ca9ff2856f55d",
"sha256:b3e5864eba71a3718236a120547e52c8da2ccb57cc96cecd0480106a0c799c92", "sha256:a5a2856e12cf5f54301ddf043bcbf0552561d61555e1bcf348b63f42b8e1eec2",
"sha256:bbda1da8d541904ba262825a833c9f619e93cb3fd1156be0a5e43cd54d588dcd", "sha256:b2801f85c5c0293aa710f8aa5262c707a83c1c203962ae5a22b4d9095e71aa9d",
"sha256:c6e27189ff9aebfb2c02fd252c629ea58657e7a5ff1a321b7fc9c2bf6dc0b5f3", "sha256:b72f4e4def50414164a1d899f2ce4e782a029fad0ed5585981d1611e8ae29a74",
"sha256:c8239ce63a90007bce479adf5460d48c1adae4b933d8e39a4eafecfc084e503c", "sha256:bdaf89dd82f4a0e1b8b5ffc9cdc0c9551be6175f7eee5af6a838e92ba2e57100",
"sha256:d209594e68bec103ad5243ecac1b40bf5770c9ebf482df7abf175748a34f4853", "sha256:c5e333b81fe10d14efebd4e9429b7bb865ed9463ca8bef07a7136dfa1fd4a37b",
"sha256:d5327f54a9c39e7871fc532639616f3777304364a0bb9b89d6033ad34ef6c5f8", "sha256:ce1fc3f64fd42d5f763d6b83651471f32920338a1ba107a3186211474861af57",
"sha256:db4bd1c4792da753f914ff0b688086b9a8fd78bb9bc5ae8b6d2e65f176b81eb9", "sha256:d0c96592f54edd571e00ba6b1ed5df8263328ca1da9e78088c0ebc93c2e6562c",
"sha256:e4780be0f19e5894c17f75fc8de2fe1ae233ab37827125239ceb593c6f6bd1e2", "sha256:dc97238fa44be86971270943a0c21c19ce18b8d1596919048e57912e8abc02cc",
"sha256:e4a019f723b6c1e6b3781be00fb9e0844bc6156f9951c836ff60787cc3938d76", "sha256:e19546924f0cf2ec930d1faf318b7365e5827276410a513340f31a2b423e96a4",
"sha256:e62c4e762d6fd2901692a093f208a6a6575b930e9458ad58c2a7f080dd6132da", "sha256:f2938edc512dd1fa48653e14c1655ab46144d4450f0e6b33da7acd8ba77fbfd7",
"sha256:e730603cae5747bc6d6dece98b45a57d647ed553c8d5ecef602697b1c1501cf2", "sha256:f387b496a4c9474d8580195bb2660264a3f295a04d3a9d00f4fa15e9e597427e",
"sha256:ebc4eeb1737a5a9bdb0c24f4c982319fa6edd23cdee27180978c29cbb026f2bd", "sha256:f409f35a0330ab0cb18ece736b86d8b8233c64f4461fcb10993f67afc0ac7e5a",
"sha256:ee2946042cc7851842d7a086a92b9b7b494cbe8c3e7e4627e27bc912d3a7655e", "sha256:f662cf69484c59f8a3435902c40dfc34d86050bdb15e23d437074ce9f153306b",
"sha256:f005245e1cb9b8ca53df73ee85e029ac43155e062405015e49ec6187a2e3fb44", "sha256:fbcc51fdbc89fafe4f4fe66f59372a8be88ded04de34ef438ab04f980beb12d4",
"sha256:f49c5d3c070a72ecb96df703966c9678dda0d4cb2e2736f88d15f5e1203b4159", "sha256:fc1dae11bd5167f9eb53b3ccad24a79813004612141e76de21cf4c028dc30b34",
"sha256:f61ab84956dc628c8dfe9d105b6aec38afb96adae3e5e7da6085b583ff6ea789" "sha256:ff6496ad5e9dc8baeb93a151cc2f599d01e5f8928a2aaf0b09a06428fdbaf553"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==2.0.9" "version": "==2.0.16"
}, },
"sqlalchemy-utils": { "sqlalchemy-utils": {
"hashes": [ "hashes": [
"sha256:894cce255eea0bcc4fdcff628af30219d24a325526011586dd7f1e3d9dfebba0", "sha256:6c96b0768ea3f15c0dc56b363d386138c562752b84f647fb8d31a2223aaab801",
"sha256:986b4140f7740ff37244f6ed9182e8c997caa334150773de5932009b2490fb50" "sha256:a2181bff01eeb84479e38571d2c0718eb52042f9afd8c194d0d02877e84b7d74"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.41.0" "version": "==0.41.1"
}, },
"typing-extensions": { "typing-extensions": {
"hashes": [ "hashes": [
"sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb", "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26",
"sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4" "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==4.5.0" "version": "==4.6.3"
}, },
"visitor": { "visitor": {
"hashes": [ "hashes": [
@ -488,11 +504,11 @@
}, },
"werkzeug": { "werkzeug": {
"hashes": [ "hashes": [
"sha256:2e1ccc9417d4da358b9de6f174e3ac094391ea1d4fbef2d667865d819dfd0afe", "sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890",
"sha256:56433961bc1f12533306c624f3be5e744389ac61d722175d543e1751285da612" "sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.8'",
"version": "==2.2.3" "version": "==2.3.6"
}, },
"wtforms": { "wtforms": {
"hashes": [ "hashes": [

View File

@ -1,10 +1,12 @@
from src import create_app, db from src import create_app, db
from src.models import Bought, Establishment, Item, LoginToken, Receipt, User, UserSchema from src.models import *
app = create_app() app = create_app()
@app.shell_context_processor @app.shell_context_processor
def make_shell_context(): def make_shell_context():
return {'db': db, 'User': User, 'Bought': Bought, 'Item': Item, return {'db': db, 'User': User, 'Bought': Bought, "Brand": Brand, 'Item': Item,
"LoginToken": LoginToken, "Establishment": Establishment, "Receipt": Receipt, "LoginToken": LoginToken, "Establishment": Establishment, "Receipt": Receipt,
'UserSchema': UserSchema} "brandschema": BrandSchema(), "itemschema": ItemSchema(), "testitem": Item.query.get(4311501628485),
"testuser": User.query.get(1)}

View File

@ -4,6 +4,7 @@ from flask_bootstrap import Bootstrap
from flask_cors import CORS from flask_cors import CORS
from flask_login import LoginManager from flask_login import LoginManager
from flask_mail import Mail from flask_mail import Mail
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from logging import getLogger from logging import getLogger
@ -31,6 +32,7 @@ cors = CORS()
db = SQLAlchemy() db = SQLAlchemy()
login = LoginManager() login = LoginManager()
login.login_view = 'auth.web_login' login.login_view = 'auth.web_login'
ma = Marshmallow()
mail = Mail() mail = Mail()
migrate = Migrate() migrate = Migrate()
@ -42,6 +44,7 @@ def create_app(config_class=Config):
cors.init_app(app) cors.init_app(app)
db.init_app(app) db.init_app(app)
login.init_app(app) login.init_app(app)
ma.init_app(app)
mail.init_app(app) mail.init_app(app)
migrate.init_app(app, db, render_as_batch=True) migrate.init_app(app, db, render_as_batch=True)

View File

@ -2,5 +2,5 @@ from flask import Blueprint
bp = Blueprint('api', __name__, url_prefix='/api') bp = Blueprint('api', __name__, url_prefix='/api')
from src.api.v1 import bp as bp_v1 from .v1 import bp as bp_v1
bp.register_blueprint(bp_v1) bp.register_blueprint(bp_v1)

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint('v1', __name__, url_prefix='/v1') bp = Blueprint('v1', __name__, url_prefix='/v1')
from src.api.v1 import routes from . import routes

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint('auth', __name__, url_prefix='/auth') bp = Blueprint('auth', __name__, url_prefix='/auth')
from src.auth import forms, routes from . import forms, routes

View File

@ -1,7 +1,7 @@
from src import db from src import db
from src.auth import bp from . import bp
from src.auth.email import send_password_reset_email from .email import send_password_reset_email
from src.auth.forms import LoginForm, RegistrationForm, ResetPasswordForm, ResetPasswordRequestForm from .forms import LoginForm, RegistrationForm, ResetPasswordForm, ResetPasswordRequestForm
from src.models.user import User from src.models.user import User
from src.utils.routes_utils import render_custom_template as render_template from src.utils.routes_utils import render_custom_template as render_template
from flask import flash, redirect, request, url_for from flask import flash, redirect, request, url_for

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint('error', __name__, url_prefix='/error') bp = Blueprint('error', __name__, url_prefix='/error')
from src.errors import handlers from . import handlers

View File

@ -1,13 +1,13 @@
from flask import Blueprint from flask import Blueprint
bp = Blueprint('establishment', __name__, url_prefix='/establishment') bp = Blueprint('establishment', __name__, url_prefix='/establishment')
from src.establishment.candidates import bp as bp_candidates from .candidates import bp as bp_candidates
bp.register_blueprint(bp_candidates) bp.register_blueprint(bp_candidates)
from src.establishment.list import bp as bp_list from .list import bp as bp_list
bp.register_blueprint(bp_list) bp.register_blueprint(bp_list)
from src.establishment.new import bp as bp_new from .new import bp as bp_new
bp.register_blueprint(bp_new) bp.register_blueprint(bp_new)
from src.establishment.overview import bp as bp_overview from .overview import bp as bp_overview
bp.register_blueprint(bp_overview) bp.register_blueprint(bp_overview)
from src.establishment.payment import bp as bp_payment from .payment import bp as bp_payment
bp.register_blueprint(bp_payment) bp.register_blueprint(bp_payment)

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint("candidates", __name__, url_prefix='candidates') bp = Blueprint("candidates", __name__, url_prefix='candidates')
from src.establishment.candidates import routes from . import forms, routes

View File

@ -1,8 +1,8 @@
from flask import abort, redirect, url_for from flask import abort, redirect, url_for
from flask_login import current_user, login_required from flask_login import current_user, login_required
from . import bp
from .forms import EvaluateCandidateForm
from src import db, LOGGER from src import db, LOGGER
from src.establishment.candidates import bp
from src.establishment.candidates.forms import EvaluateCandidateForm
from src.models import Establishment, EstablishmentCandidate, LoginToken, User from src.models import Establishment, EstablishmentCandidate, LoginToken, User
from src.utils.routes_utils import render_custom_template as render_template from src.utils.routes_utils import render_custom_template as render_template
from src.utils.database_utils import generate_token from src.utils.database_utils import generate_token

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint("list", __name__, url_prefix='list') bp = Blueprint("list", __name__, url_prefix='list')
from src.establishment.list import routes from . import routes

View File

@ -1,11 +1,11 @@
# from src import db, LOGGER # from src import db, LOGGER
from flask import abort, current_app, redirect, request, url_for from flask import abort, current_app, redirect, request, url_for
from flask_login import current_user from flask_login import current_user
from . import bp
from .forms import JoinEstablishmentForm
from .utils import backend_validation
from src import db from src import db
from src.models import Establishment from src.models import Establishment
from src.establishment.list import bp
from src.establishment.list.forms import JoinEstablishmentForm
from src.establishment.list.utils import backend_validation
from src.models import EstablishmentCandidate from src.models import EstablishmentCandidate
from src.utils.routes_utils import render_custom_template as render_template from src.utils.routes_utils import render_custom_template as render_template
@ -15,10 +15,6 @@ def show_establishments():
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
establishments = Establishment.query.order_by(Establishment.id.asc()).paginate( establishments = Establishment.query.order_by(Establishment.id.asc()).paginate(
page=page, per_page=current_app.config['POSTS_PER_PAGE'], error_out=False) page=page, per_page=current_app.config['POSTS_PER_PAGE'], error_out=False)
next_url = url_for(".show_establishments",
page=establishments.next_num) if establishments.has_next else None
prev_url = url_for(".show_establishments",
page=establishments.prev_num) if establishments.has_prev else None
if current_user.is_authenticated: if current_user.is_authenticated:
form = JoinEstablishmentForm() form = JoinEstablishmentForm()
if (form.validate_on_submit()): if (form.validate_on_submit()):
@ -29,5 +25,5 @@ def show_establishments():
db.session.commit() db.session.commit()
return redirect(url_for('establishment.list.show_establishments')) return redirect(url_for('establishment.list.show_establishments'))
return abort(403) return abort(403)
return render_template("establishment/list/establishment_list.html", establishments=establishments.items, form=form, next_url=next_url, prev_url=prev_url) return render_template("establishment/list/establishment_list.html", establishments=establishments.items, form=form)
return render_template("establishment/list/establishment_list.html", establishments=establishments.items, next_url=next_url, prev_url=prev_url) return render_template("establishment/list/establishment_list.html", establishments=establishments.items)

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint("new", __name__, url_prefix='new') bp = Blueprint("new", __name__, url_prefix='new')
from src.establishment.new import forms, routes from . import forms, routes

View File

@ -1,7 +1,7 @@
from . import bp
from .forms import NewEstablishmentForm
from src import db, LOGGER from src import db, LOGGER
from src.models import Establishment, LoginToken from src.models import Establishment, LoginToken
from src.establishment.new import bp
from src.establishment.new.forms import NewEstablishmentForm
from src.utils import database_utils from src.utils import database_utils
from src.utils.routes_utils import render_custom_template as render_template from src.utils.routes_utils import render_custom_template as render_template
from flask import redirect, url_for from flask import redirect, url_for

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint('overview', __name__, url_prefix='/overview') bp = Blueprint('overview', __name__, url_prefix='/overview')
from src.establishment.overview import routes from . import forms, routes

View File

@ -1,8 +1,8 @@
from flask import abort, request from flask import abort, request
from flask.json import jsonify from flask.json import jsonify
from flask_login import current_user, login_required from flask_login import current_user, login_required
from . import bp
from src import LOGGER from src import LOGGER
from src.establishment.overview import bp
from src.models import Establishment from src.models import Establishment
from src.utils import view_utils, database_utils from src.utils import view_utils, database_utils
from src.utils.routes_utils import render_custom_template as render_template from src.utils.routes_utils import render_custom_template as render_template

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint('payment', __name__, url_prefix='/payment') bp = Blueprint('payment', __name__, url_prefix='/payment')
from src.establishment.payment import routes from . import forms, routes

View File

@ -1,8 +1,8 @@
from flask import abort, redirect, url_for from flask import abort, redirect, url_for
from flask_login import current_user, login_required from flask_login import current_user, login_required
from . import bp
from .forms import NewPaymentForm
from src import db, LOGGER from src import db, LOGGER
from src.establishment.payment import bp
from src.establishment.payment.forms import NewPaymentForm
from src.models import Establishment, Payment from src.models import Establishment, Payment
from src.utils.routes_utils import render_custom_template as render_template from src.utils.routes_utils import render_custom_template as render_template

View File

@ -1,5 +1,7 @@
from flask import Blueprint from flask import Blueprint
bp = Blueprint('item', __name__, url_prefix='/item') bp = Blueprint('item', __name__, url_prefix='/item')
from src.item.new import bp as bp_new_item from .new import bp as bp_new_item
bp.register_blueprint(bp_new_item) bp.register_blueprint(bp_new_item)
from .list import bp as bp_item_list
bp.register_blueprint(bp_item_list)

View File

@ -0,0 +1,5 @@
from flask import Blueprint
bp = Blueprint('list', __name__, url_prefix='/list')
from . import routes

View File

@ -0,0 +1,16 @@
from flask import abort, current_app, request
from flask_login import current_user, login_required
from . import bp
from src.models import Item
from src.models.schemas import ItemSchema
from src.utils.routes_utils import render_custom_template as render_template
@bp.route('/show_items', methods=['GET', 'POST'])
@login_required
def show_items():
page = request.args.get('page', 1, type=int)
items = Item.query.order_by(Item.id.asc()).paginate(
page=page, per_page=current_app.config['POSTS_PER_PAGE'], error_out=False)
if current_user.is_anonymous:
abort(403)
return render_template('item/list/show_items.html', items = items)

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint('new', __name__, url_prefix='/new') bp = Blueprint('new', __name__, url_prefix='/new')
from src.item.new import forms, routes from . import forms, routes

View File

@ -1,10 +1,10 @@
from datetime import date from datetime import date
from flask import abort, redirect, url_for from flask import abort, redirect, url_for
from flask_login import current_user, login_required from flask_login import current_user, login_required
from . import bp
from .forms import NewItemForm
from src import db, LOGGER from src import db, LOGGER
from src.models import AmountChange, Brand, Item, PriceChange from src.models import AmountChange, Brand, Item, PriceChange
from src.item.new import bp
from src.item.new.forms import NewItemForm
from src.utils.routes_utils import render_custom_template as render_template from src.utils.routes_utils import render_custom_template as render_template
@bp.route('/new_item', methods=['GET', 'POST']) @bp.route('/new_item', methods=['GET', 'POST'])

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint('main', __name__) bp = Blueprint('main', __name__)
from src.main import forms, routes from . import forms, routes

View File

@ -1,16 +1,9 @@
from flask import jsonify from flask import jsonify
from src.main import bp from . import bp
from src.models import User
from src.utils.routes_utils import render_custom_template as render_template from src.utils.routes_utils import render_custom_template as render_template
from src.models import User, UserSchema
@bp.route('/') @bp.route('/')
@bp.route('/index') @bp.route('/index')
def index(): def index():
return render_template("base.html") return render_template("base.html")
@bp.route('/test')
def test():
user_objects = User.query.all()
schema = UserSchema(many = True)
users = schema.dump(user_objects)
return jsonify(users)

View File

@ -1,14 +1,16 @@
from src.models.amount_change import AmountChange from .payment import Payment
from src.models.bought import Bought from .receipt_item import ReceiptItem
from src.models.brand import Brand from .receipt import Receipt
from src.models.category import Category from .login_token import LoginToken
from src.models.establishment import Establishment from .bought import Bought
from src.models.establishment_candidate import EstablishmentCandidate from .establishment import Establishment
from src.models.item_category import item_category from .establishment_candidate import EstablishmentCandidate
from src.models.item import Item from .user import User
from src.models.login_token import LoginToken from .amount_change import AmountChange
from src.models.payment import Payment from .price_change import PriceChange
from src.models.price_change import PriceChange from .category import Category
from src.models.receipt_item import ReceiptItem from .item import Item
from src.models.receipt import Receipt from .brand import Brand
from src.models.user import User, UserSchema from .item_category import item_category
from .schemas import *

View File

@ -1,9 +1,12 @@
from src import db
from datetime import date from datetime import date
from src import db
class AmountChange(db.Model): class AmountChange(db.Model):
item = db.Column(db.ForeignKey('item.id'), primary_key=True, server_onupdate=db.FetchedValue()) item = db.Column(db.ForeignKey('item.id'), primary_key=True,
date = db.Column(db.Date, primary_key=True, server_default=str(date(2021, 12, 1))) server_onupdate=db.FetchedValue())
date = db.Column(db.Date, primary_key=True,
server_default=str(date(2021, 12, 1)))
amount = db.Column(db.SmallInteger, nullable=False, server_default=str(1)) amount = db.Column(db.SmallInteger, nullable=False, server_default=str(1))
def __repr__(self) -> str: def __repr__(self) -> str:

View File

@ -1,8 +1,11 @@
from src import db from src import db
class Bought(db.Model): class Bought(db.Model):
token = db.Column(db.ForeignKey('login_token.token'), primary_key=True, server_onupdate=db.FetchedValue()) token = db.Column(db.ForeignKey('login_token.token'),
item = db.Column(db.ForeignKey('item.id'), primary_key=True, server_onupdate=db.FetchedValue()) primary_key=True, server_onupdate=db.FetchedValue())
item = db.Column(db.ForeignKey('item.id'), primary_key=True,
server_onupdate=db.FetchedValue())
date = db.Column(db.Date, primary_key=True) date = db.Column(db.Date, primary_key=True)
amount = db.Column(db.SmallInteger, nullable=False) amount = db.Column(db.SmallInteger, nullable=False)

View File

@ -1,5 +1,6 @@
from src import db from src import db
class Brand(db.Model): class Brand(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32), nullable=False) name = db.Column(db.String(32), nullable=False)

View File

@ -1,11 +1,13 @@
from src import db from src import db
from src.models.item_category import item_category from src.models.item_category import item_category
class Category(db.Model): class Category(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32), nullable=False, unique=True) name = db.Column(db.String(32), nullable=False, unique=True)
Item = db.relationship("Item", secondary=item_category, lazy="dynamic", back_populates="Category") Item = db.relationship("Item", secondary=item_category,
lazy="dynamic", back_populates="Category")
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<Category {self.id} ({self.name})>" return f"<Category {self.id} ({self.name})>"

View File

@ -1,14 +1,17 @@
from src import db from src import db
class Establishment(db.Model): class Establishment(db.Model):
id = db.Column(db.BigInteger, primary_key=True) id = db.Column(db.BigInteger, primary_key=True)
name = db.Column(db.String(64), nullable=False) name = db.Column(db.String(64), nullable=False)
owner = db.Column(db.ForeignKey('user.id'), nullable=False) owner = db.Column(db.ForeignKey('user.id'), nullable=False)
LoginToken = db.relationship("LoginToken", backref='Establishment', lazy='dynamic') LoginToken = db.relationship(
"LoginToken", backref='Establishment', lazy='dynamic')
Bought = db.relationship("Bought", secondary="login_token", Bought = db.relationship("Bought", secondary="login_token",
lazy='dynamic', overlaps="Establishment,LoginToken,Bought") lazy='dynamic', overlaps="Establishment,LoginToken,Bought")
EstablishmentCandidate = db.relationship("EstablishmentCandidate", backref='Establishment', lazy='dynamic') EstablishmentCandidate = db.relationship(
"EstablishmentCandidate", backref='Establishment', lazy='dynamic')
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<Establishment {self.id} ({self.name})>" return f"<Establishment {self.id} ({self.name})>"

View File

@ -1,8 +1,10 @@
from src import db from src import db
class EstablishmentCandidate(db.Model): class EstablishmentCandidate(db.Model):
user = db.Column(db.ForeignKey('user.id'), primary_key=True) user = db.Column(db.ForeignKey('user.id'), primary_key=True)
establishment = db.Column(db.ForeignKey('establishment.id'), primary_key=True) establishment = db.Column(db.ForeignKey(
'establishment.id'), primary_key=True)
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<EstablishmentCandidate {self.user} ({self.establishment})>" return f"<EstablishmentCandidate {self.user} ({self.establishment})>"

View File

@ -1,17 +1,23 @@
from src import db from src import db, ma
from src.models.item_category import item_category from src.models.item_category import item_category
class Item(db.Model): class Item(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=False) id = db.Column(db.BigInteger, primary_key=True, autoincrement=False)
name = db.Column(db.String(64), nullable=False) name = db.Column(db.String(64), nullable=False)
brand = db.Column(db.ForeignKey('brand.id'), nullable=False, server_onupdate=db.FetchedValue()) brand = db.Column(db.ForeignKey('brand.id'), nullable=False,
server_onupdate=db.FetchedValue())
description = db.Column(db.Text, nullable=False) description = db.Column(db.Text, nullable=False)
AmountChange = db.relationship("AmountChange", backref='Item', lazy='dynamic') AmountChange = db.relationship(
"AmountChange", backref='Item', lazy='dynamic')
Bought = db.relationship("Bought", backref='Item', lazy='dynamic') Bought = db.relationship("Bought", backref='Item', lazy='dynamic')
Category = db.relationship("Category", secondary=item_category, lazy="dynamic", back_populates="Item") Category = db.relationship(
PriceChange = db.relationship("PriceChange", backref='Item', lazy='dynamic') "Category", secondary=item_category, lazy="dynamic", back_populates="Item")
ReceiptItem = db.relationship("ReceiptItem", backref='Item', lazy='dynamic') PriceChange = db.relationship(
"PriceChange", backref='Item', lazy='dynamic')
ReceiptItem = db.relationship(
"ReceiptItem", backref='Item', lazy='dynamic')
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<Item {self.id} ({self.name})>" return f"<Item {self.id} ({self.name})>"

View File

@ -1,8 +1,11 @@
from src import db from src import db
class LoginToken(db.Model): class LoginToken(db.Model):
user = db.Column(db.ForeignKey('user.id'), primary_key=True, server_onupdate=db.FetchedValue()) user = db.Column(db.ForeignKey('user.id'), primary_key=True,
establishment = db.Column(db.ForeignKey('establishment.id'), primary_key=True, server_onupdate=db.FetchedValue()) server_onupdate=db.FetchedValue())
establishment = db.Column(db.ForeignKey(
'establishment.id'), primary_key=True, server_onupdate=db.FetchedValue())
token = db.Column(db.String(15), nullable=False, unique=True) token = db.Column(db.String(15), nullable=False, unique=True)
Payment = db.relationship("Payment", backref='LoginToken', lazy='dynamic') Payment = db.relationship("Payment", backref='LoginToken', lazy='dynamic')

View File

@ -1,8 +1,10 @@
from src import db from src import db
class Payment(db.Model): class Payment(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
token = db.Column(db.ForeignKey('login_token.token'), primary_key=True, server_onupdate=db.FetchedValue()) token = db.Column(db.ForeignKey('login_token.token'),
primary_key=True, server_onupdate=db.FetchedValue())
date = db.Column(db.Date, nullable=False, server_default=db.func.now()) date = db.Column(db.Date, nullable=False, server_default=db.func.now())
amount = db.Column(db.BigInteger, nullable=False, server_default=str(0)) amount = db.Column(db.BigInteger, nullable=False, server_default=str(0))

View File

@ -1,9 +1,12 @@
from src import db
from datetime import date from datetime import date
from src import db
class PriceChange(db.Model): class PriceChange(db.Model):
item = db.Column(db.ForeignKey('item.id'), primary_key=True, server_onupdate=db.FetchedValue()) item = db.Column(db.ForeignKey('item.id'), primary_key=True,
date = db.Column(db.Date, primary_key=True, server_default=str(date(2021, 12, 1))) server_onupdate=db.FetchedValue())
date = db.Column(db.Date, primary_key=True,
server_default=str(date(2021, 12, 1)))
price = db.Column(db.SmallInteger, nullable=False) price = db.Column(db.SmallInteger, nullable=False)
def __repr__(self) -> str: def __repr__(self) -> str:

View File

@ -1,12 +1,17 @@
from src import db from src import db
class Receipt(db.Model):
id = db.Column(db.Numeric(precision=24, scale=0), primary_key=True, autoincrement=False)
date = db.Column(db.Date, nullable=False)
from_user = db.Column(db.ForeignKey("login_token.token"), server_onupdate=db.FetchedValue())
registered = db.Column(db.Boolean, nullable=False, server_default=str(False))
ReceiptItem = db.relationship("ReceiptItem", backref='Receipt', lazy='dynamic') class Receipt(db.Model):
id = db.Column(db.Numeric(precision=24, scale=0),
primary_key=True, autoincrement=False)
date = db.Column(db.Date, nullable=False)
from_user = db.Column(db.ForeignKey("login_token.token"),
server_onupdate=db.FetchedValue())
registered = db.Column(db.Boolean, nullable=False,
server_default=str(False))
ReceiptItem = db.relationship(
"ReceiptItem", backref='Receipt', lazy='dynamic')
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<Receipt {self.id}>" return f"<Receipt {self.id}>"

View File

@ -1,9 +1,13 @@
from src import db from src import db
class ReceiptItem(db.Model): class ReceiptItem(db.Model):
receipt = db.Column(db.ForeignKey("receipt.id"), primary_key=True, server_onupdate=db.FetchedValue()) receipt = db.Column(db.ForeignKey("receipt.id"),
item = db.Column(db.ForeignKey("item.id"), primary_key=True, server_onupdate=db.FetchedValue()) primary_key=True, server_onupdate=db.FetchedValue())
item = db.Column(db.ForeignKey("item.id"), primary_key=True,
server_onupdate=db.FetchedValue())
amount = db.Column(db.SmallInteger, nullable=False) amount = db.Column(db.SmallInteger, nullable=False)
accepted = db.Column(db.Boolean, nullable=False)
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<ReceiptItem {self.receipt}: {self.item}>" return f"<ReceiptItem {self.receipt}: {self.item}>"

View File

@ -0,0 +1,13 @@
from .brand import BrandSchema
from .item import ItemSchema
from .category import CategorySchema
from .price_change import PriceChangeSchema
from .amount_change import AmountChangeSchema
from .user import UserSchema
from .establishment import EstablishmentSchema
from .establishment_candidate import EstablishmentCandidateSchema
from .login_token import LoginTokenSchema
from .bought import BoughtSchema
from .receipt import ReceiptSchema
from .receipt_item import ReceiptItemSchema
from .payment import PaymentSchema

View File

@ -0,0 +1,13 @@
from src import ma
from src.models import AmountChange
from src.models.schemas import ItemSchema
class AmountChangeSchema(ma.SQLAlchemySchema):
class Meta:
model = AmountChange
include_fk = True
Item = ma.Nested(ItemSchema)
date = ma.auto_field()
amount = ma.auto_field()

View File

@ -0,0 +1,14 @@
from src import ma
from src.models import Bought
from src.models.schemas import LoginTokenSchema, ItemSchema
class BoughtSchema(ma.SQLAlchemySchema):
class Meta:
model = Bought
include_fk = True
LoginToken = ma.Nested(LoginTokenSchema)
Item = ma.Nested(ItemSchema)
date = ma.auto_field()
amount = ma.auto_field()

View File

@ -0,0 +1,10 @@
from src import ma
from src.models import Brand
class BrandSchema(ma.SQLAlchemySchema):
class Meta:
model = Brand
id = ma.auto_field()
name = ma.auto_field()

View File

@ -0,0 +1,11 @@
# from marshmallow import Schema, fields
from src import ma
from src.models import Category
class CategorySchema(ma.SQLAlchemySchema):
class Meta:
model = Category
id = ma.auto_field()
name = ma.auto_field()

View File

@ -0,0 +1,13 @@
from src import ma
from src.models import Establishment
from src.models.schemas import UserSchema
class EstablishmentSchema(ma.SQLAlchemySchema):
class Meta:
model = Establishment
include_fk = True
id = ma.auto_field()
name = ma.auto_field()
User = ma.Nested(UserSchema)

View File

@ -0,0 +1,12 @@
from src import ma
from src.models import EstablishmentCandidate
from src.models.schemas import EstablishmentSchema, UserSchema
class EstablishmentCandidateSchema(ma.SQLAlchemySchema):
class Meta:
model = EstablishmentCandidate
include_fk = True
User = ma.Nested(UserSchema)
Establishment = ma.Nested(EstablishmentSchema)

View File

@ -0,0 +1,14 @@
from src import ma
from src.models import Item
from src.models.schemas import BrandSchema
class ItemSchema(ma.SQLAlchemySchema):
class Meta:
model = Item
include_fk = True
id = ma.auto_field()
name = ma.auto_field()
description = ma.auto_field()
Brand = ma.Nested(BrandSchema)

View File

@ -0,0 +1,13 @@
from src import ma
from src.models import LoginToken
from src.models.schemas import EstablishmentSchema, UserSchema
class LoginTokenSchema(ma.SQLAlchemySchema):
class Meta:
model = LoginToken
include_fk = True
User = ma.Nested(UserSchema)
Establishment = ma.Nested(EstablishmentSchema)
token = ma.auto_field()

View File

@ -0,0 +1,14 @@
from src import ma
from src.models import Payment
from src.models.schemas import LoginTokenSchema
class PaymentSchema(ma.SQLAlchemySchema):
class Meta:
model = Payment
include_fk = True
id = ma.auto_field()
LoginToken = ma.Nested(LoginTokenSchema)
date = ma.auto_field()
amount = ma.auto_field()

View File

@ -0,0 +1,13 @@
from src import ma
from src.models import PriceChange
from src.models.schemas import ItemSchema
class PriceChangeSchema(ma.SQLAlchemySchema):
class Meta:
model = PriceChange
include_fk = True
Item = ma.Nested(ItemSchema)
date = ma.auto_field()
price = ma.auto_field()

View File

@ -0,0 +1,14 @@
from src import ma
from src.models import Receipt
from src.models.schemas import LoginTokenSchema
class ReceiptSchema(ma.SQLAlchemySchema):
class Meta:
model = Receipt
include_fk = True
id = ma.auto_field()
date = ma.auto_field()
LoginToken = ma.Nested(LoginTokenSchema)
registered = ma.auto_field()

View File

@ -0,0 +1,14 @@
from src import ma
from src.models import ReceiptItem
from src.models.schemas import ItemSchema, ReceiptSchema
class ReceiptItemSchema(ma.SQLAlchemySchema):
class Meta:
model = ReceiptItem
include_fk = True
Receipt = ma.Nested(ReceiptSchema)
Item = ma.Nested(ItemSchema)
amount = ma.auto_field()
accepted = ma.auto_field()

View File

@ -0,0 +1,10 @@
from src import ma
from src.models import User
class UserSchema(ma.SQLAlchemySchema):
class Meta:
model = User
id = ma.auto_field()
email = ma.auto_field()
password_hash = ma.auto_field()

View File

@ -1,11 +1,11 @@
import jwt import jwt
from src import db, login
from flask import current_app from flask import current_app
from flask_login import UserMixin from flask_login import UserMixin
from marshmallow import Schema, fields from src import db, login
from time import time from time import time
from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.security import generate_password_hash, check_password_hash
class User(UserMixin, db.Model): class User(UserMixin, db.Model):
id = db.Column(db.BigInteger, primary_key=True) id = db.Column(db.BigInteger, primary_key=True)
email = db.Column(db.String(255), nullable=False, unique=True) email = db.Column(db.String(255), nullable=False, unique=True)
@ -13,9 +13,11 @@ class User(UserMixin, db.Model):
LoginToken = db.relationship("LoginToken", backref='User', lazy='dynamic') LoginToken = db.relationship("LoginToken", backref='User', lazy='dynamic')
Bought = db.relationship("Bought", secondary="login_token", Bought = db.relationship("Bought", secondary="login_token",
lazy='dynamic', overlaps="User,LoginToken") lazy='dynamic', overlaps="User,LoginToken")
EstablishmentCandidate = db.relationship("EstablishmentCandidate", backref='User', lazy='dynamic') EstablishmentCandidate = db.relationship(
Establishment = db.relationship("Establishment", backref="User", lazy="dynamic") "EstablishmentCandidate", backref='User', lazy='dynamic')
Establishment = db.relationship(
"Establishment", backref="User", lazy="dynamic")
def set_password(self, password): def set_password(self, password):
self.password_hash = generate_password_hash(password) self.password_hash = generate_password_hash(password)
@ -40,10 +42,6 @@ class User(UserMixin, db.Model):
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<User {self.id} ({self.email})>" return f"<User {self.id} ({self.email})>"
class UserSchema(Schema):
id = fields.Number()
email = fields.Str()
password_hash = fields.Str()
@login.user_loader @login.user_loader
def load_user(id): def load_user(id):

View File

@ -2,4 +2,4 @@ from flask import Blueprint
bp = Blueprint('receipts', __name__, url_prefix='/receipts') bp = Blueprint('receipts', __name__, url_prefix='/receipts')
from src.receipts import forms, routes from . import forms, routes

View File

@ -1,12 +1,12 @@
from flask import abort, request, url_for
from flask_login import current_user, login_required
from . import bp
from .forms import CheckItemsForm, UploadReceiptForm
from src import db, LOGGER from src import db, LOGGER
from src.models.receipt import Receipt from src.models.receipt import Receipt
from src.models.login_token import LoginToken from src.models.login_token import LoginToken
from src.receipts import bp
from src.receipts.forms import CheckItemsForm, UploadReceiptForm
from src.utils.pdf_receipt_parser import PDFReceipt from src.utils.pdf_receipt_parser import PDFReceipt
from src.utils.routes_utils import render_custom_template as render_template from src.utils.routes_utils import render_custom_template as render_template
from flask import abort, request, url_for
from flask_login import current_user, login_required
PDFDir = "./" PDFDir = "./"

View File

@ -45,7 +45,7 @@ CostHive
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small"> <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
<li><a href="{{ url_for('establishment.list.show_establishments') }}" <li><a href="{{ url_for('establishment.list.show_establishments') }}"
class="link-dark rounded">Einrichtungen</a></li> class="link-dark rounded">Einrichtungen</a></li>
<li><a href="#" class="link-dark rounded">Inventar</a></li> <li><a href="{{ url_for('item.list.show_items') }}" class="link-dark rounded">Inventar</a></li>
</ul> </ul>
</div> </div>
</li> </li>

View File

@ -23,5 +23,8 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% with pagination_object=establishments %}
{% include "utils/general/_page_navigation.html" %} {% include "utils/general/_page_navigation.html" %}
{% endwith %}
{% endblock %} {% endblock %}

View File

@ -0,0 +1,29 @@
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Beschreibung</th>
<th scope="col">Marke</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<th scope="row">{{ item.id }}</th>
<td>{{ item.name }}</td>
<td>{{ item.description }}</td>
<td>{{ item.Brand.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% with pagination_object=items %}
{% include "utils/general/_page_navigation.html" %}
{% endwith %}
{% endblock %}

View File

@ -1,6 +1,14 @@
{% if prev_url %} {% if pagination_object.has_prev %}
<a href="{{ prev_url }}">Previous</a> <a href="{{ url_for(request.endpoint, page=pagination_object.prev_num) }}">
<button class="btn btn-primary">Previous</button>
</a>
{% else %}
<button class="btn btn-secondary">Previous</button>
{% endif %} {% endif %}
{% if next_url %} {% if pagination_object.has_next %}
<a href="{{ next_url }}">Next</a> <a href="{{ url_for(request.endpoint, page=pagination_object.next_num) }}">
<button class="btn btn-primary">Next</button>
</a>
{% else %}
<button class="btn btn-secondary">Next</button>
{% endif %} {% endif %}

View File

@ -1 +1 @@
APPNAME = "scan2kasse" APPNAME = "CostHive"

View File

@ -1,6 +1,3 @@
from src import db, LOGGER
from src.models import Bought, Establishment, Item, LoginToken, User
from src.utils.view_utils import bought_with_prices as bwp
from copy import deepcopy from copy import deepcopy
from datetime import date as dtdate, timedelta from datetime import date as dtdate, timedelta
from flask_login import current_user from flask_login import current_user
@ -9,6 +6,9 @@ from random import choice as rndchoice
from sqlalchemy import and_, text from sqlalchemy import and_, text
from sqlalchemy.dialects.postgresql import insert from sqlalchemy.dialects.postgresql import insert
from string import ascii_letters, digits from string import ascii_letters, digits
from .view_utils import bought_with_prices as bwp
from src import db, LOGGER
from src.models import Bought, Establishment, Item, LoginToken, User
def insert_bought_items(token: str, dates: list[dict[str: any]]): def insert_bought_items(token: str, dates: list[dict[str: any]]):

View File

@ -1,7 +1,7 @@
from src import mail
from flask import current_app from flask import current_app
from flask_mail import Message from flask_mail import Message
from threading import Thread from threading import Thread
from src import mail
def send_async_email(app, msg): def send_async_email(app, msg):
with app.app_context(): with app.app_context():

View File

@ -1,5 +1,5 @@
from datetime import datetime
import fitz import fitz
from datetime import datetime
from re import search from re import search
class PDFReceipt: class PDFReceipt:

View File

@ -1,8 +1,8 @@
from sqlalchemy_utils import create_view
from src import db, LOGGER from src import db, LOGGER
from src.models.amount_change import AmountChange from src.models.amount_change import AmountChange
from src.models.bought import Bought from src.models.bought import Bought
from src.models.price_change import PriceChange from src.models.price_change import PriceChange
from sqlalchemy_utils import create_view
def group_results(results: tuple) -> list: def group_results(results: tuple) -> list:
result_list = [] result_list = []

View File

@ -25,6 +25,7 @@
"src/assets" "src/assets"
], ],
"styles": [ "styles": [
"@angular/material/prebuilt-themes/purple-green.css",
"src/styles.css" "src/styles.css"
], ],
"scripts": [] "scripts": []
@ -87,6 +88,7 @@
"src/assets" "src/assets"
], ],
"styles": [ "styles": [
"@angular/material/prebuilt-themes/purple-green.css",
"src/styles.css" "src/styles.css"
], ],
"scripts": [] "scripts": []

File diff suppressed because it is too large Load Diff

View File

@ -10,23 +10,25 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^15.2.0", "@angular/animations": "^16.0.3",
"@angular/common": "^15.2.0", "@angular/cdk": "^16.0.2",
"@angular/compiler": "^15.2.0", "@angular/common": "^16.0.3",
"@angular/core": "^15.2.0", "@angular/compiler": "^16.0.3",
"@angular/forms": "^15.2.0", "@angular/core": "^16.0.3",
"@angular/platform-browser": "^15.2.0", "@angular/forms": "^16.0.3",
"@angular/platform-browser-dynamic": "^15.2.0", "@angular/material": "^16.0.2",
"@angular/router": "^15.2.0", "@angular/platform-browser": "^16.0.3",
"@angular/platform-browser-dynamic": "^16.0.3",
"@angular/router": "^16.0.3",
"npm": "^9.6.4", "npm": "^9.6.4",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.12.0" "zone.js": "~0.13.0"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^15.2.1", "@angular-devkit/build-angular": "^16.0.3",
"@angular/cli": "~15.2.1", "@angular/cli": "~16.0.3",
"@angular/compiler-cli": "^15.2.0", "@angular/compiler-cli": "^16.0.3",
"@types/jasmine": "~4.3.0", "@types/jasmine": "~4.3.0",
"jasmine-core": "~4.5.0", "jasmine-core": "~4.5.0",
"karma": "~6.4.0", "karma": "~6.4.0",

View File

@ -1,7 +1,10 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { UsersComponent } from './users/users.component';
const routes: Routes = []; const routes: Routes = [
{path: 'users', component: UsersComponent}
];
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes)], imports: [RouterModule.forRoot(routes)],

View File

@ -0,0 +1,6 @@
.example-container {
width: 400px;
height: 200px;
margin: 10px;
border: 1px solid #555;
}

View File

@ -1,9 +1,6 @@
<div style="text-align:center"> <mat-drawer-container class="example-container">
<h1>Users</h1> <mat-drawer mode="side" opened>Drawer content</mat-drawer>
</div> <mat-drawer-content>
<h2>Here are the users created so far: </h2> <router-outlet></router-outlet>
<ul> </mat-drawer-content>
<li *ngFor="let user of usersList"> </mat-drawer-container>
{{user.email}}
</li>
</ul>

View File

@ -1,35 +1,8 @@
import {Component, OnInit, OnDestroy} from '@angular/core'; import { Component } from '@angular/core';
import {Subscription} from 'rxjs';
import {UsersApiService} from './users/users-api.service';
import {User} from './users/user.model';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.css'] styleUrls: ['./app.component.css']
}) })
export class AppComponent implements OnInit, OnDestroy { export class AppComponent { }
title = 'app';
usersListSubs: Subscription;
usersList: User[];
constructor(private usersApi: UsersApiService) {
this.usersListSubs = new Subscription;
this.usersList = []
}
ngOnInit() {
this.usersListSubs = this.usersApi
.getExams()
.subscribe(res => {
console.log(res);
this.usersList = res;
},
console.error
);
}
ngOnDestroy() {
this.usersListSubs.unsubscribe();
}
}

View File

@ -1,19 +1,25 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import {HttpClientModule} from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import {UsersApiService} from './users/users-api.service'; import { UsersComponent } from './users/users.component';
import { UsersApiService } from './users/users-api.service';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatSidenavModule } from '@angular/material/sidenav';
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent AppComponent,
UsersComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
HttpClientModule, HttpClientModule,
AppRoutingModule AppRoutingModule,
BrowserAnimationsModule,
MatSidenavModule
], ],
providers: [UsersApiService], providers: [UsersApiService],
bootstrap: [AppComponent] bootstrap: [AppComponent]

View File

@ -0,0 +1,9 @@
<div style="text-align:center">
<h1>Users</h1>
</div>
<h2>Here are the users created so far: </h2>
<ul>
<li *ngFor="let user of usersList">
{{user.email}}
</li>
</ul>

View File

@ -0,0 +1,35 @@
import {Component, OnInit, OnDestroy} from '@angular/core';
import {Subscription} from 'rxjs';
import {UsersApiService} from './users-api.service';
import {User} from './user.model';
@Component({
selector: 'app-root',
templateUrl: './users.component.html',
styleUrls: ['./users.component.css']
})
export class UsersComponent implements OnInit, OnDestroy {
title = 'app';
usersListSubs: Subscription;
usersList: User[];
constructor(private usersApi: UsersApiService) {
this.usersListSubs = new Subscription;
this.usersList = []
}
ngOnInit() {
this.usersListSubs = this.usersApi
.getExams()
.subscribe((res: User[]) => {
console.log(res);
this.usersList = res;
},
console.error
);
}
ngOnDestroy() {
this.usersListSubs.unsubscribe();
}
}

View File

@ -1,18 +1,19 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Frontend</title> <title>Frontend</title>
<base href="/"> <base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head> </head>
<body>
<mat-sidenav-container> <body class="mat-typography">
<mat-sidenav>Start</mat-sidenav> <app-root></app-root>
<mat-sidenav-content>
<app-root></app-root>
</mat-sidenav-content>
</mat-sidenav-container>
</body> </body>
</html> </html>

View File

@ -1 +1,4 @@
/* You can add global styles to this file, and also import other style files */ /* You can add global styles to this file, and also import other style files */
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }