diff --git a/alembic/versions/021_add_billing_records_table.py b/alembic/versions/021_add_billing_records_table.py new file mode 100644 index 000000000..ba0479a6c --- /dev/null +++ b/alembic/versions/021_add_billing_records_table.py @@ -0,0 +1,43 @@ +"""Task 3.09: Create billing_records table + +Revision ID: 021 +Revises: 020 +Create Date: 2026-07-03 + +新增 billing_records 表,用于存储账单记录。 +""" + +import sqlalchemy as sa + +from alembic import op + +revision = "021" +down_revision = "020" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.create_table( + "billing_records", + sa.Column("id", sa.String(36), primary_key=True), + sa.Column("user_id", sa.String(36), nullable=False, index=True), + sa.Column("plan_name", sa.String(50), nullable=False), + sa.Column("amount", sa.Float, nullable=False), + sa.Column("billing_cycle", sa.String(20), nullable=False), + sa.Column("status", sa.String(20), nullable=False, server_default="pending"), + sa.Column("payment_method", sa.String(50), nullable=True), + sa.Column("payment_id", sa.String(100), nullable=True), + sa.Column("invoice_url", sa.String(500), nullable=True), + sa.Column( + "created_at", + sa.DateTime(), + nullable=False, + server_default=sa.func.now(), + ), + sa.Column("paid_at", sa.DateTime(), nullable=True), + ) + + +def downgrade() -> None: + op.drop_table("billing_records") diff --git a/docs/schema-metadata-snapshot.json b/docs/schema-metadata-snapshot.json index 92906191a..b4364bcae 100644 --- a/docs/schema-metadata-snapshot.json +++ b/docs/schema-metadata-snapshot.json @@ -314,6 +314,110 @@ "id" ] }, + "billing_records": { + "columns": [ + { + "index": false, + "name": "id", + "nullable": false, + "primary_key": true, + "type": "VARCHAR(36)", + "unique": false + }, + { + "index": true, + "name": "user_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(36)", + "unique": false + }, + { + "index": false, + "name": "plan_name", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(50)", + "unique": false + }, + { + "index": false, + "name": "amount", + "nullable": false, + "primary_key": false, + "type": "FLOAT", + "unique": false + }, + { + "index": false, + "name": "billing_cycle", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "status", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "payment_method", + "nullable": true, + "primary_key": false, + "type": "VARCHAR(50)", + "unique": false + }, + { + "index": false, + "name": "payment_id", + "nullable": true, + "primary_key": false, + "type": "VARCHAR(100)", + "unique": false + }, + { + "index": false, + "name": "invoice_url", + "nullable": true, + "primary_key": false, + "type": "VARCHAR(500)", + "unique": false + }, + { + "index": false, + "name": "created_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "paid_at", + "nullable": true, + "primary_key": false, + "type": "DATETIME", + "unique": false + } + ], + "indexes": [ + { + "columns": [ + "user_id" + ], + "name": "ix_billing_records_user_id", + "unique": false + } + ], + "primary_key": [ + "id" + ] + }, "classification_jobs": { "columns": [ { @@ -624,7 +728,7 @@ "id" ] }, - "edit_templates": { + "edit_plan_clips": { "columns": [ { "index": false, @@ -636,7 +740,39 @@ }, { "index": true, - "name": "project_id", + "name": "plan_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": true, + "name": "clip_type", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "order", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": true, + "name": "template_clip_config_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": true, + "name": "asset_id", "nullable": false, "primary_key": false, "type": "VARCHAR(32)", @@ -644,15 +780,7 @@ }, { "index": false, - "name": "name", - "nullable": false, - "primary_key": false, - "type": "VARCHAR(120)", - "unique": false - }, - { - "index": false, - "name": "description", + "name": "text_content", "nullable": false, "primary_key": false, "type": "TEXT", @@ -660,7 +788,7 @@ }, { "index": false, - "name": "target_duration", + "name": "start_time", "nullable": false, "primary_key": false, "type": "FLOAT", @@ -668,31 +796,31 @@ }, { "index": false, - "name": "clip_count", + "name": "duration", "nullable": false, "primary_key": false, - "type": "INTEGER", + "type": "FLOAT", "unique": false }, { "index": false, - "name": "is_active", + "name": "transition_effect", "nullable": false, "primary_key": false, - "type": "BOOLEAN", + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": true, + "name": "status", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", "unique": false }, { "index": false, - "name": "created_by_user_id", - "nullable": false, - "primary_key": false, - "type": "VARCHAR(32)", - "unique": false - }, - { - "index": false, - "name": "metadata", + "name": "config", "nullable": false, "primary_key": false, "type": "JSON", @@ -718,9 +846,234 @@ "indexes": [ { "columns": [ - "project_id" + "asset_id" ], - "name": "ix_edit_templates_project_id", + "name": "ix_edit_plan_clips_asset_id", + "unique": false + }, + { + "columns": [ + "clip_type" + ], + "name": "ix_edit_plan_clips_clip_type", + "unique": false + }, + { + "columns": [ + "plan_id" + ], + "name": "ix_edit_plan_clips_plan_id", + "unique": false + }, + { + "columns": [ + "status" + ], + "name": "ix_edit_plan_clips_status", + "unique": false + }, + { + "columns": [ + "template_clip_config_id" + ], + "name": "ix_edit_plan_clips_template_clip_config_id", + "unique": false + } + ], + "primary_key": [ + "id" + ] + }, + "edit_plans": { + "columns": [ + { + "index": false, + "name": "id", + "nullable": false, + "primary_key": true, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": true, + "name": "template_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": false, + "name": "name", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(200)", + "unique": false + }, + { + "index": true, + "name": "status", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "total_duration", + "nullable": false, + "primary_key": false, + "type": "FLOAT", + "unique": false + }, + { + "index": false, + "name": "config", + "nullable": false, + "primary_key": false, + "type": "JSON", + "unique": false + }, + { + "index": false, + "name": "created_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "updated_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + } + ], + "indexes": [ + { + "columns": [ + "status" + ], + "name": "ix_edit_plans_status", + "unique": false + }, + { + "columns": [ + "template_id" + ], + "name": "ix_edit_plans_template_id", + "unique": false + } + ], + "primary_key": [ + "id" + ] + }, + "edit_templates": { + "columns": [ + { + "index": false, + "name": "id", + "nullable": false, + "primary_key": true, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": false, + "name": "name", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(120)", + "unique": false + }, + { + "index": false, + "name": "description", + "nullable": false, + "primary_key": false, + "type": "TEXT", + "unique": false + }, + { + "index": true, + "name": "template_type", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(50)", + "unique": false + }, + { + "index": false, + "name": "config", + "nullable": false, + "primary_key": false, + "type": "JSON", + "unique": false + }, + { + "index": false, + "name": "preview_url", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(1000)", + "unique": false + }, + { + "index": true, + "name": "sort_weight", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": true, + "name": "status", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "created_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "updated_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + } + ], + "indexes": [ + { + "columns": [ + "sort_weight" + ], + "name": "ix_edit_templates_sort_weight", + "unique": false + }, + { + "columns": [ + "status" + ], + "name": "ix_edit_templates_status", + "unique": false + }, + { + "columns": [ + "template_type" + ], + "name": "ix_edit_templates_template_type", "unique": false } ], @@ -1223,6 +1576,194 @@ "id" ] }, + "jobs": { + "columns": [ + { + "index": false, + "name": "id", + "nullable": false, + "primary_key": true, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": true, + "name": "project_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": true, + "name": "job_type", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(30)", + "unique": false + }, + { + "index": true, + "name": "status", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "progress", + "nullable": false, + "primary_key": false, + "type": "FLOAT", + "unique": false + }, + { + "index": false, + "name": "current_stage", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(200)", + "unique": false + }, + { + "index": false, + "name": "payload", + "nullable": false, + "primary_key": false, + "type": "JSON", + "unique": false + }, + { + "index": false, + "name": "result", + "nullable": false, + "primary_key": false, + "type": "JSON", + "unique": false + }, + { + "index": false, + "name": "error_message", + "nullable": false, + "primary_key": false, + "type": "TEXT", + "unique": false + }, + { + "index": false, + "name": "retry_count", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": false, + "name": "max_retries", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": false, + "name": "celery_task_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(100)", + "unique": false + }, + { + "index": true, + "name": "source_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": true, + "name": "created_by_user_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": false, + "name": "started_at", + "nullable": true, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "completed_at", + "nullable": true, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "created_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "updated_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + } + ], + "indexes": [ + { + "columns": [ + "created_by_user_id" + ], + "name": "ix_jobs_created_by_user_id", + "unique": false + }, + { + "columns": [ + "job_type" + ], + "name": "ix_jobs_job_type", + "unique": false + }, + { + "columns": [ + "project_id" + ], + "name": "ix_jobs_project_id", + "unique": false + }, + { + "columns": [ + "source_id" + ], + "name": "ix_jobs_source_id", + "unique": false + }, + { + "columns": [ + "status" + ], + "name": "ix_jobs_status", + "unique": false + } + ], + "primary_key": [ + "id" + ] + }, "projects": { "columns": [ { @@ -1503,6 +2044,125 @@ "id" ] }, + "template_clip_configs": { + "columns": [ + { + "index": false, + "name": "id", + "nullable": false, + "primary_key": true, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": true, + "name": "template_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(32)", + "unique": false + }, + { + "index": true, + "name": "clip_type", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "order", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": false, + "name": "min_duration", + "nullable": false, + "primary_key": false, + "type": "FLOAT", + "unique": false + }, + { + "index": false, + "name": "max_duration", + "nullable": false, + "primary_key": false, + "type": "FLOAT", + "unique": false + }, + { + "index": false, + "name": "text_template", + "nullable": false, + "primary_key": false, + "type": "TEXT", + "unique": false + }, + { + "index": false, + "name": "material_requirements", + "nullable": false, + "primary_key": false, + "type": "JSON", + "unique": false + }, + { + "index": false, + "name": "transition_effect", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "config", + "nullable": false, + "primary_key": false, + "type": "JSON", + "unique": false + }, + { + "index": false, + "name": "created_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "updated_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + } + ], + "indexes": [ + { + "columns": [ + "clip_type" + ], + "name": "ix_template_clip_configs_clip_type", + "unique": false + }, + { + "columns": [ + "template_id" + ], + "name": "ix_template_clip_configs_template_id", + "unique": false + } + ], + "primary_key": [ + "id" + ] + }, "template_segments": { "columns": [ { @@ -1836,6 +2496,205 @@ "id" ] }, + "tts_jobs": { + "columns": [ + { + "index": false, + "name": "id", + "nullable": false, + "primary_key": true, + "type": "VARCHAR(36)", + "unique": false + }, + { + "index": true, + "name": "user_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(36)", + "unique": false + }, + { + "index": false, + "name": "input_text", + "nullable": false, + "primary_key": false, + "type": "TEXT", + "unique": false + }, + { + "index": false, + "name": "voice_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(100)", + "unique": false + }, + { + "index": false, + "name": "voice_model", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(100)", + "unique": false + }, + { + "index": false, + "name": "project_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(36)", + "unique": false + }, + { + "index": false, + "name": "voice_clone_profile_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(36)", + "unique": false + }, + { + "index": true, + "name": "status", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "output_audio_url", + "nullable": false, + "primary_key": false, + "type": "TEXT", + "unique": false + }, + { + "index": false, + "name": "output_audio_key", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(500)", + "unique": false + }, + { + "index": false, + "name": "duration", + "nullable": false, + "primary_key": false, + "type": "FLOAT", + "unique": false + }, + { + "index": false, + "name": "file_size", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": false, + "name": "sample_rate", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": false, + "name": "format", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "error_message", + "nullable": false, + "primary_key": false, + "type": "TEXT", + "unique": false + }, + { + "index": false, + "name": "retry_count", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": false, + "name": "max_retries", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": false, + "name": "metadata", + "nullable": false, + "primary_key": false, + "type": "JSON", + "unique": false + }, + { + "index": false, + "name": "started_at", + "nullable": true, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "completed_at", + "nullable": true, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "created_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "updated_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + } + ], + "indexes": [ + { + "columns": [ + "status" + ], + "name": "ix_tts_jobs_status", + "unique": false + }, + { + "columns": [ + "user_id" + ], + "name": "ix_tts_jobs_user_id", + "unique": false + } + ], + "primary_key": [ + "id" + ] + }, "users": { "columns": [ { @@ -2003,6 +2862,157 @@ "id" ] }, + "voice_clone_profiles": { + "columns": [ + { + "index": false, + "name": "id", + "nullable": false, + "primary_key": true, + "type": "VARCHAR(36)", + "unique": false + }, + { + "index": true, + "name": "user_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(36)", + "unique": false + }, + { + "index": false, + "name": "name", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(100)", + "unique": false + }, + { + "index": false, + "name": "description", + "nullable": false, + "primary_key": false, + "type": "TEXT", + "unique": false + }, + { + "index": false, + "name": "source_audio_url", + "nullable": false, + "primary_key": false, + "type": "TEXT", + "unique": false + }, + { + "index": false, + "name": "voice_id", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(100)", + "unique": false + }, + { + "index": false, + "name": "voice_model", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(100)", + "unique": false + }, + { + "index": false, + "name": "language", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "gender", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": true, + "name": "status", + "nullable": false, + "primary_key": false, + "type": "VARCHAR(20)", + "unique": false + }, + { + "index": false, + "name": "error_message", + "nullable": false, + "primary_key": false, + "type": "TEXT", + "unique": false + }, + { + "index": false, + "name": "retry_count", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": false, + "name": "max_retries", + "nullable": false, + "primary_key": false, + "type": "INTEGER", + "unique": false + }, + { + "index": false, + "name": "metadata", + "nullable": false, + "primary_key": false, + "type": "JSON", + "unique": false + }, + { + "index": false, + "name": "created_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + }, + { + "index": false, + "name": "updated_at", + "nullable": false, + "primary_key": false, + "type": "DATETIME", + "unique": false + } + ], + "indexes": [ + { + "columns": [ + "status" + ], + "name": "ix_voice_clone_profiles_status", + "unique": false + }, + { + "columns": [ + "user_id" + ], + "name": "ix_voice_clone_profiles_user_id", + "unique": false + } + ], + "primary_key": [ + "id" + ] + }, "voice_libraries": { "columns": [ {