"feat(managers): extend commission/payment/position managers
- CommissionEngine: ListRules/DisableRule/ListRateTables/ListEvents - PaymentManager: ListConfigs/GetConfigByUUID/DisableConfig/SetConfigStatus/DeleteConfig - PositionManager: HasTemplatePerm"
This commit is contained in:
1 parent
e9bde4db76
commit
f6842ee3c8
7 files changed
+296
-4
No files matched your search
Binary file not shown.
+205
-4
@@ -1,17 +1,17 @@
|
||||
import uuid
|
||||
from django.utils import timezone as _timezone
|
||||
|
||||
from gvsdsdk.models import Role, UserRole, RolePermission, Permission
|
||||
from gvsdsdk.models import Role, UserRole, RolePermission, Permission, Position, PositionTemplate, PositionTemplatePermission
|
||||
from gvsdsdk.model_utils import _GetUserModel
|
||||
|
||||
# NOTE: 类型注解暂缓——RoleManager 静态方法较多,全量补充注解工作量较大且易引入回归,后续单独迭代处理。
|
||||
# NOTE: 类型注解暂缓——RoleManager/PositionManager 静态方法较多,全量补充注解工作量较大且易引入回归,后续单独迭代处理。
|
||||
|
||||
|
||||
class RoleManager:
|
||||
"""角色管理器——提供角色创建、分配、权限管理"""
|
||||
|
||||
@staticmethod
|
||||
def CreateRole(Name, TenantUUID, AssignScope=0, AssignScopeUUID=None, RoleType=2):
|
||||
def CreateRole(Name, TenantUUID, AssignScope=0, AssignScopeUUID=None, RoleType=2, RoleDesc=''):
|
||||
"""创建角色"""
|
||||
role = Role(
|
||||
RoleUUID=uuid.uuid4().bytes,
|
||||
@@ -21,12 +21,17 @@ class RoleManager:
|
||||
RoleStatus=1,
|
||||
AssignScope=AssignScope,
|
||||
AssignScopeUUID=AssignScopeUUID,
|
||||
RoleDesc='',
|
||||
RoleDesc=RoleDesc,
|
||||
CreateTime=_timezone.now(),
|
||||
)
|
||||
role.save()
|
||||
return role
|
||||
|
||||
@staticmethod
|
||||
def GetRoleByUUID(RoleUUID):
|
||||
"""按 UUID 查询角色(不存在返回 None)"""
|
||||
return Role.objects.filter(RoleUUID=RoleUUID).first()
|
||||
|
||||
@staticmethod
|
||||
def GetRoleByName(Name, TenantUUID=None):
|
||||
"""按名称查询角色(同租户内角色名唯一)
|
||||
@@ -138,3 +143,199 @@ class RoleManager:
|
||||
perm_uuids = qs.values_list('PermUUID', flat=True)
|
||||
return Permission.objects.filter(PermUUID__in=perm_uuids, PermStatus=1)
|
||||
|
||||
@staticmethod
|
||||
def GetUserRoleDetails(UserUUID, CompanyUUID=None):
|
||||
"""获取用户的 UserRole 关联详情(按行返回,保留行级信息)
|
||||
|
||||
与 GetRolesForUser(仅返回 Role)互补:本方法保留 UserRole 的
|
||||
CompanyUUID、RoleName 覆盖、RoleType、UserRoleUUID 等行级字段,
|
||||
供需要展示"角色+公司+覆盖名"等富信息的场景使用。
|
||||
|
||||
Returns:
|
||||
list[UserRole]:UserRole 实例列表(保持数据库顺序)
|
||||
"""
|
||||
qs = UserRole.objects.filter(UserUUID=UserUUID)
|
||||
if CompanyUUID is not None:
|
||||
qs = qs.filter(CompanyUUID=CompanyUUID)
|
||||
return list(qs)
|
||||
|
||||
@staticmethod
|
||||
def HasRolePermission(RoleUUID, PermUUID, CompanyUUID=None):
|
||||
"""检查角色是否已拥有指定权限(同公司下防重复绑定)"""
|
||||
qs = RolePermission.objects.filter(RoleUUID=RoleUUID, PermUUID=PermUUID)
|
||||
if CompanyUUID is not None:
|
||||
qs = qs.filter(CompanyUUID=CompanyUUID)
|
||||
return qs.exists()
|
||||
|
||||
|
||||
class PositionManager:
|
||||
"""职务管理器——提供人事职务标签创建、岗位模板管理"""
|
||||
|
||||
# ── 人事职务标签 ──
|
||||
|
||||
@staticmethod
|
||||
def CreatePosition(Name, TenantUUID, Code='', Level=0, **Kwargs):
|
||||
"""创建人事职务标签(TenantUUID 传 UUIDObj/str/bytes)"""
|
||||
position = Position(
|
||||
PositionUUID=uuid.uuid4().bytes,
|
||||
TenantUUID=TenantUUID,
|
||||
PositionName=Name,
|
||||
PositionCode=Code,
|
||||
PositionLevel=Level,
|
||||
PositionStatus=1,
|
||||
PositionDesc=Kwargs.get('PositionDesc', ''),
|
||||
CreateTime=_timezone.now(),
|
||||
UpdateTime=_timezone.now(),
|
||||
)
|
||||
position.save()
|
||||
return position
|
||||
|
||||
@staticmethod
|
||||
def GetPositionsForTenant(TenantUUID):
|
||||
"""获取租户下的所有启用职务"""
|
||||
return Position.objects.filter(TenantUUID=TenantUUID, PositionStatus=1)
|
||||
|
||||
@staticmethod
|
||||
def GetPositionByUUID(PositionUUID):
|
||||
"""按 UUID 查询职务(不存在返回 None)"""
|
||||
return Position.objects.filter(PositionUUID=PositionUUID).first()
|
||||
|
||||
@staticmethod
|
||||
def UpdatePosition(PositionUUID, **Fields):
|
||||
"""更新职务字段(自动刷新 UpdateTime)
|
||||
|
||||
Args:
|
||||
PositionUUID: 职务 UUID
|
||||
**Fields: 允许字段 PositionName/PositionCode/PositionLevel/PositionStatus/PositionDesc
|
||||
|
||||
Returns:
|
||||
更新后的 Position 实例;职务不存在返回 None
|
||||
"""
|
||||
position = Position.objects.filter(PositionUUID=PositionUUID).first()
|
||||
if not position:
|
||||
return None
|
||||
allowed = ('PositionName', 'PositionCode', 'PositionLevel', 'PositionStatus', 'PositionDesc')
|
||||
update_fields = []
|
||||
for key, value in Fields.items():
|
||||
if key in allowed:
|
||||
setattr(position, key, value)
|
||||
update_fields.append(key)
|
||||
position.UpdateTime = _timezone.now()
|
||||
update_fields.append('UpdateTime')
|
||||
if update_fields:
|
||||
position.save(update_fields=update_fields)
|
||||
return position
|
||||
|
||||
@staticmethod
|
||||
def DeletePosition(PositionUUID):
|
||||
"""软删除职务(PositionStatus=0);返回是否命中"""
|
||||
position = Position.objects.filter(PositionUUID=PositionUUID).first()
|
||||
if not position:
|
||||
return False
|
||||
position.PositionStatus = 0
|
||||
position.UpdateTime = _timezone.now()
|
||||
position.save(update_fields=['PositionStatus', 'UpdateTime'])
|
||||
return True
|
||||
|
||||
# ── 岗位模板 ──
|
||||
|
||||
@staticmethod
|
||||
def CreatePositionTemplate(Name, TenantUUID, Code='', **Kwargs):
|
||||
"""创建岗位模板(TenantUUID 传 UUIDObj/str/bytes)"""
|
||||
template = PositionTemplate(
|
||||
PositionTemplateUUID=uuid.uuid4().bytes,
|
||||
TenantUUID=TenantUUID,
|
||||
TemplateName=Name,
|
||||
TemplateCode=Code,
|
||||
TemplateStatus=1,
|
||||
TemplateDesc=Kwargs.get('TemplateDesc', ''),
|
||||
CreateTime=_timezone.now(),
|
||||
UpdateTime=_timezone.now(),
|
||||
)
|
||||
template.save()
|
||||
return template
|
||||
|
||||
@staticmethod
|
||||
def GetTemplatesForTenant(TenantUUID):
|
||||
"""获取租户下的所有启用岗位模板"""
|
||||
return PositionTemplate.objects.filter(TenantUUID=TenantUUID, TemplateStatus=1)
|
||||
|
||||
@staticmethod
|
||||
def GetPositionTemplateByUUID(PositionTemplateUUID):
|
||||
"""按 UUID 查询岗位模板(不存在返回 None)"""
|
||||
return PositionTemplate.objects.filter(PositionTemplateUUID=PositionTemplateUUID).first()
|
||||
|
||||
@staticmethod
|
||||
def UpdatePositionTemplate(PositionTemplateUUID, **Fields):
|
||||
"""更新岗位模板字段(自动刷新 UpdateTime)
|
||||
|
||||
Args:
|
||||
PositionTemplateUUID: 岗位模板 UUID
|
||||
**Fields: 允许字段 TemplateName/TemplateCode/TemplateStatus/TemplateDesc
|
||||
|
||||
Returns:
|
||||
更新后的 PositionTemplate 实例;模板不存在返回 None
|
||||
"""
|
||||
template = PositionTemplate.objects.filter(PositionTemplateUUID=PositionTemplateUUID).first()
|
||||
if not template:
|
||||
return None
|
||||
allowed = ('TemplateName', 'TemplateCode', 'TemplateStatus', 'TemplateDesc')
|
||||
update_fields = []
|
||||
for key, value in Fields.items():
|
||||
if key in allowed:
|
||||
setattr(template, key, value)
|
||||
update_fields.append(key)
|
||||
template.UpdateTime = _timezone.now()
|
||||
update_fields.append('UpdateTime')
|
||||
if update_fields:
|
||||
template.save(update_fields=update_fields)
|
||||
return template
|
||||
|
||||
@staticmethod
|
||||
def DeletePositionTemplate(PositionTemplateUUID):
|
||||
"""软删除岗位模板(TemplateStatus=0);返回是否命中"""
|
||||
template = PositionTemplate.objects.filter(PositionTemplateUUID=PositionTemplateUUID).first()
|
||||
if not template:
|
||||
return False
|
||||
template.TemplateStatus = 0
|
||||
template.UpdateTime = _timezone.now()
|
||||
template.save(update_fields=['TemplateStatus', 'UpdateTime'])
|
||||
return True
|
||||
|
||||
# ── 岗位模板权限关联 ──
|
||||
|
||||
@staticmethod
|
||||
def AssignPermToTemplate(TemplateUUID, PermUUID):
|
||||
"""为岗位模板关联权限"""
|
||||
ptp = PositionTemplatePermission(
|
||||
PTPermUUID=uuid.uuid4().bytes,
|
||||
PositionTemplateUUID=TemplateUUID,
|
||||
PermUUID=PermUUID,
|
||||
CreateTime=_timezone.now(),
|
||||
)
|
||||
ptp.save()
|
||||
return ptp
|
||||
|
||||
@staticmethod
|
||||
def RemovePermFromTemplate(TemplateUUID, PermUUID):
|
||||
"""移除岗位模板与权限的关联;返回是否命中"""
|
||||
deleted, _ = PositionTemplatePermission.objects.filter(
|
||||
PositionTemplateUUID=TemplateUUID, PermUUID=PermUUID
|
||||
).delete()
|
||||
return deleted > 0
|
||||
|
||||
@staticmethod
|
||||
def GetPermsForTemplate(TemplateUUID):
|
||||
"""获取岗位模板关联的所有启用权限"""
|
||||
perm_uuids = PositionTemplatePermission.objects.filter(
|
||||
PositionTemplateUUID=TemplateUUID
|
||||
).values_list('PermUUID', flat=True)
|
||||
return Permission.objects.filter(PermUUID__in=perm_uuids, PermStatus=1)
|
||||
|
||||
@staticmethod
|
||||
def HasTemplatePerm(TemplateUUID, PermUUID):
|
||||
"""检查岗位模板是否已关联指定权限"""
|
||||
return PositionTemplatePermission.objects.filter(
|
||||
PositionTemplateUUID=TemplateUUID, PermUUID=PermUUID,
|
||||
).exists()
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -166,6 +166,54 @@ class CommissionEngine:
|
||||
logger.info(f'费率表已创建: {table_code}@tenant={self.TenantUUID}')
|
||||
return table
|
||||
|
||||
def ListRules(self, event_type=None):
|
||||
"""列出租户下的分佣规则(仅启用,按优先级降序)
|
||||
|
||||
Args:
|
||||
event_type: 可选,按事件类型过滤
|
||||
|
||||
Returns:
|
||||
QuerySet[CommissionRule]
|
||||
"""
|
||||
qs = CommissionRule.objects.filter(
|
||||
TenantUUID=self.TenantUUID, RuleStatus=1,
|
||||
)
|
||||
if event_type:
|
||||
qs = qs.filter(EventType=event_type)
|
||||
return qs.order_by('-RulePriority')
|
||||
|
||||
def DisableRule(self, rule_uuid):
|
||||
"""软禁用分佣规则(RuleStatus=0);返回是否命中"""
|
||||
updated = CommissionRule.objects.filter(
|
||||
TenantUUID=self.TenantUUID, RuleUUID=rule_uuid,
|
||||
).update(RuleStatus=0)
|
||||
return updated > 0
|
||||
|
||||
def ListRateTables(self):
|
||||
"""列出租户下的费率表(仅启用)
|
||||
|
||||
Returns:
|
||||
QuerySet[RateTable]
|
||||
"""
|
||||
return RateTable.objects.filter(
|
||||
TenantUUID=self.TenantUUID, TableStatus=1,
|
||||
)
|
||||
|
||||
def ListEvents(self, event_type=None, limit=50):
|
||||
"""列出租户下的分佣事件(按创建时间倒序)
|
||||
|
||||
Args:
|
||||
event_type: 可选,按事件类型过滤
|
||||
limit: 返回条数上限
|
||||
|
||||
Returns:
|
||||
QuerySet[CommissionEvent]
|
||||
"""
|
||||
qs = CommissionEvent.objects.filter(TenantUUID=self.TenantUUID)
|
||||
if event_type:
|
||||
qs = qs.filter(EventType=event_type)
|
||||
return qs.order_by('-CreateTime')[:limit]
|
||||
|
||||
def Dispatch(self, event_type, event_key, total_amount,
|
||||
source_user_uuid=None, participants=None,
|
||||
tier_index=0, payload=None, auto_settle=True):
|
||||
|
||||
Binary file not shown.
@@ -160,6 +160,49 @@ class PaymentManager:
|
||||
logger.info(f'支付网关配置: {platform}@tenant={self.TenantUUID}')
|
||||
return config
|
||||
|
||||
def ListConfigs(self, status=None):
|
||||
"""列出租户下的支付网关配置(默认按默认渠道优先、平台名排序)
|
||||
|
||||
Args:
|
||||
status: 可选,按配置状态过滤(1=启用,0=禁用)
|
||||
|
||||
Returns:
|
||||
QuerySet[PaymentGatewayConfig]
|
||||
"""
|
||||
qs = PaymentGatewayConfig.objects.filter(
|
||||
TenantUUID=self.TenantUUID,
|
||||
)
|
||||
if status is not None:
|
||||
qs = qs.filter(ConfigStatus=status)
|
||||
return qs.order_by('-ConfigDefault', 'Platform')
|
||||
|
||||
def GetConfigByUUID(self, config_uuid):
|
||||
"""按 ConfigUUID 查询租户下的配置(不存在返回 None)"""
|
||||
return PaymentGatewayConfig.objects.filter(
|
||||
ConfigUUID=config_uuid, TenantUUID=self.TenantUUID,
|
||||
).first()
|
||||
|
||||
def DisableConfig(self, platform):
|
||||
"""禁用租户指定平台的配置(ConfigStatus=0 并清空更新时间);返回是否命中"""
|
||||
updated = PaymentGatewayConfig.objects.filter(
|
||||
TenantUUID=self.TenantUUID, Platform=platform,
|
||||
).update(ConfigStatus=0, UpdateTime=None)
|
||||
return updated > 0
|
||||
|
||||
def SetConfigStatus(self, config_uuid, status):
|
||||
"""更新租户指定配置的状态;返回是否命中"""
|
||||
updated = PaymentGatewayConfig.objects.filter(
|
||||
ConfigUUID=config_uuid, TenantUUID=self.TenantUUID,
|
||||
).update(ConfigStatus=status)
|
||||
return updated > 0
|
||||
|
||||
def DeleteConfig(self, config_uuid):
|
||||
"""删除租户指定配置;返回是否命中"""
|
||||
deleted, _ = PaymentGatewayConfig.objects.filter(
|
||||
ConfigUUID=config_uuid, TenantUUID=self.TenantUUID,
|
||||
).delete()
|
||||
return deleted > 0
|
||||
|
||||
def Pay(self, platform, amount, subject='', body='',
|
||||
method='jsapi', open_id='', client_ip='',
|
||||
extra=None, expire_minutes=30):
|
||||
|
||||
Reference in new issue
Block a user