부가정보 2차분 20종 — 165종 → 185종 (워크플로 조사 라운드 4·5)

병렬 조사(읽기 11 + 반박 검증 11)로 39종을 분석하고 그중 20종을 이식:

값 18종 — OCM_발병일(:8125, 발병시작일 최신 고정), OCM_당일식이
(:12620, PIVOT 원문 유지·"아침 : X " 결합), OCM_알러지+조영제/약물/
음식/기타(:14941-15140, LISTAGG CRLF — 카테고리는 한글 리터럴),
OCM_알러지_List(:15142 — " - " 구분자가 한 번 켜지면 안 꺼지는
스티키 결함 보존), OCM_외출예상시작/종료일시(:15197/:15231 — 같은
행의 양끝, 원문부터 결정적), ETC_건강보험증번호(:15269 — PisInsCod=1
숫자 리터럴 유지), ETC_재해발생일(:15323), ETC_산재지정번호(:15727 —
진료과→병원 HspWrkNum, 문맥 시점), OCM_감염분류_감염정보(:14084),
OCM_퇴원분석_수술처치명(:13920 — 후행 개행까지 원문), OCM_병실인실
(:7065, 최신 입실 고정), OCM_병실차액(:7103 — 원문부터 첫 입실
결정적), OCM_VITAL접수일시_LAST(:12996 — 시각만 정렬하는 원문 유지),
OCM_진료과_전화번호(:2773 — 진료과 행 재사용, 왕복 0), OCM_전과일시/
전과일자(:12985/:12990 — 문맥 진료 행).

사유 완결 2종 — OCM_감염정보(:14122 원문 SQL 의 바인드 콜론 누락
→ 상시 ORA-00904 → 빈 값. 고치면 없던 값이 생기므로 사유로 안내),
OCM_Cosign_의사명(:14812 — 저장 기록 키(EmrKey) 의존, 미리보기 부재).

검증이 잡은 레거시 결함 3건 기록: 감염정보 콜론 누락, 알러지_List
스티키 구분자, 진료기간_진료과 SQL B 의 sDepCod 미바인드(다음 배치).

- dotnet test 338/338 · --edit-smoke 실패 0 (이름 검사 185종)
- --db-patient ①~㉟ 전건 통과 — ㉟ 신설: 새 조회 12종 실행 확인
  (O_OkdInf·O_ImlInf·O_OutAdmInf·S_AlgInf·S_IcnInf·S_DssOpn 전부 존재)
- --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-19 19:09:38 +09:00
co-authored by Claude Fable 5
parent a33229b5e1
commit 7bae9b9057
3 changed files with 459 additions and 7 deletions
@@ -2417,6 +2417,62 @@ public static class DbSmoke
Check("㉞ 회신 완료 협진이 있는 내원에서는 협진과가 나온다",
consults.Count > 0, "O_CstInf 조인이나 CstSttFlg 를 의심할 것");
}
// ㉟ 부가정보 2차분 — 새 자기 SQL 12종이 예외 없이 돈다.
// O_ 계열 표(O_OkdInf·O_ImlInf·O_OutAdmInf)가 이 시험 DB 에
// 없으면 개별 [진단] 줄로 남기고 판정은 실행 가능한 것만 본다.
try
{
var probes = new (string Probe, Func<string> Run)[]
{
("알러지", () => extra.Allergy(extraOwner, null).Length.ToString()),
("알러지목록", () => extra.AllergyRows(extraOwner).Count.ToString()),
("보험증번호", () => extra.InsuranceCertNumber(extraOwner).Length.ToString()),
("재해발생일", () => extra.AccidentDate(extraOwner).Length.ToString()),
("감염정보", () => extra.InfectionInfo(extraOwner).Length.ToString()),
("발병일", () => owner2 is null ? "-" : extra.OnsetDate(extraOwner, owner2.Value).Length.ToString()),
("당일식이", () => owner2 is null ? "-" : extra.TodayMeals(owner2.Value).Count.ToString()),
("외출예상", () => extra.ExpectedOuting(extraOwner, false).Length.ToString()),
("퇴원분석", () => owner2 is null ? "-" : extra.DischargeAnalysisOperations(owner2.Value).Count.ToString()),
("병실인실", () => owner2 is null ? "-" : extra.RoomBedCount(owner2.Value).Length.ToString()),
("병실차액", () => owner2 is null ? "-" : extra.RoomExtraCharge(owner2.Value).Length.ToString()),
("산재지정번호", () => extra.IndustrialAccidentNumber("0506", "20260819").Length.ToString()),
};
var shapes2 = new List<string>();
var failed = new List<string>();
foreach (var (probe, run) in probes)
{
try
{
shapes2.Add($"{probe} {run()}");
}
catch (Exception ex)
{
var first = ex.Message.Split('\n')[0];
// 표 자체가 없는 것(ORA-00942)은 시험 DB 한계다
if (first.Contains("ORA-00942"))
{
shapes2.Add($"{probe} [표없음]");
}
else
{
failed.Add($"{probe}: {first}");
}
}
}
lines.Add($" 부가정보2: {string.Join(" · ", shapes2)}");
foreach (var f in failed)
{
lines.Add($" [진단] {f}");
}
Check("㉟ 부가정보 2차분 조회가 예외 없이 돈다", failed.Count == 0,
"위 [진단] 줄의 컬럼·조인 이름을 의심할 것");
}
catch (Exception ex)
{
Check("㉟ 부가정보 2차분 조회가 예외 없이 돈다", false,
$"{ex.GetType().Name}: {ex.Message.Split('\n')[0]}");
}
}
}
catch (Exception ex)