import pytest from datetime import date from types import SimpleNamespace from room_cal.discount import DiscountData, DiscountType from room_cal.pricing import CalPrice from room_cal.pricing.price_calendar import PriceData from room_cal.rules.discount.min_price import RULE_NAME, run def _stub_prices(monkeypatch, bases: dict[date, int]): async def _get(self, start_date, end_date): return {str(d): PriceData(base=base, net=base) for d, base in bases.items()} monkeypatch.setattr(CalPrice, 'get', _get) def _stub_config(monkeypatch, min_net: int): cfg = SimpleNamespace(rules=SimpleNamespace(min_price=SimpleNamespace(min_net=min_net))) monkeypatch.setattr('room_cal.rules.discount.min_price.get_config', lambda: cfg) def test_rule_registered(): assert RULE_NAME == 'min_price' @pytest.mark.asyncio async def test_empty_input_returns_empty(): assert await run(date(2026, 1, 1), date(2026, 1, 1), {}) == {} @pytest.mark.asyncio async def test_percent_discount_clamped_to_floor(monkeypatch): d = date(2026, 1, 10) _stub_prices(monkeypatch, {d: 100}) _stub_config(monkeypatch, 52) data = {d: DiscountData(type=DiscountType.PERCENT, value=60)} result = await run(d, d, data) # headroom = 100 - 52 = 48 -> max_pct = 48% assert result[d].value == 48 @pytest.mark.asyncio async def test_flat_discount_clamped_to_floor(monkeypatch): d = date(2026, 1, 10) _stub_prices(monkeypatch, {d: 100}) _stub_config(monkeypatch, 52) data = {d: DiscountData(type=DiscountType.FLAT, value=60)} result = await run(d, d, data) assert result[d].value == 48 @pytest.mark.asyncio async def test_discount_under_floor_passes_through(monkeypatch): d = date(2026, 1, 10) _stub_prices(monkeypatch, {d: 100}) _stub_config(monkeypatch, 52) data = {d: DiscountData(type=DiscountType.PERCENT, value=30)} result = await run(d, d, data) assert result[d].value == 30 @pytest.mark.asyncio async def test_base_at_or_below_floor_drops_discount(monkeypatch): d = date(2026, 1, 10) _stub_prices(monkeypatch, {d: 50}) _stub_config(monkeypatch, 52) data = {d: DiscountData(type=DiscountType.PERCENT, value=10)} result = await run(d, d, data) assert d not in result