- Add Cloud for Sovereignty landing zone architecture and deployment - Implement complete legal document management system - Reorganize documentation with improved navigation - Add infrastructure improvements (Dockerfiles, K8s, monitoring) - Add operational improvements (graceful shutdown, rate limiting, caching) - Create comprehensive project structure documentation - Add Azure deployment automation scripts - Improve repository navigation and organization
358 lines
9.0 KiB
TypeScript
358 lines
9.0 KiB
TypeScript
/**
|
|
* Court Filing Management
|
|
* Handles e-filing, court submissions, and filing tracking
|
|
*/
|
|
|
|
import { query } from './client';
|
|
import { z } from 'zod';
|
|
|
|
export const CourtFilingSchema = z.object({
|
|
id: z.string().uuid(),
|
|
matter_id: z.string().uuid(),
|
|
document_id: z.string().uuid(),
|
|
filing_type: z.string(),
|
|
court_name: z.string(),
|
|
court_system: z.string().optional(),
|
|
case_number: z.string().optional(),
|
|
docket_number: z.string().optional(),
|
|
filing_date: z.date().optional(),
|
|
filing_deadline: z.date().optional(),
|
|
status: z.enum(['draft', 'submitted', 'accepted', 'rejected', 'filed']),
|
|
filing_reference: z.string().optional(),
|
|
filing_confirmation: z.string().optional(),
|
|
submitted_by: z.string().uuid().optional(),
|
|
submitted_at: z.date().optional(),
|
|
accepted_at: z.date().optional(),
|
|
rejection_reason: z.string().optional(),
|
|
metadata: z.record(z.unknown()).optional(),
|
|
created_at: z.date(),
|
|
updated_at: z.date(),
|
|
});
|
|
|
|
export type CourtFiling = z.infer<typeof CourtFilingSchema>;
|
|
|
|
export type FilingType =
|
|
| 'pleading'
|
|
| 'motion'
|
|
| 'brief'
|
|
| 'exhibit'
|
|
| 'affidavit'
|
|
| 'order'
|
|
| 'judgment'
|
|
| 'notice'
|
|
| 'response'
|
|
| 'reply'
|
|
| 'other';
|
|
|
|
export type CourtSystem = 'federal' | 'state' | 'municipal' | 'administrative' | 'other';
|
|
|
|
export interface CreateCourtFilingInput {
|
|
matter_id: string;
|
|
document_id: string;
|
|
filing_type: FilingType;
|
|
court_name: string;
|
|
court_system?: CourtSystem;
|
|
case_number?: string;
|
|
docket_number?: string;
|
|
filing_date?: Date | string;
|
|
filing_deadline?: Date | string;
|
|
status?: 'draft' | 'submitted' | 'accepted' | 'rejected' | 'filed';
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
|
|
/**
|
|
* Create a court filing record
|
|
*/
|
|
export async function createCourtFiling(input: CreateCourtFilingInput): Promise<CourtFiling> {
|
|
const result = await query<CourtFiling>(
|
|
`INSERT INTO court_filings
|
|
(matter_id, document_id, filing_type, court_name, court_system,
|
|
case_number, docket_number, filing_date, filing_deadline, status, metadata)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
RETURNING *`,
|
|
[
|
|
input.matter_id,
|
|
input.document_id,
|
|
input.filing_type,
|
|
input.court_name,
|
|
input.court_system || null,
|
|
input.case_number || null,
|
|
input.docket_number || null,
|
|
input.filing_date ? new Date(input.filing_date) : null,
|
|
input.filing_deadline ? new Date(input.filing_deadline) : null,
|
|
input.status || 'draft',
|
|
input.metadata ? JSON.stringify(input.metadata) : null,
|
|
]
|
|
);
|
|
|
|
return result.rows[0]!;
|
|
}
|
|
|
|
/**
|
|
* Get filing by ID
|
|
*/
|
|
export async function getCourtFiling(id: string): Promise<CourtFiling | null> {
|
|
const result = await query<CourtFiling>(
|
|
`SELECT * FROM court_filings WHERE id = $1`,
|
|
[id]
|
|
);
|
|
return result.rows[0] || null;
|
|
}
|
|
|
|
/**
|
|
* Get filings for a matter
|
|
*/
|
|
export async function getMatterFilings(
|
|
matter_id: string,
|
|
status?: string
|
|
): Promise<CourtFiling[]> {
|
|
const conditions = ['matter_id = $1'];
|
|
const params: unknown[] = [matter_id];
|
|
let paramIndex = 2;
|
|
|
|
if (status) {
|
|
conditions.push(`status = $${paramIndex++}`);
|
|
params.push(status);
|
|
}
|
|
|
|
const result = await query<CourtFiling>(
|
|
`SELECT * FROM court_filings
|
|
WHERE ${conditions.join(' AND ')}
|
|
ORDER BY filing_date DESC NULLS LAST, created_at DESC`,
|
|
params
|
|
);
|
|
|
|
return result.rows;
|
|
}
|
|
|
|
/**
|
|
* Get filings for a document
|
|
*/
|
|
export async function getDocumentFilings(document_id: string): Promise<CourtFiling[]> {
|
|
const result = await query<CourtFiling>(
|
|
`SELECT * FROM court_filings
|
|
WHERE document_id = $1
|
|
ORDER BY filing_date DESC NULLS LAST`,
|
|
[document_id]
|
|
);
|
|
return result.rows;
|
|
}
|
|
|
|
/**
|
|
* Update filing status
|
|
*/
|
|
export async function updateFilingStatus(
|
|
id: string,
|
|
status: 'draft' | 'submitted' | 'accepted' | 'rejected' | 'filed',
|
|
updates?: {
|
|
filing_reference?: string;
|
|
filing_confirmation?: string;
|
|
submitted_by?: string;
|
|
submitted_at?: Date;
|
|
accepted_at?: Date;
|
|
rejection_reason?: string;
|
|
}
|
|
): Promise<CourtFiling | null> {
|
|
const fields: string[] = [`status = $1`];
|
|
const values: unknown[] = [status];
|
|
let paramIndex = 2;
|
|
|
|
if (updates) {
|
|
if (updates.filing_reference !== undefined) {
|
|
fields.push(`filing_reference = $${paramIndex++}`);
|
|
values.push(updates.filing_reference);
|
|
}
|
|
|
|
if (updates.filing_confirmation !== undefined) {
|
|
fields.push(`filing_confirmation = $${paramIndex++}`);
|
|
values.push(updates.filing_confirmation);
|
|
}
|
|
|
|
if (updates.submitted_by !== undefined) {
|
|
fields.push(`submitted_by = $${paramIndex++}`);
|
|
values.push(updates.submitted_by);
|
|
}
|
|
|
|
if (updates.submitted_at !== undefined) {
|
|
fields.push(`submitted_at = $${paramIndex++}`);
|
|
values.push(updates.submitted_at);
|
|
} else if (status === 'submitted') {
|
|
fields.push(`submitted_at = NOW()`);
|
|
}
|
|
|
|
if (updates.accepted_at !== undefined) {
|
|
fields.push(`accepted_at = $${paramIndex++}`);
|
|
values.push(updates.accepted_at);
|
|
} else if (status === 'accepted' || status === 'filed') {
|
|
fields.push(`accepted_at = NOW()`);
|
|
}
|
|
|
|
if (updates.rejection_reason !== undefined) {
|
|
fields.push(`rejection_reason = $${paramIndex++}`);
|
|
values.push(updates.rejection_reason);
|
|
}
|
|
}
|
|
|
|
fields.push(`updated_at = NOW()`);
|
|
values.push(id);
|
|
|
|
const result = await query<CourtFiling>(
|
|
`UPDATE court_filings
|
|
SET ${fields.join(', ')}
|
|
WHERE id = $${paramIndex}
|
|
RETURNING *`,
|
|
values
|
|
);
|
|
|
|
return result.rows[0] || null;
|
|
}
|
|
|
|
/**
|
|
* Get upcoming filing deadlines
|
|
*/
|
|
export async function getUpcomingFilingDeadlines(
|
|
days_ahead = 30,
|
|
matter_id?: string
|
|
): Promise<CourtFiling[]> {
|
|
const conditions = [
|
|
`filing_deadline IS NOT NULL`,
|
|
`filing_deadline >= CURRENT_DATE`,
|
|
`filing_deadline <= CURRENT_DATE + INTERVAL '${days_ahead} days'`,
|
|
`status IN ('draft', 'submitted')`,
|
|
];
|
|
const params: unknown[] = [];
|
|
let paramIndex = 1;
|
|
|
|
if (matter_id) {
|
|
conditions.push(`matter_id = $${paramIndex++}`);
|
|
params.push(matter_id);
|
|
}
|
|
|
|
const result = await query<CourtFiling>(
|
|
`SELECT * FROM court_filings
|
|
WHERE ${conditions.join(' AND ')}
|
|
ORDER BY filing_deadline ASC`,
|
|
params
|
|
);
|
|
|
|
return result.rows;
|
|
}
|
|
|
|
/**
|
|
* Get filings by court
|
|
*/
|
|
export async function getFilingsByCourt(
|
|
court_name: string,
|
|
case_number?: string
|
|
): Promise<CourtFiling[]> {
|
|
const conditions = ['court_name = $1'];
|
|
const params: unknown[] = [court_name];
|
|
let paramIndex = 2;
|
|
|
|
if (case_number) {
|
|
conditions.push(`case_number = $${paramIndex++}`);
|
|
params.push(case_number);
|
|
}
|
|
|
|
const result = await query<CourtFiling>(
|
|
`SELECT * FROM court_filings
|
|
WHERE ${conditions.join(' AND ')}
|
|
ORDER BY filing_date DESC NULLS LAST`,
|
|
params
|
|
);
|
|
|
|
return result.rows;
|
|
}
|
|
|
|
/**
|
|
* Get filing statistics
|
|
*/
|
|
export interface FilingStatistics {
|
|
total: number;
|
|
by_status: Record<string, number>;
|
|
by_type: Record<string, number>;
|
|
upcoming_deadlines: number;
|
|
overdue: number;
|
|
}
|
|
|
|
export async function getFilingStatistics(
|
|
matter_id?: string
|
|
): Promise<FilingStatistics> {
|
|
const conditions: string[] = [];
|
|
const params: unknown[] = [];
|
|
let paramIndex = 1;
|
|
|
|
if (matter_id) {
|
|
conditions.push(`matter_id = $${paramIndex++}`);
|
|
params.push(matter_id);
|
|
}
|
|
|
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
|
|
// Get total and by status
|
|
const statusResult = await query<{ status: string; count: string }>(
|
|
`SELECT status, COUNT(*) as count
|
|
FROM court_filings
|
|
${whereClause}
|
|
GROUP BY status`,
|
|
params
|
|
);
|
|
|
|
// Get by type
|
|
const typeResult = await query<{ filing_type: string; count: string }>(
|
|
`SELECT filing_type, COUNT(*) as count
|
|
FROM court_filings
|
|
${whereClause}
|
|
GROUP BY filing_type`,
|
|
params
|
|
);
|
|
|
|
// Get upcoming deadlines
|
|
const upcomingResult = await query<{ count: string }>(
|
|
`SELECT COUNT(*) as count
|
|
FROM court_filings
|
|
${whereClause}
|
|
AND filing_deadline IS NOT NULL
|
|
AND filing_deadline >= CURRENT_DATE
|
|
AND filing_deadline <= CURRENT_DATE + INTERVAL '30 days'
|
|
AND status IN ('draft', 'submitted')`,
|
|
params
|
|
);
|
|
|
|
// Get overdue
|
|
const overdueResult = await query<{ count: string }>(
|
|
`SELECT COUNT(*) as count
|
|
FROM court_filings
|
|
${whereClause}
|
|
AND filing_deadline IS NOT NULL
|
|
AND filing_deadline < CURRENT_DATE
|
|
AND status IN ('draft', 'submitted')`,
|
|
params
|
|
);
|
|
|
|
const stats: FilingStatistics = {
|
|
total: 0,
|
|
by_status: {},
|
|
by_type: {},
|
|
upcoming_deadlines: parseInt(upcomingResult.rows[0]?.count || '0', 10),
|
|
overdue: parseInt(overdueResult.rows[0]?.count || '0', 10),
|
|
};
|
|
|
|
for (const row of statusResult.rows) {
|
|
const count = parseInt(row.count, 10);
|
|
stats.total += count;
|
|
stats.by_status[row.status] = count;
|
|
}
|
|
|
|
for (const row of typeResult.rows) {
|
|
stats.by_type[row.filing_type] = parseInt(row.count, 10);
|
|
}
|
|
|
|
return stats;
|
|
}
|
|
|
|
// Aliases for route compatibility
|
|
export const listCourtFilings = getMatterFilings;
|
|
export const getFilingDeadlines = getUpcomingFilingDeadlines;
|
|
|