Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| from datetime import UTC, datetime | |
| from pathlib import Path | |
| from app.config import Settings | |
| from app.pricing_engine import PricingEngine | |
| from app.schemas import KagglePricingRequest, OrderEvent, PricingRequest | |
| class _StaticSyntheticPipeline: | |
| def predict(self, _frame): | |
| return [200.0] | |
| class _StaticKagglePipeline: | |
| def predict(self, _frame): | |
| return [212.5] | |
| def _build_settings(tmp_path: Path) -> Settings: | |
| model_path = tmp_path / "model.joblib" | |
| metrics_path = tmp_path / "metrics.json" | |
| raw_data_path = tmp_path / "raw.csv" | |
| price_history_path = tmp_path / "history.csv" | |
| model_path.write_text("stub", encoding="utf-8") | |
| metrics_path.write_text("{}", encoding="utf-8") | |
| raw_data_path.write_text("", encoding="utf-8") | |
| return Settings( | |
| model_path=model_path, | |
| metrics_path=metrics_path, | |
| raw_data_path=raw_data_path, | |
| price_history_path=price_history_path, | |
| redis_url="", | |
| ) | |
| def test_synthetic_recommendation_applies_guardrails(monkeypatch, tmp_path: Path) -> None: | |
| monkeypatch.setattr( | |
| "app.pricing_engine.load_model_bundle", | |
| lambda _path: {"dataset_profile": "synthetic", "pipeline": _StaticSyntheticPipeline()}, | |
| ) | |
| engine = PricingEngine(_build_settings(tmp_path)) | |
| engine.competitor_client.get_price = lambda _sku_id, fallback_price: fallback_price | |
| result = engine.recommend_price( | |
| PricingRequest( | |
| sku_id="SKU-9", | |
| category="electronics", | |
| brand="brand_a", | |
| customer_segment="premium", | |
| hour_of_day=20, | |
| day_of_week=5, | |
| is_weekend=1, | |
| is_festival=1, | |
| inventory_level=10, | |
| inventory_days_cover=2.0, | |
| competitor_price=195.0, | |
| click_through_rate=0.08, | |
| conversion_rate=0.05, | |
| units_sold_last_5m=10, | |
| units_sold_last_1h=60, | |
| base_cost=100.0, | |
| current_price=130.0, | |
| ) | |
| ) | |
| assert result.response.recommended_price == 175.5 | |
| assert result.response.flash_sale_multiplier == 1.0 | |
| assert result.response.inventory_adjustment == 1.1 | |
| assert result.response.demand_adjustment == 1.11 | |
| def test_flash_sale_detection_activates_multiplier(monkeypatch, tmp_path: Path) -> None: | |
| monkeypatch.setattr( | |
| "app.pricing_engine.load_model_bundle", | |
| lambda _path: {"dataset_profile": "synthetic", "pipeline": _StaticSyntheticPipeline()}, | |
| ) | |
| engine = PricingEngine(_build_settings(tmp_path)) | |
| engine.competitor_client.get_price = lambda _sku_id, fallback_price: fallback_price | |
| now = datetime.now(UTC) | |
| for _ in range(engine.settings.flash_sale_order_threshold): | |
| engine.register_order_event(OrderEvent(sku_id="SKU-1", quantity=1, event_time=now)) | |
| result = engine.recommend_price( | |
| PricingRequest( | |
| sku_id="SKU-1", | |
| category="electronics", | |
| brand="brand_a", | |
| customer_segment="premium", | |
| hour_of_day=20, | |
| day_of_week=5, | |
| is_weekend=1, | |
| is_festival=0, | |
| inventory_level=50, | |
| inventory_days_cover=8.0, | |
| competitor_price=200.0, | |
| click_through_rate=0.06, | |
| conversion_rate=0.05, | |
| units_sold_last_5m=8, | |
| units_sold_last_1h=50, | |
| base_cost=100.0, | |
| current_price=150.0, | |
| ) | |
| ) | |
| assert result.response.detected_flash_sale is True | |
| assert result.response.flash_sale_multiplier == 1.12 | |
| def test_kaggle_recommendation_uses_current_and_competitor_context( | |
| monkeypatch, tmp_path: Path | |
| ) -> None: | |
| monkeypatch.setattr( | |
| "app.pricing_engine.load_model_bundle", | |
| lambda _path: {"dataset_profile": "kaggle_retail", "pipeline": _StaticKagglePipeline()}, | |
| ) | |
| engine = PricingEngine(_build_settings(tmp_path)) | |
| result = engine.recommend_kaggle_price( | |
| KagglePricingRequest( | |
| product_id="P-55", | |
| product_category_name="home", | |
| qty=12, | |
| freight_price=4.5, | |
| product_name_lenght=24, | |
| product_description_lenght=90, | |
| product_photos_qty=3, | |
| product_weight_g=700, | |
| product_score=4.4, | |
| customers=8, | |
| weekday=2, | |
| weekend=0, | |
| holiday=0, | |
| volume=6480, | |
| comp_1=208.0, | |
| ps1=4.0, | |
| fp1=5.0, | |
| comp_2=210.0, | |
| ps2=4.1, | |
| fp2=5.0, | |
| comp_3=206.0, | |
| ps3=4.2, | |
| fp3=6.0, | |
| lag_price=198.0, | |
| month=4, | |
| year=2026, | |
| current_price=199.0, | |
| ) | |
| ) | |
| assert result.response.recommended_price == 212.5 | |
| assert result.response.gap_to_current_price == 13.5 | |
| assert result.response.competitor_anchor_price == 208.0 | |
| assert "current price" in result.response.reason | |