diff --git a/api/src/pcapi/core/offers/factories.py b/api/src/pcapi/core/offers/factories.py index 7220eaf40a4..07bf1f0b326 100644 --- a/api/src/pcapi/core/offers/factories.py +++ b/api/src/pcapi/core/offers/factories.py @@ -21,11 +21,23 @@ from . import models +EVENT_PRODUCT_SUBCATEGORIES_IDS = [subcategories.SEANCE_CINE.id] +THINGS_PRODUCT_SUBCATEGORIES_IDS = [ + subcategories.LIVRE_PAPIER.id, + subcategories.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, + subcategories.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id, +] +ALL_PRODUCT_SUBCATEGORIES_IDS = EVENT_PRODUCT_SUBCATEGORIES_IDS + THINGS_PRODUCT_SUBCATEGORIES_IDS + + class ProductFactory(BaseFactory): + AVAILABLE_SUBCATEGORIES = ALL_PRODUCT_SUBCATEGORIES_IDS + class Meta: model = models.Product + exclude = ("AVAILABLE_SUBCATEGORIES",) - subcategoryId = subcategories.SUPPORT_PHYSIQUE_FILM.id + subcategoryId = subcategories.LIVRE_PAPIER.id name = factory.Sequence("Product {}".format) description = factory.Sequence("A passionate description of product {}".format) @@ -37,6 +49,9 @@ def _create( **kwargs: typing.Any, ) -> models.Product: # Graciously provide the required idAtProviders if lastProvider is given. + if kwargs["subcategoryId"] not in cls.AVAILABLE_SUBCATEGORIES: + raise ValueError(f"Events products subcategory can only be one of {cls.AVAILABLE_SUBCATEGORIES}.") + if kwargs.get("lastProvider") and not kwargs.get("idAtProviders"): kwargs["idAtProviders"] = uuid.uuid4() @@ -62,11 +77,13 @@ class Meta: class EventProductFactory(ProductFactory): + AVAILABLE_SUBCATEGORIES = EVENT_PRODUCT_SUBCATEGORIES_IDS subcategoryId = subcategories.SEANCE_CINE.id class ThingProductFactory(ProductFactory): - subcategoryId = subcategories.SUPPORT_PHYSIQUE_FILM.id + AVAILABLE_SUBCATEGORIES = THINGS_PRODUCT_SUBCATEGORIES_IDS + subcategoryId = subcategories.SUPPORT_PHYSIQUE_MUSIQUE_CD.id def build_extra_data_from_subcategory( diff --git a/api/src/pcapi/sandboxes/scripts/creators/industrial/__init__.py b/api/src/pcapi/sandboxes/scripts/creators/industrial/__init__.py index 00ab448d052..b566a076aef 100644 --- a/api/src/pcapi/sandboxes/scripts/creators/industrial/__init__.py +++ b/api/src/pcapi/sandboxes/scripts/creators/industrial/__init__.py @@ -18,7 +18,6 @@ from pcapi.sandboxes.scripts.creators.industrial.create_industrial_eac_data import create_eac_data from pcapi.sandboxes.scripts.creators.industrial.create_industrial_event_occurrences import * from pcapi.sandboxes.scripts.creators.industrial.create_industrial_event_offers import * -from pcapi.sandboxes.scripts.creators.industrial.create_industrial_event_products import * from pcapi.sandboxes.scripts.creators.industrial.create_industrial_event_stocks import * from pcapi.sandboxes.scripts.creators.industrial.create_industrial_incidents import create_industrial_incidents from pcapi.sandboxes.scripts.creators.industrial.create_industrial_individual_offerers import ( @@ -41,7 +40,6 @@ create_industrial_search_indexed_objects, ) from pcapi.sandboxes.scripts.creators.industrial.create_industrial_thing_offers import * -from pcapi.sandboxes.scripts.creators.industrial.create_industrial_thing_products import * from pcapi.sandboxes.scripts.creators.industrial.create_industrial_thing_stocks import * from pcapi.sandboxes.scripts.creators.industrial.create_industrial_venues import * from pcapi.sandboxes.scripts.creators.industrial.create_industrial_venues_with_timezone import ( @@ -79,13 +77,9 @@ def save_industrial_sandbox() -> None: venues_by_name = create_industrial_venues(offerers_by_name) - event_products_by_name = create_industrial_event_products() + event_offers_by_name = create_industrial_event_offers(offerers_by_name) - thing_products_by_name = create_industrial_thing_products() - - event_offers_by_name = create_industrial_event_offers(event_products_by_name, offerers_by_name) - - thing_offers_by_name = create_industrial_thing_offers(thing_products_by_name, offerers_by_name, venues_by_name) + thing_offers_by_name = create_industrial_thing_offers(offerers_by_name, venues_by_name) create_industrial_draft_offers(offerers_by_name) diff --git a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_occurrences.py b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_occurrences.py index 635fa1aad1b..17ee90c2013 100644 --- a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_occurrences.py +++ b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_occurrences.py @@ -44,7 +44,7 @@ def create_industrial_event_occurrences( price_categories: dict[decimal.Decimal, offers_models.PriceCategory] = {} for index, beginning_datetime in enumerate(EVENT_OCCURRENCE_BEGINNING_DATETIMES, start=1): name = "{} / {} / {} ".format( - event_offer_with_occurrences.product.name if event_offer_with_occurrences.product else "", + event_offer_with_occurrences.name, event_offer_with_occurrences.venue.name, beginning_datetime.strftime(date_utils.DATE_ISO_FORMAT), ) diff --git a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_offers.py b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_offers.py index 83e29f93743..bc0c8cd6972 100644 --- a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_offers.py +++ b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_offers.py @@ -1,9 +1,11 @@ import logging +from pcapi.core.categories import subcategories_v2 import pcapi.core.offerers.models as offerers_models import pcapi.core.offers.factories as offers_factories import pcapi.core.offers.models as offers_models from pcapi.repository import repository +from pcapi.sandboxes.scripts.mocks.event_mocks import MOCK_NAMES logger = logging.getLogger(__name__) @@ -14,7 +16,6 @@ def create_industrial_event_offers( - events_by_name: dict[str, offers_models.Product], offerers_by_name: dict[str, offerers_models.Offerer], ) -> dict[str, offers_models.Offer]: logger.info("create_industrial_event_offers") @@ -24,7 +25,7 @@ def create_industrial_event_offers( event_index = 0 offer_index = 0 - event_items = list(events_by_name.items()) + event_subcategories = [s for s in subcategories_v2.ALL_SUBCATEGORIES if s.is_event and s.is_offline_only] for offerer in offerers_by_name.values(): event_venues = [venue for venue in offerer.managedVenues if not venue.isVirtual] @@ -35,9 +36,10 @@ def create_industrial_event_offers( event_venue = event_venues[0] for venue_event_index in range(0, EVENTS_PER_OFFERER_WITH_PHYSICAL_VENUE): - rest_event_index = (venue_event_index + event_index) % len(event_items) - - (event_name, event) = event_items[rest_event_index] + event_subcategory_index = (venue_event_index + event_index) % len(event_subcategories) + event_subcategory = event_subcategories[event_subcategory_index] + mock_index = (venue_event_index + event_index) % len(MOCK_NAMES) + event_name = MOCK_NAMES[mock_index] name = "{} / {}".format(event_name, event_venue.name) if offer_index % DEACTIVATED_OFFERS_PICK_MODULO == 0: @@ -50,8 +52,10 @@ def create_industrial_event_offers( is_duo = True event_offers_by_name[name] = offers_factories.OfferFactory( venue=event_venue, - product=event, - extraData=event.extraData, + subcategoryId=event_subcategory.id, + extraData=offers_factories.build_extra_data_from_subcategory( + event_subcategory.id, set_all_fields=False + ), isActive=is_active, isDuo=is_duo, ) diff --git a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_products.py b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_products.py deleted file mode 100644 index 4e4b6da15fe..00000000000 --- a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_event_products.py +++ /dev/null @@ -1,85 +0,0 @@ -import logging -import random - -from pcapi.core.categories import subcategories_v2 -import pcapi.core.offers.factories as offers_factories -import pcapi.core.offers.models as offers_models -from pcapi.domain.music_types import MUSIC_TYPES -from pcapi.domain.show_types import SHOW_TYPES -from pcapi.repository import repository -from pcapi.sandboxes.scripts.mocks.event_mocks import MOCK_DESCRIPTIONS -from pcapi.sandboxes.scripts.mocks.event_mocks import MOCK_NAMES -from pcapi.sandboxes.scripts.mocks.user_mocks import MOCK_FIRST_NAMES -from pcapi.sandboxes.scripts.mocks.user_mocks import MOCK_LAST_NAMES - - -logger = logging.getLogger(__name__) - - -EVENT_COUNTS_PER_TYPE = 7 - - -def create_industrial_event_products() -> dict[str, offers_models.Product]: - logger.info("create_industrial_event_products") - - event_products_by_name = {} - - event_subcategories = [s for s in subcategories_v2.ALL_SUBCATEGORIES if s.is_event and s.is_offline_only] - - for product_creation_counter in range(0, EVENT_COUNTS_PER_TYPE): - for event_subcategories_list_index, event_subcategory in enumerate(event_subcategories): - mock_index = (product_creation_counter + event_subcategories_list_index) % len(MOCK_NAMES) - event_name = MOCK_NAMES[mock_index] - description = MOCK_DESCRIPTIONS[mock_index] - - name = "{} / {}".format(event_subcategory.id, event_name) - event_product = offers_factories.ProductFactory( - description=description, - durationMinutes=60, - name=event_name, - subcategoryId=event_subcategory.id, - ) - - extraData = {} - extra_data_index = 0 - for conditional_field_name in event_product.subcategory.conditional_fields: - conditional_index = product_creation_counter + event_subcategories_list_index + extra_data_index - if conditional_field_name in [ - subcategories_v2.ExtraDataFieldEnum.AUTHOR.value, - subcategories_v2.ExtraDataFieldEnum.PERFORMER.value, - subcategories_v2.ExtraDataFieldEnum.SPEAKER.value, - subcategories_v2.ExtraDataFieldEnum.STAGE_DIRECTOR.value, - ]: - mock_first_name_index = conditional_index % len(MOCK_FIRST_NAMES) - mock_first_name = MOCK_FIRST_NAMES[mock_first_name_index] - mock_last_name_index = conditional_index % len(MOCK_LAST_NAMES) - mock_last_name = MOCK_LAST_NAMES[mock_last_name_index] - mock_name = "{} {}".format(mock_first_name, mock_last_name) - extraData[conditional_field_name] = mock_name - elif conditional_field_name == subcategories_v2.ExtraDataFieldEnum.MUSIC_TYPE.value: - music_type_index: int = conditional_index % len(MUSIC_TYPES) - music_type = MUSIC_TYPES[music_type_index] - extraData[conditional_field_name] = str(music_type.code) - music_sub_type_index: int = conditional_index % len(music_type.children) - music_sub_type = music_type.children[music_sub_type_index] - extraData["musicSubType"] = str(music_sub_type.code) - elif conditional_field_name == subcategories_v2.ExtraDataFieldEnum.SHOW_TYPE.value: - show_type_index: int = conditional_index % len(SHOW_TYPES) - show_type = SHOW_TYPES[show_type_index] - extraData[conditional_field_name] = str(show_type.code) - show_sub_type_index: int = conditional_index % len(show_type.children) - show_sub_type = show_type.children[show_sub_type_index] - extraData["showSubType"] = str(show_sub_type.code) - elif conditional_field_name == subcategories_v2.ExtraDataFieldEnum.VISA.value: - extraData[conditional_field_name] = "".join(random.choices([str(i) for i in range(9)], k=10)) - extra_data_index += 1 - event_product.extraData = extraData - event_products_by_name[name] = event_product - - product_creation_counter += len(event_subcategories) - - repository.save(*event_products_by_name.values()) - - logger.info("created %d event products", len(event_products_by_name)) - - return event_products_by_name diff --git a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_thing_offers.py b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_thing_offers.py index e6504d89d56..a59f2c08fbb 100644 --- a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_thing_offers.py +++ b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_thing_offers.py @@ -1,9 +1,11 @@ import logging +from pcapi.core.categories import subcategories_v2 import pcapi.core.offerers.models as offerers_models import pcapi.core.offers.factories as offers_factories import pcapi.core.offers.models as offers_models from pcapi.repository import repository +from pcapi.sandboxes.scripts.mocks.thing_mocks import MOCK_NAMES logger = logging.getLogger(__name__) @@ -14,7 +16,6 @@ def create_industrial_thing_offers( - thing_products_by_name: dict[str, offers_models.Product], offerers_by_name: dict[str, offerers_models.Offerer], venues_by_name: dict[str, offerers_models.Venue], ) -> dict[str, offers_models.Offer]: @@ -22,10 +23,11 @@ def create_industrial_thing_offers( thing_offers_by_name: dict[str, offers_models.Offer] = {} + thing_subcategories = [s for s in subcategories_v2.ALL_SUBCATEGORIES if not s.is_event] + id_at_provider = 1234 thing_index = 0 offer_index = 0 - thing_items = list(thing_products_by_name.items()) for offerer in offerers_by_name.values(): virtual_venue = [venue for venue in offerer.managedVenues if venue.isVirtual][0] @@ -34,17 +36,20 @@ def create_industrial_thing_offers( for venue_thing_index in range(0, THINGS_PER_OFFERER): thing_venue = None - while thing_venue is None: - rest_thing_index = (venue_thing_index + thing_index) % len(thing_items) - (thing_name, thing_product) = thing_items[rest_thing_index] - if thing_product.subcategory.is_offline_only: - thing_venue = physical_venue - elif thing_product.subcategory.is_online_only: - thing_venue = virtual_venue - else: - thing_venue = physical_venue - - thing_index += 1 + subcategory_index = (venue_thing_index + thing_index) % len(thing_subcategories) + subcategory = thing_subcategories[subcategory_index] + thing_name_index = (venue_thing_index + thing_index) % len(MOCK_NAMES) + thing_name = MOCK_NAMES[thing_name_index] + + if subcategory.is_offline_only: + thing_venue = physical_venue + elif subcategory.is_online_only: + thing_venue = virtual_venue + else: + thing_venue = physical_venue + + if thing_venue is None: + continue name = "{} / {}".format(thing_name, thing_venue.name) if offer_index % DEACTIVATED_OFFERS_PICK_MODULO == 0: @@ -53,11 +58,11 @@ def create_industrial_thing_offers( is_active = True thing_offers_by_name[name] = offers_factories.OfferFactory( venue=thing_venue, - subcategoryId=thing_product.subcategoryId, + subcategoryId=subcategory.id, isActive=is_active, - url="http://example.com" if thing_product.subcategory.is_online_only else None, + url="http://example.com" if subcategory.is_online_only else None, idAtProvider=str(id_at_provider), - extraData=thing_product.extraData, + extraData=offers_factories.build_extra_data_from_subcategory(subcategory.id, set_all_fields=False), ) offer_index += 1 id_at_provider += 1 diff --git a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_thing_products.py b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_thing_products.py deleted file mode 100644 index f2a7adbff68..00000000000 --- a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_thing_products.py +++ /dev/null @@ -1,354 +0,0 @@ -import logging -import random - -from pcapi.core.categories import subcategories_v2 -import pcapi.core.offers.factories as offers_factories -import pcapi.core.offers.models as offers_models -import pcapi.core.providers.factories as providers_factories -from pcapi.core.providers.titelive_gtl import GTLS -from pcapi.domain.music_types import MUSIC_SUB_TYPES_BY_SLUG -from pcapi.domain.music_types import MUSIC_TYPES -from pcapi.domain.music_types import MUSIC_TYPES_BY_SLUG -from pcapi.repository import repository -import pcapi.sandboxes.scripts.creators.industrial.utils as industrial_utils -from pcapi.sandboxes.scripts.mocks.thing_mocks import MOCK_AUTHOR_NAMES -from pcapi.sandboxes.scripts.mocks.thing_mocks import MOCK_DESCRIPTIONS -from pcapi.sandboxes.scripts.mocks.thing_mocks import MOCK_NAMES -from pcapi.sandboxes.scripts.mocks.user_mocks import MOCK_FIRST_NAMES -from pcapi.sandboxes.scripts.mocks.user_mocks import MOCK_LAST_NAMES -from pcapi.utils import date as date_utils - - -logger = logging.getLogger(__name__) - - -THINGS_PER_SUBCATEGORY = 7 - - -def create_industrial_thing_products() -> dict[str, offers_models.Product]: - logger.info("create_industrial_thing_products") - - thing_products_by_name = {} - - thing_subcategories = [s for s in subcategories_v2.ALL_SUBCATEGORIES if not s.is_event] - - id_at_providers = 1234 - provider = providers_factories.PublicApiProviderFactory(name="ThingMusicProvider") - base_ean = 1234567890123 - - for product_creation_counter in range(0, THINGS_PER_SUBCATEGORY): - for thing_subcategories_list_index, thing_subcategory in enumerate(thing_subcategories): - mock_index = (product_creation_counter + thing_subcategories_list_index) % len(MOCK_NAMES) - - name = "{} / {}".format(thing_subcategory.id, MOCK_NAMES[mock_index]) - - # FIXME (yacine-pc, 2024-01-24): do not create product for only online subcategories (digital products) - thing_product = offers_factories.ProductFactory( - lastProvider=provider, - extraData={"author": MOCK_AUTHOR_NAMES[mock_index]}, - description=MOCK_DESCRIPTIONS[mock_index], - idAtProviders=str(id_at_providers), - name=MOCK_NAMES[mock_index], - subcategoryId=thing_subcategory.id, - ) - - extraData = {} - extra_data_index = 0 - for conditionalField_name in thing_product.subcategory.conditional_fields: - conditional_index = product_creation_counter + thing_subcategories_list_index + extra_data_index - if conditionalField_name in [ - subcategories_v2.ExtraDataFieldEnum.AUTHOR.value, - subcategories_v2.ExtraDataFieldEnum.PERFORMER.value, - subcategories_v2.ExtraDataFieldEnum.SPEAKER.value, - subcategories_v2.ExtraDataFieldEnum.STAGE_DIRECTOR.value, - ]: - mock_first_name_index = ( - product_creation_counter + thing_subcategories_list_index + extra_data_index - ) % len(MOCK_FIRST_NAMES) - mock_first_name = MOCK_FIRST_NAMES[mock_first_name_index] - mock_last_name_index = ( - product_creation_counter + thing_subcategories_list_index + extra_data_index - ) % len(MOCK_LAST_NAMES) - mock_last_name = MOCK_LAST_NAMES[mock_last_name_index] - mock_name = "{} {}".format(mock_first_name, mock_last_name) - extraData[conditionalField_name] = mock_name - elif conditionalField_name == "musicType": - music_type_index: int = conditional_index % len(MUSIC_TYPES) - music_type = MUSIC_TYPES[music_type_index] - extraData[conditionalField_name] = str(music_type.code) - music_sub_type_index: int = conditional_index % len(music_type.children) - music_sub_type = music_type.children[music_sub_type_index] - extraData["musicSubType"] = str(music_sub_type.code) - elif conditionalField_name == "ean": - extraData["ean"] = str(base_ean) - base_ean += 1 - elif conditionalField_name == "gtl_id": - extraData["gtl_id"] = random.choice(list(GTLS.keys())) - extra_data_index += 1 - thing_product.extraData = extraData - thing_products_by_name[name] = thing_product - id_at_providers += 1 - - product_creation_counter += len(thing_subcategories) - - titelive_synced_products = create_titelive_synced_music_products() - thing_products_by_name |= {product.name: product for product in titelive_synced_products} - - repository.save(*thing_products_by_name.values()) - - industrial_utils.create_products_thumb(titelive_synced_products) - - logger.info("created %d thing products", len(thing_products_by_name)) - - return thing_products_by_name - - -def create_titelive_synced_music_products() -> list[offers_models.Product]: - provider = providers_factories.PublicApiProviderFactory(name="ThingMusicProvider") - logger.info("create_titelive_synced_music_products") - - unavailable_cd = offers_factories.ProductFactory( - lastProvider=provider, - description=None, - extraData=offers_models.OfferExtraData( - artist="Queen", - author="Queen", - comment="Limited Edition", - dispo="4", - distributeur="Universal Music France", - ean="0602438073177", - editeur="VIRGIN RECORDS FRANCE", - gtl_id="70100", - music_label="UNIVERSAL MUSIC", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["ROCK-HARD_ROCK"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["ROCK-HARD_ROCK"].code), - nb_galettes="1", - performer="Queen", - ), - idAtProviders="0602438073177", - name="Greatest Hits", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, - ) - - soon_released_cd = offers_factories.ProductFactory( - lastProvider=provider, - description="Après les récentes rééditions de The Who 'Sell Out', 'My Generation', 'Tommy' et 'Quadrophenia', voici enfin Who's Next, considéré par de nombreux fans comme le plus grand album du groupe ! Découvrez cette nouvelle réédition déclinée en plusieurs supports : CD Cristal, 2CD Digipack, LP, Coffret 10CD+Blu-ray Audio ainsi qu'un coffret 4LP (album rematerisé Who's Next et le Live At The Civic Auditorium, San Francisco -1971).\n\nLe processus de création de l'album fut à l'époque révolutionnaire. Au début des années 70, The Who, et en particulier leur principal auteur-compositeur Pete Townshend, ont été confrontés à un immense défi : Comment succéder au succès international de Tommy ? La réponse a été un projet ambitieux, futuriste et prémonitoire nommé 'Life House'. Life House prédisait un monde dystopique qui semble aujourd'hui familier. Les thèmes abordés étaient ceux de la pollution, des entreprises trop puissantes et de la technologie. Le projet en deux volets réunissait un film et une performance live au Young Vic Theatre de Londres.\n\nEt comme l'écrit Pete Townshend « La fiction et l'expérience Live étaient toutes deux imparfaites, et aucune n'a été correctement réalisée. Mais une musique merveilleuse est sortie du projet, et l'idée m'a toujours hantée, car de nombreux éléments de la fiction semblent se réaliser »\n", - extraData=offers_models.OfferExtraData( - artist="The who", - author="The who", - comment="TBC", - date_parution=date_utils.parse_titelive_date_to_string("15/09/2023"), - dispo="2", - distributeur="Universal Music France", - ean="0602435858395", - editeur="UNIVERSAL", - gtl_id="70100", - music_label="UNIVERSAL", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["ROCK-HARD_ROCK"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["ROCK-HARD_ROCK"].code), - nb_galettes="1", - performer="The Who", - ), - idAtProviders="0602435858395", - name="Who's Next", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, - ) - - available_rap_cd_1 = offers_factories.ProductFactory( - lastProvider=provider, - description='GIMS revient avec " Les dernières volontés de Mozart ", un album de tubes.\n\n" Les dernières volontés de Mozart " est un album phénomène.\nWolfgang Amadeus Mozart ne rentrait dans aucune case, il a composé et excellé dans tous les registres de son époque. Son audace, sa virtuosité et son génie sont inégalables et traversent le temps.\nD\'une créativité rare, GIMS relève encore une fois le défi : celui d\'avoir composé des morceaux aux univers tous différents, à la fois populaires et toujours innovants. Ce nouvel opus est d\'une qualité redoutable, rassemblant 20 titres qui sont autant de tubes en devenir.\nEt pour que la surprise soit totale, l\'album offre des collaborations aussi réussies qu\'inattendues...\nInclus le tube " Maintenant ".\n', - extraData=offers_models.OfferExtraData( - artist="Gims", - author="Gims", - date_parution=date_utils.parse_titelive_date_to_string("02/12/2022"), - dispo="1", - distributeur="Believe", - ean="3700187679323", - editeur="BELIEVE", - gtl_id="110400", - music_label="PLAY TWO", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["HIP_HOP_RAP-RAP_FRANCAIS"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["HIP_HOP_RAP-RAP_FRANCAIS"].code), - nb_galettes="1", - performer="Gims", - ), - idAtProviders="3700187679323", - name="Les dernières volontés de Mozart (symphony)", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, - ) - - available_rap_cd_2 = offers_factories.ProductFactory( - lastProvider=provider, - description='.Après l\'immense succès de " Civilisation " (déjà plus de 600.000 ventes) et de la nouvelle saison de la série-documentaire " Montre jamais ça à personne ", OrelSan revient avec une version augmentée de 10 nouveaux titres de son album déjà culte : "Civilisation Edition Ultime".\n\nAvec près de 2,5 millions d\'albums vendus en cumulé et 9 Victoires de la Musique, OrelSan occupe une place à part dans le paysage français. La voix d\'une génération.\n\nOrelSan " Civilisation Edition Ultime ", double album CD.\n', - extraData=offers_models.OfferExtraData( - artist="Orelsan", - author="Orelsan", - comment="édition double CD sous fourreau", - date_parution=date_utils.parse_titelive_date_to_string("28/10/2022"), - dispo="1", - distributeur="Wagram Music", - ean="3596974281424", - editeur="3EME BUREAU", - gtl_id="110400", - music_label="3EME BUREAU", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["HIP_HOP_RAP-RAP_FRANCAIS"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["HIP_HOP_RAP-RAP_FRANCAIS"].code), - nb_galettes="2", - performer="Orelsan", - ), - idAtProviders="3596974281424", - name="Civilisation - Edition ultime", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, - ) - - available_multiple_discs_cd = offers_factories.ProductFactory( - lastProvider=provider, - description="PROJET CARITATIF, A BUT NON LUCRATIF :\n\nTOUS LES PROFITS SERONT REVERSES A L’ASSOCIATION LES RESTOS DU COEUR\n \nFidèles à l’appel lancé par Coluche dès 1985, et après 2 ans de concerts sans public, les plus grands artistes de la scène musicale française se réunissent pour la cause des Restos du Coeur.\n\nPlus que jamais, les Restos du Coeur ont besoin de vous !\nEt rappelez-vous que « CHAQUE CD OU DVD VENDU = 17 REPAS OFFERTS AUX RESTOS DU COEUR ».\n\nRetrouvez L’INTEGRALITE DU SPECTACLE « 2023 Enfoirés un jour, toujours ».\nInclus le single « Rêvons » écrit et composé par Amir, Nazim et Nyadjiko.", - extraData=offers_models.OfferExtraData( - artist="Les enfoirés", - author="Les enfoirés", - date_parution=date_utils.parse_titelive_date_to_string("04/03/2023"), - dispo="1", - distributeur="Sony Music Entertainement", - ean="0196587966423", - editeur="SONY MUSIC CATALOGUE", - gtl_id="50200", - music_label="COLUMBIA", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["CHANSON_VARIETE-CHANSON_FRANCAISE"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["CHANSON_VARIETE-CHANSON_FRANCAISE"].code), - nb_galettes="2", - performer="Les Enfoirés", - ), - idAtProviders="0196587966423", - name="2023 Enfoirés un jour, toujours", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, - ) - - available_french_cd = offers_factories.ProductFactory( - lastProvider=provider, - description="'Coeur Encore' est la nouvelle édition limitée du dernier album de Clara Luciani, déjà certifié triple disque de platine. Après deux Victoires de la Musique en 2022 (Artiste féminine et Meilleur album) l'artiste rend hommage au son qui a bercé la création de son album 'Coeur', en reprenant en français 4 titres légendaires du disco funk dont 'Celebration' en featuring avec Kool & The Gang.", - extraData=offers_models.OfferExtraData( - artist="Clara luciani", - author="Clara luciani", - date_parution=date_utils.parse_titelive_date_to_string("25/11/2022"), - dispo="1", - distributeur="Universal Music France", - ean="0602448125255", - editeur="ROMANCE MUSIQUE", - gtl_id="50200", - music_label="ROMANCE MUSIQUE", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["CHANSON_VARIETE-CHANSON_FRANCAISE"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["CHANSON_VARIETE-CHANSON_FRANCAISE"].code), - nb_galettes="2", - performer="Clara Luciani", - ), - idAtProviders="0602448125255", - name="Coeur Encore", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, - ) - - available_pop_vinyl_1 = offers_factories.ProductFactory( - lastProvider=provider, - description="LE GROUPE INTERNATIONAL N°1 DE RETOUR AVEC UN ALBUM DE TUBES POP ! NEUVIÈME ALBUM STUDIO DU QUATUOR BRITANNIQUE, PRODUIT PAR MAX MARTIN ET PORTÉ PAR LE SINGLE 'HIGHER POWER' LANCÉ AU PRINTEMPS 2021 DEPUIS LA STATION SPATIALE INTERNATIONALE AVEC L'AIDE DE THOMAS PESQUET.\nLe quatuor britannique s'apprête à sortir leur neuvième album studio, 'Music Of The Spheres', produit par le producteur star de nombreuses fois récompensé Max Martin, et introduit avec le single \"Higher Power\", ritournelle pop optimiste et entraînante lancée depuis la Station Spatiale Internationale par Thomas Pesquet. Sur le thème graphique de l'espace, Coldplay livre un nouvel opus pop taillé pour les stades, fait à la fois d'hymnes entraînants et de ballades chaleureuses.", - extraData=offers_models.OfferExtraData( - artist="Coldplay", - author="Coldplay", - date_parution=date_utils.parse_titelive_date_to_string("15/10/2021"), - dispo="1", - distributeur="Warner Music France", - ean="0190296666964", - editeur="WEA", - gtl_id="50300", - music_label="PARLOPHONE", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["POP-POP_ROCK"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["POP-POP_ROCK"].code), - nb_galettes="1", - performer="Coldplay", - ), - idAtProviders="0190296666964", - name="Music Of The Spheres", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id, - ) - - available_pop_vinyl_2 = offers_factories.ProductFactory( - lastProvider=provider, - description="Ce huitième album studio de Gorillaz est une collection énergique, optimiste et riche en genres de 10 titres mettant en vedette un line-up stellaire de collaborateurs : Thundercat, Tame Impala, Bad Bunny, Stevie Nicks, Adeleye Omotayo, Bootie Brown et Beck. Enregistré à Londres et à Los Angeles plus tôt, il est produit par Gorillaz, Remi Kabaka jr. et le producteur de multiples fois récompensé Greg Kurstin.", - extraData=offers_models.OfferExtraData( - artist="Gorillaz", - author="Gorillaz", - date_parution=date_utils.parse_titelive_date_to_string("24/02/2023"), - dispo="1", - distributeur="Warner Music France", - ean="5054197199738", - editeur="WARNER MUSIC UK", - gtl_id="50300", - music_label="WARNER MUSIC UK", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["POP-POP_ROCK"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["POP-POP_ROCK"].code), - nb_galettes="1", - performer="Gorillaz", - ), - idAtProviders="5054197199738", - name="Cracker Island", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id, - ) - - available_rock_vinyl = offers_factories.ProductFactory( - lastProvider=provider, - description='" The Hightlights " la compilation de ses plus grands tubes !\n\nAprès une année 2020 interstellaire ! The Weeknd nous livre ses plus grands HITS dans une compilation exceptionnelle !\n', - extraData=offers_models.OfferExtraData( - artist="The weeknd", - author="The weeknd", - date_parution=date_utils.parse_titelive_date_to_string("21/07/2023"), - dispo="1", - distributeur="Universal Music France", - ean="0602435931975", - editeur="UNIVERSAL", - gtl_id="60200", - music_label="RCA MUSIC GROUP/AMADE", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["ROCK-INDIE_ROCK"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["ROCK-INDIE_ROCK"].code), - nb_galettes="1", - performer="The Weeknd", - ), - idAtProviders="0602435931975", - name="The Highlights", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id, - ) - - available_multiple_discs_vinyl = offers_factories.ProductFactory( - lastProvider=provider, - description="LONDON GRAMMAR EST UN TRÈS JEUNE TRIO ANGLAIS FORMÉ SUR LES BANCS DE L'UNIVERSITÉ.\nAUTEURS-COMPOSITEURS-INTERPRÈTES : HANNAH REID, DOT MAJOR & DAN ROTHMAN SUSCITENT L'ENTHOUSIASME DE PART ET D'AUTRE DE LA MANCHE.\nPORTÉ PAR LA VOIX PUISSANTE ET BLUFFANTE DE HANNAH, LONDON GRAMMAR EST DÉJÀ CONSIDÉRÉ COMME LE PENDANT POP DE THE XX.", - extraData=offers_models.OfferExtraData( - artist="London grammar", - author="London grammar", - comment="édition double vinyle gatefold + CD", - date_parution=date_utils.parse_titelive_date_to_string("02/01/2019"), - dispo="1", - distributeur="Universal Music France", - ean="5060281614698", - editeur="BECAUSE", - gtl_id="60200", - music_label="BECAUSE", - musicSubType=str(MUSIC_SUB_TYPES_BY_SLUG["ROCK-INDIE_ROCK"].code), - musicType=str(MUSIC_TYPES_BY_SLUG["ROCK-INDIE_ROCK"].code), - nb_galettes="3", - performer="London Grammar", - ), - idAtProviders="5060281614698", - name="If you wait", - subcategoryId=subcategories_v2.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id, - ) - - return [ - unavailable_cd, - soon_released_cd, - available_rap_cd_1, - available_rap_cd_2, - available_multiple_discs_cd, - available_french_cd, - available_pop_vinyl_1, - available_pop_vinyl_2, - available_rock_vinyl, - available_multiple_discs_vinyl, - ] diff --git a/api/src/pcapi/scripts/integration/__init__.py b/api/src/pcapi/scripts/integration/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/api/src/pcapi/scripts/integration/add_eans.py b/api/src/pcapi/scripts/integration/add_eans.py deleted file mode 100644 index 565dfaab32f..00000000000 --- a/api/src/pcapi/scripts/integration/add_eans.py +++ /dev/null @@ -1,51 +0,0 @@ -from contextlib import suppress - -import sqlalchemy as sa - -import pcapi.core.categories.subcategories_v2 as subcategories -from pcapi.core.categories.subcategories_v2 import Subcategory -from pcapi.core.offers.models import Product -from pcapi.models import db -from pcapi.scripts.integration.eans_data import EANS -from pcapi.scripts.integration.eans_data import EAN_CAT - - -def get_known_eans() -> set[str]: - query = Product.query.filter(Product.extraData != None).options(sa.orm.load_only(Product.extraData)) - eans = set() - - for product in query.yield_per(2_000): - with suppress(TypeError, KeyError): - eans.add(product.extraData["ean"]) - - return eans - - -def get_subcategory_from_ean_type(ean_type: EAN_CAT) -> Subcategory: - return { - EAN_CAT.CDS: subcategories.SUPPORT_PHYSIQUE_MUSIQUE_CD, - EAN_CAT.VINYLES: subcategories.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE, - EAN_CAT.EBOOKS: subcategories.LIVRE_NUMERIQUE, - EAN_CAT.UNELIGIBLE_BOOKS: subcategories.LIVRE_PAPIER, - EAN_CAT.ELIGIBLE_BOOKS: subcategories.LIVRE_PAPIER, - }[ean_type] - - -def fill_missing_eans() -> None: - known_eans = get_known_eans() - - for idx, (ean_type, eans) in enumerate(EANS.items()): - missing_eans = eans - known_eans - subcategory = get_subcategory_from_ean_type(ean_type) - - for ean in missing_eans: - db.session.add( - Product(name=f"{subcategory.pro_label} #{idx}", subcategoryId=subcategory.id, extraData={"ean": ean}) - ) - - try: - db.session.commit() - except Exception: - db.session.rollback() - print(f"Could not commit for {ean_type}") - raise diff --git a/api/src/pcapi/scripts/integration/eans_data.py b/api/src/pcapi/scripts/integration/eans_data.py deleted file mode 100644 index cfa3f09101b..00000000000 --- a/api/src/pcapi/scripts/integration/eans_data.py +++ /dev/null @@ -1,550 +0,0 @@ -import enum - - -class EAN_CAT(enum.Enum): - CDS = "CDS" - VINYLES = "VINYLES" - EBOOKS = "EBOOKS" - ELIGIBLE_BOOKS = "ELIGIBLE_BOOKS" - UNELIGIBLE_BOOKS = "UNELIGIBLE_BOOKS" - - -EANS = { - EAN_CAT.CDS: { - "0606949048624", - "5060620870099", - "3700551784172", - "0196922401817", - "3700187670139", - "0724387383814", - "0196922264986", - "0192641820717", - "3700187676858", - "3700187672676", - "0888751437319", - "0196922331725", - "0190295286101", - "0196922597602", - "0190295484088", - "3700187672249", - "8809440339761", - "0602498614747", - "0196922331701", - "0196922402258", - "0602448224330", - "8809440339532", - "0602438406562", - "0196587268220", - "9700000363259", - "0190295076566", - "0190295378370", - "3700187673994", - "8809903921274", - "0196922330780", - "3700187670498", - "8804775053795", - "5055667602659", - "8804775077494", - "0196922401671", - "8809634382139", - "8809440339938", - "0196922580734", - "0196588460326", - "3700551784776", - "8809440338276", - "0190295378356", - "0196587214623", - "0197190174267", - "0602547481917", - "0602508598531", - "3700187665289", - "0889030027429", - "3596973626424", - "0196922580727", - "8809789999893", - "8809929746745", - "5054197887093", - "0075678625718", - "0602508390753", - "0196922401664", - "0602537865413", - "0194399456811", - "0196922597596", - "0602445926015", - "3700187664015", - "0602537514472", - "0602508924330", - "0196922330186", - "9700000359146", - "8804775083280", - "0196922330902", - "0602438882458", - "0196922264863", - "8809903921786", - "0888750652010", - "0602577420283", - "0194398186313", - "8809634387042", - "0602557611755", - "0196922575761", - "0196922597589", - "0196922330575", - "3700551782314", - "8804775056895", - "3700187680121", - "0196922266096", - "0196587035426", - "8809634386403", - "0190295049423", - "0194399913529", - "0196922330179", - "0602537183968", - "9700000387989", - "8809440338092", - "0602577627866", - "0196587397111", - "0602567749967", - "0196922401688", - "8804775051135", - "8809848758058", - "0194399008126", - "3700187681418", - "0196922462016", - "0602577393471", - "0602577597244", - "0602508556517", - "9700000363273", - "0190295344467", - "0190759306123", - "3701216806123", - "8804775066856", - "3596972473029", - "0602547300683", - "0196587214524", - "8809440338238", - "8809269509154", - "8809634380036", - "0889854467517", - "0602455678249", - "0602567971092", - "8809848751110", - }, - EAN_CAT.VINYLES: { - "0889854690519", - "0602527594934", - "9700000387811", - "0602547311009", - "0602448591951", - "3700187671259", - "0602445638895", - "0194399974810", - "0190295385606", - "0602557919486", - "3700551784660", - "0602547306777", - "0196587196714", - "0190295194239", - "0602567971665", - "0600753030523", - "5054197427862", - "0093624904236", - "5099902987613", - "5054197404801", - "0602557315615", - "5054197307379", - "5060525435683", - "3596974251267", - "0194397116816", - "0602435450902", - "0600753511060", - "3700551783083", - "0720642442517", - "3596974043169", - "0602527950891", - "0602435489834", - "0075678893032", - "9700000371421", - "0093624738619", - "0602577427664", - "0888915663776", - "0602438106417", - "0602527934242", - "0602557618280", - "0602517341289", - "0602465364613", - "0075678637513", - "0602508148453", - "0602448161406", - "0600753454589", - "0602557589962", - "0190295472719", - "0190295076139", - "0602435973548", - "0602557048445", - "0602508648229", - "0196587220518", - "3700551782888", - "0602445643851", - "0602537874484", - "0842812106729", - "0602577656897", - "0888837168618", - "0196588460319", - "0602458163667", - "0060250881840", - "0602557048414", - "0602508818400", - "0606949028718", - "0602508822780", - "3596974250468", - "3700187682002", - "0194397051414", - "3700551782192", - "0720841214618", - "3700187671266", - "0190295276324", - "0602567555780", - "5054197498350", - "3283451235727", - "0190759652213", - "0887828031719", - "0602455816818", - "0194399166413", - "3700187671273", - "0602547379184", - "0190295446802", - "0602438590148", - "0602577820298", - "0190296617164", - "0600753822005", - "0196587737313", - "3596974078666", - "0196588151613", - "0602508409400", - "3700551782413", - "0889854390310", - "0190758933719", - "0602557227512", - "0602435931975", - "3700551783076", - "0600753913079", - "0190758883618", - "0190296459054", - "0602465026276", - "0602455542144", - "0602508332456", - }, - EAN_CAT.EBOOKS: { - "9782378760786", - "9782824710808", - "9782755697483", - "9781781101087", - "9782381671321", - "9782755650426", - "9782017207627", - "9782258192331", - "9782755620849", - "9798546545420", - "9782755625684", - "9782755663464", - "9791032711866", - "3760264231530", - "9781781101049", - "9782017207801", - "9782823875898", - "9782755690460", - "9781781101032", - "9791040113386", - "9782378910372", - "9782075067102", - "9781781101070", - "9782016273364", - "9782226432339", - "9782017243366", - "9782815314480", - "9782221250884", - "9782755649895", - "9782017184690", - "9782017218876", - "9782072446597", - "9782226448613", - "9781781101056", - "9782290131558", - " 9782378761585", - "9782755625516", - "9782755650372", - "9782290383520", - "9782290131619", - "9782081245792", - "9782755646207", - "9781781101094", - "9782344055038", - "9782755620030", - "9782755630756", - "9782017078432", - "9782709660266", - "9781781101063", - "9782755621204", - "9782290393017", - "9782755697391", - "9782377174911", - "9782841235636", - "9782211237789", - "9782755697810", - "9782221266687", - "9782290256343", - "9798679880795", - "9782290131589", - "9782290366899", - "9781729152744", - "9782755650617", - "9782317021237", - "9782381511078", - "9782011613479", - "9782317016059", - "9782290393314", - "9782811673482", - "3760264231431", - "9782317025006", - "9782213707877", - "9782368010013", - "9782382670385", - "9782755684339", - "9782749952352", - "9782490921034", - "9782755651072", - "9782017219101", - "9782246815822", - "9782755620023", - "9782755650150", - "9782290380550", - "9782092576748", - "9780857895264", - "9782290131466", - "9782381511306", - "9782381511276", - "9791040802747", - "9782290131527", - "9782017078937", - "9782755645989", - "9782317015915", - "9782884717076", - "9782368122747", - }, - EAN_CAT.ELIGIBLE_BOOKS: { - "9782811618803", - "9782752400130", - "9786035011471", - "9782380711509", - "9782755696073", - "9782017206965", - "9791032705544", - "9782809482324", - "9782826035831", - "9782723489928", - "9782752402998", - "9782381222738", - "9782811617240", - "9782379891465", - "9782380710250", - "9782380710243", - "9782916457383", - "9782755664539", - "9782811615154", - "9782809493900", - "9782853008884", - "9782809849899", - "9782081240254", - "9781405291750", - "9781398515628", - "9791092928143", - "9782811613297", - "9782849336212", - "9782809476903", - "9782811618360", - "9782266192415", - "9782809482317", - "9782755664607", - "9782017207030", - "9782811618810", - "9782070325030", - "9791032706671", - "9782723489898", - "9782914483902", - "9782608122278", - "9782247204908", - "9782811620943", - "9782723450997", - "9782608122315", - "9782290028827", - "9782380712605", - "9782895761808", - "9782266268554", - "9782811611705", - "9782809492491", - "9782809477542", - "9782940335824", - "9782200619527", - "9782723449045", - "9782382880296", - "9782070360024", - "9782130789277", - "9782811614355", - "9782381223551", - "9782820340542", - "9798721009792", - "9782382880302", - "9791032711194", - "9791032706688", - "9782809495430", - "9791032707517", - "9782811644574", - "9782264049063", - "9782811612818", - "9782826036210", - "9782809476132", - "9782956947981", - "9782344049020", - "9782723488525", - "9782608123015", - "9782344047576", - "9782940335770", - "9782494885011", - "9782811612207", - "9782711035687", - "9782344052143", - "9782380711486", - "9791032707630", - "9782811642204", - "9782266204972", - "9782916457376", - "9791032707883", - "9782723489911", - "9782365262583", - "9782755670356", - "9782070469826", - "9782809490084", - "9782723450980", - "9782723489904", - "9782841614363", - "9782380711479", - "9782723449052", - "9782889130696", - "9782290258064", - "9782811615994", - "9791032707821", - "9782608122261", - "9782608128072", - "9782841615209", - "9782811615628", - "9782266229487", - "9782608129086", - "9782809491616", - "9782608129109", - "9782723450973", - "9791032706565", - "9782811611699", - "9782266278638", - "9782755633832", - "9782356140555", - "9791032705537", - "9791032706343", - "9782863145005", - "9782914483872", - }, - EAN_CAT.UNELIGIBLE_BOOKS: { - # early childhood books - "9782017143741", - "9782017217404", - "9782017237280", - "9782075165419", - "9782092496923", - "9782095018306", - "9782203232648", - "9782211304153", - "9782211304214", - "9782215160502", - "9782244403519", - "9782244409023", - "9782324030437", - "9782324032318", - "9782330118730", - "9782354816544", - "9782359907377", - "9782359907759", - "9782379700651", - "9782383070443", - "9782383070450", - "9782493290168", - "9782493290182", - "9782508052477", - "9782733895818", - "9782809681857", - "9791027604654", - "9791036304811", - "9791036346149", - "9791036356186", - # school books - "9782017151029", - "9782017183822", - "9782017874126", - "9782091674230", - "9782091674988", - "9782091676067", - "9782092496350", - "9782092496619", - "9782095017651", - "9782095021443", - "9782212573220", - "9782311214987", - "9782321018810", - "9782321018827", - "9782321018834", - "9782340070134", - "9782354971588", - "9782362462559", - "9782362463440", - "9782362463952", - "9782375637517", - "9782381972633", - "9782490102389", - "9782606016890", - "9782753115811", - "9782753115828", - "9782753115835", - "9782758151647", - "9782759314010", - "9782822307710", - # extracurricular books - "9782017153146", - "9782036021853", - "9782091655017", - "9782095016692", - "9782095025823", - "9782140328671", - "9782210750975", - "9782210754119", - "9782210754959", - "9782210756786", - "9782210758810", - "9782210759176", - "9782210777569", - "9782218963100", - "9782321018391", - "9782367040110", - "9782384170005", - "9782401098466", - "9782700507010", - "9782700508321", - "9782700508758", - "9782700570892", - "9782710146544", - "9782710146674", - "9782710146704", - "9782759045334", - "9782759050161", - "9791028501846", - "9791028524449", - "9791035822767", - }, -} diff --git a/api/tests/core/mails/transactional/bookings/booking_expiration_to_beneficiary_test.py b/api/tests/core/mails/transactional/bookings/booking_expiration_to_beneficiary_test.py index f1cd8bd62de..f2b6b4b28f7 100644 --- a/api/tests/core/mails/transactional/bookings/booking_expiration_to_beneficiary_test.py +++ b/api/tests/core/mails/transactional/bookings/booking_expiration_to_beneficiary_test.py @@ -66,7 +66,7 @@ def test_should_get_correct_data_when_expired_bookings_cancelled(self): now = datetime.utcnow() amnesiac_user = users_factories.BeneficiaryGrant18Factory(email="dory@example.com", firstName="Dory") long_ago = now - timedelta(days=31) - dvd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) + dvd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id) expired_today_dvd_booking = CancelledBookingFactory( stock__offer__product=dvd, stock__offer__name="Memento", diff --git a/api/tests/core/offers/test_factories.py b/api/tests/core/offers/test_factories.py index a8722afc6d8..2877b96da90 100644 --- a/api/tests/core/offers/test_factories.py +++ b/api/tests/core/offers/test_factories.py @@ -115,8 +115,10 @@ def test_generate_book_extra_data(self): assert re.match(r"\d{13}", book_product.extraData.get("ean")) assert book_product.extraData.get("gtl_id") in GTLS - def test_generate_concert_extra_data(self): - concert_product = ProductFactory(subcategoryId=subcategories.CONCERT.id, set_all_fields=True) + def test_generate_CDs_extra_data(self): + concert_product = ProductFactory( + subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, set_all_fields=True + ) assert concert_product.extraData is not None assert isinstance(concert_product.extraData.get("author"), str) @@ -131,19 +133,20 @@ def test_generate_concert_extra_data(self): assert music_sub_type_code == -1 or music_sub_type in music_type.children - def test_generate_spectacle_representation_extra_data(self): - concert_product = ProductFactory(subcategoryId=subcategories.SPECTACLE_REPRESENTATION.id, set_all_fields=True) + def test_generate_vinyles_extra_data(self): + concert_product = ProductFactory( + subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id, set_all_fields=True + ) assert concert_product.extraData is not None assert isinstance(concert_product.extraData.get("author"), str) - assert isinstance(concert_product.extraData.get("stageDirector"), str) assert isinstance(concert_product.extraData.get("performer"), str) - show_type_code = int(concert_product.extraData.get("showType")) - show_type = show_types.SHOW_TYPES_BY_CODE.get(show_type_code) - assert show_type_code in show_types.SHOW_TYPES_BY_CODE + music_type_code = int(concert_product.extraData.get("musicType")) + music_type = music_types.MUSIC_TYPES_BY_CODE.get(music_type_code) + assert music_type_code in music_types.MUSIC_TYPES_BY_CODE - show_sub_type_code = int(concert_product.extraData.get("showSubType")) - show_sub_type = show_types.SHOW_SUB_TYPES_BY_CODE.get(show_sub_type_code) + music_sub_type_code = int(concert_product.extraData.get("musicSubType")) + music_sub_type = music_types.MUSIC_SUB_TYPES_BY_CODE.get(music_sub_type_code) - assert show_sub_type_code == -1 or show_sub_type in show_type.children + assert music_sub_type_code == -1 or music_sub_type in music_type.children diff --git a/api/tests/local_providers/local_provider_test.py b/api/tests/local_providers/local_provider_test.py index 21796657987..fe5852e6b7a 100644 --- a/api/tests/local_providers/local_provider_test.py +++ b/api/tests/local_providers/local_provider_test.py @@ -75,7 +75,7 @@ def test_updates_existing_object(self, next_function): lastProvider=provider, idAtProviders=providable_info.id_at_providers, name="Old product name", - subcategoryId=subcategories.ACHAT_INSTRUMENT.id, + subcategoryId=subcategories.LIVRE_PAPIER.id, ) local_provider = provider_test_utils.TestLocalProvider() next_function.side_effect = [[providable_info]] @@ -98,7 +98,7 @@ def test_does_not_update_existing_object_when_date_is_older_than_last_modified_d lastProvider=provider, idAtProviders=providable_info.id_at_providers, name="Old product name", - subcategoryId=subcategories.ACHAT_INSTRUMENT.id, + subcategoryId=subcategories.LIVRE_PAPIER.id, ) local_provider = provider_test_utils.TestLocalProvider() next_function.side_effect = [[providable_info]] @@ -217,7 +217,7 @@ def test_returns_object_with_expected_attributes(self): providable_info = ProvidableInfo() product = offers_factories.ThingProductFactory( name="Old product name", - subcategoryId=subcategories.ACHAT_INSTRUMENT.id, + subcategoryId=subcategories.LIVRE_PAPIER.id, idAtProviders=providable_info.id_at_providers, lastProvider=provider, ) diff --git a/api/tests/routes/native/v1/offers_test.py b/api/tests/routes/native/v1/offers_test.py index e7ec1efe060..a27fd8ce5bc 100644 --- a/api/tests/routes/native/v1/offers_test.py +++ b/api/tests/routes/native/v1/offers_test.py @@ -252,7 +252,7 @@ def test_get_event_offer(self, client): assert response.json["withdrawalDetails"] == "modalité de retrait" def test_get_offer_with_unlimited_stock(self, client): - product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(thumbCount=1) offer = offers_factories.OfferFactory(product=product, venue__isPermanent=True) offers_factories.ThingStockFactory(offer=offer, price=12.34, quantity=None) @@ -266,10 +266,7 @@ def test_get_offer_with_unlimited_stock(self, client): assert response.json["stocks"][0]["remainingQuantity"] is None def test_get_thing_offer(self, client): - product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) - offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id - ) + offer = offers_factories.OfferFactory(venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id) offers_factories.ThingStockFactory(offer=offer, price=12.34) offer_id = offer.id @@ -625,12 +622,12 @@ def should_not_update_offer_stocks_when_getting_offer(self, client): assert len(offer.stocks) == 2 def test_get_offer_with_product_mediation_and_thumb(self, client): - product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.LIVRE_PAPIER.id) offers_factories.ProductMediationFactory( product=product, url="https://url.com", imageType=TiteliveImageType.RECTO ) offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id + product=product, venue__isPermanent=True, subcategoryId=subcategories.LIVRE_PAPIER.id ) offers_factories.ThingStockFactory(offer=offer, price=12.34) @@ -646,7 +643,7 @@ def test_get_offer_with_product_mediation_and_thumb(self, client): } def test_get_offer_with_two_product_mediation(self, client): - product = offers_factories.ProductFactory(thumbCount=0, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(thumbCount=0, subcategoryId=subcategories.LIVRE_PAPIER.id) offers_factories.ProductMediationFactory( product=product, url="https://url.com/recto", imageType=TiteliveImageType.RECTO ) @@ -654,7 +651,7 @@ def test_get_offer_with_two_product_mediation(self, client): product=product, url="https://url.com/verso", imageType=TiteliveImageType.VERSO ) offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id + product=product, venue__isPermanent=True, subcategoryId=subcategories.LIVRE_PAPIER.id ) offers_factories.ThingStockFactory(offer=offer, price=12.34) @@ -670,9 +667,9 @@ def test_get_offer_with_two_product_mediation(self, client): } def test_get_offer_with_thumb_only(self, client): - product = offers_factories.ProductFactory(id=111, thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(id=111, thumbCount=1, subcategoryId=subcategories.LIVRE_PAPIER.id) offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id + product=product, venue__isPermanent=True, subcategoryId=subcategories.LIVRE_PAPIER.id ) offers_factories.ThingStockFactory(offer=offer, price=12.34) @@ -688,12 +685,12 @@ def test_get_offer_with_thumb_only(self, client): } def test_get_offer_with_mediation_and_product_mediation(self, client): - product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.LIVRE_PAPIER.id) offers_factories.ProductMediationFactory( product=product, url="https://url.com", imageType=TiteliveImageType.RECTO ) offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id + product=product, venue__isPermanent=True, subcategoryId=subcategories.LIVRE_PAPIER.id ) offers_factories.ThingStockFactory(offer=offer, price=12.34) offers_factories.MediationFactory(id=111, offer=offer, thumbCount=2, credit="street credit") @@ -929,7 +926,7 @@ def test_get_event_offer(self, client): assert response.json["withdrawalDetails"] == "modalité de retrait" def test_get_offer_with_unlimited_stock(self, client): - product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.LIVRE_PAPIER.id) offer = offers_factories.OfferFactory(product=product, venue__isPermanent=True) offers_factories.ThingStockFactory(offer=offer, price=12.34, quantity=None) @@ -941,10 +938,7 @@ def test_get_offer_with_unlimited_stock(self, client): assert response.json["stocks"][0]["remainingQuantity"] is None def test_get_thing_offer(self, client): - product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) - offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id - ) + offer = offers_factories.OfferFactory(venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id) offers_factories.ThingStockFactory(offer=offer, price=12.34) offer_id = offer.id @@ -1453,12 +1447,12 @@ def should_not_update_offer_stocks_when_getting_offer(self, client): assert len(offer.stocks) == 2 def test_get_offer_with_product_mediation_and_thumb(self, client): - product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.LIVRE_PAPIER.id) offers_factories.ProductMediationFactory( product=product, url="https://url.com", imageType=TiteliveImageType.RECTO ) offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id + product=product, venue__isPermanent=True, subcategoryId=subcategories.LIVRE_PAPIER.id ) offers_factories.ThingStockFactory(offer=offer, price=12.34) @@ -1475,7 +1469,7 @@ def test_get_offer_with_product_mediation_and_thumb(self, client): } def test_get_offer_with_two_product_mediation(self, client): - product = offers_factories.ProductFactory(thumbCount=0, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(thumbCount=0, subcategoryId=subcategories.LIVRE_PAPIER.id) offers_factories.ProductMediationFactory( product=product, url="https://url.com/recto", imageType=TiteliveImageType.RECTO ) @@ -1483,7 +1477,7 @@ def test_get_offer_with_two_product_mediation(self, client): product=product, url="https://url.com/verso", imageType=TiteliveImageType.VERSO ) offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id + product=product, venue__isPermanent=True, subcategoryId=subcategories.LIVRE_PAPIER.id ) offers_factories.ThingStockFactory(offer=offer, price=12.34) @@ -1504,9 +1498,9 @@ def test_get_offer_with_two_product_mediation(self, client): } def test_get_offer_with_thumb_only(self, client): - product = offers_factories.ProductFactory(id=111, thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(id=111, thumbCount=1, subcategoryId=subcategories.LIVRE_PAPIER.id) offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id + product=product, venue__isPermanent=True, subcategoryId=subcategories.LIVRE_PAPIER.id ) offers_factories.ThingStockFactory(offer=offer, price=12.34) @@ -1523,12 +1517,12 @@ def test_get_offer_with_thumb_only(self, client): } def test_get_offer_with_mediation_and_product_mediation(self, client): - product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.CARTE_MUSEE.id) + product = offers_factories.ProductFactory(thumbCount=1, subcategoryId=subcategories.LIVRE_PAPIER.id) offers_factories.ProductMediationFactory( product=product, url="https://url.com", imageType=TiteliveImageType.RECTO ) offer = offers_factories.OfferFactory( - product=product, venue__isPermanent=True, subcategoryId=subcategories.CARTE_MUSEE.id + product=product, venue__isPermanent=True, subcategoryId=subcategories.LIVRE_PAPIER.id ) offers_factories.ThingStockFactory(offer=offer, price=12.34) offers_factories.MediationFactory(id=111, offer=offer, thumbCount=2, credit="street credit") diff --git a/api/tests/routes/public/individual_offers/v1/get_eans_availability_test.py b/api/tests/routes/public/individual_offers/v1/get_eans_availability_test.py index a59e7e7107f..dbd7e6e3361 100644 --- a/api/tests/routes/public/individual_offers/v1/get_eans_availability_test.py +++ b/api/tests/routes/public/individual_offers/v1/get_eans_availability_test.py @@ -34,7 +34,7 @@ def test_should_return_eans_ordered_by_availability(self, client: TestClient): # Invalid EAN because of subcategory invalid_ean_because_not_in_allowed_subcategory = "2234567890123" offers_factories.ProductFactory( - subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id, + subcategoryId=subcategories.SEANCE_CINE.id, name="Les 3000 mousquetaires contre Goldorak (collection Art & Essai)", extraData={ "ean": invalid_ean_because_not_in_allowed_subcategory, diff --git a/api/tests/scripts/booking/handle_expired_bookings_test.py b/api/tests/scripts/booking/handle_expired_bookings_test.py index e33305ae654..ad3b1b438ae 100644 --- a/api/tests/scripts/booking/handle_expired_bookings_test.py +++ b/api/tests/scripts/booking/handle_expired_bookings_test.py @@ -126,9 +126,9 @@ def test_handle_expired_bookings_should_cancel_expired_individual_bookings(self, now = datetime.utcnow() two_months_ago = now - timedelta(days=60) - dvd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) + cd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_CD.id) expired_individual_booking = booking_factories.BookingFactory( - stock__offer__product=dvd, dateCreated=two_months_ago + stock__offer__product=cd, dateCreated=two_months_ago ) book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id) @@ -240,9 +240,9 @@ def should_notify_of_todays_expired_bookings(self, app) -> None: yesterday = now - timedelta(days=1) long_ago = now - timedelta(days=31) very_long_ago = now - timedelta(days=32) - dvd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) - expired_today_dvd_booking = booking_factories.CancelledBookingFactory( - stock__offer__product=dvd, + vinyle = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id) + expired_today_vinyle_booking = booking_factories.CancelledBookingFactory( + stock__offer__product=vinyle, dateCreated=long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, ) @@ -252,9 +252,9 @@ def should_notify_of_todays_expired_bookings(self, app) -> None: dateCreated=long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, ) - painting = ProductFactory(subcategoryId=subcategories.OEUVRE_ART.id) + book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id) booking_factories.CancelledBookingFactory( - stock__offer__product=painting, + stock__offer__product=book, dateCreated=very_long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, cancellationDate=yesterday, @@ -268,13 +268,13 @@ def should_notify_of_todays_expired_bookings(self, app) -> None: (outbox[1]["To"], outbox[1]["params"]["BOOKINGS"][0]["offer_name"]), } - dvd_user_email = expired_today_dvd_booking.user.email - dvd_offer_name = expired_today_dvd_booking.stock.offer.name + vinyle_user_email = expired_today_vinyle_booking.user.email + vinyle_offer_name = expired_today_vinyle_booking.stock.offer.name cd_user_email = expired_today_cd_booking.user.email cd_offer_name = expired_today_cd_booking.stock.offer.name - assert email_recaps == {(dvd_user_email, dvd_offer_name), (cd_user_email, cd_offer_name)} + assert email_recaps == {(vinyle_user_email, vinyle_offer_name), (cd_user_email, cd_offer_name)} class NotifyOfferersOfExpiredBookingsTest: @@ -284,9 +284,9 @@ def test_should_notify_of_todays_expired_individual_bookings(self, mocked_send_e yesterday = now - timedelta(days=1) long_ago = now - timedelta(days=31) very_long_ago = now - timedelta(days=32) - dvd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) - expired_today_dvd_booking = booking_factories.CancelledBookingFactory( - stock__offer__product=dvd, + vinyle = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id) + expired_today_vinyle_booking = booking_factories.CancelledBookingFactory( + stock__offer__product=vinyle, dateCreated=long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, ) @@ -296,9 +296,9 @@ def test_should_notify_of_todays_expired_individual_bookings(self, mocked_send_e dateCreated=long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, ) - painting = ProductFactory(subcategoryId=subcategories.OEUVRE_ART.id) + book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id) _expired_yesterday_booking = booking_factories.CancelledBookingFactory( - stock__offer__product=painting, + stock__offer__product=book, dateCreated=very_long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, cancellationDate=yesterday, @@ -308,8 +308,8 @@ def test_should_notify_of_todays_expired_individual_bookings(self, mocked_send_e assert mocked_send_email_recap.call_count == 2 assert mocked_send_email_recap.call_args_list[0][0] == ( - expired_today_dvd_booking.offerer, - [expired_today_dvd_booking], + expired_today_vinyle_booking.offerer, + [expired_today_vinyle_booking], ) assert mocked_send_email_recap.call_args_list[1][0] == ( expired_today_cd_booking.offerer, diff --git a/api/tests/scripts/booking/notify_soon_to_be_expired_bookings_test.py b/api/tests/scripts/booking/notify_soon_to_be_expired_bookings_test.py index 79c10cbadfd..c9fb701165f 100644 --- a/api/tests/scripts/booking/notify_soon_to_be_expired_bookings_test.py +++ b/api/tests/scripts/booking/notify_soon_to_be_expired_bookings_test.py @@ -22,9 +22,9 @@ def should_call_email_service_for_individual_bookings_which_will_expire_in_7_day booking_date_23_days_ago = now - timedelta(days=23) booking_date_22_days_ago = now - timedelta(days=22) - dvd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) + vinyle = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_VINYLE.id) expire_in_7_days_dvd_individual_booking = BookingFactory( - stock__offer__product=dvd, + stock__offer__product=vinyle, dateCreated=booking_date_23_days_ago, ) non_expired_cd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_CD.id) diff --git a/api/tests/scripts/integration/__init__.py b/api/tests/scripts/integration/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/api/tests/scripts/integration/add_eans_test.py b/api/tests/scripts/integration/add_eans_test.py deleted file mode 100644 index 5761a51186e..00000000000 --- a/api/tests/scripts/integration/add_eans_test.py +++ /dev/null @@ -1,96 +0,0 @@ -from contextlib import suppress - -import pytest - -import pcapi.core.categories.subcategories_v2 as subcategories -from pcapi.core.offers.factories import ProductFactory -from pcapi.core.offers.models import Product -from pcapi.scripts.integration.add_eans import fill_missing_eans -from pcapi.scripts.integration.eans_data import EANS -from pcapi.scripts.integration.eans_data import EAN_CAT - - -pytestmark = pytest.mark.usefixtures("db_session") - - -@pytest.fixture(name="cds") -def cds_fixture(): - eans = list(EANS[EAN_CAT.CDS])[:2] - return [ - ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, extraData={"ean": eans[0]}), - ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE_CD.id, extraData={"ean": eans[1]}), - ] - - -@pytest.fixture(name="ebooks") -def ebooks_fixture(): - eans = list(EANS[EAN_CAT.EBOOKS])[:2] - return [ - ProductFactory(subcategoryId=subcategories.LIVRE_NUMERIQUE.id, extraData={"ean": eans[0]}), - ProductFactory(subcategoryId=subcategories.LIVRE_NUMERIQUE.id, extraData={"ean": eans[1]}), - ] - - -class FillMissingEANsTest: - def test_with_no_products_at_all(self): - fill_missing_eans() - - assert_products_count() - assert_eans() - - def test_some_eans_already_exists(self, cds, ebooks): - fill_missing_eans() - - assert_products_count() - assert_eans() - - def test_some_eans_exists_next_to_unrelated_products(self, cds, ebooks): - subcategory_id = subcategories.SUPPORT_PHYSIQUE_FILM.id - products = [ - ProductFactory(subcategoryId=subcategory_id, extraData={"ean": "001122334455"}), - ProductFactory(subcategoryId=subcategory_id, extraData={"ean": "667788990011"}), - ] - - fill_missing_eans() - - assert_products_count(products) - assert_eans(products) - - def test_some_eans_exists_next_to_unrelated_products_without_eans(self, cds, ebooks): - products = [ - # first, create with none value, then remove whole extraData - # otherwise, the factory would create some random extraData - ProductFactory(subcategoryId=subcategories.LOCATION_INSTRUMENT.id, extraData={"ean": None}), - ProductFactory(subcategoryId=subcategories.LOCATION_INSTRUMENT.id, extraData={"ean": None}), - ] - - for product in products: - product.extraData = None - - fill_missing_eans() - - assert_products_count(products) - assert_eans() - - -def assert_products_count(extra_expected=None): - extra_expected = extra_expected or [] - - found_products = Product.query.all() - assert len(found_products) == sum(len(eans) for eans in EANS.values()) + len(extra_expected) - - -def assert_eans(extra_expected=None): - if extra_expected is not None: - extra_expected = {p.extraData["ean"] for p in extra_expected} - else: - extra_expected = set() - - found_products = Product.query.all() - found_eans = set() - - for product in found_products: - with suppress(TypeError, KeyError): - found_eans.add(product.extraData["ean"]) - - assert found_eans == {ean for eans in EANS.values() for ean in eans} | extra_expected