Spaces:
Build error
Build error
Ajit Panday commited on
Commit ·
0e6aefc
1
Parent(s): 1445330
Add database port field and fix relationship between Customer and CallRecord
Browse files- app/auth.py +2 -1
- app/models.py +42 -69
- app/static/admin.html +5 -0
app/auth.py
CHANGED
|
@@ -100,7 +100,7 @@ async def create_customer(
|
|
| 100 |
"""Create a new customer"""
|
| 101 |
try:
|
| 102 |
# Validate required fields
|
| 103 |
-
required_fields = ["name", "company_name", "email", "db_host", "db_user", "db_password", "db_name"]
|
| 104 |
missing_fields = [field for field in required_fields if field not in customer_data]
|
| 105 |
if missing_fields:
|
| 106 |
raise HTTPException(
|
|
@@ -123,6 +123,7 @@ async def create_customer(
|
|
| 123 |
email=customer_data["email"],
|
| 124 |
api_key=str(secrets.token_urlsafe(32)),
|
| 125 |
db_host=customer_data["db_host"],
|
|
|
|
| 126 |
db_user=customer_data["db_user"],
|
| 127 |
db_password=customer_data["db_password"],
|
| 128 |
db_name=customer_data["db_name"]
|
|
|
|
| 100 |
"""Create a new customer"""
|
| 101 |
try:
|
| 102 |
# Validate required fields
|
| 103 |
+
required_fields = ["name", "company_name", "email", "db_host", "db_port", "db_user", "db_password", "db_name"]
|
| 104 |
missing_fields = [field for field in required_fields if field not in customer_data]
|
| 105 |
if missing_fields:
|
| 106 |
raise HTTPException(
|
|
|
|
| 123 |
email=customer_data["email"],
|
| 124 |
api_key=str(secrets.token_urlsafe(32)),
|
| 125 |
db_host=customer_data["db_host"],
|
| 126 |
+
db_port=customer_data["db_port"],
|
| 127 |
db_user=customer_data["db_user"],
|
| 128 |
db_password=customer_data["db_password"],
|
| 129 |
db_name=customer_data["db_name"]
|
app/models.py
CHANGED
|
@@ -15,122 +15,94 @@ class Customer(Base):
|
|
| 15 |
__tablename__ = "customers"
|
| 16 |
|
| 17 |
id = Column(Integer, primary_key=True, index=True)
|
| 18 |
-
name = Column(String(
|
| 19 |
-
company_name = Column(String(
|
| 20 |
-
email = Column(String(
|
| 21 |
-
api_key = Column(String(
|
| 22 |
is_active = Column(Boolean, default=True)
|
| 23 |
created_at = Column(DateTime, default=datetime.utcnow)
|
| 24 |
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
| 25 |
|
| 26 |
# Database credentials
|
| 27 |
-
db_host = Column(String(
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
|
|
|
| 31 |
|
| 32 |
# Relationship with call records
|
| 33 |
-
call_records = relationship("CallRecord", back_populates="customer")
|
| 34 |
|
| 35 |
def get_db_engine(self):
|
| 36 |
-
"""
|
| 37 |
try:
|
| 38 |
-
|
| 39 |
-
db_url = f"mysql+pymysql://{self.db_user}:{self.db_password}@{self.db_host}/{self.db_name}"
|
| 40 |
-
|
| 41 |
-
# Create engine
|
| 42 |
engine = create_engine(db_url)
|
| 43 |
-
|
| 44 |
# Test connection
|
| 45 |
with engine.connect() as conn:
|
| 46 |
conn.execute("SELECT 1")
|
| 47 |
-
|
| 48 |
return engine
|
| 49 |
except Exception as e:
|
| 50 |
-
print(f"Error
|
| 51 |
return None
|
| 52 |
|
| 53 |
def create_tables(self):
|
| 54 |
"""Create necessary tables in customer's database"""
|
| 55 |
-
engine = self.get_db_engine()
|
| 56 |
-
if not engine:
|
| 57 |
-
return False
|
| 58 |
-
|
| 59 |
try:
|
| 60 |
-
|
|
|
|
|
|
|
| 61 |
Base.metadata.create_all(engine)
|
| 62 |
return True
|
| 63 |
except Exception as e:
|
| 64 |
print(f"Error creating tables: {str(e)}")
|
| 65 |
return False
|
| 66 |
|
| 67 |
-
def get_call_records(self
|
| 68 |
-
"""Get call records for this customer"""
|
| 69 |
engine = self.get_db_engine()
|
| 70 |
if not engine:
|
| 71 |
return []
|
| 72 |
-
|
|
|
|
| 73 |
try:
|
| 74 |
-
|
| 75 |
-
session = Session()
|
| 76 |
-
|
| 77 |
-
query = session.query(CallRecord).filter(CallRecord.customer_id == self.id)
|
| 78 |
-
|
| 79 |
-
if start_date:
|
| 80 |
-
query = query.filter(CallRecord.created_at >= start_date)
|
| 81 |
-
if end_date:
|
| 82 |
-
query = query.filter(CallRecord.created_at <= end_date)
|
| 83 |
-
|
| 84 |
-
records = query.all()
|
| 85 |
-
session.close()
|
| 86 |
return records
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
return []
|
| 90 |
|
| 91 |
-
def get_call_details(self, call_id):
|
| 92 |
-
"""Get
|
| 93 |
engine = self.get_db_engine()
|
| 94 |
if not engine:
|
| 95 |
return None
|
| 96 |
-
|
|
|
|
| 97 |
try:
|
| 98 |
-
Session = sessionmaker(bind=engine)
|
| 99 |
-
session = Session()
|
| 100 |
-
|
| 101 |
record = session.query(CallRecord).filter(
|
| 102 |
CallRecord.id == call_id,
|
| 103 |
CallRecord.customer_id == self.id
|
| 104 |
).first()
|
| 105 |
-
|
| 106 |
-
session.close()
|
| 107 |
return record
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
return None
|
| 111 |
|
| 112 |
-
def search_calls(self, query):
|
| 113 |
-
"""Search calls
|
| 114 |
engine = self.get_db_engine()
|
| 115 |
if not engine:
|
| 116 |
return []
|
| 117 |
-
|
|
|
|
| 118 |
try:
|
| 119 |
-
Session = sessionmaker(bind=engine)
|
| 120 |
-
session = Session()
|
| 121 |
-
|
| 122 |
-
# Implement search logic here
|
| 123 |
-
# This is a basic example
|
| 124 |
records = session.query(CallRecord).filter(
|
| 125 |
CallRecord.customer_id == self.id,
|
| 126 |
-
CallRecord.transcription.ilike(f"%{query}%")
|
|
|
|
| 127 |
).all()
|
| 128 |
-
|
| 129 |
-
session.close()
|
| 130 |
return records
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
return []
|
| 134 |
|
| 135 |
def get_db_url(self) -> Optional[str]:
|
| 136 |
"""Get database URL if credentials are configured"""
|
|
@@ -192,10 +164,10 @@ class Customer(Base):
|
|
| 192 |
class CallRecord(Base):
|
| 193 |
__tablename__ = "call_records"
|
| 194 |
|
| 195 |
-
id = Column(
|
| 196 |
-
customer_id = Column(Integer, nullable=False)
|
| 197 |
-
caller_number = Column(String(
|
| 198 |
-
called_number = Column(String(
|
| 199 |
file_path = Column(String(255), nullable=False)
|
| 200 |
transcription = Column(String(10000))
|
| 201 |
summary = Column(String(1000))
|
|
@@ -203,6 +175,7 @@ class CallRecord(Base):
|
|
| 203 |
created_at = Column(DateTime, default=datetime.utcnow)
|
| 204 |
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
| 205 |
|
|
|
|
| 206 |
customer = relationship("Customer", back_populates="call_records")
|
| 207 |
|
| 208 |
@classmethod
|
|
|
|
| 15 |
__tablename__ = "customers"
|
| 16 |
|
| 17 |
id = Column(Integer, primary_key=True, index=True)
|
| 18 |
+
name = Column(String(100), nullable=False)
|
| 19 |
+
company_name = Column(String(100), nullable=False)
|
| 20 |
+
email = Column(String(100), unique=True, nullable=False)
|
| 21 |
+
api_key = Column(String(100), unique=True, nullable=False)
|
| 22 |
is_active = Column(Boolean, default=True)
|
| 23 |
created_at = Column(DateTime, default=datetime.utcnow)
|
| 24 |
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
| 25 |
|
| 26 |
# Database credentials
|
| 27 |
+
db_host = Column(String(100), nullable=False)
|
| 28 |
+
db_port = Column(Integer, nullable=False, default=3306) # Default MySQL port
|
| 29 |
+
db_user = Column(String(100), nullable=False)
|
| 30 |
+
db_password = Column(String(100), nullable=False)
|
| 31 |
+
db_name = Column(String(100), nullable=False)
|
| 32 |
|
| 33 |
# Relationship with call records
|
| 34 |
+
call_records = relationship("CallRecord", back_populates="customer", cascade="all, delete-orphan")
|
| 35 |
|
| 36 |
def get_db_engine(self):
|
| 37 |
+
"""Create SQLAlchemy engine for customer's database"""
|
| 38 |
try:
|
| 39 |
+
db_url = f"mysql+pymysql://{self.db_user}:{self.db_password}@{self.db_host}:{self.db_port}/{self.db_name}"
|
|
|
|
|
|
|
|
|
|
| 40 |
engine = create_engine(db_url)
|
|
|
|
| 41 |
# Test connection
|
| 42 |
with engine.connect() as conn:
|
| 43 |
conn.execute("SELECT 1")
|
|
|
|
| 44 |
return engine
|
| 45 |
except Exception as e:
|
| 46 |
+
print(f"Error creating database engine: {str(e)}")
|
| 47 |
return None
|
| 48 |
|
| 49 |
def create_tables(self):
|
| 50 |
"""Create necessary tables in customer's database"""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
try:
|
| 52 |
+
engine = self.get_db_engine()
|
| 53 |
+
if not engine:
|
| 54 |
+
return False
|
| 55 |
Base.metadata.create_all(engine)
|
| 56 |
return True
|
| 57 |
except Exception as e:
|
| 58 |
print(f"Error creating tables: {str(e)}")
|
| 59 |
return False
|
| 60 |
|
| 61 |
+
def get_call_records(self):
|
| 62 |
+
"""Get all call records for this customer"""
|
| 63 |
engine = self.get_db_engine()
|
| 64 |
if not engine:
|
| 65 |
return []
|
| 66 |
+
Session = sessionmaker(bind=engine)
|
| 67 |
+
session = Session()
|
| 68 |
try:
|
| 69 |
+
records = session.query(CallRecord).filter(CallRecord.customer_id == self.id).all()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
return records
|
| 71 |
+
finally:
|
| 72 |
+
session.close()
|
|
|
|
| 73 |
|
| 74 |
+
def get_call_details(self, call_id: int):
|
| 75 |
+
"""Get detailed call information"""
|
| 76 |
engine = self.get_db_engine()
|
| 77 |
if not engine:
|
| 78 |
return None
|
| 79 |
+
Session = sessionmaker(bind=engine)
|
| 80 |
+
session = Session()
|
| 81 |
try:
|
|
|
|
|
|
|
|
|
|
| 82 |
record = session.query(CallRecord).filter(
|
| 83 |
CallRecord.id == call_id,
|
| 84 |
CallRecord.customer_id == self.id
|
| 85 |
).first()
|
|
|
|
|
|
|
| 86 |
return record
|
| 87 |
+
finally:
|
| 88 |
+
session.close()
|
|
|
|
| 89 |
|
| 90 |
+
def search_calls(self, query: str):
|
| 91 |
+
"""Search calls by transcription or summary"""
|
| 92 |
engine = self.get_db_engine()
|
| 93 |
if not engine:
|
| 94 |
return []
|
| 95 |
+
Session = sessionmaker(bind=engine)
|
| 96 |
+
session = Session()
|
| 97 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
records = session.query(CallRecord).filter(
|
| 99 |
CallRecord.customer_id == self.id,
|
| 100 |
+
(CallRecord.transcription.ilike(f"%{query}%") |
|
| 101 |
+
CallRecord.summary.ilike(f"%{query}%"))
|
| 102 |
).all()
|
|
|
|
|
|
|
| 103 |
return records
|
| 104 |
+
finally:
|
| 105 |
+
session.close()
|
|
|
|
| 106 |
|
| 107 |
def get_db_url(self) -> Optional[str]:
|
| 108 |
"""Get database URL if credentials are configured"""
|
|
|
|
| 164 |
class CallRecord(Base):
|
| 165 |
__tablename__ = "call_records"
|
| 166 |
|
| 167 |
+
id = Column(Integer, primary_key=True, index=True)
|
| 168 |
+
customer_id = Column(Integer, ForeignKey("customers.id"), nullable=False)
|
| 169 |
+
caller_number = Column(String(20), nullable=False)
|
| 170 |
+
called_number = Column(String(20), nullable=False)
|
| 171 |
file_path = Column(String(255), nullable=False)
|
| 172 |
transcription = Column(String(10000))
|
| 173 |
summary = Column(String(1000))
|
|
|
|
| 175 |
created_at = Column(DateTime, default=datetime.utcnow)
|
| 176 |
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
| 177 |
|
| 178 |
+
# Relationship with customer
|
| 179 |
customer = relationship("Customer", back_populates="call_records")
|
| 180 |
|
| 181 |
@classmethod
|
app/static/admin.html
CHANGED
|
@@ -58,6 +58,10 @@
|
|
| 58 |
<label for="db_host" class="form-label">Database Host</label>
|
| 59 |
<input type="text" class="form-control" id="db_host" required>
|
| 60 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
<div class="mb-3">
|
| 62 |
<label for="db_user" class="form-label">Database Username</label>
|
| 63 |
<input type="text" class="form-control" id="db_user" required>
|
|
@@ -150,6 +154,7 @@
|
|
| 150 |
company_name: document.getElementById('company_name').value,
|
| 151 |
email: document.getElementById('email').value,
|
| 152 |
db_host: document.getElementById('db_host').value,
|
|
|
|
| 153 |
db_user: document.getElementById('db_user').value,
|
| 154 |
db_password: document.getElementById('db_password').value,
|
| 155 |
db_name: document.getElementById('db_name').value
|
|
|
|
| 58 |
<label for="db_host" class="form-label">Database Host</label>
|
| 59 |
<input type="text" class="form-control" id="db_host" required>
|
| 60 |
</div>
|
| 61 |
+
<div class="mb-3">
|
| 62 |
+
<label for="db_port" class="form-label">Database Port</label>
|
| 63 |
+
<input type="number" class="form-control" id="db_port" value="3306" required>
|
| 64 |
+
</div>
|
| 65 |
<div class="mb-3">
|
| 66 |
<label for="db_user" class="form-label">Database Username</label>
|
| 67 |
<input type="text" class="form-control" id="db_user" required>
|
|
|
|
| 154 |
company_name: document.getElementById('company_name').value,
|
| 155 |
email: document.getElementById('email').value,
|
| 156 |
db_host: document.getElementById('db_host').value,
|
| 157 |
+
db_port: parseInt(document.getElementById('db_port').value),
|
| 158 |
db_user: document.getElementById('db_user').value,
|
| 159 |
db_password: document.getElementById('db_password').value,
|
| 160 |
db_name: document.getElementById('db_name').value
|