Files
medical_training/test/test_cms_relation.py
T

135 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""CMS 师生关系管理测试:CMS-REL-1~4(医院管理员本院 / 超管全平台)。"""
import io
from openpyxl import Workbook
from django.core.files.uploadedfile import SimpleUploadedFile
from rest_framework.test import APIClient
from apps.user.models import TeacherStudentRelation
from .conftest import CacheTestCase, create_test_user, get_auth_client, ensure_institution
REL_URL = '/api/cms/teacher-student-relations/'
XLSX_CT = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
def rel_detail(pk):
return f'/api/cms/teacher-student-relations/{pk}/'
def rel_disable(pk):
return f'/api/cms/teacher-student-relations/{pk}/disable/' # 停用:POST(原 DELETE /{id}/
def make_xlsx(headers, rows):
wb = Workbook(); ws = wb.active
ws.append(headers)
for r in rows:
ws.append(r)
buf = io.BytesIO(); wb.save(buf); buf.seek(0)
return SimpleUploadedFile('rel.xlsx', buf.read(), content_type=XLSX_CT)
class CmsRelationTest(CacheTestCase):
def setUp(self):
super().setUp()
self.inst = ensure_institution(name='本院', code='REL-A')
self.other = ensure_institution(name='他院', code='REL-B')
self.admin = create_test_user(phone='13932000001', role_type='hospital_admin', institution=self.inst)
self.client = get_auth_client(self.admin)
self.doc = create_test_user(phone='13932000002', real_name='张医生', role_type='doctor', institution=self.inst)
self.stu = create_test_user(phone='13932000003', real_name='李同学', role_type='student', institution=self.inst)
self.other_stu = create_test_user(phone='13932000004', real_name='王同学', role_type='student', institution=self.other)
# 完整新增载荷(姓名+手机号均必填)
def _payload(self, **over):
p = {'teacher_name': '张医生', 'teacher_phone': '13932000002',
'student_name': '李同学', 'student_phone': '13932000003'}
p.update(over)
return p
def test_permission(self):
self.assertEqual(APIClient().get(REL_URL).status_code, 401)
stu_client = get_auth_client(self.stu)
self.assertEqual(stu_client.get(REL_URL).status_code, 403)
def test_create_and_list(self):
resp = self.client.post(REL_URL, self._payload())
self.assertEqual(resp.status_code, 201, resp.content)
self.assertEqual(resp.json()['teacher_phone'], '13932000002')
self.assertEqual(resp.json()['student_phone'], '13932000003')
self.assertEqual(resp.json()['teacher_name'], '张医生')
self.assertEqual(resp.json()['student_name'], '李同学')
# 列表
resp = self.client.get(REL_URL)
self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.json()['results']), 1)
def test_create_missing_name_400(self):
resp = self.client.post(REL_URL, self._payload(student_name=''))
self.assertEqual(resp.status_code, 400, resp.content)
self.assertEqual(resp.json()['code'], 'CMS_VALIDATION_ERROR')
def test_create_name_phone_mismatch_400(self):
# 姓名与手机号不符 → 解析不到
resp = self.client.post(REL_URL, self._payload(teacher_name='不存在'))
self.assertEqual(resp.status_code, 400, resp.content)
self.assertEqual(resp.json()['code'], 'CMS_REL_TEACHER_NOT_FOUND')
def test_create_duplicate(self):
self.client.post(REL_URL, self._payload())
resp = self.client.post(REL_URL, self._payload())
self.assertEqual(resp.status_code, 400, resp.content)
self.assertEqual(resp.json()['code'], 'CMS_REL_EXISTS')
def test_teacher_must_be_doctor(self):
# 用学生姓名+手机号当带教老师 → 解析不到 doctor
resp = self.client.post(REL_URL, self._payload(teacher_name='李同学', teacher_phone='13932000003'))
self.assertEqual(resp.status_code, 400, resp.content)
self.assertEqual(resp.json()['code'], 'CMS_REL_TEACHER_NOT_FOUND')
def test_scope_other_institution_student_rejected(self):
resp = self.client.post(REL_URL, self._payload(student_name='王同学', student_phone='13932000004'))
self.assertEqual(resp.status_code, 403, resp.content)
self.assertEqual(resp.json()['code'], 'CMS_REL_SCOPE_FORBIDDEN')
def test_dropdown_lists(self):
# 2 个下拉数据源:本院 doctor / student,姓名+手机号一并返回
docs = self.client.get(REL_URL + 'doctors/').json()
self.assertEqual(docs, [{'id': self.doc.id, 'real_name': '张医生', 'phone': '13932000002'}])
studs = self.client.get(REL_URL + 'students/').json()
# 他院学生不在内(本院仅李同学)
self.assertEqual(studs, [{'id': self.stu.id, 'real_name': '李同学', 'phone': '13932000003'}])
# 学生无权访问
self.assertEqual(get_auth_client(self.stu).get(REL_URL + 'doctors/').status_code, 403)
def test_soft_delete(self):
r = TeacherStudentRelation.objects.create(teacher=self.doc, student=self.stu, status=1)
resp = self.client.post(rel_disable(r.id))
self.assertEqual(resp.status_code, 200, resp.content)
self.assertFalse(TeacherStudentRelation.objects.filter(id=r.id).exists())
self.assertTrue(TeacherStudentRelation.all_objects.get(id=r.id).is_deleted)
def test_import_and_export(self):
f = make_xlsx(['带教医生姓名', '带教医生手机号', '学生姓名', '学生手机号'], [
['张医生', '13932000002', '李同学', '13932000003'], # ✅
['张医生', '13932000002', '王同学', '13932000004'], # 学生他院 → 失败
['不存在', '00000000000', '李同学', '13932000003'], # 医生不存在 → 失败
])
resp = self.client.post('/api/cms/teacher-student-relations/import/', {'file': f}, format='multipart')
self.assertEqual(resp.status_code, 200, resp.content)
body = resp.json()
self.assertEqual(body['success'], 1)
self.assertEqual(body['failed'], 2)
# 导出
resp = self.client.get('/api/cms/teacher-student-relations/export/')
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp['Content-Type'], XLSX_CT)
def test_list_scoped_to_own(self):
# 他院的师生关系不可见
other_doc = create_test_user(phone='13932000005', role_type='doctor', institution=self.other)
TeacherStudentRelation.objects.create(teacher=other_doc, student=self.other_stu, status=1)
TeacherStudentRelation.objects.create(teacher=self.doc, student=self.stu, status=1)
resp = self.client.get(REL_URL)
self.assertEqual(len(resp.json()['results']), 1) # 只看到本院那条