feat(park-company): 园区企业→成员 + 企业算力(折扣%/配额,只增不减) 后端

- 迁移0015:park_companies 加 compute_discount/compute_quota/compute_quota_used/engine_group/owner_user_id;users 加 park_company_id(成员归属一家企业)
- tenants.py:company_members/get/add/remove(写 users.park_company_id)、available_members(候选)、set_company_compute(折扣%/配额 单调非降,越界 ValueError)、sync_company_engine(引擎组倍率同步,best-effort)
- park/routers.py:carrier 端点 company-members GET/POST/DELETE、company-pool、companies/{cid}/compute(monotonic+引擎同步);鉴权 _carrier_user+_my_park 隔离本园区
- compute_client.py:set_user_group_by_username、set_group_group_ratio(组倍率=1-discount%)、grant_user_quota_by_username(解析引擎id后 add_quota)
- rbac_admin.py:平台兜底 GET /park/tenants/{tid}/companies、PUT .../companies/{cid}/compute(monotonic+audit)
- _user_to_dict 暴露 park_company_id
- 单调校验服务端强判:折扣降/配额负增 → 400

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Pine
2026-08-26 19:57:37 +08:00
parent ac2df72b21
commit 8697119aaa
7 changed files with 346 additions and 6 deletions
+35
View File
@@ -0,0 +1,35 @@
"""园区企业算力 + 用户企业归属
Revision ID: 0015_company_compute
Revises: 0014_drop_user_identities
Create Date: 2026-08-26
"""
from __future__ import annotations
import sqlalchemy as sa
from alembic import op
revision = "0015_company_compute"
down_revision = "0014_drop_user_identities"
branch_labels = None
depends_on = None
def upgrade() -> None:
# 园区企业:算力折扣%/配额(只增不减)
op.add_column("park_companies", sa.Column("compute_discount", sa.Integer(), nullable=False, server_default="0"))
op.add_column("park_companies", sa.Column("compute_quota", sa.Integer(), nullable=False, server_default="0"))
op.add_column("park_companies", sa.Column("compute_quota_used", sa.Integer(), nullable=False, server_default="0"))
op.add_column("park_companies", sa.Column("engine_group", sa.String(), nullable=False, server_default=""))
op.add_column("park_companies", sa.Column("owner_user_id", sa.String(), nullable=False, server_default=""))
# 用户归属园区企业(成员)
op.add_column("users", sa.Column("park_company_id", sa.String(), nullable=True))
def downgrade() -> None:
op.drop_column("users", "park_company_id")
op.drop_column("park_companies", "owner_user_id")
op.drop_column("park_companies", "engine_group")
op.drop_column("park_companies", "compute_quota_used")
op.drop_column("park_companies", "compute_quota")
op.drop_column("park_companies", "compute_discount")