basis for paypal transactions
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m48s
Run linting on the backend code / Build (pull_request) Failing after 29s
Run testing on the backend code / Build (pull_request) Failing after 50s
Build and release debug APK / Build APK (pull_request) Failing after 3m50s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 27s

This commit is contained in:
Helldragon67 2025-02-17 11:54:03 +01:00
parent f258df8e72
commit dd277287af
11 changed files with 441 additions and 278 deletions

View File

@ -26,3 +26,4 @@ pulp = "*"
scipy = "*" scipy = "*"
requests = "*" requests = "*"
supabase = "*" supabase = "*"
paypalrestsdk = "*"

336
backend/Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "6fb866543b6ea2eb10165b6451666650fff3949e872b4dd4902d0b728f1b495c" "sha256": "e02d6fa1d52eaf7da8fc8814385d25a0346398b744522245ef96c28a4c712b25"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": {}, "requires": {},
@ -149,6 +149,79 @@
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==2025.1.31" "version": "==2025.1.31"
}, },
"cffi": {
"hashes": [
"sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8",
"sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2",
"sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1",
"sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15",
"sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36",
"sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824",
"sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8",
"sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36",
"sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17",
"sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf",
"sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc",
"sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3",
"sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed",
"sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702",
"sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1",
"sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8",
"sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903",
"sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6",
"sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d",
"sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b",
"sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e",
"sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be",
"sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c",
"sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683",
"sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9",
"sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c",
"sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8",
"sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1",
"sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4",
"sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655",
"sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67",
"sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595",
"sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0",
"sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65",
"sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41",
"sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6",
"sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401",
"sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6",
"sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3",
"sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16",
"sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93",
"sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e",
"sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4",
"sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964",
"sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c",
"sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576",
"sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0",
"sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3",
"sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662",
"sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3",
"sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff",
"sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5",
"sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd",
"sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f",
"sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5",
"sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14",
"sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d",
"sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9",
"sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7",
"sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382",
"sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a",
"sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e",
"sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a",
"sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4",
"sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99",
"sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87",
"sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"
],
"markers": "platform_python_implementation != 'PyPy'",
"version": "==1.17.1"
},
"charset-normalizer": { "charset-normalizer": {
"hashes": [ "hashes": [
"sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537",
@ -255,6 +328,43 @@
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==8.1.8" "version": "==8.1.8"
}, },
"cryptography": {
"hashes": [
"sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7",
"sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3",
"sha256:1f9a92144fa0c877117e9748c74501bea842f93d21ee00b0cf922846d9d0b183",
"sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69",
"sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a",
"sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62",
"sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911",
"sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7",
"sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a",
"sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41",
"sha256:5fed5cd6102bb4eb843e3315d2bf25fede494509bddadb81e03a859c1bc17b83",
"sha256:610a83540765a8d8ce0f351ce42e26e53e1f774a6efb71eb1b41eb01d01c3d12",
"sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864",
"sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf",
"sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c",
"sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2",
"sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b",
"sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0",
"sha256:94f99f2b943b354a5b6307d7e8d19f5c423a794462bde2bf310c770ba052b1c4",
"sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9",
"sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008",
"sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862",
"sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009",
"sha256:d9c5b9f698a83c8bd71e0f4d3f9f839ef244798e5ffe96febfa9714717db7af7",
"sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f",
"sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026",
"sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f",
"sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd",
"sha256:f4daefc971c2d1f82f03097dc6f216744a6cd2ac0f04c68fb935ea2ba2a0d420",
"sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14",
"sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00"
],
"markers": "python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1'",
"version": "==44.0.1"
},
"deprecation": { "deprecation": {
"hashes": [ "hashes": [
"sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff", "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff",
@ -625,65 +735,65 @@
}, },
"numpy": { "numpy": {
"hashes": [ "hashes": [
"sha256:02935e2c3c0c6cbe9c7955a8efa8908dd4221d7755644c59d1bba28b94fd334f", "sha256:0391ea3622f5c51a2e29708877d56e3d276827ac5447d7f45e9bc4ade8923c52",
"sha256:0349b025e15ea9d05c3d63f9657707a4e1d471128a3b1d876c095f328f8ff7f0", "sha256:12c045f43b1d2915eca6b880a7f4a256f59d62df4f044788c8ba67709412128d",
"sha256:09d6a2032faf25e8d0cadde7fd6145118ac55d2740132c1d845f98721b5ebcfd", "sha256:136553f123ee2951bfcfbc264acd34a2fc2f29d7cdf610ce7daf672b6fbaa693",
"sha256:0bc61b307655d1a7f9f4b043628b9f2b721e80839914ede634e3d485913e1fb2", "sha256:1402da8e0f435991983d0a9708b779f95a8c98c6b18a171b9f1be09005e64d9d",
"sha256:0eec19f8af947a61e968d5429f0bd92fec46d92b0008d0a6685b40d6adf8a4f4", "sha256:16372619ee728ed67a2a606a614f56d3eabc5b86f8b615c79d01957062826ca8",
"sha256:106397dbbb1896f99e044efc90360d098b3335060375c26aa89c0d8a97c5f648", "sha256:1ad78ce7f18ce4e7df1b2ea4019b5817a2f6a8a16e34ff2775f646adce0a5027",
"sha256:128c41c085cab8a85dc29e66ed88c05613dccf6bc28b3866cd16050a2f5448be", "sha256:1b416af7d0ed3271cad0f0a0d0bee0911ed7eba23e66f8424d9f3dfcdcae1304",
"sha256:149d1113ac15005652e8d0d3f6fd599360e1a708a4f98e43c9c77834a28238cb", "sha256:1f45315b2dc58d8a3e7754fe4e38b6fce132dab284a92851e41b2b344f6441c5",
"sha256:159ff6ee4c4a36a23fe01b7c3d07bd8c14cc433d9720f977fcd52c13c0098160", "sha256:2376e317111daa0a6739e50f7ee2a6353f768489102308b0d98fcf4a04f7f3b5",
"sha256:22ea3bb552ade325530e72a0c557cdf2dea8914d3a5e1fecf58fa5dbcc6f43cd", "sha256:23c9f4edbf4c065fddb10a4f6e8b6a244342d95966a48820c614891e5059bb50",
"sha256:23ae9f0c2d889b7b2d88a3791f6c09e2ef827c2446f1c4a3e3e76328ee4afd9a", "sha256:246535e2f7496b7ac85deffe932896a3577be7af8fb7eebe7146444680297e9a",
"sha256:250c16b277e3b809ac20d1f590716597481061b514223c7badb7a0f9993c7f84", "sha256:2e8da03bd561504d9b20e7a12340870dfc206c64ea59b4cfee9fceb95070ee94",
"sha256:2ec6c689c61df613b783aeb21f945c4cbe6c51c28cb70aae8430577ab39f163e", "sha256:34c1b7e83f94f3b564b35f480f5652a47007dd91f7c839f404d03279cc8dd021",
"sha256:2ffbb1acd69fdf8e89dd60ef6182ca90a743620957afb7066385a7bbe88dc748", "sha256:39261798d208c3095ae4f7bc8eaeb3481ea8c6e03dc48028057d3cbdbdb8937e",
"sha256:3074634ea4d6df66be04f6728ee1d173cfded75d002c75fac79503a880bf3825", "sha256:3b787adbf04b0db1967798dba8da1af07e387908ed1553a0d6e74c084d1ceafe",
"sha256:356ca982c188acbfa6af0d694284d8cf20e95b1c3d0aefa8929376fea9146f60", "sha256:3c2ec8a0f51d60f1e9c0c5ab116b7fc104b165ada3f6c58abf881cb2eb16044d",
"sha256:3fbe72d347fbc59f94124125e73fc4976a06927ebc503ec5afbfb35f193cd957", "sha256:435e7a933b9fda8126130b046975a968cc2d833b505475e588339e09f7672890",
"sha256:40c7ff5da22cd391944a28c6a9c638a5eef77fcf71d6e3a79e1d9d9e82752715", "sha256:4d8335b5f1b6e2bce120d55fb17064b0262ff29b459e8493d1785c18ae2553b8",
"sha256:41184c416143defa34cc8eb9d070b0a5ba4f13a0fa96a709e20584638254b317", "sha256:4d9828d25fb246bedd31e04c9e75714a4087211ac348cb39c8c5f99dbb6683fe",
"sha256:451e854cfae0febe723077bd0cf0a4302a5d84ff25f0bfece8f29206c7bed02e", "sha256:52659ad2534427dffcc36aac76bebdd02b67e3b7a619ac67543bc9bfe6b7cdb1",
"sha256:4525b88c11906d5ab1b0ec1f290996c0020dd318af8b49acaa46f198b1ffc283", "sha256:5266de33d4c3420973cf9ae3b98b54a2a6d53a559310e3236c4b2b06b9c07d4e",
"sha256:463247edcee4a5537841d5350bc87fe8e92d7dd0e8c71c995d2c6eecb8208278", "sha256:5521a06a3148686d9269c53b09f7d399a5725c47bbb5b35747e1cb76326b714b",
"sha256:4dbd80e453bd34bd003b16bd802fac70ad76bd463f81f0c518d1245b1c55e3d9", "sha256:596140185c7fa113563c67c2e894eabe0daea18cf8e33851738c19f70ce86aeb",
"sha256:57b4012e04cc12b78590a334907e01b3a85efb2107df2b8733ff1ed05fce71de", "sha256:5b732c8beef1d7bc2d9e476dbba20aaff6167bf205ad9aa8d30913859e82884b",
"sha256:5a8c863ceacae696aff37d1fd636121f1a512117652e5dfb86031c8d84836369", "sha256:5ebeb7ef54a7be11044c33a17b2624abe4307a75893c001a4800857956b41094",
"sha256:5acea83b801e98541619af398cc0109ff48016955cc0818f478ee9ef1c5c3dcb", "sha256:712a64103d97c404e87d4d7c47fb0c7ff9acccc625ca2002848e0d53288b90ea",
"sha256:642199e98af1bd2b6aeb8ecf726972d238c9877b0f6e8221ee5ab945ec8a2189", "sha256:7678556eeb0152cbd1522b684dcd215250885993dd00adb93679ec3c0e6e091c",
"sha256:64bd6e1762cd7f0986a740fee4dff927b9ec2c5e4d9a28d056eb17d332158014", "sha256:77974aba6c1bc26e3c205c2214f0d5b4305bdc719268b93e768ddb17e3fdd636",
"sha256:6d9fc9d812c81e6168b6d405bf00b8d6739a7f72ef22a9214c4241e0dc70b323", "sha256:783145835458e60fa97afac25d511d00a1eca94d4a8f3ace9fe2043003c678e4",
"sha256:7079129b64cb78bdc8d611d1fd7e8002c0a2565da6a47c4df8062349fee90e3e", "sha256:7bfdb06b395385ea9b91bf55c1adf1b297c9fdb531552845ff1d3ea6e40d5aba",
"sha256:7dca87ca328f5ea7dafc907c5ec100d187911f94825f8700caac0b3f4c384b49", "sha256:7c8dde0ca2f77828815fd1aedfdf52e59071a5bae30dac3b4da2a335c672149a",
"sha256:860fd59990c37c3ef913c3ae390b3929d005243acca1a86facb0773e2d8d9e50", "sha256:83807d445817326b4bcdaaaf8e8e9f1753da04341eceec705c001ff342002e5d",
"sha256:8e6da5cffbbe571f93588f562ed130ea63ee206d12851b60819512dd3e1ba50d", "sha256:87eed225fd415bbae787f93a457af7f5990b92a334e346f72070bf569b9c9c95",
"sha256:8ec0636d3f7d68520afc6ac2dc4b8341ddb725039de042faf0e311599f54eb37", "sha256:8fb62fe3d206d72fe1cfe31c4a1106ad2b136fcc1606093aeab314f02930fdf2",
"sha256:9491100aba630910489c1d0158034e1c9a6546f0b1340f716d522dc103788e39", "sha256:95172a21038c9b423e68be78fd0be6e1b97674cde269b76fe269a5dfa6fadf0b",
"sha256:97b974d3ba0fb4612b77ed35d7627490e8e3dff56ab41454d9e8b23448940576", "sha256:9f48ba6f6c13e5e49f3d3efb1b51c8193215c42ac82610a04624906a9270be6f",
"sha256:995f9e8181723852ca458e22de5d9b7d3ba4da3f11cc1cb113f093b271d7965a", "sha256:a0c03b6be48aaf92525cccf393265e02773be8fd9551a2f9adbe7db1fa2b60f1",
"sha256:9dd47ff0cb2a656ad69c38da850df3454da88ee9a6fde0ba79acceee0e79daba", "sha256:a5ae282abe60a2db0fd407072aff4599c279bcd6e9a2475500fc35b00a57c532",
"sha256:9fad446ad0bc886855ddf5909cbf8cb5d0faa637aaa6277fb4b19ade134ab3c7", "sha256:aee2512827ceb6d7f517c8b85aa5d3923afe8fc7a57d028cffcd522f1c6fd082",
"sha256:a972cec723e0563aa0823ee2ab1df0cb196ed0778f173b381c871a03719d4826", "sha256:c8b0451d2ec95010d1db8ca733afc41f659f425b7f608af569711097fd6014e2",
"sha256:ac9bea18d6d58a995fac1b2cb4488e17eceeac413af014b1dd26170b766d8467", "sha256:c9aa4496fd0e17e3843399f533d62857cef5900facf93e735ef65aa4bbc90ef0",
"sha256:b0531f0b0e07643eb089df4c509d30d72c9ef40defa53e41363eca8a8cc61495", "sha256:cbc6472e01952d3d1b2772b720428f8b90e2deea8344e854df22b0618e9cce71",
"sha256:b208cfd4f5fe34e1535c08983a1a6803fdbc7a1e86cf13dd0c61de0b51a0aadc", "sha256:cdfe0c22692a30cd830c0755746473ae66c4a8f2e7bd508b35fb3b6a0813d787",
"sha256:b3482cb7b3325faa5f6bc179649406058253d91ceda359c104dac0ad320e1391", "sha256:cf802eef1f0134afb81fef94020351be4fe1d6681aadf9c5e862af6602af64ef",
"sha256:b6fb9c32a91ec32a689ec6410def76443e3c750e7cfc3fb2206b985ffb2b85f0", "sha256:d42f9c36d06440e34226e8bd65ff065ca0963aeecada587b937011efa02cdc9d",
"sha256:b78ea78450fd96a498f50ee096f69c75379af5138f7881a51355ab0e11286c97", "sha256:d5b47c440210c5d1d67e1cf434124e0b5c395eee1f5806fdd89b553ed1acd0a3",
"sha256:bd249bc894af67cbd8bad2c22e7cbcd46cf87ddfca1f1289d1e7e54868cc785c", "sha256:d9b4a8148c57ecac25a16b0e11798cbe88edf5237b0df99973687dd866f05e1b",
"sha256:c7d1fd447e33ee20c1f33f2c8e6634211124a9aabde3c617687d8b739aa69eac", "sha256:daf43a3d1ea699402c5a850e5313680ac355b4adc9770cd5cfc2940e7861f1bf",
"sha256:d0bbe7dd86dca64854f4b6ce2ea5c60b51e36dfd597300057cf473d3615f2369", "sha256:dbdc15f0c81611925f382dfa97b3bd0bc2c1ce19d4fe50482cb0ddc12ba30020",
"sha256:d6d6a0910c3b4368d89dde073e630882cdb266755565155bc33520283b2d9df8", "sha256:deaa09cd492e24fd9b15296844c0ad1b3c976da7907e1c1ed3a0ad21dded6f76",
"sha256:da1eeb460ecce8d5b8608826595c777728cdf28ce7b5a5a8c8ac8d949beadcf2", "sha256:e37242f5324ffd9f7ba5acf96d774f9276aa62a966c0bad8dae692deebec7716",
"sha256:e0c8854b09bc4de7b041148d8550d3bd712b5c21ff6a8ed308085f190235d7ff", "sha256:ed2cf9ed4e8ebc3b754d398cba12f24359f018b416c380f577bbae112ca52fc9",
"sha256:e0d4142eb40ca6f94539e4db929410f2a46052a0fe7a2c1c59f6179c39938d2a", "sha256:f2712c5179f40af9ddc8f6727f2bd910ea0eb50206daea75f58ddd9fa3f715bb",
"sha256:e9e82dcb3f2ebbc8cb5ce1102d5f1c5ed236bf8a11730fb45ba82e2841ec21df", "sha256:f4ca91d61a4bf61b0f2228f24bbfa6a9facd5f8af03759fe2a655c50ae2c6610",
"sha256:ed6906f61834d687738d25988ae117683705636936cc605be0bb208b23df4d8f" "sha256:f6b3dfc7661f8842babd8ea07e9897fe3d9b69a1d7e5fbb743e4160f9387833b"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.10'", "markers": "python_version >= '3.10'",
"version": "==2.2.2" "version": "==2.2.3"
}, },
"packaging": { "packaging": {
"hashes": [ "hashes": [
@ -693,6 +803,14 @@
"markers": "python_version >= '3.8'", "markers": "python_version >= '3.8'",
"version": "==24.2" "version": "==24.2"
}, },
"paypalrestsdk": {
"hashes": [
"sha256:a3f51616ee8f6d975a5a5a8c2049db63653c843479c8fdd71c9d588a31e14560",
"sha256:dac236492a9ac1260a760014a2e56ab38b09d8143295b5e896545359b61fedd6"
],
"index": "pypi",
"version": "==1.13.3"
},
"postgrest": { "postgrest": {
"hashes": [ "hashes": [
"sha256:03a7e638962454d10bb712c35e63a8a4bc452917917a4e9eb7427bd5b3c6c485", "sha256:03a7e638962454d10bb712c35e63a8a4bc452917917a4e9eb7427bd5b3c6c485",
@ -798,6 +916,14 @@
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==2.9.0" "version": "==2.9.0"
}, },
"pycparser": {
"hashes": [
"sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6",
"sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"
],
"markers": "python_version >= '3.8'",
"version": "==2.22"
},
"pydantic": { "pydantic": {
"hashes": [ "hashes": [
"sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584",
@ -930,6 +1056,14 @@
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==4.0.0" "version": "==4.0.0"
}, },
"pyopenssl": {
"hashes": [
"sha256:424c247065e46e76a37411b9ab1782541c23bb658bf003772c3405fbaa128e90",
"sha256:cd2cef799efa3936bb08e8ccb9433a575722b9dd986023f1cabc4ae64e9dac16"
],
"markers": "python_version >= '3.7'",
"version": "==25.0.0"
},
"python-dateutil": { "python-dateutil": {
"hashes": [ "hashes": [
"sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
@ -1075,50 +1209,56 @@
}, },
"scipy": { "scipy": {
"hashes": [ "hashes": [
"sha256:033a75ddad1463970c96a88063a1df87ccfddd526437136b6ee81ff0312ebdf6", "sha256:01edfac9f0798ad6b46d9c4c9ca0e0ad23dbf0b1eb70e96adb9fa7f525eff0bf",
"sha256:0458839c9f873062db69a03de9a9765ae2e694352c76a16be44f93ea45c28d2b", "sha256:03205d57a28e18dfd39f0377d5002725bf1f19a46f444108c29bdb246b6c8a11",
"sha256:070d10654f0cb6abd295bc96c12656f948e623ec5f9a4eab0ddb1466c000716e", "sha256:08b57a9336b8e79b305a143c3655cc5bdbe6d5ece3378578888d2afbb51c4e37",
"sha256:09c52320c42d7f5c7748b69e9f0389266fd4f82cf34c38485c14ee976cb8cb04", "sha256:11e7ad32cf184b74380f43d3c0a706f49358b904fa7d5345f16ddf993609184d",
"sha256:0ac102ce99934b162914b1e4a6b94ca7da0f4058b6d6fd65b0cef330c0f3346f", "sha256:28a0d2c2075946346e4408b211240764759e0fabaeb08d871639b5f3b1aca8a0",
"sha256:0fb57b30f0017d4afa5fe5f5b150b8f807618819287c21cbe51130de7ccdaed2", "sha256:2b871df1fe1a3ba85d90e22742b93584f8d2b8e6124f8372ab15c71b73e428b8",
"sha256:100193bb72fbff37dbd0bf14322314fc7cbe08b7ff3137f11a34d06dc0ee6b85", "sha256:302093e7dfb120e55515936cb55618ee0b895f8bcaf18ff81eca086c17bd80af",
"sha256:14eaa373c89eaf553be73c3affb11ec6c37493b7eaaf31cf9ac5dffae700c2e0", "sha256:42dabaaa798e987c425ed76062794e93a243be8f0f20fff6e7a89f4d61cb3d40",
"sha256:2114a08daec64980e4b4cbdf5bee90935af66d750146b1d2feb0d3ac30613692", "sha256:447ce30cee6a9d5d1379087c9e474628dab3db4a67484be1b7dc3196bfb2fac9",
"sha256:21e10b1dd56ce92fba3e786007322542361984f8463c6d37f6f25935a5a6ef52", "sha256:4c6676490ad76d1c2894d77f976144b41bd1a4052107902238047fb6a473e971",
"sha256:2722a021a7929d21168830790202a75dbb20b468a8133c74a2c0230c72626b6c", "sha256:54c462098484e7466362a9f1672d20888f724911a74c22ae35b61f9c5919183d",
"sha256:395be70220d1189756068b3173853029a013d8c8dd5fd3d1361d505b2aa58fa7", "sha256:597a0c7008b21c035831c39927406c6181bcf8f60a73f36219b69d010aa04737",
"sha256:3fe1d95944f9cf6ba77aa28b82dd6bb2a5b52f2026beb39ecf05304b8392864b", "sha256:5a6fd6eac1ce74a9f77a7fc724080d507c5812d61e72bd5e4c489b042455865e",
"sha256:491d57fe89927fa1aafbe260f4cfa5ffa20ab9f1435025045a5315006a91b8f5", "sha256:5ea7ed46d437fc52350b028b1d44e002646e28f3e8ddc714011aaf87330f2f32",
"sha256:4b17d4220df99bacb63065c76b0d1126d82bbf00167d1730019d2a30d6ae01ea", "sha256:601881dfb761311045b03114c5fe718a12634e5608c3b403737ae463c9885d53",
"sha256:4c9d8fc81d6a3b6844235e6fd175ee1d4c060163905a2becce8e74cb0d7554ce", "sha256:62ca1ff3eb513e09ed17a5736929429189adf16d2d740f44e53270cc800ecff1",
"sha256:55cc79ce4085c702ac31e49b1e69b27ef41111f22beafb9b49fea67142b696c4", "sha256:69ea6e56d00977f355c0f84eba69877b6df084516c602d93a33812aa04d90a3d",
"sha256:5b190b935e7db569960b48840e5bef71dc513314cc4e79a1b7d14664f57fd4ff", "sha256:6a8e34cf4c188b6dd004654f88586d78f95639e48a25dfae9c5e34a6dc34547e",
"sha256:5bd8d27d44e2c13d0c1124e6a556454f52cd3f704742985f6b09e75e163d20d2", "sha256:6d0194c37037707b2afa7a2f2a924cf7bac3dc292d51b6a925e5fcb89bc5c776",
"sha256:5dff14e75cdbcf07cdaa1c7707db6017d130f0af9ac41f6ce443a93318d6c6e0", "sha256:6f223753c6ea76983af380787611ae1291e3ceb23917393079dcc746ba60cfb5",
"sha256:5eb0ca35d4b08e95da99a9f9c400dc9f6c21c424298a0ba876fdc69c7afacedf", "sha256:6f5e296ec63c5da6ba6fa0343ea73fd51b8b3e1a300b0a8cae3ed4b1122c7462",
"sha256:63b9b6cd0333d0eb1a49de6f834e8aeaefe438df8f6372352084535ad095219e", "sha256:7cd5b77413e1855351cdde594eca99c1f4a588c2d63711388b6a1f1c01f62274",
"sha256:667f950bf8b7c3a23b4199db24cb9bf7512e27e86d0e3813f015b74ec2c6e3df", "sha256:869269b767d5ee7ea6991ed7e22b3ca1f22de73ab9a49c44bad338b725603301",
"sha256:6b3e71893c6687fc5e29208d518900c24ea372a862854c9888368c0b267387ab", "sha256:87994da02e73549dfecaed9e09a4f9d58a045a053865679aeb8d6d43747d4df3",
"sha256:71ba9a76c2390eca6e359be81a3e879614af3a71dfdabb96d1d7ab33da6f2364", "sha256:888307125ea0c4466287191e5606a2c910963405ce9671448ff9c81c53f85f58",
"sha256:74bb864ff7640dea310a1377d8567dc2cb7599c26a79ca852fc184cc851954ac", "sha256:92233b2df6938147be6fa8824b8136f29a18f016ecde986666be5f4d686a91a4",
"sha256:82add84e8a9fb12af5c2c1a3a3f1cb51849d27a580cb9e6bd66226195142be6e", "sha256:9412f5e408b397ff5641080ed1e798623dbe1ec0d78e72c9eca8992976fa65aa",
"sha256:837299eec3d19b7e042923448d17d95a86e43941104d33f00da7e31a0f715d3c", "sha256:9b18aa747da280664642997e65aab1dd19d0c3d17068a04b3fe34e2559196cb9",
"sha256:900f3fa3db87257510f011c292a5779eb627043dd89731b9c461cd16ef76ab3d", "sha256:9de9d1416b3d9e7df9923ab23cd2fe714244af10b763975bea9e4f2e81cebd27",
"sha256:9f151e9fb60fbf8e52426132f473221a49362091ce7a5e72f8aa41f8e0da4f25", "sha256:a2ec871edaa863e8213ea5df811cd600734f6400b4af272e1c011e69401218e9",
"sha256:af0b61c1de46d0565b4b39c6417373304c1d4f5220004058bdad3061c9fa8a95", "sha256:a5080a79dfb9b78b768cebf3c9dcbc7b665c5875793569f48bf0e2b1d7f68f6f",
"sha256:bc7136626261ac1ed988dca56cfc4ab5180f75e0ee52e58f1e6aa74b5f3eacd5", "sha256:a8bf5cb4a25046ac61d38f8d3c3426ec11ebc350246a4642f2f315fe95bda655",
"sha256:be3deeb32844c27599347faa077b359584ba96664c5c79d71a354b80a0ad0ce0", "sha256:b09ae80010f52efddb15551025f9016c910296cf70adbf03ce2a8704f3a5ad20",
"sha256:c09aa9d90f3500ea4c9b393ee96f96b0ccb27f2f350d09a47f533293c78ea776", "sha256:b5e025e903b4f166ea03b109bb241355b9c42c279ea694d8864d033727205e65",
"sha256:c352c1b6d7cac452534517e022f8f7b8d139cd9f27e6fbd9f3cbd0bfd39f5bef", "sha256:bad78d580270a4d32470563ea86c6590b465cb98f83d760ff5b0990cb5518a93",
"sha256:c64ded12dcab08afff9e805a67ff4480f5e69993310e093434b10e85dc9d43e1", "sha256:bae43364d600fdc3ac327db99659dcb79e6e7ecd279a75fe1266669d9a652828",
"sha256:cdde8414154054763b42b74fe8ce89d7f3d17a7ac5dd77204f0e142cdc9239e9", "sha256:c4697a10da8f8765bb7c83e24a470da5797e37041edfd77fd95ba3811a47c4fd",
"sha256:ce3a000cd28b4430426db2ca44d96636f701ed12e2b3ca1f2b1dd7abdd84b39a", "sha256:c90ebe8aaa4397eaefa8455a8182b164a6cc1d59ad53f79943f266d99f68687f",
"sha256:f735bc41bd1c792c96bc426dece66c8723283695f02df61dcc4d0a707a42fc54", "sha256:cd58a314d92838f7e6f755c8a2167ead4f27e1fd5c1251fd54289569ef3495ec",
"sha256:f82fcf4e5b377f819542fbc8541f7b5fbcf1c0017d0df0bc22c781bf60abc4d8" "sha256:cf72ff559a53a6a6d77bd8eefd12a17995ffa44ad86c77a5df96f533d4e6c6bb",
"sha256:def751dd08243934c884a3221156d63e15234a3155cf25978b0a668409d45eb6",
"sha256:e7c68b6a43259ba0aab737237876e5c2c549a031ddb7abc28c7b47f22e202ded",
"sha256:ecf797d2d798cf7c838c6d98321061eb3e72a74710e6c40540f0e8087e3b499e",
"sha256:f031846580d9acccd0044efd1a90e6f4df3a6e12b4b6bd694a7bc03a89892b28",
"sha256:fb530e4794fc8ea76a4a21ccb67dea33e5e0e60f07fc38a49e821e1eae3b71a0",
"sha256:fe8a9eb875d430d81755472c5ba75e84acc980e4a8f6204d402849234d3017db"
], ],
"index": "pypi", "index": "pypi",
"markers": "python_version >= '3.10'", "markers": "python_version >= '3.10'",
"version": "==1.15.1" "version": "==1.15.2"
}, },
"shapely": { "shapely": {
"hashes": [ "hashes": [

View File

@ -328,7 +328,7 @@ div.media {
</head> </head>
<body> <body>
<h1 id="title">Backend Testing Report</h1> <h1 id="title">Backend Testing Report</h1>
<p>Report generated on 17-Feb-2025 at 10:26:33 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a> <p>Report generated on 17-Feb-2025 at 11:20:02 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a>
v4.1.1</p> v4.1.1</p>
<div id="environment-header"> <div id="environment-header">
<h2>Environment</h2> <h2>Environment</h2>
@ -382,7 +382,7 @@ div.media {
<h2>Summary</h2> <h2>Summary</h2>
<div class="additional-summary prefix"> <div class="additional-summary prefix">
</div> </div>
<p class="run-count">1 test took 415 ms.</p> <p class="run-count">1 test took 524 ms.</p>
<p class="filter">(Un)check the boxes to filter the results.</p> <p class="filter">(Un)check the boxes to filter the results.</p>
<div class="summary__reload"> <div class="summary__reload">
<div class="summary__reload__button hidden" onclick="location.reload()"> <div class="summary__reload__button hidden" onclick="location.reload()">
@ -432,7 +432,7 @@ div.media {
</table> </table>
</body> </body>
<footer> <footer>
<div id="data-container" data-jsonblob="{&#34;environment&#34;: {&#34;Python&#34;: &#34;3.12.3&#34;, &#34;Platform&#34;: &#34;Linux-6.8.0-53-generic-x86_64-with-glibc2.39&#34;, &#34;Packages&#34;: {&#34;pytest&#34;: &#34;8.3.4&#34;, &#34;pluggy&#34;: &#34;1.5.0&#34;}, &#34;Plugins&#34;: {&#34;html&#34;: &#34;4.1.1&#34;, &#34;anyio&#34;: &#34;4.8.0&#34;, &#34;metadata&#34;: &#34;3.1.1&#34;}}, &#34;tests&#34;: {&#34;src/tests/test_user.py::test_user_handling&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Passed&#34;, &#34;testId&#34;: &#34;src/tests/test_user.py::test_user_handling&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Passed&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;src/tests/test_user.py::test_user_handling&lt;/td&gt;&#34;, &#34;&lt;td&gt;N/A&lt;/td&gt;&#34;, &#34;&lt;td&gt;N/A&lt;/td&gt;&#34;, &#34;&lt;td&gt;N/A&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;415 ms&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.main:main.py:291 User created successfully, ID: c1b09594-24d8-47fd-91a8-b84afcea46f3\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nERROR src.main:main.py:283 Failed to create user : email_exists\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nDEBUG src.main:main.py:301 None\nINFO src.main:main.py:309 User with ID c1b09594-24d8-47fd-91a8-b84afcea46f3 deleted successfully\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nERROR src.main:main.py:304 Failed to delete user : user_not_found\n\n&#34;}]}, &#34;renderCollapsed&#34;: [&#34;passed&#34;], &#34;initialSort&#34;: &#34;result&#34;, &#34;title&#34;: &#34;Backend Testing Report&#34;}"></div> <div id="data-container" data-jsonblob="{&#34;environment&#34;: {&#34;Python&#34;: &#34;3.12.3&#34;, &#34;Platform&#34;: &#34;Linux-6.8.0-53-generic-x86_64-with-glibc2.39&#34;, &#34;Packages&#34;: {&#34;pytest&#34;: &#34;8.3.4&#34;, &#34;pluggy&#34;: &#34;1.5.0&#34;}, &#34;Plugins&#34;: {&#34;html&#34;: &#34;4.1.1&#34;, &#34;anyio&#34;: &#34;4.8.0&#34;, &#34;metadata&#34;: &#34;3.1.1&#34;}}, &#34;tests&#34;: {&#34;src/tests/test_user.py::test_user_handling&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Passed&#34;, &#34;testId&#34;: &#34;src/tests/test_user.py::test_user_handling&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Passed&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;src/tests/test_user.py::test_user_handling&lt;/td&gt;&#34;, &#34;&lt;td&gt;N/A&lt;/td&gt;&#34;, &#34;&lt;td&gt;N/A&lt;/td&gt;&#34;, &#34;&lt;td&gt;N/A&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;524 ms&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;------------------------------ Captured log call -------------------------------\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nINFO src.payments.supabase_routes:supabase_routes.py:34 User created successfully, ID: e0b9176d-0211-43fc-b8c7-db815293835e\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nERROR src.payments.supabase_routes:supabase_routes.py:26 Failed to create user : email_exists\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nDEBUG src.payments.supabase_routes:supabase_routes.py:44 None\nINFO src.payments.supabase_routes:supabase_routes.py:52 User with ID e0b9176d-0211-43fc-b8c7-db815293835e deleted successfully\nDEBUG asyncio:selector_events.py:64 Using selector: EpollSelector\nERROR src.payments.supabase_routes:supabase_routes.py:47 Failed to delete user : user_not_found\n\n&#34;}]}, &#34;renderCollapsed&#34;: [&#34;passed&#34;], &#34;initialSort&#34;: &#34;result&#34;, &#34;title&#34;: &#34;Backend Testing Report&#34;}"></div>
<script> <script>
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
const { getCollapsedCategory, setCollapsedIds } = require('./storage.js') const { getCollapsedCategory, setCollapsedIds } = require('./storage.js')

View File

@ -1,7 +1,6 @@
"""Main app for backend api""" """Main app for backend api"""
import logging import logging
import traceback
import time import time
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException, BackgroundTasks, Query, Body from fastapi import FastAPI, HTTPException, BackgroundTasks, Query, Body
@ -11,15 +10,15 @@ from .structs.landmark import Landmark, Toilets
from .structs.preferences import Preferences from .structs.preferences import Preferences
from .structs.linked_landmarks import LinkedLandmarks from .structs.linked_landmarks import LinkedLandmarks
from .structs.trip import Trip from .structs.trip import Trip
from .structs.requests import UserDeleteRequest
from .utils.landmarks_manager import LandmarkManager from .utils.landmarks_manager import LandmarkManager
from .utils.toilets_manager import ToiletsManager from .utils.toilets_manager import ToiletsManager
from .optimization.optimizer import Optimizer from .optimization.optimizer import Optimizer
from .optimization.refiner import Refiner from .optimization.refiner import Refiner
from .overpass.overpass import fill_cache from .overpass.overpass import fill_cache
from .cache import client as cache_client from .cache import client as cache_client
# from .payments.payment_routes import router as payment_router
from .payments.supabase import Supabase from .payments.supabase import Supabase
from .payments.payment_routes import router as payment_router
from .payments.supabase_routes import router as supabase_router
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -42,8 +41,9 @@ async def lifespan(app: FastAPI):
app = FastAPI(lifespan=lifespan) app = FastAPI(lifespan=lifespan)
# Include the payment routes # Include the payment routes and supabase routes
# app.include_router(payment_router, prefix="/payments") app.include_router(payment_router)
app.include_router(supabase_router)
@app.post("/trip/new") @app.post("/trip/new")
@ -270,42 +270,4 @@ def get_toilets(location: tuple[float, float] = Query(...), radius: int = 500) -
raise HTTPException(status_code=404, detail="No toilets found") from exc raise HTTPException(status_code=404, detail="No toilets found") from exc
@app.post("/user/create/{email}/{password}")
def register_user(email: str, password: str) -> str:
try:
response = supabase.supabase.auth.admin.create_user({
"email": email,
"password": password
})
except Exception as e:
if e.code == 'email_exists' :
logger.error(f"Failed to create user : {str(e.code)}")
raise HTTPException(status_code=422, detail=str(e)) from e
logger.error(f"Failed to create user : {str(e.code)}")
raise HTTPException(status_code=500, detail=str(e)) from e
# Extract the identity_id and user_id
user_id = response.user.id
logger.info(f"User created successfully, ID: {user_id}")
return user_id
@app.post("/user/delete/{user_id}")
def delete_user(user_id: str):
try:
response = supabase.supabase.auth.admin.delete_user(user_id)
logger.debug(response)
except Exception as e:
if e.code == 'user_not_found' :
logger.error(f"Failed to delete user : {str(e.code)}")
raise HTTPException(status_code=404, detail=str(e)) from e
logger.error(f"Failed to create user : {str(e.code)}")
raise HTTPException(status_code=500, detail=str(e)) from e
logger.info(f"User with ID {user_id} deleted successfully")

View File

View File

@ -0,0 +1,70 @@
from typing import Literal
import paypalrestsdk
from pydantic import BaseModel
from fastapi import HTTPException
import logging
# Model for payment request body
class PaymentRequest(BaseModel):
user_id: str
credit_amount: Literal[10, 50, 100]
currency: Literal["USD", "EUR", "CHF"]
description: str = "Purchase of credits"
# Payment handler class for managing PayPal payments
class PaymentHandler:
payment_id: str
def __init__(self, transaction_details: PaymentRequest):
self.details = transaction_details
self.logger = logging.getLogger(__name__)
# Only support purchase of credit 'bundles': 10, 50 or 100 credits worth of trip generation
def fetch_price(self) -> float:
"""
Fetches the price of credits in the specified currency.
"""
result = self.supabase.table("prices").select("credit_amount").eq("currency", self.details.currency).single().execute()
if result.data:
return result.data.get("price")
else:
self.logger.error(f"Unsupported currency: {self.details.currency}")
return None
def create_paypal_payment(self) -> str:
"""
Creates a PayPal payment and returns the approval URL.
"""
price = self.fetch_price()
payment = paypalrestsdk.Payment({
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"transactions": [{
"amount": {
"total": f"{price:.2f}",
"currency": self.details.currency
},
"description": self.details.description
}],
"redirect_urls": {
"return_url": "http://localhost:8000/payment/success",
"cancel_url": "http://localhost:8000/payment/cancel"
}
})
if payment.create():
self.logger.info("Payment created successfully")
self.payment_id = payment.id
# Get the approval URL and return it for the user to approve
for link in payment.links:
if link.rel == "approval_url":
return link.href
else:
self.logger.error(f"Failed to create payment: {payment.error}")
raise HTTPException(status_code=500, detail="Payment creation failed")

View File

@ -1,49 +1,79 @@
from os import getenv import logging
from fastapi import APIRouter, HTTPException import paypalrestsdk
from .paypal import create_paypal_order, capture_paypal_order from fastapi import HTTPException, APIRouter
from supabase import create_client, Client
from ..constants import SUPABASE_URL, SUPABASE_KEY from .payment_handler import PaymentRequest, PaymentHandler
from .supabase import Supabase
# Set up logging and supabase
logger = logging.getLogger(__name__)
supabase = Supabase()
# Configure PayPal SDK
paypalrestsdk.configure({
"mode": "sandbox", # Use 'live' for production
"client_id": "YOUR_PAYPAL_CLIENT_ID",
"client_secret": "YOUR_PAYPAL_SECRET"
})
# Initialize Supabase # Define the API router
supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
# Define router
router = APIRouter() router = APIRouter()
@router.post("/purchase/credits")
def purchase_credits(payment_request: PaymentRequest):
"""
Handles token purchases. Calculates the number of tokens based on the amount paid,
updates the user's balance, and processes PayPal payment.
"""
payment_handler = PaymentHandler(payment_request)
@router.post("/create-paypal-payment/") # Create PayPal payment and get the approval URL
def create_payment(amount: float, currency: str = "USD"): approval_url = payment_handler.create_paypal_payment()
"""
Create a PayPal payment and return approval URL. return {
""" "message": "Purchase initiated successfully",
try: "payment_id": payment_handler.payment_id,
payment = create_paypal_order(amount, currency) "credits": payment_request.credit_amount,
return {"approval_url": payment["approval_url"]} "approval_url": approval_url,
except Exception as e: }
raise HTTPException(status_code=500, detail=str(e))
@router.post("/capture-paypal-payment/") @router.get("/payment/success")
def capture_payment(order_id: str, user_id: str, country: str): def payment_success(paymentId: str, PayerID: str):
""" """
Capture the PayPal payment and unlock the country in Supabase. Handles successful PayPal payment.
""" """
try: payment = paypalrestsdk.Payment.find(paymentId)
# Capture payment
capture_response = capture_paypal_order(order_id) if payment.execute({"payer_id": PayerID}):
if capture_response.get("status") == "COMPLETED": logger.info("Payment executed successfully")
# Update Supabase to unlock the country for the user
supabase.table("unlocked_countries").insert({ # Retrieve transaction details from the database
"user_id": user_id, result = supabase.table("pending_payments").select("*").eq("payment_id", paymentId).single().execute()
"country": country, if not result.data:
"paid": True, raise HTTPException(status_code=404, detail="Transaction not found")
}).execute()
# Extract the necessary information
user_id = result.data["user_id"]
credit_amount = result.data["credit_amount"]
# Update the user's balance
supabase.increment_credit_balance(user_id, amount=credit_amount)
# Optionally, delete the pending payment entry since the transaction is completed
supabase.table("pending_payments").delete().eq("payment_id", paymentId).execute()
return {"message": "Payment completed successfully"}
else:
logger.error(f"Payment execution failed: {payment.error}")
raise HTTPException(status_code=500, detail="Payment execution failed")
@router.get("/payment/cancel")
def payment_cancel():
"""
Handles PayPal payment cancellation.
"""
return {"message": "Payment was cancelled"}
return {"status": "Payment captured and country unlocked successfully"}
else:
raise HTTPException(status_code=400, detail="Payment not completed")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

View File

@ -1,87 +0,0 @@
from requests import post
from fastapi import HTTPException
from ..constants import PAYPAL_API_URL, PAYPAL_CLIENT_ID, PAYPAL_SECRET
def get_paypal_access_token():
"""
Get an access token from PayPal to authenticate API requests.
"""
response = post(
f"{PAYPAL_API_URL}/v1/oauth2/token",
headers={
"Accept": "application/json",
"Accept-Language": "en_US",
},
data={"grant_type": "client_credentials"},
auth=(PAYPAL_CLIENT_ID, PAYPAL_SECRET),
)
if response.status_code != 200:
raise HTTPException(status_code=response.status_code, detail="Failed to get PayPal access token")
return response.json()["access_token"]
def create_paypal_order(amount: float, currency: str = "USD"):
"""
Create a PayPal payment order.
"""
access_token = get_paypal_access_token()
order_data = {
"intent": "CAPTURE",
"purchase_units": [
{
"amount": {
"currency_code": currency,
"value": f"{amount:.2f}",
}
}
],
"application_context": {
"return_url": "https://placeholderlink.com/payment-success",
"cancel_url": "https://placeholderlink.com/payment-cancelled",
}
}
response = post(
f"{PAYPAL_API_URL}/v2/checkout/orders",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {access_token}",
},
json=order_data,
)
if response.status_code != 201:
raise HTTPException(status_code=response.status_code, detail="Failed to create PayPal order")
order = response.json()
approval_url = next(link['href'] for link in order['links'] if link['rel'] == 'approve')
return {
"approval_url": approval_url,
"order_id": order["id"],
}
def capture_paypal_order(order_id: str):
"""
Capture the PayPal payment order after user approval.
"""
access_token = get_paypal_access_token()
response = post(
f"{PAYPAL_API_URL}/v2/checkout/orders/{order_id}/capture",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {access_token}",
},
)
if response.status_code != 201:
raise HTTPException(status_code=response.status_code, detail="Failed to capture PayPal payment")
return response.json()

View File

@ -75,9 +75,8 @@ class Supabase:
self.logger.warning(f'Insufficient balance for user {user_id}. Trip generation cannot proceed.') self.logger.warning(f'Insufficient balance for user {user_id}. Trip generation cannot proceed.')
return False return False
def decrement_credit_balance(self, user_id: str) -> bool: def decrement_credit_balance(self, user_id: str, amount: int=1) -> bool:
""" """
Decrements the user's credit balance by 1. Decrements the user's credit balance by 1.
@ -106,7 +105,7 @@ class Supabase:
current_credits = response.data['credit_amount'] current_credits = response.data['credit_amount']
updated_credits = current_credits - 1 updated_credits = current_credits - amount
# Update the user's credits in the table # Update the user's credits in the table
update_response = ( update_response = (
@ -124,7 +123,7 @@ class Supabase:
raise Exception("Error decrementing credit balance.") raise Exception("Error decrementing credit balance.")
def increment_credit_balance(self, user_id: str) -> bool: def increment_credit_balance(self, user_id: str, amount: int=1) -> bool:
""" """
Increments the user's credit balance by 1. Increments the user's credit balance by 1.
@ -153,7 +152,7 @@ class Supabase:
current_credits = response.data['credit_amount'] current_credits = response.data['credit_amount']
updated_credits = current_credits + 1 updated_credits = current_credits + amount
# Update the user's credits in the table # Update the user's credits in the table
update_response = ( update_response = (

View File

@ -0,0 +1,52 @@
"""Endpoints for supabase user handling."""
import logging
from fastapi import APIRouter, HTTPException
from .supabase import Supabase
# Set up logging and supabase.
logger = logging.getLogger(__name__)
supabase = Supabase()
# Create fastapi router
router = APIRouter()
@router.post("/user/create/{email}/{password}")
def register_user(email: str, password: str) -> str:
try:
response = supabase.supabase.auth.admin.create_user({
"email": email,
"password": password
})
except Exception as e:
if e.code == 'email_exists' :
logger.error(f"Failed to create user : {str(e.code)}")
raise HTTPException(status_code=422, detail=str(e)) from e
logger.error(f"Failed to create user : {str(e.code)}")
raise HTTPException(status_code=500, detail=str(e)) from e
# Extract the identity_id and user_id
user_id = response.user.id
logger.info(f"User created successfully, ID: {user_id}")
return user_id
@router.post("/user/delete/{user_id}")
def delete_user(user_id: str):
try:
response = supabase.supabase.auth.admin.delete_user(user_id)
logger.debug(response)
except Exception as e:
if e.code == 'user_not_found' :
logger.error(f"Failed to delete user : {str(e.code)}")
raise HTTPException(status_code=404, detail=str(e)) from e
logger.error(f"Failed to create user : {str(e.code)}")
raise HTTPException(status_code=500, detail=str(e)) from e
logger.info(f"User with ID {user_id} deleted successfully")

View File

@ -1,4 +0,0 @@
from pydantic import BaseModel
class UserDeleteRequest(BaseModel):
user_id: str