Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
12 changes: 2 additions & 10 deletions app/core/associations/factory_associations.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,14 @@


class AssociationsFactory(Factory):
association_ids = [
uuid.uuid4(),
uuid.uuid4(),
uuid.uuid4(),
uuid.uuid4(),
]
association_ids = [uuid.uuid4() for _ in range(len(CoreGroupsFactory.groups_ids))]

depends_on = [CoreGroupsFactory]

@classmethod
async def create_associations(cls, db: AsyncSession):
descriptions = [
"Association 1",
"Association 2",
"Association 3",
"Association 4",
f"Association {i + 1}" for i in range(len(CoreGroupsFactory.groups_ids))
]
for i in range(len(CoreGroupsFactory.groups_ids)):
await cruds_associations.create_association(
Expand Down
28 changes: 20 additions & 8 deletions app/core/groups/factory_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,35 @@


class CoreGroupsFactory(Factory):
groups_ids = [
str(uuid.uuid4()),
str(uuid.uuid4()),
str(uuid.uuid4()),
str(uuid.uuid4()),
]
groups_ids = [str(uuid.uuid4()) for _ in range(10)]

depends_on = [CoreUsersFactory]

@classmethod
async def create_core_groups(cls, db: AsyncSession):
groups = ["BDE", "BDS", "Oui", "Pixels"]
groups = [
"BDE",
"BDS",
"Pixels",
"Commuz",
"Musique",
"Fablab",
"BDA",
"Fouquette",
"Soli",
"SDeC",
]
descriptions = [
"Bureau des élèves",
"Bureau des sports",
"Association d'entraide",
"Association de photographie",
"",
"",
"",
"",
"",
"",
"",
]
for i in range(len(groups)):
await cruds_groups.create_group(
Expand Down
12 changes: 12 additions & 0 deletions app/core/mypayment/cruds_mypayment.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@ async def get_store_by_name(
return result.scalars().first()


async def get_store_by_association_id(
association_id: UUID,
db: AsyncSession,
) -> models_mypayment.Store | None:
result = await db.execute(
select(models_mypayment.Store).where(
models_mypayment.Store.association_id == association_id,
),
)
return result.scalars().first()


async def get_stores_by_structure_id(
db: AsyncSession,
structure_id: UUID,
Expand Down
36 changes: 36 additions & 0 deletions app/core/mypayment/endpoints_mypayment.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from fastapi.responses import FileResponse, RedirectResponse
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.associations import cruds_associations
from app.core.auth import schemas_auth
from app.core.checkout import schemas_checkout
from app.core.checkout.payment_tool import PaymentTool
Expand Down Expand Up @@ -91,6 +92,7 @@
generate_pdf_from_template,
get_core_data,
get_file_from_data,
is_user_member_of_an_association,
patch_identity_in_text,
set_core_data,
)
Expand Down Expand Up @@ -500,6 +502,7 @@ async def create_store(
Stores name should be unique, as an user need to be able to identify a store by its name.

**The user must be the manager for this structure**
**The user must be a member of the associated CoreAssociation**
"""
structure = await cruds_mypayment.get_structure_by_id(
structure_id=structure_id,
Expand All @@ -526,6 +529,36 @@ async def create_store(
detail="Store with this name already exists in this structure",
)

if store.association_id is not None:
association = await cruds_associations.get_association_by_id(
db=db,
association_id=store.association_id,
)
if not association:
raise HTTPException(
status_code=404,
detail="Association not found",
)
if not is_user_member_of_an_association(
user=user,
association=association,
):
raise HTTPException(
status_code=403,
detail="You are not allowed to create stores for this association",
)
existing_store_for_association = (
await cruds_mypayment.get_store_by_association_id(
association_id=store.association_id,
db=db,
)
)
if existing_store_for_association is not None:
raise HTTPException(
status_code=400,
detail="Store for this association already exists",
)

# Create new wallet for store
wallet_id = uuid.uuid4()
await cruds_mypayment.create_wallet(
Expand All @@ -541,6 +574,7 @@ async def create_store(
structure_id=structure_id,
wallet_id=wallet_id,
creation=datetime.now(tz=UTC),
association_id=store.association_id,
)
await cruds_mypayment.create_store(
store=store_db,
Expand Down Expand Up @@ -574,6 +608,7 @@ async def create_store(
wallet_id=store_db.wallet_id,
creation=store_db.creation,
structure=structure,
association_id=store_db.association_id,
)


Expand Down Expand Up @@ -845,6 +880,7 @@ async def get_user_stores(
can_see_history=seller.can_see_history,
can_cancel=seller.can_cancel,
can_manage_sellers=seller.can_manage_sellers,
association_id=store.association_id,
),
)

Expand Down
8 changes: 7 additions & 1 deletion app/core/mypayment/factory_mypayment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from faker import Faker
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.associations.factory_associations import AssociationsFactory
from app.core.mypayment import cruds_mypayment, models_mypayment, schemas_mypayment
from app.core.mypayment.types_mypayment import WalletType
from app.core.users.factory_users import CoreUsersFactory
Expand All @@ -17,7 +18,7 @@


class MyPaymentFactory(Factory):
depends_on = [CoreUsersFactory]
depends_on = [CoreUsersFactory, AssociationsFactory]

demo_structures_id: list[uuid.UUID]
other_structures_id: list[uuid.UUID]
Expand Down Expand Up @@ -67,6 +68,7 @@ async def create_structures(cls, db: AsyncSession):

@classmethod
async def create_other_structures_stores(cls, db: AsyncSession):
association_id_index = 0
for structure_id in cls.other_structures_id:
structure_store_ids = []
structure_wallet_ids = []
Expand All @@ -88,9 +90,13 @@ async def create_other_structures_stores(cls, db: AsyncSession):
name=faker.company(),
creation=datetime.now(UTC),
wallet_id=wallet_id,
association_id=AssociationsFactory.association_ids[
association_id_index
],
),
db,
)
association_id_index += 1
cls.other_stores_id.append(structure_store_ids)
cls.other_stores_wallet_id.append(structure_wallet_ids)

Expand Down
5 changes: 5 additions & 0 deletions app/core/mypayment/models_mypayment.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ class Store(Base):
)
creation: Mapped[datetime]

association_id: Mapped[UUID | None] = mapped_column(
ForeignKey("associations_associations.id"),
unique=True,
)

structure: Mapped[Structure] = relationship(init=False, lazy="joined")


Expand Down
1 change: 1 addition & 0 deletions app/core/mypayment/schemas_mypayment.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class StructureTranfert(BaseModel):

class StoreBase(BaseModel):
name: str
association_id: UUID | None = None


class StoreSimple(StoreBase):
Expand Down
1 change: 1 addition & 0 deletions app/core/mypayment/utils_mypayment.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ def invoice_model_to_schema(
structure_id=detail.store.structure_id,
wallet_id=detail.store.wallet_id,
creation=detail.store.creation,
association_id=detail.store.association_id,
),
)
for detail in invoice.details
Expand Down
8 changes: 3 additions & 5 deletions migrations/versions/49-compress_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,14 @@

def upgrade() -> None:
for data_folder, params in data_sources.items():
print("__________________________________________") # noqa: T201
print(f"Processing folder: {data_folder}") # noqa: T201
print(f"\nCompressing images from folder: {data_folder}", end="") # noqa: T201
height = params.get("height")
width = params.get("width")
quality = params.get("quality", 85)
fit = bool(params.get("fit", 0))
if Path("data/" + data_folder).exists():
for file_path in Path("data/" + data_folder).iterdir():
print(" - ", file_path) # noqa: T201
print(".", end="") # noqa: T201
if file_path.suffix in (".png", ".jpg", ".webp"):
file_bytes = file_path.read_bytes()

Expand All @@ -105,8 +104,7 @@ def upgrade() -> None:

Path(f"data/{data_folder}/{file_path.stem}.webp").write_bytes(res)

# Delete the original file
Path(f"data/{data_folder}/{file_path.name}").unlink()
print() # noqa: T201


def downgrade() -> None:
Expand Down
61 changes: 61 additions & 0 deletions migrations/versions/66-stores_coreassociations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""empty message

Create Date: 2026-03-01 11:41:22.994301
"""

from collections.abc import Sequence
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from pytest_alembic import MigrationContext

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision: str = "146db8dcb23e"
down_revision: str | None = "562adbd796ae"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
op.add_column(
"mypayment_store",
sa.Column(
"association_id",
sa.Uuid(),
nullable=True,
),
)
op.create_foreign_key(
None,
"mypayment_store",
"associations_associations",
["association_id"],
["id"],
)
op.create_unique_constraint(None, "mypayment_store", ["association_id"])


def downgrade() -> None:
op.drop_constraint(
"mypayment_store_association_id_fkey",
"mypayment_store",
type_="foreignkey",
)
op.drop_column("mypayment_store", "association_id")


def pre_test_upgrade(
alembic_runner: "MigrationContext",
alembic_connection: sa.Connection,
) -> None:
pass


def test_upgrade(
alembic_runner: "MigrationContext",
alembic_connection: sa.Connection,
) -> None:
pass
Loading
Loading