87 lines
3.7 KiB
Python
87 lines
3.7 KiB
Python
from django.conf import settings
|
||
from rest_framework import serializers
|
||
|
||
from config.exceptions import AppError
|
||
from apps.user.models import Institution, Department
|
||
|
||
|
||
class CmsInstitutionSerializer(serializers.ModelSerializer):
|
||
"""CMS 机构(医院)序列化器。
|
||
|
||
- `code` 显式声明以去掉默认 UniqueValidator,改用自定义错误码校验唯一性。
|
||
- `banner_url` **可写**(新增/编辑可传,可选):入参可为静态相对路径(如
|
||
`institutions/xxx.png`)或完整 `http(s)` URL;**输出**统一转为可访问的完整 URL
|
||
(未配置时为空串,便于管理端识别「未设图」)。传空串则清空。
|
||
"""
|
||
code = serializers.CharField(max_length=100)
|
||
banner_url = serializers.CharField(
|
||
max_length=500, required=False, allow_blank=True,
|
||
help_text='机构 Banner 图:相对静态路径或完整 http(s) URL;可选,传空串清空',
|
||
)
|
||
|
||
class Meta:
|
||
model = Institution
|
||
fields = [
|
||
'id', 'code', 'name', 'type', 'level',
|
||
'province', 'city', 'banner_url', 'created_at', 'updated_at',
|
||
]
|
||
read_only_fields = ['id', 'created_at', 'updated_at']
|
||
|
||
def to_representation(self, instance):
|
||
data = super().to_representation(instance)
|
||
data['banner_url'] = self._full_banner_url(instance)
|
||
return data
|
||
|
||
def _full_banner_url(self, obj):
|
||
if not obj.banner_url:
|
||
return ''
|
||
value = obj.banner_url
|
||
if value.startswith(('http://', 'https://')):
|
||
return value
|
||
request = self.context.get('request')
|
||
prefix = getattr(settings, 'STATIC_PUBLIC_PREFIX', '').rstrip('/')
|
||
path = prefix + '/' + settings.STATIC_URL.strip('/') + '/' + value.lstrip('/')
|
||
return request.build_absolute_uri(path) if request else path
|
||
|
||
def validate_banner_url(self, value):
|
||
return (value or '').strip()
|
||
|
||
def validate_code(self, value):
|
||
value = (value or '').strip()
|
||
if not value:
|
||
raise AppError('CMS_VALIDATION_ERROR', '机构编码不能为空', status_code=400)
|
||
# 唯一性按 all_objects(含已停用)判定:编码唯一约束对软删行仍生效,
|
||
# 否则同编码重建会在写库时撞唯一约束抛 500。
|
||
qs = Institution.all_objects.filter(code=value)
|
||
if self.instance is not None:
|
||
qs = qs.exclude(pk=self.instance.pk)
|
||
if qs.exists():
|
||
raise AppError('CMS_INSTITUTION_CODE_EXISTS',
|
||
'机构编码已存在(含已停用机构),如需复用请先恢复或更换编码',
|
||
status_code=400)
|
||
return value
|
||
|
||
|
||
class CmsDepartmentSerializer(serializers.ModelSerializer):
|
||
"""CMS 科室(全局表,与机构无关)。"""
|
||
name = serializers.CharField(max_length=100)
|
||
|
||
class Meta:
|
||
model = Department
|
||
fields = ['id', 'name', 'category', 'created_at', 'updated_at']
|
||
read_only_fields = ['id', 'created_at', 'updated_at']
|
||
|
||
def validate_name(self, value):
|
||
value = (value or '').strip()
|
||
if not value:
|
||
raise AppError('CMS_VALIDATION_ERROR', '科室名称不能为空', status_code=400)
|
||
# 唯一性按 all_objects(含已停用)判定,避免同名重建在写库时撞唯一约束抛 500。
|
||
qs = Department.all_objects.filter(name=value)
|
||
if self.instance is not None:
|
||
qs = qs.exclude(pk=self.instance.pk)
|
||
if qs.exists():
|
||
raise AppError('CMS_DEPARTMENT_NAME_EXISTS',
|
||
'科室名称已存在(含已停用科室),如需复用请先恢复或更换名称',
|
||
status_code=400)
|
||
return value
|