mirror of
https://github.com/marcogll/telegram_expenses_controller.git
synced 2026-01-13 13:25:15 +00:00
feat: Implement core application structure, AI extraction, persistence, and Telegram bot modules with updated configuration and dependencies.
This commit is contained in:
0
app/schema/__init__.py
Normal file
0
app/schema/__init__.py
Normal file
80
app/schema/base.py
Normal file
80
app/schema/base.py
Normal file
@@ -0,0 +1,80 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional, List
|
||||
from datetime import datetime, date
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ExpenseStatus(str, Enum):
|
||||
"""
|
||||
Defines the explicit states an expense can be in throughout its lifecycle.
|
||||
"""
|
||||
RECEIVED = "RECEIVED"
|
||||
ANALYZED = "ANALYZED"
|
||||
AWAITING_CONFIRMATION = "AWAITING_CONFIRMATION"
|
||||
CONFIRMED = "CONFIRMED"
|
||||
CORRECTED = "CORRECTED"
|
||||
STORED = "STORED"
|
||||
|
||||
class RawInput(BaseModel):
|
||||
"""
|
||||
Represents the raw data received from the input source (e.g., n8n).
|
||||
"""
|
||||
user_id: str
|
||||
input_type: str = Field(..., alias="type", description="The type of input, e.g., 'text', 'voice', 'image', 'pdf'")
|
||||
data: str
|
||||
|
||||
class ExtractedExpense(BaseModel):
|
||||
"""
|
||||
Represents an expense after initial data extraction (e.g., from OCR or transcription).
|
||||
Fields are mostly optional as extraction may not be perfect.
|
||||
"""
|
||||
provider_name: Optional[str] = None
|
||||
amount: Optional[float] = None
|
||||
currency: Optional[str] = "MXN"
|
||||
expense_date: Optional[date] = None
|
||||
description: Optional[str] = None
|
||||
raw_text: str
|
||||
|
||||
class ProvisionalExpense(BaseModel):
|
||||
"""
|
||||
Represents a fully processed but unconfirmed expense.
|
||||
This is the state before the user validates the data.
|
||||
"""
|
||||
user_id: str
|
||||
extracted_data: ExtractedExpense
|
||||
|
||||
# Classified fields
|
||||
category: Optional[str] = "Por Determinar"
|
||||
subcategory: Optional[str] = None
|
||||
expense_type: Optional[str] = Field(None, alias="tipo_gasto_default", description="e.g., 'personal' or 'negocio'")
|
||||
|
||||
# Metadata
|
||||
confidence_score: float
|
||||
processing_method: str = Field(..., description="How the expense was classified, e.g., 'provider_match', 'keyword_match', 'ai_inference'")
|
||||
validation_notes: List[str] = []
|
||||
status: ExpenseStatus = ExpenseStatus.AWAITING_CONFIRMATION
|
||||
timestamp: datetime = Field(default_factory=datetime.now)
|
||||
|
||||
class FinalExpense(BaseModel):
|
||||
"""
|
||||
Represents a final, user-confirmed expense record.
|
||||
This is the data that will be stored permanently.
|
||||
"""
|
||||
user_id: str
|
||||
provider_name: str
|
||||
amount: float
|
||||
currency: str
|
||||
expense_date: date
|
||||
description: Optional[str] = None
|
||||
|
||||
category: str
|
||||
subcategory: Optional[str] = None
|
||||
expense_type: str
|
||||
|
||||
# Audit trail
|
||||
initial_processing_method: str
|
||||
confirmed_by: str
|
||||
confirmed_at: datetime = Field(default_factory=datetime.now)
|
||||
audit_log: List[str] = []
|
||||
|
||||
status: ExpenseStatus = ExpenseStatus.CONFIRMED
|
||||
14
app/schema/freeform.py
Normal file
14
app/schema/freeform.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
Pydantic schemas for unstructured or freeform text entries.
|
||||
"""
|
||||
from pydantic import BaseModel
|
||||
from datetime import datetime
|
||||
|
||||
class FreeformEntry(BaseModel):
|
||||
"""
|
||||
Represents a piece of text that could not be structured into an expense.
|
||||
"""
|
||||
user_id: str
|
||||
text: str
|
||||
timestamp: datetime
|
||||
notes: str = "Could not be automatically categorized."
|
||||
10
app/schema/receipt.py
Normal file
10
app/schema/receipt.py
Normal file
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
Pydantic schemas for structured receipts.
|
||||
"""
|
||||
from app.schema.base import FinalExpense
|
||||
|
||||
class Receipt(FinalExpense):
|
||||
"""
|
||||
A specialized expense model for receipts, could include line items in the future.
|
||||
"""
|
||||
pass
|
||||
18
app/schema/report.py
Normal file
18
app/schema/report.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""
|
||||
Pydantic schemas for reports or summaries.
|
||||
"""
|
||||
from pydantic import BaseModel
|
||||
from typing import List
|
||||
from datetime import date
|
||||
|
||||
class ExpenseReport(BaseModel):
|
||||
"""
|
||||
Represents a summary or report of multiple expenses.
|
||||
"""
|
||||
report_name: str
|
||||
start_date: date
|
||||
end_date: date
|
||||
total_amount: float
|
||||
expense_count: int
|
||||
# In a real app, you'd link to the actual expense models
|
||||
expenses: List[int]
|
||||
Reference in New Issue
Block a user