비급여처방·전문그룹과목·청구진료과목·임신주기 4종 — 250종 → 254종

OCM_비급여처방(bzDataInterface.vb:10964, Case Else + SRCH 조건 갈래 —
고지 대상(SgaNtiNon='Y')·수가 그룹 존재만. TYRCH UNION·BSGH 치료실·
GNRH·BSQ·SUSS 분기 미이식). 보험 코드로 금액 컬럼을 골라 0 초과만
"이름(##,###)원" CRLF 결합. 특수 계산코드(SGACFG Use_SgaCA1/2)
환자군은 레거시가 SELECT 에 없는 컬럼을 읽어 항상 빈 값(무증상
실패) — 설정을 읽어 그 환자군이면 사유로 말한다(이 DB 에 설정이
실제로 1건 있다 — ㉟ 확인).

OCM_진단서전문그룹과목(:11245 — DepBilCod='01'+세부과목이면 MEDDTL
이름, 아니면 GDPTBL 그룹과목. 원문의 0행 Rows(0) 크래시는 사유로).
OCM_청구진료과목(:11398 — 문맥 진료과 행의 DepBilCod 를 BDPTBL 로.
부서 시점과 유효기간 시점이 어긋나는 원문 특이점 그대로).
OCM_임신주기(:11845 — 사용자 설정(EDD/LMP) 조회가 코드 컬럼에
사용자 이름을 비교하는 결함으로 항상 0행 → 기본값 LMP 고정.
LMP 산식만 옮기고 도달 불가한 EDD 산식은 미이식. 주수는 총일수/7·
나머지, 월경일이 미래면 음수 일수만 — 원문 그대로).

- dotnet test 342/342 · --edit-smoke 실패 0 (이름 검사 254종)
- --db-patient ①~㊱ 전건 통과 (그룹과목 실값 3컬럼)
- --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-20 08:59:49 +09:00
co-authored by Claude Fable 5
parent 199a4142ee
commit edb9cc65cf
3 changed files with 201 additions and 0 deletions
@@ -763,6 +763,82 @@ public sealed class PatientExtraStore
+ " ORDER BY OdrDtm, OdrCod, OdrNam",
("m", comNum));
/// <summary>
/// 비급여 오더 행들(OCM_비급여처방, :10964 — Case Else + SRCH 조건 갈래).
/// SRCH 는 고지 대상(SgaNtiNon='Y')이고 수가 그룹(SgaHgnCod)이 있는 것만 본다.
/// TYRCH(UNION)·BSGH(치료실)·GNRH·BSQ·SUSS 분기는 미이식.
/// </summary>
public IReadOnlyList<IReadOnlyDictionary<string, string>> NonInsuredOrders(decimal comNum)
=> Rows(
"SELECT SgaKorNam, SgaHthNon, SgaGudNon, SgaCarNon, SgaWrkNon, SgaGenFor, SgaGenNon"
+ " FROM O_OdrInf"
+ " INNER JOIN O_OdsInf ON OdrKey = OdsOdrKey AND OdsStt = 'OE'"
+ " LEFT JOIN M_SgaMst ON OdrCod = SgaCod"
+ " AND OdrDtm BETWEEN SgaStrDte AND SgaEndDte || '2359'"
+ " WHERE OdrComNum = :m AND OdrStt = 'OE' AND OdrStkStt = 'OE'"
+ " AND OdrInsYon = '3'"
+ " AND (OdrHidden IS NULL OR OdrHidden <> 1)"
+ " AND OdrGrpSub = 0"
+ " AND (OdrAutCod IS NULL OR OdrAutCod = '-')"
+ " AND (OdrCod IS NOT NULL AND OdrCod <> '-')"
+ " AND (OdrSimEdt IS NULL OR OdrSimEdt NOT IN ('I','E'))"
+ " AND SgaNtiNon = 'Y'"
+ " AND (SgaHgnCod IS NOT NULL AND SgaHgnCod <> ' ')"
+ " GROUP BY SgaKorNam, SgaHthNon, SgaGudNon, SgaCarNon, SgaWrkNon, SgaGenFor, SgaGenNon"
+ " ORDER BY SgaKorNam",
("m", comNum));
/// <summary>
/// 특수 계산코드 2종(M_DtlMst SGACFG 의 Use_SgaCA1/Use_SgaCA2, DtlCodVal 의 첫 '/' 조각 —
/// clsCommonLib.vb:3946-3999). 환자 계산코드가 여기 맞으면 레거시 비급여처방은
/// SELECT 에 없는 컬럼(SgaCA1Non)을 읽어 <b>항상 빈 값</b>이었다 — 해석기가 사유로 만든다.
/// </summary>
public IReadOnlyList<string> SpecialNonInsuredCalCodes()
=> Rows("SELECT DtlCod, DtlCodVal FROM M_DtlMst WHERE DtlTblCod = 'SGACFG'")
.Where(r => r.TryGetValue("DtlCod", out var c)
&& c.Trim().ToUpperInvariant() is "USE_SGACA1" or "USE_SGACA2")
.Select(r => (r.TryGetValue("DtlCodVal", out var v) ? v : string.Empty)
.Split('/')[0].Trim())
.Where(v => v.Length > 0)
.ToArray();
/// <summary>
/// 진료과의 그룹과목 행(OCM_진단서전문그룹과목, :11245 쿼리1) — 오늘 기준.
/// 원문은 0행이면 Rows(0) 크래시였다 — 여기는 빈 사전(해석기가 사유로).
/// </summary>
public IReadOnlyDictionary<string, string> GroupSubjectRow(string depCod)
=> depCod.Trim().Length == 0
? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
: Row(
"SELECT * FROM (SELECT DepBilCod, DepMedDtl, DtlCodNam FROM M_DepMst"
+ " INNER JOIN M_DtlMst ON DepGrpCod = DtlCod AND DtlTblCod = 'GDPTBL'"
+ " AND TO_CHAR(SYSDATE, 'YYYYMMDD') BETWEEN DtlStrDte AND DtlExpDte"
+ " WHERE TRIM(DepCod) = :d"
+ " AND TO_CHAR(SYSDATE, 'YYYYMMDD') BETWEEN DepStrDte AND DepEndDte)"
+ " WHERE ROWNUM = 1",
("d", depCod.Trim()));
/// <summary>
/// 코드표 이름 — 레거시 GetDtlCodNam(tbl, cod)(기간 조건 없음, clsCommonLib.vb:7020) 대응.
/// 다중이면 원문 첫 행 — 시작일 최신으로 고정한다.
/// </summary>
public string CodeName(string tableCod, string cod)
=> cod.Trim().Length == 0 ? string.Empty
: Scalar(
"SELECT v FROM (SELECT DtlCodNam v FROM M_DtlMst"
+ " WHERE DtlTblCod = :t AND DtlCod = :c ORDER BY DtlStrDte DESC) WHERE ROWNUM = 1",
("t", tableCod), ("c", cod.Trim()));
/// <summary>
/// 임신 정보 최신 행(OCM_임신주기, :11845) — 분만예정일(PrgEddDte)·최종월경일(PrgLmpDte)
/// 과 서버 오늘. 갱신일시 최신 행(원문 정렬 그대로).
/// </summary>
public IReadOnlyDictionary<string, string> PregnancyRow(decimal comNum)
=> Row(
"SELECT * FROM (SELECT PrgEddDte, PrgLmpDte, TO_CHAR(SYSDATE, 'YYYYMMDD') AS Today"
+ " FROM O_PrgInf WHERE PrgComNum = :m ORDER BY PrgUpdDtf DESC) WHERE ROWNUM = 1",
("m", comNum));
/// <summary>스칼라 1칸 — 0행이거나 NULL 이면 빈 문자열. 잔여 공백은 걷는다(문맥 행과 같은 규칙)</summary>
private string Scalar(string sql, params (string Name, object Value)[] binds)
{