Skip to content

Commit 0b7973a

Browse files
committed
Update README to reflect actual implemented features
1 parent f4b4388 commit 0b7973a

12 files changed

Lines changed: 1977 additions & 7 deletions

File tree

README.md

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
1-
# SmartProBono - Legal Help Made Simple
1+
# SmartProBono - Complete Legal Platform
22

3-
A streamlined legal assistance platform with AI-powered document analysis and generation.
3+
A comprehensive legal assistance platform with AI-powered features, role-based dashboards, and real-time case management.
44

5-
## 🚀 Features
5+
## 🚀 Core Features
66

7+
### 🤖 AI-Powered Features
8+
- **AI Virtual Paralegal**: Autonomous AI system for case research and document generation
9+
- **Legal AI Chat**: Instant legal assistance and guidance
710
- **Document Scanner**: Upload and analyze legal documents with AI insights
811
- **PDF Generator**: Create professional legal documents from templates
9-
- **AI Legal Chat**: Get instant legal assistance (coming soon)
12+
- **Case Law Research**: Real-time access to CourtListener API for case law research
13+
14+
### 👥 Role-Based Dashboards
15+
- **Client Portal**: Case tracking, progress monitoring, document access
16+
- **Lawyer Dashboard**: Case management, client communication, analytics
17+
- **Bondsman Dashboard**: Bail bond management, payment tracking, risk assessment
18+
- **Admin Dashboard**: System management, user analytics, compliance monitoring
19+
20+
### 🔄 Real-Time Features
21+
- **Live Notifications**: Real-time updates on case progress and deadlines
22+
- **WebSocket Integration**: Instant communication and updates
23+
- **Progress Tracking**: Visual progress bars and status updates
24+
- **Document Collaboration**: Real-time document sharing and editing
25+
26+
### ⚖️ Legal Tools
27+
- **Document Analysis**: AI-powered legal document review
28+
- **Form Generation**: Automated legal form creation
29+
- **Compliance Scanner**: Legal compliance checking
30+
- **Risk Assessment**: Automated risk analysis for cases
1031

1132
## 🛠️ Quick Start
1233

@@ -52,17 +73,62 @@ SmartProBono-main/
5273

5374
## 🔧 API Endpoints
5475

76+
### Document Processing
5577
- `GET /api/scanner/health` - Document scanner health check
5678
- `POST /api/scanner/analyze` - Analyze uploaded documents
5779
- `GET /api/generator/templates` - Get document templates
5880
- `POST /api/generator/create` - Generate PDF documents
81+
82+
### AI Virtual Paralegal
83+
- `POST /api/v1/ai-virtual-paralegal/start` - Start AI workflow
84+
- `GET /api/v1/ai-virtual-paralegal/status` - Get AI status
85+
- `GET /api/v1/ai-virtual-paralegal/logs` - Get activity logs
86+
- `POST /api/v1/ai-virtual-paralegal/search-cases` - Search CourtListener API
87+
- `POST /api/v1/ai-virtual-paralegal/similar-cases` - Find similar cases
88+
- `GET /api/v1/ai-virtual-paralegal/recent-cases` - Get recent cases
89+
- `POST /api/v1/ai-virtual-paralegal/generate-document` - Generate documents
90+
- `GET /api/v1/ai-virtual-paralegal/dashboard` - Get dashboard data
91+
92+
### Enhanced API (v2)
93+
- `GET /api/v2/` - API documentation and root
94+
- `GET /api/v2/cases/` - List cases with pagination
95+
- `POST /api/v2/cases/` - Create new case
96+
- `GET /api/v2/cases/{id}/` - Get specific case
97+
- `PUT /api/v2/cases/{id}/` - Update case
98+
- `DELETE /api/v2/cases/{id}/` - Delete case
99+
- `GET /api/v2/users/` - List users
100+
- `GET /api/v2/documents/` - List documents
101+
- `GET /api/v2/health/` - Health check
102+
103+
### Contact & Support
59104
- `POST /api/contact/submit` - Submit contact form
60105

61106
## 🌐 Access
62107

63-
- Frontend: http://localhost:3002
64-
- Backend: http://localhost:3001
65-
- Legal Tools: http://localhost:3002/legal-tools
108+
### Main Application
109+
- **Frontend**: http://localhost:3002
110+
- **Backend**: http://localhost:3001
111+
112+
### User Dashboards
113+
- **Client Portal**: http://localhost:3002/client-portal
114+
- **Lawyer Dashboard**: http://localhost:3002/lawyer-dashboard
115+
- **Bondsman Dashboard**: http://localhost:3002/bondsman-dashboard
116+
- **Admin Dashboard**: http://localhost:3002/admin
117+
118+
### AI Features
119+
- **AI Virtual Paralegal**: http://localhost:3002/ai-virtual-paralegal
120+
- **Legal AI Chat**: http://localhost:3002/legal-chat
121+
- **Virtual Paralegal**: http://localhost:3002/virtual-paralegal
122+
123+
### Legal Tools
124+
- **Legal Tools**: http://localhost:3002/legal-tools
125+
- **Document Scanner**: http://localhost:3002/document-scanner
126+
- **Document Generator**: http://localhost:3002/generate-document
127+
- **Safety Check**: http://localhost:3002/safety-check
128+
129+
### API Documentation
130+
- **Enhanced API**: http://localhost:3001/api/v2/
131+
- **API Health**: http://localhost:3001/api/v2/health/
66132

67133
## 📝 License
68134

backend/models/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from .document import Document
44
from .notification import Notification
55
from .case import Case
6+
from .payment import Payment, BailBond, CourtDate
7+
from .client_intake import ClientIntake, Task
68
from .audit import (
79
AuditLog, UserActivity, SecurityEvent, PerformanceMetric,
810
ComplianceRecord, APIAudit, DocumentAudit,
@@ -14,6 +16,11 @@
1416
'Document',
1517
'Notification',
1618
'Case',
19+
'Payment',
20+
'BailBond',
21+
'CourtDate',
22+
'ClientIntake',
23+
'Task',
1724
'AuditLog',
1825
'UserActivity',
1926
'SecurityEvent',

backend/models/client_intake.py

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
"""
2+
Client intake model for the SmartProBono application.
3+
Handles the complete client intake process from initial contact to case assignment.
4+
"""
5+
from datetime import datetime
6+
from database import db
7+
import json
8+
9+
class ClientIntake(db.Model):
10+
"""Client intake model for storing intake information."""
11+
__tablename__ = 'client_intakes'
12+
13+
id = db.Column(db.Integer, primary_key=True)
14+
client_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True) # Can be null for anonymous intakes
15+
16+
# Personal Information
17+
first_name = db.Column(db.String(100), nullable=False)
18+
last_name = db.Column(db.String(100), nullable=False)
19+
email = db.Column(db.String(255), nullable=False)
20+
phone = db.Column(db.String(20), nullable=False)
21+
date_of_birth = db.Column(db.Date, nullable=True)
22+
23+
# Address Information
24+
street_address = db.Column(db.String(255), nullable=True)
25+
city = db.Column(db.String(100), nullable=True)
26+
state = db.Column(db.String(50), nullable=True)
27+
zip_code = db.Column(db.String(20), nullable=True)
28+
country = db.Column(db.String(100), default='USA')
29+
30+
# Legal Information
31+
legal_issue_type = db.Column(db.String(100), nullable=False) # immigration, family, criminal, civil, etc.
32+
case_description = db.Column(db.Text, nullable=False)
33+
urgency_level = db.Column(db.String(20), default='medium') # low, medium, high, emergency
34+
35+
# Financial Information
36+
income_level = db.Column(db.String(50), nullable=True) # low, medium, high
37+
can_afford_legal_fees = db.Column(db.Boolean, nullable=True)
38+
needs_pro_bono = db.Column(db.Boolean, default=False)
39+
40+
# Case Details
41+
case_start_date = db.Column(db.Date, nullable=True) # When the legal issue started
42+
previous_legal_representation = db.Column(db.Boolean, default=False)
43+
previous_attorney_name = db.Column(db.String(255), nullable=True)
44+
45+
# Status and Processing
46+
status = db.Column(db.String(50), default='submitted') # submitted, under_review, assigned, rejected, completed
47+
assigned_lawyer_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
48+
assigned_paralegal_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
49+
50+
# AI Analysis Results
51+
ai_analysis = db.Column(db.Text, nullable=True) # JSON string with AI analysis
52+
recommended_actions = db.Column(db.Text, nullable=True) # JSON string with recommendations
53+
risk_assessment = db.Column(db.String(20), nullable=True) # low, medium, high
54+
55+
# Dates
56+
submitted_at = db.Column(db.DateTime, default=datetime.utcnow)
57+
reviewed_at = db.Column(db.DateTime, nullable=True)
58+
assigned_at = db.Column(db.DateTime, nullable=True)
59+
completed_at = db.Column(db.DateTime, nullable=True)
60+
created_at = db.Column(db.DateTime, default=datetime.utcnow)
61+
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
62+
63+
# Additional Information
64+
notes = db.Column(db.Text, nullable=True)
65+
_metadata = db.Column('metadata', db.Text, nullable=True) # JSON for additional data
66+
_documents = db.Column('documents', db.Text, nullable=True) # JSON array of document IDs
67+
68+
@property
69+
def metadata(self):
70+
"""Get intake metadata as a dictionary."""
71+
if not self._metadata:
72+
return {}
73+
return json.loads(self._metadata)
74+
75+
@metadata.setter
76+
def metadata(self, value):
77+
"""Set intake metadata from a dictionary."""
78+
if isinstance(value, dict):
79+
self._metadata = json.dumps(value)
80+
else:
81+
self._metadata = None
82+
83+
@property
84+
def documents(self):
85+
"""Get associated document IDs as a list."""
86+
if not self._documents:
87+
return []
88+
return json.loads(self._documents)
89+
90+
@documents.setter
91+
def documents(self, value):
92+
"""Set associated document IDs from a list."""
93+
if isinstance(value, list):
94+
self._documents = json.dumps(value)
95+
else:
96+
self._documents = None
97+
98+
def add_document(self, document_id):
99+
"""Add a document ID to the intake."""
100+
current_docs = self.documents
101+
if document_id not in current_docs:
102+
current_docs.append(document_id)
103+
self.documents = current_docs
104+
105+
def get_full_name(self):
106+
"""Get the client's full name."""
107+
return f"{self.first_name} {self.last_name}"
108+
109+
def get_full_address(self):
110+
"""Get the client's full address."""
111+
address_parts = [self.street_address, self.city, self.state, self.zip_code]
112+
return ", ".join([part for part in address_parts if part])
113+
114+
def to_dict(self):
115+
"""Convert intake to a dictionary."""
116+
return {
117+
'id': self.id,
118+
'client_id': self.client_id,
119+
'first_name': self.first_name,
120+
'last_name': self.last_name,
121+
'full_name': self.get_full_name(),
122+
'email': self.email,
123+
'phone': self.phone,
124+
'date_of_birth': self.date_of_birth.isoformat() if self.date_of_birth else None,
125+
'street_address': self.street_address,
126+
'city': self.city,
127+
'state': self.state,
128+
'zip_code': self.zip_code,
129+
'country': self.country,
130+
'full_address': self.get_full_address(),
131+
'legal_issue_type': self.legal_issue_type,
132+
'case_description': self.case_description,
133+
'urgency_level': self.urgency_level,
134+
'income_level': self.income_level,
135+
'can_afford_legal_fees': self.can_afford_legal_fees,
136+
'needs_pro_bono': self.needs_pro_bono,
137+
'case_start_date': self.case_start_date.isoformat() if self.case_start_date else None,
138+
'previous_legal_representation': self.previous_legal_representation,
139+
'previous_attorney_name': self.previous_attorney_name,
140+
'status': self.status,
141+
'assigned_lawyer_id': self.assigned_lawyer_id,
142+
'assigned_paralegal_id': self.assigned_paralegal_id,
143+
'ai_analysis': json.loads(self.ai_analysis) if self.ai_analysis else None,
144+
'recommended_actions': json.loads(self.recommended_actions) if self.recommended_actions else None,
145+
'risk_assessment': self.risk_assessment,
146+
'submitted_at': self.submitted_at.isoformat() if self.submitted_at else None,
147+
'reviewed_at': self.reviewed_at.isoformat() if self.reviewed_at else None,
148+
'assigned_at': self.assigned_at.isoformat() if self.assigned_at else None,
149+
'completed_at': self.completed_at.isoformat() if self.completed_at else None,
150+
'created_at': self.created_at.isoformat() if self.created_at else None,
151+
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
152+
'notes': self.notes,
153+
'metadata': self.metadata,
154+
'documents': self.documents
155+
}
156+
157+
def __repr__(self):
158+
return f'<ClientIntake {self.id}: {self.get_full_name()} - {self.legal_issue_type}>'
159+
160+
161+
class Task(db.Model):
162+
"""Task model for managing legal tasks and assignments."""
163+
__tablename__ = 'tasks'
164+
165+
id = db.Column(db.Integer, primary_key=True)
166+
case_id = db.Column(db.Integer, db.ForeignKey('cases.id'), nullable=True)
167+
intake_id = db.Column(db.Integer, db.ForeignKey('client_intakes.id'), nullable=True)
168+
assigned_to = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
169+
assigned_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
170+
171+
# Task details
172+
title = db.Column(db.String(255), nullable=False)
173+
description = db.Column(db.Text, nullable=True)
174+
task_type = db.Column(db.String(50), nullable=False) # research, document_review, client_meeting, court_filing, etc.
175+
priority = db.Column(db.String(20), default='medium') # low, medium, high, urgent
176+
177+
# Status and tracking
178+
status = db.Column(db.String(50), default='pending') # pending, in_progress, completed, cancelled, overdue
179+
progress_percentage = db.Column(db.Integer, default=0)
180+
181+
# Dates
182+
due_date = db.Column(db.DateTime, nullable=True)
183+
started_at = db.Column(db.DateTime, nullable=True)
184+
completed_at = db.Column(db.DateTime, nullable=True)
185+
created_at = db.Column(db.DateTime, default=datetime.utcnow)
186+
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
187+
188+
# Additional info
189+
notes = db.Column(db.Text, nullable=True)
190+
_metadata = db.Column('metadata', db.Text, nullable=True)
191+
192+
@property
193+
def metadata(self):
194+
"""Get task metadata as a dictionary."""
195+
if not self._metadata:
196+
return {}
197+
return json.loads(self._metadata)
198+
199+
@metadata.setter
200+
def metadata(self, value):
201+
"""Set task metadata from a dictionary."""
202+
if isinstance(value, dict):
203+
self._metadata = json.dumps(value)
204+
else:
205+
self._metadata = None
206+
207+
def is_overdue(self):
208+
"""Check if the task is overdue."""
209+
if not self.due_date or self.status in ['completed', 'cancelled']:
210+
return False
211+
return datetime.utcnow() > self.due_date
212+
213+
def to_dict(self):
214+
"""Convert task to a dictionary."""
215+
return {
216+
'id': self.id,
217+
'case_id': self.case_id,
218+
'intake_id': self.intake_id,
219+
'assigned_to': self.assigned_to,
220+
'assigned_by': self.assigned_by,
221+
'title': self.title,
222+
'description': self.description,
223+
'task_type': self.task_type,
224+
'priority': self.priority,
225+
'status': self.status,
226+
'progress_percentage': self.progress_percentage,
227+
'due_date': self.due_date.isoformat() if self.due_date else None,
228+
'started_at': self.started_at.isoformat() if self.started_at else None,
229+
'completed_at': self.completed_at.isoformat() if self.completed_at else None,
230+
'created_at': self.created_at.isoformat() if self.created_at else None,
231+
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
232+
'notes': self.notes,
233+
'metadata': self.metadata,
234+
'is_overdue': self.is_overdue()
235+
}
236+
237+
def __repr__(self):
238+
return f'<Task {self.id}: {self.title} - {self.status}>'

0 commit comments

Comments
 (0)