RABC fejlesztése és beélesítése hibák kijavításával

This commit is contained in:
Roo
2026-06-18 18:09:51 +00:00
parent 611307a24b
commit fe3c32597d
57 changed files with 4689 additions and 655 deletions

View File

@@ -14,8 +14,11 @@ from sqlalchemy.orm import selectinload
from pydantic import BaseModel, Field, ConfigDict, EmailStr
from app.db.session import get_db
from app.api.deps import get_current_user
from app.api.deps import get_current_user, RequireSystemCapability
from app.schemas.organization import CorpOnboardIn, CorpOnboardResponse, OrganizationUpdate, OrganizationResponse
from app.schemas.subscription import SubscriptionTierResponse
from app.services.billing_engine import upgrade_org_subscription
from app.core.capabilities import Capability
from app.models.marketplace.organization import Organization, OrgType, OrganizationMember, Branch, OrgUserRole, OrgRole
from app.models.identity import User, OneTimePassword
from app.core.config import settings
@@ -219,7 +222,14 @@ async def get_my_organizations(
"subscription_plan": o.subscription_plan,
"org_type": o.org_type.value if hasattr(o.org_type, 'value') else str(o.org_type),
"visual_settings": o.visual_settings if hasattr(o, 'visual_settings') else None,
"user_role": _get_user_role(o, current_user.id)
"user_role": _get_user_role(o, current_user.id),
# ── Cím adatok (Address fields) ──
"address_zip": o.address_zip,
"address_city": o.address_city,
"address_street_name": o.address_street_name,
"address_street_type": o.address_street_type,
"address_house_number": o.address_house_number,
"address_hrsz": o.address_hrsz,
}
for o in orgs
]
@@ -663,19 +673,7 @@ async def update_organization(
Csak OWNER vagy ADMIN jogosultságú felhasználó módosíthatja.
"""
# 1. Jogosultság ellenőrzése
stmt_member = select(OrganizationMember).where(
(OrganizationMember.organization_id == org_id) &
(OrganizationMember.user_id == current_user.id) &
(OrganizationMember.role.in_(["OWNER", "ADMIN"]))
)
member = (await db.execute(stmt_member)).scalar_one_or_none()
if not member:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=_("ORGANIZATION.ERROR.ACCESS_DENIED")
)
# 2. Szervezet lekérése
# Először lekérjük a szervezetet, hogy ellenőrizhessük az owner_id-t is
stmt_org = select(Organization).where(
Organization.id == org_id,
Organization.is_deleted == False
@@ -688,7 +686,23 @@ async def update_organization(
detail=_("ORGANIZATION.ERROR.NOT_FOUND")
)
# 3. JSONB merge visual_settings esetén
# Jogosultság: OWNER/ADMIN a OrganizationMember táblában VAGY owner_id a Organization-ben
is_owner_by_field = (org.owner_id == current_user.id)
stmt_member = select(OrganizationMember).where(
(OrganizationMember.organization_id == org_id) &
(OrganizationMember.user_id == current_user.id) &
(OrganizationMember.role.in_(["OWNER", "ADMIN"]))
)
member = (await db.execute(stmt_member)).scalar_one_or_none()
if not member and not is_owner_by_field:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=_("ORGANIZATION.ERROR.ACCESS_DENIED")
)
# 2. JSONB merge visual_settings esetén
update_dict = update_data.model_dump(exclude_unset=True)
if "visual_settings" in update_dict and update_dict["visual_settings"] is not None:
@@ -717,6 +731,63 @@ async def update_organization(
return OrganizationResponse.model_validate(org)
# ── P0 FEATURE: SUBSCRIPTION & PACKAGE ASSIGNMENT BRIDGE ──
class SubscriptionAssignIn(BaseModel):
"""PUT body a szervezet előfizetési csomagjának beállításához."""
tier_id: int = Field(..., description="SubscriptionTier ID a system.subscription_tiers táblából")
@router.put("/{org_id}/subscription", response_model=dict)
async def assign_organization_subscription(
org_id: int,
body: SubscriptionAssignIn,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
_: bool = Depends(RequireSystemCapability(Capability.CAN_MANAGE_SUBSCRIPTIONS))
):
"""
Szervezet előfizetési csomagjának beállítása (Subscription & Package Assignment Bridge).
P0 Feature: This endpoint assigns a subscription_tier to an organization.
It requires the 'can_manage_subscriptions' system capability (SUPERADMIN or ADMIN).
The endpoint:
1. Validates the tier exists in system.subscription_tiers
2. Sets subscription_tier_id on the Organization record
3. Updates subscription_plan and base_asset_limit from tier rules
4. Creates/updates a finance.org_subscriptions audit record
"""
try:
result = await upgrade_org_subscription(
db=db,
org_id=org_id,
tier_id=body.tier_id,
actor_user_id=current_user.id
)
await db.commit()
await security_service.log_event(
db, user_id=current_user.id, action="ORG_SUBSCRIPTION_ASSIGNED",
severity=LogSeverity.info, target_type="Organization", target_id=str(org_id),
new_data={"tier_id": body.tier_id, "tier_name": result.get("tier_name")}
)
return result
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=str(e)
)
except Exception as e:
await db.rollback()
logger.error(f"Subscription assignment failed: org_id={org_id}, tier_id={body.tier_id}: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=_("ORGANIZATION.ERROR.DATABASE_ERROR", error=str(e))
)
# ── CÉG CSATLAKOZÁS ÉS ÁRVA CÉG ÁTVÉTEL ──
class JoinRequestIn(BaseModel):