Skip to content

Commit fe0bc28

Browse files
Feat raid different prices (#754)
### Description Goes hand to hand with : aeecleclair/raid-registering#58 ### Checklist - [ ] Created tests which fail without the change (if possible) - [ ] All tests passing - [ ] Extended the documentation, if necessary --------- Co-authored-by: Armand Didierjean <[email protected]>
1 parent 2cb6f09 commit fe0bc28

File tree

5 files changed

+117
-58
lines changed

5 files changed

+117
-58
lines changed

app/modules/raid/coredata_raid.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ class RaidDriveFolders(core_data.BaseCoreData):
2727
class RaidPrice(core_data.BaseCoreData):
2828
student_price: int | None = None
2929
partner_price: int | None = None
30+
external_price: int | None = None
3031
t_shirt_price: int | None = None

app/modules/raid/endpoints_raid.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,24 +1106,44 @@ async def get_payment_url(
11061106
raise MissingHelloAssoSlugError("HELLOASSO_SLUG")
11071107

11081108
raid_prices = await get_core_data(coredata_raid.RaidPrice, db)
1109-
if not raid_prices.student_price or not raid_prices.t_shirt_price:
1109+
if (
1110+
not raid_prices.student_price
1111+
or not raid_prices.t_shirt_price
1112+
or not raid_prices.external_price
1113+
):
11101114
raise HTTPException(status_code=404, detail="Prices not set.")
1115+
11111116
price = 0
11121117
checkout_name = ""
11131118
participant = await cruds_raid.get_participant_by_id(user.id, db)
1114-
if participant:
1115-
if not participant.payment:
1116-
price += raid_prices.student_price
1117-
checkout_name += "Inscription Raid"
1119+
if not participant:
1120+
raise HTTPException(status_code=404, detail="Participant not found.")
1121+
1122+
if participant.validation_progress != 100:
1123+
raise HTTPException(
1124+
status_code=400,
1125+
detail="You must complete your registration before paying.",
1126+
)
1127+
1128+
if not participant.payment:
11181129
if (
1119-
participant.t_shirt_size
1120-
and participant.t_shirt_size != Size.None_
1121-
and not participant.t_shirt_payment
1130+
participant.student_card is not None
1131+
and participant.student_card.validation == DocumentValidation.accepted
11221132
):
1123-
price += raid_prices.t_shirt_price
1124-
if not participant.payment:
1125-
checkout_name += " + "
1126-
checkout_name += "T Shirt taille" + participant.t_shirt_size.value
1133+
price += raid_prices.student_price
1134+
checkout_name = "Inscription Raid - Tarif étudiant"
1135+
else:
1136+
price += raid_prices.external_price
1137+
checkout_name = "Inscription Raid - Tarif externe"
1138+
if (
1139+
participant.t_shirt_size
1140+
and participant.t_shirt_size != Size.None_
1141+
and not participant.t_shirt_payment
1142+
):
1143+
price += raid_prices.t_shirt_price
1144+
if not participant.payment:
1145+
checkout_name += " + "
1146+
checkout_name += "T Shirt taille" + participant.t_shirt_size.value
11271147
user_dict = user.__dict__
11281148
user_dict.pop("school", None)
11291149
checkout = await payment_tool.init_checkout(

app/modules/raid/models_raid.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ def validation_progress(self) -> float:
201201
self.t_shirt_size,
202202
self.situation,
203203
self.attestation_on_honour,
204-
self.payment,
205204
]
206205
number_validated: float = sum(
207206
[condition is not None for condition in conditions],

tests/commons.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
from app.core.utils import security
2020
from app.core.utils.config import Settings
2121
from app.dependencies import get_settings
22+
from app.types import core_data
2223
from app.types.exceptions import RedisConnectionError
2324
from app.types.floors_type import FloorsType
2425
from app.types.scheduler import OfflineScheduler, Scheduler
2526
from app.types.sqlalchemy import Base
2627
from app.utils.redis import connect, disconnect
2728
from app.utils.tools import (
2829
get_random_string,
30+
set_core_data,
2931
)
3032

3133

@@ -224,6 +226,23 @@ async def add_object_to_db(db_object: Base) -> None:
224226
await db.close()
225227

226228

229+
async def add_coredata_to_db(
230+
core_data: core_data.BaseCoreData,
231+
) -> None:
232+
"""
233+
Add a CoreData object
234+
"""
235+
async with TestingSessionLocal() as db:
236+
try:
237+
await set_core_data(core_data, db=db)
238+
await db.commit()
239+
except Exception as error:
240+
await db.rollback()
241+
raise FailedToAddObjectToDB from error
242+
finally:
243+
await db.close()
244+
245+
227246
class MockedPaymentTool:
228247
original_payment_tool: PaymentTool
229248

tests/test_raid.py

Lines changed: 65 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import pytest_asyncio
99
from fastapi.testclient import TestClient
1010
from PIL import Image
11+
from pytest_mock import MockerFixture
1112

1213
from app.core.groups.groups_type import GroupType
1314
from app.core.users import models_users
@@ -26,6 +27,7 @@
2627
maximize_image,
2728
)
2829
from tests.commons import (
30+
add_coredata_to_db,
2931
add_object_to_db,
3032
create_api_access_token,
3133
create_user_with_groups,
@@ -207,6 +209,14 @@ async def init_objects() -> None:
207209
"data/raid/" + path,
208210
)
209211

212+
await add_coredata_to_db(
213+
coredata_raid.RaidPrice(
214+
student_price=50,
215+
t_shirt_price=15,
216+
external_price=90,
217+
),
218+
)
219+
210220

211221
def test_get_participant_by_id(client: TestClient):
212222
response = client.get(
@@ -638,7 +648,7 @@ def test_get_raid_price(client: TestClient):
638648

639649

640650
def test_update_raid_price(client: TestClient):
641-
price_data = {"student_price": 50, "t_shirt_price": 15}
651+
price_data = {"student_price": 50, "t_shirt_price": 15, "external_price": 90}
642652
response = client.patch(
643653
"/raid/price",
644654
json=price_data,
@@ -664,40 +674,38 @@ def test_delete_team(client: TestClient):
664674
assert response.status_code == 204
665675

666676

667-
async def test_get_payment_url_no_participant(client: TestClient, mocker):
677+
async def test_get_payment_url_no_participant(
678+
client: TestClient,
679+
mocker: MockerFixture,
680+
):
668681
# Mock the necessary dependencies
669682
mocker.patch("app.modules.raid.cruds_raid.get_participant_by_id", return_value=None)
670-
mocker.patch(
671-
"app.utils.tools.get_core_data",
672-
return_value=coredata_raid.RaidPrice(student_price=50, t_shirt_price=15),
673-
)
674683

675684
mocker.patch("app.modules.raid.cruds_raid.create_participant_checkout")
676685

677686
response = client.get(
678687
"/raid/pay",
679688
headers={"Authorization": f"Bearer {token_simple}"},
680689
)
681-
assert response.status_code == 201
682-
assert "url" in response.json()
683-
assert response.json()["url"] == "https://some.url.fr/checkout"
690+
assert response.status_code == 404
691+
assert response.json()["detail"] == "Participant not found."
684692

685693

686-
async def test_get_payment_url_participant_no_payment(client: TestClient, mocker):
687-
# Mock the necessary dependencies
694+
async def test_get_payment_url_participant_no_payment(
695+
client: TestClient,
696+
mocker: MockerFixture,
697+
):
698+
# Mock the necessary dependencies test_get_payment_url_participant_already_paid
688699
mocker.patch(
689700
"app.modules.raid.cruds_raid.get_participant_by_id",
690701
return_value=Mock(
691702
payment=False,
692703
t_shirt_size=None,
693704
t_shirt_payment=False,
694705
id=str(uuid.uuid4()),
706+
validation_progress=100,
695707
),
696708
)
697-
mocker.patch(
698-
"app.utils.tools.get_core_data",
699-
return_value=coredata_raid.RaidPrice(student_price=50, t_shirt_price=15),
700-
)
701709

702710
mocker.patch("app.modules.raid.cruds_raid.create_participant_checkout")
703711

@@ -710,7 +718,10 @@ async def test_get_payment_url_participant_no_payment(client: TestClient, mocker
710718
assert response.json()["url"] == "https://some.url.fr/checkout"
711719

712720

713-
async def test_get_payment_url_participant_with_tshirt(client: TestClient, mocker):
721+
async def test_get_payment_url_participant_with_tshirt(
722+
client: TestClient,
723+
mocker: MockerFixture,
724+
):
714725
# Mock the necessary dependencies
715726
mocker.patch(
716727
"app.modules.raid.cruds_raid.get_participant_by_id",
@@ -719,12 +730,10 @@ async def test_get_payment_url_participant_with_tshirt(client: TestClient, mocke
719730
t_shirt_size=Mock(value="L"),
720731
t_shirt_payment=False,
721732
id=str(uuid.uuid4()),
733+
validation_progress=100,
722734
),
723735
)
724-
mocker.patch(
725-
"app.utils.tools.get_core_data",
726-
return_value=coredata_raid.RaidPrice(student_price=50, t_shirt_price=15),
727-
)
736+
728737
mocker.patch(
729738
"app.core.payment.payment_tool.PaymentTool.init_checkout",
730739
return_value=Mock(
@@ -743,26 +752,32 @@ async def test_get_payment_url_participant_with_tshirt(client: TestClient, mocke
743752
assert response.json()["url"] == "https://some.url.fr/checkout"
744753

745754

746-
# async def test_get_payment_url_prices_not_set(client: TestClient, mocker):
747-
# # Mock the necessary dependencies
748-
# mocker.patch(
749-
# "app.utils.tools.get_core_data",
750-
# return_value=coredata_raid.RaidPrice(student_price=None, t_shirt_price=None),
751-
# )
752-
# mocker.patch(
753-
# "app.core.payment.payment_tool.PaymentTool.init_checkout",
754-
# return_value=Mock(id=str(uuid.uuid4()), payment_url="http://mock-url.com"),
755-
# )
755+
async def test_get_payment_url_prices_not_set(
756+
client: TestClient,
757+
mocker: MockerFixture,
758+
):
759+
# Mock the necessary dependencies
760+
mocker.patch(
761+
"app.modules.raid.endpoints_raid.get_core_data",
762+
return_value=coredata_raid.RaidPrice(student_price=None, t_shirt_price=None),
763+
)
764+
mocker.patch(
765+
"app.core.payment.payment_tool.PaymentTool.init_checkout",
766+
return_value=Mock(id=str(uuid.uuid4()), payment_url="http://mock-url.com"),
767+
)
756768

757-
# response = client.get(
758-
# "/raid/pay",
759-
# headers={"Authorization": f"Bearer {token_simple}"},
760-
# )
761-
# assert response.status_code == 404
762-
# assert response.json()["detail"] == "Prices not set."
769+
response = client.get(
770+
"/raid/pay",
771+
headers={"Authorization": f"Bearer {token_simple}"},
772+
)
773+
assert response.status_code == 404
774+
assert response.json()["detail"] == "Prices not set."
763775

764776

765-
async def test_get_payment_url_participant_already_paid(client: TestClient, mocker):
777+
async def test_get_payment_url_participant_already_paid(
778+
client: TestClient,
779+
mocker: MockerFixture,
780+
):
766781
# Mock the necessary dependencies
767782
mocker.patch(
768783
"app.modules.raid.cruds_raid.get_participant_by_id",
@@ -771,12 +786,9 @@ async def test_get_payment_url_participant_already_paid(client: TestClient, mock
771786
t_shirt_size=None,
772787
t_shirt_payment=True,
773788
id=str(uuid.uuid4()),
789+
validation_progress=100,
774790
),
775791
)
776-
mocker.patch(
777-
"app.utils.tools.get_core_data",
778-
return_value=coredata_raid.RaidPrice(student_price=50, t_shirt_price=15),
779-
)
780792

781793
mocker.patch("app.modules.raid.cruds_raid.create_participant_checkout")
782794

@@ -967,7 +979,9 @@ def test_html_pdf_writer_init():
967979
# assert result == f"data/raid/{mock_participant.id}.pdf"
968980

969981

970-
async def test_set_team_number_utility_empty_database(mocker):
982+
async def test_set_team_number_utility_empty_database(
983+
mocker: MockerFixture,
984+
):
971985
"""Test the set_team_number utility with an empty database (no existing teams)"""
972986
# Create mock objects
973987
mock_db = mocker.AsyncMock()
@@ -998,7 +1012,9 @@ async def test_set_team_number_utility_empty_database(mocker):
9981012
assert args[1].number == 101 # 100 (sports separator) + 1
9991013

10001014

1001-
async def test_set_team_number_utility_existing_teams(mocker):
1015+
async def test_set_team_number_utility_existing_teams(
1016+
mocker: MockerFixture,
1017+
):
10021018
"""Test the set_team_number utility with existing teams"""
10031019
# Create mock objects
10041020
mock_db = mocker.AsyncMock()
@@ -1029,7 +1045,9 @@ async def test_set_team_number_utility_existing_teams(mocker):
10291045
assert args[1].number == 221 # 220 + 1
10301046

10311047

1032-
async def test_set_team_number_utility_no_difficulty(mocker):
1048+
async def test_set_team_number_utility_no_difficulty(
1049+
mocker: MockerFixture,
1050+
):
10331051
"""Test the set_team_number utility with a team without difficulty"""
10341052
# Create mock objects
10351053
mock_db = mocker.AsyncMock()
@@ -1051,7 +1069,9 @@ async def test_set_team_number_utility_no_difficulty(mocker):
10511069
mock_update_team.assert_not_called()
10521070

10531071

1054-
async def test_set_team_number_utility_discovery_difficulty(mocker):
1072+
async def test_set_team_number_utility_discovery_difficulty(
1073+
mocker: MockerFixture,
1074+
):
10551075
"""Test the set_team_number utility with discovery difficulty"""
10561076
# Create mock objects
10571077
mock_db = mocker.AsyncMock()

0 commit comments

Comments
 (0)