Skip to content
Merged
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
15 changes: 10 additions & 5 deletions services/ps_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,15 +292,20 @@ def best_ps_id(region_code: str, ps_ids: dict[str, str]) -> str | None:
return next((pid for pid in ps_ids.values() if pid.startswith(preferred)), None)


_PURCHASE_CTA_TYPES = frozenset({"ADD_TO_CART", "PREORDER"})

# Returns the price dict for the first outright purchase CTA, or None if the game
# is unavailable in the region (UNAVAILABLE type) or only free/PS Plus options exist.
# PREORDER is treated identically to ADD_TO_CART — pre-order prices are real prices.
def _outright_price(webctas: list[dict]) -> dict | None:
for cta in webctas:
if cta.get("type") == "ADD_TO_CART":
if (cta.get("meta") or {}).get("upSellService") == "NONE":
price = cta.get("price")
if not (price or {}).get("isFree"):
return price
if cta.get("type") not in _PURCHASE_CTA_TYPES:
continue
if (cta.get("meta") or {}).get("upSellService") not in ("NONE", None):
continue
price = cta.get("price")
if price and not price.get("isFree"):
return price
return None


Expand Down
57 changes: 57 additions & 0 deletions tests/unit/test_ps_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,63 @@ async def test_get_game_info_skips_free_trial_cta(make_mock_store):
assert price.currency == "¥"


# --- pre-order ---

PRE_ORDER_PS_ID = "UP9000-PPSA03671_00-MARVELSWOLVERINE"


def _preorder_gql(ps_id: str, base: int = 6999, discounted: int | None = None, currency: str = "USD") -> dict:
return {"data": {"productRetrieve": {"concept": {"products": [{
"id": ps_id,
"name": "Marvel's Wolverine",
"platforms": ["PS5"],
"storeDisplayClassification": "FULL_GAME",
"media": [],
"webctas": [{
"type": "PREORDER",
"meta": {"upSellService": "NONE"},
"price": {
"isFree": False,
"basePriceValue": base,
"discountedValue": discounted if discounted is not None else base,
"currencyCode": currency,
},
}],
}]}}}}


@pytest.mark.asyncio
async def test_get_game_info_preorder_returns_game(make_mock_store):
make_mock_store(_preorder_gql(PRE_ORDER_PS_ID))
result = await get_game_info(PRE_ORDER_PS_ID, "en-us")
assert result is not None
game, _ = result
assert game.title == "Marvel's Wolverine"
assert game.type == "FULL_GAME"


@pytest.mark.asyncio
async def test_get_game_info_preorder_price(make_mock_store):
make_mock_store(_preorder_gql(PRE_ORDER_PS_ID, base=6999, currency="USD"))
result = await get_game_info(PRE_ORDER_PS_ID, "en-us")
assert result is not None
_, price = result
assert price.price == 69.99
assert price.currency == "$"
assert price.base_price is None


@pytest.mark.asyncio
async def test_get_game_info_preorder_discount(make_mock_store):
"""Pre-order early-bird discount: discountedValue < basePriceValue."""
make_mock_store(_preorder_gql(PRE_ORDER_PS_ID, base=6999, discounted=4999, currency="USD"))
result = await get_game_info(PRE_ORDER_PS_ID, "en-us")
assert result is not None
_, price = result
assert price.price == 49.99
assert price.base_price == 69.99


# --- ps_id_suffix ---

def test_ps_id_suffix_standard():
Expand Down
Loading