stepolan commited on
Commit Β·
21b7b35
1
Parent(s): 928cf68
Add rich plan document format with deal types, targets, illustrative scenarios
Browse filesSupports co-founder's detailed comp plan view with:
- Deal type table (Enterprise/SMB with different rates)
- Annual quota built from deal targets
- Grouped ramp schedule with monthly targets and notes
- Accelerator tiers
- Illustrative earnings scenarios by deal mix
- Full policy terms
- Signature block
app.py
CHANGED
|
@@ -638,127 +638,251 @@ if active_tab == "compare":
|
|
| 638 |
|
| 639 |
# Build agreement text
|
| 640 |
lines = []
|
| 641 |
-
|
| 642 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 643 |
lines.append("")
|
|
|
|
|
|
|
| 644 |
lines.append("1. COMPENSATION OVERVIEW")
|
| 645 |
lines.append("")
|
| 646 |
-
lines.append(
|
| 647 |
-
lines.append(f"
|
|
|
|
|
|
|
| 648 |
|
| 649 |
-
# Draw
|
| 650 |
-
draw_amt = p.get("draw_amount", 0)
|
| 651 |
if draw_amt > 0:
|
| 652 |
draw_mo = p.get("draw_months", 0)
|
| 653 |
rec_label = "recoverable" if p.get("draw_recoverable", False) else "non-recoverable"
|
| 654 |
monthly_draw = draw_amt / max(draw_mo, 1)
|
| 655 |
-
lines.append(
|
| 656 |
-
lines.append(f"
|
| 657 |
-
|
| 658 |
-
|
| 659 |
-
|
| 660 |
-
lines.append("")
|
| 661 |
-
|
| 662 |
-
# Ramp
|
| 663 |
-
ramp_list = p.get("ramp_pcts", [])
|
| 664 |
-
if ramp_list:
|
| 665 |
-
lines.append("2. RAMP-UP PERIOD")
|
| 666 |
-
lines.append("")
|
| 667 |
-
lines.append(f" The initial ramp period shall be the first {len(ramp_list)} months of employment.")
|
| 668 |
-
lines.append(f" During ramp, quota targets are reduced as follows:")
|
| 669 |
-
lines.append("")
|
| 670 |
-
lines.append(f" {'Month':<12} {'Quota %':<12}")
|
| 671 |
-
lines.append(f" {'-' * 10:<12} {'-' * 10:<12}")
|
| 672 |
-
for i, pct in enumerate(ramp_list):
|
| 673 |
-
lines.append(f" Month {i+1:<5} {int(pct)}%")
|
| 674 |
-
lines.append(f" Month {len(ramp_list)+1}+{'':<3} 100%")
|
| 675 |
lines.append("")
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
lines.append("
|
|
|
|
|
|
|
|
|
|
| 679 |
lines.append("")
|
| 680 |
-
lines.append(" No ramp period. Full quota applies from Month 1.")
|
| 681 |
|
|
|
|
|
|
|
|
|
|
| 682 |
lines.append("")
|
| 683 |
|
| 684 |
-
# Commission
|
| 685 |
-
lines.append("
|
| 686 |
lines.append("")
|
| 687 |
|
| 688 |
comm_tiers = p.get("commission_tiers")
|
| 689 |
-
|
| 690 |
accel_t = p.get("accel_tiers")
|
| 691 |
|
| 692 |
-
if
|
| 693 |
-
lines.append("
|
| 694 |
-
lines.append("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 695 |
lines.append("")
|
| 696 |
-
lines.append(
|
| 697 |
-
lines.append(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 698 |
for i, tier in enumerate(comm_tiers):
|
| 699 |
upper, rate = tier[0], tier[1]
|
| 700 |
if upper is None:
|
| 701 |
prev_upper = int(comm_tiers[i-1][0])
|
| 702 |
-
lines.append(f"
|
| 703 |
elif i == 0:
|
| 704 |
-
lines.append(f"
|
| 705 |
else:
|
| 706 |
prev_upper = int(comm_tiers[i-1][0])
|
| 707 |
-
lines.append(f"
|
| 708 |
-
elif
|
| 709 |
-
lines.append("
|
| 710 |
lines.append("")
|
| 711 |
-
lines.append(f"
|
| 712 |
-
lines.append(f"
|
| 713 |
-
for tier in
|
| 714 |
mn, mx, rt = tier[0], tier[1], tier[2]
|
| 715 |
if mx is None:
|
| 716 |
-
lines.append(f"
|
| 717 |
else:
|
| 718 |
-
lines.append(f"
|
| 719 |
-
|
| 720 |
-
if accel_t:
|
| 721 |
-
lines.append("")
|
| 722 |
-
lines.append(" Accelerators apply based on annual quota attainment:")
|
| 723 |
-
lines.append("")
|
| 724 |
-
lines.append(f" {'Attainment Level':<24} {'Multiplier':<18}")
|
| 725 |
-
lines.append(f" {'-' * 22:<24} {'-' * 16:<18}")
|
| 726 |
-
for i, tier in enumerate(accel_t):
|
| 727 |
-
upper, mult = tier[0], tier[1]
|
| 728 |
-
if upper is None:
|
| 729 |
-
prev_upper = int(accel_t[i-1][0])
|
| 730 |
-
lines.append(f" {prev_upper}%+{'':<19} {mult:.1f}x")
|
| 731 |
-
elif i == 0:
|
| 732 |
-
lines.append(f" 0% β {int(upper)}%{'':<14} {mult:.1f}x")
|
| 733 |
-
else:
|
| 734 |
-
prev_upper = int(accel_t[i-1][0])
|
| 735 |
-
lines.append(f" {prev_upper}% β {int(upper)}%{'':<12} {mult:.1f}x")
|
| 736 |
|
| 737 |
lines.append("")
|
| 738 |
-
|
| 739 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 740 |
|
| 741 |
# Illustrative earnings
|
| 742 |
-
lines.append("
|
| 743 |
-
lines.append("")
|
| 744 |
-
lines.append(f" At {r.get('attainment_pct', 0):.0f}% quota attainment (${inp.get('actual_revenue', 0):,.0f} revenue):")
|
| 745 |
lines.append("")
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
lines.append(f"
|
| 749 |
-
|
| 750 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 751 |
lines.append("")
|
|
|
|
| 752 |
|
| 753 |
# Policies
|
| 754 |
-
lines.append("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 755 |
lines.append("")
|
| 756 |
-
lines.append("
|
| 757 |
-
lines.append("
|
| 758 |
-
lines.append(" territory changes, product availability, and strategic priorities.")
|
| 759 |
-
lines.append(" - The Company reserves the right to modify or terminate this plan at any time.")
|
| 760 |
-
lines.append(" - All determinations will be made in good faith and in compliance with")
|
| 761 |
-
lines.append(" applicable law.")
|
| 762 |
|
| 763 |
agreement_text = "\n".join(lines)
|
| 764 |
|
|
|
|
| 638 |
|
| 639 |
# Build agreement text
|
| 640 |
lines = []
|
| 641 |
+
deal_types = p.get("deal_types")
|
| 642 |
+
illustrative = p.get("illustrative_scenarios")
|
| 643 |
+
policies = p.get("policies")
|
| 644 |
+
equity = p.get("equity")
|
| 645 |
+
|
| 646 |
+
lines.append("SALES COMPENSATION PLAN")
|
| 647 |
+
lines.append("=" * 60)
|
| 648 |
+
lines.append("")
|
| 649 |
+
|
| 650 |
+
# Header summary
|
| 651 |
+
lines.append(f" ${p.get('base_salary', 0):,.0f}".ljust(22) + f"~${r.get('total_comp', 0):,.0f}".ljust(22))
|
| 652 |
+
lines.append(" Base Salary".ljust(22) + "OTE".ljust(22))
|
| 653 |
+
draw_amt = p.get("draw_amount", 0)
|
| 654 |
+
if draw_amt > 0 or equity:
|
| 655 |
+
line_l = f" ${draw_amt:,.0f}" if draw_amt > 0 else ""
|
| 656 |
+
line_r = f" {equity.get('pct', '')}%" if equity else ""
|
| 657 |
+
lines.append(line_l.ljust(22) + line_r.ljust(22))
|
| 658 |
+
line_l2 = f" Draw ({p.get('draw_months', 0)} mo.)" if draw_amt > 0 else ""
|
| 659 |
+
line_r2 = f" Equity (Options)" if equity else ""
|
| 660 |
+
lines.append(line_l2.ljust(22) + line_r2.ljust(22))
|
| 661 |
lines.append("")
|
| 662 |
+
|
| 663 |
+
# 1. Compensation Overview
|
| 664 |
lines.append("1. COMPENSATION OVERVIEW")
|
| 665 |
lines.append("")
|
| 666 |
+
lines.append(" Base Salary")
|
| 667 |
+
lines.append(f" β’ ${p.get('base_salary', 0):,.0f} / year paid semi-monthly")
|
| 668 |
+
lines.append(f" β’ Full benefits eligibility from day 1")
|
| 669 |
+
lines.append("")
|
| 670 |
|
|
|
|
|
|
|
| 671 |
if draw_amt > 0:
|
| 672 |
draw_mo = p.get("draw_months", 0)
|
| 673 |
rec_label = "recoverable" if p.get("draw_recoverable", False) else "non-recoverable"
|
| 674 |
monthly_draw = draw_amt / max(draw_mo, 1)
|
| 675 |
+
lines.append(" Signing Draw")
|
| 676 |
+
lines.append(f" β’ ${draw_amt:,.0f} {rec_label} draw")
|
| 677 |
+
lines.append(f" β’ Paid over {draw_mo} months in equal installments ~${monthly_draw:,.0f}/mo.")
|
| 678 |
+
if not p.get("draw_recoverable", False):
|
| 679 |
+
lines.append(f" β’ Not subject to clawback β protects ramp period")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 680 |
lines.append("")
|
| 681 |
+
|
| 682 |
+
if equity:
|
| 683 |
+
lines.append(" Equity Grant")
|
| 684 |
+
lines.append(f" β’ {equity.get('pct', '')}% of company in stock options")
|
| 685 |
+
lines.append(f" β’ {equity.get('vesting', '4-year vest with 1-year cliff')}")
|
| 686 |
+
lines.append(f" β’ Strike price = FMV at grant date")
|
| 687 |
lines.append("")
|
|
|
|
| 688 |
|
| 689 |
+
lines.append(" On-Target Earnings (OTE)")
|
| 690 |
+
lines.append(f" β’ ${p.get('base_salary', 0):,.0f} base + ~${r.get('commission', 0):,.0f} variable = ~${r.get('total_comp', 0):,.0f} OTE")
|
| 691 |
+
lines.append(f" β’ Uncapped β no ceiling on commissions")
|
| 692 |
lines.append("")
|
| 693 |
|
| 694 |
+
# 2. Commission Structure
|
| 695 |
+
lines.append("2. COMMISSION STRUCTURE")
|
| 696 |
lines.append("")
|
| 697 |
|
| 698 |
comm_tiers = p.get("commission_tiers")
|
| 699 |
+
deal_tiers_data = p.get("deal_rate_tiers")
|
| 700 |
accel_t = p.get("accel_tiers")
|
| 701 |
|
| 702 |
+
if deal_types:
|
| 703 |
+
lines.append(" Commission is paid on all closed-won deals. Rates vary by deal type:")
|
| 704 |
+
lines.append("")
|
| 705 |
+
lines.append(f" {'Deal Type':<14} {'ACV Range':<22} {'Rate':<10} {'Per-Deal Range':<20} {'Notes'}")
|
| 706 |
+
lines.append(f" {'-'*13:<14} {'-'*20:<22} {'-'*8:<10} {'-'*18:<20} {'-'*20}")
|
| 707 |
+
for dt in deal_types:
|
| 708 |
+
acv_range = f"${dt['acv_min']:,.0f} β ${dt['acv_max']:,.0f}" if dt.get('acv_max') else f"${dt['acv_min']:,.0f}+"
|
| 709 |
+
payout_lo = dt['acv_min'] * dt['rate'] / 100
|
| 710 |
+
payout_hi = (dt.get('acv_max', dt['acv_min']) * dt['rate'] / 100) if dt.get('acv_max') else 0
|
| 711 |
+
payout_range = f"${payout_lo:,.0f} β ${payout_hi:,.0f}" if payout_hi else f"${payout_lo:,.0f}+"
|
| 712 |
+
lines.append(f" {dt['name']:<14} {acv_range:<22} {dt['rate']:.0f}%{'':<7} {payout_range:<20} {dt.get('notes', '')}")
|
| 713 |
lines.append("")
|
| 714 |
+
lines.append(" Timing: Commissions earned upon fully-executed contract and first invoice")
|
| 715 |
+
lines.append(" issued. Paid on the first payroll cycle of the following month.")
|
| 716 |
+
lines.append(" Churn within 90 days triggers a proportional clawback.")
|
| 717 |
+
elif comm_tiers:
|
| 718 |
+
lines.append(" Commission rates are applied on a marginal basis. Each rate applies")
|
| 719 |
+
lines.append(" only to revenue earned within that attainment band.")
|
| 720 |
+
lines.append("")
|
| 721 |
+
lines.append(f" {'Attainment Level':<24} {'Commission Rate':<18}")
|
| 722 |
+
lines.append(f" {'-' * 22:<24} {'-' * 16:<18}")
|
| 723 |
for i, tier in enumerate(comm_tiers):
|
| 724 |
upper, rate = tier[0], tier[1]
|
| 725 |
if upper is None:
|
| 726 |
prev_upper = int(comm_tiers[i-1][0])
|
| 727 |
+
lines.append(f" {prev_upper}%+{'':<19} {rate:.1f}%")
|
| 728 |
elif i == 0:
|
| 729 |
+
lines.append(f" 0% β {int(upper)}%{'':<14} {rate:.1f}%")
|
| 730 |
else:
|
| 731 |
prev_upper = int(comm_tiers[i-1][0])
|
| 732 |
+
lines.append(f" {prev_upper}% β {int(upper)}%{'':<12} {rate:.1f}%")
|
| 733 |
+
elif deal_tiers_data:
|
| 734 |
+
lines.append(" Commission is calculated as a percentage of deal ACV based on deal size.")
|
| 735 |
lines.append("")
|
| 736 |
+
lines.append(f" {'Deal ACV Range':<28} {'Commission Rate':<18}")
|
| 737 |
+
lines.append(f" {'-' * 26:<28} {'-' * 16:<18}")
|
| 738 |
+
for tier in deal_tiers_data:
|
| 739 |
mn, mx, rt = tier[0], tier[1], tier[2]
|
| 740 |
if mx is None:
|
| 741 |
+
lines.append(f" ${mn:,.0f}+{'':<19} {rt:.1f}%")
|
| 742 |
else:
|
| 743 |
+
lines.append(f" ${mn:,.0f} β ${mx:,.0f}{'':<8} {rt:.1f}%")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 744 |
|
| 745 |
lines.append("")
|
| 746 |
+
|
| 747 |
+
# 3. Annual Quota & Deal Targets
|
| 748 |
+
deal_targets = p.get("deal_targets")
|
| 749 |
+
if deal_targets:
|
| 750 |
+
lines.append("3. ANNUAL QUOTA & DEAL TARGETS")
|
| 751 |
+
lines.append("")
|
| 752 |
+
lines.append(f" On-target quota is ${p.get('annual_quota', 0):,.0f} ACV.")
|
| 753 |
+
lines.append("")
|
| 754 |
+
lines.append(f" {'Segment':<14} {'# Deals':<10} {'Avg ACV':<14} {'Total ACV':<14} {'Rate':<8} {'Commission'}")
|
| 755 |
+
lines.append(f" {'-'*13:<14} {'-'*8:<10} {'-'*12:<14} {'-'*12:<14} {'-'*6:<8} {'-'*12}")
|
| 756 |
+
total_deals = 0
|
| 757 |
+
total_acv = 0
|
| 758 |
+
total_comm = 0
|
| 759 |
+
for dt in deal_targets:
|
| 760 |
+
t_acv = dt['num_deals'] * dt['avg_acv']
|
| 761 |
+
t_comm = t_acv * dt['rate'] / 100
|
| 762 |
+
total_deals += dt['num_deals']
|
| 763 |
+
total_acv += t_acv
|
| 764 |
+
total_comm += t_comm
|
| 765 |
+
lines.append(f" {dt['segment']:<14} {dt['num_deals']:<10} ${dt['avg_acv']:,.0f}{'':<6} ${t_acv:,.0f}{'':<6} {dt['rate']:.0f}%{'':<5} ${t_comm:,.0f}")
|
| 766 |
+
lines.append(f" {'Total':<14} {total_deals:<10} {'β':<14} ${total_acv:,.0f}{'':<6} {'β':<8} ~${total_comm:,.0f}")
|
| 767 |
+
lines.append("")
|
| 768 |
+
section_num = 4
|
| 769 |
+
else:
|
| 770 |
+
section_num = 3
|
| 771 |
+
|
| 772 |
+
# Ramp
|
| 773 |
+
ramp_list = p.get("ramp_pcts", [])
|
| 774 |
+
if ramp_list:
|
| 775 |
+
lines.append(f"{section_num}. QUOTA RAMP SCHEDULE")
|
| 776 |
+
lines.append("")
|
| 777 |
+
lines.append(f" Commission rates remain constant throughout the ramp. Only the quota")
|
| 778 |
+
lines.append(f" hurdle changes, giving time to build pipeline without sacrificing")
|
| 779 |
+
lines.append(f" earnings on early deals closed.")
|
| 780 |
+
lines.append("")
|
| 781 |
+
monthly_quota = p.get('annual_quota', 0) / 12
|
| 782 |
+
lines.append(f" {'Month':<10} {'Quota %':<12} {'Monthly Target':<18} {'Ann. Run Rate':<16} {'Notes'}")
|
| 783 |
+
lines.append(f" {'-'*8:<10} {'-'*10:<12} {'-'*16:<18} {'-'*14:<16} {'-'*20}")
|
| 784 |
+
# Group consecutive months with same pct
|
| 785 |
+
ramp_groups = []
|
| 786 |
+
i = 0
|
| 787 |
+
while i < len(ramp_list):
|
| 788 |
+
pct = ramp_list[i]
|
| 789 |
+
start = i + 1
|
| 790 |
+
while i + 1 < len(ramp_list) and ramp_list[i + 1] == pct:
|
| 791 |
+
i += 1
|
| 792 |
+
end = i + 1
|
| 793 |
+
ramp_groups.append((start, end, pct))
|
| 794 |
+
i += 1
|
| 795 |
+
ramp_notes = {0: "Onboarding, no quota", 25: "First demos, early pipeline",
|
| 796 |
+
50: "Close first deals", 75: "Full funnel operating", 100: "Full quota in effect"}
|
| 797 |
+
for start, end, pct in ramp_groups:
|
| 798 |
+
month_label = f"{start}β{end}" if start != end else str(start)
|
| 799 |
+
target = monthly_quota * pct / 100
|
| 800 |
+
run_rate = target * 12
|
| 801 |
+
note = ramp_notes.get(int(pct), "")
|
| 802 |
+
if draw_amt > 0:
|
| 803 |
+
monthly_draw_val = draw_amt / max(p.get('draw_months', 1), 1)
|
| 804 |
+
lines.append(f" {month_label:<10} {int(pct)}%{'':<9} ${target:,.0f}{'':<8} ${run_rate:,.0f}{'':<6} {note}")
|
| 805 |
+
else:
|
| 806 |
+
lines.append(f" {month_label:<10} {int(pct)}%{'':<9} ${target:,.0f}{'':<8} ${run_rate:,.0f}{'':<6} {note}")
|
| 807 |
+
# Full quota months
|
| 808 |
+
if len(ramp_list) < 12:
|
| 809 |
+
month_label = f"{len(ramp_list)+1}β12"
|
| 810 |
+
lines.append(f" {month_label:<10} 100%{'':<8} ${monthly_quota:,.0f}{'':<8} ${monthly_quota*12:,.0f}{'':<6} Full quota in effect")
|
| 811 |
+
lines.append("")
|
| 812 |
+
section_num += 1
|
| 813 |
+
|
| 814 |
+
# Accelerators
|
| 815 |
+
if accel_t:
|
| 816 |
+
lines.append(f"{section_num}. ACCELERATORS & OVERACHIEVEMENT")
|
| 817 |
+
lines.append("")
|
| 818 |
+
lines.append(f" {'Attainment':<18} {'Rate / Multiplier':<22} {'Notes'}")
|
| 819 |
+
lines.append(f" {'-'*16:<18} {'-'*20:<22} {'-'*20}")
|
| 820 |
+
for i, tier in enumerate(accel_t):
|
| 821 |
+
upper, mult = tier[0], tier[1]
|
| 822 |
+
if upper is None:
|
| 823 |
+
prev_upper = int(accel_t[i-1][0])
|
| 824 |
+
lines.append(f" {prev_upper}%+{'':<14} {mult:.1f}x multiplier")
|
| 825 |
+
elif i == 0:
|
| 826 |
+
lines.append(f" 0% β {int(upper)}%{'':<9} {mult:.1f}x (base rate)")
|
| 827 |
+
else:
|
| 828 |
+
prev_upper = int(accel_t[i-1][0])
|
| 829 |
+
lines.append(f" {prev_upper}% β {int(upper)}%{'':<7} {mult:.1f}x multiplier")
|
| 830 |
+
lines.append("")
|
| 831 |
+
section_num += 1
|
| 832 |
+
elif comm_tiers:
|
| 833 |
+
# Attainment-based tiers already shown above, no separate accelerator section needed
|
| 834 |
+
pass
|
| 835 |
|
| 836 |
# Illustrative earnings
|
| 837 |
+
lines.append(f"{section_num}. ILLUSTRATIVE EARNINGS SCENARIOS")
|
|
|
|
|
|
|
| 838 |
lines.append("")
|
| 839 |
+
if illustrative:
|
| 840 |
+
lines.append(f" {'Scenario':<22} {'Deal Mix':<20} {'Total ACV':<14} {'Commission':<14} {'Total Cash':<14} {'Notes'}")
|
| 841 |
+
lines.append(f" {'-'*20:<22} {'-'*18:<20} {'-'*12:<14} {'-'*12:<14} {'-'*12:<14} {'-'*20}")
|
| 842 |
+
for sc in illustrative:
|
| 843 |
+
lines.append(f" {sc['label']:<22} {sc.get('deal_mix', 'β'):<20} ${sc['acv']:,.0f}{'':<4} ${sc['commission']:,.0f}{'':<4} ${sc['total_cash']:,.0f}{'':<4} {sc.get('notes', '')}")
|
| 844 |
+
else:
|
| 845 |
+
lines.append(f" At {r.get('attainment_pct', 0):.0f}% quota attainment (${inp.get('actual_revenue', 0):,.0f} revenue):")
|
| 846 |
+
lines.append("")
|
| 847 |
+
lines.append(f" Base Salary: ${p.get('base_salary', 0):,.0f}")
|
| 848 |
+
if draw_amt > 0:
|
| 849 |
+
lines.append(f" Draw: ${r.get('draw_paid', 0):,.0f}")
|
| 850 |
+
lines.append(f" Commission: ${r.get('commission', 0):,.0f}")
|
| 851 |
+
lines.append(f" Total Compensation: ${r.get('total_comp', 0):,.0f}")
|
| 852 |
lines.append("")
|
| 853 |
+
section_num += 1
|
| 854 |
|
| 855 |
# Policies
|
| 856 |
+
lines.append(f"{section_num}. KEY POLICIES & TERMS")
|
| 857 |
+
lines.append("")
|
| 858 |
+
if policies:
|
| 859 |
+
for key, val in policies.items():
|
| 860 |
+
lines.append(f" {key:<24} {val}")
|
| 861 |
+
else:
|
| 862 |
+
lines.append(" Commission Earned Upon fully-executed contract and recognized revenue.")
|
| 863 |
+
lines.append(" Commission Paid First payroll cycle following the month of close.")
|
| 864 |
+
lines.append(" Clawback Proportional if customer churns within 90 days.")
|
| 865 |
+
lines.append(" Split Deals Agreed upfront in writing; default 50/50.")
|
| 866 |
+
lines.append(" Plan Changes Company may update at each FY with 30 days notice.")
|
| 867 |
+
if draw_amt > 0:
|
| 868 |
+
lines.append(f" Draw Period {p.get('draw_months', 0)} months from start. Ceases if employment ends.")
|
| 869 |
+
if equity:
|
| 870 |
+
lines.append(f" Equity Vesting {equity.get('vesting', '4-year vest, 1-year cliff')}.")
|
| 871 |
+
lines.append(" Territory As assigned by Company. May be refined as team grows.")
|
| 872 |
+
lines.append("")
|
| 873 |
+
section_num += 1
|
| 874 |
+
|
| 875 |
+
# Acknowledgment
|
| 876 |
+
lines.append(f"{section_num}. ACKNOWLEDGMENT & ACCEPTANCE")
|
| 877 |
+
lines.append("")
|
| 878 |
+
lines.append(" By signing below, both parties agree to the terms of this")
|
| 879 |
+
lines.append(" Sales Compensation Plan.")
|
| 880 |
+
lines.append("")
|
| 881 |
+
lines.append(" ________________________________________")
|
| 882 |
+
lines.append(" Account Executive Signature Date")
|
| 883 |
lines.append("")
|
| 884 |
+
lines.append(" ________________________________________")
|
| 885 |
+
lines.append(" Authorized Signatory Date")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 886 |
|
| 887 |
agreement_text = "\n".join(lines)
|
| 888 |
|