diff --git a/app/modules/cdr/cruds_cdr.py b/app/modules/cdr/cruds_cdr.py index 4d0c33063b..404af870ea 100644 --- a/app/modules/cdr/cruds_cdr.py +++ b/app/modules/cdr/cruds_cdr.py @@ -1,7 +1,7 @@ from collections.abc import Sequence from uuid import UUID -from sqlalchemy import delete, select, update +from sqlalchemy import delete, func, select, update from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import noload, selectinload @@ -798,6 +798,67 @@ async def delete_payment( ) +async def get_payment_products_by_seller( + db: AsyncSession, + cdr_year: int, +) -> list[schemas_cdr.TotalPurchaseValidatedBySeller]: + 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 + and models_cdr.ProductVariant.year == cdr_year, + ) + .group_by(models_cdr.Seller.id), + ) + + return [ + schemas_cdr.TotalPurchaseValidatedBySeller( + total_validated=row.total_amount, + name=row.name, + ) + for row in result.all() + ] + + +async def get_total_payment_types( + db: AsyncSession, + cdr_year: int, +) -> list[schemas_cdr.PaymentBase]: + 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() + ] + + def create_action( db: AsyncSession, action: models_cdr.CdrAction, diff --git a/app/modules/cdr/endpoints_cdr.py b/app/modules/cdr/endpoints_cdr.py index d4af676047..4fa7a6d9a1 100644 --- a/app/modules/cdr/endpoints_cdr.py +++ b/app/modules/cdr/endpoints_cdr.py @@ -2623,6 +2623,62 @@ async def delete_curriculum_membership( ) +@module.router.get( + "/cdr/users/total_payments_by_seller/", + response_model=list[schemas_cdr.PaymentComplete], + status_code=200, +) +async def get_total_payments_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 payments done in the CDR by each seller. + + **User must a CDR Admin to use this endpoint** + """ + if not (await has_user_permission(user, CdrPermissions.manage_cdr, db)): + raise HTTPException( + status_code=403, + detail="You're not allowed to see this.", + ) + return await cruds_cdr.get_payment_products_by_seller( + db=db, + cdr_year=cdr_year.year, + ) + + +@module.router.get( + "/cdr/users/total_payments/", + response_model=list[schemas_cdr.TotalPurchaseValidatedBySeller], + status_code=200, +) +async def get_total_payments( + 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 payments done in the CDR. + + **User must a CDR Admin to use this endpoint** + """ + if not (await has_user_permission(user, CdrPermissions.manage_cdr, db)): + raise HTTPException( + status_code=403, + detail="You're not allowed to see this.", + ) + return await cruds_cdr.get_total_payment_types( + db=db, + cdr_year=cdr_year.year, + ) + + @module.router.get( "/cdr/users/{user_id}/payments/", response_model=list[schemas_cdr.PaymentComplete], diff --git a/app/modules/cdr/schemas_cdr.py b/app/modules/cdr/schemas_cdr.py index 4571809c6b..b6cae89813 100644 --- a/app/modules/cdr/schemas_cdr.py +++ b/app/modules/cdr/schemas_cdr.py @@ -331,3 +331,8 @@ class BatchValidation(BaseModel): user_emails: list[str] product_variant_id: UUID validated: bool + + +class TotalPurchaseValidatedBySeller(BaseModel): + name: str + total_validated: int