이름은 "부서번호"지만 값은 로그인 사용자 부서의 전화번호다 (bzDataInterface.vb:17287-17313 — M_DepMst.DepTelNum, SYSDATE 기준 M_UidMst 조인). 우리 로그인 조회가 이미 같은 시점·같은 조인으로 부서 행을 붙이고 있어 컬럼 하나(NVL(d.DepTelNum,' '))만 얹었다 — 왕복이 늘지 않는다. HisUser.DepPhone → UserField.DepPhone. - dotnet test 338/338 · --edit-smoke 실패 0 - --db-patient ①~㉞ 전건 통과 - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
112 lines
5.6 KiB
C#
112 lines
5.6 KiB
C#
using Oracle.ManagedDataAccess.Client;
|
|
|
|
namespace SheetMe.Data.Stores;
|
|
|
|
/// <summary>
|
|
/// HIS 로그인 사용자 — 감사 컬럼(SdgUidCod/ShtUpdUid 등)에 기록되는 UidCod 의 유일한 출처.
|
|
/// 부서·병원은 표시 전용이며 없어도 인증은 성립한다(레거시 bzLogIn 과 동일 의미론).
|
|
/// </summary>
|
|
public sealed record HisUser(
|
|
string UidCod, string UidNam,
|
|
string DepCod, string DepNam,
|
|
string HspCod, string HspNam,
|
|
/// <summary>의사 여부(UidDtrYon=Y) — OCM_User진료과 계열이 로그인 사용자 분기에 쓴다</summary>
|
|
string DoctorYn = "",
|
|
/// <summary>부서 공식 명칭(DepOfcNam) — 개원일 조건이 걸리는 병원에서 한글명 대신 쓴다</summary>
|
|
string DepOfficialName = "",
|
|
/// <summary>의사면허번호(UidLicNum) — ETC_로그인_의사면허번호</summary>
|
|
string LicenseNumber = "",
|
|
/// <summary>전문의번호(UidSpcLic) — ETC_로그인_전문의번호</summary>
|
|
string SpecialistNumber = "",
|
|
/// <summary>직종명(M_DtsMst JOBCOD 의 DtsCodNam) — ETC_로그인_직종</summary>
|
|
string JobName = "",
|
|
/// <summary>부서 전화번호(M_DepMst.DepTelNum) — ETC_접속유저_부서번호(이름과 달리 전화번호다)</summary>
|
|
string DepPhone = "")
|
|
{
|
|
/// <summary>미인증 세션(인자 없이 단독 실행) — DB 쓰기가 차단된다</summary>
|
|
public static readonly HisUser Unknown = new(string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty);
|
|
|
|
/// <summary>HIS 사용자로 확인되었는지</summary>
|
|
public bool IsAuthenticated => UidCod.Length > 0;
|
|
|
|
/// <summary>표시용 — "홍길동(MSYS)" 형태, 미인증이면 안내 문구</summary>
|
|
public string Display => IsAuthenticated
|
|
? (UidNam.Length > 0 ? $"{UidNam}({UidCod})" : UidCod)
|
|
: "사용자 미확인";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 사용자 컨텍스트 조회 — 레거시 bzLogIn.LogIn(uid, autoLogin) 의 신규 대응물.
|
|
/// 레거시도 자동 로그인에서는 비밀번호를 확인하지 않고 M_UidMst 행 존재 + 유효기간만 판정한다
|
|
/// (daLogIn.vb: SELECT * FROM M_UidMst WHERE UidCod=:u AND :adp BETWEEN UidStrDte AND UidEndDte).
|
|
/// </summary>
|
|
public sealed class UserContextStore
|
|
{
|
|
#region Member Fields
|
|
private readonly string connectionString;
|
|
#endregion
|
|
|
|
#region Constructors
|
|
public UserContextStore(string connectionString)
|
|
{
|
|
this.connectionString = connectionString;
|
|
}
|
|
#endregion
|
|
|
|
#region Methods
|
|
/// <summary>
|
|
/// UidCod 검증 + 표시 정보 조회 — 미존재이거나 유효기간 밖이면 null.
|
|
/// 적용일자는 서버 시각을 쓴다(단말 시계가 밀리면 유효 계정이 거부될 수 있다).
|
|
/// 부서·병원은 LEFT JOIN 이라 마스터에 행이 없어도 인증 자체는 성립한다.
|
|
/// </summary>
|
|
public HisUser? Resolve(string uidCod)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(uidCod))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
using var connection = new OracleConnection(connectionString);
|
|
connection.Open();
|
|
using var command = connection.CreateCommand();
|
|
command.BindByName = true;
|
|
// 레거시와 두 가지가 <b>의도적으로</b> 다르다(워크플로 검증이 짚었고, 받아들이기로 했다):
|
|
// · 유효기간 판정 일자 — 레거시는 로그인 시점(GetAdpDtm 앞 8자, clsCommonLib.vb:10622),
|
|
// 여기는 SYSDATE. 자정을 넘겨 계속 켜 둔 세션에서만 갈린다.
|
|
// · Trim — 레거시는 UidCod/UidNam 을 무가공으로 쓰고(bzDataInterface.vb:16713, 16720)
|
|
// 여기는 걷는다. CHAR 잔여 공백이 종이에 찍히는 쪽이 더 이상하다고 판단했다.
|
|
command.CommandText =
|
|
"SELECT u.UidCod, NVL(u.UidNam,' '), " +
|
|
" NVL(u.UidDepCod,' '), NVL(d.DepKorNam,' '), " +
|
|
" NVL(u.UidHspCod,' '), NVL(h.HspInsNam,' '), " +
|
|
" NVL(u.UidDtrYon,' '), NVL(d.DepOfcNam,' '), " +
|
|
" NVL(u.UidLicNum,' '), NVL(u.UidSpcLic,' '), NVL(j.DtsCodNam,' '), " +
|
|
" NVL(d.DepTelNum,' ') " +
|
|
"FROM M_UidMst u " +
|
|
"LEFT JOIN M_DepMst d ON d.DepCod = u.UidDepCod " +
|
|
" AND TO_CHAR(SYSDATE,'YYYYMMDD') BETWEEN d.DepStrDte AND d.DepEndDte " +
|
|
"LEFT JOIN M_HspMst h ON h.HspCod = u.UidHspCod " +
|
|
" AND TO_CHAR(SYSDATE,'YYYYMMDD') BETWEEN h.HspStrDte AND NVL(h.HspEndDte,'99991231') " +
|
|
// 직종 조인은 레거시 그대로 DtsDtlCod 만으로 건다(bzDataInterface.vb:17944 — DtsTblCod 조건이 없다)
|
|
"LEFT JOIN M_DtsMst j ON j.DtsDtlCod = 'JOBCOD' AND j.DtsCod = u.UidJobCod " +
|
|
" AND TO_CHAR(SYSDATE,'YYYYMMDD') BETWEEN j.DtsStrDte AND j.DtsExpDte " +
|
|
"WHERE u.UidCod = :u " +
|
|
"AND TO_CHAR(SYSDATE,'YYYYMMDD') BETWEEN u.UidStrDte AND u.UidEndDte";
|
|
command.Parameters.Add(new OracleParameter("u", uidCod.Trim()));
|
|
|
|
using var reader = command.ExecuteReader();
|
|
if (!reader.Read())
|
|
{
|
|
return null;
|
|
}
|
|
return new HisUser(
|
|
reader.GetString(0).Trim(), reader.GetString(1).Trim(),
|
|
reader.GetString(2).Trim(), reader.GetString(3).Trim(),
|
|
reader.GetString(4).Trim(), reader.GetString(5).Trim(),
|
|
reader.GetString(6).Trim(), reader.GetString(7).Trim(),
|
|
reader.GetString(8).Trim(), reader.GetString(9).Trim(), reader.GetString(10).Trim(),
|
|
reader.GetString(11).Trim());
|
|
}
|
|
#endregion
|
|
}
|