165 lines
6.7 KiB
Python
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"])
|