feat: add translation billing stats and remove Export/Settings pages
- Add TranslationLog model to track translation API usage per task - Integrate Dify API actual price (total_price) into translation stats - Display translation statistics in admin dashboard with per-task costs - Remove unused Export and Settings pages to simplify frontend - Add GET /api/v2/admin/translation-stats endpoint 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
87
backend/app/models/translation_log.py
Normal file
87
backend/app/models/translation_log.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""
|
||||
Tool_OCR - Translation Log Model
|
||||
Tracks translation usage statistics for billing and monitoring
|
||||
"""
|
||||
|
||||
from sqlalchemy import Column, Integer, String, DateTime, Float, ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class TranslationLog(Base):
|
||||
"""
|
||||
Translation log model for tracking API usage and costs.
|
||||
|
||||
Each record represents a single translation job completion,
|
||||
storing token usage and estimated costs for billing purposes.
|
||||
"""
|
||||
|
||||
__tablename__ = "tool_ocr_translation_logs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
user_id = Column(Integer, ForeignKey("tool_ocr_users.id", ondelete="CASCADE"),
|
||||
nullable=False, index=True,
|
||||
comment="Foreign key to users table")
|
||||
task_id = Column(String(255), nullable=False, index=True,
|
||||
comment="Task UUID that was translated")
|
||||
target_lang = Column(String(10), nullable=False, index=True,
|
||||
comment="Target language code (e.g., 'en', 'ja', 'zh-TW')")
|
||||
source_lang = Column(String(10), nullable=True,
|
||||
comment="Source language code (or 'auto')")
|
||||
|
||||
# Token usage statistics
|
||||
input_tokens = Column(Integer, default=0, nullable=False,
|
||||
comment="Number of input tokens used")
|
||||
output_tokens = Column(Integer, default=0, nullable=False,
|
||||
comment="Number of output tokens generated")
|
||||
total_tokens = Column(Integer, default=0, nullable=False,
|
||||
comment="Total tokens (input + output)")
|
||||
|
||||
# Translation statistics
|
||||
total_elements = Column(Integer, default=0, nullable=False,
|
||||
comment="Total elements in document")
|
||||
translated_elements = Column(Integer, default=0, nullable=False,
|
||||
comment="Number of elements translated")
|
||||
total_characters = Column(Integer, default=0, nullable=False,
|
||||
comment="Total characters translated")
|
||||
|
||||
# Cost tracking (estimated based on token pricing)
|
||||
estimated_cost = Column(Float, default=0.0, nullable=False,
|
||||
comment="Estimated cost in USD")
|
||||
|
||||
# Processing info
|
||||
processing_time_seconds = Column(Float, default=0.0, nullable=False,
|
||||
comment="Translation processing time")
|
||||
provider = Column(String(50), default="dify", nullable=False,
|
||||
comment="Translation provider (e.g., 'dify')")
|
||||
|
||||
# Timestamps
|
||||
created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
||||
|
||||
# Relationships
|
||||
user = relationship("User", back_populates="translation_logs")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<TranslationLog(id={self.id}, task_id='{self.task_id}', target_lang='{self.target_lang}', tokens={self.total_tokens})>"
|
||||
|
||||
def to_dict(self):
|
||||
"""Convert translation log to dictionary"""
|
||||
return {
|
||||
"id": self.id,
|
||||
"user_id": self.user_id,
|
||||
"task_id": self.task_id,
|
||||
"target_lang": self.target_lang,
|
||||
"source_lang": self.source_lang,
|
||||
"input_tokens": self.input_tokens,
|
||||
"output_tokens": self.output_tokens,
|
||||
"total_tokens": self.total_tokens,
|
||||
"total_elements": self.total_elements,
|
||||
"translated_elements": self.translated_elements,
|
||||
"total_characters": self.total_characters,
|
||||
"estimated_cost": self.estimated_cost,
|
||||
"processing_time_seconds": self.processing_time_seconds,
|
||||
"provider": self.provider,
|
||||
"created_at": self.created_at.isoformat() if self.created_at else None
|
||||
}
|
||||
Reference in New Issue
Block a user