수술 8종을 옮긴다 — 그리고 이 시험 DB 에는 O_OprInf 가 없다는 것을 알았다. 51종 → 59종
## GetOprInfDT(bzDataInterface.vb:13203-13363)의 이식 상병과 달리 병원 분기가 없다(Select Case 0회). 바인드는 내원번호 하나 — 접수일자 조건은 원문에서 이미 주석 처리된 죽은 코드다. SQL 133줄을 원문에서 기계 추출했다(O_OprInf 축, 수술명·부위·상병·집도의·마취의 LISTAGG). 소비 태그 8종이 전부 <b>첫 행에서 컬럼 하나</b>를 집는다: OCM_OPNAME · OPRCODNAM · DX · 수술상병(OkdNam) · 수술부위(OprRegionName) 수술_OprPatETC · 수술집도의(OprDtrNam) · 수술마취의사(AneUidCod) 원문 Catch 는 ErrorMessageBox 를 띄운다 — 조회 함수의 대화상자 부작용은 옮기지 않고 던져서 해석기가 사유로 바꾼다. 수술 조회도 상병과 같은 지연 정책이다 (수술 태그가 없는 서식이 다수라 환자를 붙일 때 무조건 읽지 않는다). ## 검증의 한계를 정확히 적는다 --db-patient ㉘ 이 O_OprInf 에서 내원을 못 찾았고, 처음엔 "행이 없다"로 적었다. 가려 보니 <b>ORA-00942 — 이 시험 DB(SRCH_TEST)에 표 자체가 없다.</b> 즉 수술 태그는 여기서 실행 검증이 불가능하고 운영 DB 에서만 확인할 수 있다. SKIP 문구를 그 사실대로 고쳤다 — "확인했다"고 적을 뻔한 것을 진단이 막았다. 런타임에서는 해석기가 예외를 잡아 "수술 조회에 실패했습니다"로 말한다. ## 게이트 - dotnet test 338/338 · --edit-smoke 실패 0(이름 검사 59종) - --db-patient ①~㉗ 통과, ㉘ SKIP(표 부재 명시) - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0da3305a75
commit
460f6c4a91
@@ -0,0 +1,192 @@
|
|||||||
|
using Oracle.ManagedDataAccess.Client;
|
||||||
|
|
||||||
|
namespace SheetMe.Data.Stores;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 수술 정보 조회 — 레거시 <c>GetOprInfDT</c>(bzDataInterface.vb:13203-13363)의 이식.
|
||||||
|
///
|
||||||
|
/// 상병과 달리 <b>병원 분기가 없다</b>(Select Case 0회). 바인드는 내원번호 하나뿐이고
|
||||||
|
/// 접수일자 조건은 원문에서 이미 주석 처리되어 있다(:sAcpDte — 죽은 코드).
|
||||||
|
///
|
||||||
|
/// SQL 은 원문에서 기계 추출했다(133줄 그대로). O_OprInf 를 축으로 수술명·부위·상병·
|
||||||
|
/// 집도의·마취의를 LISTAGG 로 접는 큰 조회이고, 소비 태그 8종이 전부
|
||||||
|
/// <b>첫 행에서 컬럼 하나</b>를 집는다 — 그래서 행 목록만 돌려주고 선택은 해석기가 한다.
|
||||||
|
///
|
||||||
|
/// 원문의 Catch 는 ErrorMessageBox 를 띄운다 — 여기서는 던진다(해석기가 사유로 바꾼다).
|
||||||
|
/// 조회 함수가 대화상자를 띄우는 부작용은 옮기지 않는다.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class SurgeryStore
|
||||||
|
{
|
||||||
|
#region Member Fields
|
||||||
|
private readonly string connectionString;
|
||||||
|
|
||||||
|
/// <summary>원문 그대로의 조회 — 바인드는 :iComNum 하나다</summary>
|
||||||
|
private const string Query = @"
|
||||||
|
With
|
||||||
|
OprInfRec
|
||||||
|
AS
|
||||||
|
(
|
||||||
|
SELECT Opr.*
|
||||||
|
FROM (
|
||||||
|
|
||||||
|
SELECT /* 수술 정보 */
|
||||||
|
OprKey
|
||||||
|
, OprDte
|
||||||
|
, OprChtNum
|
||||||
|
, OprComNum, OprOrgCom, OprGbnCod, OprStt
|
||||||
|
, OprRomCod
|
||||||
|
, OprUseTms, OprStrTms, OprDayNum
|
||||||
|
, OprActStt
|
||||||
|
, OprNam
|
||||||
|
, OprDtrCod, OprDepCod, OprSplCmt
|
||||||
|
, CASE OprRegion WHEN '1' THEN '오른쪽'
|
||||||
|
WHEN '2' THEN '왼쪽'
|
||||||
|
WHEN '3' THEN '양쪽'
|
||||||
|
ELSE '없음'
|
||||||
|
END AS OprRegionName
|
||||||
|
, OprPatEtc
|
||||||
|
, OPR.OprUpdDtf
|
||||||
|
|
||||||
|
/* 인적 정보 */
|
||||||
|
, PatNam
|
||||||
|
, PatSexTyp
|
||||||
|
, ComPatTyp
|
||||||
|
, SUBSTR(ComAcpDtm, 1, 8) AS ComAcpDte
|
||||||
|
|
||||||
|
/* 관련 정보 */
|
||||||
|
, PRGSTSDTL.DtlCodNam AS OprActFlg
|
||||||
|
, UIDOPRDTR.UidNam AS OprDtrNam /* 집도의 명 */
|
||||||
|
, UIDCODDTR.UidNam AS CodDtrNam /* 주치의 명 */
|
||||||
|
|
||||||
|
, ROW_NUMBER() OVER (PARTITION BY OprKey ORDER BY CodStrDtm DESC ) AS RN
|
||||||
|
|
||||||
|
FROM S_OprInf OPR
|
||||||
|
LEFT JOIN P_PatInf
|
||||||
|
ON PatChtNum = OprChtNum
|
||||||
|
|
||||||
|
/* 수술정보의 내원정보 */
|
||||||
|
LEFT JOIN P_ComInf
|
||||||
|
ON OprComNum = ComNum
|
||||||
|
LEFT JOIN P_CodInf
|
||||||
|
ON CodComNum = ComNum
|
||||||
|
AND CASE WHEN ComPatTyp = 'I' THEN OprDte ||'2359'
|
||||||
|
ELSE CodStrDtm
|
||||||
|
END BETWEEN CodStrDtm AND CodEndDtm
|
||||||
|
|
||||||
|
LEFT JOIN M_DtlMst PRGSTSDTL
|
||||||
|
ON PRGSTSDTL.DtlTblCod = 'OPRPRGSTS'
|
||||||
|
AND PRGSTSDTL.DtlCod = OprActStt
|
||||||
|
/* 집도의 */
|
||||||
|
LEFT JOIN M_UidMst UIDOPRDTR
|
||||||
|
ON UIDOPRDTR.UidCod = OprDtrCod
|
||||||
|
AND OprDte BETWEEN UIDOPRDTR.UidStrDte AND UIDOPRDTR.UidEndDte
|
||||||
|
/* 주치의 */
|
||||||
|
LEFT JOIN M_UidMst UIDCODDTR
|
||||||
|
ON UIDCODDTR.UidCod = CodDtrCod
|
||||||
|
AND OprDte BETWEEN UIDCODDTR.UidStrDte AND UIDCODDTR.UidEndDte
|
||||||
|
|
||||||
|
WHERE 1 = 1
|
||||||
|
AND OprStt = 'E'
|
||||||
|
-- AND OprDte = :sAcpDte
|
||||||
|
AND OprComNum = :iComNum
|
||||||
|
-- AND OprDepCod IN ('0100','0101','0200','0201','0300','1601','1900','2100','2301','7001','0400','0500','0501','0550','0600','0601','0900','0901','1000','1100','1300','2601','0800','1400','1500','1600','5500')
|
||||||
|
|
||||||
|
) OPR
|
||||||
|
|
||||||
|
WHERE RN = 1
|
||||||
|
)
|
||||||
|
,
|
||||||
|
OprTypRec
|
||||||
|
AS
|
||||||
|
(
|
||||||
|
SELECT OprTypKey, DX, OPNAME
|
||||||
|
, SUBSTR(ANECOD, 1, LENGTH(ANECOD)-1) AS ANECOD
|
||||||
|
, SUBSTR(ANECODNAM, 1, LENGTH(ANECODNAM)-1) AS ANECODNAM
|
||||||
|
, SUBSTR(ANEUIDCOD, 1, LENGTH(ANEUIDCOD)-1) AS ANEUIDCOD
|
||||||
|
, SUBSTR(OKDNAM, 1, LENGTH(OKDNAM)) AS OKDNAM
|
||||||
|
, SUBSTR(OPRCODNAM, 1, LENGTH(OPRCODNAM)) AS OPRCODNAM
|
||||||
|
FROM (
|
||||||
|
SELECT OprKey AS OprTypKey
|
||||||
|
, MAX(DX.OprCodNam) AS DX
|
||||||
|
, MAX(OPNAME.OprCodNam) AS OPNAME
|
||||||
|
, regexp_replace(LISTAGG(ANECOD.OprCod || ',') WITHIN GROUP ( ORDER BY ANECOD.OprTypKey ), '([^,]+)(,\1)+', '\1') AS ANECOD
|
||||||
|
, regexp_replace(LISTAGG(ANECOD.OprCodNam || ',') WITHIN GROUP ( ORDER BY ANECOD.OprTypKey ), '([^,]+)(,\1)+', '\1') AS ANECODNAM
|
||||||
|
, regexp_replace(LISTAGG(ANEUID.OprCodNam || ',') WITHIN GROUP ( ORDER BY ANEUID.OprTypKey ), '([^,]+)(,\1)+', '\1') AS ANEUIDCOD
|
||||||
|
, MIN(OKDNAM.OprCodNam) AS OKDNAM
|
||||||
|
, MIN(OPRCODNAM.OprCodNam) AS OPRCODNAM
|
||||||
|
|
||||||
|
FROM OprInfRec
|
||||||
|
LEFT JOIN S_OprTyp DX
|
||||||
|
ON OprKey = DX.OprKeyNum
|
||||||
|
AND DX.OprTyp = 'DX'
|
||||||
|
LEFT JOIN S_OprTyp OPNAME
|
||||||
|
ON OprKey = OPNAME.OprKeyNum
|
||||||
|
AND OPNAME.OprTyp = 'OPNAME'
|
||||||
|
LEFT JOIN S_OprTyp ANECOD
|
||||||
|
ON OprKey = ANECOD.OprKeyNum
|
||||||
|
AND ANECOD.OprTyp = 'ANECOD'
|
||||||
|
LEFT JOIN S_OprTyp ANEUID
|
||||||
|
ON OprKey = ANEUID.OprKeyNum
|
||||||
|
AND ANEUID.OprTyp = 'ANEUIDCOD'
|
||||||
|
LEFT JOIN S_OprTyp OKDNAM
|
||||||
|
ON OprKey = OKDNAM.OprKeyNum
|
||||||
|
AND OKDNAM.OprTyp = 'OKD'
|
||||||
|
LEFT JOIN S_OprTyp OPRCODNAM
|
||||||
|
ON OprKey = OPRCODNAM.OprKeyNum
|
||||||
|
AND OPRCODNAM.OprTyp = 'OPRCOD'
|
||||||
|
AND ROWNUM = 1
|
||||||
|
|
||||||
|
WHERE 1 = 1
|
||||||
|
GROUP BY OprKey
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
,
|
||||||
|
OprLstRec
|
||||||
|
AS
|
||||||
|
(
|
||||||
|
SELECT *
|
||||||
|
FROM OprInfRec
|
||||||
|
LEFT JOIN OprTypRec
|
||||||
|
ON OprKey = OprTypKey
|
||||||
|
)
|
||||||
|
|
||||||
|
--SELECT * FROM OprInfRec
|
||||||
|
--SELECT * FROM OprTypRec
|
||||||
|
SELECT * FROM OprLstRec
|
||||||
|
ORDER BY OprComNum, OprDte DESC, OprDayNum ASC
|
||||||
|
";
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
public SurgeryStore(string connectionString) => this.connectionString = connectionString;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
/// <summary>이 내원의 수술 행들 — 없으면 빈 목록</summary>
|
||||||
|
public List<Dictionary<string, string>> Surgeries(decimal comNum)
|
||||||
|
{
|
||||||
|
using var connection = new OracleConnection(connectionString);
|
||||||
|
connection.Open();
|
||||||
|
using var command = connection.CreateCommand();
|
||||||
|
command.BindByName = true;
|
||||||
|
command.CommandText = Query;
|
||||||
|
command.Parameters.Add(new OracleParameter("iComNum", comNum));
|
||||||
|
|
||||||
|
var rows = new List<Dictionary<string, string>>();
|
||||||
|
using var reader = command.ExecuteReader();
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
var row = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
for (var i = 0; i < reader.FieldCount; i++)
|
||||||
|
{
|
||||||
|
row[reader.GetName(i)] = reader.IsDBNull(i)
|
||||||
|
? string.Empty
|
||||||
|
: reader.GetValue(i).ToString()!.Trim();
|
||||||
|
}
|
||||||
|
rows.Add(row);
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -2237,6 +2237,32 @@ public static class DbSmoke
|
|||||||
"M_KcdMst 조인이 빈 이름을 냈다");
|
"M_KcdMst 조인이 빈 이름을 냈다");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ㉘ 수술 — 원문 기계 추출 SQL 이 실제로 돈다.
|
||||||
|
var oprOwner = FirstComNum(conn, "O_OprInf", "OprComNum", "OprComNum");
|
||||||
|
if (oprOwner is null)
|
||||||
|
{
|
||||||
|
// "행이 없다"와 "표가 없다/조회가 죽었다"를 가른다 —
|
||||||
|
// FirstComNum 은 예외를 삼키므로 이 줄 없이는 못 가른다.
|
||||||
|
foreach (var line in ExplainPeriod(conn, 0,
|
||||||
|
"SELECT COUNT(*) OPRCNT FROM O_OprInf WHERE :k = 0"))
|
||||||
|
{
|
||||||
|
lines.Add($" [진단] O_OprInf: {line}");
|
||||||
|
}
|
||||||
|
lines.Add("SKIP ㉘ 수술 — 확인 불가. 위 [진단] 줄이 원인이다:"
|
||||||
|
+ " ORA-00942 면 이 시험 DB 에 O_OprInf 가 아예 없는 것이고,"
|
||||||
|
+ " 수술 태그는 운영 DB 에서만 검증할 수 있다");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var surgeries = new SurgeryStore(conn).Surgeries(oprOwner.Value);
|
||||||
|
var opName = surgeries.Count > 0
|
||||||
|
&& surgeries[0].TryGetValue("OPNAME", out var on) ? on : "";
|
||||||
|
lines.Add($" 수술: 내원 {oprOwner.Value:F0} → {surgeries.Count}행,"
|
||||||
|
+ $" OPNAME {opName.Length}자 (값은 기록하지 않는다)");
|
||||||
|
Check("㉘ 수술 쿼리가 행을 돌려준다", surgeries.Count > 0,
|
||||||
|
"OprStt='E' 조건이나 조인을 의심할 것");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,15 @@ public static class PatientIdentity
|
|||||||
: new DiagnosisStore(connection).Diagnoses(context.ComNum, scope);
|
: new DiagnosisStore(connection).Diagnoses(context.ComNum, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>수술 행 공급자 — 상병과 같은 정책(필요할 때 1회, 실패는 던져 사유로)</summary>
|
||||||
|
public static Func<IReadOnlyList<Dictionary<string, string>>> SurgerySourceFor(PatientContext context)
|
||||||
|
{
|
||||||
|
var connection = ConfigService.Current.ConnectionString;
|
||||||
|
return () => connection.Length == 0
|
||||||
|
? new List<Dictionary<string, string>>()
|
||||||
|
: new SurgeryStore(connection).Surgeries(context.ComNum);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 이 내원의 진료과 마스터 행 — 못 읽으면 빈 사전.
|
/// 이 내원의 진료과 마스터 행 — 못 읽으면 빈 사전.
|
||||||
/// 진료과 코드는 문맥의 CodInf(적용일시로 고른 행)에서, 유효기간 일자는
|
/// 진료과 코드는 문맥의 CodInf(적용일시로 고른 행)에서, 유효기간 일자는
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ public static class PatientSession
|
|||||||
PatientIdentity.ResidentNumberOf(picked), PatientIdentity.AddressOf(picked),
|
PatientIdentity.ResidentNumberOf(picked), PatientIdentity.AddressOf(picked),
|
||||||
PatientIdentity.DoctorOf(picked), PatientIdentity.DepartmentOf(picked),
|
PatientIdentity.DoctorOf(picked), PatientIdentity.DepartmentOf(picked),
|
||||||
PatientIdentity.HospitalNameOf(picked),
|
PatientIdentity.HospitalNameOf(picked),
|
||||||
PatientIdentity.DiagnosisSourceFor(picked))
|
PatientIdentity.DiagnosisSourceFor(picked),
|
||||||
|
PatientIdentity.SurgerySourceFor(picked))
|
||||||
: session;
|
: session;
|
||||||
return (tags, new MDataTableRunner(document, Variables()));
|
return (tags, new MDataTableRunner(document, Variables()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,11 +174,17 @@ public sealed class PatientTagResolver : ITagValueResolver
|
|||||||
|
|
||||||
private readonly Dictionary<DiagnosisStore.Scope, IReadOnlyList<Dictionary<string, string>>> diagnosisCache = new();
|
private readonly Dictionary<DiagnosisStore.Scope, IReadOnlyList<Dictionary<string, string>>> diagnosisCache = new();
|
||||||
|
|
||||||
|
/// <summary>수술 행 공급자 — 상병과 같은 이유로 물을 때 한 번만 읽는다</summary>
|
||||||
|
private readonly Func<IReadOnlyList<Dictionary<string, string>>>? surgerySource;
|
||||||
|
|
||||||
|
private IReadOnlyList<Dictionary<string, string>>? surgeryCache;
|
||||||
|
|
||||||
public PatientTagResolver(PatientContext context, ITagValueResolver next,
|
public PatientTagResolver(PatientContext context, ITagValueResolver next,
|
||||||
string residentNumber = "", IReadOnlyDictionary<string, string>? address = null,
|
string residentNumber = "", IReadOnlyDictionary<string, string>? address = null,
|
||||||
IReadOnlyDictionary<string, string>? doctor = null,
|
IReadOnlyDictionary<string, string>? doctor = null,
|
||||||
IReadOnlyDictionary<string, string>? department = null, string hospitalName = "",
|
IReadOnlyDictionary<string, string>? department = null, string hospitalName = "",
|
||||||
Func<DiagnosisStore.Scope, IReadOnlyList<Dictionary<string, string>>>? diagnosisSource = null)
|
Func<DiagnosisStore.Scope, IReadOnlyList<Dictionary<string, string>>>? diagnosisSource = null,
|
||||||
|
Func<IReadOnlyList<Dictionary<string, string>>>? surgerySource = null)
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.next = next;
|
this.next = next;
|
||||||
@@ -188,6 +194,7 @@ public sealed class PatientTagResolver : ITagValueResolver
|
|||||||
this.department = department ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
this.department = department ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
this.hospitalName = hospitalName;
|
this.hospitalName = hospitalName;
|
||||||
this.diagnosisSource = diagnosisSource;
|
this.diagnosisSource = diagnosisSource;
|
||||||
|
this.surgerySource = surgerySource;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -215,6 +222,10 @@ public sealed class PatientTagResolver : ITagValueResolver
|
|||||||
{
|
{
|
||||||
return diagnosisValue;
|
return diagnosisValue;
|
||||||
}
|
}
|
||||||
|
if (FromSurgery(tag) is { } surgeryValue)
|
||||||
|
{
|
||||||
|
return surgeryValue;
|
||||||
|
}
|
||||||
if (Computed.TryGetValue(tag, out var compute))
|
if (Computed.TryGetValue(tag, out var compute))
|
||||||
{
|
{
|
||||||
var made = compute(context);
|
var made = compute(context);
|
||||||
@@ -503,6 +514,54 @@ public sealed class PatientTagResolver : ITagValueResolver
|
|||||||
: new TagValue(false, "상병 행은 있는데 그 값이 비어 있습니다");
|
: new TagValue(false, "상병 행은 있는데 그 값이 비어 있습니다");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 수술 8종 — 해당 태그가 아니면 null. 전부 <b>첫 행에서 컬럼 하나</b>다
|
||||||
|
/// (bzDataInterface.vb:13099-13202 및 :3109 — 각 함수가 Rows(0).Item(...) 을 집는다).
|
||||||
|
/// GetOprInfDT 는 병원 분기가 없어 미이식 병원 안내가 필요 없다.
|
||||||
|
/// </summary>
|
||||||
|
private TagValue? FromSurgery(string tag)
|
||||||
|
{
|
||||||
|
var column = tag switch
|
||||||
|
{
|
||||||
|
"OCM_OPNAME" => "OPNAME",
|
||||||
|
"OCM_OPRCODNAM" => "OPRCODNAM",
|
||||||
|
"OCM_DX" => "DX",
|
||||||
|
"OCM_수술상병" => "OkdNam",
|
||||||
|
"OCM_수술부위" => "OprRegionName",
|
||||||
|
"OCM_수술_OprPatETC" => "OprPatEtc",
|
||||||
|
"OCM_수술집도의" => "OprDtrNam",
|
||||||
|
"OCM_수술마취의사" => "AneUidCod",
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
if (column is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (surgerySource is null)
|
||||||
|
{
|
||||||
|
return new TagValue(false, "수술 조회가 연결되지 않았습니다");
|
||||||
|
}
|
||||||
|
if (surgeryCache is null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
surgeryCache = surgerySource();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new TagValue(false, $"수술 조회에 실패했습니다: {ex.GetType().Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (surgeryCache.Count == 0)
|
||||||
|
{
|
||||||
|
return new TagValue(false, "이 내원에 등록된 수술이 없습니다");
|
||||||
|
}
|
||||||
|
var value = surgeryCache[0].TryGetValue(column, out var v) ? v.Trim() : string.Empty;
|
||||||
|
return value.Length > 0
|
||||||
|
? new TagValue(true, value)
|
||||||
|
: new TagValue(false, $"수술 행은 있는데 {column} 값이 비어 있습니다");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>주민번호에서 나온 값 — 비면 <b>왜</b> 비었는지 말한다</summary>
|
/// <summary>주민번호에서 나온 값 — 비면 <b>왜</b> 비었는지 말한다</summary>
|
||||||
private TagValue Wrap(string value) => value.Length > 0
|
private TagValue Wrap(string value) => value.Length > 0
|
||||||
? new TagValue(true, value)
|
? new TagValue(true, value)
|
||||||
@@ -523,6 +582,8 @@ public sealed class PatientTagResolver : ITagValueResolver
|
|||||||
"OCM_상병명_가로", "OCM_상병명_세로", "OCM_상병명_영어_가로", "OCM_상병명_영어_세로",
|
"OCM_상병명_가로", "OCM_상병명_세로", "OCM_상병명_영어_가로", "OCM_상병명_영어_세로",
|
||||||
"OCM_상병코드_가로", "OCM_상병코드_세로", "OCM_부상병코드", "OCM_부상병POA",
|
"OCM_상병코드_가로", "OCM_상병코드_세로", "OCM_부상병코드", "OCM_부상병POA",
|
||||||
"OCM_주상병명", "OCM_주상병코드", "OCM_주상병POA",
|
"OCM_주상병명", "OCM_주상병코드", "OCM_주상병POA",
|
||||||
|
"OCM_OPNAME", "OCM_OPRCODNAM", "OCM_DX", "OCM_수술상병", "OCM_수술부위",
|
||||||
|
"OCM_수술_OprPatETC", "OCM_수술집도의", "OCM_수술마취의사",
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -225,7 +225,8 @@ public partial class PreviewWindow : Window
|
|||||||
PatientIdentity.ResidentNumberOf(picked), PatientIdentity.AddressOf(picked),
|
PatientIdentity.ResidentNumberOf(picked), PatientIdentity.AddressOf(picked),
|
||||||
PatientIdentity.DoctorOf(picked), PatientIdentity.DepartmentOf(picked),
|
PatientIdentity.DoctorOf(picked), PatientIdentity.DepartmentOf(picked),
|
||||||
PatientIdentity.HospitalNameOf(picked),
|
PatientIdentity.HospitalNameOf(picked),
|
||||||
PatientIdentity.DiagnosisSourceFor(picked));
|
PatientIdentity.DiagnosisSourceFor(picked),
|
||||||
|
PatientIdentity.SurgerySourceFor(picked));
|
||||||
// 러너를 <b>새로</b> 만든다. 같은 러너를 재사용하면 옛 환자의 조회 결과가 캐시에 남아
|
// 러너를 <b>새로</b> 만든다. 같은 러너를 재사용하면 옛 환자의 조회 결과가 캐시에 남아
|
||||||
// 환자를 바꿨는데 표는 그대로가 된다 — 태그만 바뀌고 표는 안 바뀌면 아무도 눈치채지 못한다.
|
// 환자를 바꿨는데 표는 그대로가 된다 — 태그만 바뀌고 표는 안 바뀌면 아무도 눈치채지 못한다.
|
||||||
fields = new MDataTableRunner(designer.Document,
|
fields = new MDataTableRunner(designer.Document,
|
||||||
|
|||||||
Reference in New Issue
Block a user