"""CMS 带教医生 - 我的学生测试:CMS-TEA-1~2。 带教医生(doctor)仅能看到 teacher_student_relation 中 teacher=自己 且 status=1 的学生;只读,不能新增/编辑/删除。 """ from rest_framework.test import APIClient from apps.user.models import TeacherStudentRelation from .conftest import ( CacheTestCase, create_test_user, get_auth_client, ensure_institution, ensure_department, create_teacher_student_relation, ) STUDENTS_URL = '/api/cms/students/' def student_detail(pk): return f'/api/cms/students/{pk}/' class CmsStudentsTest(CacheTestCase): def setUp(self): super().setUp() self.inst = ensure_institution(name='本院', code='TEA-A') self.dept = ensure_department(name='内科') self.doc = create_test_user( phone='13940000001', password='Doc12345', real_name='张医生', role_type='doctor', institution=self.inst, ) self.other_doc = create_test_user( phone='13940000002', real_name='李医生', role_type='doctor', institution=self.inst, ) # 名下进行中学生 self.stu_own = create_test_user( phone='13940000011', real_name='我的学生', role_type='student', institution=self.inst, ) self.stu_own.department = self.dept self.stu_own.save(update_fields=['department']) # 名下已结束学生(status=0,列表应排除) self.stu_ended = create_test_user( phone='13940000012', real_name='已毕业学生', role_type='student', institution=self.inst, ) # 其他医生的学生(当前医生不应看到) self.stu_other = create_test_user( phone='13940000013', real_name='其他学生', role_type='student', institution=self.inst, ) create_teacher_student_relation(self.doc, self.stu_own, status=1) create_teacher_student_relation(self.doc, self.stu_ended, status=0) create_teacher_student_relation(self.other_doc, self.stu_other, status=1) self.client = get_auth_client(self.doc) # ── 权限 ────────────────────────────────────────────────────────────────── def test_unauthenticated_401(self): self.assertEqual(APIClient().get(STUDENTS_URL).status_code, 401) def test_non_doctor_403(self): admin = create_test_user(phone='13940000091', role_type='hospital_admin', institution=self.inst) resp = get_auth_client(admin).get(STUDENTS_URL) self.assertEqual(resp.status_code, 403, resp.content) self.assertEqual(resp.json()['code'], 'CMS_PERMISSION_DENIED') # 学生本人也无权访问 resp2 = get_auth_client(self.stu_own).get(STUDENTS_URL) self.assertEqual(resp2.status_code, 403, resp2.content) # ── CMS-TEA-1 列表 ───────────────────────────────────────────────────────── def test_list_own_active_students_only(self): resp = self.client.get(STUDENTS_URL) self.assertEqual(resp.status_code, 200, resp.content) results = resp.json()['results'] ids = {u['id'] for u in results} self.assertIn(self.stu_own.id, ids) self.assertNotIn(self.stu_ended.id, ids) # status=0 self.assertNotIn(self.stu_other.id, ids) # 他医生 self.assertNotIn(self.doc.id, ids) # 不含自己 self.assertEqual(len(results), 1) def test_list_search(self): resp = self.client.get(STUDENTS_URL, {'search': '我的学生'}) self.assertEqual(resp.status_code, 200, resp.content) ids = {u['id'] for u in resp.json()['results']} self.assertEqual(ids, {self.stu_own.id}) def test_list_student_fields(self): resp = self.client.get(STUDENTS_URL) item = resp.json()['results'][0] self.assertEqual(item['real_name'], '我的学生') self.assertEqual(item['role_type'], 'student') self.assertEqual(item['department_name'], '内科') self.assertIn('total_training_count', item) # ── CMS-TEA-2 详情 ───────────────────────────────────────────────────────── def test_retrieve_own_student(self): resp = self.client.get(student_detail(self.stu_own.id)) self.assertEqual(resp.status_code, 200, resp.content) self.assertEqual(resp.json()['real_name'], '我的学生') self.assertEqual(resp.json()['phone'], '13940000011') def test_retrieve_other_student_404(self): resp = self.client.get(student_detail(self.stu_other.id)) self.assertEqual(resp.status_code, 404, resp.content) def test_retrieve_ended_student_404(self): resp = self.client.get(student_detail(self.stu_ended.id)) self.assertEqual(resp.status_code, 404, resp.content) # ── 软删除师生关系 ───────────────────────────────────────────────────────── def test_soft_deleted_relation_excludes_student(self): rel = TeacherStudentRelation.objects.get(teacher=self.doc, student=self.stu_own) rel.delete() # SoftDeleteModel 逻辑删除 resp = self.client.get(STUDENTS_URL) self.assertEqual(resp.status_code, 200, resp.content) ids = {u['id'] for u in resp.json()['results']} self.assertNotIn(self.stu_own.id, ids) # ── 只读 ────────────────────────────────────────────────────────────────── def test_readonly_methods_not_allowed(self): self.assertEqual(self.client.post(STUDENTS_URL, {}).status_code, 405) self.assertEqual(self.client.delete(student_detail(self.stu_own.id)).status_code, 405)