초기 커밋: SheetMe 서식생성기 (P0~P5 완료 상태)

레거시 서식생성기(VB.NET WinForms) 대체용 C#/.NET 10 WPF 디자이너.
기준선: 실DB 활성 디자인 1,271건 왕복 의미론 diff 0 / 예외 0, 단위 테스트 49/49.

이 커밋에 함께 포함된 자격증명 분리:
- appsettings.json 을 __HOST__/__PASSWORD__ 플레이스홀더로 전환
- 실접속 정보는 appsettings.Development.json 으로 분리(.gitignore 제외,
  csproj Debug 조건부 복사라 Release 산출물에 실리지 않음)
- ConfigLoader 를 환경변수 > Development > appsettings 순 레이어링으로 변경,
  미치환 플레이스홀더는 '미설정'으로 간주

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-11 17:20:22 +09:00
co-authored by Claude Fable 5
commit 16c07f48dc
102 changed files with 14210 additions and 0 deletions
@@ -0,0 +1,117 @@
using SheetMe.Core.Models;
using SheetMe.Data.Config;
using SheetMe.Data.Stores;
using SheetMe.Designer.Services;
namespace SheetMe.Designer.DataBusiness;
/// <summary>
/// 서식 디자인 데이터 비즈니스 — 저장소(파일/DB) 접근을 ViewModel 에서 격리.
/// 본 도구는 내부 관리용 팻 클라이언트로 저장소를 직접 호출한다(컨벤션 편차 — 계획서 명시).
/// DB 저장은 SaveMode='Db' 설정 게이트 뒤에서만 활성화. REST 전환 시 이 계층만 교체한다.
/// </summary>
internal sealed class FormDesignDataBusiness
{
#region Member Fields
private readonly XmlFileFormStore fileStore = new();
private OracleLegacyFormStore? dbStore;
#endregion
#region Properties
/// <summary>데이터 설정(appsettings.json)</summary>
public DataConfig Config { get; } = ConfigLoader.Load();
/// <summary>DB 사용 가능 여부 — 접속 문자열 존재</summary>
public bool CanUseDb => Config.ConnectionString.Length > 0;
/// <summary>DB 저장 허용 여부 — SaveMode='Db' 명시 설정</summary>
public bool CanSaveToDb => CanUseDb && Config.IsDbSaveMode();
#endregion
#region Methods
/// <summary>레거시 XML 파일 열기</summary>
public FormDocument OpenXmlFile(string path) => fileStore.LoadFile(path);
/// <summary>레거시 XML 파일 저장</summary>
public void SaveXmlFile(FormDocument document, string path) => fileStore.SaveFile(document, path);
/// <summary>새 문서 생성 — 빈 페이지 1장(레거시 기본 720×856)</summary>
public FormDocument CreateNew()
{
var document = new FormDocument
{
FormId = "NewSheet",
Title = "새 서식",
};
document.Pages.Add(Core.Serialization.LegacyXmlSerializer.CreateEmptyPage(1));
return document;
}
/// <summary>DB 서식 목록 검색</summary>
public List<SheetSummary> ListSheets(string? keyword)
=> DbStore().ListSheets(keyword);
/// <summary>DB 활성 디자인 열기 — 디자인 없으면 null</summary>
public FormDocument? OpenFromDb(string shtCod)
=> DbStore().LoadActiveDesign(shtCod);
/// <summary>서식 디자인 버전 이력(E_SdgMst, 본문 제외)</summary>
public List<DesignVersionInfo> ListVersions(string shtCod)
=> DbStore().ListVersions(shtCod);
/// <summary>특정 버전 디자인 열기 — 이력 열람/복원</summary>
public FormDocument? OpenFromDbVersion(string shtCod, decimal sdgKey)
=> DbStore().LoadDesignByKey(shtCod, sdgKey);
/// <summary>서식의 Spread 격자(E_SpdMst 파싱) — 컨트롤명 → 격자 정보(파싱 실패 건 제외)</summary>
public Dictionary<string, Core.Serialization.SpreadGridInfo> LoadSpreadGrids(string shtCod)
{
var result = new Dictionary<string, Core.Serialization.SpreadGridInfo>(StringComparer.Ordinal);
foreach (var (name, xml) in DbStore().LoadSpreadDesigns(shtCod))
{
if (Core.Serialization.FarPointSpreadParser.Parse(xml) is { } grid)
{
result[name] = grid;
}
}
return result;
}
/// <summary>DB 저장(E_SdgMst 버저닝 + E_SctMst 재생성) — 반환 SdgKey</summary>
public decimal SaveToDb(FormDocument document)
{
if (!CanSaveToDb)
{
throw new InvalidOperationException(
"DB 저장이 비활성화되어 있습니다. appsettings.json 의 FormStore:SaveMode 를 'Db' 로 설정하세요.");
}
return DbStore().SaveDesign(document, Environment.UserName);
}
/// <summary>서식 코드 등록 여부(E_ShtMst)</summary>
public bool SheetExists(string shtCod) => DbStore().SheetExists(shtCod);
/// <summary>신규 서식 최소 등록 — 디자이너 서식 관행 기본값</summary>
public void RegisterSheet(string shtCod, string korName, string? clsCod)
=> DbStore().RegisterSheet(shtCod, korName, clsCod, Environment.UserName);
/// <summary>상용구 저장소(E_SHTWRDMST) — DB 접속 필요</summary>
public RecordWordStore RecordWords()
{
if (!CanUseDb)
{
throw new InvalidOperationException("DB 접속 문자열(ConnectionStrings:His)이 설정되지 않았습니다.");
}
return new RecordWordStore(Config.ConnectionString);
}
private OracleLegacyFormStore DbStore()
{
if (!CanUseDb)
{
throw new InvalidOperationException("DB 접속 문자열(ConnectionStrings:His)이 설정되지 않았습니다.");
}
return dbStore ??= new OracleLegacyFormStore(Config.ConnectionString);
}
#endregion
}