Files
SMANAGE/_flask_backup/fsr_compat.py
T
2026-06-16 11:55:14 +08:00

406 lines
13 KiB
Python

import uuid
import json
import datetime
from django.conf import settings
from django.http import HttpRequest
from gvsds.apps.core.models import User, UUIDField
from gvsds.apps.gerp.models import (
Tenant, CompanyInfo, Company, Department, Role, UserRole, RoleDept,
Permission, FileAsset, WorkOrder, Message, Menu,
)
from gvsds.apps.crb.models import Enterprise, EnterpriseUser
from gvsds.apps.doc.models import CommunityDocument, CommunitySeries
from gvsds.apps.sve.models import SVEBase
from gvsds.apps.t4.models import T4User
from gvsds.apps.mc.models import MCUser
from gvsds.apps.invite.models import InviteConversation
from gvsds.apps.ccgo.models import PlansNotify, PlansTalentPlan, Link
from PDAPI_django import UUIDObj, NewBUUID, snake_to_pascal
MODEL_REGISTRY = {
"User": User,
"UserAvatar": User,
"EphemeralTokens": User,
"Tenant": Tenant,
"CompanyInfo": CompanyInfo,
"Company": Company,
"Dept": Department,
"Role": Role,
"UserRole": UserRole,
"RoleDept": RoleDept,
"Permission": Permission,
"FileAsset": FileAsset,
"WorkOrder": WorkOrder,
"Message": Message,
"Menu": Menu,
"Enterprise": Enterprise,
"EnterpriseUser": EnterpriseUser,
"document": CommunityDocument,
"series": CommunitySeries,
"sve": SVEBase,
"computers": T4User,
"InviteConversation": InviteConversation,
"notify": PlansNotify,
"talentplan": PlansTalentPlan,
"links": Link,
}
def _pascal_to_snake(name):
import re
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
class TableConfig:
def __init__(self, model_class):
self.model = model_class
self._fields = None
self._row = None
self.data = self.Get()
@property
def Model(self):
return self.model
@property
def PrimaryKey(self):
for item in self.row:
if "PrimaryKey" in item.get("Groups", []):
return item["Name"]
return None
@property
def PrimaryKeys(self):
return [item["Name"] for item in self.row if "PrimaryKey" in item.get("Groups", [])]
@property
def IsCompositeKey(self):
return len(self.PrimaryKeys) > 1
def RangeItemList(self):
return [item["Name"] for item in self.row]
def RangeItem(self):
return iter([item["Name"] for item in self.row])
def GetPrimaryKeyField(self):
pk_name = self.PrimaryKey
if pk_name:
return self.GetItem(pk_name)
return None
def GetModel(self):
return self.model()
def CheckAllUniqueFieldsDuplicate(self, form_data):
from django.db.models import Q
unique_fields = []
for f in self.model._meta.local_fields:
if f.unique and not f.primary_key:
pascal = snake_to_pascal(f.name)
unique_fields.append((f.name, pascal))
for db_name, pascal_name in unique_fields:
val = form_data.get(pascal_name)
if val is not None and val != '':
if self.model.objects.filter(**{db_name: val}).exists():
return False, pascal_name
return True, None
def PrimaryKeyGenerationFunction(self):
pk_field = None
for f in self.model._meta.local_fields:
if f.primary_key:
pk_field = f
break
if pk_field is None:
return None
from gvsds.apps.core.models import UUIDField
if isinstance(pk_field, UUIDField):
return NewBUUID
return None
@property
def row(self):
if self._row is not None:
return self._row
self._row = self.Get()
return self._row
def Get(self):
if self._fields is not None:
return self._fields
fields = []
for f in self.model._meta.get_fields():
if hasattr(f, 'column'):
pascal_name = snake_to_pascal(f.name)
field_info = {
"Name": pascal_name,
"Type": self._map_type(f),
"Required": not f.null and not f.has_default(),
"AllowedEmpty": f.null,
"Groups": self._get_groups(f),
}
if f.has_default():
default = f.get_default()
if default is not None:
field_info["Default"] = default
if getattr(f, 'max_length', None):
field_info["MaxLen"] = f.max_length
fields.append(field_info)
self._fields = fields
return fields
def _get_groups(self, field):
if field.primary_key:
return ["PrimaryKey"]
if field.null or field.has_default():
return ["MechanicalItem"]
return ["ManualItem"]
def _map_type(self, field):
from django.db import models as dj_models
if isinstance(field, dj_models.ForeignKey):
return "UUID"
if isinstance(field, UUIDField):
return "UUID"
if isinstance(field, dj_models.BinaryField):
return "UUID"
if isinstance(field, dj_models.SmallIntegerField):
return "int"
if isinstance(field, dj_models.IntegerField):
return "int"
if isinstance(field, dj_models.BigIntegerField):
return "int"
if isinstance(field, dj_models.FloatField):
return "float"
if isinstance(field, dj_models.DecimalField):
return "float"
if isinstance(field, dj_models.DateTimeField):
return "timestampstr"
if isinstance(field, dj_models.JSONField):
return "json"
if isinstance(field, dj_models.TextField):
return "str"
if isinstance(field, dj_models.BooleanField):
return "bool"
return "str"
def GetItem(self, field_name):
for f in self.Get():
if f["Name"] == field_name:
return f
return None
def SetRequired(self, fields, required):
pass
def KeyToUUIDConversion(self, field_name, value, target_type):
if value is None:
return None
if hasattr(value, '_meta'):
pk = value._meta.pk
if pk:
value = getattr(value, pk.name)
if target_type == bytes:
if isinstance(value, bytes) and len(value) == 16:
return value
if isinstance(value, str):
try:
return uuid.UUID(value).bytes
except ValueError:
return None
if isinstance(value, uuid.UUID):
return value.bytes
elif target_type == str:
if isinstance(value, bytes) and len(value) == 16:
return str(uuid.UUID(bytes=value)).upper().replace('-', '')
if isinstance(value, uuid.UUID):
return str(value).upper().replace('-', '')
if isinstance(value, str):
return value
return str(value)
return value
class _PermissionManager:
def _build_context(self, table, table_name, cleaned_data):
return {"table": table, "table_name": table_name, "data": cleaned_data}
def check_permission(self, action, ctx):
return True
def run_before_add(self, ctx):
return False, None
def run_after_add(self, ctx, result):
return result, False
def run_before_modify(self, ctx):
return False, None
def run_after_modify(self, ctx, result):
return result, False
def run_before_modify_item(self, ctx):
return False, None
def run_after_modify_item(self, ctx, result):
return result, False
def run_before_delete(self, ctx):
return False, None
def run_after_delete(self, ctx, result):
return result, False
def run_before_get(self, ctx):
return False, None
def run_after_get(self, ctx, result):
return result, False
class FormDataCompat:
_instance = None
TABLE_CODE_DISPLAY = {}
TABLE_ENUM_LABELS = {}
TABLE_FK_PICKER = {}
TABLE_HIDE_IN_FORM = set()
TABLE_TEXTAREA_FIELDS = set()
TABLE_FIELD_PLACEHOLDER = {}
TABLE_DISPLAY_NAMES = {
"User": "用户", "UserAvatar": "用户头像", "EphemeralTokens": "临时令牌",
"Tenant": "租户", "TenantCompany": "企业入驻申请", "CompanyInfo": "企业入驻申请",
"Company": "公司", "Dept": "部门", "Role": "角色", "Permission": "权限",
"UserRole": "用户角色", "RoleDept": "角色部门", "WorkOrder": "工单",
"Menu": "菜单", "Message": "消息", "FileAsset": "文件资产",
}
TABLE_EXCLUDED_FIELDS = {}
TABLE_UUID_INPUT_ALLOWED = set()
data = {}
PM = _PermissionManager()
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def GetTable(self, table_name):
model_class = MODEL_REGISTRY.get(table_name)
if not model_class:
return None
return TableConfig(model_class)
@staticmethod
def get_user_models():
from gvsds.apps.core.models import User, UserAvatar, EphemeralToken
from gvsds.apps.gerp.models import (
Tenant, CompanyInfo, Company, Department, Role, Permission,
UserRole, RoleDept, WorkOrder, Menu, Message,
)
return {
"User": User,
"UserAvatar": UserAvatar,
"EphemeralTokens": EphemeralToken,
"Tenant": Tenant,
"Company": Company,
"Dept": Department,
"Role": Role,
"Permission": Permission,
"UserRole": UserRole,
"RoleDept": RoleDept,
"WorkOrder": WorkOrder,
"Menu": Menu,
"CompanyInfo": CompanyInfo,
"Message": Message,
}
@staticmethod
def get_field_display_name(table_name, field_name):
name_map = {
"UUID": "UUID", "UserUUID": "用户UUID", "UserName": "用户名",
"UserEmail": "邮箱", "UserTele": "电话", "UserPassword": "密码",
"CompanyUUID": "公司UUID", "CompanyName": "公司名称", "CompanyShort": "公司简称",
"RoleUUID": "角色UUID", "RoleName": "角色名称", "RoleType": "角色类型",
"RoleStatus": "角色状态", "DeptUUID": "部门UUID", "DeptName": "部门名称",
"MenuUUID": "菜单UUID", "MenuName": "菜单名称", "MenuTitle": "菜单标题",
"MenuLink": "菜单链接", "MenuIcon": "菜单图标", "MenuSort": "排序",
"ParentMenuUUID": "上级菜单UUID", "PermissionKey": "权限键",
"PermissionName": "权限名称", "PermissionContent": "权限内容",
"PermissionEnabled": "是否启用", "CreateTime": "创建时间",
"UpdateTime": "更新时间", "MessageUUID": "消息UUID",
"MessageTitle": "消息标题", "MessageContent": "消息内容",
"WorkOrderUUID": "工单UUID", "WorkOrderTitle": "工单标题",
"WorkOrderContent": "工单内容", "WorkOrderStatus": "工单状态",
"TenantName": "租户名称", "TenantExpireTime": "过期时间",
}
return name_map.get(field_name, field_name)
@staticmethod
def get_code_display(table_name, field_name, value):
return str(value) if value is not None else ""
@staticmethod
def get_table_extension(table_name):
return None
@staticmethod
def get_user_timezone():
return "UTC"
@staticmethod
def utc_to_user_tz(dt, tz=None):
return dt
@staticmethod
def user_tz_to_utc(value):
return value
@staticmethod
def RegisterFunctionExtension(*args, **kwargs):
pass
class FormAPIPlugin:
name = ""
description = ""
def on_before_add(self, ctx):
return False, None
def on_after_add(self, ctx, result):
pass
def on_before_modify(self, ctx):
return False, None
def on_after_modify(self, ctx, result):
pass
def on_before_delete(self, ctx):
return False, None
def on_after_delete(self, ctx, result):
pass
class PluginManager:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._plugins = {}
return cls._instance
def register(self, plugin):
self._plugins[plugin.name] = plugin
def get_plugin(self, name):
return self._plugins.get(name)
def get_all_plugins(self):
return list(self._plugins.values())