feat: React 프론트엔드 기능 대폭 확장

- 월별근무표: 휴일/근무일 관리, 자동 초기화
- 메일양식: 템플릿 CRUD, To/CC/BCC 설정
- 그룹정보: 부서 관리, 비트 연산 기반 권한 설정
- 업무일지: 수정 성공 메시지 제거, 오늘 근무시간 필터링 수정
- 웹소켓 메시지 type 충돌 버그 수정

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
backuppc
2025-11-27 17:25:31 +09:00
parent b57af6dad7
commit c9b5d756e1
65 changed files with 14028 additions and 467 deletions

View File

@@ -0,0 +1,177 @@
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 Holiday API ()
/// <summary>
/// 월별근무표 목록 조회
/// </summary>
public string Holiday_GetList(string month)
{
try
{
var monthPattern = month + "%";
var sql = @"SELECT idx, pdate, free, memo, wuid, wdate
FROM HolidayList WITH (nolock)
WHERE pdate LIKE @month
ORDER BY pdate";
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.AddWithValue("@month", monthPattern);
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 Holiday_Save(string month, string holidaysJson)
{
try
{
var holidays = JsonConvert.DeserializeObject<List<HolidayItem>>(holidaysJson);
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
{
cn.Open();
using (var tran = cn.BeginTransaction())
{
try
{
foreach (var item in holidays)
{
var sql = @"
IF EXISTS (SELECT 1 FROM HolidayList WHERE pdate = @pdate)
UPDATE HolidayList SET free = @free, memo = @memo, wuid = @wuid, wdate = GETDATE() WHERE pdate = @pdate
ELSE
INSERT INTO HolidayList (pdate, free, memo, wuid, wdate) VALUES (@pdate, @free, @memo, @wuid, GETDATE())";
using (var cmd = new SqlCommand(sql, cn, tran))
{
cmd.Parameters.AddWithValue("@pdate", item.pdate);
cmd.Parameters.AddWithValue("@free", item.free);
cmd.Parameters.AddWithValue("@memo", item.memo ?? "");
cmd.Parameters.AddWithValue("@wuid", info.Login.no);
cmd.ExecuteNonQuery();
}
}
tran.Commit();
return JsonConvert.SerializeObject(new { Success = true, Message = "저장되었습니다." });
}
catch
{
tran.Rollback();
throw;
}
}
}
}
catch (Exception ex)
{
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
}
}
/// <summary>
/// 월별근무표 초기 데이터 생성 (해당 월에 데이터가 없을 때)
/// </summary>
public string Holiday_Initialize(string month)
{
try
{
// 해당 월 데이터 존재 여부 확인
var monthPattern = month + "%";
var checkSql = "SELECT COUNT(*) FROM HolidayList WITH (nolock) WHERE pdate LIKE @month";
var cs = Properties.Settings.Default.gwcs;
using (var cn = new SqlConnection(cs))
{
cn.Open();
using (var checkCmd = new SqlCommand(checkSql, cn))
{
checkCmd.Parameters.AddWithValue("@month", monthPattern);
var count = (int)checkCmd.ExecuteScalar();
if (count > 0)
{
return JsonConvert.SerializeObject(new { Success = true, Message = "이미 데이터가 존재합니다.", Created = false });
}
}
// 해당 월의 모든 날짜 생성
var startDate = DateTime.Parse(month + "-01");
var endDate = startDate.AddMonths(1).AddDays(-1);
using (var tran = cn.BeginTransaction())
{
try
{
for (var date = startDate; date <= endDate; date = date.AddDays(1))
{
var isFree = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
var memo = date.DayOfWeek == DayOfWeek.Saturday ? "토요일" :
date.DayOfWeek == DayOfWeek.Sunday ? "일요일" : "";
var sql = @"INSERT INTO HolidayList (pdate, free, memo, wuid, wdate)
VALUES (@pdate, @free, @memo, @wuid, GETDATE())";
using (var cmd = new SqlCommand(sql, cn, tran))
{
cmd.Parameters.AddWithValue("@pdate", date.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("@free", isFree);
cmd.Parameters.AddWithValue("@memo", memo);
cmd.Parameters.AddWithValue("@wuid", info.Login.no);
cmd.ExecuteNonQuery();
}
}
tran.Commit();
return JsonConvert.SerializeObject(new { Success = true, Message = "초기 데이터가 생성되었습니다.", Created = true });
}
catch
{
tran.Rollback();
throw;
}
}
}
}
catch (Exception ex)
{
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
}
}
#endregion
}
public class HolidayItem
{
public int idx { get; set; }
public string pdate { get; set; }
public bool free { get; set; }
public string memo { get; set; }
}
}