Merge commit '4cf6f91e954b770198578bcb8db5d98ac964bfed' as 'common'
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
"""Generate Coupon seed data."""
|
||||
|
||||
import random
|
||||
import uuid
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
from faker import Faker
|
||||
|
||||
from cartsnitch_common.constants import DiscountType
|
||||
from cartsnitch_common.seed.config import (
|
||||
COUPON_EXPIRED_PCT,
|
||||
NUM_COUPONS,
|
||||
SEED_END_DATE,
|
||||
SEED_START_DATE,
|
||||
)
|
||||
|
||||
|
||||
def _decimal(val: float) -> Decimal:
|
||||
return Decimal(str(round(val, 2)))
|
||||
|
||||
|
||||
_COUPON_TITLES: list[str] = [
|
||||
"Save {val} on {product}",
|
||||
"{val} off your next {product} purchase",
|
||||
"Get {val} off {product}",
|
||||
"Buy {product}, save {val}",
|
||||
"Weekend special: {val} off {product}",
|
||||
"Member exclusive: {val} off {product}",
|
||||
"Digital coupon: {val} off {product}",
|
||||
]
|
||||
|
||||
|
||||
def generate_coupons(
|
||||
fake: Faker,
|
||||
products: list[dict],
|
||||
stores: list[dict],
|
||||
) -> list[dict]:
|
||||
"""Return NUM_COUPONS coupon records with realistic mix of active/expired."""
|
||||
now = datetime.now(tz=UTC)
|
||||
today = SEED_END_DATE
|
||||
coupons = []
|
||||
|
||||
num_expired = int(NUM_COUPONS * COUPON_EXPIRED_PCT)
|
||||
num_active = NUM_COUPONS - num_expired
|
||||
|
||||
def make_coupon(is_active: bool) -> dict:
|
||||
store = random.choice(stores)
|
||||
product = random.choice(products) if random.random() > 0.1 else None
|
||||
product_name = product["canonical_name"].split(" ", 2)[-1] if product else "any item"
|
||||
|
||||
discount_type = random.choice(list(DiscountType))
|
||||
|
||||
if discount_type == DiscountType.PERCENT:
|
||||
discount_value = _decimal(random.choice([5, 10, 15, 20, 25, 30]))
|
||||
title = f"Save {int(discount_value)}% on {product_name}"
|
||||
elif discount_type == DiscountType.FIXED:
|
||||
discount_value = _decimal(random.choice([0.50, 1.00, 1.50, 2.00, 2.50, 3.00, 5.00]))
|
||||
title = f"Save ${discount_value} on {product_name}"
|
||||
elif discount_type == DiscountType.BOGO:
|
||||
discount_value = None
|
||||
title = f"BOGO: Buy one {product_name}, get one free"
|
||||
else: # BUY_X_GET_Y
|
||||
discount_value = None
|
||||
title = f"Buy 2 {product_name}, get 1 free"
|
||||
|
||||
if is_active:
|
||||
valid_from = today - timedelta(days=random.randint(1, 30))
|
||||
valid_to = today + timedelta(days=random.randint(1, 60))
|
||||
else:
|
||||
valid_to = today - timedelta(days=random.randint(1, 180))
|
||||
valid_from = valid_to - timedelta(days=random.randint(7, 30))
|
||||
|
||||
requires_clip = random.random() > 0.5
|
||||
coupon_code = fake.bothify(text="??##-??##").upper() if not requires_clip else None
|
||||
min_purchase = _decimal(random.choice([0, 0, 0, 5.00, 10.00, 15.00])) or None
|
||||
|
||||
scraped_at = datetime(
|
||||
SEED_START_DATE.year, SEED_START_DATE.month, SEED_START_DATE.day, tzinfo=UTC
|
||||
) + timedelta(days=random.randint(0, 180))
|
||||
|
||||
return {
|
||||
"id": uuid.uuid4(),
|
||||
"store_id": store["id"],
|
||||
"normalized_product_id": product["id"] if product else None,
|
||||
"title": title,
|
||||
"description": fake.sentence(nb_words=10),
|
||||
"discount_type": discount_type,
|
||||
"discount_value": discount_value,
|
||||
"min_purchase": min_purchase,
|
||||
"valid_from": valid_from,
|
||||
"valid_to": valid_to,
|
||||
"requires_clip": requires_clip,
|
||||
"coupon_code": coupon_code,
|
||||
"source_url": None,
|
||||
"scraped_at": scraped_at,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
}
|
||||
|
||||
for _ in range(num_expired):
|
||||
coupons.append(make_coupon(is_active=False))
|
||||
for _ in range(num_active):
|
||||
coupons.append(make_coupon(is_active=True))
|
||||
|
||||
random.shuffle(coupons)
|
||||
return coupons
|
||||
Reference in New Issue
Block a user