stepolan commited on
Commit Β·
75ecc2d
1
Parent(s): 9c022b0
Add scenario detail view with full plan config, save commission tiers in scenario data
Browse files
app.py
CHANGED
|
@@ -457,6 +457,9 @@ if active_tab == "scenario":
|
|
| 457 |
"draw_months": int(draw_months), "draw_recoverable": draw_recoverable,
|
| 458 |
"ramp_pcts": ramp_pcts, "cogs_pct": cogs_pct,
|
| 459 |
"other_cost_per_rep": other_cost_per_rep,
|
|
|
|
|
|
|
|
|
|
| 460 |
},
|
| 461 |
"inputs": {
|
| 462 |
"months_employed": months_employed,
|
|
@@ -607,5 +610,90 @@ if active_tab == "compare":
|
|
| 607 |
fig.update_layout(barmode="group", height=400,
|
| 608 |
margin=dict(l=0, r=0, t=30, b=0))
|
| 609 |
st.plotly_chart(fig, use_container_width=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 610 |
else:
|
| 611 |
st.info("No saved scenarios yet. Save one from the Scenario Calculator tab.")
|
|
|
|
| 457 |
"draw_months": int(draw_months), "draw_recoverable": draw_recoverable,
|
| 458 |
"ramp_pcts": ramp_pcts, "cogs_pct": cogs_pct,
|
| 459 |
"other_cost_per_rep": other_cost_per_rep,
|
| 460 |
+
"commission_tiers": att_tiers if commission_mode == "Attainment-based rates" else None,
|
| 461 |
+
"deal_rate_tiers": deal_rate_tiers if commission_mode != "Attainment-based rates" else None,
|
| 462 |
+
"accel_tiers": accel_tiers if commission_mode != "Attainment-based rates" else None,
|
| 463 |
},
|
| 464 |
"inputs": {
|
| 465 |
"months_employed": months_employed,
|
|
|
|
| 610 |
fig.update_layout(barmode="group", height=400,
|
| 611 |
margin=dict(l=0, r=0, t=30, b=0))
|
| 612 |
st.plotly_chart(fig, use_container_width=True)
|
| 613 |
+
|
| 614 |
+
# --- Scenario detail view ---
|
| 615 |
+
st.divider()
|
| 616 |
+
st.markdown("**Scenario Details**")
|
| 617 |
+
st.caption("Click a scenario to see its full plan configuration.")
|
| 618 |
+
detail_name = st.selectbox("View details for", [""] + selected, key="detail_sel")
|
| 619 |
+
if detail_name and detail_name in scenarios:
|
| 620 |
+
s = scenarios[detail_name]
|
| 621 |
+
p = s.get("params", {})
|
| 622 |
+
inp = s.get("inputs", {})
|
| 623 |
+
r = s.get("results", {})
|
| 624 |
+
|
| 625 |
+
dc1, dc2 = st.columns(2)
|
| 626 |
+
with dc1:
|
| 627 |
+
st.markdown(f"**{detail_name}**")
|
| 628 |
+
st.markdown(f"- **Author:** {s.get('author', 'β')}")
|
| 629 |
+
st.markdown(f"- **Commission Model:** {s.get('commission_mode', 'β')}")
|
| 630 |
+
st.markdown(f"- **Base Salary:** ${p.get('base_salary', 0):,.0f}")
|
| 631 |
+
st.markdown(f"- **Annual Quota:** ${p.get('annual_quota', 0):,.0f}")
|
| 632 |
+
st.markdown(f"- **Effective Quota:** ${r.get('effective_quota', 0):,.0f}")
|
| 633 |
+
|
| 634 |
+
draw_amt = p.get("draw_amount", 0)
|
| 635 |
+
if draw_amt > 0:
|
| 636 |
+
rec = "Recoverable" if p.get("draw_recoverable", False) else "Non-recoverable"
|
| 637 |
+
st.markdown(f"- **Draw:** ${draw_amt:,.0f} over {p.get('draw_months', 0)} months ({rec})")
|
| 638 |
+
else:
|
| 639 |
+
st.markdown("- **Draw:** None")
|
| 640 |
+
|
| 641 |
+
ramp = p.get("ramp_pcts", [])
|
| 642 |
+
if ramp:
|
| 643 |
+
ramp_str = " β ".join(f"{int(r)}%" for r in ramp) + " β 100%"
|
| 644 |
+
st.markdown(f"- **Ramp:** {len(ramp)} months ({ramp_str})")
|
| 645 |
+
else:
|
| 646 |
+
st.markdown("- **Ramp:** None (full quota from month 1)")
|
| 647 |
+
|
| 648 |
+
with dc2:
|
| 649 |
+
# Commission tiers
|
| 650 |
+
comm_tiers = p.get("commission_tiers")
|
| 651 |
+
deal_tiers = p.get("deal_rate_tiers")
|
| 652 |
+
accel_t = p.get("accel_tiers")
|
| 653 |
+
|
| 654 |
+
if comm_tiers:
|
| 655 |
+
st.markdown("**Commission Tiers (attainment-based)**")
|
| 656 |
+
for i, tier in enumerate(comm_tiers):
|
| 657 |
+
upper, rate = tier[0], tier[1]
|
| 658 |
+
if upper is None:
|
| 659 |
+
st.markdown(f"- Above prior: **{rate}%**")
|
| 660 |
+
elif i == 0:
|
| 661 |
+
st.markdown(f"- 0β{int(upper)}%: **{rate}%**")
|
| 662 |
+
else:
|
| 663 |
+
prev_upper = int(comm_tiers[i-1][0])
|
| 664 |
+
st.markdown(f"- {prev_upper}β{int(upper)}%: **{rate}%**")
|
| 665 |
+
elif deal_tiers:
|
| 666 |
+
st.markdown("**Deal-Size Commission Rates**")
|
| 667 |
+
for tier in deal_tiers:
|
| 668 |
+
mn, mx, rt = tier[0], tier[1], tier[2]
|
| 669 |
+
if mx is None:
|
| 670 |
+
st.markdown(f"- ${mn:,.0f}+: **{rt}%**")
|
| 671 |
+
else:
|
| 672 |
+
st.markdown(f"- ${mn:,.0f}β${mx:,.0f}: **{rt}%**")
|
| 673 |
+
if accel_t:
|
| 674 |
+
st.markdown("**Accelerators**")
|
| 675 |
+
for i, tier in enumerate(accel_t):
|
| 676 |
+
upper, mult = tier[0], tier[1]
|
| 677 |
+
if upper is None:
|
| 678 |
+
st.markdown(f"- Above prior: **{mult}x**")
|
| 679 |
+
elif i == 0:
|
| 680 |
+
st.markdown(f"- 0β{int(upper)}%: **{mult}x**")
|
| 681 |
+
else:
|
| 682 |
+
prev_upper = int(accel_t[i-1][0])
|
| 683 |
+
st.markdown(f"- {prev_upper}β{int(upper)}%: **{mult}x**")
|
| 684 |
+
|
| 685 |
+
st.markdown("**Results**")
|
| 686 |
+
st.markdown(f"- **Revenue:** ${inp.get('actual_revenue', 0):,.0f}")
|
| 687 |
+
st.markdown(f"- **Attainment:** {r.get('attainment_pct', 0)}%")
|
| 688 |
+
st.markdown(f"- **Commission:** ${r.get('commission', 0):,.0f}")
|
| 689 |
+
st.markdown(f"- **Total Variable:** ${r.get('total_variable', 0):,.0f}")
|
| 690 |
+
st.markdown(f"- **Total Comp:** ${r.get('total_comp', 0):,.0f}")
|
| 691 |
+
|
| 692 |
+
st.markdown("**Company Side**")
|
| 693 |
+
st.markdown(f"- **COGS:** {p.get('cogs_pct', 0)}%")
|
| 694 |
+
st.markdown(f"- **Other Cost/Rep:** ${p.get('other_cost_per_rep', 0):,.0f}/yr")
|
| 695 |
+
st.markdown(f"- **Gross Profit:** ${r.get('gross_profit', 0):,.0f}")
|
| 696 |
+
st.markdown(f"- **Net After Rep:** ${r.get('net_after_rep', 0):,.0f}")
|
| 697 |
+
st.markdown(f"- **ROI:** {r.get('roi_on_rep', 0):.1f}x")
|
| 698 |
else:
|
| 699 |
st.info("No saved scenarios yet. Save one from the Scenario Calculator tab.")
|