Spaces:
Running
Running
File size: 6,685 Bytes
1a704c9 93b6d30 1a704c9 93b6d30 1a704c9 31591d8 161f628 31591d8 a55e4f2 31591d8 1a704c9 93b6d30 1a704c9 93b6d30 9aaf067 08cdf46 93b6d30 1a704c9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | import subprocess
import sys
import json
import os
from app.database import engine
from app.models import Base, User, Producer, Client
from sqlalchemy.orm import Session
print("Initializing database...")
Base.metadata.create_all(bind=engine)
# ββ Migrate: add new columns if missing ββββββββββββββββββ
import sqlite3
def add_column_if_missing(db_path, table, column, col_type):
conn = sqlite3.connect(db_path)
cursor = conn.execute(f"PRAGMA table_info({table})")
columns = [row[1] for row in cursor.fetchall()]
if column not in columns:
conn.execute(f"ALTER TABLE {table} ADD COLUMN {column} {col_type}")
conn.commit()
print(f" Added column {table}.{column}")
conn.close()
db_path = "/data/app.db"
print("Checking for schema migrations...")
add_column_if_missing(db_path, "producers", "email", "VARCHAR(255)")
add_column_if_missing(db_path, "approvals", "approval_token", "VARCHAR(64)")
# Add unique index separately (SQLite doesn't support UNIQUE in ALTER TABLE)
conn = sqlite3.connect(db_path)
try:
conn.execute("CREATE UNIQUE INDEX IF NOT EXISTS ix_approvals_approval_token ON approvals(approval_token)")
conn.commit()
print(" Added unique index on approvals.approval_token")
except Exception as e:
print(f" Index already exists or skipped: {e}")
conn.close()
print("Schema migrations complete.")
s = Session(engine)
# Seed config tables on first run
if not s.query(User).first():
print("First run - seeding database...")
from app.seed_db import seed
seed(s)
else:
print("Database exists.")
# ββ Data migration: fix commission tier labels βββββββββββ
from app.models import CommissionAgreement, CommissionTier
print("Checking commission data migrations...")
# Fix Referral/Origination Fee: "Year 1-2" β "Year 1 & Year 2"
ref_agr = s.query(CommissionAgreement).filter(
CommissionAgreement.name == "Referral / Origination Fee Agreement"
).first()
if ref_agr:
updated = 0
for tier in ref_agr.tiers:
if tier.years_label == "Year 1-2":
tier.years_label = "Year 1 & Year 2"
updated += 1
if updated:
s.commit()
print(f" Fixed Referral/Origination Fee: {updated} tier labels updated to 'Year 1 & Year 2'")
# Fix Life Origination Fee: "All Years" at 20% β "Year 1" at 20% + "Year 2+" Ended
life_agr = s.query(CommissionAgreement).filter(
CommissionAgreement.name == "Life Origination Fee Agreement"
).first()
if life_agr:
all_years_tiers = [t for t in life_agr.tiers if t.years_label == "All Years"]
if all_years_tiers:
# Update existing tier to Year 1
all_years_tiers[0].years_label = "Year 1"
# Add Year 2+ Ended tier
max_sort = max((t.sort_order for t in life_agr.tiers), default=0)
ended_tier = CommissionTier(
agreement_id=life_agr.id,
producer_role="P1",
years_label="Year 2+",
commission=None,
credit=None,
agreement_label="Ended",
note="Life Referral is 20% Year 1 only. Year 2 it is removed.",
sort_order=max_sort + 1,
)
s.add(ended_tier)
s.commit()
print(" Fixed Life Origination Fee: Year 1 at 20%, Year 2+ Ended")
print("Commission data migrations complete.")
# ββ Auto-assign producer emails (first initial + last name @snellingswalters.com) ββ
import re
print("Checking producer email assignments...")
from app.models import Producer as ProdModel
producers_without_email = s.query(ProdModel).filter(
ProdModel.is_active == True,
(ProdModel.email == None) | (ProdModel.email == "")
).all()
email_count = 0
for prod in producers_without_email:
name = prod.name.strip()
parts = name.split()
if len(parts) < 2:
# Single-word or unclear name β use fallback
prod.email = "ai@snellingswalters.com"
email_count += 1
continue
# Non-person entries get fallback email
lower_name = name.lower()
if any(kw in lower_name for kw in ["uac", "house", "account"]):
prod.email = "ai@snellingswalters.com"
email_count += 1
continue
first_clean = re.sub(r'[^a-zA-Z]', '', parts[0]).lower()
last_clean = re.sub(r'[^a-zA-Z]', '', parts[-1]).lower()
if first_clean and last_clean:
prod.email = first_clean[0] + last_clean + "@snellingswalters.com"
else:
prod.email = "ai@snellingswalters.com"
email_count += 1
if email_count:
s.commit()
print(f" Auto-assigned {email_count} producer emails.")
else:
print(" All producers already have emails.")
# Import refresh data if present (uploaded by Colab daily refresh)
REFRESH_FILE = "refresh_data.json"
if os.path.exists(REFRESH_FILE):
print(f"Found {REFRESH_FILE} - importing producers & clients...")
try:
with open(REFRESH_FILE) as f:
data = json.load(f)
# Upsert Producers
s.query(Producer).update({Producer.is_active: False})
prod_count = 0
for p in data.get("producers", []):
existing = s.query(Producer).filter(Producer.code == p["code"]).first()
if existing:
existing.prefix = p["prefix"]
existing.suffix = p["suffix"]
existing.name = p["name"]
existing.is_active = True
else:
s.add(Producer(
code=p["code"],
prefix=p["prefix"],
suffix=p["suffix"],
name=p["name"],
is_active=True,
))
prod_count += 1
# Upsert Clients
s.query(Client).update({Client.is_active: False})
cl_count = 0
for c in data.get("clients", []):
existing = s.query(Client).filter(Client.lookup_code == c["lookup_code"]).first()
if existing:
existing.name = c["name"]
existing.is_active = True
else:
s.add(Client(
lookup_code=c["lookup_code"],
name=c["name"],
is_active=True,
))
cl_count += 1
s.commit()
print(f"Imported {prod_count} producers, {cl_count} clients.")
except Exception as e:
print(f"Error importing refresh data: {e}")
s.rollback()
else:
print("No refresh_data.json found - skipping data import.")
s.close()
print("Starting server...")
subprocess.run([
sys.executable, "-m", "uvicorn",
"app.main:app",
"--host", "0.0.0.0",
"--port", "7860"
])
|