diff --git a/BO/BO.csproj b/BO/BO.csproj index 7f8bf25..bda18af 100644 --- a/BO/BO.csproj +++ b/BO/BO.csproj @@ -717,6 +717,7 @@ + diff --git a/BO/Controllers/userController.cs b/BO/Controllers/userController.cs index fa15969..b194de1 100644 --- a/BO/Controllers/userController.cs +++ b/BO/Controllers/userController.cs @@ -1,6 +1,8 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using System.Web; using System.Web.Mvc; @@ -10,9 +12,56 @@ namespace NP.BO.Controllers { public class userController : BOBaseController { - public ActionResult users(NP.Model.VMUser vm){vm.viewname = "user";return us(vm);} - public ActionResult professors(NP.Model.VMUser vm){vm.viewname = "professor";return us(vm);} - public ActionResult admins(NP.Model.VMUser vm){vm.viewname = "admin";return us(vm);} + /// + /// 사용자설정 > 수강생 + /// + /// + /// + public ActionResult users(NP.Model.VMUser vm) + { + vm.viewname = "user";return us(vm); + } + + /// + /// 사용자설정 > 교강사 + /// + /// + /// + public ActionResult professors(NP.Model.VMUser vm) + { + vm.viewname = "professor"; return us(vm); + } + + /// + /// 사용자설정 > 운영자 + /// + /// + /// + public ActionResult admins(NP.Model.VMUser vm) + { + vm.viewname = "admin";return us(vm); + } + + /// + /// 사용자설정 > 회원탈퇴 + /// + /// 회원탈퇴히스토리 ViewModel + /// + public ActionResult LeaveHistory(VMUsersLeave vm) + { + #region + Get : users.leavelist (탈퇴히스토리 리스트) + var p = SetHash(vm); + base.SetHash(vm); + p.Add("LeaveStatus", vm.LeaveStatus); + + vm.UserLeaves = Dao.Get("users.leavelist", p) ?? new List(); + vm.pagetotalcount = GetCount(vm.UserLeaves.FirstOrDefault()); + #endregion + + return View(vm); + } + + public ActionResult us(VMUser vm) { LogSet(new ActLog() {logtype = 10, logtarget = vm.viewname == "user" ? 11 : vm.viewname == "professor" ? 12 : 13, logdata = vm.viewname == "user" ? "사용자목록" : vm.viewname == "professor" ? "교강사목록" : "운영자목록", uno = SUserInfo.UserNo, uip = GetUserIP() }); @@ -43,25 +92,32 @@ namespace NP.BO.Controllers } ht[vm.stringval4] = vm.stringval5; } + vm.Users = Dao.Get("users.users", ht); ViewBag.IsSiteAdmin = SUserInfo.IsSiteAdmin; vm.pagetotalcount = GetCount(vm.Users.FirstOrDefault()); + return View("us",vm); } + public ActionResult userreg(NP.Model.VMUser vm) { return ur(vm); } public ActionResult professorreg(NP.Model.VMUser vm) { return ur(vm); } public ActionResult adminreg(NP.Model.VMUser vm) { return ur(vm); } public ActionResult ur(VMUser vm) { - vm.User = new Users() { status = 1, /*jointype=0,*/ usertype = vm.viewname == "user" ? 1 : vm.viewname == "professor" ? 11 : 0 }; + + vm.User = new Users() { status = 1, usertype = vm.viewname == "user" ? 1 : vm.viewname == "professor" ? 11 : 0 }; vm.Lects = new List() { }; vm.FileList = new List() { }; vm.CMPRs = new List() { }; vm.Councels = new List() { }; vm.ComCodes2 = GetComCodes("bldgcat"); + + if (vm.intval > 0) - { + { vm.User = Dao.Get("users.users", new System.Collections.Hashtable() { { "userno", vm.intval } , { "includesysadmin", 1 } }).First(); + vm.Councel = new Councel() { }; vm.Councels = Dao.Get("users.councels", new System.Collections.Hashtable() { { "userno", vm.intval } }); LogSet(new ActLog() { logtype = 20, logtarget = 21, logdata = vm.User.username + "("+vm.User.userid+")", userno = vm.User.userno, uno = SUserInfo.UserNo, uip = GetUserIP() }); diff --git a/BO/Views/Home/Index.cshtml b/BO/Views/Home/Index.cshtml index 0f3268b..eb70c5a 100644 --- a/BO/Views/Home/Index.cshtml +++ b/BO/Views/Home/Index.cshtml @@ -9,6 +9,7 @@ 미열람쪽지 홈페이지Q&A미답변 강의Q&A미답변 + 회원탈퇴요청 환불요청 @*교재미배송*@ 계산서미확인 @@ -19,6 +20,7 @@ @Model.Data.intval.ToString("#,0") 건 @Model.Data.intval2.ToString("#,0") 건 @Model.Data.intval3.ToString("#,0") 건 + @Model.Data.intval7.ToString("#,0") 건 @Model.Data.intval4.ToString("#,0") 건 @*@Model.Data.intval5.ToString("#,0") 건*@ @Model.Data.intval6.ToString("#,0") 건 @@ -128,7 +130,7 @@ @* /* 잔여업무 요약 클릭 시 링크 - * @param {string} tabNo - 탭 번호 (1: 미열람쪽지, 2: 홈페이지Q&A미답변, 3: 강의Q&A미답변, 4: 환불요청, 5: 계산서미확인) + * @param {string} tabNo - 탭 번호 (1: 미열람쪽지, 2: 홈페이지Q&A미답변, 3: 강의Q&A미답변, 4: 환불요청, 5: 계산서미확인), 6: 회원탈퇴요청 * */ *@ function taskSummaryPendingLink(tabNo) { @@ -156,6 +158,11 @@ p.stringval12 = '0'; postSubmit('/croom/tax', p); break; + case 6: + var p = {}; + p.LeaveStatus = 0; + postSubmit('/user/LeaveHistory', p); + break; default: break; } } diff --git a/BO/Views/user/LeaveHistory.cshtml b/BO/Views/user/LeaveHistory.cshtml new file mode 100644 index 0000000..0f93841 --- /dev/null +++ b/BO/Views/user/LeaveHistory.cshtml @@ -0,0 +1,191 @@ +@model NP.Model.VMUsersLeave +
+
+ @Html.Partial("./Partial/SearchCaption") +
+
+
+ @Html.Partial("./Partial/Select", null, new ViewDataDictionary { { "name", "LeaveStatus" }, { "selected", Model.LeaveStatus }, { "valuetext", ":-선택;0:신청;1:완료;2:취소" } }) + @Html.Partial("./Partial/Select", null, new ViewDataDictionary { { "name", "searchtype" }, { "selected", Model.searchtype }, { "valuetext", "username:이름;userid:ID" } }) + @Html.Partial("./Partial/Text", Model.stringval5, Helpers.DicText(new NP.Model.TextDic() { Name = "searchtext", Value = Model.searchtext, PH = "검색어를 입력하세요.", CssClass = "esitem" })) +
+ +
+ +
+
+
+
+
+ @Html.Partial("./Partial/pagerow", new ViewDataDictionary { { "tbodyid", "tbody1" }, { "searchmethod", "submit()" }, { "pagesize", Model.pagerowcount } }) + 완료처리 + 취소처리 +
+
+
+
+ + + + + + + + + + + + + + + + + @if (Model.UserLeaves.Any()) + { + foreach (var item in Model.UserLeaves) + { + + + + + + + } + } + +
선택아이디요청일처리상태
+ @if (item.status == 0 && item.userstatus == 98) + { // 탈퇴신청이면서 회원상태는 탈퇴신청일때만 체크박스 + + } + else if (item.status == 0 && item.userstatus != 98) + { // 위 if절이 명확하지 않으면 readonly 처리 (조작된 데이터로 예상) + + } + + + @if (item.status != 1 && item.userstatus != 99) + { + + @item.userid @string.Format("({0})", item.username) + + } + else + { + @item.userid + } + @item.levdate.ToString("yy-MM-dd HH:mm") + @if (item.status != 1 && item.userstatus == 99) + { + @this.LeaveStatusToText(item.status) (관리자탈퇴) + } + else + { + @this.LeaveStatusToText(item.status) + } + +
+
+ @Html.Pager((int)Model.pagenum, 10, Model.pagerowcount, Model.pagetotalcount) +
+
+
+
+
+ @Html.Partial("./Partial/dform", Model, new ViewDataDictionary { { "preform", 1 } }) +
+@section scripts{ + +} +@functions{ + + /// + /// 탈퇴 신청 히스토리의 상태코드 값을 텍스트로 반환 + /// + /// + /// + public string LeaveStatusToText(byte status) + { + string result = string.Empty; + + switch (status) + { + case 0: result = "신청"; break; + case 1: result = "완료"; break; + case 2: result = "취소"; break; + default: break; + } + + return result; + } + +} \ No newline at end of file diff --git a/BO/Views/user/ur.cshtml b/BO/Views/user/ur.cshtml index 60eea1d..8c1245b 100644 --- a/BO/Views/user/ur.cshtml +++ b/BO/Views/user/ur.cshtml @@ -228,10 +228,15 @@ { 휴면해제 } + else if(Model.viewname == "leavehistory") + { + 탈퇴신청내역 + } else { 저장 } + @if (Model.User.userno > 0 && Model.viewname == "user") { 탈퇴 @@ -240,7 +245,11 @@ { 삭제 } - 목록 + + @if (Model.viewname != "leavehistory") + { + 목록 + } @Html.HiddenFor(m => m.intval) @Html.HiddenFor(m => m.User.userno) @@ -639,9 +648,13 @@ function del() { if (confirm(('@Model.viewname' == "user"?"탈퇴":"삭제")+"처리하시겠습니까?")) { - capp("/acommon/userexitjoin", { userno: @Model.User.userno}, "cbdel"); + capp( + "/acommon/UsersDel", + { usernos: @Model.User.userno}, + "cbdel"); } } + function cbdel() { if (capResult.code == 1000) { msg("처리되었습니다.", 0, null, null, true); @@ -784,5 +797,10 @@ $("#taxform").submit(); }, 500); } + + function goLeaveHistory() { + window.location.href = '/user/LeaveHistory'; + } + } diff --git a/BO/Web.config b/BO/Web.config index a24954d..db13d98 100644 --- a/BO/Web.config +++ b/BO/Web.config @@ -23,7 +23,7 @@ - + @@ -33,7 +33,7 @@ - + diff --git a/Base/Controller/ACommonUser.cs b/Base/Controller/ACommonUser.cs index 947c207..2714f72 100644 --- a/Base/Controller/ACommonUser.cs +++ b/Base/Controller/ACommonUser.cs @@ -8,6 +8,7 @@ using NP.Model; using System.Collections; using NP.Base.Auth; using NP.Base.ENUM; +using IBatisNet.Common.Transaction; namespace NP.Base.Controllers { public partial class ACommonController : NP.Base.BaseController @@ -99,12 +100,35 @@ namespace NP.Base.Controllers { return JsonOK(Dao.Save("users.exitjoin", new Hashtable() { { "userno", userno }, { "uno", SUserInfo.UserNo }, { "uip", GetUserIP() } })); } - public JsonResult UsersDel(String usernos) - { - Dao.Save("users.dormant.delete", new Hashtable() { { "usernos", usernos }}); - return JsonOK(Dao.Save("users.exitjoin", new Hashtable() { { "usernos", usernos }, { "uno", SUserInfo.UserNo }, { "uip", GetUserIP() } })); + /// + /// 탈퇴 + /// + /// 회원번호들 ("1,2,3,4...") + /// + public JsonResult UsersDel(string usernos) + { + int resultCode = 0; + var p = new Hashtable(); + + #region + Save: users.dormant.delete (휴면회원 삭제) + p.Clear(); + p.Add("usernos", usernos); + Dao.Save("users.dormant.delete", p); + #endregion + + #region + Save: users.leave (회원 탈퇴 및 개인정보 삭제) + p.Clear(); + p.Add("usernos", usernos); + p.Add("uno", SUserInfo.UserNo); + p.Add("uip", GetUserIP()); + resultCode = Dao.Save("users.leave", p); + #endregion + + return JsonOK(resultCode); } + + public JsonResult UsersDormant(String usernos) { return JsonOK(Dao.Save("users.dormant", new Hashtable() { { "usernos", usernos }, { "uno", SUserInfo.UserNo }, { "uip", GetUserIP() } })); @@ -339,6 +363,94 @@ namespace NP.Base.Controllers } + /// + /// 회원 탈퇴 + /// + /// , 로 구분자 생성된 회원번호들 + /// 탈퇴신청상태 (1:완료, 2:취소) + /// + [HttpPost] + public JsonResult UserLeaves(string usernos, int leaveStatus) + { + var p = new Hashtable(); + + try + { + int resultCode = 0; + + using (var t = new TransactionScope()) + { + if (leaveStatus == 1) + { + #region + Save: users.dormant.delete (휴면회원정보 완전삭제, 데이터가 없을 수있다.) + p.Clear(); + p.Add("usernos", usernos); + + resultCode = Dao.Save("users.dormant.delete", p); + #endregion + + #region + Save: users.leave (탈퇴완료 처리 (완전히 회원정보 삭제)) + p.Clear(); + p.Add("usernos", usernos); + p.Add("uno", SUserInfo.UserNo); + p.Add("uip", GetUserIP()); + + resultCode = Dao.Save("users.leave", p); + #endregion + + #region + Save: users.leave.update (탈퇴히스토라 상태 업데이트(1)) + if (resultCode > 0) + { + p.Clear(); + p.Add("status", leaveStatus); + p.Add("usernos", usernos); + p.Add("uno", SUserInfo.UserNo); + p.Add("uip", GetUserIP()); + resultCode = Dao.Save("users.leave.update", p); + } + #endregion + } + else if (leaveStatus == 2) + { + #region + Save: users.status.update (탈퇴취소: users테이블 status 업데이트) + p.Clear(); + p.Add("usernos", usernos); + p.Add("status", 1); // 탈퇴취소로 정상으로 되돌림 + p.Add("uno", SUserInfo.UserNo); + p.Add("uip", GetUserIP()); + resultCode = Dao.Save("users.status.update", p); + #endregion + + #region + Save: users.leave.update (탈퇴히스토라 상태 업데이트(2)) + if (resultCode > 0) + { + p.Clear(); + p.Add("status", leaveStatus); + p.Add("usernos", usernos); + p.Add("uno", SUserInfo.UserNo); + p.Add("uip", GetUserIP()); + + resultCode = Dao.Save("users.leave.update", p); + } + #endregion + } + + // 쿼리 2건 실행에 대한 최종 커밋 + if (resultCode > 0) + { + t.Complete(); + } + } + + return JsonOK(resultCode); + } + catch (Exception ex) + { + SetError($"회원 탈퇴처리 실패: {ex.Message}"); + return JsonBack(new JsonRtn() { code = 1 }); + } + } + } diff --git a/Base/Controller/BasePartialController.cs b/Base/Controller/BasePartialController.cs index 5b4d8f5..e684692 100644 --- a/Base/Controller/BasePartialController.cs +++ b/Base/Controller/BasePartialController.cs @@ -316,23 +316,41 @@ namespace NP.Base return Convert.ToInt64(b); } + /// + /// 현재 HTTP 요청이 POST 메서드를 사용하는지 여부 + /// + /// public bool IsPost() { - return Request.HttpMethod.ToUpper().Equals("POST"); + return Request?.HttpMethod?.Equals("POST", StringComparison.OrdinalIgnoreCase) ?? false; } - public System.Collections.Hashtable SetHash(NP.Model.VMBase vm, bool appendSearch = true) + /// + /// 매개변수 VMBase를 받아 페이지 번호화 페이지 출력수를 설정한 Hashtable을 반환. + /// + /// + /// + public Hashtable SetHash(VMBase vm, bool appendSearch = true) { vm.pagenum = vm.pagenum ?? 1; vm.pagerowcount = vm.pagerowcount < 1 ? (vm.isexceldown == 1 ? 100000 : PageRowCount) : vm.pagerowcount; - var rht = new System.Collections.Hashtable() { { "pagenum", vm.pagenum.Value }, { "pagerowsize", vm.pagerowcount } }; + + var rht = new Hashtable() + { + { "pagenum", vm.pagenum.Value }, + { "pagerowsize", vm.pagerowcount }, + { "pageoffset", (vm.pagenum.Value - 1) * vm.pagerowcount } + }; + if (appendSearch) { rht.Add("searchtype", vm.searchtype); rht.Add("searchtext", vm.searchtext); } + return rht; } + public List InitM() { return new List() { }; @@ -1956,7 +1974,7 @@ namespace NP.Base // p.Add("subdomain", sd); //} var u = Dao.Get("users.userlogin", p).FirstOrDefault(); - if (u != null) + if (u != null && u.status != 98 && u.status != 99) { /* diff --git a/Base/Controller/FCommonMy.cs b/Base/Controller/FCommonMy.cs index 4c8b8aa..c2fbf07 100644 --- a/Base/Controller/FCommonMy.cs +++ b/Base/Controller/FCommonMy.cs @@ -1,16 +1,18 @@ -using System; +using IBatisNet.Common.Transaction; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using NP.Base.Auth; +using NP.Base.ENUM; +using NP.Base.Popbill; +using NP.Model; +using QRCoder; +using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; - -using NP.Model; -using System.Collections; -using NP.Base.Auth; -using NP.Base.ENUM; -using QRCoder; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json; +using System.Web.UI.WebControls; namespace NP.Base.Controllers { @@ -272,17 +274,60 @@ namespace NP.Base.Controllers return JsonOK(passResult); } + /// + /// 회원탈퇴 진행 + /// + /// + /// [HttpPost] public JsonResult UserExit(String exitreason) { - //탈퇴할때데이터 정리는 무엇인가 해야할 텐데? - var rtn = Dao.Save("users.exit", new Hashtable() { { "userno", SUserInfo.UserNo }, { "exitreason", exitreason }, { "uno", SUserInfo.UserNo }, { "uip", GetUserIP() } }); - if (rtn > 0) + try { - CookieClear(null, true); + int rtn = -1; + + using (var t = new TransactionScope()) + { + #region + Save: users.exit (회원 탈퇴 신청) + var p = new Hashtable(); + p.Add("userno", SUserInfo.UserNo); + p.Add("status", 98); // 98 탈퇴신청, 99 탈퇴완료 + p.Add("uno", SUserInfo.UserNo); + p.Add("uip", GetUserIP()); + + rtn = Dao.Save("users.exit", p); + #endregion + + if (rtn > 0) + { + #region + Save: users.leave.register (회원 탈퇴 히스토리 등록) + rtn = Dao.Save("users.leave.register", p); + #endregion + } + + if (rtn > 0) + { + CookieClear(null, true); + Session.Abandon(); + + t.Complete(); + + return JsonOK(rtn); + } + else + { + return JsonError(JSONCode.Error, "데이터 처리 오류.", false); + } + } } - return JsonOK(rtn); + catch (Exception ex) + { + SetError($"회원탈퇴 실패: {ex.Message}"); + return JsonError(JSONCode.Error, "회원탈퇴에 실패 하였습니다.", false); + } + } + [HttpPost] public JsonResult AssignUpdate(Assign a) { diff --git a/Base/Controller/FOCommon.cs b/Base/Controller/FOCommon.cs index 4b609a0..a227f8e 100644 --- a/Base/Controller/FOCommon.cs +++ b/Base/Controller/FOCommon.cs @@ -115,9 +115,11 @@ namespace NP.Base.Controllers { CookieClear("savedid"); } + if (!string.IsNullOrEmpty(uid) && !string.IsNullOrEmpty(upw)) { var u = GoLogin(uid, upw); + if (u != null) { if(u.intv1 == 1) @@ -152,6 +154,15 @@ namespace NP.Base.Controllers { return JsonBack(new JsonRtn() { code = 1000, msg = "-3", obj = u.userno }); } + + if (u.status == 98) + { + // 탈퇴신청중 + u = null; + CookieClear(null, true); + return JsonBack(new JsonRtn() { code = 1000, msg = "-6", obj = null }); + } + return JsonOK(u.userno); } } diff --git a/Dao/MyBatis/Maps/Common.xml b/Dao/MyBatis/Maps/Common.xml index 0bc523b..867158b 100644 --- a/Dao/MyBatis/Maps/Common.xml +++ b/Dao/MyBatis/Maps/Common.xml @@ -396,7 +396,13 @@ order by b.username select a.userno,a.username - ,a.isacceptemail - ,CAST(AES_DECRYPT(UNHEX(a.email), ) AS char) email + ,a.isacceptemail + ,CAST(AES_DECRYPT(UNHEX(a.email), ) AS char) email from users a where a.userno in ($usernos$) and a.status=1 order by a.username @@ -660,12 +658,50 @@ ,CAST(AES_DECRYPT(UNHEX(email), ) AS char) email from users where userno=#userno# - - select a.userid, a.userpass,a.userno,a.username,a.status,usertype,a.asno,a.udt ,b.subdomain from users a @@ -765,12 +801,51 @@ ,username='탈퇴회원',usernameeng=null,email=null,mobile=null,telno=null,birthday=null,vssn=null,di=null,ci=null,userpno=null,bankno=null,post=null,address1=null,address2=null,authplatform=0,status=99 where userno=#userno# --> + + - update users set - ,exitreason=#exitreason# - ,status=99 - where userno=#userno# + UPDATE users + SET + , status = #status# + WHERE userno=#userno# + + + + INSERT INTO userleave ( + userno, + userid, + status, + levdate, + uno, + uip + ) + SELECT + u.userno, + u.userid, + 0 AS status, + NOW() AS levdate, + u.uno, + u.uip + FROM users u + WHERE u.status = #status# + AND u.userno = #userno# + + + + + + + userno IN ($usernos$) + + + update users a inner join assign b on b.asno=a.asno and b.siteip like concat('%',#siteip#,'%') @@ -923,8 +998,13 @@ delete from userdormant where userno in ($usernos$); + - delete from userdormant where userno in ($usernos$); + @@ -979,8 +1059,34 @@ ,introhtml =case when #introhtml# is not null then #introhtml# else introhtml end where userno=#userno# + + + - - - + \ No newline at end of file diff --git a/FO/Views/Account/IndexBase.cshtml b/FO/Views/Account/IndexBase.cshtml index 85c6039..f87cca7 100644 --- a/FO/Views/Account/IndexBase.cshtml +++ b/FO/Views/Account/IndexBase.cshtml @@ -35,7 +35,7 @@ + + +
- - - - + + + + @@ -73,7 +157,7 @@ - - + + - + @* - - - *@ + + + *@ @* - - - *@ + + + *@
ID

@u.userid

@@ -83,67 +167,67 @@ 생년월일

- @if (!string.IsNullOrEmpty(u.birthday)) - { - @(u.birthday.Replace("-", ".")) - } + @if (!string.IsNullOrEmpty(u.birthday)) + { + @(u.birthday.Replace("-", ".")) + }

학습인증수단 -
+

@(u.authplatform == AuthPlatform.None ? "-" : "I-PIN 인증")

- 휴대폰 인증으로 변경 -
- +

@(u.authplatform == AuthPlatform.None ? "-" : "휴대폰 인증")

- I-PIN 인증으로 변경 + I-PIN 인증으로 변경

※ 인증수단 변경 시 추가 인증을 진행해야 합니다.
※ 추가 인증 후 하단의 [저장] 버튼을 클릭해야 변경이 완료됩니다.
연락처
- @if(u.authplatform == AuthPlatform.Mobile) + @if (u.authplatform == AuthPlatform.Mobile) { -

@(u.mobile)

수정 +

@(u.mobile)

수정 } else { - - } + + }
소속 -
    -
  • -
  • -
-
소속 +
    +
  • +
  • +
+
직장 -
- -

@(u.asname ?? "-")

- 수정 -
-
직장 +
+ +

@(u.asname ?? "-")

+ 수정 +
+
학력 @@ -198,37 +282,61 @@ @Html.Partial("./Partial/OkCert3", null, new ViewDataDictionary { }) - -