근태(Holyday) API 추가 및 일별/업무형태별 집계 다이얼로그 구현, OT 시작/종료시간 필드 추가

This commit is contained in:
backuppc
2025-12-02 08:26:24 +09:00
parent adcdc40169
commit aa956cf063
14 changed files with 2012 additions and 240 deletions

View File

@@ -0,0 +1,447 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Newtonsoft.Json;
using FCOMMON;
namespace Project.Web
{
public partial class MachineBridge
{
#region Holyday () API
/// <summary>
/// 근태 목록 조회 (사용자 선택 가능)
/// </summary>
public string Holyday_GetList(string sd, string ed, string uid)
{
try
{
// 권한 확인
int curLevel = Math.Max(info.Login.level, DBM.getAuth(DBM.eAuthType.holyday));
var sql = @"SELECT h.*, u.name as UserName
FROM Holyday h WITH (nolock)
LEFT JOIN Users u ON h.uid = u.id
WHERE h.gcode = @gcode";
var parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("@gcode", info.Login.gcode));
// 권한에 따라 사용자 필터링
if (curLevel < 5)
{
// 일반 사용자는 본인 것만
sql += " AND h.uid = @uid";
parameters.Add(new SqlParameter("@uid", info.Login.no));
}
else if (!string.IsNullOrEmpty(uid) && uid != "%")
{
// 관리자가 특정 사용자 선택
sql += " AND h.uid = @uid";
parameters.Add(new SqlParameter("@uid", uid));
}
if (!string.IsNullOrEmpty(sd))
{
sql += " AND h.sdate >= @sd";
parameters.Add(new SqlParameter("@sd", sd));
}
if (!string.IsNullOrEmpty(ed))
{
sql += " AND h.sdate <= @ed";
parameters.Add(new SqlParameter("@ed", ed));
}
sql += " ORDER BY h.sdate DESC, h.idx DESC";
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddRange(parameters.ToArray());
using (var da = new SqlDataAdapter(cmd))
{
var dt = new DataTable();
da.Fill(dt);
return JsonConvert.SerializeObject(new { Success = true, Data = dt });
}
}
}
catch (Exception ex)
{
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
}
}
/// <summary>
/// 근태 상세 조회
/// </summary>
public string Holyday_GetDetail(int idx)
{
try
{
var sql = @"SELECT h.*, u.name as UserName
FROM Holyday h WITH (nolock)
LEFT JOIN Users u ON h.uid = u.id
WHERE h.idx = @idx AND h.gcode = @gcode";
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddWithValue("@idx", idx);
cmd.Parameters.AddWithValue("@gcode", info.Login.gcode);
using (var da = new SqlDataAdapter(cmd))
{
var dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count > 0)
{
var row = dt.Rows[0];
var data = new Dictionary<string, object>();
foreach (DataColumn col in dt.Columns)
{
data[col.ColumnName] = row[col] == DBNull.Value ? null : row[col];
}
return JsonConvert.SerializeObject(new { Success = true, Data = data });
}
return JsonConvert.SerializeObject(new { Success = false, Message = "데이터를 찾을 수 없습니다." });
}
}
}
catch (Exception ex)
{
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
}
}
/// <summary>
/// 근태 추가
/// </summary>
public string Holyday_Add(string cate, string sdate, string edate, double term, double crtime,
double termDr, double drTime, string contents, string uid)
{
try
{
// 권한 확인
int curLevel = Math.Max(info.Login.level, DBM.getAuth(DBM.eAuthType.holyday));
if (curLevel < 5)
{
return JsonConvert.SerializeObject(new { Success = false, Message = "권한이 없습니다." });
}
// 마감 체크
var smon = sdate.Substring(0, 7);
if (DBM.GetMagamStatus(smon))
{
return JsonConvert.SerializeObject(new { Success = false, Message = $"등록일이 속한 월({smon})이 마감되었습니다." });
}
var sql = @"INSERT INTO Holyday (gcode, cate, sdate, edate, term, crtime, termDr, DrTime, contents, uid, wdate, wuid)
VALUES (@gcode, @cate, @sdate, @edate, @term, @crtime, @termDr, @drTime, @contents, @uid, GETDATE(), @wuid);
SELECT SCOPE_IDENTITY();";
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddWithValue("@gcode", info.Login.gcode);
cmd.Parameters.AddWithValue("@cate", cate ?? "");
cmd.Parameters.AddWithValue("@sdate", sdate);
cmd.Parameters.AddWithValue("@edate", edate);
cmd.Parameters.AddWithValue("@term", term);
cmd.Parameters.AddWithValue("@crtime", crtime);
cmd.Parameters.AddWithValue("@termDr", termDr);
cmd.Parameters.AddWithValue("@drTime", drTime);
cmd.Parameters.AddWithValue("@contents", contents ?? "");
cmd.Parameters.AddWithValue("@uid", uid);
cmd.Parameters.AddWithValue("@wuid", info.Login.no);
cn.Open();
var newId = Convert.ToInt32(cmd.ExecuteScalar());
return JsonConvert.SerializeObject(new { Success = true, Message = "저장되었습니다.", Data = new { idx = newId } });
}
}
catch (Exception ex)
{
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
}
}
/// <summary>
/// 근태 수정
/// </summary>
public string Holyday_Edit(int idx, string cate, string sdate, string edate, double term, double crtime,
double termDr, double drTime, string contents)
{
try
{
// 권한 확인
int curLevel = Math.Max(info.Login.level, DBM.getAuth(DBM.eAuthType.holyday));
if (curLevel < 5)
{
return JsonConvert.SerializeObject(new { Success = false, Message = "권한이 없습니다." });
}
// 마감 체크
var smon = sdate.Substring(0, 7);
if (DBM.GetMagamStatus(smon))
{
return JsonConvert.SerializeObject(new { Success = false, Message = $"등록일이 속한 월({smon})이 마감되었습니다." });
}
// 외부 연동 데이터 체크
var checkSql = "SELECT extcate, extidx FROM Holyday WHERE idx = @idx AND gcode = @gcode";
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
{
using (var cmd = new SqlCommand(checkSql, cn))
{
cmd.Parameters.AddWithValue("@idx", idx);
cmd.Parameters.AddWithValue("@gcode", info.Login.gcode);
cn.Open();
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
var extcate = reader["extcate"] != DBNull.Value ? reader["extcate"].ToString() : "";
var extidx = reader["extidx"] != DBNull.Value ? Convert.ToInt32(reader["extidx"]) : -1;
if (!string.IsNullOrEmpty(extcate) && extidx > 0)
{
return JsonConvert.SerializeObject(new {
Success = false,
Message = $"이 자료는 외부에서 자동생성된 자료입니다. (소스: {extcate}:{extidx})"
});
}
}
}
}
var sql = @"UPDATE Holyday SET
cate = @cate, sdate = @sdate, edate = @edate, term = @term, crtime = @crtime,
termDr = @termDr, DrTime = @drTime, contents = @contents, wuid = @wuid, wdate = GETDATE()
WHERE idx = @idx AND gcode = @gcode";
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddWithValue("@idx", idx);
cmd.Parameters.AddWithValue("@gcode", info.Login.gcode);
cmd.Parameters.AddWithValue("@cate", cate ?? "");
cmd.Parameters.AddWithValue("@sdate", sdate);
cmd.Parameters.AddWithValue("@edate", edate);
cmd.Parameters.AddWithValue("@term", term);
cmd.Parameters.AddWithValue("@crtime", crtime);
cmd.Parameters.AddWithValue("@termDr", termDr);
cmd.Parameters.AddWithValue("@drTime", drTime);
cmd.Parameters.AddWithValue("@contents", contents ?? "");
cmd.Parameters.AddWithValue("@wuid", info.Login.no);
var result = cmd.ExecuteNonQuery();
return JsonConvert.SerializeObject(new { Success = result > 0, Message = result > 0 ? "수정되었습니다." : "수정에 실패했습니다." });
}
}
}
catch (Exception ex)
{
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
}
}
/// <summary>
/// 근태 삭제
/// </summary>
public string Holyday_Delete(int idx)
{
try
{
// 권한 확인
int curLevel = Math.Max(info.Login.level, DBM.getAuth(DBM.eAuthType.holyday));
if (curLevel < 5)
{
return JsonConvert.SerializeObject(new { Success = false, Message = "권한이 없습니다." });
}
// 외부 연동 데이터 및 마감 체크
var checkSql = "SELECT extcate, extidx, sdate FROM Holyday WHERE idx = @idx AND gcode = @gcode";
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
{
using (var cmd = new SqlCommand(checkSql, cn))
{
cmd.Parameters.AddWithValue("@idx", idx);
cmd.Parameters.AddWithValue("@gcode", info.Login.gcode);
cn.Open();
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
var extcate = reader["extcate"] != DBNull.Value ? reader["extcate"].ToString() : "";
var extidx = reader["extidx"] != DBNull.Value ? Convert.ToInt32(reader["extidx"]) : -1;
var sdate = reader["sdate"] != DBNull.Value ? reader["sdate"].ToString() : "";
if (!string.IsNullOrEmpty(extcate) && extidx > 0)
{
return JsonConvert.SerializeObject(new {
Success = false,
Message = $"이 자료는 외부에서 자동생성된 자료입니다. (소스: {extcate}:{extidx})"
});
}
if (!string.IsNullOrEmpty(sdate) && sdate.Length >= 7)
{
var smon = sdate.Substring(0, 7);
if (DBM.GetMagamStatus(smon))
{
return JsonConvert.SerializeObject(new { Success = false, Message = $"등록일이 속한 월({smon})이 마감되었습니다." });
}
}
}
}
}
var sql = "DELETE FROM Holyday WHERE idx = @idx AND gcode = @gcode";
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddWithValue("@idx", idx);
cmd.Parameters.AddWithValue("@gcode", info.Login.gcode);
var result = cmd.ExecuteNonQuery();
return JsonConvert.SerializeObject(new { Success = result > 0, Message = result > 0 ? "삭제되었습니다." : "삭제에 실패했습니다." });
}
}
}
catch (Exception ex)
{
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
}
}
/// <summary>
/// 근태 사용자 목록 조회 (기간 내 데이터가 있는 사용자)
/// </summary>
public string Holyday_GetUserList(string sd, string ed)
{
try
{
// 권한 확인
int curLevel = Math.Max(info.Login.level, DBM.getAuth(DBM.eAuthType.holyday));
var sql = @"SELECT DISTINCT h.uid, u.name as UserName
FROM Holyday h WITH (nolock)
LEFT JOIN Users u ON h.uid = u.id
WHERE h.gcode = @gcode";
var parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("@gcode", info.Login.gcode));
if (!string.IsNullOrEmpty(sd))
{
sql += " AND h.sdate >= @sd";
parameters.Add(new SqlParameter("@sd", sd));
}
if (!string.IsNullOrEmpty(ed))
{
sql += " AND h.sdate <= @ed";
parameters.Add(new SqlParameter("@ed", ed));
}
sql += " ORDER BY u.name";
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddRange(parameters.ToArray());
using (var da = new SqlDataAdapter(cmd))
{
var dt = new DataTable();
da.Fill(dt);
return JsonConvert.SerializeObject(dt);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Holyday_GetUserList 오류: {ex.Message}");
return "[]";
}
}
/// <summary>
/// 근태 권한 정보 조회
/// </summary>
public string Holyday_GetPermission()
{
try
{
int curLevel = Math.Max(info.Login.level, DBM.getAuth(DBM.eAuthType.holyday));
bool canManage = curLevel >= 5;
return JsonConvert.SerializeObject(new
{
Success = true,
CurrentUserId = info.Login.no,
Level = curLevel,
CanManage = canManage
});
}
catch (Exception ex)
{
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
}
}
/// <summary>
/// 근태 잔량 조회 (연도별)
/// </summary>
public string Holyday_GetBalance(string year, string uid)
{
try
{
// 권한 확인
int curLevel = Math.Max(info.Login.level, DBM.getAuth(DBM.eAuthType.holyday));
// 본인 확인 또는 관리자 권한 확인
if (uid != info.Login.no && curLevel < 5)
{
return JsonConvert.SerializeObject(new { Success = false, Message = "권한이 없습니다." });
}
var sql = @"SELECT
cate,
ISNULL(SUM(termDr), 0) as TotalGenDays,
ISNULL(SUM(DrTime), 0) as TotalGenHours,
ISNULL(SUM(term), 0) as TotalUseDays,
ISNULL(SUM(crtime), 0) as TotalUseHours
FROM Holyday WITH (nolock)
WHERE gcode = @gcode AND uid = @uid AND sdate LIKE @year + '%'
GROUP BY cate";
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddWithValue("@gcode", info.Login.gcode);
cmd.Parameters.AddWithValue("@uid", uid);
cmd.Parameters.AddWithValue("@year", year);
using (var da = new SqlDataAdapter(cmd))
{
var dt = new DataTable();
da.Fill(dt);
return JsonConvert.SerializeObject(new { Success = true, Data = dt });
}
}
}
catch (Exception ex)
{
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
}
}
#endregion
}
}

View File

@@ -99,10 +99,10 @@ namespace Project.Web
{
try
{
// 뷰에서 기본 정보 조회, 원본 테이블에서 jobgrp, tag 추가 조회
// 뷰에서 기본 정보 조회, 원본 테이블에서 jobgrp, tag, otStart, otEnd 추가 조회
var sql = @"SELECT v.idx, v.pidx, v.pdate, v.id, v.name, v.type, v.svalue, v.hrs, v.ot,
v.requestpart, v.package, v.userprocess, v.status, v.projectName, v.description,
v.ww, v.otpms, v.process, j.jobgrp, j.tag
v.ww, v.otpms, v.process, j.jobgrp, j.tag, j.otStart, j.otEnd
FROM vJobReportForUser v WITH (nolock)
INNER JOIN JobReport j WITH (nolock) ON v.idx = j.idx
WHERE v.idx = @idx AND v.gcode = @gcode";
@@ -141,7 +141,8 @@ namespace Project.Web
/// 업무일지 추가 (JobReport 테이블)
/// </summary>
public string Jobreport_Add(string pdate, string projectName, int pidx, string requestpart, string package,
string type, string process, string status, string description, double hrs, double ot, string jobgrp, string tag)
string type, string process, string status, string description, double hrs, double ot, string jobgrp, string tag,
string otStart, string otEnd)
{
try
{
@@ -153,9 +154,9 @@ namespace Project.Web
}
var sql = @"INSERT INTO JobReport (gcode, uid, pdate, projectName, requestpart, package,
type, process, status, description, hrs, ot, jobgrp, tag, wuid, wdate, pidx)
type, process, status, description, hrs, ot, jobgrp, tag, wuid, wdate, pidx, otStart, otEnd)
VALUES (@gcode, @uid, @pdate, @projectName, @requestpart, @package,
@type, @process, @status, @description, @hrs, @ot, @jobgrp, @tag, @wuid, GETDATE(), @pidx);
@type, @process, @status, @description, @hrs, @ot, @jobgrp, @tag, @wuid, GETDATE(), @pidx, @otStart, @otEnd);
SELECT SCOPE_IDENTITY();";
var cs = Properties.Settings.Default.gwcs;
@@ -178,6 +179,20 @@ namespace Project.Web
cmd.Parameters.AddWithValue("@jobgrp", jobgrp ?? "");
cmd.Parameters.AddWithValue("@tag", tag ?? "");
cmd.Parameters.AddWithValue("@wuid", info.Login.no);
// otStart, otEnd 처리 (HH:mm 형식을 datetime으로 변환)
if (!string.IsNullOrEmpty(otStart) && !string.IsNullOrEmpty(otEnd))
{
var otStartDateTime = DateTime.Parse($"{pdate} {otStart}:00");
var otEndDateTime = DateTime.Parse($"{pdate} {otEnd}:00");
cmd.Parameters.AddWithValue("@otStart", otStartDateTime);
cmd.Parameters.AddWithValue("@otEnd", otEndDateTime);
}
else
{
cmd.Parameters.AddWithValue("@otStart", DBNull.Value);
cmd.Parameters.AddWithValue("@otEnd", DBNull.Value);
}
cn.Open();
var newId = Convert.ToInt32(cmd.ExecuteScalar());
@@ -194,7 +209,8 @@ namespace Project.Web
/// 업무일지 수정 (JobReport 테이블)
/// </summary>
public string Jobreport_Edit(int idx, string pdate, string projectName, int pidx, string requestpart, string package,
string type, string process, string status, string description, double hrs, double ot, string jobgrp, string tag)
string type, string process, string status, string description, double hrs, double ot, string jobgrp, string tag,
string otStart, string otEnd)
{
try
{
@@ -231,7 +247,7 @@ namespace Project.Web
pdate = @pdate, projectName = @projectName, pidx = @pidx, requestpart = @requestpart,
package = @package, type = @type, process = @process, status = @status,
description = @description, hrs = @hrs, ot = @ot, jobgrp = @jobgrp, tag = @tag,
wuid = @wuid, wdate = GETDATE()
otStart = @otStart, otEnd = @otEnd, wuid = @wuid, wdate = GETDATE()
WHERE idx = @idx AND gcode = @gcode";
var cs = Properties.Settings.Default.gwcs;
@@ -254,6 +270,20 @@ namespace Project.Web
cmd.Parameters.AddWithValue("@jobgrp", jobgrp ?? "");
cmd.Parameters.AddWithValue("@tag", tag ?? "");
cmd.Parameters.AddWithValue("@wuid", info.Login.no);
// otStart, otEnd 처리 (HH:mm 형식을 datetime으로 변환)
if (!string.IsNullOrEmpty(otStart) && !string.IsNullOrEmpty(otEnd))
{
var otStartDateTime = DateTime.Parse($"{pdate} {otStart}:00");
var otEndDateTime = DateTime.Parse($"{pdate} {otEnd}:00");
cmd.Parameters.AddWithValue("@otStart", otStartDateTime);
cmd.Parameters.AddWithValue("@otEnd", otEndDateTime);
}
else
{
cmd.Parameters.AddWithValue("@otStart", DBNull.Value);
cmd.Parameters.AddWithValue("@otEnd", DBNull.Value);
}
cn.Open();
var result = cmd.ExecuteNonQuery();

View File

@@ -646,7 +646,9 @@ namespace Project.Web
double ot = json.ot ?? 0.0;
string jobgrp = json.jobgrp ?? "";
string tag = json.tag ?? "";
string result = _bridge.Jobreport_Add(pdate, projectName, pidx, requestpart, package, jobType, process, status, description, hrs, ot, jobgrp, tag);
string otStart = json.otStart ?? "00:00";
string otEnd = json.otEnd ?? "00:00";
string result = _bridge.Jobreport_Add(pdate, projectName, pidx, requestpart, package, jobType, process, status, description, hrs, ot, jobgrp, tag, otStart, otEnd);
var response = new { type = "JOBREPORT_ADDED", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
@@ -668,7 +670,9 @@ namespace Project.Web
double ot = json.ot ?? 0.0;
string jobgrp = json.jobgrp ?? "";
string tag = json.tag ?? "";
string result = _bridge.Jobreport_Edit(idx, pdate, projectName, pidx, requestpart, package, jobType, process, status, description, hrs, ot, jobgrp, tag);
string otStart = json.otStart ?? "00:00";
string otEnd = json.otEnd ?? "00:00";
string result = _bridge.Jobreport_Edit(idx, pdate, projectName, pidx, requestpart, package, jobType, process, status, description, hrs, ot, jobgrp, tag, otStart, otEnd);
var response = new { type = "JOBREPORT_EDITED", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
@@ -729,6 +733,99 @@ namespace Project.Web
}
break;
// ===== Holyday (근태) API =====
case "HOLYDAY_GET_LIST":
{
string sd = json.sd ?? "";
string ed = json.ed ?? "";
string uid = json.uid ?? "%";
string result = _bridge.Holyday_GetList(sd, ed, uid);
var response = new { type = "HOLYDAY_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
break;
case "HOLYDAY_GET_DETAIL":
{
int idx = json.idx ?? 0;
string result = _bridge.Holyday_GetDetail(idx);
var response = new { type = "HOLYDAY_DETAIL_DATA", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
break;
case "HOLYDAY_ADD":
{
string cate = json.cate ?? "";
string sdate = json.sdate ?? "";
string edate = json.edate ?? "";
double term = json.term ?? 0.0;
double crtime = json.crtime ?? 0.0;
double termDr = json.termDr ?? 0.0;
double drTime = json.drTime ?? 0.0;
string contents = json.contents ?? "";
string uid = json.uid ?? "";
string result = _bridge.Holyday_Add(cate, sdate, edate, term, crtime, termDr, drTime, contents, uid);
var response = new { type = "HOLYDAY_ADDED", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
break;
case "HOLYDAY_EDIT":
{
int idx = json.idx ?? 0;
string cate = json.cate ?? "";
string sdate = json.sdate ?? "";
string edate = json.edate ?? "";
double term = json.term ?? 0.0;
double crtime = json.crtime ?? 0.0;
double termDr = json.termDr ?? 0.0;
double drTime = json.drTime ?? 0.0;
string contents = json.contents ?? "";
string result = _bridge.Holyday_Edit(idx, cate, sdate, edate, term, crtime, termDr, drTime, contents);
var response = new { type = "HOLYDAY_EDITED", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
break;
case "HOLYDAY_DELETE":
{
int idx = json.idx ?? 0;
string result = _bridge.Holyday_Delete(idx);
var response = new { type = "HOLYDAY_DELETED", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
break;
case "HOLYDAY_GET_USERLIST":
{
string sd = json.sd ?? "";
string ed = json.ed ?? "";
string result = _bridge.Holyday_GetUserList(sd, ed);
var response = new { type = "HOLYDAY_USERLIST_DATA", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
break;
case "HOLYDAY_GET_PERMISSION":
{
string result = _bridge.Holyday_GetPermission();
var response = new { type = "HOLYDAY_PERMISSION_DATA", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
break;
case "HOLYDAY_GET_BALANCE":
{
string year = json.year ?? "";
string uid = json.uid ?? "";
string result = _bridge.Holyday_GetBalance(year, uid);
var response = new { type = "HOLYDAY_BALANCE_DATA", data = JsonConvert.DeserializeObject(result) };
await Send(socket, JsonConvert.SerializeObject(response));
}
break;
// ===== Holiday API (월별근무표) =====
case "HOLIDAY_GET_LIST":
{