쿼리 치환 변수를 클래스 전체 이름 형식으로 교체 (치환 실패 → ORA 오류 수정)
레거시 런타임 bzDesignSheetLoader.ConvertQuery 는 토큰 접두어를 PatientInfo/SheetInfo/WorkInfo 의 GetType.FullName 과 Select Case 완전일치로 비교한다. 기존 목록은 <<PatientInfo.ChtNum>> 축약형이라 어떤 토큰도 치환되지 않고 <<...>> 가 SQL 에 리터럴로 남아 ORA 구문오류를 냈다 — 그 데이터소스를 참조하는 컨트롤이 전부 공백이 되는 조용한 실패다. 기존 서식의 쿼리는 원문 보존이라 영향 없고, 신규 작성분만 해당된다. 접두어는 ucLoadSheetBase.vb:7619-7631 이 형을 고정한다: PatientInfo/WorkInfo → M.CMM.HISOperatingInfo.* SheetInfo → M.EMR.SheetLoadOperatingInfo.bzSheetInfo 기존 20개 중 8개는 접두어뿐 아니라 속성명 자체가 실존하지 않았다(리플렉션 null): PatientInfo.OdrNum/OdrSeq, SheetInfo.EmrGbn/PatTyp/OdrNum/OdrSeq, WorkInfo.WrkNam/AdpDep. bzPatientInfo/bzSheetInfo/bzWorkInfo 의 실존 공개 스칼라 속성으로 다시 큐레이션했다. DataRow 접근형(...PatInfDR.item(컬럼))은 LastIndexOf(.) 규칙이 접두어를 깨뜨려 이 경로에서 반드시 실패하므로 목록에서 제외. - LegacyQueryVariableCatalog 신설(그룹/설명 포함 레코드) - 편집기 목록을 그룹 헤더 + 설명/토큰 2줄 + 툴팁으로 — 축약 오해 재발 방지 - 상용구 편집의 QueryEditorWindow 재사용에 showVariables:false 추가 (상용구 문구 화면에 SQL 변수 목록이 노출되던 오조작 여지 제거) 검증: 테스트 70/70(레거시 완전일치 규칙 시뮬레이션 + 운영 실사용 토큰 존재 검사 포함), edit-smoke 에 두 모드 실제 창 생성 검사 추가 — 실패 0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
c445b851a1
commit
d0538ef95a
@@ -1,54 +1,52 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using SheetMe.Core.Catalog;
|
||||
|
||||
namespace SheetMe.Designer.Views;
|
||||
|
||||
/// <summary>
|
||||
/// 데이터소스(MDataTable) 쿼리 전용 편집기 — 큰 SQL 편집 영역 + 치환 변수 삽입.
|
||||
/// 치환 규칙 원본: [014]EMRLoader bzDesignSheetLoader.ConvertQuery — <<PatientInfo/SheetInfo/WorkInfo.속성>> 리플렉션 치환.
|
||||
/// 변수 목록 출처: [021]SheetLoadOperatingInfo 의 bzPatientInfo/bzSheetInfo/bzWorkInfo 공개 속성(스칼라만 큐레이션, 2026-07-16).
|
||||
/// 치환 규칙 원본: [014]EMRLoader bzDesignSheetLoader.ConvertQuery.
|
||||
/// 토큰 접두어는 <b>클래스 전체 이름</b>이어야 하며 런타임이 GetType.FullName 과 완전일치로 비교한다
|
||||
/// (ucLoadSheetBase.vb:7619-7631 이 형을 고정). 목록은 <see cref="LegacyQueryVariableCatalog"/> 참조.
|
||||
///
|
||||
/// 큰 다중행 편집 영역이 필요한 다른 용도(상용구 문구)에도 재사용한다 —
|
||||
/// 그 경우 <c>showVariables: false</c> 로 SQL 변수 패널을 숨긴다.
|
||||
/// </summary>
|
||||
public partial class QueryEditorWindow : Window
|
||||
{
|
||||
#region Member Fields
|
||||
/// <summary>치환 변수 목록 — 작성 시점 실제 값으로 치환됨</summary>
|
||||
private static readonly string[] Variables =
|
||||
{
|
||||
"<<PatientInfo.ChtNum>>",
|
||||
"<<PatientInfo.ComNum>>",
|
||||
"<<PatientInfo.PatTyp>>",
|
||||
"<<PatientInfo.OdrNum>>",
|
||||
"<<PatientInfo.OdrSeq>>",
|
||||
"<<SheetInfo.ShtCod>>",
|
||||
"<<SheetInfo.ShtNam>>",
|
||||
"<<SheetInfo.EmrKey>>",
|
||||
"<<SheetInfo.EmrGbn>>",
|
||||
"<<SheetInfo.AdpDtm>>",
|
||||
"<<SheetInfo.PatTyp>>",
|
||||
"<<SheetInfo.OdrNum>>",
|
||||
"<<SheetInfo.OdrSeq>>",
|
||||
"<<SheetInfo.TemKey>>",
|
||||
"<<WorkInfo.WrkUid>>",
|
||||
"<<WorkInfo.WrkNam>>",
|
||||
"<<WorkInfo.WrkDte>>",
|
||||
"<<WorkInfo.WrkDtm>>",
|
||||
"<<WorkInfo.AdpDep>>",
|
||||
"<<WorkInfo.AdpDtm>>",
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>편집 결과 SQL — 확인 시 채워짐</summary>
|
||||
/// <summary>편집 결과 텍스트 — 확인 시 채워짐</summary>
|
||||
public string QueryText { get; private set; } = string.Empty;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public QueryEditorWindow(string ownerLabel, string initialQuery)
|
||||
/// <param name="ownerLabel">제목에 붙일 대상 이름</param>
|
||||
/// <param name="initialQuery">초기 텍스트</param>
|
||||
/// <param name="showVariables">SQL 치환 변수 패널 표시 여부 — 상용구 등 SQL 이 아닌 용도에서는 false</param>
|
||||
public QueryEditorWindow(string ownerLabel, string initialQuery, bool showVariables = true)
|
||||
{
|
||||
InitializeComponent();
|
||||
Title = $"쿼리 편집 — {ownerLabel}";
|
||||
SqlBox.Text = initialQuery;
|
||||
VariableList.ItemsSource = Variables;
|
||||
|
||||
if (showVariables)
|
||||
{
|
||||
Title = $"쿼리 편집 — {ownerLabel}";
|
||||
var view = new CollectionViewSource { Source = LegacyQueryVariableCatalog.All };
|
||||
view.GroupDescriptions.Add(new PropertyGroupDescription(nameof(QueryVariable.Group)));
|
||||
VariableList.ItemsSource = view.View;
|
||||
}
|
||||
else
|
||||
{
|
||||
Title = ownerLabel;
|
||||
HintText.Text = "내용을 편집한 뒤 확인을 누르세요.";
|
||||
VariablePane.Visibility = Visibility.Collapsed;
|
||||
SplitterColumn.Width = new GridLength(0);
|
||||
VariableColumn.Width = new GridLength(0);
|
||||
}
|
||||
|
||||
Loaded += (_, _) =>
|
||||
{
|
||||
SqlBox.Focus();
|
||||
@@ -63,13 +61,13 @@ public partial class QueryEditorWindow : Window
|
||||
|
||||
private void OnInsertVariable(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (VariableList.SelectedItem is not string variable)
|
||||
if (VariableList.SelectedItem is not QueryVariable variable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var caret = SqlBox.CaretIndex;
|
||||
SqlBox.Text = SqlBox.Text.Insert(caret, variable);
|
||||
SqlBox.CaretIndex = caret + variable.Length;
|
||||
SqlBox.Text = SqlBox.Text.Insert(caret, variable.Token);
|
||||
SqlBox.CaretIndex = caret + variable.Token.Length;
|
||||
SqlBox.Focus();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user