- Items: 우측에 이미지, 담당자, 입고/발주내역 패널 추가 (fItems 윈폼 동일) - Project: 목록 및 상세 다이얼로그 구현 - Kuntae: 오류검사/수정 기능 추가 - UserAuth: 사용자 권한 관리 페이지 추가 - UserGroup: 그룹정보 다이얼로그로 전환 - Header: 사용자 메뉴 서브메뉴 방향 수정, 즐겨찾기 기능 - Backend API: Items 상세/담당자/구매내역, 근태 오류검사, 프로젝트 목록 등 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
468 lines
18 KiB
C#
468 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Data.SqlClient;
|
|
using System.Text;
|
|
using Newtonsoft.Json;
|
|
using FCOMMON;
|
|
|
|
namespace Project.Web
|
|
{
|
|
public partial class MachineBridge
|
|
{
|
|
#region Kuntae API
|
|
|
|
#region 오류검사 관련 클래스
|
|
public class KuntaeErrorCheckResult
|
|
{
|
|
public string Date { get; set; }
|
|
public string Gubun { get; set; }
|
|
public string OccurDay { get; set; }
|
|
public string OccurTime { get; set; }
|
|
public string UseDay { get; set; }
|
|
public string UseTime { get; set; }
|
|
public string CateError { get; set; }
|
|
public bool IsError { get; set; }
|
|
public bool IsMagam { get; set; }
|
|
}
|
|
|
|
public class KuntaeErrorCheckProgress
|
|
{
|
|
public string CurrentDate { get; set; }
|
|
public double JobreportOT { get; set; }
|
|
public double HolidayRequestDay { get; set; }
|
|
public double HolidayRequestTime { get; set; }
|
|
public double KuntaeCRDay { get; set; }
|
|
public double KuntaeCRTime { get; set; }
|
|
public double KuntaeDRDay { get; set; }
|
|
public double KuntaeDRTime { get; set; }
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 근태 목록 조회
|
|
/// </summary>
|
|
public string Kuntae_GetList(string sd, string ed)
|
|
{
|
|
try
|
|
{
|
|
var sql = @"SELECT k.*, u.name as userName
|
|
FROM EETGW_Kuntae k WITH (nolock)
|
|
LEFT JOIN Users u ON k.uid = u.id
|
|
WHERE k.gcode = @gcode AND k.uid = @uid";
|
|
|
|
var parameters = new List<SqlParameter>();
|
|
parameters.Add(new SqlParameter("@gcode", info.Login.gcode));
|
|
parameters.Add(new SqlParameter("@uid", info.Login.no));
|
|
|
|
if (!string.IsNullOrEmpty(sd))
|
|
{
|
|
sql += " AND k.kdate >= @sd";
|
|
parameters.Add(new SqlParameter("@sd", sd));
|
|
}
|
|
if (!string.IsNullOrEmpty(ed))
|
|
{
|
|
sql += " AND k.kdate <= @ed";
|
|
parameters.Add(new SqlParameter("@ed", ed));
|
|
}
|
|
|
|
sql += " ORDER BY k.kdate DESC";
|
|
|
|
var cs = Properties.Settings.Default.gwcs;
|
|
var cn = new SqlConnection(cs);
|
|
var cmd = new SqlCommand(sql, cn);
|
|
cmd.Parameters.AddRange(parameters.ToArray());
|
|
|
|
var da = new SqlDataAdapter(cmd);
|
|
var dt = new DataTable();
|
|
da.Fill(dt);
|
|
da.Dispose();
|
|
cmd.Dispose();
|
|
cn.Dispose();
|
|
|
|
return JsonConvert.SerializeObject(new { Success = true, Data = dt }, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 근태 삭제
|
|
/// </summary>
|
|
public string Kuntae_Delete(int id)
|
|
{
|
|
try
|
|
{
|
|
var sql = "DELETE FROM EETGW_Kuntae WHERE idx = @idx AND gcode = @gcode AND uid = @uid";
|
|
|
|
var cs = Properties.Settings.Default.gwcs;
|
|
var cn = new SqlConnection(cs);
|
|
var cmd = new SqlCommand(sql, cn);
|
|
cmd.Parameters.AddWithValue("@idx", id);
|
|
cmd.Parameters.AddWithValue("@gcode", info.Login.gcode);
|
|
cmd.Parameters.AddWithValue("@uid", info.Login.no);
|
|
|
|
cn.Open();
|
|
var result = cmd.ExecuteNonQuery();
|
|
cn.Close();
|
|
cmd.Dispose();
|
|
cn.Dispose();
|
|
|
|
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 Kuntae_ErrorCheck(string sd, string ed)
|
|
{
|
|
try
|
|
{
|
|
var startDate = DateTime.Parse(sd);
|
|
var endDate = DateTime.Parse(ed);
|
|
var gcode = info.Login.gcode;
|
|
var uid = info.Login.no;
|
|
|
|
var okList = new List<KuntaeErrorCheckResult>();
|
|
var ngList = new List<KuntaeErrorCheckResult>();
|
|
|
|
var cs = Properties.Settings.Default.gwcs;
|
|
using (var cn = new SqlConnection(cs))
|
|
{
|
|
cn.Open();
|
|
using (var cmd = new SqlCommand("", cn))
|
|
{
|
|
cmd.Parameters.Add("@gcode", SqlDbType.VarChar).Value = gcode;
|
|
cmd.Parameters.Add("@uid", SqlDbType.VarChar).Value = uid;
|
|
|
|
var idx = 0;
|
|
while (true)
|
|
{
|
|
var currentDate = startDate.AddDays(idx++);
|
|
if (currentDate > endDate) break;
|
|
|
|
var pdate = currentDate.ToString("yyyy-MM-dd");
|
|
var result = CheckDateError(cmd, pdate, gcode);
|
|
|
|
if (result.IsError)
|
|
ngList.Add(result);
|
|
else
|
|
okList.Add(result);
|
|
}
|
|
}
|
|
}
|
|
|
|
return JsonConvert.SerializeObject(new {
|
|
Success = true,
|
|
OkList = okList,
|
|
NgList = ngList
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 날짜의 오류 검사
|
|
/// </summary>
|
|
private KuntaeErrorCheckResult CheckDateError(SqlCommand cmd, string pdate, string gcode)
|
|
{
|
|
var result = new KuntaeErrorCheckResult
|
|
{
|
|
Date = pdate,
|
|
Gubun = "입력/생성",
|
|
IsError = false,
|
|
IsMagam = false
|
|
};
|
|
|
|
// 1. 업무일지 OT2 합계 (발생시간)
|
|
cmd.CommandText = $"SELECT SUM(ISNULL(ot2,0)) FROM jobreport WHERE gcode = @gcode AND pdate='{pdate}' AND ISNULL(ot,0) > 0 AND ISNULL(ot2,0) > 0";
|
|
var jobreportOT = 0.0;
|
|
var objJobreport = cmd.ExecuteScalar();
|
|
if (objJobreport != null && objJobreport != DBNull.Value)
|
|
jobreportOT = Convert.ToDouble(objJobreport);
|
|
|
|
// 2. 휴가신청 확인 (승인된 것만)
|
|
cmd.CommandText = $"SELECT cate, SUM(HolyDays), SUM(HolyTimes) FROM EETGW_HolydayRequest WHERE gcode = @gcode AND sdate = '{pdate}' AND ISNULL(conf,0) = 1 GROUP BY cate";
|
|
var holidayDay = 0.0;
|
|
var holidayTime = 0.0;
|
|
var cateListD = new Dictionary<string, double>();
|
|
var cateListT = new Dictionary<string, double>();
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
while (reader.Read())
|
|
{
|
|
var cate = reader[0].ToString();
|
|
var vDay = reader[1] != DBNull.Value ? Convert.ToDouble(reader[1]) : 0.0;
|
|
var vTime = reader[2] != DBNull.Value ? Convert.ToDouble(reader[2]) : 0.0;
|
|
|
|
holidayDay += vDay;
|
|
holidayTime += vTime;
|
|
|
|
if (vDay != 0.0)
|
|
{
|
|
if (cateListD.ContainsKey(cate))
|
|
cateListD[cate] += vDay;
|
|
else
|
|
cateListD.Add(cate, vDay);
|
|
}
|
|
|
|
if (vTime != 0.0)
|
|
{
|
|
if (cateListT.ContainsKey(cate))
|
|
cateListT[cate] += vTime;
|
|
else
|
|
cateListT.Add(cate, vTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. 근태입력자료 확인
|
|
cmd.CommandText = $@"SELECT cate, SUM(term), SUM(crtime), SUM(termdr), SUM(drtime), SUM(drtimepms)
|
|
FROM Holyday
|
|
WHERE gcode = @gcode AND sdate = '{pdate}' AND ISNULL(extidx,-1) <> -1
|
|
GROUP BY cate";
|
|
|
|
var kuntaeCRDay = 0.0;
|
|
var kuntaeCRTime = 0.0;
|
|
var kuntaeDRDay = 0.0;
|
|
var kuntaeDRTime = 0.0;
|
|
var dCRD = new Dictionary<string, double>();
|
|
var dCRT = new Dictionary<string, double>();
|
|
var dDRD = new Dictionary<string, double>();
|
|
var dDRT = new Dictionary<string, double>();
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
while (reader.Read())
|
|
{
|
|
var cate = reader[0].ToString();
|
|
var vCRD = reader[1] != DBNull.Value ? Convert.ToDouble(reader[1]) : 0.0;
|
|
var vCRT = reader[2] != DBNull.Value ? Convert.ToDouble(reader[2]) : 0.0;
|
|
var vDRD = reader[3] != DBNull.Value ? Convert.ToDouble(reader[3]) : 0.0;
|
|
var vDRT = reader[4] != DBNull.Value ? Convert.ToDouble(reader[4]) : 0.0;
|
|
|
|
if (vCRD != 0.0)
|
|
{
|
|
if (dCRD.ContainsKey(cate)) dCRD[cate] += vCRD;
|
|
else dCRD.Add(cate, vCRD);
|
|
}
|
|
if (vCRT != 0.0)
|
|
{
|
|
if (dCRT.ContainsKey(cate)) dCRT[cate] += vCRT;
|
|
else dCRT.Add(cate, vCRT);
|
|
}
|
|
if (vDRD != 0.0)
|
|
{
|
|
if (dDRD.ContainsKey(cate)) dDRD[cate] += vDRD;
|
|
else dDRD.Add(cate, vDRD);
|
|
}
|
|
if (vDRT != 0.0)
|
|
{
|
|
if (dDRT.ContainsKey(cate)) dDRT[cate] += vDRT;
|
|
else dDRT.Add(cate, vDRT);
|
|
}
|
|
|
|
kuntaeCRDay += vCRD;
|
|
kuntaeCRTime += vCRT;
|
|
kuntaeDRDay += vDRD;
|
|
kuntaeDRTime += vDRT;
|
|
}
|
|
}
|
|
|
|
// 4. 카테고리별 데이터 확인
|
|
var sbCate = new StringBuilder();
|
|
var cateErr = false;
|
|
|
|
// 휴가신청(일) vs 근태입력(CR일)
|
|
foreach (var item in cateListD)
|
|
{
|
|
if (!dCRD.ContainsKey(item.Key))
|
|
{
|
|
sbCate.Append($"{item.Key}(X)");
|
|
cateErr = true;
|
|
break;
|
|
}
|
|
else if (dCRD[item.Key] != item.Value)
|
|
{
|
|
sbCate.Append($"{item.Key}({dCRD[item.Key]}|{item.Value})");
|
|
cateErr = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!cateErr)
|
|
{
|
|
foreach (var item in cateListT)
|
|
{
|
|
if (!dCRT.ContainsKey(item.Key))
|
|
{
|
|
sbCate.Append($"{item.Key}(X)");
|
|
cateErr = true;
|
|
break;
|
|
}
|
|
else if (dCRT[item.Key] != item.Value)
|
|
{
|
|
sbCate.Append($"{item.Key}({dCRT[item.Key]}|{item.Value})");
|
|
cateErr = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!cateErr)
|
|
{
|
|
foreach (var item in dCRD)
|
|
{
|
|
if (item.Key.Equals("대체")) continue;
|
|
if (!cateListD.ContainsKey(item.Key))
|
|
{
|
|
sbCate.Append($"{item.Key}(X)");
|
|
cateErr = true;
|
|
break;
|
|
}
|
|
else if (cateListD[item.Key] != item.Value)
|
|
{
|
|
sbCate.Append($"{item.Key}({cateListD[item.Key]}|{item.Value})");
|
|
cateErr = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!cateErr)
|
|
{
|
|
foreach (var item in dCRT)
|
|
{
|
|
if (item.Key.Equals("대체")) continue;
|
|
if (!cateListT.ContainsKey(item.Key))
|
|
{
|
|
sbCate.Append($"{item.Key}(X)");
|
|
cateErr = true;
|
|
break;
|
|
}
|
|
else if (cateListT[item.Key] != item.Value)
|
|
{
|
|
sbCate.Append($"{item.Key}({cateListT[item.Key]}|{item.Value})");
|
|
cateErr = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 5. 결과 생성
|
|
result.OccurDay = $"--/{kuntaeDRDay}";
|
|
result.OccurTime = $"{jobreportOT}/{kuntaeDRTime}";
|
|
result.UseDay = $"{holidayDay}/{kuntaeCRDay}";
|
|
result.UseTime = $"{holidayTime}/{kuntaeCRTime}";
|
|
result.CateError = sbCate.ToString();
|
|
|
|
// 오류 여부 판단
|
|
if (jobreportOT != kuntaeDRTime) result.IsError = true;
|
|
if (holidayDay != kuntaeCRDay) result.IsError = true;
|
|
if (holidayTime != kuntaeCRTime) result.IsError = true;
|
|
if (cateErr) result.IsError = true;
|
|
|
|
// 마감 여부 확인
|
|
if (result.IsError)
|
|
{
|
|
result.IsMagam = DBM.GetMagamStatus(pdate.Substring(0, 7));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 근태 오류 수정 (재생성)
|
|
/// </summary>
|
|
public string Kuntae_FixError(string pdate)
|
|
{
|
|
try
|
|
{
|
|
var gcode = info.Login.gcode;
|
|
var uid = info.Login.no;
|
|
|
|
var cs = Properties.Settings.Default.gwcs;
|
|
using (var cn = new SqlConnection(cs))
|
|
{
|
|
cn.Open();
|
|
using (var cmd = new SqlCommand("", cn))
|
|
{
|
|
cmd.Parameters.Add("@gcode", SqlDbType.VarChar).Value = gcode;
|
|
cmd.Parameters.Add("@uid", SqlDbType.VarChar).Value = uid;
|
|
cmd.Parameters.Add("@pdate", SqlDbType.VarChar).Value = pdate;
|
|
|
|
// 1. 근태-업무일지자료 삭제
|
|
cmd.CommandText = "DELETE FROM Holyday WHERE gcode = @gcode AND extcate = 'HO' AND sdate = @pdate AND ISNULL(extidx,-1) <> -1";
|
|
var cnt1 = cmd.ExecuteNonQuery();
|
|
|
|
// 2. 근태-업무일지자료 생성
|
|
cmd.CommandText = @"INSERT INTO Holyday(gcode, cate, sdate, edate, term, crtime, termdr, DrTime, contents, [uid], wdate, wuid, extcate, extidx)
|
|
SELECT gcode, '대체', pdate, pdate, 0, 0, 0, ISNULL(ot2,0), projectname, uid, GETDATE(), @uid + '-ERR', 'HO', idx
|
|
FROM jobreport
|
|
WHERE gcode = @gcode AND pdate = @pdate AND ISNULL(ot2,0) > 0 AND ISNULL(ot,0) > 0";
|
|
var cnt2 = cmd.ExecuteNonQuery();
|
|
|
|
// 3. 근태-휴가신청자료 삭제
|
|
cmd.CommandText = "DELETE FROM Holyday WHERE gcode = @gcode AND extcate = '휴가' AND sdate = @pdate AND ISNULL(extidx,-1) <> -1";
|
|
var cnt3 = cmd.ExecuteNonQuery();
|
|
|
|
// 4. 근태-휴가신청자료 생성 (승인완료된 자료 대상)
|
|
cmd.CommandText = @"INSERT INTO Holyday(gcode, cate, sdate, edate, term, crtime, termdr, DrTime, contents, [uid], wdate, wuid, extcate, extidx)
|
|
SELECT gcode, cate, sdate, edate, ISNULL(holydays,0), ISNULL(holytimes,0), 0, 0, HolyReason, uid, GETDATE(), @uid + '-ERR', '휴가', idx
|
|
FROM EETGW_HolydayRequest
|
|
WHERE gcode = @gcode AND sdate = @pdate AND ISNULL(conf,0) = 1";
|
|
var cnt4 = cmd.ExecuteNonQuery();
|
|
|
|
return JsonConvert.SerializeObject(new {
|
|
Success = true,
|
|
Message = $"{pdate} 재생성 완료 (삭제: {cnt1 + cnt3}건, 생성: {cnt2 + cnt4}건)"
|
|
});
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 여러 날짜 오류 일괄 수정
|
|
/// </summary>
|
|
public string Kuntae_FixErrors(string dates)
|
|
{
|
|
try
|
|
{
|
|
var dateList = JsonConvert.DeserializeObject<List<string>>(dates);
|
|
var results = new List<object>();
|
|
|
|
foreach (var date in dateList)
|
|
{
|
|
var resultJson = Kuntae_FixError(date);
|
|
var resultObj = JsonConvert.DeserializeObject<dynamic>(resultJson);
|
|
results.Add(new { Date = date, Success = (bool)resultObj.Success, Message = (string)resultObj.Message });
|
|
}
|
|
|
|
return JsonConvert.SerializeObject(new { Success = true, Results = results });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|