- Todo 상태 관리 시스템 추가 (대기, 진행, 보류, 완료, 취소) - 완료일(okdate) 자동 설정 기능 구현 - 대시보드 할일 목록에서 만료일 지난 항목 적색 배경 강조 - 휴가신청 목록에서 항목별 색상 구분 (대체=노란색, 년차=녹색, 하기=파란색) - 휴가신청 목록 데이터 매핑 수정 (holydays, holytimes, HolyReason) - Todo 정렬 순서 개선 (상태별 우선순위 적용) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
440 lines
15 KiB
C#
440 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Web.Http;
|
|
using Newtonsoft.Json;
|
|
using FCOMMON;
|
|
using Project.Web.Model;
|
|
|
|
namespace Project.Web.Controllers
|
|
{
|
|
public class TodoController : BaseController
|
|
{
|
|
[HttpGet]
|
|
public HttpResponseMessage Index()
|
|
{
|
|
var filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", "wwwroot", "Todo", "index.html");
|
|
var contents = string.Empty;
|
|
|
|
if (System.IO.File.Exists(filePath))
|
|
{
|
|
contents = System.IO.File.ReadAllText(filePath, System.Text.Encoding.UTF8);
|
|
}
|
|
else
|
|
{
|
|
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 GetTodos()
|
|
{
|
|
try
|
|
{
|
|
var currentUser = GetCurrentUser();
|
|
if (currentUser == null)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "로그인되지 않은 상태입니다."
|
|
});
|
|
}
|
|
|
|
string gcode = FCOMMON.info.Login.gcode;
|
|
string uid = FCOMMON.info.Login.no;
|
|
|
|
var sql = @"SELECT * FROM EETGW_Todo WHERE gcode = @gcode AND uid = @uid
|
|
ORDER BY
|
|
CASE
|
|
WHEN ISNULL(status,'0') = '1' THEN 1 -- 진행
|
|
WHEN ISNULL(status,'0') = '0' THEN 2 -- 대기
|
|
WHEN ISNULL(status,'0') = '3' THEN 3 -- 보류
|
|
WHEN ISNULL(status,'0') = '5' THEN 4 -- 완료
|
|
WHEN ISNULL(status,'0') = '2' THEN 5 -- 취소
|
|
ELSE 6
|
|
END, flag DESC,
|
|
ISNULL(seqno, 0) DESC,
|
|
expire ASC";
|
|
var todos = DBM.Query<TodoModel>(sql, new { gcode = gcode, uid = uid });
|
|
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = true,
|
|
Data = todos
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "Todo 목록을 가져오는 중 오류가 발생했습니다: " + ex.Message
|
|
});
|
|
}
|
|
}
|
|
|
|
[HttpGet]
|
|
public HttpResponseMessage GetUrgentTodos()
|
|
{
|
|
try
|
|
{
|
|
var currentUser = GetCurrentUser();
|
|
if (currentUser == null)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "로그인되지 않은 상태입니다."
|
|
});
|
|
}
|
|
|
|
string gcode = FCOMMON.info.Login.gcode;
|
|
string uid = FCOMMON.info.Login.no;
|
|
|
|
var sql = @"
|
|
SELECT * FROM EETGW_Todo
|
|
WHERE gcode = @gcode AND uid = @uid
|
|
and isnull(status,'0') not in ('2','3','5')
|
|
ORDER BY flag DESC, seqno DESC, expire ASC, wdate ASC";
|
|
|
|
var todos = DBM.Query<TodoModel>(sql, new { gcode = gcode, uid = uid });
|
|
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = true,
|
|
Data = todos
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "급한 Todo 목록을 가져오는 중 오류가 발생했습니다: " + ex.Message
|
|
});
|
|
}
|
|
}
|
|
|
|
[HttpPost]
|
|
public HttpResponseMessage CreateTodo([FromBody] TodoModel todo)
|
|
{
|
|
try
|
|
{
|
|
var currentUser = GetCurrentUser();
|
|
if (currentUser == null)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "로그인되지 않은 상태입니다."
|
|
});
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(todo.remark))
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "할일 내용은 필수입니다."
|
|
});
|
|
}
|
|
|
|
todo.gcode = FCOMMON.info.Login.gcode;
|
|
todo.uid = FCOMMON.info.Login.no;
|
|
todo.wuid = FCOMMON.info.Login.no;
|
|
todo.wdate = DateTime.Now;
|
|
|
|
if (todo.seqno == null) todo.seqno = 0;
|
|
if (todo.flag == null) todo.flag = false;
|
|
if (todo.status == '\0') todo.status = '0';
|
|
|
|
// 새로 생성할 때 완료 상태면 완료일 설정
|
|
DateTime? okdateValue = null;
|
|
if (todo.status == '5')
|
|
{
|
|
okdateValue = DateTime.Now;
|
|
}
|
|
|
|
var sql = @"
|
|
INSERT INTO EETGW_Todo (gcode, uid, title, remark, flag, expire, seqno, request, status, okdate, wuid, wdate)
|
|
VALUES (@gcode, @uid, @title, @remark, @flag, @expire, @seqno, @request, @status, @okdate, @wuid, @wdate);
|
|
SELECT SCOPE_IDENTITY();";
|
|
|
|
var newId = DBM.QuerySingle<int>(sql, new
|
|
{
|
|
gcode = todo.gcode,
|
|
uid = todo.uid,
|
|
title = todo.title,
|
|
remark = todo.remark,
|
|
flag = todo.flag,
|
|
expire = todo.expire,
|
|
seqno = todo.seqno,
|
|
request = todo.request,
|
|
status = todo.status,
|
|
okdate = okdateValue,
|
|
wuid = todo.wuid,
|
|
wdate = todo.wdate
|
|
});
|
|
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = true,
|
|
Message = "할일이 추가되었습니다.",
|
|
Data = new { idx = newId }
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "할일 추가 중 오류가 발생했습니다: " + ex.Message
|
|
});
|
|
}
|
|
}
|
|
|
|
[HttpPut]
|
|
public HttpResponseMessage UpdateTodo([FromBody] TodoModel todo)
|
|
{
|
|
try
|
|
{
|
|
var currentUser = GetCurrentUser();
|
|
if (currentUser == null)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "로그인되지 않은 상태입니다."
|
|
});
|
|
}
|
|
|
|
if (todo.idx <= 0)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "유효하지 않은 Todo ID입니다."
|
|
});
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(todo.remark))
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "할일 내용은 필수입니다."
|
|
});
|
|
}
|
|
|
|
string gcode = FCOMMON.info.Login.gcode;
|
|
string uid = FCOMMON.info.Login.no;
|
|
|
|
// 상태가 완료('5')로 변경되고 아직 완료일이 설정되지 않은 경우 완료일 설정
|
|
DateTime? okdateValue = null;
|
|
if (todo.status == '5')
|
|
{
|
|
// 기존 완료일이 있는지 확인
|
|
var existingTodo = DBM.QuerySingleOrDefault<TodoModel>(
|
|
"SELECT okdate FROM EETGW_Todo WHERE idx = @idx AND gcode = @gcode AND uid = @uid",
|
|
new { idx = todo.idx, gcode = gcode, uid = uid });
|
|
|
|
if (existingTodo?.okdate == null)
|
|
{
|
|
okdateValue = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
var sql = @"
|
|
UPDATE EETGW_Todo
|
|
SET title = @title, remark = @remark, flag = @flag, expire = @expire, seqno = @seqno, request = @request, status = @status, okdate = @okdate
|
|
WHERE idx = @idx AND gcode = @gcode AND uid = @uid";
|
|
|
|
var affectedRows = DBM.Execute(sql, new
|
|
{
|
|
title = todo.title,
|
|
remark = todo.remark,
|
|
flag = todo.flag ?? false,
|
|
expire = todo.expire,
|
|
seqno = todo.seqno ?? 0,
|
|
request = todo.request,
|
|
status = todo.status == '\0' ? '0' : todo.status,
|
|
okdate = okdateValue,
|
|
idx = todo.idx,
|
|
gcode = gcode,
|
|
uid = uid
|
|
});
|
|
|
|
if (affectedRows == 0)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "수정할 할일을 찾을 수 없습니다."
|
|
});
|
|
}
|
|
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = true,
|
|
Message = "할일이 수정되었습니다."
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "할일 수정 중 오류가 발생했습니다: " + ex.Message
|
|
});
|
|
}
|
|
}
|
|
|
|
[HttpDelete]
|
|
public HttpResponseMessage DeleteTodo(int id)
|
|
{
|
|
try
|
|
{
|
|
var currentUser = GetCurrentUser();
|
|
if (currentUser == null)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "로그인되지 않은 상태입니다."
|
|
});
|
|
}
|
|
|
|
if (id <= 0)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "유효하지 않은 Todo ID입니다."
|
|
});
|
|
}
|
|
|
|
string gcode = FCOMMON.info.Login.gcode;
|
|
string uid = FCOMMON.info.Login.no;
|
|
|
|
var sql = "DELETE FROM EETGW_Todo WHERE idx = @idx AND gcode = @gcode AND uid = @uid";
|
|
var affectedRows = DBM.Execute(sql, new { idx = id, gcode = gcode, uid = uid });
|
|
|
|
if (affectedRows == 0)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "삭제할 할일을 찾을 수 없습니다."
|
|
});
|
|
}
|
|
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = true,
|
|
Message = "할일이 삭제되었습니다."
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "할일 삭제 중 오류가 발생했습니다: " + ex.Message
|
|
});
|
|
}
|
|
}
|
|
|
|
[HttpGet]
|
|
public HttpResponseMessage GetTodo(int id)
|
|
{
|
|
try
|
|
{
|
|
var currentUser = GetCurrentUser();
|
|
if (currentUser == null)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "로그인되지 않은 상태입니다."
|
|
});
|
|
}
|
|
|
|
if (id <= 0)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "유효하지 않은 Todo ID입니다."
|
|
});
|
|
}
|
|
|
|
string gcode = FCOMMON.info.Login.gcode;
|
|
string uid = FCOMMON.info.Login.no;
|
|
|
|
var sql = "SELECT * FROM EETGW_Todo WHERE idx = @idx AND gcode = @gcode AND uid = @uid";
|
|
var todo = DBM.QuerySingleOrDefault<TodoModel>(sql, new { idx = id, gcode = gcode, uid = uid });
|
|
|
|
if (todo == null)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "할일을 찾을 수 없습니다."
|
|
});
|
|
}
|
|
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = true,
|
|
Data = todo
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return CreateJsonResponse(new
|
|
{
|
|
Success = false,
|
|
Message = "할일 조회 중 오류가 발생했습니다: " + ex.Message
|
|
});
|
|
}
|
|
}
|
|
|
|
private object GetCurrentUser()
|
|
{
|
|
if (string.IsNullOrEmpty(FCOMMON.info.Login.no)) return null;
|
|
else return FCOMMON.info.Login;
|
|
}
|
|
|
|
private HttpResponseMessage CreateJsonResponse(object data)
|
|
{
|
|
var json = JsonConvert.SerializeObject(data, new JsonSerializerSettings
|
|
{
|
|
NullValueHandling = NullValueHandling.Ignore,
|
|
DateFormatString = "yyyy-MM-dd HH:mm:ss"
|
|
});
|
|
|
|
return new HttpResponseMessage()
|
|
{
|
|
Content = new StringContent(
|
|
json,
|
|
System.Text.Encoding.UTF8,
|
|
"application/json")
|
|
};
|
|
}
|
|
}
|
|
}
|