Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
9 changes: 9 additions & 0 deletions app/core/myeclpay/coredata_myeclpay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from uuid import UUID

from app.types.core_data import BaseCoreData


class MyECLPayBankAccountHolder(BaseCoreData):
"""Bank account holder information for MyECLPay."""

holder_structure_id: UUID
278 changes: 229 additions & 49 deletions app/core/myeclpay/cruds_myeclpay.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,39 @@
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import noload, selectinload

from app.core.memberships import schemas_memberships
from app.core.myeclpay import models_myeclpay, schemas_myeclpay
from app.core.myeclpay.exceptions_myeclpay import WalletNotFoundOnUpdateError
from app.core.myeclpay.types_myeclpay import (
TransactionStatus,
WalletDeviceStatus,
WalletType,
)
from app.core.myeclpay.utils_myeclpay import (
invoice_model_to_schema,
structure_model_to_schema,
)
from app.core.users import schemas_users


async def create_structure(
structure: schemas_myeclpay.Structure,
structure: schemas_myeclpay.StructureSimple,
db: AsyncSession,
) -> None:
db.add(
models_myeclpay.Structure(
id=structure.id,
short_id=structure.short_id,
name=structure.name,
association_membership_id=structure.association_membership_id,
manager_user_id=structure.manager_user_id,
siret=structure.siret,
siege_address_street=structure.siege_address_street,
siege_address_city=structure.siege_address_city,
siege_address_zipcode=structure.siege_address_zipcode,
siege_address_country=structure.siege_address_country,
iban=structure.iban,
bic=structure.bic,
creation=structure.creation,
),
)

Expand Down Expand Up @@ -112,28 +124,7 @@ async def get_structures(
) -> Sequence[schemas_myeclpay.Structure]:
result = await db.execute(select(models_myeclpay.Structure))
return [
schemas_myeclpay.Structure(
name=structure.name,
association_membership_id=structure.association_membership_id,
association_membership=schemas_memberships.MembershipSimple(
id=structure.association_membership.id,
name=structure.association_membership.name,
manager_group_id=structure.association_membership.manager_group_id,
)
if structure.association_membership
else None,
manager_user_id=structure.manager_user_id,
id=structure.id,
manager_user=schemas_users.CoreUserSimple(
id=structure.manager_user.id,
firstname=structure.manager_user.firstname,
name=structure.manager_user.name,
nickname=structure.manager_user.nickname,
account_type=structure.manager_user.account_type,
school_id=structure.manager_user.school_id,
),
)
for structure in result.scalars().all()
structure_model_to_schema(structure) for structure in result.scalars().all()
]


Expand All @@ -152,31 +143,7 @@ async def get_structure_by_id(
.scalars()
.first()
)
return (
schemas_myeclpay.Structure(
name=structure.name,
association_membership_id=structure.association_membership_id,
association_membership=schemas_memberships.MembershipSimple(
id=structure.association_membership.id,
name=structure.association_membership.name,
manager_group_id=structure.association_membership.manager_group_id,
)
if structure.association_membership
else None,
manager_user_id=structure.manager_user_id,
id=structure.id,
manager_user=schemas_users.CoreUserSimple(
id=structure.manager_user.id,
firstname=structure.manager_user.firstname,
name=structure.manager_user.name,
nickname=structure.manager_user.nickname,
account_type=structure.manager_user.account_type,
school_id=structure.manager_user.school_id,
),
)
if structure
else None
)
return structure_model_to_schema(structure) if structure else None


async def create_store(
Expand Down Expand Up @@ -981,3 +948,216 @@ async def delete_used_qrcode(
models_myeclpay.UsedQRCode.qr_code_id == qr_code_id,
),
)


async def get_invoices(
db: AsyncSession,
skip: int | None = None,
limit: int | None = None,
structures_ids: list[UUID] | None = None,
start_date: datetime | None = None,
end_date: datetime | None = None,
) -> list[schemas_myeclpay.Invoice]:
select_command = (
select(models_myeclpay.Invoice)
.where(
models_myeclpay.Invoice.end_date >= start_date
if start_date
else and_(True),
models_myeclpay.Invoice.end_date <= end_date if end_date else and_(True),
models_myeclpay.Invoice.structure_id.in_(structures_ids)
if structures_ids
else and_(True),
)
.order_by(
models_myeclpay.Invoice.end_date.desc(),
)
)
if skip is not None:
select_command = select_command.offset(skip)
if limit is not None:
select_command = select_command.limit(limit)
result = await db.execute(select_command)
return [invoice_model_to_schema(invoice) for invoice in result.scalars().all()]


async def get_invoice_by_id(
invoice_id: UUID,
db: AsyncSession,
) -> schemas_myeclpay.Invoice | None:
result = await db.execute(
select(models_myeclpay.Invoice)
.where(
models_myeclpay.Invoice.id == invoice_id,
)
.with_for_update(of=models_myeclpay.Invoice),
)
invoice = result.scalars().first()
return invoice_model_to_schema(invoice) if invoice else None


async def get_pending_invoices_by_structure_id(
structure_id: UUID,
db: AsyncSession,
) -> list[schemas_myeclpay.Invoice]:
result = await db.execute(
select(models_myeclpay.Invoice).where(
models_myeclpay.Invoice.structure_id == structure_id,
models_myeclpay.Invoice.received.is_(False),
),
)
return [invoice_model_to_schema(invoice) for invoice in result.scalars().all()]


async def get_unreceived_invoices_by_store_id(
store_id: UUID,
db: AsyncSession,
) -> list[schemas_myeclpay.InvoiceDetailBase]:
result = await db.execute(
select(models_myeclpay.InvoiceDetail)
.join(models_myeclpay.Invoice)
.where(
models_myeclpay.InvoiceDetail.store_id == store_id,
models_myeclpay.Invoice.received.is_(False),
),
)
return [
schemas_myeclpay.InvoiceDetailBase(
invoice_id=detail.invoice_id,
store_id=detail.store_id,
total=detail.total,
)
for detail in result.scalars().all()
]


async def create_invoice(
invoice: schemas_myeclpay.InvoiceInfo,
db: AsyncSession,
) -> None:
invoice_db = models_myeclpay.Invoice(
id=invoice.id,
reference=invoice.reference,
creation=invoice.creation,
start_date=invoice.start_date,
end_date=invoice.end_date,
total=invoice.total,
structure_id=invoice.structure_id,
received=invoice.received,
)
db.add(invoice_db)
for detail in invoice.details:
detail_db = models_myeclpay.InvoiceDetail(
invoice_id=invoice.id,
store_id=detail.store_id,
total=detail.total,
)
db.add(detail_db)


async def update_invoice_received_status(
invoice_id: UUID,
db: AsyncSession,
) -> None:
await db.execute(
update(models_myeclpay.Invoice)
.where(models_myeclpay.Invoice.id == invoice_id)
.values(received=True),
)


async def update_invoice_paid_status(
invoice_id: UUID,
paid: bool,
db: AsyncSession,
) -> None:
await db.execute(
update(models_myeclpay.Invoice)
.where(models_myeclpay.Invoice.id == invoice_id)
.values(paid=paid),
)


async def delete_invoice(
invoice_id: UUID,
db: AsyncSession,
) -> None:
await db.execute(
delete(models_myeclpay.InvoiceDetail).where(
models_myeclpay.InvoiceDetail.invoice_id == invoice_id,
),
)
await db.execute(
delete(models_myeclpay.Invoice).where(
models_myeclpay.Invoice.id == invoice_id,
),
)


async def get_last_structure_invoice(
structure_id: UUID,
db: AsyncSession,
) -> schemas_myeclpay.Invoice | None:
result = (
(
await db.execute(
select(models_myeclpay.Invoice)
.where(
models_myeclpay.Invoice.structure_id == structure_id,
)
.order_by(models_myeclpay.Invoice.end_date.desc())
.limit(1),
)
)
.scalars()
.first()
)
return invoice_model_to_schema(result) if result else None


async def add_withdrawal(
withdrawal: schemas_myeclpay.Withdrawal,
db: AsyncSession,
) -> None:
withdrawal_db = models_myeclpay.Withdrawal(
id=withdrawal.id,
wallet_id=withdrawal.wallet_id,
total=withdrawal.total,
creation=withdrawal.creation,
)
db.add(withdrawal_db)


async def get_withdrawals(
db: AsyncSession,
) -> list[schemas_myeclpay.Withdrawal]:
result = await db.execute(select(models_myeclpay.Withdrawal))
return [
schemas_myeclpay.Withdrawal(
id=withdrawal.id,
wallet_id=withdrawal.wallet_id,
total=withdrawal.total,
creation=withdrawal.creation,
)
for withdrawal in result.scalars().all()
]


async def get_withdrawals_by_wallet_id(
wallet_id: UUID,
db: AsyncSession,
) -> list[schemas_myeclpay.Withdrawal]:
result = await db.execute(
select(models_myeclpay.Withdrawal).where(
models_myeclpay.Withdrawal.wallet_id == wallet_id,
),
)
return [
schemas_myeclpay.Withdrawal(
id=withdrawal.id,
wallet_id=withdrawal.wallet_id,
total=withdrawal.total,
creation=withdrawal.creation,
)
for withdrawal in result.scalars().all()
]
34 changes: 34 additions & 0 deletions app/core/myeclpay/dependencies_myeclpay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from fastapi import Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.myeclpay.coredata_myeclpay import MyECLPayBankAccountHolder
from app.core.myeclpay.cruds_myeclpay import get_structure_by_id
from app.core.users.models_users import CoreUser
from app.dependencies import get_db, is_user
from app.utils.tools import get_core_data


async def is_user_bank_account_holder(
user: CoreUser = Depends(is_user()),
db: AsyncSession = Depends(get_db),
) -> CoreUser:
"""Check if the user is a bank account holder."""
account_holder = await get_core_data(
MyECLPayBankAccountHolder,
db=db,
)
structure = await get_structure_by_id(
db=db,
structure_id=account_holder.holder_structure_id,
)
if not structure:
raise HTTPException(
status_code=404,
detail="Structure not found for the bank account holder",
)
if structure.manager_user_id != user.id:
raise HTTPException(
status_code=403,
detail="User is not the bank account holder",
)
return user
Loading