Compare commits

..
2 Commits
3 changed files with 71 additions and 3 deletions

No files matched your search

+14
View File
@@ -97,6 +97,16 @@ class ProductMetadata:
overstock_text: Overstock label text when present. overstock_text: Overstock label text when present.
percentage: Computed discount percentage. percentage: Computed discount percentage.
affiliate_url: Affiliate link when available. affiliate_url: Affiliate link when available.
promo_code: Event-level checkout code (e.g. "BIRTHDAY26") when the
product's event advertises one, else None.
promo_percentage: Advertised percent off from a percentage code
("extra 22% off" -> 22); None for dollar codes or no code. This is
the claimed discount, not the actual price delta.
promo_dollar_off: Advertised dollar amount off from a spend-threshold
code ("get an extra $22 off" -> 22); None for percentage codes or
no code. Pairs with promo_min_spend.
promo_min_spend: Spend threshold a dollar code requires ("Spend $100"
-> 100); None unless promo_dollar_off is set.
""" """
image_url: str | None = None image_url: str | None = None
@@ -106,6 +116,10 @@ class ProductMetadata:
overstock_text: str | None = None overstock_text: str | None = None
percentage: int | None = None percentage: int | None = None
affiliate_url: str | None = None affiliate_url: str | None = None
promo_code: str | None = None
promo_percentage: int | None = None
promo_dollar_off: int | None = None
promo_min_spend: int | None = None
@dataclass @dataclass
-1
View File
@@ -11,7 +11,6 @@ import random
from aioproxies import AioProxies from aioproxies import AioProxies
from aioweb import Response from aioweb import Response
from aioweb_tls import CurlCffi, TLSSession from aioweb_tls import CurlCffi, TLSSession
from monitor_utils.constants import CLIENT_IDENTIFIERS, RETRY_LIMIT, TIMEOUT_SECONDS from monitor_utils.constants import CLIENT_IDENTIFIERS, RETRY_LIMIT, TIMEOUT_SECONDS
+57 -2
View File
@@ -11,15 +11,16 @@ Product), which is why convert_product_to_mongo no longer coerces them itself.
from datetime import datetime from datetime import datetime
from monitor_utils.database import convert_product_to_mongo from monitor_utils.database import convert_product_to_mongo
from monitor_utils.models import PricingInfo, Product from monitor_utils.models import PricingInfo, Product, ProductMetadata
def _product(**pricing) -> Product: def _product(metadata: ProductMetadata | None = None, **pricing) -> Product:
return Product( return Product(
product_id="p1", product_id="p1",
title="Widget", title="Widget",
url="http://x/p1", url="http://x/p1",
pricing=PricingInfo(**pricing), pricing=PricingInfo(**pricing),
metadata=metadata or ProductMetadata(),
) )
@@ -46,3 +47,57 @@ def test_core_fields_map_through():
doc = convert_product_to_mongo(_product(original_price=200.0, current_price=150.0)) doc = convert_product_to_mongo(_product(original_price=200.0, current_price=150.0))
assert doc["title"] == "Widget" assert doc["title"] == "Widget"
assert doc["url"] == "http://x/p1" assert doc["url"] == "http://x/p1"
def test_promo_and_affiliate_fields_serialize():
"""promo specifics + affiliate url reach the document under camelCase keys"""
doc = convert_product_to_mongo(
_product(
metadata=ProductMetadata(
affiliate_url="http://aff/p1",
promo_code="BIRTHDAY26",
promo_percentage=22,
promo_dollar_off=None,
promo_min_spend=None,
),
original_price=200.0,
current_price=150.0,
)
)
assert doc["affiliateUrl"] == "http://aff/p1"
assert doc["promoCode"] == "BIRTHDAY26"
assert doc["promoPercentage"] == 22
assert doc["promoDollarOff"] is None
assert doc["promoMinSpend"] is None
def test_dollar_promo_fields_serialize():
"""a spend-threshold code stores amount + min spend, not a percentage"""
doc = convert_product_to_mongo(
_product(
metadata=ProductMetadata(
promo_code="STORE22",
promo_dollar_off=22,
promo_min_spend=100,
),
original_price=200.0,
current_price=150.0,
)
)
assert doc["promoCode"] == "STORE22"
assert doc["promoDollarOff"] == 22
assert doc["promoMinSpend"] == 100
assert doc["promoPercentage"] is None
def test_promo_fields_default_to_none():
"""a product with no promo still carries the keys as None (uniform doc shape)"""
doc = convert_product_to_mongo(_product(original_price=200.0, current_price=150.0))
for key in ("promoCode", "promoPercentage", "promoDollarOff", "promoMinSpend"):
assert doc[key] is None
# percentage and channelId stay OUT of the doc on purpose
assert "percentage" not in doc
assert "channelId" not in doc