diff --git a/src/SheetMe.Core/Catalog/PatientPreviewPolicy.cs b/src/SheetMe.Core/Catalog/PatientPreviewPolicy.cs
index 2ed1892..ac31849 100644
--- a/src/SheetMe.Core/Catalog/PatientPreviewPolicy.cs
+++ b/src/SheetMe.Core/Catalog/PatientPreviewPolicy.cs
@@ -14,28 +14,36 @@ namespace SheetMe.Core.Catalog;
/// (전체 검색 + 감사 로그), 그래서 남기는 쪽이 안전장치의 본체다 —
/// 조회 자체를 막지 않는 대신 흔적을 남긴다.
///
-/// 조건은 와 같은 축을 쓴다. 환자 기록을 보는 일은
-/// 지금 쓰이는 서식을 제자리에서 고치는 일과 무게가 다르지 않다.
+/// 부서 문(전산실)을 걸지 않는다. 처음에는 를 그대로 갖다 썼는데
+/// 그건 레거시에 없는 제약이었다. 레거시가 부서로 가리는 툴은 TK_MODIFY 하나뿐이고
+/// (frmSheetDesigner.vb:1030-1060, MSYS 전용인 TK_ExportXML/ImportXML 은 계정 문),
+/// TK_PREVIEW 에는 어떤 가시성 조건도 걸리지 않는다 — 서식생성기를 열 수 있으면 쓸 수 있다.
+///
+/// 두 일의 무게가 다르기도 하다. 수정은 지금 쓰이는 서식을 제자리에서 바꿔 병원 전체에
+/// 즉시 영향을 준다. 미리보기는 이미 그 사람이 볼 수 있는 기록을 읽기만 한다.
+/// 여기에 부서 문을 걸면 서식을 만드는 사람이 자기 서식을 검증할 수 없게 되고,
+/// 검증을 못 하면 값이 틀린 서식이 그대로 운영에 올라간다 — 막아서 더 위험해지는 쪽이다.
///
public static class PatientPreviewPolicy
{
#region Methods
///
- /// 이 사용자가 환자 데이터로 미리보기를 볼 수 있는가.
+ /// 이 사용자가 환자 데이터로 미리보기를 볼 수 있는가 — 인증만 요구한다.
///
- /// 인증된 HIS 사용자여야 한다 — 미인증이면 감사 로그에 남길 주체가 없고,
- /// 주체 없는 환자 조회는 그 자체로 남기면 안 되는 일이다.
+ /// 미인증이면 감사 로그에 남길 주체가 없고, 주체 없는 환자 조회는 남기면 안 되는 일이다.
+ /// 그것이 유일한 조건이다. 병원·부서 인자는 일부러 받아 두고 쓰지 않는다 —
+ /// 병원별 규칙이 생기면 호출부를 고치지 않고 여기서 받을 수 있어야 하고,
+ /// 인자가 없으면 그때 호출부 전부를 다시 손대야 한다.
///
public static bool CanPreviewPatient(string hospitalCode, string departmentCode, string uidCod,
string hospitalStartDate)
- => uidCod.Length > 0
- && ModifyPolicy.CanModify(hospitalCode, departmentCode, uidCod, hospitalStartDate);
+ => uidCod.Length > 0;
/// 왜 막혔는지 — "권한이 없습니다"만으로는 누구에게 물어야 할지 모른다
public static string DenyReason(string hospitalCode, string uidCod, string hospitalStartDate)
=> uidCod.Length == 0
? "HIS 사용자가 확인되지 않았습니다. 기록지정보 화면에서 실행하거나 사용자 코드를 전달해 주세요."
- : ModifyPolicy.DenyReason(hospitalCode, uidCod, hospitalStartDate);
+ : string.Empty;
///
/// 감사 로그 한 줄 — 누가·언제·어느 내원을 열었는가.
diff --git a/src/SheetMe.Designer/DataBusiness/FormDesignDataBusiness.cs b/src/SheetMe.Designer/DataBusiness/FormDesignDataBusiness.cs
index f52ddc4..55e2944 100644
--- a/src/SheetMe.Designer/DataBusiness/FormDesignDataBusiness.cs
+++ b/src/SheetMe.Designer/DataBusiness/FormDesignDataBusiness.cs
@@ -132,11 +132,12 @@ internal sealed class FormDesignDataBusiness
UserSession.Current.HspCod, UserSession.Current.UidCod, HospitalStartDate);
///
- /// 이 사용자가 실제 환자로 미리보기를 할 수 있는가.
+ /// 이 사용자가 실제 환자로 미리보기를 할 수 있는가 — 인증만 확인한다.
///
- /// 수정과 같은 문을 쓴다 — 서식생성기에서 환자 정보를 꺼내 보는 것은 진료 행위가 아니라
- /// 서식이 맞게 뽑히는지 확인하는 일이고, 그 권한은 레거시가 전산실에만 열어 둔 것과 같은 범위다.
- /// 여기를 넓히면 서식생성기가 환자 조회 도구가 된다.
+ /// 수정과 다른 문이다. 레거시가 부서로 가리는 툴은 TK_MODIFY 하나뿐이고
+ /// TK_PREVIEW 에는 조건이 없다(frmSheetDesigner.vb:1030-1060).
+ /// 여기에 부서 문을 걸면 서식을 만든 사람이 자기 서식을 검증할 수 없다.
+ /// 안전장치는 막는 것이 아니라 감사 로그다.
///
public static bool CanPreviewPatient() => PatientPreviewPolicy.CanPreviewPatient(
UserSession.Current.HspCod, UserSession.Current.DepCod, UserSession.Current.UidCod,
diff --git a/tests/SheetMe.Core.Tests/PatientPreviewPolicyTests.cs b/tests/SheetMe.Core.Tests/PatientPreviewPolicyTests.cs
index d58d224..4b3d75b 100644
--- a/tests/SheetMe.Core.Tests/PatientPreviewPolicyTests.cs
+++ b/tests/SheetMe.Core.Tests/PatientPreviewPolicyTests.cs
@@ -5,9 +5,9 @@ namespace SheetMe.Core.Tests;
///
/// 환자 미리보기 접근 규칙 고정.
///
-/// 이 표가 느슨해지면 서식을 만드는 사람 누구나 운영 환자 기록을 열 수 있다.
-/// 레거시가 그 상태였다 — 인가코드가 소스에 평문이고, 검색 범위 무제한이고, 감사 0건이다.
-/// 검색 범위는 레거시와 같게 두기로 했으므로 감사와 권한이 유일한 장치다.
+/// 레거시는 인가코드가 소스에 평문이고, 검색 범위 무제한이고, 감사 0건이었다.
+/// 검색 범위와 접근 범위는 레거시와 같게 두기로 했으므로 감사 로그가 유일한 장치다 —
+/// 그래서 감사 한 줄의 모양(주체가 있는가, 이름이 새지 않는가)이 여기서 가장 중요한 판정이다.
///
[TestClass]
public sealed class PatientPreviewPolicyTests
@@ -23,13 +23,30 @@ public sealed class PatientPreviewPolicyTests
}
[TestMethod]
- public void 수정_권한과_같은_축을_쓴다()
+ public void 부서로_막지_않는다()
{
- // 환자 기록을 보는 일은 지금 쓰이는 서식을 제자리에서 고치는 일과 무게가 다르지 않다.
- Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("ABC", "EDPS", "011825", string.Empty));
- Assert.IsFalse(PatientPreviewPolicy.CanPreviewPatient("ABC", "NURS", "011825", string.Empty));
- Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("HANKOOK", "SALO", "011825", string.Empty));
- Assert.IsFalse(PatientPreviewPolicy.CanPreviewPatient("XYZ", "EDPS", "011825", "20250501"));
+ // 처음에는 수정 권한(ModifyPolicy)을 그대로 갖다 썼다. 그건 레거시에 없는 제약이었다 —
+ // 레거시가 부서로 가리는 툴은 TK_MODIFY 하나뿐이고 TK_PREVIEW 에는 문이 없다
+ // (frmSheetDesigner.vb:1030-1060). 서식을 만드는 사람이 자기 서식을 검증할 수 없으면
+ // 값이 틀린 서식이 그대로 운영에 올라간다.
+ foreach (var dep in new[] { "EDPS", "NURS", "SALO", "MEDI", "" })
+ {
+ Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("ABC", dep, "011825", string.Empty),
+ $"부서 '{dep}' 로 막혔다");
+ }
+ // 수정에만 걸리던 갈래도 미리보기에는 걸리지 않는다
+ Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("XYZ", "NURS", "011825", "20250501"));
+ Assert.IsTrue(PatientPreviewPolicy.CanPreviewPatient("HANKOOK", "NURS", "011825", string.Empty));
+ }
+
+ [TestMethod]
+ public void 수정_권한은_그대로_좁게_남는다()
+ {
+ // 미리보기를 연 것이 수정까지 연 것이 되면 안 된다 — 수정은 지금 쓰이는 서식을
+ // 제자리에서 바꿔 병원 전체에 즉시 영향을 준다. 이 대조가 없으면 위 완화가
+ // 조용히 ModifyPolicy 까지 번져도 알 수 없다.
+ Assert.IsFalse(ModifyPolicy.CanModify("ABC", "NURS", "011825", string.Empty));
+ Assert.IsTrue(ModifyPolicy.CanModify("ABC", "EDPS", "011825", string.Empty));
}
[TestMethod]