backend/feature/supabase #60
| @@ -26,3 +26,4 @@ pulp = "*" | ||||
| scipy = "*" | ||||
| requests = "*" | ||||
| supabase = "*" | ||||
| paypalrestsdk = "*" | ||||
|   | ||||
							
								
								
									
										336
									
								
								backend/Pipfile.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										336
									
								
								backend/Pipfile.lock
									
									
									
										generated
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|     "_meta": { | ||||
|         "hash": { | ||||
|             "sha256": "6fb866543b6ea2eb10165b6451666650fff3949e872b4dd4902d0b728f1b495c" | ||||
|             "sha256": "e02d6fa1d52eaf7da8fc8814385d25a0346398b744522245ef96c28a4c712b25" | ||||
|         }, | ||||
|         "pipfile-spec": 6, | ||||
|         "requires": {}, | ||||
| @@ -149,6 +149,79 @@ | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "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": { | ||||
|             "hashes": [ | ||||
|                 "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", | ||||
| @@ -255,6 +328,43 @@ | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "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": { | ||||
|             "hashes": [ | ||||
|                 "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff", | ||||
| @@ -625,65 +735,65 @@ | ||||
|         }, | ||||
|         "numpy": { | ||||
|             "hashes": [ | ||||
|                 "sha256:02935e2c3c0c6cbe9c7955a8efa8908dd4221d7755644c59d1bba28b94fd334f", | ||||
|                 "sha256:0349b025e15ea9d05c3d63f9657707a4e1d471128a3b1d876c095f328f8ff7f0", | ||||
|                 "sha256:09d6a2032faf25e8d0cadde7fd6145118ac55d2740132c1d845f98721b5ebcfd", | ||||
|                 "sha256:0bc61b307655d1a7f9f4b043628b9f2b721e80839914ede634e3d485913e1fb2", | ||||
|                 "sha256:0eec19f8af947a61e968d5429f0bd92fec46d92b0008d0a6685b40d6adf8a4f4", | ||||
|                 "sha256:106397dbbb1896f99e044efc90360d098b3335060375c26aa89c0d8a97c5f648", | ||||
|                 "sha256:128c41c085cab8a85dc29e66ed88c05613dccf6bc28b3866cd16050a2f5448be", | ||||
|                 "sha256:149d1113ac15005652e8d0d3f6fd599360e1a708a4f98e43c9c77834a28238cb", | ||||
|                 "sha256:159ff6ee4c4a36a23fe01b7c3d07bd8c14cc433d9720f977fcd52c13c0098160", | ||||
|                 "sha256:22ea3bb552ade325530e72a0c557cdf2dea8914d3a5e1fecf58fa5dbcc6f43cd", | ||||
|                 "sha256:23ae9f0c2d889b7b2d88a3791f6c09e2ef827c2446f1c4a3e3e76328ee4afd9a", | ||||
|                 "sha256:250c16b277e3b809ac20d1f590716597481061b514223c7badb7a0f9993c7f84", | ||||
|                 "sha256:2ec6c689c61df613b783aeb21f945c4cbe6c51c28cb70aae8430577ab39f163e", | ||||
|                 "sha256:2ffbb1acd69fdf8e89dd60ef6182ca90a743620957afb7066385a7bbe88dc748", | ||||
|                 "sha256:3074634ea4d6df66be04f6728ee1d173cfded75d002c75fac79503a880bf3825", | ||||
|                 "sha256:356ca982c188acbfa6af0d694284d8cf20e95b1c3d0aefa8929376fea9146f60", | ||||
|                 "sha256:3fbe72d347fbc59f94124125e73fc4976a06927ebc503ec5afbfb35f193cd957", | ||||
|                 "sha256:40c7ff5da22cd391944a28c6a9c638a5eef77fcf71d6e3a79e1d9d9e82752715", | ||||
|                 "sha256:41184c416143defa34cc8eb9d070b0a5ba4f13a0fa96a709e20584638254b317", | ||||
|                 "sha256:451e854cfae0febe723077bd0cf0a4302a5d84ff25f0bfece8f29206c7bed02e", | ||||
|                 "sha256:4525b88c11906d5ab1b0ec1f290996c0020dd318af8b49acaa46f198b1ffc283", | ||||
|                 "sha256:463247edcee4a5537841d5350bc87fe8e92d7dd0e8c71c995d2c6eecb8208278", | ||||
|                 "sha256:4dbd80e453bd34bd003b16bd802fac70ad76bd463f81f0c518d1245b1c55e3d9", | ||||
|                 "sha256:57b4012e04cc12b78590a334907e01b3a85efb2107df2b8733ff1ed05fce71de", | ||||
|                 "sha256:5a8c863ceacae696aff37d1fd636121f1a512117652e5dfb86031c8d84836369", | ||||
|                 "sha256:5acea83b801e98541619af398cc0109ff48016955cc0818f478ee9ef1c5c3dcb", | ||||
|                 "sha256:642199e98af1bd2b6aeb8ecf726972d238c9877b0f6e8221ee5ab945ec8a2189", | ||||
|                 "sha256:64bd6e1762cd7f0986a740fee4dff927b9ec2c5e4d9a28d056eb17d332158014", | ||||
|                 "sha256:6d9fc9d812c81e6168b6d405bf00b8d6739a7f72ef22a9214c4241e0dc70b323", | ||||
|                 "sha256:7079129b64cb78bdc8d611d1fd7e8002c0a2565da6a47c4df8062349fee90e3e", | ||||
|                 "sha256:7dca87ca328f5ea7dafc907c5ec100d187911f94825f8700caac0b3f4c384b49", | ||||
|                 "sha256:860fd59990c37c3ef913c3ae390b3929d005243acca1a86facb0773e2d8d9e50", | ||||
|                 "sha256:8e6da5cffbbe571f93588f562ed130ea63ee206d12851b60819512dd3e1ba50d", | ||||
|                 "sha256:8ec0636d3f7d68520afc6ac2dc4b8341ddb725039de042faf0e311599f54eb37", | ||||
|                 "sha256:9491100aba630910489c1d0158034e1c9a6546f0b1340f716d522dc103788e39", | ||||
|                 "sha256:97b974d3ba0fb4612b77ed35d7627490e8e3dff56ab41454d9e8b23448940576", | ||||
|                 "sha256:995f9e8181723852ca458e22de5d9b7d3ba4da3f11cc1cb113f093b271d7965a", | ||||
|                 "sha256:9dd47ff0cb2a656ad69c38da850df3454da88ee9a6fde0ba79acceee0e79daba", | ||||
|                 "sha256:9fad446ad0bc886855ddf5909cbf8cb5d0faa637aaa6277fb4b19ade134ab3c7", | ||||
|                 "sha256:a972cec723e0563aa0823ee2ab1df0cb196ed0778f173b381c871a03719d4826", | ||||
|                 "sha256:ac9bea18d6d58a995fac1b2cb4488e17eceeac413af014b1dd26170b766d8467", | ||||
|                 "sha256:b0531f0b0e07643eb089df4c509d30d72c9ef40defa53e41363eca8a8cc61495", | ||||
|                 "sha256:b208cfd4f5fe34e1535c08983a1a6803fdbc7a1e86cf13dd0c61de0b51a0aadc", | ||||
|                 "sha256:b3482cb7b3325faa5f6bc179649406058253d91ceda359c104dac0ad320e1391", | ||||
|                 "sha256:b6fb9c32a91ec32a689ec6410def76443e3c750e7cfc3fb2206b985ffb2b85f0", | ||||
|                 "sha256:b78ea78450fd96a498f50ee096f69c75379af5138f7881a51355ab0e11286c97", | ||||
|                 "sha256:bd249bc894af67cbd8bad2c22e7cbcd46cf87ddfca1f1289d1e7e54868cc785c", | ||||
|                 "sha256:c7d1fd447e33ee20c1f33f2c8e6634211124a9aabde3c617687d8b739aa69eac", | ||||
|                 "sha256:d0bbe7dd86dca64854f4b6ce2ea5c60b51e36dfd597300057cf473d3615f2369", | ||||
|                 "sha256:d6d6a0910c3b4368d89dde073e630882cdb266755565155bc33520283b2d9df8", | ||||
|                 "sha256:da1eeb460ecce8d5b8608826595c777728cdf28ce7b5a5a8c8ac8d949beadcf2", | ||||
|                 "sha256:e0c8854b09bc4de7b041148d8550d3bd712b5c21ff6a8ed308085f190235d7ff", | ||||
|                 "sha256:e0d4142eb40ca6f94539e4db929410f2a46052a0fe7a2c1c59f6179c39938d2a", | ||||
|                 "sha256:e9e82dcb3f2ebbc8cb5ce1102d5f1c5ed236bf8a11730fb45ba82e2841ec21df", | ||||
|                 "sha256:ed6906f61834d687738d25988ae117683705636936cc605be0bb208b23df4d8f" | ||||
|                 "sha256:0391ea3622f5c51a2e29708877d56e3d276827ac5447d7f45e9bc4ade8923c52", | ||||
|                 "sha256:12c045f43b1d2915eca6b880a7f4a256f59d62df4f044788c8ba67709412128d", | ||||
|                 "sha256:136553f123ee2951bfcfbc264acd34a2fc2f29d7cdf610ce7daf672b6fbaa693", | ||||
|                 "sha256:1402da8e0f435991983d0a9708b779f95a8c98c6b18a171b9f1be09005e64d9d", | ||||
|                 "sha256:16372619ee728ed67a2a606a614f56d3eabc5b86f8b615c79d01957062826ca8", | ||||
|                 "sha256:1ad78ce7f18ce4e7df1b2ea4019b5817a2f6a8a16e34ff2775f646adce0a5027", | ||||
|                 "sha256:1b416af7d0ed3271cad0f0a0d0bee0911ed7eba23e66f8424d9f3dfcdcae1304", | ||||
|                 "sha256:1f45315b2dc58d8a3e7754fe4e38b6fce132dab284a92851e41b2b344f6441c5", | ||||
|                 "sha256:2376e317111daa0a6739e50f7ee2a6353f768489102308b0d98fcf4a04f7f3b5", | ||||
|                 "sha256:23c9f4edbf4c065fddb10a4f6e8b6a244342d95966a48820c614891e5059bb50", | ||||
|                 "sha256:246535e2f7496b7ac85deffe932896a3577be7af8fb7eebe7146444680297e9a", | ||||
|                 "sha256:2e8da03bd561504d9b20e7a12340870dfc206c64ea59b4cfee9fceb95070ee94", | ||||
|                 "sha256:34c1b7e83f94f3b564b35f480f5652a47007dd91f7c839f404d03279cc8dd021", | ||||
|                 "sha256:39261798d208c3095ae4f7bc8eaeb3481ea8c6e03dc48028057d3cbdbdb8937e", | ||||
|                 "sha256:3b787adbf04b0db1967798dba8da1af07e387908ed1553a0d6e74c084d1ceafe", | ||||
|                 "sha256:3c2ec8a0f51d60f1e9c0c5ab116b7fc104b165ada3f6c58abf881cb2eb16044d", | ||||
|                 "sha256:435e7a933b9fda8126130b046975a968cc2d833b505475e588339e09f7672890", | ||||
|                 "sha256:4d8335b5f1b6e2bce120d55fb17064b0262ff29b459e8493d1785c18ae2553b8", | ||||
|                 "sha256:4d9828d25fb246bedd31e04c9e75714a4087211ac348cb39c8c5f99dbb6683fe", | ||||
|                 "sha256:52659ad2534427dffcc36aac76bebdd02b67e3b7a619ac67543bc9bfe6b7cdb1", | ||||
|                 "sha256:5266de33d4c3420973cf9ae3b98b54a2a6d53a559310e3236c4b2b06b9c07d4e", | ||||
|                 "sha256:5521a06a3148686d9269c53b09f7d399a5725c47bbb5b35747e1cb76326b714b", | ||||
|                 "sha256:596140185c7fa113563c67c2e894eabe0daea18cf8e33851738c19f70ce86aeb", | ||||
|                 "sha256:5b732c8beef1d7bc2d9e476dbba20aaff6167bf205ad9aa8d30913859e82884b", | ||||
|                 "sha256:5ebeb7ef54a7be11044c33a17b2624abe4307a75893c001a4800857956b41094", | ||||
|                 "sha256:712a64103d97c404e87d4d7c47fb0c7ff9acccc625ca2002848e0d53288b90ea", | ||||
|                 "sha256:7678556eeb0152cbd1522b684dcd215250885993dd00adb93679ec3c0e6e091c", | ||||
|                 "sha256:77974aba6c1bc26e3c205c2214f0d5b4305bdc719268b93e768ddb17e3fdd636", | ||||
|                 "sha256:783145835458e60fa97afac25d511d00a1eca94d4a8f3ace9fe2043003c678e4", | ||||
|                 "sha256:7bfdb06b395385ea9b91bf55c1adf1b297c9fdb531552845ff1d3ea6e40d5aba", | ||||
|                 "sha256:7c8dde0ca2f77828815fd1aedfdf52e59071a5bae30dac3b4da2a335c672149a", | ||||
|                 "sha256:83807d445817326b4bcdaaaf8e8e9f1753da04341eceec705c001ff342002e5d", | ||||
|                 "sha256:87eed225fd415bbae787f93a457af7f5990b92a334e346f72070bf569b9c9c95", | ||||
|                 "sha256:8fb62fe3d206d72fe1cfe31c4a1106ad2b136fcc1606093aeab314f02930fdf2", | ||||
|                 "sha256:95172a21038c9b423e68be78fd0be6e1b97674cde269b76fe269a5dfa6fadf0b", | ||||
|                 "sha256:9f48ba6f6c13e5e49f3d3efb1b51c8193215c42ac82610a04624906a9270be6f", | ||||
|                 "sha256:a0c03b6be48aaf92525cccf393265e02773be8fd9551a2f9adbe7db1fa2b60f1", | ||||
|                 "sha256:a5ae282abe60a2db0fd407072aff4599c279bcd6e9a2475500fc35b00a57c532", | ||||
|                 "sha256:aee2512827ceb6d7f517c8b85aa5d3923afe8fc7a57d028cffcd522f1c6fd082", | ||||
|                 "sha256:c8b0451d2ec95010d1db8ca733afc41f659f425b7f608af569711097fd6014e2", | ||||
|                 "sha256:c9aa4496fd0e17e3843399f533d62857cef5900facf93e735ef65aa4bbc90ef0", | ||||
|                 "sha256:cbc6472e01952d3d1b2772b720428f8b90e2deea8344e854df22b0618e9cce71", | ||||
|                 "sha256:cdfe0c22692a30cd830c0755746473ae66c4a8f2e7bd508b35fb3b6a0813d787", | ||||
|                 "sha256:cf802eef1f0134afb81fef94020351be4fe1d6681aadf9c5e862af6602af64ef", | ||||
|                 "sha256:d42f9c36d06440e34226e8bd65ff065ca0963aeecada587b937011efa02cdc9d", | ||||
|                 "sha256:d5b47c440210c5d1d67e1cf434124e0b5c395eee1f5806fdd89b553ed1acd0a3", | ||||
|                 "sha256:d9b4a8148c57ecac25a16b0e11798cbe88edf5237b0df99973687dd866f05e1b", | ||||
|                 "sha256:daf43a3d1ea699402c5a850e5313680ac355b4adc9770cd5cfc2940e7861f1bf", | ||||
|                 "sha256:dbdc15f0c81611925f382dfa97b3bd0bc2c1ce19d4fe50482cb0ddc12ba30020", | ||||
|                 "sha256:deaa09cd492e24fd9b15296844c0ad1b3c976da7907e1c1ed3a0ad21dded6f76", | ||||
|                 "sha256:e37242f5324ffd9f7ba5acf96d774f9276aa62a966c0bad8dae692deebec7716", | ||||
|                 "sha256:ed2cf9ed4e8ebc3b754d398cba12f24359f018b416c380f577bbae112ca52fc9", | ||||
|                 "sha256:f2712c5179f40af9ddc8f6727f2bd910ea0eb50206daea75f58ddd9fa3f715bb", | ||||
|                 "sha256:f4ca91d61a4bf61b0f2228f24bbfa6a9facd5f8af03759fe2a655c50ae2c6610", | ||||
|                 "sha256:f6b3dfc7661f8842babd8ea07e9897fe3d9b69a1d7e5fbb743e4160f9387833b" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "markers": "python_version >= '3.10'", | ||||
|             "version": "==2.2.2" | ||||
|             "version": "==2.2.3" | ||||
|         }, | ||||
|         "packaging": { | ||||
|             "hashes": [ | ||||
| @@ -693,6 +803,14 @@ | ||||
|             "markers": "python_version >= '3.8'", | ||||
|             "version": "==24.2" | ||||
|         }, | ||||
|         "paypalrestsdk": { | ||||
|             "hashes": [ | ||||
|                 "sha256:a3f51616ee8f6d975a5a5a8c2049db63653c843479c8fdd71c9d588a31e14560", | ||||
|                 "sha256:dac236492a9ac1260a760014a2e56ab38b09d8143295b5e896545359b61fedd6" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==1.13.3" | ||||
|         }, | ||||
|         "postgrest": { | ||||
|             "hashes": [ | ||||
|                 "sha256:03a7e638962454d10bb712c35e63a8a4bc452917917a4e9eb7427bd5b3c6c485", | ||||
| @@ -798,6 +916,14 @@ | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==2.9.0" | ||||
|         }, | ||||
|         "pycparser": { | ||||
|             "hashes": [ | ||||
|                 "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", | ||||
|                 "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.8'", | ||||
|             "version": "==2.22" | ||||
|         }, | ||||
|         "pydantic": { | ||||
|             "hashes": [ | ||||
|                 "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", | ||||
| @@ -930,6 +1056,14 @@ | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==4.0.0" | ||||
|         }, | ||||
|         "pyopenssl": { | ||||
|             "hashes": [ | ||||
|                 "sha256:424c247065e46e76a37411b9ab1782541c23bb658bf003772c3405fbaa128e90", | ||||
|                 "sha256:cd2cef799efa3936bb08e8ccb9433a575722b9dd986023f1cabc4ae64e9dac16" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==25.0.0" | ||||
|         }, | ||||
|         "python-dateutil": { | ||||
|             "hashes": [ | ||||
|                 "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", | ||||
| @@ -1075,50 +1209,56 @@ | ||||
|         }, | ||||
|         "scipy": { | ||||
|             "hashes": [ | ||||
|                 "sha256:033a75ddad1463970c96a88063a1df87ccfddd526437136b6ee81ff0312ebdf6", | ||||
|                 "sha256:0458839c9f873062db69a03de9a9765ae2e694352c76a16be44f93ea45c28d2b", | ||||
|                 "sha256:070d10654f0cb6abd295bc96c12656f948e623ec5f9a4eab0ddb1466c000716e", | ||||
|                 "sha256:09c52320c42d7f5c7748b69e9f0389266fd4f82cf34c38485c14ee976cb8cb04", | ||||
|                 "sha256:0ac102ce99934b162914b1e4a6b94ca7da0f4058b6d6fd65b0cef330c0f3346f", | ||||
|                 "sha256:0fb57b30f0017d4afa5fe5f5b150b8f807618819287c21cbe51130de7ccdaed2", | ||||
|                 "sha256:100193bb72fbff37dbd0bf14322314fc7cbe08b7ff3137f11a34d06dc0ee6b85", | ||||
|                 "sha256:14eaa373c89eaf553be73c3affb11ec6c37493b7eaaf31cf9ac5dffae700c2e0", | ||||
|                 "sha256:2114a08daec64980e4b4cbdf5bee90935af66d750146b1d2feb0d3ac30613692", | ||||
|                 "sha256:21e10b1dd56ce92fba3e786007322542361984f8463c6d37f6f25935a5a6ef52", | ||||
|                 "sha256:2722a021a7929d21168830790202a75dbb20b468a8133c74a2c0230c72626b6c", | ||||
|                 "sha256:395be70220d1189756068b3173853029a013d8c8dd5fd3d1361d505b2aa58fa7", | ||||
|                 "sha256:3fe1d95944f9cf6ba77aa28b82dd6bb2a5b52f2026beb39ecf05304b8392864b", | ||||
|                 "sha256:491d57fe89927fa1aafbe260f4cfa5ffa20ab9f1435025045a5315006a91b8f5", | ||||
|                 "sha256:4b17d4220df99bacb63065c76b0d1126d82bbf00167d1730019d2a30d6ae01ea", | ||||
|                 "sha256:4c9d8fc81d6a3b6844235e6fd175ee1d4c060163905a2becce8e74cb0d7554ce", | ||||
|                 "sha256:55cc79ce4085c702ac31e49b1e69b27ef41111f22beafb9b49fea67142b696c4", | ||||
|                 "sha256:5b190b935e7db569960b48840e5bef71dc513314cc4e79a1b7d14664f57fd4ff", | ||||
|                 "sha256:5bd8d27d44e2c13d0c1124e6a556454f52cd3f704742985f6b09e75e163d20d2", | ||||
|                 "sha256:5dff14e75cdbcf07cdaa1c7707db6017d130f0af9ac41f6ce443a93318d6c6e0", | ||||
|                 "sha256:5eb0ca35d4b08e95da99a9f9c400dc9f6c21c424298a0ba876fdc69c7afacedf", | ||||
|                 "sha256:63b9b6cd0333d0eb1a49de6f834e8aeaefe438df8f6372352084535ad095219e", | ||||
|                 "sha256:667f950bf8b7c3a23b4199db24cb9bf7512e27e86d0e3813f015b74ec2c6e3df", | ||||
|                 "sha256:6b3e71893c6687fc5e29208d518900c24ea372a862854c9888368c0b267387ab", | ||||
|                 "sha256:71ba9a76c2390eca6e359be81a3e879614af3a71dfdabb96d1d7ab33da6f2364", | ||||
|                 "sha256:74bb864ff7640dea310a1377d8567dc2cb7599c26a79ca852fc184cc851954ac", | ||||
|                 "sha256:82add84e8a9fb12af5c2c1a3a3f1cb51849d27a580cb9e6bd66226195142be6e", | ||||
|                 "sha256:837299eec3d19b7e042923448d17d95a86e43941104d33f00da7e31a0f715d3c", | ||||
|                 "sha256:900f3fa3db87257510f011c292a5779eb627043dd89731b9c461cd16ef76ab3d", | ||||
|                 "sha256:9f151e9fb60fbf8e52426132f473221a49362091ce7a5e72f8aa41f8e0da4f25", | ||||
|                 "sha256:af0b61c1de46d0565b4b39c6417373304c1d4f5220004058bdad3061c9fa8a95", | ||||
|                 "sha256:bc7136626261ac1ed988dca56cfc4ab5180f75e0ee52e58f1e6aa74b5f3eacd5", | ||||
|                 "sha256:be3deeb32844c27599347faa077b359584ba96664c5c79d71a354b80a0ad0ce0", | ||||
|                 "sha256:c09aa9d90f3500ea4c9b393ee96f96b0ccb27f2f350d09a47f533293c78ea776", | ||||
|                 "sha256:c352c1b6d7cac452534517e022f8f7b8d139cd9f27e6fbd9f3cbd0bfd39f5bef", | ||||
|                 "sha256:c64ded12dcab08afff9e805a67ff4480f5e69993310e093434b10e85dc9d43e1", | ||||
|                 "sha256:cdde8414154054763b42b74fe8ce89d7f3d17a7ac5dd77204f0e142cdc9239e9", | ||||
|                 "sha256:ce3a000cd28b4430426db2ca44d96636f701ed12e2b3ca1f2b1dd7abdd84b39a", | ||||
|                 "sha256:f735bc41bd1c792c96bc426dece66c8723283695f02df61dcc4d0a707a42fc54", | ||||
|                 "sha256:f82fcf4e5b377f819542fbc8541f7b5fbcf1c0017d0df0bc22c781bf60abc4d8" | ||||
|                 "sha256:01edfac9f0798ad6b46d9c4c9ca0e0ad23dbf0b1eb70e96adb9fa7f525eff0bf", | ||||
|                 "sha256:03205d57a28e18dfd39f0377d5002725bf1f19a46f444108c29bdb246b6c8a11", | ||||
|                 "sha256:08b57a9336b8e79b305a143c3655cc5bdbe6d5ece3378578888d2afbb51c4e37", | ||||
|                 "sha256:11e7ad32cf184b74380f43d3c0a706f49358b904fa7d5345f16ddf993609184d", | ||||
|                 "sha256:28a0d2c2075946346e4408b211240764759e0fabaeb08d871639b5f3b1aca8a0", | ||||
|                 "sha256:2b871df1fe1a3ba85d90e22742b93584f8d2b8e6124f8372ab15c71b73e428b8", | ||||
|                 "sha256:302093e7dfb120e55515936cb55618ee0b895f8bcaf18ff81eca086c17bd80af", | ||||
|                 "sha256:42dabaaa798e987c425ed76062794e93a243be8f0f20fff6e7a89f4d61cb3d40", | ||||
|                 "sha256:447ce30cee6a9d5d1379087c9e474628dab3db4a67484be1b7dc3196bfb2fac9", | ||||
|                 "sha256:4c6676490ad76d1c2894d77f976144b41bd1a4052107902238047fb6a473e971", | ||||
|                 "sha256:54c462098484e7466362a9f1672d20888f724911a74c22ae35b61f9c5919183d", | ||||
|                 "sha256:597a0c7008b21c035831c39927406c6181bcf8f60a73f36219b69d010aa04737", | ||||
|                 "sha256:5a6fd6eac1ce74a9f77a7fc724080d507c5812d61e72bd5e4c489b042455865e", | ||||
|                 "sha256:5ea7ed46d437fc52350b028b1d44e002646e28f3e8ddc714011aaf87330f2f32", | ||||
|                 "sha256:601881dfb761311045b03114c5fe718a12634e5608c3b403737ae463c9885d53", | ||||
|                 "sha256:62ca1ff3eb513e09ed17a5736929429189adf16d2d740f44e53270cc800ecff1", | ||||
|                 "sha256:69ea6e56d00977f355c0f84eba69877b6df084516c602d93a33812aa04d90a3d", | ||||
|                 "sha256:6a8e34cf4c188b6dd004654f88586d78f95639e48a25dfae9c5e34a6dc34547e", | ||||
|                 "sha256:6d0194c37037707b2afa7a2f2a924cf7bac3dc292d51b6a925e5fcb89bc5c776", | ||||
|                 "sha256:6f223753c6ea76983af380787611ae1291e3ceb23917393079dcc746ba60cfb5", | ||||
|                 "sha256:6f5e296ec63c5da6ba6fa0343ea73fd51b8b3e1a300b0a8cae3ed4b1122c7462", | ||||
|                 "sha256:7cd5b77413e1855351cdde594eca99c1f4a588c2d63711388b6a1f1c01f62274", | ||||
|                 "sha256:869269b767d5ee7ea6991ed7e22b3ca1f22de73ab9a49c44bad338b725603301", | ||||
|                 "sha256:87994da02e73549dfecaed9e09a4f9d58a045a053865679aeb8d6d43747d4df3", | ||||
|                 "sha256:888307125ea0c4466287191e5606a2c910963405ce9671448ff9c81c53f85f58", | ||||
|                 "sha256:92233b2df6938147be6fa8824b8136f29a18f016ecde986666be5f4d686a91a4", | ||||
|                 "sha256:9412f5e408b397ff5641080ed1e798623dbe1ec0d78e72c9eca8992976fa65aa", | ||||
|                 "sha256:9b18aa747da280664642997e65aab1dd19d0c3d17068a04b3fe34e2559196cb9", | ||||
|                 "sha256:9de9d1416b3d9e7df9923ab23cd2fe714244af10b763975bea9e4f2e81cebd27", | ||||
|                 "sha256:a2ec871edaa863e8213ea5df811cd600734f6400b4af272e1c011e69401218e9", | ||||
|                 "sha256:a5080a79dfb9b78b768cebf3c9dcbc7b665c5875793569f48bf0e2b1d7f68f6f", | ||||
|                 "sha256:a8bf5cb4a25046ac61d38f8d3c3426ec11ebc350246a4642f2f315fe95bda655", | ||||
|                 "sha256:b09ae80010f52efddb15551025f9016c910296cf70adbf03ce2a8704f3a5ad20", | ||||
|                 "sha256:b5e025e903b4f166ea03b109bb241355b9c42c279ea694d8864d033727205e65", | ||||
|                 "sha256:bad78d580270a4d32470563ea86c6590b465cb98f83d760ff5b0990cb5518a93", | ||||
|                 "sha256:bae43364d600fdc3ac327db99659dcb79e6e7ecd279a75fe1266669d9a652828", | ||||
|                 "sha256:c4697a10da8f8765bb7c83e24a470da5797e37041edfd77fd95ba3811a47c4fd", | ||||
|                 "sha256:c90ebe8aaa4397eaefa8455a8182b164a6cc1d59ad53f79943f266d99f68687f", | ||||
|                 "sha256:cd58a314d92838f7e6f755c8a2167ead4f27e1fd5c1251fd54289569ef3495ec", | ||||
|                 "sha256:cf72ff559a53a6a6d77bd8eefd12a17995ffa44ad86c77a5df96f533d4e6c6bb", | ||||
|                 "sha256:def751dd08243934c884a3221156d63e15234a3155cf25978b0a668409d45eb6", | ||||
|                 "sha256:e7c68b6a43259ba0aab737237876e5c2c549a031ddb7abc28c7b47f22e202ded", | ||||
|                 "sha256:ecf797d2d798cf7c838c6d98321061eb3e72a74710e6c40540f0e8087e3b499e", | ||||
|                 "sha256:f031846580d9acccd0044efd1a90e6f4df3a6e12b4b6bd694a7bc03a89892b28", | ||||
|                 "sha256:fb530e4794fc8ea76a4a21ccb67dea33e5e0e60f07fc38a49e821e1eae3b71a0", | ||||
|                 "sha256:fe8a9eb875d430d81755472c5ba75e84acc980e4a8f6204d402849234d3017db" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "markers": "python_version >= '3.10'", | ||||
|             "version": "==1.15.1" | ||||
|             "version": "==1.15.2" | ||||
|         }, | ||||
|         "shapely": { | ||||
|             "hashes": [ | ||||
|   | ||||
| @@ -328,7 +328,7 @@ div.media { | ||||
|   </head> | ||||
|   <body> | ||||
|     <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> | ||||
|     <div id="environment-header"> | ||||
|       <h2>Environment</h2> | ||||
| @@ -382,7 +382,7 @@ div.media { | ||||
|         <h2>Summary</h2> | ||||
|         <div class="additional-summary prefix"> | ||||
|         </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> | ||||
|         <div class="summary__reload"> | ||||
|           <div class="summary__reload__button hidden" onclick="location.reload()"> | ||||
| @@ -432,7 +432,7 @@ div.media { | ||||
|     </table> | ||||
|   </body> | ||||
|   <footer> | ||||
|     <div id="data-container" data-jsonblob="{"environment": {"Python": "3.12.3", "Platform": "Linux-6.8.0-53-generic-x86_64-with-glibc2.39", "Packages": {"pytest": "8.3.4", "pluggy": "1.5.0"}, "Plugins": {"html": "4.1.1", "anyio": "4.8.0", "metadata": "3.1.1"}}, "tests": {"src/tests/test_user.py::test_user_handling": [{"extras": [], "result": "Passed", "testId": "src/tests/test_user.py::test_user_handling", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_user.py::test_user_handling</td>", "<td>N/A</td>", "<td>N/A</td>", "<td>N/A</td>", "<td class=\"col-duration\">415 ms</td>", "<td class=\"col-links\"></td>"], "log": "------------------------------ 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"}]}, "renderCollapsed": ["passed"], "initialSort": "result", "title": "Backend Testing Report"}"></div> | ||||
|     <div id="data-container" data-jsonblob="{"environment": {"Python": "3.12.3", "Platform": "Linux-6.8.0-53-generic-x86_64-with-glibc2.39", "Packages": {"pytest": "8.3.4", "pluggy": "1.5.0"}, "Plugins": {"html": "4.1.1", "anyio": "4.8.0", "metadata": "3.1.1"}}, "tests": {"src/tests/test_user.py::test_user_handling": [{"extras": [], "result": "Passed", "testId": "src/tests/test_user.py::test_user_handling", "resultsTableRow": ["<td class=\"col-result\">Passed</td>", "<td class=\"col-testId\">src/tests/test_user.py::test_user_handling</td>", "<td>N/A</td>", "<td>N/A</td>", "<td>N/A</td>", "<td class=\"col-duration\">524 ms</td>", "<td class=\"col-links\"></td>"], "log": "------------------------------ 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"}]}, "renderCollapsed": ["passed"], "initialSort": "result", "title": "Backend Testing Report"}"></div> | ||||
|     <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){ | ||||
| const { getCollapsedCategory, setCollapsedIds } = require('./storage.js') | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| """Main app for backend api""" | ||||
|  | ||||
| import logging | ||||
| import traceback | ||||
| import time | ||||
| from contextlib import asynccontextmanager | ||||
| 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.linked_landmarks import LinkedLandmarks | ||||
| from .structs.trip import Trip | ||||
| from .structs.requests import UserDeleteRequest | ||||
| from .utils.landmarks_manager import LandmarkManager | ||||
| from .utils.toilets_manager import ToiletsManager | ||||
| from .optimization.optimizer import Optimizer | ||||
| from .optimization.refiner import Refiner | ||||
| from .overpass.overpass import fill_cache | ||||
| from .cache import client as cache_client | ||||
| # from .payments.payment_routes import router as payment_router | ||||
| 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__) | ||||
| @@ -42,8 +41,9 @@ async def lifespan(app: FastAPI): | ||||
| app = FastAPI(lifespan=lifespan) | ||||
|  | ||||
|  | ||||
| # Include the payment routes | ||||
| # app.include_router(payment_router, prefix="/payments") | ||||
| # Include the payment routes and supabase routes | ||||
| app.include_router(payment_router) | ||||
| app.include_router(supabase_router) | ||||
|  | ||||
|  | ||||
| @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 | ||||
|  | ||||
|  | ||||
| @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") | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										0
									
								
								backend/src/payments/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								backend/src/payments/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										70
									
								
								backend/src/payments/payment_handler.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								backend/src/payments/payment_handler.py
									
									
									
									
									
										Normal 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") | ||||
| @@ -1,49 +1,79 @@ | ||||
| from os import getenv | ||||
| from fastapi import APIRouter, HTTPException | ||||
| from .paypal import create_paypal_order, capture_paypal_order | ||||
| from supabase import create_client, Client | ||||
| import logging | ||||
| import paypalrestsdk | ||||
| from fastapi import HTTPException, APIRouter | ||||
|  | ||||
| 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 | ||||
| supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY) | ||||
|  | ||||
|  | ||||
| # Define router | ||||
| # Define the API router | ||||
| 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/") | ||||
| def create_payment(amount: float, currency: str = "USD"): | ||||
|     """ | ||||
|     Create a PayPal payment and return approval URL. | ||||
|     """ | ||||
|     try: | ||||
|         payment = create_paypal_order(amount, currency) | ||||
|         return {"approval_url": payment["approval_url"]} | ||||
|     except Exception as e: | ||||
|         raise HTTPException(status_code=500, detail=str(e)) | ||||
|     # Create PayPal payment and get the approval URL | ||||
|     approval_url = payment_handler.create_paypal_payment() | ||||
|  | ||||
|     return { | ||||
|         "message": "Purchase initiated successfully", | ||||
|         "payment_id": payment_handler.payment_id, | ||||
|         "credits": payment_request.credit_amount, | ||||
|         "approval_url": approval_url, | ||||
|     } | ||||
|  | ||||
|  | ||||
| @router.post("/capture-paypal-payment/") | ||||
| def capture_payment(order_id: str, user_id: str, country: str): | ||||
| @router.get("/payment/success") | ||||
| def payment_success(paymentId: str, PayerID: str): | ||||
|     """ | ||||
|     Capture the PayPal payment and unlock the country in Supabase. | ||||
|     Handles successful PayPal payment. | ||||
|     """ | ||||
|     try: | ||||
|         # Capture payment | ||||
|         capture_response = capture_paypal_order(order_id) | ||||
|         if capture_response.get("status") == "COMPLETED": | ||||
|             # Update Supabase to unlock the country for the user | ||||
|             supabase.table("unlocked_countries").insert({ | ||||
|                 "user_id": user_id, | ||||
|                 "country": country, | ||||
|                 "paid": True, | ||||
|             }).execute() | ||||
|     payment = paypalrestsdk.Payment.find(paymentId) | ||||
|  | ||||
|     if payment.execute({"payer_id": PayerID}): | ||||
|         logger.info("Payment executed successfully") | ||||
|  | ||||
|         # Retrieve transaction details from the database | ||||
|         result = supabase.table("pending_payments").select("*").eq("payment_id", paymentId).single().execute() | ||||
|         if not result.data: | ||||
|             raise HTTPException(status_code=404, detail="Transaction not found") | ||||
|  | ||||
|         # 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)) | ||||
|   | ||||
| @@ -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() | ||||
| @@ -75,9 +75,8 @@ class Supabase: | ||||
|         self.logger.warning(f'Insufficient balance for user {user_id}. Trip generation cannot proceed.') | ||||
|         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. | ||||
|  | ||||
| @@ -106,7 +105,7 @@ class Supabase: | ||||
|  | ||||
|  | ||||
|         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_response = ( | ||||
| @@ -124,7 +123,7 @@ class Supabase: | ||||
|             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. | ||||
|  | ||||
| @@ -153,7 +152,7 @@ class Supabase: | ||||
|  | ||||
|  | ||||
|         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_response = ( | ||||
|   | ||||
							
								
								
									
										52
									
								
								backend/src/payments/supabase_routes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								backend/src/payments/supabase_routes.py
									
									
									
									
									
										Normal 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") | ||||
| @@ -1,4 +0,0 @@ | ||||
| from pydantic import BaseModel | ||||
|  | ||||
| class UserDeleteRequest(BaseModel): | ||||
|     user_id: str | ||||
		Reference in New Issue
	
	Block a user