Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e43ccfa
Back cdr : Endpoint to get total of validated payments
Bombefire Sep 9, 2026
c88b800
Adding the year of cdr as a param in the endpoint
Bombefire Sep 9, 2026
0831dfd
Lint and ruff format
Bombefire Sep 9, 2026
2eff11a
modified: app/modules/cdr/endpoints_cdr.py
Bombefire Sep 9, 2026
2d5c395
New changes on the endpoint to handle them more easily in Enceladus
Bombefire Sep 9, 2026
3f02d2e
Lint check
Bombefire Sep 9, 2026
587cca5
Resolving lint
Bombefire Sep 9, 2026
4fc6fd3
resolving mypy
Bombefire Sep 9, 2026
e6e161b
(Unnecessary schema)
Bombefire Sep 9, 2026
f394425
Renaming and adding description in cruds and endpoints
Bombefire Sep 9, 2026
a62e3db
mypy .
Bombefire Sep 9, 2026
cc24f74
Update app/modules/cdr/endpoints_cdr.py
Bombefire Sep 9, 2026
cbf2ce2
Update app/modules/cdr/endpoints_cdr.py
Bombefire Sep 9, 2026
20aa50d
Update app/modules/cdr/endpoints_cdr.py
Bombefire Sep 9, 2026
8248c11
Adding tests and fixes
Bombefire Sep 9, 2026
ea93711
Fix
Bombefire Sep 9, 2026
427b98d
lint
Bombefire Sep 9, 2026
3bb1a02
Why are we still here just to suffer ?
Bombefire Sep 9, 2026
edaea35
Fix
Bombefire Sep 9, 2026
2f3e3b1
Fix
Bombefire Sep 9, 2026
5cfb86c
....
Bombefire Sep 9, 2026
7e143f5
Seperating tests
Bombefire Sep 9, 2026
2799daa
...
Bombefire Sep 9, 2026
01af78a
Test complémentaire n°1
Bombefire Sep 9, 2026
7f037a7
Put it up the tests
Bombefire Sep 9, 2026
ef0fd51
Only one error left
Bombefire Sep 9, 2026
60d8cbb
Fix test
Bombefire Sep 9, 2026
b11fed6
Fix
Bombefire Sep 9, 2026
56351e3
Test
Bombefire Sep 9, 2026
7d1f771
Fix
Bombefire Sep 9, 2026
5a6921e
Finish
Bombefire Sep 9, 2026
344d61d
feat: More tests
Bombefire Sep 11, 2026
aeefa36
Schemas for total payment
Bombefire Sep 13, 2026
ea1a9a2
Stash
Bombefire Sep 13, 2026
019bb3c
Schemas for total payment
Bombefire Sep 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions app/modules/cdr/cruds_cdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,84 @@ async def delete_payment(
)


async def get_payment_total_by_seller(
db: AsyncSession,
cdr_year: int,
) -> schemas_cdr.TotalPaymentBySeller:
result = await db.execute(
select(
models_cdr.Seller.name,
func.sum(
models_cdr.ProductVariant.price * models_cdr.Purchase.quantity,
).label("total_amount"),
)
.join(
models_cdr.CdrProduct,
models_cdr.Seller.id == models_cdr.CdrProduct.seller_id,
)
.join(
models_cdr.ProductVariant,
models_cdr.ProductVariant.product_id == models_cdr.CdrProduct.id,
)
.join(
models_cdr.Purchase,
models_cdr.Purchase.product_variant_id == models_cdr.ProductVariant.id,
)
.where(
models_cdr.Purchase.validated,
models_cdr.ProductVariant.year == cdr_year,
)
.group_by(models_cdr.Seller.id),
)

return schemas_cdr.TotalPaymentBySeller(
total_amounts=[
schemas_cdr.TotalPaymentOfSeller(
total_amount=row.total_amount,
name=row.name,
)
for row in result.all()
],
)


async def get_payment_total_by_type(
db: AsyncSession,
cdr_year: int,
) -> list[schemas_cdr.PaymentBase]:
Comment thread
Bombefire marked this conversation as resolved.
result = await db.execute(
select(
models_cdr.Payment.payment_type,
func.sum(models_cdr.Payment.total).label("total"),
)
.where(models_cdr.Payment.year == cdr_year)
.group_by(models_cdr.Payment.payment_type),
)

return [
schemas_cdr.PaymentBase(
total=row.total,
payment_type=row.payment_type,
)
for row in result.all()
]


async def get_payment_total(
db: AsyncSession,
cdr_year: int,
) -> schemas_cdr.TotalPayment:

result = await db.execute(
select(
func.sum(models_cdr.Payment.total).label("total"),
).where(models_cdr.Payment.year == cdr_year),
)
Comment thread
Luhmos marked this conversation as resolved.
total = result.scalar()

return schemas_cdr.TotalPayment(total_amount=total if total is not None else 0)


def create_action(
db: AsyncSession,
action: models_cdr.CdrAction,
Expand Down
69 changes: 69 additions & 0 deletions app/modules/cdr/endpoints_cdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,75 @@ async def get_cdr_users_pending_validation(
]


@module.router.get(
"/cdr/stats/payment_total_by_seller/",
response_model=schemas_cdr.TotalPaymentBySeller,
status_code=200,
)
async def get_payment_total_by_seller(
db: AsyncSession = Depends(get_db),
user: models_users.CoreUser = Depends(
is_user_allowed_to([CdrPermissions.manage_cdr]),
),
cdr_year: coredata_cdr.CdrYear = Depends(get_current_cdr_year),
):
"""
Get the total of all payments made in the CDR for each seller.

**User must be a CDR Admin to use this endpoint**
"""
return await cruds_cdr.get_payment_total_by_seller(
db=db,
cdr_year=cdr_year.year,
)


@module.router.get(
"/cdr/stats/payment_total_per_type/",
response_model=list[schemas_cdr.PaymentBase],
status_code=200,
)
async def get_payment_total_per_type(
db: AsyncSession = Depends(get_db),
user: models_users.CoreUser = Depends(
is_user_allowed_to([CdrPermissions.manage_cdr]),
),
cdr_year: coredata_cdr.CdrYear = Depends(get_current_cdr_year),
):
"""
Get the total of all payments made in the CDR for each payment type.

**User must a CDR Admin to use this endpoint**
"""
return await cruds_cdr.get_payment_total_by_type(
db=db,
cdr_year=cdr_year.year,
)


@module.router.get(
"/cdr/stats/payment_total/",
response_model=schemas_cdr.TotalPayment,
status_code=200,
)
async def get_payment_total(
db: AsyncSession = Depends(get_db),
user: models_users.CoreUser = Depends(
is_user_allowed_to([CdrPermissions.manage_cdr]),
),
cdr_year: coredata_cdr.CdrYear = Depends(get_current_cdr_year),
):
"""
Get the total of all payments made in the CDR.

**User must a CDR Admin to use this endpoint**
"""
return await cruds_cdr.get_payment_total(
db=db,
cdr_year=cdr_year.year,
)


@module.router.get(
"/cdr/users/{user_id}/",
response_model=schemas_cdr.CdrUser,
Expand Down
13 changes: 13 additions & 0 deletions app/modules/cdr/schemas_cdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,16 @@ class BatchValidation(BaseModel):
user_emails: list[str]
product_variant_id: UUID
validated: bool


class TotalPaymentOfSeller(BaseModel):
name: str
total_amount: int


class TotalPaymentBySeller(BaseModel):
total_amounts: list[TotalPaymentOfSeller]


class TotalPayment(BaseModel):
total_amount: int
19 changes: 19 additions & 0 deletions tests/commons.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ class FailedToAddObjectToDB(Exception):
"""Exception raised when an object cannot be added to the database."""


class FailedToUpdateObjectInDB(Exception):
"""Exception raised when an object cannot be updated in the database."""


async def override_init_state(
app: FastAPI,
settings: Settings,
Expand Down Expand Up @@ -327,6 +331,21 @@ async def add_object_to_db(db_object: Base) -> None:
await db.close()


async def update_object_in_db(db_object: Base) -> None:
"""
Update an existing object in the database
"""
async with TestingSessionLocal() as db:
try:
await db.merge(db_object)
await db.commit()
except Exception as error:
await db.rollback()
raise FailedToUpdateObjectInDB from error
finally:
await db.close()


async def add_coredata_to_db(
core_data: core_data.BaseCoreData,
) -> None:
Expand Down
72 changes: 72 additions & 0 deletions tests/modules/cdr/test_cdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
create_user_with_groups,
get_TestingSessionLocal,
mocked_checkout_id,
update_object_in_db,
)

year = datetime.now(UTC).year
Expand Down Expand Up @@ -479,6 +480,77 @@ async def init_objects():
await add_object_to_db(ticket)


def test_get_payment_total_as_admin(client: TestClient):
response = client.get(
"/cdr/stats/payment_total/",
headers={"Authorization": f"Bearer {token_admin}"},
)
assert response.status_code == 200
assert response.json()["total_amount"] == 5000


def test_get_payment_total_as_user(client: TestClient):
response = client.get(
"/cdr/stats/payment_total/",
headers={"Authorization": f"Bearer {token_user}"},
)
assert response.status_code == 403


async def test_get_payment_total_by_seller_as_admin(client: TestClient):
response = client.get(
"/cdr/stats/payment_total_by_seller/",
headers={"Authorization": f"Bearer {token_admin}"},
)
assert response.status_code == 200
assert response.json() == {"total_amounts": []}

purchase.validated = True
await update_object_in_db(purchase)
response = client.get(
"/cdr/stats/payment_total_by_seller/",
headers={"Authorization": f"Bearer {token_admin}"},
)

data = response.json()
assert len(data["total_amounts"]) == 1
first_data = data["total_amounts"][0]
assert first_data["name"] == "BDE"
assert first_data["total_amount"] == 100

purchase.validated = False
await update_object_in_db(purchase)


def test_get_payment_total_by_seller_as_user(client: TestClient):
response = client.get(
"/cdr/stats/payment_total_by_seller/",
headers={"Authorization": f"Bearer {token_user}"},
)
assert response.status_code == 403


def test_get_payment_total_per_type_as_admin(client: TestClient):
response = client.get(
"/cdr/stats/payment_total_per_type/",
headers={"Authorization": f"Bearer {token_admin}"},
)
assert response.status_code == 200
data = response.json()
assert len(data) == 1
first_data = data[0]
assert first_data["payment_type"] == "cash"
assert first_data["total"] == 5000


def test_get_payment_total_per_type_as_user(client: TestClient):
response = client.get(
"/cdr/stats/payment_total_per_type/",
headers={"Authorization": f"Bearer {token_user}"},
)
assert response.status_code == 403


def test_get_all_cdr_users_seller(client: TestClient):
response = client.get(
"/cdr/users/",
Expand Down
Loading