Files
Groupware/Project/Web/Controller/JobreportController.cs

825 lines
37 KiB
C#

using Microsoft.Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web;
using System.Web.Http;
namespace Project.Web.Controllers
{
public class JobreportController : BaseController
{
// PUT api/values/5
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete]
public HttpResponseMessage Delete(int id)
{
try
{
if (id <= 0)
{
throw new Exception("유효하지 않은 업무일지 ID입니다.");
}
// 직접 SQL 삭제 실행
string connectionString = Properties.Settings.Default.gwcs;
using (var connection = new System.Data.SqlClient.SqlConnection(connectionString))
{
connection.Open();
string deleteSql = @"
DELETE FROM JobReport
WHERE idx = @idx AND gcode = @gcode";
using (var command = new System.Data.SqlClient.SqlCommand(deleteSql, connection))
{
command.Parameters.AddWithValue("@idx", id);
command.Parameters.AddWithValue("@gcode", FCOMMON.info.Login.gcode);
int rowsAffected = command.ExecuteNonQuery();
if (rowsAffected == 0)
{
throw new Exception("업무일지를 찾을 수 없거나 삭제 권한이 없습니다.");
}
}
}
var jsonData = "{\"success\":true,\"message\":\"데이터가 성공적으로 삭제되었습니다.\"}";
var resp = new HttpResponseMessage()
{
Content = new StringContent(
jsonData,
System.Text.Encoding.UTF8,
"application/json")
};
return resp;
}
catch (Exception ex)
{
var errorResp = new HttpResponseMessage()
{
Content = new StringContent(
$"{{\"success\":false,\"message\":\"{EscapeJsonString(ex.Message)}\"}}",
System.Text.Encoding.UTF8,
"application/json")
};
return errorResp;
}
}
[HttpPost]
public string Add(FormCollection formData)
{
try
{
// 폼 데이터에서 값 추출
var pdate = formData["pdate"] ?? DateTime.Now.ToShortDateString();
var status = formData["status"] ?? "";
var projectName = formData["projectName"] ?? "";
var requestpart = formData["requestpart"] ?? "";
var type = formData["type"] ?? "";
var description = formData["description"] ?? "";
var otStart = formData["otStart"] ?? "";
var otEnd = formData["otEnd"] ?? "";
decimal hrs = 0;
decimal.TryParse(formData["hrs"], out hrs);
decimal ot = 0;
decimal.TryParse(formData["ot"], out ot);
// 직접 SQL 삽입 실행
string connectionString = Properties.Settings.Default.gwcs;
using (var connection = new System.Data.SqlClient.SqlConnection(connectionString))
{
connection.Open();
string insertSql = @"
INSERT INTO JobReport
(gcode, pdate, projectName, uid, requestpart, status, type, description, hrs, ot, otStart, otEnd, wuid, wdate)
VALUES
(@gcode, @pdate, @projectName, @uid, @requestpart, @status, @type, @description, @hrs, @ot, @otStart, @otEnd, @wuid, @wdate)";
using (var command = new System.Data.SqlClient.SqlCommand(insertSql, connection))
{
command.Parameters.AddWithValue("@gcode", FCOMMON.info.Login.gcode);
command.Parameters.AddWithValue("@pdate", pdate);
command.Parameters.AddWithValue("@projectName", projectName);
command.Parameters.AddWithValue("@uid", FCOMMON.info.Login.no);
command.Parameters.AddWithValue("@requestpart", requestpart);
command.Parameters.AddWithValue("@status", status);
command.Parameters.AddWithValue("@type", type);
command.Parameters.AddWithValue("@description", description);
command.Parameters.AddWithValue("@hrs", hrs);
command.Parameters.AddWithValue("@ot", ot);
command.Parameters.AddWithValue("@otStart", string.IsNullOrEmpty(otStart) ? (object)DBNull.Value : otStart);
command.Parameters.AddWithValue("@otEnd", string.IsNullOrEmpty(otEnd) ? (object)DBNull.Value : otEnd);
command.Parameters.AddWithValue("@wuid", FCOMMON.info.Login.no);
command.Parameters.AddWithValue("@wdate", DateTime.Now);
command.ExecuteNonQuery();
}
}
return "{\"success\":true,\"message\":\"데이터가 성공적으로 저장되었습니다.\"}";
}
catch (Exception ex)
{
return $"{{\"success\":false,\"message\":\"{EscapeJsonString(ex.Message)}\"}}";
}
}
[HttpPost]
public HttpResponseMessage Edit()
{
try
{
// Request.Form에서 직접 값 추출
var idx = HttpContext.Current.Request.Form["idx"];
var pdate = HttpContext.Current.Request.Form["pdate"] ?? DateTime.Now.ToShortDateString();
var status = HttpContext.Current.Request.Form["status"] ?? "";
var projectName = HttpContext.Current.Request.Form["projectName"] ?? "";
var requestpart = HttpContext.Current.Request.Form["requestpart"] ?? "";
var type = HttpContext.Current.Request.Form["type"] ?? "";
var description = HttpContext.Current.Request.Form["description"] ?? "";
var otStart = HttpContext.Current.Request.Form["otStart"] ?? "";
var otEnd = HttpContext.Current.Request.Form["otEnd"] ?? "";
decimal hrs = 0;
decimal.TryParse(HttpContext.Current.Request.Form["hrs"], out hrs);
decimal ot = 0;
decimal.TryParse(HttpContext.Current.Request.Form["ot"], out ot);
int idxNum = 0;
int.TryParse(idx, out idxNum);
if (idxNum <= 0)
{
throw new Exception("유효하지 않은 업무일지 ID입니다.");
}
// 직접 SQL 업데이트 실행
string connectionString = Properties.Settings.Default.gwcs;
using (var connection = new System.Data.SqlClient.SqlConnection(connectionString))
{
connection.Open();
string updateSql = @"
UPDATE JobReport
SET pdate = @pdate,
status = @status,
projectName = @projectName,
requestpart = @requestpart,
type = @type,
description = @description,
hrs = @hrs,
ot = @ot,
otStart = @otStart,
otEnd = @otEnd,
wuid = @wuid,
wdate = @wdate
WHERE idx = @idx AND gcode = @gcode";
using (var command = new System.Data.SqlClient.SqlCommand(updateSql, connection))
{
command.Parameters.AddWithValue("@idx", idxNum);
command.Parameters.AddWithValue("@gcode", FCOMMON.info.Login.gcode);
command.Parameters.AddWithValue("@pdate", pdate);
command.Parameters.AddWithValue("@status", status);
command.Parameters.AddWithValue("@projectName", projectName);
command.Parameters.AddWithValue("@requestpart", requestpart);
command.Parameters.AddWithValue("@type", type);
command.Parameters.AddWithValue("@description", description);
command.Parameters.AddWithValue("@hrs", hrs);
command.Parameters.AddWithValue("@ot", ot);
command.Parameters.AddWithValue("@otStart", string.IsNullOrEmpty(otStart) ? (object)DBNull.Value : otStart);
command.Parameters.AddWithValue("@otEnd", string.IsNullOrEmpty(otEnd) ? (object)DBNull.Value : otEnd);
command.Parameters.AddWithValue("@wuid", FCOMMON.info.Login.no);
command.Parameters.AddWithValue("@wdate", DateTime.Now);
int rowsAffected = command.ExecuteNonQuery();
if (rowsAffected == 0)
{
throw new Exception("업무일지를 찾을 수 없거나 수정 권한이 없습니다.");
}
}
}
var jsonData = "{\"success\":true,\"message\":\"데이터가 성공적으로 수정되었습니다.\"}";
var resp = new HttpResponseMessage()
{
Content = new StringContent(
jsonData,
System.Text.Encoding.UTF8,
"application/json")
};
return resp;
}
catch (Exception ex)
{
var errorResp = new HttpResponseMessage()
{
Content = new StringContent(
$"{{\"success\":false,\"message\":\"{EscapeJsonString(ex.Message)}\"}}",
System.Text.Encoding.UTF8,
"application/json")
};
return errorResp;
}
}
[HttpGet]
public HttpResponseMessage Edit(int id)
{
//로그인이 되어있지않다면 로그인을 가져온다
MethodResult result;
result = View("/jobreport/edit");
var gets = Request.GetQueryNameValuePairs();// GetParameters(data);
var key_search = gets.Where(t => t.Key == "search").FirstOrDefault();
var model = GetGlobalModel();
var getParams = Request.GetQueryNameValuePairs();// GetParameters(data);
//기본값을 찾아서 없애줘야한다
var searchkey = string.Empty;
if (key_search.Key != null && key_search.Value.isEmpty() == false) searchkey = key_search.Value.Trim();
var tbody = new System.Text.StringBuilder();
//테이블데이터생성
var db = new dsMSSQLTableAdapters.vJobReportForUserTableAdapter();//. EEEntitiesJobreport();
var sd = DateTime.Now.ToString("yyyy-MM-01");
var ed = DateTime.Now.ToShortDateString();
var rows = db.GetData(FCOMMON.info.Login.gcode, id).FirstOrDefault();//.vJobReportForUser.AsNoTracking().Where(t => t.gcode == FCOMMON.info.Login.gcode && t.idx == id).FirstOrDefault();
var contents = result.Content;
if (rows == null)
{
//아이템이 없는 메시지를 표시한다
}
else
{
//치환작업을 진행한다
contents = contents.Replace("{pdate}", rows.pdate);
contents = contents.Replace("{status}", rows.status);
contents = contents.Replace("{name}", rows.name);
contents = contents.Replace("{package}", rows.package);
contents = contents.Replace("{process}", rows.process);
contents = contents.Replace("{type}", rows.type);
contents = contents.Replace("{userProcess}", rows.userProcess);
contents = contents.Replace("{projectName}", rows.projectName);
contents = contents.Replace("{hrs}", rows.hrs.ToString());
contents = contents.Replace("{ot}", rows.ot.ToString());
contents = contents.Replace("{requestpart}", rows.requestpart);
contents = contents.Replace("{description}", rows.description);
}
//공용값 적용
ApplyCommonValue(ref contents);
//최종문자 적용
result.Content = contents;
var resp = new HttpResponseMessage()
{
Content = new StringContent(
result.Content,
System.Text.Encoding.UTF8,
"text/html")
};
return resp;
}
[HttpGet]
public HttpResponseMessage Add()
{
//로그인이 되어있지않다면 로그인을 가져온다
MethodResult result;
result = View("/jobreport/add");
var gets = Request.GetQueryNameValuePairs();// GetParameters(data);
var key_search = gets.Where(t => t.Key == "search").FirstOrDefault();
var model = GetGlobalModel();
var getParams = Request.GetQueryNameValuePairs();// GetParameters(data);
//기본값을 찾아서 없애줘야한다
var searchkey = string.Empty;
if (key_search.Key != null && key_search.Value.isEmpty() == false) searchkey = key_search.Value.Trim();
var tbody = new System.Text.StringBuilder();
//테이블데이터생성
var itemcnt = 0;
//if (searchkey.isEmpty() == false)
{
var db = new dsMSSQLTableAdapters.vJobReportForUserTableAdapter();// EEEntitiesJobreport();
var sd = DateTime.Now.ToString("yyyy-MM-01");
var ed = DateTime.Now.ToShortDateString();
var rows = db.GetByDate(FCOMMON.info.Login.gcode, FCOMMON.info.Login.no, sd, ed);
//vJobReportForUser.AsNoTracking().Where(t => t.gcode == FCOMMON.info.Login.gcode && t.id == FCOMMON.info.Login.no && t.pdate.CompareTo(sd) >= 0 && t.pdate.CompareTo(ed) <= 1).OrderByDescending(t => t.pdate);
itemcnt = rows.Count();
foreach (var item in rows)
{
tbody.AppendLine("<tr>");
tbody.AppendLine($"<th scope='row'>{item.pdate.Substring(5)}</th>");
tbody.AppendLine($"<td>{item.ww}</td>");
tbody.AppendLine($"<td>{item.name}</td>");
if (item.status == "진행 중" || item.status.EndsWith("%"))
tbody.AppendLine($"<td class='table-info text-center'>{item.status}</td>");
else
tbody.AppendLine($"<td class='text-center'>{item.status}</td>");
tbody.AppendLine($"<td>{item.type}</td>");
tbody.AppendLine($"<td>{item.projectName}</td>");
tbody.AppendLine($"<td>{item.hrs}</td>");
tbody.AppendLine($"<td>{item.ot}</td>");
tbody.AppendLine("<td><span class='d-inline-block text-truncate' style='max-width: 150px;'>");
tbody.AppendLine(item.description);
tbody.AppendLine("</span></td>");
tbody.AppendLine("</tr>");
}
}
//아잍쳄이 없는경우
if (itemcnt == 0)
{
tbody.AppendLine("<tr>");
tbody.AppendLine("<th scope='row'>1</th>");
tbody.AppendLine("<td colspan='6'>자료가 없습니다</td>");
tbody.AppendLine("</tr>");
}
var contents = result.Content.Replace("{search}", searchkey);
contents = contents.Replace("{tabledata}", tbody.ToString());
contents = contents.Replace("{cnt}", itemcnt.ToString());
//공용값 적용
ApplyCommonValue(ref contents);
//최종문자 적용
result.Content = contents;
var resp = new HttpResponseMessage()
{
Content = new StringContent(
result.Content,
System.Text.Encoding.UTF8,
"text/html")
};
return resp;
}
[HttpGet]
public HttpResponseMessage Find()
{
//로그인이 되어있지않다면 로그인을 가져온다
MethodResult result;
result = View();
var gets = Request.GetQueryNameValuePairs();// GetParameters(data);
var key_search = gets.Where(t => t.Key == "search").FirstOrDefault();
var model = GetGlobalModel();
var getParams = Request.GetQueryNameValuePairs();// GetParameters(data);
//기본값을 찾아서 없애줘야한다
var searchkey = string.Empty;
if (key_search.Key != null && key_search.Value.isEmpty() == false) searchkey = key_search.Value.Trim();
var tbody = new System.Text.StringBuilder();
//테이블데이터생성
var itemcnt = 0;
if (searchkey.isEmpty() == false)
{
var db = new dsMSSQLTableAdapters.vJobReportForUserTableAdapter();// EEEntitiesJobreport();
var sd = DateTime.Now.ToShortDateString();
var rows = db.GetByToday(FCOMMON.info.Login.gcode, sd);//.vJobReportForUser.Where(t => t.gcode == FCOMMON.info.Login.gcode && t.pdate.CompareTo(sd) == 0).OrderBy(t => t.name);
itemcnt = rows.Count();
foreach (var item in rows)
{
tbody.AppendLine("<tr>");
tbody.AppendLine($"<th scope='row'>{item.pdate}</th>");
tbody.AppendLine($"<td>{item.status}</td>");
tbody.AppendLine($"<td>{item.name}</td>");
tbody.AppendLine($"<td>{item.projectName}</td>");
tbody.AppendLine($"<td>{item.hrs}</td>");
tbody.AppendLine($"<td>{item.ot}</td>");
tbody.AppendLine($"<td>{item.description}</td>");
if (item.description.Length > 10)
tbody.AppendLine($"<td>{item.description.Substring(0, 10)}...</td>");
else
tbody.AppendLine($"<td>{item.description}</td>");
tbody.AppendLine("</tr>");
}
}
//아잍쳄이 없는경우
if (itemcnt == 0)
{
tbody.AppendLine("<tr>");
tbody.AppendLine("<th scope='row'>1</th>");
tbody.AppendLine("<td colspan='6'>자료가 없습니다</td>");
tbody.AppendLine("</tr>");
}
var contents = result.Content.Replace("{search}", searchkey);
contents = contents.Replace("{tabledata}", tbody.ToString());
contents = contents.Replace("{cnt}", itemcnt.ToString());
//공용값 적용
ApplyCommonValue(ref contents);
//최종문자 적용
result.Content = contents;
var resp = new HttpResponseMessage()
{
Content = new StringContent(
result.Content,
System.Text.Encoding.UTF8,
"text/html")
};
return resp;
}
[HttpGet]
public HttpResponseMessage Index()
{
// 직접 파일을 읽어서 반환
var filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", "wwwroot", "Jobreport", "index.html");
var contents = string.Empty;
if (System.IO.File.Exists(filePath))
{
contents = System.IO.File.ReadAllText(filePath, System.Text.Encoding.UTF8);
}
else
{
// 파일이 없으면 404 에러 페이지 또는 기본 메시지
contents = "<html><body><h1>404 - File Not Found</h1><p>The requested file was not found: " + filePath + "</p></body></html>";
}
//공용값 적용
ApplyCommonValue(ref contents);
var resp = new HttpResponseMessage()
{
Content = new StringContent(
contents,
System.Text.Encoding.UTF8,
"text/html")
};
return resp;
}
[HttpGet]
public HttpResponseMessage GetJobDetail(int id)
{
try
{
// 특정 업무일지의 전체 정보 조회
string connectionString = Properties.Settings.Default.gwcs;
using (var connection = new System.Data.SqlClient.SqlConnection(connectionString))
{
connection.Open();
string selectSql = @"
SELECT idx, pdate, gcode, uid as id, '' as name, '' as process, type, '' as svalue,
hrs, ot, requestpart, '' as package, '' as userProcess, status, projectName,
description, '' as ww, otStart, otEnd, ot as ot2, '' as otReason,
'' as grade, '' as indate, '' as outdate, pidx
FROM JobReport WITH (NOLOCK)
WHERE gcode = @gcode AND uid = @uid AND idx = @idx";
using (var command = new System.Data.SqlClient.SqlCommand(selectSql, connection))
{
command.Parameters.AddWithValue("@gcode", FCOMMON.info.Login.gcode);
command.Parameters.AddWithValue("@uid", FCOMMON.info.Login.no);
command.Parameters.AddWithValue("@idx", id);
using (var reader = command.ExecuteReader())
{
if (reader.Read())
{
var item = new
{
idx = reader["idx"],
pdate = reader["pdate"],
gcode = reader["gcode"],
id = reader["id"],
name = reader["name"],
process = reader["process"],
type = reader["type"],
svalue = reader["svalue"],
hrs = reader["hrs"],
ot = reader["ot"],
requestpart = reader["requestpart"],
package = reader["package"],
userProcess = reader["userProcess"],
status = reader["status"],
projectName = reader["projectName"],
description = reader["description"], // 전체 내용
ww = reader["ww"],
otStart = reader["otStart"],
otEnd = reader["otEnd"],
ot2 = reader["ot2"],
otReason = reader["otReason"],
grade = reader["grade"],
indate = reader["indate"],
outdate = reader["outdate"],
pidx = reader["pidx"]
};
// JSON 형태로 변환
decimal hrs = 0;
decimal ot = 0;
int idx = 0;
int pidx = 0;
try { hrs = Convert.ToDecimal(item.hrs); } catch { hrs = 0; }
try { ot = Convert.ToDecimal(item.ot); } catch { ot = 0; }
try { idx = Convert.ToInt32(item.idx); } catch { idx = 0; }
try { pidx = Convert.ToInt32(item.pidx); } catch { pidx = 0; }
var desc = EscapeJsonString(item.description?.ToString() ?? ""); // 전체 내용
var pdate = EscapeJsonString(item.pdate?.ToString() ?? "");
var status = EscapeJsonString(item.status?.ToString() ?? "");
var type = EscapeJsonString(item.type?.ToString() ?? "");
var projectName = EscapeJsonString(item.projectName?.ToString() ?? "");
var requestpart = EscapeJsonString(item.requestpart?.ToString() ?? "");
var otStart = EscapeJsonString(item.otStart?.ToString() ?? "");
var otEnd = EscapeJsonString(item.otEnd?.ToString() ?? "");
var jsonData = "{";
jsonData += $"\"pdate\":\"{pdate}\",";
jsonData += $"\"status\":\"{status}\",";
jsonData += $"\"type\":\"{type}\",";
jsonData += $"\"projectName\":\"{projectName}\",";
jsonData += $"\"requestpart\":\"{requestpart}\",";
jsonData += $"\"hrs\":{hrs},";
jsonData += $"\"ot\":{ot},";
jsonData += $"\"description\":\"{desc}\",";
jsonData += $"\"otStart\":\"{otStart}\",";
jsonData += $"\"otEnd\":\"{otEnd}\",";
jsonData += $"\"idx\":{idx},";
jsonData += $"\"pidx\":{pidx}";
jsonData += "}";
var resp = new HttpResponseMessage()
{
Content = new StringContent(
jsonData,
System.Text.Encoding.UTF8,
"application/json")
};
return resp;
}
}
}
}
// 데이터를 찾을 수 없는 경우
var errorResp = new HttpResponseMessage()
{
Content = new StringContent(
"{\"error\":\"데이터를 찾을 수 없습니다.\"}",
System.Text.Encoding.UTF8,
"application/json")
};
return errorResp;
}
catch (Exception ex)
{
var errorResp = new HttpResponseMessage()
{
Content = new StringContent(
$"{{\"error\":\"{ex.Message}\"}}",
System.Text.Encoding.UTF8,
"application/json")
};
return errorResp;
}
}
[HttpGet]
public HttpResponseMessage GetJobData()
{
try
{
var gets = Request.GetQueryNameValuePairs();
var startDateParam = gets.Where(t => t.Key == "startDate").FirstOrDefault();
var endDateParam = gets.Where(t => t.Key == "endDate").FirstOrDefault();
var startDate = startDateParam.Key != null ? startDateParam.Value : null;
var endDate = endDateParam.Key != null ? endDateParam.Value : null;
// 날짜 파라미터 처리
string sd, ed;
if (!string.IsNullOrEmpty(startDate) && !string.IsNullOrEmpty(endDate))
{
sd = startDate;
ed = endDate;
}
else
{
// 기본값: 오늘부터 -2주
var now = DateTime.Now;
var twoWeeksAgo = now.AddDays(-14);
sd = twoWeeksAgo.ToShortDateString();
ed = now.ToShortDateString();
}
// 직접 SQL로 데이터 조회
string connectionString = Properties.Settings.Default.gwcs;
var jobReports = new List<dynamic>();
using (var connection = new System.Data.SqlClient.SqlConnection(connectionString))
{
connection.Open();
string selectSql = @"
SELECT idx, pdate, gcode, uid as id, '' as name, '' as process, type, '' as svalue,
hrs, ot, requestpart, '' as package, '' as userProcess, status, projectName,
description, '' as ww, otStart, otEnd, ot as ot2, '' as otReason,
'' as grade, '' as indate, '' as outdate, pidx
FROM JobReport WITH (NOLOCK)
WHERE gcode = @gcode AND uid = @uid AND pdate BETWEEN @startDate AND @endDate
ORDER BY pdate DESC";
using (var command = new System.Data.SqlClient.SqlCommand(selectSql, connection))
{
command.Parameters.AddWithValue("@gcode", FCOMMON.info.Login.gcode);
command.Parameters.AddWithValue("@uid", FCOMMON.info.Login.no);
command.Parameters.AddWithValue("@startDate", sd);
command.Parameters.AddWithValue("@endDate", ed);
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
jobReports.Add(new
{
idx = reader["idx"],
pdate = reader["pdate"],
gcode = reader["gcode"],
id = reader["id"],
name = reader["name"],
process = reader["process"],
type = reader["type"],
svalue = reader["svalue"],
hrs = reader["hrs"],
ot = reader["ot"],
requestpart = reader["requestpart"],
package = reader["package"],
userProcess = reader["userProcess"],
status = reader["status"],
projectName = reader["projectName"],
description = reader["description"],
ww = reader["ww"],
otStart = reader["otStart"],
otEnd = reader["otEnd"],
ot2 = reader["ot2"],
otReason = reader["otReason"],
grade = reader["grade"],
indate = reader["indate"],
outdate = reader["outdate"],
pidx = reader["pidx"]
});
}
}
}
}
// JSON 형태로 변환
var jsonData = "[";
bool first = true;
if (jobReports != null)
{
foreach (var item in jobReports)
{
if (!first) jsonData += ",";
first = false;
// DBNull 처리를 위한 안전한 변환
decimal hrs = 0;
decimal ot = 0;
int idx = 0;
int pidx = 0;
try { hrs = Convert.ToDecimal(item.hrs); } catch { hrs = 0; }
try { ot = Convert.ToDecimal(item.ot); } catch { ot = 0; }
try { idx = Convert.ToInt32(item.idx); } catch { idx = 0; }
try { pidx = Convert.ToInt32(item.pidx); } catch { pidx = 0; }
// 안전한 JSON 문자열 이스케이프 처리 및 25자 제한
var fullDesc = item.description?.ToString() ?? "";
var desc = EscapeJsonString(fullDesc.Length > 25 ? fullDesc.Substring(0, 25) + "..." : fullDesc);
var pdate = EscapeJsonString(item.pdate?.ToString() ?? "");
var ww = EscapeJsonString(item.ww?.ToString() ?? "");
var name = EscapeJsonString(item.name?.ToString() ?? "");
var status = EscapeJsonString(item.status?.ToString() ?? "");
var type = EscapeJsonString(item.type?.ToString() ?? "");
var projectName = EscapeJsonString(item.projectName?.ToString() ?? "");
var requestpart = EscapeJsonString(item.requestpart?.ToString() ?? "");
var userProcess = EscapeJsonString(item.userProcess?.ToString() ?? "");
jsonData += "{";
jsonData += $"\"pdate\":\"{pdate}\",";
jsonData += $"\"ww\":\"{ww}\",";
jsonData += $"\"name\":\"{name}\",";
jsonData += $"\"status\":\"{status}\",";
jsonData += $"\"type\":\"{type}\",";
jsonData += $"\"projectName\":\"{projectName}\",";
jsonData += $"\"requestpart\":\"{requestpart}\",";
jsonData += $"\"userProcess\":\"{userProcess}\",";
jsonData += $"\"hrs\":{hrs},";
jsonData += $"\"ot\":{ot},";
jsonData += $"\"description\":\"{desc}\",";
jsonData += $"\"idx\":{idx},";
jsonData += $"\"pidx\":{pidx}";
jsonData += "}";
}
}
jsonData += "]";
var resp = new HttpResponseMessage()
{
Content = new StringContent(
jsonData,
System.Text.Encoding.UTF8,
"application/json")
};
return resp;
}
catch (Exception ex)
{
var errorResp = new HttpResponseMessage()
{
Content = new StringContent(
$"{{\"error\":\"{ex.Message}\"}}",
System.Text.Encoding.UTF8,
"application/json")
};
return errorResp;
}
}
private string EscapeJsonString(string input)
{
if (string.IsNullOrEmpty(input))
return "";
// 제어 문자 제거 (0x00-0x1F 범위)
var cleanInput = System.Text.RegularExpressions.Regex.Replace(input, @"[\x00-\x08\x0B\x0C\x0E-\x1F]", "");
return cleanInput
.Replace("\\", "\\\\") // 백슬래시
.Replace("\"", "\\\"") // 따옴표
.Replace("\n", "\\n") // 개행
.Replace("\r", "\\r") // 캐리지 리턴
.Replace("\t", "\\t"); // 탭
}
}
}