Files
cma-management/backend/app/models/cost_model.py
T
Hermes CI Fix 696f8bc934 feat(cost): 成本模型加研发归集维度 research_flag/project_type (cma-rd-dimension-20260905)
- StandardCost/ActualCost 增加 research_flag(int,idx)/project_type(varchar30,idx)
  project_type: platform_dev平台研发/client_delivery客户交付/internal内部管理
- 生产库两表 ALTER 完成, 存量 29+134 行默认 internal(保守防误归研发)
- API: create/update 支持写入维度, 未传默认 client_delivery(录入默认),
  research_flag 未显式传入按 project_type 联动(platform_dev=1);
  create/update/delete 绑定 entity_id(token优先, 防跨账套)
- API: standard/actual 列表支持 project_type/research_flag 过滤
- 前端 CostDashboard: 表单加归集类型下拉(默认客户交付+研发提示),
  列表加归集类型列(标签), 工具栏按归集类型过滤
- tests: test_cost.py +6 用例(默认值/联动/过滤/更新)
- scripts: verify_cost_research_dimension_e2e.py 生产E2E(标记+清理+回查)
2026-09-05 09:10:35 +08:00

86 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""成本分析模型 — 管理会计OS
标准成本卡片、实际成本归集、作业成本法(ABC)
"""
from sqlalchemy import Column, Integer, String, Float, DateTime, Text, ForeignKey, JSON, func
from app.database import Base
RESEARCH_PROJECT_TYPES = ("platform_dev", "client_delivery", "internal")
class StandardCost(Base):
"""标准成本卡片 — 每项产品或服务的标准成本构成"""
__tablename__ = "standard_costs"
id = Column(Integer, primary_key=True, index=True)
entity_id = Column(Integer, default=1, comment="企业ID (P2多租户隔离 2026-08-23)")
research_flag = Column(Integer, default=0, index=True, comment="是否研发投入 0/1(研发费用加计扣除归集 2026-09-05)")
project_type = Column(String(30), default="internal", index=True, comment="归集类型: platform_dev平台研发/client_delivery客户交付/internal内部管理(默认internal保守防误归研发)")
product_code = Column(String(50), nullable=False, comment="产品/服务编码")
product_name = Column(String(200), nullable=False, comment="产品/服务名称")
cost_type = Column(String(20), nullable=False, comment="成本类型: material/labor/overhead")
item_name = Column(String(200), nullable=False, comment="成本项目名称")
standard_quantity = Column(Float, nullable=False, comment="标准用量")
unit = Column(String(20), nullable=True, comment="单位")
standard_price = Column(Float, nullable=False, comment="标准单价")
standard_cost = Column(Float, nullable=False, comment="标准成本 = 用量×单价")
version = Column(String(20), default="v1.0", comment="版本号")
status = Column(String(20), default="active", comment="active/archived")
remark = Column(Text, nullable=True)
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
class ActualCost(Base):
"""实际成本归集 — 从ERP/手工录入的实际成本"""
__tablename__ = "actual_costs"
id = Column(Integer, primary_key=True, index=True)
entity_id = Column(Integer, default=1, comment="企业ID (P2多租户隔离 2026-08-23)")
research_flag = Column(Integer, default=0, index=True, comment="是否研发投入 0/1(研发费用加计扣除归集 2026-09-05)")
project_type = Column(String(30), default="internal", index=True, comment="归集类型: platform_dev平台研发/client_delivery客户交付/internal内部管理(默认internal保守防误归研发)")
period = Column(String(20), nullable=False, comment="期间 2026-05")
product_code = Column(String(50), nullable=False, comment="产品/服务编码")
product_name = Column(String(200), nullable=False, comment="产品/服务名称")
cost_type = Column(String(20), nullable=False, comment="成本类型: material/labor/overhead")
item_name = Column(String(200), nullable=False, comment="成本项目名称")
actual_quantity = Column(Float, nullable=False, comment="实际用量")
actual_price = Column(Float, nullable=False, comment="实际单价")
actual_cost = Column(Float, nullable=False, comment="实际成本 = 用量×单价")
source = Column(String(50), default="manual", comment="数据来源: erp/manual")
created_at = Column(DateTime, server_default=func.now())
class AbcActivity(Base):
"""ABC作业中心定义"""
__tablename__ = "abc_activities"
id = Column(Integer, primary_key=True, index=True)
entity_id = Column(Integer, default=1, comment="企业ID (P2多租户隔离 2026-08-23)")
activity_code = Column(String(50), unique=True, nullable=False, comment="作业编码")
activity_name = Column(String(200), nullable=False, comment="作业名称")
activity_desc = Column(Text, nullable=True, comment="作业描述")
cost_driver = Column(String(100), nullable=False, comment="成本动因")
driver_unit = Column(String(50), nullable=True, comment="动因单位")
total_cost = Column(Float, default=0, comment="作业总成本")
driver_volume = Column(Float, default=0, comment="动因总量")
driver_rate = Column(Float, default=0, comment="动因分配率 = 总成本/动因总量")
status = Column(String(20), default="active", comment="active/inactive")
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
class AbcAllocation(Base):
"""ABC成本分配记录 — 按动因分配到产品"""
__tablename__ = "abc_allocations"
id = Column(Integer, primary_key=True, index=True)
entity_id = Column(Integer, default=1, comment="企业ID (P2多租户隔离 2026-08-23)")
period = Column(String(20), nullable=False, comment="期间 2026-05")
activity_id = Column(Integer, ForeignKey("abc_activities.id"), nullable=False)
product_code = Column(String(50), nullable=False, comment="产品/服务编码")
product_name = Column(String(200), nullable=False, comment="产品/服务名称")
driver_consumed = Column(Float, nullable=False, comment="消耗的动因量")
allocated_cost = Column(Float, nullable=False, comment="分配的成本")
created_at = Column(DateTime, server_default=func.now())