주소 4종을 옮긴다 — 결합 규칙이 셋 다 다르다
19종 → 23종. M_ZipMst 를 건물관리번호(PatZipBdg)로 찾는 조회 하나가 추가됐다. ## 결합식을 그대로 옮긴다 레거시(clsCommonLib.vb:16600)는 DECODE 로 빈 조각을 건너뛰며 구분자를 붙인다. 시도·시군구·읍면·도로명·지하여부·건물번호 본번/부번·건물명이 각각 다른 규칙으로 이어진다. 손으로 다시 짜면 주소가 미묘하게 달라지므로 SQL 을 그대로 가져왔다(바인드는 유지). ## 눈으로 보면 오타 같은 것 셋 PAT_도로명주소 도로명주소 + " " + 상세 (공백 있음) PAT_지번주소 지번주소 + 상세 (공백 <b>없음</b>) PAT_영문도로명주소 상세 + " " + 영문주소 (순서가 <b>뒤바뀐다</b>) 레거시가 그렇게 찍는다. 맞춰야 같은 종이가 된다. 그리고 PAT_우편번호 가 돌려주는 것은 <b>우편번호 컬럼이 아니라 구역번호</b>다. 조회는 둘 다 가져오지만 레거시가 쓰는 것은 구역번호다. 주소를 못 찾으면 빈 값이 아니라 <b>상세주소만</b> 돌려준다 — 레거시와 같다. ## 왕복은 환자당 한 번 주소 태그가 넷이라 태그마다 읽으면 왕복이 넷이 된다. 주민번호와 같이 환자를 붙이는 시점에 한 번 읽어 해석기에 넘긴다. 읽기에 실패해도 던지지 않는다 — 상세주소만으로 값을 만들 수 있고 레거시도 그렇게 한다. ## 게이트 - dotnet test 336/336 - --edit-smoke 실패 0 — 이름 검사가 23종 전부 실제 태그임을 확인 - --db-patient ①~㉑ 전건 통과 - --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
510663c5fc
commit
d63f6f6bc0
@@ -54,5 +54,31 @@ public static class PatientIdentity
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이 환자의 주소 조각들(구역번호·도로명·지번·영문) — 못 읽으면 빈 사전.
|
||||
///
|
||||
/// 주민번호와 같은 이유로 <b>환자를 붙일 때 한 번만</b> 읽는다 —
|
||||
/// 주소 태그가 넷이라 태그마다 읽으면 왕복이 넷이 된다.
|
||||
/// 실패해도 던지지 않는다: 호출부가 상세주소만으로 값을 만들 수 있고, 레거시도 그렇게 한다.
|
||||
/// </summary>
|
||||
public static IReadOnlyDictionary<string, string> AddressOf(PatientContext context)
|
||||
{
|
||||
var connection = ConfigService.Current.ConnectionString;
|
||||
var empty = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
if (connection.Length == 0)
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
try
|
||||
{
|
||||
return new PatientContextStore(connection)
|
||||
.Address(PatientContext.Value(context.PatInf, "PatZipBdg"));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -128,12 +128,16 @@ public sealed class PatientTagResolver : ITagValueResolver
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>M_ZipMst 에서 만든 주소 조각들 — 없으면 상세주소만 쓴다</summary>
|
||||
private readonly IReadOnlyDictionary<string, string> address;
|
||||
|
||||
public PatientTagResolver(PatientContext context, ITagValueResolver next,
|
||||
string residentNumber = "")
|
||||
string residentNumber = "", IReadOnlyDictionary<string, string>? address = null)
|
||||
{
|
||||
this.context = context;
|
||||
this.next = next;
|
||||
this.residentNumber = residentNumber;
|
||||
this.address = address ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -145,6 +149,10 @@ public sealed class PatientTagResolver : ITagValueResolver
|
||||
{
|
||||
return derived;
|
||||
}
|
||||
if (FromAddress(tag) is { } located)
|
||||
{
|
||||
return located;
|
||||
}
|
||||
if (Computed.TryGetValue(tag, out var compute))
|
||||
{
|
||||
var made = compute(context);
|
||||
@@ -218,6 +226,40 @@ public sealed class PatientTagResolver : ITagValueResolver
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 주소 네 종 — 해당 태그가 아니면 null.
|
||||
///
|
||||
/// <b>결합 규칙이 셋 다 다르다</b>(bzDataInterface.vb 우편번호·도로명·지번·영문도로명).
|
||||
/// 도로명은 <c>주소 + " " + 상세</c>, 지번은 <c>주소 + 상세</c>(공백 없음),
|
||||
/// 영문은 <c>상세 + " " + 주소</c>(순서가 뒤바뀐다).
|
||||
/// 눈으로 보면 오타 같지만 레거시가 그렇게 찍는다 — 맞춰야 같은 종이가 된다.
|
||||
///
|
||||
/// 우편번호 태그가 돌려주는 것은 <c>우편번호</c> 컬럼이 아니라 <b>구역번호</b>다.
|
||||
/// 조회는 둘 다 가져오지만 레거시가 쓰는 것은 구역번호다.
|
||||
///
|
||||
/// 주소를 못 찾으면 <b>상세주소만</b> 돌려준다 — 레거시와 같다. 빈 값이 아니다.
|
||||
/// </summary>
|
||||
private TagValue? FromAddress(string tag)
|
||||
{
|
||||
if (tag is not ("PAT_우편번호" or "PAT_도로명주소" or "PAT_지번주소" or "PAT_영문도로명주소"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var detail = Pat(context, "PatAdrDtl");
|
||||
var found = (string column) => address.TryGetValue(column, out var v) ? v.Trim() : string.Empty;
|
||||
|
||||
var value = tag switch
|
||||
{
|
||||
"PAT_우편번호" => found("구역번호"),
|
||||
"PAT_도로명주소" => found("도로명주소").Length > 0 ? found("도로명주소") + " " + detail : detail,
|
||||
"PAT_지번주소" => found("지번주소").Length > 0 ? found("지번주소") + detail : detail,
|
||||
_ => found("영문도로명주소").Length > 0 ? detail + " " + found("영문도로명주소") : detail,
|
||||
};
|
||||
return value.Trim().Length > 0
|
||||
? new TagValue(true, value)
|
||||
: new TagValue(false, "이 환자에게는 주소 정보가 없습니다");
|
||||
}
|
||||
|
||||
/// <summary>주민번호에서 나온 값 — 비면 <b>왜</b> 비었는지 말한다</summary>
|
||||
private TagValue Wrap(string value) => value.Length > 0
|
||||
? new TagValue(true, value)
|
||||
@@ -230,6 +272,7 @@ public sealed class PatientTagResolver : ITagValueResolver
|
||||
public static readonly string[] DerivedTags =
|
||||
{
|
||||
"PAT_주민번호", "PAT_주민번호_Dash", "PAT_성별", "PAT_한글성별",
|
||||
"PAT_우편번호", "PAT_도로명주소", "PAT_지번주소", "PAT_영문도로명주소",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user