- 新增数据库迁移脚本,为详情表添加四个价格相关字段 - 完善后端schema校验、序列化逻辑,增加价格相关的数据清理与验证规则 - 新增价格配置校验逻辑,设置起售价时必须选择对应的计价单位 - 在Admin UI详情编辑器中新增价格配置模块,支持配置起售价、计价单位、适用人数范围和价格说明 - 更新小程序端详情页面,支持展示配置的参考价格信息 - 补充相关测试用例,更新API文档与类型定义
65 lines
2.0 KiB
Python
65 lines
2.0 KiB
Python
"""Add configurable price presentation fields to detail records."""
|
|
|
|
from alembic import context, op
|
|
import sqlalchemy as sa
|
|
from sqlalchemy import inspect
|
|
|
|
from app.migration_compat import baseline_column_names
|
|
|
|
|
|
revision = "0037_detail_price_config"
|
|
down_revision = "0036_customer_browse_history"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
PRICE_COLUMNS = {
|
|
"priceStartingValue",
|
|
"priceUnit",
|
|
"pricePeopleRange",
|
|
"priceDescription",
|
|
}
|
|
|
|
|
|
def missing_price_columns(existing_columns: set[str]) -> set[str]:
|
|
return PRICE_COLUMNS.difference(existing_columns)
|
|
|
|
|
|
def is_offline_mode() -> bool:
|
|
try:
|
|
return context.is_offline_mode()
|
|
except (NameError, AttributeError):
|
|
return False
|
|
|
|
|
|
def upgrade() -> None:
|
|
if is_offline_mode():
|
|
columns_to_add = missing_price_columns(baseline_column_names("DetailRecord"))
|
|
else:
|
|
existing_columns = {
|
|
column["name"] for column in inspect(op.get_bind()).get_columns("DetailRecord")
|
|
}
|
|
columns_to_add = missing_price_columns(existing_columns)
|
|
|
|
definitions = {
|
|
"priceStartingValue": sa.Column("priceStartingValue", sa.Float(), nullable=True),
|
|
"priceUnit": sa.Column("priceUnit", sa.String(), nullable=True),
|
|
"pricePeopleRange": sa.Column("pricePeopleRange", sa.String(), nullable=True),
|
|
"priceDescription": sa.Column("priceDescription", sa.Text(), nullable=True),
|
|
}
|
|
for name, column in definitions.items():
|
|
if name in columns_to_add:
|
|
op.add_column("DetailRecord", column)
|
|
|
|
|
|
def downgrade() -> None:
|
|
if is_offline_mode():
|
|
columns_to_drop = PRICE_COLUMNS.intersection(baseline_column_names("DetailRecord"))
|
|
else:
|
|
columns_to_drop = {
|
|
column["name"] for column in inspect(op.get_bind()).get_columns("DetailRecord")
|
|
}.intersection(PRICE_COLUMNS)
|
|
|
|
for name in ("priceDescription", "pricePeopleRange", "priceUnit", "priceStartingValue"):
|
|
if name in columns_to_drop:
|
|
op.drop_column("DetailRecord", name)
|