init: 管理会计OS初始代码
包含前后端完整代码: - 前端:Vue3+Vite+ElementPlus - 后端:FastAPI+SQLAlchemy - 模块:驾驶舱/KPI/战略地图/预警/预算/成本/预测/改善行动 - 当前版本:v1.0.0
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
"""管理会计OS 数据模型"""
|
||||
from sqlalchemy import Column, Integer, String, Text, Float, DateTime, ForeignKey, Boolean, JSON, func
|
||||
from app.database import Base
|
||||
|
||||
from app.models.budget_plan import BudgetPlan
|
||||
from app.models.cost_model import StandardCost, ActualCost, AbcActivity, AbcAllocation
|
||||
|
||||
|
||||
class User(Base):
|
||||
"""用户"""
|
||||
__tablename__ = "users"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
username = Column(String(50), unique=True, nullable=False)
|
||||
password_hash = Column(String(128), nullable=False)
|
||||
name = Column(String(100), nullable=False)
|
||||
role = Column(String(20), default="finance") # ceo / finance / business / it
|
||||
phone = Column(String(20), nullable=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
|
||||
|
||||
class StrategicMap(Base):
|
||||
"""战略地图"""
|
||||
__tablename__ = "strategic_maps"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
title = Column(String(200), nullable=False, comment="地图名称")
|
||||
version = Column(String(20), default="v1.0", comment="版本号")
|
||||
status = Column(String(20), default="draft", comment="draft/published")
|
||||
dimensions = Column(JSON, nullable=True, comment="四维度和目标列表")
|
||||
canvas_data = Column(JSON, nullable=True, comment="画布连线数据")
|
||||
created_by = Column(Integer, nullable=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
|
||||
|
||||
class KPIDefinition(Base):
|
||||
"""KPI字典"""
|
||||
__tablename__ = "kpi_definitions"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
map_id = Column(Integer, ForeignKey("strategic_maps.id"), nullable=True, comment="关联战略地图")
|
||||
kpi_code = Column(String(50), unique=True, nullable=False, comment="KPI编码")
|
||||
kpi_name = Column(String(200), nullable=False, comment="KPI名称")
|
||||
dimension = Column(String(50), comment="所属维度: finance/customer/process/learning")
|
||||
objective = Column(String(200), comment="关联战略目标")
|
||||
formula = Column(Text, nullable=True, comment="计算公式")
|
||||
formula_desc = Column(String(500), nullable=True, comment="公式说明")
|
||||
data_source_type = Column(String(20), default="manual", comment="erp/business/excel/manual")
|
||||
data_source_config = Column(JSON, nullable=True, comment="数据源配置")
|
||||
frequency = Column(String(20), default="monthly", comment="daily/weekly/monthly/quarterly/yearly")
|
||||
unit = Column(String(50), default="%", comment="单位")
|
||||
target_value = Column(Float, nullable=True, comment="目标值")
|
||||
threshold_green = Column(String(100), nullable=True, comment="绿灯阈值")
|
||||
threshold_yellow = Column(String(100), nullable=True, comment="黄灯阈值")
|
||||
threshold_red = Column(String(100), nullable=True, comment="红灯阈值")
|
||||
category = Column(String(50), nullable=True, comment="BSC二级类别: revenue_growth/profitability/cost_control/asset_efficiency/cash_risk/customer_scale/customer_concentration/customer_satisfaction/supply_chain/delivery_quality/talent_pipeline/employee_engagement/innovation")
|
||||
responsible_dept = Column(String(200), nullable=True, comment="负责部门")
|
||||
responsible_user = Column(String(100), nullable=True, comment="负责人")
|
||||
status = Column(String(20), default="active")
|
||||
epic = Column(String(50), default="Epic2", comment="所属Epic")
|
||||
created_by = Column(Integer, nullable=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
|
||||
|
||||
class KPIValue(Base):
|
||||
"""KPI实际值"""
|
||||
__tablename__ = "kpi_values"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
kpi_id = Column(Integer, ForeignKey("kpi_definitions.id"), nullable=False)
|
||||
period = Column(String(20), nullable=False, comment="期间 2026-05")
|
||||
actual_value = Column(Float, nullable=True, comment="实际值")
|
||||
source_type = Column(String(20), default="manual", comment="erp/excel/manual")
|
||||
source_batch = Column(String(100), nullable=True, comment="导入批次号")
|
||||
data_status = Column(String(20), default="pending", comment="pending/verified/error")
|
||||
calculated_at = Column(DateTime, server_default=func.now())
|
||||
remark = Column(String(500), nullable=True)
|
||||
|
||||
|
||||
class DataSourceConfig(Base):
|
||||
"""数据源配置"""
|
||||
__tablename__ = "data_source_config"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(200), nullable=False, comment="数据源名称")
|
||||
source_type = Column(String(20), nullable=False, comment="erp/business/excel")
|
||||
api_endpoint = Column(String(500), nullable=True, comment="API地址")
|
||||
api_key = Column(String(200), nullable=True, comment="API Key")
|
||||
query_sql = Column(Text, nullable=True, comment="SQL查询语句")
|
||||
sync_type = Column(String(20), default="realtime", comment="realtime/batch")
|
||||
status = Column(String(20), default="active")
|
||||
last_sync_at = Column(DateTime, nullable=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
|
||||
|
||||
class KPIAlert(Base):
|
||||
"""预警记录"""
|
||||
__tablename__ = "kpi_alerts"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
kpi_id = Column(Integer, ForeignKey("kpi_definitions.id"), nullable=False)
|
||||
kpi_value_id = Column(Integer, ForeignKey("kpi_values.id"), nullable=True)
|
||||
alert_level = Column(String(20), default="yellow", comment="green/yellow/red")
|
||||
alert_message = Column(String(500), nullable=False)
|
||||
status = Column(String(20), default="pending", comment="pending/processing/resolved")
|
||||
assignee = Column(String(100), nullable=True, comment="处理人")
|
||||
resolution = Column(Text, nullable=True, comment="处理结果")
|
||||
resolved_at = Column(DateTime, nullable=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
|
||||
|
||||
class OperationLog(Base):
|
||||
"""操作日志"""
|
||||
__tablename__ = "operation_logs"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, nullable=True)
|
||||
action = Column(String(50), nullable=False, comment="create/update/delete/calculate/import")
|
||||
target_type = Column(String(50), nullable=False, comment="kpi/map/alert/source")
|
||||
target_id = Column(Integer, nullable=True)
|
||||
detail = Column(JSON, nullable=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
|
||||
|
||||
class NotificationChannel(Base):
|
||||
"""通知渠道配置"""
|
||||
__tablename__ = "notification_channels"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(100), nullable=False, comment="渠道名称")
|
||||
channel_type = Column(String(30), nullable=False, comment="wecom/mail/sms")
|
||||
config = Column(JSON, nullable=True, comment="渠道配置")
|
||||
enabled = Column(Boolean, default=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
|
||||
|
||||
class NotificationLog(Base):
|
||||
"""通知发送日志"""
|
||||
__tablename__ = "notification_logs"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
alert_id = Column(Integer, ForeignKey("kpi_alerts.id"), nullable=True)
|
||||
channel = Column(String(30), nullable=False, comment="wecom/mail")
|
||||
recipient = Column(String(200), nullable=True, comment="收件人")
|
||||
title = Column(String(200), nullable=True)
|
||||
content = Column(Text, nullable=True)
|
||||
status = Column(String(20), default="pending", comment="pending/sent/failed")
|
||||
error_msg = Column(String(500), nullable=True)
|
||||
sent_at = Column(DateTime, nullable=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
|
||||
|
||||
class RolePermission(Base):
|
||||
"""角色权限配置(单条记录,key-value)"""
|
||||
__tablename__ = "role_permissions"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
key = Column(String(50), unique=True, nullable=False, comment="配置键: route_permissions / action_permissions")
|
||||
value = Column(JSON, nullable=False, comment="配置值")
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
|
||||
|
||||
class ActionPlan(Base):
|
||||
"""改善行动计划"""
|
||||
__tablename__ = "action_plans"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
alert_id = Column(Integer, ForeignKey("kpi_alerts.id"), nullable=True, comment="关联预警")
|
||||
kpi_id = Column(Integer, ForeignKey("kpi_definitions.id"), nullable=False, comment="关联KPI")
|
||||
title = Column(String(200), nullable=False, comment="计划标题")
|
||||
description = Column(Text, nullable=True, comment="详细描述")
|
||||
assignee = Column(String(100), nullable=True, comment="负责人")
|
||||
priority = Column(String(20), default="medium", comment="high/medium/low")
|
||||
due_date = Column(DateTime, nullable=True, comment="截止日期")
|
||||
status = Column(String(20), default="pending", comment="pending/in_progress/completed/cancelled")
|
||||
progress = Column(Integer, default=0, comment="完成进度 0-100")
|
||||
result = Column(Text, nullable=True, comment="改善结果")
|
||||
created_by = Column(String(100), nullable=True, comment="创建人")
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
|
||||
|
||||
class OrgNode(Base):
|
||||
"""组织节点: 集团→事业部→区域→部门→班组 5级"""
|
||||
__tablename__ = "org_nodes"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
parent_id = Column(Integer, ForeignKey("org_nodes.id"), nullable=True, comment="父节点ID")
|
||||
name = Column(String(100), nullable=False, comment="节点名称")
|
||||
code = Column(String(50), unique=True, nullable=True, comment="编码")
|
||||
level = Column(Integer, nullable=False, comment="1=集团 2=事业部 3=区域 4=部门 5=班组")
|
||||
sort_order = Column(Integer, default=0, comment="排序")
|
||||
enabled = Column(Integer, default=1, comment="1启用 0禁用")
|
||||
path = Column(String(500), nullable=True, comment="路径")
|
||||
remark = Column(String(200), nullable=True, comment="备注")
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
|
||||
|
||||
class StrategicMapVersion(Base):
|
||||
"""战略地图版本快照"""
|
||||
__tablename__ = "strategic_map_versions"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
map_id = Column(Integer, ForeignKey("strategic_maps.id", ondelete="CASCADE"), nullable=False, comment="关联地图")
|
||||
version = Column(String(20), nullable=False, comment="版本号 v1.0 v1.1 ...")
|
||||
dimensions = Column(JSON, nullable=False, comment="维度数据快照")
|
||||
canvas_data = Column(JSON, nullable=False, comment="画布数据快照")
|
||||
comment = Column(String(500), nullable=True, comment="说明")
|
||||
created_by = Column(Integer, nullable=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
|
||||
|
||||
class MapObjective(Base):
|
||||
"""战略地图目标: 每个维度下的具体目标"""
|
||||
__tablename__ = "map_objectives"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
map_id = Column(Integer, ForeignKey("strategic_maps.id", ondelete="CASCADE"), nullable=False, comment="关联地图")
|
||||
dimension_key = Column(String(50), nullable=False, comment="所属维度: finance/customer/process/learning")
|
||||
name = Column(String(200), nullable=False, comment="目标名称")
|
||||
description = Column(Text, nullable=True, comment="描述")
|
||||
icon = Column(String(50), default="target", comment="图标标识")
|
||||
sort_order = Column(Integer, default=0, comment="排序")
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
Reference in New Issue
Block a user