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 = "*"
pymupdf = "*"
sqlalchemy-utils = "*"
marshmallow = "*"
flask-marshmallow = "*"
marshmallow-sqlalchemy = "*"
[dev-packages]

318
backend/Pipfile.lock generated
View File

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

View File

@ -1,10 +1,12 @@
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.shell_context_processor
def make_shell_context():
return {'db': db, 'User': User, 'Bought': Bought, 'Item': Item,
"LoginToken": LoginToken, "Establishment": Establishment, "Receipt": Receipt,
'UserSchema': UserSchema}
return {'db': db, 'User': User, 'Bought': Bought, "Brand": Brand, 'Item': Item,
"LoginToken": LoginToken, "Establishment": Establishment, "Receipt": Receipt,
"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_login import LoginManager
from flask_mail import Mail
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from logging import getLogger
@ -31,6 +32,7 @@ cors = CORS()
db = SQLAlchemy()
login = LoginManager()
login.login_view = 'auth.web_login'
ma = Marshmallow()
mail = Mail()
migrate = Migrate()
@ -42,6 +44,7 @@ def create_app(config_class=Config):
cors.init_app(app)
db.init_app(app)
login.init_app(app)
ma.init_app(app)
mail.init_app(app)
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')
from src.api.v1 import bp as bp_v1
from .v1 import bp as bp_v1
bp.register_blueprint(bp_v1)

View File

@ -2,4 +2,4 @@ from flask import Blueprint
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')
from src.auth import forms, routes
from . import forms, routes

View File

@ -1,7 +1,7 @@
from src import db
from src.auth import bp
from src.auth.email import send_password_reset_email
from src.auth.forms import LoginForm, RegistrationForm, ResetPasswordForm, ResetPasswordRequestForm
from . import bp
from .email import send_password_reset_email
from .forms import LoginForm, RegistrationForm, ResetPasswordForm, ResetPasswordRequestForm
from src.models.user import User
from src.utils.routes_utils import render_custom_template as render_template
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')
from src.errors import handlers
from . import handlers

View File

@ -1,13 +1,13 @@
from flask import Blueprint
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)
from src.establishment.list import bp as bp_list
from .list import bp as 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)
from src.establishment.overview import bp as bp_overview
from .overview import bp as 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)

View File

@ -2,4 +2,4 @@ from flask import Blueprint
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_login import current_user, login_required
from . import bp
from .forms import EvaluateCandidateForm
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.utils.routes_utils import render_custom_template as render_template
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')
from src.establishment.list import routes
from . import routes

View File

@ -1,11 +1,11 @@
# from src import db, LOGGER
from flask import abort, current_app, redirect, request, url_for
from flask_login import current_user
from . import bp
from .forms import JoinEstablishmentForm
from .utils import backend_validation
from src import db
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.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)
establishments = Establishment.query.order_by(Establishment.id.asc()).paginate(
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:
form = JoinEstablishmentForm()
if (form.validate_on_submit()):
@ -29,5 +25,5 @@ def show_establishments():
db.session.commit()
return redirect(url_for('establishment.list.show_establishments'))
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, 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)

View File

@ -2,4 +2,4 @@ from flask import Blueprint
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.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.routes_utils import render_custom_template as render_template
from flask import redirect, url_for

View File

@ -2,4 +2,4 @@ from flask import Blueprint
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.json import jsonify
from flask_login import current_user, login_required
from . import bp
from src import LOGGER
from src.establishment.overview import bp
from src.models import Establishment
from src.utils import view_utils, database_utils
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')
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_login import current_user, login_required
from . import bp
from .forms import NewPaymentForm
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.utils.routes_utils import render_custom_template as render_template

View File

@ -1,5 +1,7 @@
from flask import Blueprint
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)
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')
from src.item.new import forms, routes
from . import forms, routes

View File

@ -1,10 +1,10 @@
from datetime import date
from flask import abort, redirect, url_for
from flask_login import current_user, login_required
from . import bp
from .forms import NewItemForm
from src import db, LOGGER
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
@bp.route('/new_item', methods=['GET', 'POST'])

View File

@ -2,4 +2,4 @@ from flask import Blueprint
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 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.models import User, UserSchema
@bp.route('/')
@bp.route('/index')
def index():
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 src.models.bought import Bought
from src.models.brand import Brand
from src.models.category import Category
from src.models.establishment import Establishment
from src.models.establishment_candidate import EstablishmentCandidate
from src.models.item_category import item_category
from src.models.item import Item
from src.models.login_token import LoginToken
from src.models.payment import Payment
from src.models.price_change import PriceChange
from src.models.receipt_item import ReceiptItem
from src.models.receipt import Receipt
from src.models.user import User, UserSchema
from .payment import Payment
from .receipt_item import ReceiptItem
from .receipt import Receipt
from .login_token import LoginToken
from .bought import Bought
from .establishment import Establishment
from .establishment_candidate import EstablishmentCandidate
from .user import User
from .amount_change import AmountChange
from .price_change import PriceChange
from .category import Category
from .item import Item
from .brand import Brand
from .item_category import item_category
from .schemas import *

View File

@ -1,9 +1,12 @@
from src import db
from datetime import date
from src import db
class AmountChange(db.Model):
item = db.Column(db.ForeignKey('item.id'), primary_key=True, server_onupdate=db.FetchedValue())
date = db.Column(db.Date, primary_key=True, server_default=str(date(2021, 12, 1)))
item = db.Column(db.ForeignKey('item.id'), primary_key=True,
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))
def __repr__(self) -> str:

View File

@ -1,8 +1,11 @@
from src import db
class Bought(db.Model):
token = db.Column(db.ForeignKey('login_token.token'), primary_key=True, server_onupdate=db.FetchedValue())
item = db.Column(db.ForeignKey('item.id'), primary_key=True, server_onupdate=db.FetchedValue())
token = db.Column(db.ForeignKey('login_token.token'),
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)
amount = db.Column(db.SmallInteger, nullable=False)

View File

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

View File

@ -1,11 +1,13 @@
from src import db
from src.models.item_category import item_category
class Category(db.Model):
id = db.Column(db.Integer, primary_key=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:
return f"<Category {self.id} ({self.name})>"

View File

@ -1,14 +1,17 @@
from src import db
class Establishment(db.Model):
id = db.Column(db.BigInteger, primary_key=True)
name = db.Column(db.String(64), 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",
lazy='dynamic', overlaps="Establishment,LoginToken,Bought")
EstablishmentCandidate = db.relationship("EstablishmentCandidate", backref='Establishment', lazy='dynamic')
lazy='dynamic', overlaps="Establishment,LoginToken,Bought")
EstablishmentCandidate = db.relationship(
"EstablishmentCandidate", backref='Establishment', lazy='dynamic')
def __repr__(self) -> str:
return f"<Establishment {self.id} ({self.name})>"

View File

@ -1,8 +1,10 @@
from src import db
class EstablishmentCandidate(db.Model):
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:
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
class Item(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=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)
AmountChange = db.relationship("AmountChange", backref='Item', lazy='dynamic')
AmountChange = db.relationship(
"AmountChange", backref='Item', lazy='dynamic')
Bought = db.relationship("Bought", backref='Item', lazy='dynamic')
Category = db.relationship("Category", secondary=item_category, lazy="dynamic", back_populates="Item")
PriceChange = db.relationship("PriceChange", backref='Item', lazy='dynamic')
ReceiptItem = db.relationship("ReceiptItem", backref='Item', lazy='dynamic')
Category = db.relationship(
"Category", secondary=item_category, lazy="dynamic", back_populates="Item")
PriceChange = db.relationship(
"PriceChange", backref='Item', lazy='dynamic')
ReceiptItem = db.relationship(
"ReceiptItem", backref='Item', lazy='dynamic')
def __repr__(self) -> str:
return f"<Item {self.id} ({self.name})>"

View File

@ -1,8 +1,11 @@
from src import db
class LoginToken(db.Model):
user = db.Column(db.ForeignKey('user.id'), primary_key=True, server_onupdate=db.FetchedValue())
establishment = db.Column(db.ForeignKey('establishment.id'), primary_key=True, server_onupdate=db.FetchedValue())
user = db.Column(db.ForeignKey('user.id'), primary_key=True,
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)
Payment = db.relationship("Payment", backref='LoginToken', lazy='dynamic')

View File

@ -1,8 +1,10 @@
from src import db
class Payment(db.Model):
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())
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 src import db
class PriceChange(db.Model):
item = db.Column(db.ForeignKey('item.id'), primary_key=True, server_onupdate=db.FetchedValue())
date = db.Column(db.Date, primary_key=True, server_default=str(date(2021, 12, 1)))
item = db.Column(db.ForeignKey('item.id'), primary_key=True,
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)
def __repr__(self) -> str:

View File

@ -1,12 +1,17 @@
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:
return f"<Receipt {self.id}>"

View File

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

View File

@ -2,4 +2,4 @@ from flask import Blueprint
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.models.receipt import Receipt
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.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 = "./"

View File

@ -45,7 +45,7 @@ CostHive
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
<li><a href="{{ url_for('establishment.list.show_establishments') }}"
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>
</div>
</li>

View File

@ -23,5 +23,8 @@
{% endfor %}
</tbody>
</table>
{% with pagination_object=establishments %}
{% include "utils/general/_page_navigation.html" %}
{% endwith %}
{% 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 %}
<a href="{{ prev_url }}">Previous</a>
{% if pagination_object.has_prev %}
<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 %}
{% if next_url %}
<a href="{{ next_url }}">Next</a>
{% if pagination_object.has_next %}
<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 %}

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 datetime import date as dtdate, timedelta
from flask_login import current_user
@ -9,6 +6,9 @@ from random import choice as rndchoice
from sqlalchemy import and_, text
from sqlalchemy.dialects.postgresql import insert
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]]):

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,7 +1,10 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { UsersComponent } from './users/users.component';
const routes: Routes = [];
const routes: Routes = [
{path: 'users', component: UsersComponent}
];
@NgModule({
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">
<h1>Users</h1>
</div>
<h2>Here are the users created so far: </h2>
<ul>
<li *ngFor="let user of usersList">
{{user.email}}
</li>
</ul>
<mat-drawer-container class="example-container">
<mat-drawer mode="side" opened>Drawer content</mat-drawer>
<mat-drawer-content>
<router-outlet></router-outlet>
</mat-drawer-content>
</mat-drawer-container>

View File

@ -1,35 +1,8 @@
import {Component, OnInit, OnDestroy} from '@angular/core';
import {Subscription} from 'rxjs';
import {UsersApiService} from './users/users-api.service';
import {User} from './users/user.model';
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent 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 => {
console.log(res);
this.usersList = res;
},
console.error
);
}
ngOnDestroy() {
this.usersListSubs.unsubscribe();
}
}
export class AppComponent { }

View File

@ -1,19 +1,25 @@
import { NgModule } from '@angular/core';
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 { 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({
declarations: [
AppComponent
AppComponent,
UsersComponent
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule
AppRoutingModule,
BrowserAnimationsModule,
MatSidenavModule
],
providers: [UsersApiService],
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>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Frontend</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<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>
<body>
<mat-sidenav-container>
<mat-sidenav>Start</mat-sidenav>
<mat-sidenav-content>
<app-root></app-root>
</mat-sidenav-content>
</mat-sidenav-container>
<body class="mat-typography">
<app-root></app-root>
</body>
</html>

View File

@ -1 +1,4 @@
/* 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; }