AI-Pricing-Agent/tests/test_impact_baseline.py

165 lines
6.7 KiB
Python

"""The profit-impact baseline: a price delta must subtract like from like.
The `current` scenario row carries TWO readings on purpose:
* ``net_30d`` — COSMOS's BOOKED profit, priced at the average customers actually
paid over the window (revenue / units).
* ``modelled_net_30d`` — the same model every other row uses, evaluated at TODAY's price.
Subtracting a projection from the booked figure mixes those bases and measures a move nobody
proposed. Observed on UBMICROFIBERDUVETTWINWHITE:
today $17.09
recommendation $17.94 (+5%, the step cap)
booked row $18.18 <- the average actually sold over 90 days
rec - booked = $2,357 - $2,435 = -$78 -> "Profit opportunity $0" beside a RAISE
rec - modelled = $2,357 - $1,150 = +$1,207 -> the real effect of $17.09 -> $17.94
The headline tile, the queue sort and the per-SKU impact all read that number.
"""
from __future__ import annotations
import pytest
from dashboard.live_data import (
_TWINNED, _scenario_economics, booked, modelled, modelled_net_30d,
)
FP = {"cost": 8.0, "fba": 4.0, "referral_pct": 0.15, "returns_pct": 0.02, "variable": 0.5}
# ---------------------------------------------------------------- the helper
def test_prefers_the_modelled_twin_when_a_row_has_one():
row = {"net_30d": 2435, "modelled_net_30d": 1150}
assert modelled_net_30d(row) == 1150
def test_falls_back_to_net_for_rows_with_no_twin():
"""Every row except `current` is already modelled — nothing to prefer."""
assert modelled_net_30d({"net_30d": 2357}) == 2357
def test_missing_row_returns_the_fallback():
assert modelled_net_30d(None, 42.0) == 42.0
assert modelled_net_30d({}, 42.0) == 42.0
# ------------------------------------------------------- against the real shape
def _econ(cur_price=17.09, realized=18.18):
"""Scenario economics shaped like the live SKU: today's price BELOW the window average."""
grid = {"current": cur_price, "up_5": round(cur_price * 1.05, 2)}
rows, _meta = _scenario_economics(
cur_price, 66.0, FP, -1.3, 0.14, 500.0, grid,
actual_30d=2435.0, actual_rev=36000.0, actual_ad=5000.0, actual_units=1980.0,
realized_price=realized, ad_model=None, bands=None, gap_per_unit=0.0,
)
return {x["key"]: x for x in rows}
def test_the_current_row_really_does_carry_two_different_numbers():
"""If these ever coincide the test below proves nothing, so assert the premise."""
e = _econ()
cur = e["current"]
assert cur["price"] == pytest.approx(18.18) # what buyers paid
assert cur["list_price"] == pytest.approx(17.09) # today's price
assert cur["net_30d"] == 2435 # booked
assert cur["modelled_net_30d"] != cur["net_30d"] # ...and its modelled twin differs
def test_the_booked_baseline_prices_the_wrong_move():
"""Reproduces the defect: a +5% raise scored as a LOSS because $17.94 < $18.18."""
e = _econ()
booked_impact = e["up_5"]["net_30d"] - e["current"]["net_30d"]
assert booked_impact < 0, "the premise of the bug no longer holds; rewrite this test"
def test_the_modelled_baseline_prices_the_move_that_was_actually_proposed():
e = _econ()
impact = modelled_net_30d(e["up_5"]) - modelled_net_30d(e["current"])
assert impact > 0
# ...and it is exactly the difference between the model at the two prices.
assert impact == pytest.approx(
e["up_5"]["net_30d"] - e["current"]["modelled_net_30d"])
def test_a_maintain_recommendation_reports_exactly_zero():
"""The recommendation lands on the current row; subtracting it from itself must be 0.
Using the booked value on one side and the modelled value on the other would report the
gap between the two readings as if holding the price earned money.
"""
e = _econ()
impact = modelled_net_30d(e["current"]) - modelled_net_30d(e["current"])
assert impact == 0
# ------------------------------------------------- the accessor, as one place to be right
def test_every_twinned_field_is_swapped_not_just_net():
"""A partial swap is the bug. Whatever `_TWINNED` lists, the current row must twin ALL of it.
Three wrong numbers shipped because each site hand-wrote its own
`row.get("modelled_x", row["x"])` and covered a different subset of fields.
"""
e = _econ()
cur = e["current"]
for field in _TWINNED:
assert f"modelled_{field}" in cur, f"current row has no modelled twin for {field!r}"
m = modelled(cur)
for field in _TWINNED:
assert m[field] == cur[f"modelled_{field}"], field
def test_the_accessor_swaps_price_too_not_only_profit():
"""The field whose absence caused the strategy table to mix bases."""
e = _econ()
cur = e["current"]
assert cur["price"] == pytest.approx(18.18) # booked: what buyers paid
assert modelled(cur)["price"] == pytest.approx(17.09) # modelled: today's price
def test_margin_is_twinned_so_now_and_after_share_a_basis():
e = _econ()
cur = e["current"]
# Booked margin and modelled margin genuinely differ here — that is the whole hazard.
assert cur["net_margin_pct"] != modelled(cur)["net_margin_pct"]
# Comparing modelled-to-modelled is the only pairing that describes the move.
assert modelled(e["up_5"])["net_margin_pct"] > modelled(cur)["net_margin_pct"]
def test_a_projected_row_passes_through_untouched():
"""Only `current` is twinned; everything else must be returned exactly as it is."""
e = _econ()
assert modelled(e["up_5"]) == e["up_5"]
assert modelled(None) == {}
def test_booked_is_available_only_for_the_row_that_is_a_fact():
e = _econ()
b = booked(e["current"])
assert b is not None and b["net_30d"] == 2435 and b["price"] == pytest.approx(18.18)
assert booked(e["up_5"]) is None # a projection is not a fact
assert booked(None) is None
def test_modelled_is_a_copy_and_does_not_mutate_the_row():
e = _econ()
cur = e["current"]
before = dict(cur)
m = modelled(cur)
m["net_30d"] = -999
assert cur == before
def test_no_spurious_impact_when_today_equals_the_window_average():
"""With no promo gap the two readings coincide and both baselines agree."""
e = _econ(cur_price=18.18, realized=18.18)
cur = e["current"]
assert cur["price"] == pytest.approx(cur["list_price"])
booked = e["up_5"]["net_30d"] - cur["net_30d"]
modelled = modelled_net_30d(e["up_5"]) - modelled_net_30d(cur)
# The booked figure is still an actual, so they need not be identical — but the modelled
# delta must not flip sign relative to the price move, which is the failure being guarded.
assert modelled > 0
assert (booked > 0) or (cur["net_30d"] != cur["modelled_net_30d"])