태그마다 값을 만들 수 있는지, 없다면 왜인지 — 판정표

'예시 값' 을 진짜로 보여 주기로 했는데, 조사해 보니 서식생성기에서 값이 나오는 태그는
384종 중 16종(4%)뿐이다. 나머지는 환자·내원 문맥이 있어야 한다.

그런데 조사에서 값보다 쓸모 있는 것이 나왔다 — <b>왜 안 되는지</b>다.
지금은 어디서도 알 수 없다:
· ETC_요양기관명칭_병원명(실사용 3위, 303건)이 환자 내원을 타고 병원을 푼다는 것
· 값이 아니라 표를 돌려주는 태그 15종(콤보 채우기용이라 한 줄 값이 없다)
· 파일서버 이미지 경로를 돌려주는 태그 9종(싸인·직인)
· 본문이 Return "" 인 죽은 태그 1종
· 태그가 아니라 레거시 내부 함수 8종 — 우리 카탈로그가 Public Function 을 전수 추출해
  섞여 들어왔다. 고르면 값이 안 나오는데 레거시는 Try 안에서 조용히 삼킨다.

그 판정을 TagPreviewCatalog 에 담았다. <b>표로 박는다</b> — 판정 근거는 레거시 함수 본문이
환자·내원 객체를 참조하는지 여부이고, 그건 태그 이름에도 접두어에도 없다.
ETC_현재일자 와 ETC_요양기관명칭_병원명 은 같은 접두어인데 한쪽만 만들 수 있다.
이름 규칙으로 추정하면 절반만 맞는다. 규칙이 확실한 둘(…List·…InitialDatatable / 싸인·직인)만
접미어·낱말로 가르고 나머지는 실측을 옮겨 적었다.

값 계산도 함께 넣었다. 서버 시각 11종은 레거시 Data2Format 과 같은 형식으로 찍고
(영문은 MM-DD-YYYY 재배치), 로그인 사용자 5종은 항목을 골라 잇는다.
ID·이름을 잇는 태그는 한쪽이 비면 점만 남은 값을 만들지 않는다.

단위 테스트 10건. 이 표가 틀리면 화면이 사용자에게 거짓말을 한다 —
값이 나오는 태그를 '안 된다'고 하거나, 안 나오는 태그에 빈 칸을 띄운다.
판정 근거가 레거시 함수 본문이라 코드로는 다시 확인할 수 없어 여기가 유일한 안전망이다.

아직 화면에 붙이지 않았다. 값 줄은 DB 조회(서버 시각·M_UidMst)가 필요하고
그 통로를 만드는 것이 다음 단계다. 판정과 계산은 순수 함수라 그 전에 확정해 둔다.

게이트: 테스트 277/277(신규 10), --edit-smoke 0실패, --modal-check 2/2,
--dialog-shots 57파일, --db-smoke 3000 diff 0·예외 0,
--db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-14 14:54:37 +09:00
co-authored by Claude Opus 5
parent b2bdc7fa41
commit 836a3e843a
2 changed files with 306 additions and 0 deletions
@@ -0,0 +1,110 @@
using SheetMe.Core.Catalog;
namespace SheetMe.Core.Tests;
/// <summary>
/// 태그 값 판정 고정.
///
/// 이 표가 틀리면 화면이 사용자에게 <b>거짓말을 한다</b> — 값이 나오는 태그를 "안 된다"고 하거나,
/// 안 나오는 태그에 빈 칸을 띄운다. 판정 근거가 레거시 함수 본문이라 코드로는 다시 확인할 수 없어
/// 여기가 유일한 안전망이다.
/// </summary>
[TestClass]
public sealed class TagPreviewCatalogTests
{
#region Methods
[TestMethod]
public void _시각_태그를_알아본다()
{
Assert.AreEqual(TagPreviewKind.Clock, TagPreviewCatalog.KindOf("ETC_현재일자"));
Assert.AreEqual(TagPreviewKind.Clock, TagPreviewCatalog.KindOf("ETC_현재일시"));
Assert.AreEqual(TagPreviewKind.Clock, TagPreviewCatalog.KindOf("ETC_현재일시_5_몇분"));
Assert.IsTrue(TagPreviewCatalog.CanResolve("ETC_현재일자"));
}
[TestMethod]
public void _사용자_태그를_알아본다()
{
Assert.AreEqual(TagPreviewKind.LoginUser, TagPreviewCatalog.KindOf("ETC_로그인_사용자명"));
Assert.AreEqual(TagPreviewKind.LoginUser, TagPreviewCatalog.KindOf("ETC_로그인_원내연락처"));
Assert.IsTrue(TagPreviewCatalog.CanResolve("ETC_로그인_사용자ID"));
}
[TestMethod]
public void _접두어라도_환자_문맥이_필요한_것은_가른다()
{
// 실사용 3위(303건). 이름만 보면 기관 정보 같지만 환자 내원을 타고 병원을 푼다 —
// 접두어로 추정할 수 없다는 것이 이 표가 존재하는 이유다.
Assert.AreEqual(TagPreviewKind.PatientContext, TagPreviewCatalog.KindOf("ETC_요양기관명칭_병원명"));
Assert.IsFalse(TagPreviewCatalog.CanResolve("ETC_요양기관명칭_병원명"));
Assert.AreEqual(TagPreviewKind.PatientContext, TagPreviewCatalog.KindOf("PAT_차트번호"));
}
[TestMethod]
public void _돌려주는_태그는_따로_가른다()
{
Assert.AreEqual(TagPreviewKind.Table, TagPreviewCatalog.KindOf("OCM_진료과List"));
Assert.AreEqual(TagPreviewKind.Table, TagPreviewCatalog.KindOf("PAT_병동InitialDatatable"));
}
[TestMethod]
public void _경로_태그는_따로_가른다()
{
Assert.AreEqual(TagPreviewKind.Image, TagPreviewCatalog.KindOf("ECT_로그인사용자싸인"));
Assert.AreEqual(TagPreviewKind.Image, TagPreviewCatalog.KindOf("ETC_병원직인"));
}
[TestMethod]
public void _태그와_태그가_아닌_것을_가른다()
{
Assert.AreEqual(TagPreviewKind.Dead, TagPreviewCatalog.KindOf("OCM_수술일자_Refer"));
Assert.AreEqual(TagPreviewKind.NotATag, TagPreviewCatalog.KindOf("GetNurseShtCod"));
Assert.AreEqual(TagPreviewKind.NotATag, TagPreviewCatalog.KindOf("퇴원약DT"));
}
[TestMethod]
public void _만드는_것에는_이유가_붙고_만드는_것에는_안_붙는다()
{
Assert.AreNotEqual(string.Empty, TagPreviewCatalog.ReasonText("PAT_차트번호"));
Assert.AreNotEqual(string.Empty, TagPreviewCatalog.ReasonText("GetNurseShtCod"));
Assert.AreEqual(string.Empty, TagPreviewCatalog.ReasonText("ETC_현재일자"),
"값이 나오는 태그에 사유가 붙으면 화면에 둘이 같이 뜬다");
Assert.AreEqual("서버 시각 기준", TagPreviewCatalog.SourceText("ETC_현재일자"));
Assert.AreEqual(string.Empty, TagPreviewCatalog.SourceText("PAT_차트번호"));
}
[TestMethod]
public void _시각을_레거시와_같은_형식으로_찍는다()
{
const string stamp = "202608141432";
Assert.AreEqual("2026-08-14", TagPreviewCatalog.FromClock("ETC_현재일자", stamp));
Assert.AreEqual("2026-08-14 14:32", TagPreviewCatalog.FromClock("ETC_현재일시", stamp));
Assert.AreEqual("2026-08-1414:32", TagPreviewCatalog.FromClock("ETC_현재일시_MaskBox", stamp));
// Data2Format_ENG 는 MM-DD-YYYY 로 재배치한다
Assert.AreEqual("08-14-2026", TagPreviewCatalog.FromClock("ETC_현재일자_영문", stamp));
Assert.AreEqual("2026", TagPreviewCatalog.FromClock("ETC_현재년도", stamp));
Assert.AreEqual("08", TagPreviewCatalog.FromClock("ETC_현재일시_2_월", stamp));
Assert.AreEqual("14:32", TagPreviewCatalog.FromClock("ETC_현재시간", stamp));
}
[TestMethod]
public void _문자열이_모자라면_빈_값이다()
{
Assert.AreEqual(string.Empty, TagPreviewCatalog.FromClock("ETC_현재일자", "2026"));
Assert.AreEqual(string.Empty, TagPreviewCatalog.FromClock("PAT_차트번호", "202608141432"));
}
[TestMethod]
public void _정보를_레거시와_같은_형식으로_잇는다()
{
Assert.AreEqual("홍길동", TagPreviewCatalog.FromUser("ETC_로그인_사용자명", "U01", "홍길동", "010", "1234"));
Assert.AreEqual("U01", TagPreviewCatalog.FromUser("ETC_로그인_사용자ID", "U01", "홍길동", "010", "1234"));
Assert.AreEqual("U01.홍길동",
TagPreviewCatalog.FromUser("ETC_로그인_사용자ID_사용자명", "U01", "홍길동", "010", "1234"));
Assert.AreEqual("010", TagPreviewCatalog.FromUser("ETC_로그인_사용자연락처", "U01", "홍길동", "010", "1234"));
// 한쪽이 비면 점만 남은 값을 만들지 않는다
Assert.AreEqual(string.Empty,
TagPreviewCatalog.FromUser("ETC_로그인_사용자ID_사용자명", "U01", string.Empty, "010", "1234"));
}
#endregion
}