namespace CounsellorBL.BLStructure.SYS { using CounsellorBL.GROUP.Helper; using CounsellorBL.Helper; using MonumentDefine; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OT.COM.ArsenalDB; using OT.COM.LogisticsUtil; using OT.COM.SignalerMessage; using SoldierData.EnterprizeV4; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using static CounsellorBL.GROUP.Helper.FbHelper; public class CommentManageService : SingleDataTableTemplate<tb_grp_comment> { private class CommentViewModel { public string uid { get; set; } public string article_uid { get; set; } public string origin_comment { get; set; } public string comment { get; set; } public DateTime comment_time { get; set; } public string group_user_id { get; set; } public int status { get; set; } public string fb_name { get; set; } public string fb_pic { get; set; } public string fb_comment_id { get; set; } public string group_id { get; set; } public string user_name { get; set; } public string user_picture { get; set; } public string member_uid { get; set; } public int status_flag { get; set; } public string parent_comment_id { get; set; } public string default_branch { get; set; } } private class GroupViewModel2 { public string fb_article_id { get; set; } public string user_token { get; set; } public string client_secret { get; set; } public string app_id { get; set; } } public CommentManageService() { EditMustConditionKeys.Add(tb_grp_comment.CN_ARTICLE_UID); dgReadCommandGenerator = readCommandGenerator; dgDeleteCommandGenerator = deleteCommandGenerator; } public new CResponseMessage Read(CRequestMessage i_crmInput) => base.Read(i_crmInput); protected string readCommandGenerator(CRequestMessage i_crmInput, JArray i_jaData, tb_sys_session i_sSessionUser, out Command o_c, [System.Runtime.CompilerServices.CallerLineNumber] int i_nCodeLine = 0, [System.Runtime.CompilerServices.CallerMemberName] string i_sMemberName = "", [System.Runtime.CompilerServices.CallerFilePath] string i_sSourcePath = "") { string sMsg; Command cRes = null; try { do { // 取得condition Dictionary<string, string> dicCondition = GetQueryMasterFirstQJEDicwherecols(i_crmInput); var lsBranch = ProjectHelper.GetUserGroup(i_crmInput); /**開始組指令**/ QueryJsonElementCollection lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeArticle = lBlocks.GetInst(); qjeArticle.table = tb_grp_article.TABLENAME; qjeArticle.displaycols = new List<string>() { tb_grp_article.CN_UID, tb_grp_article.CN_NAME, tb_grp_article.CN_GROUP_UID, tb_grp_article.CN_MESSAGE, tb_grp_article.CN_FB_ARTICLE_ID, tb_grp_article.CN_STATUS_FLAG, tb_grp_article.CN_RELEASE_DATE, tb_grp_article.CN_REMARK, tb_grp_article.CN_CLOSE_DATE, tb_grp_article.CN_POST_DATE }; List<WhereNode> wnQuery = new List<WhereNode>(); wnQuery.Add(new WhereNode(tb_grp_article.CN_STATUS_FLAG, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), BLWording.STATUS_FLAG_ON)); wnQuery.Add(new WhereNode(tb_grp_article.CN_STATUS_COMMENT, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), BLWording.STATUS_FLAG_ON)); wnQuery.Add(new WhereNode(tb_grp_article.CN_FB_ARTICLE_ID, WhereNode.EColumnOperation.EOT_ISNOTNULL, typeof(tb_grp_article))); // 搜尋社團 if (dicCondition.ContainsKey(tb_grp_article.CN_GROUP_UID)) { wnQuery.Add(new WhereNode(tb_grp_article.CN_GROUP_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), dicCondition[tb_grp_article.CN_GROUP_UID])); } if (dicCondition.ContainsKey(tb_grp_article.CN_CLOSE_DATE)) { if (dicCondition[tb_grp_article.CN_CLOSE_DATE] == "1") { wnQuery.Add(new WhereNode(tb_grp_article.CN_CLOSE_DATE, WhereNode.EColumnOperation.EOT_GTEQ, typeof(tb_grp_article), DateTime.Today)); wnQuery.Add(new WhereNode(tb_grp_article.CN_CLOSE_DATE, WhereNode.EColumnOperation.EOT_LT, typeof(tb_grp_article), DateTime.Today.AddDays(1))); } } wnQuery.Add(new WhereNode(tb_grp_article.CN_TYPE, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), (int)Enums.ArticleType.Article)); wnQuery.Add(new WhereNode(tb_grp_article.CN_GROUP_UID, WhereNode.EColumnOperation.EOT_IN, typeof(tb_grp_article), lsBranch.ToArray())); if (wnQuery.Any()) { qjeArticle.wherecols = new WhereNode(WhereNode.ENodeOperation.ENO_AND, wnQuery.ToArray()); } qjeArticle.ordercols = new List<Tuple<QueryJsonElement, string, string>> { Tuple.Create(qjeArticle, tb_grp_article.CN_POST_DATE, BLWording.ORDER_DESC), }; lBlocks.Add(qjeArticle); sMsg = MakeSelectJoinByBlocks(lBlocks, out cRes); } while (false); } catch (Exception ex) { LogHelper.DBLog(Util.GetLastExceptionMsg(ex), i_nCodeLine, i_sMemberName, i_sSourcePath); sMsg = $"{nameof(readCommandGenerator)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}. Call from {i_sMemberName} {i_sSourcePath}({i_nCodeLine})."; #if DEBUG System.Diagnostics.Debug.WriteLine(sMsg); #endif } o_c = cRes; return sMsg; } protected string deleteCommandGenerator(CRequestMessage i_crmInput, JArray i_jaItems, tb_sys_session i_sSessionUser, out List<Command> o_lcResult, List<string> i_saQryContainKeys, [System.Runtime.CompilerServices.CallerLineNumber] int i_nCodeLine = 0, [System.Runtime.CompilerServices.CallerMemberName] string i_sMemberName = "", [System.Runtime.CompilerServices.CallerFilePath] string i_sSourcePath = "") { string sMsg = null; List<Command> lcCmds = new List<Command>(); try { do { foreach (JToken jtkItem in i_jaItems) { Dictionary<string, object> dicItem = jtkItem.ToObject<Dictionary<string, object>>(); sMsg = getManualLog(i_crmInput, dicItem, BLWording.LOG_ACTION_NAME_DELETESQL, out Command cLog); if (sMsg != null) { break; } if (cLog != null) { lcCmds.Add(cLog); } string sMstUID = null; if (dicItem.ContainsKey(BLWording.WHEREDATA) && dicItem[BLWording.WHEREDATA] is JObject wheredata) { Dictionary<string, object> wheredataDic = wheredata.ToObject<Dictionary<string, object>>(); if (wheredataDic.ContainsKey(BLWording.UID)) { sMstUID = wheredataDic[BLWording.UID].ToString(); tb_grp_article t = new tb_grp_article() { status_comment = BLWording.STATUS_FLAG_OFF }; List<WhereNode> wnQuery = new List<WhereNode>(); wnQuery.Add(new WhereNode(tb_grp_comment.CN_STATUS, WhereNode.EColumnOperation.EOT_NEQ, typeof(tb_grp_comment), 9)); wnQuery.Add(new WhereNode(tb_grp_comment.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), sMstUID)); WhereNode wn = new WhereNode(WhereNode.ENodeOperation.ENO_AND, wnQuery.ToArray()); Command c = Command.SetupDeleteCmd(wn); Command tt = Command.SetupUpdateCmd(t, new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), sMstUID)); lcCmds.Add(c); if (!wheredataDic.ContainsKey("type")) { lcCmds.Add(tt); } } } } } while (false); } catch (Exception ex) { LogHelper.DBLog(Util.GetLastExceptionMsg(ex), i_crmInput); sMsg = $"{nameof(deleteCommandGenerator)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}. Call from {i_sMemberName} {i_sSourcePath}({i_nCodeLine})."; #if DEBUG System.Diagnostics.Debug.WriteLine(sMsg); #endif } o_lcResult = lcCmds; return sMsg; } private void SaveFbComment(string article_id) { // 取回文章ID跟UserToken QueryJsonElementCollection lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeArticle = lBlocks.GetInst(); qjeArticle.table = tb_grp_article.TABLENAME; qjeArticle.displaycols = new List<string>() { tb_grp_article.CN_FB_ARTICLE_ID }; qjeArticle.wherecols = new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), article_id); lBlocks.Add(qjeArticle); QueryJsonElement qjeGroup = lBlocks.GetInst(); qjeGroup.table = tb_grp_group.TABLENAME; qjeGroup.jointable = qjeArticle; qjeGroup.jointype = QueryJsonElement.LEFT_JOIN; qjeGroup.joincols = new Dictionary<string, string> { { tb_grp_group.CN_UID, tb_grp_article.CN_GROUP_UID } }; qjeGroup.displaycols = new List<string>() { tb_grp_group.CN_CLIENT_SECRET, tb_grp_group.CN_APP_ID }; lBlocks.Add(qjeGroup); QueryJsonElement qjeGroupUser = lBlocks.GetInst(); qjeGroupUser.table = tb_grp_group2user.TABLENAME; qjeGroupUser.jointable = qjeGroup; qjeGroupUser.jointype = QueryJsonElement.LEFT_JOIN; qjeGroupUser.joincols = new Dictionary<string, string> { { tb_grp_group2user.CN_GROUP_UID, tb_grp_group.CN_UID } }; qjeGroupUser.displaycols = new List<string>() { tb_grp_group2user.CN_USER_TOKEN }; qjeGroupUser.wherecols = new WhereNode(tb_grp_group2user.CN_STATUS_FLAG, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), BLWording.STATUS_FLAG_ON); lBlocks.Add(qjeGroupUser); string sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes); if (sMsg != null) { return; } ArsenalInterface ai = ArsenalDBMgr.GetInst(cRes); List<GroupViewModel2> qdArticle = ai.RunQueryList<GroupViewModel2>(cRes); string isValid = new FbHelper().CallFbCheckTokenGetAPI(qdArticle.First().user_token, qdArticle.First().app_id, qdArticle.First().client_secret, out int status); if (isValid != null) { sMsg = isValid; if (status == 2) { return; } } bool success = new FbHelper().CallFbCommentGetAPI(article_id, qdArticle.First().user_token, qdArticle.First().fb_article_id, out List<tb_grp_comment> comments); if (success) // 成功抓取資料 { if (comments == null || comments.Count == 0) // 無留言 { } else // 有留言 { } } else // 無法從FB抓取資料 { } } /// <summary> /// 傳回商品資訊 /// </summary> /// <param name="i_crmInput"></param> /// <returns></returns> public CResponseMessage FetchCommentFromFB(CRequestMessage i_crmInput) { string sMsg = null; CResponseMessage crmRes = null; try { do { sMsg = getCommonParameter(i_crmInput, BLWording.QRY_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession); if (sMsg != null) { break; } if (jaDataArray.Count != 1 || jaDataArray[0] == null) { sMsg = MessageWording.PARAM_NOT_EXPECTED; break; } var article_uid = jaDataArray[0][BLWording.WHEREDATA][BLWording.UID].ToString(); SaveFbComment(article_uid); } while (false); } catch (Exception ex) { sMsg = $"{nameof(FetchCommentFromFB)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(ex)}."; Logger.Error(ex); Logger.Error($"{nameof(FetchCommentFromFB)} sMsg: " + sMsg); #if DEBUG System.Diagnostics.Debug.WriteLine(sMsg); #endif } if (sMsg != null) { crmRes = new CErrorResponseMessage(sMsg, null); } else { crmRes = ReadComment(i_crmInput); } return crmRes; } class ReadCommentModel : tb_grp_article { public string fb_group_id { get; set; } } /// <summary> /// 傳回商品資訊 /// </summary> /// <param name="i_crmInput"></param> /// <returns></returns> public CResponseMessage ReadComment(CRequestMessage i_crmInput) { string sMsg = null; CResponseMessage crmRes = null; try { do { sMsg = getCommonParameter(i_crmInput, BLWording.QRY_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession); if (sMsg != null) { break; } if (jaDataArray.Count != 1 || jaDataArray[0] == null) { sMsg = MessageWording.PARAM_NOT_EXPECTED; break; } var article_uid = jaDataArray[0][BLWording.WHEREDATA][BLWording.UID].ToString(); // 取得貼文的post_status與group_id QueryJsonElementCollection lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeArticle = lBlocks.GetInst(); qjeArticle.table = tb_grp_article.TABLENAME; qjeArticle.displaycols = new List<string>() { tb_grp_article.CN_POST_STATUS, }; qjeArticle.wherecols = new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), article_uid); lBlocks.Add(qjeArticle); // 需判斷該會員是否為此社團 QueryJsonElement qjeGroup = lBlocks.GetInst(); qjeGroup.table = tb_grp_group.TABLENAME; qjeGroup.jointable = qjeArticle; qjeGroup.jointype = QueryJsonElement.LEFT_JOIN; qjeGroup.joincols = new Dictionary<string, string>() { { tb_grp_group.CN_UID, tb_grp_article.CN_GROUP_UID }}; qjeGroup.displaycols = new List<string>() { tb_grp_group.CN_FB_GROUP_ID, }; lBlocks.Add(qjeGroup); sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cResArticle); ArsenalInterface ai = ArsenalDBMgr.GetInst(cResArticle); List<ReadCommentModel> articles = ai.RunQueryList<ReadCommentModel>(cResArticle); /**開始組指令**/ lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeArticleToProduct = lBlocks.GetInst(); qjeArticleToProduct.table = tb_grp_comment.TABLENAME; qjeArticleToProduct.displaycols = new List<string>() { tb_grp_comment.CN_UID, tb_grp_comment.CN_ARTICLE_UID, tb_grp_comment.CN_ORIGIN_COMMENT, tb_grp_comment.CN_COMMENT, tb_grp_comment.CN_COMMENT_TIME, tb_grp_comment.CN_GROUP_USER_ID, tb_grp_comment.CN_STATUS, tb_grp_comment.CN_USER_NAME, tb_grp_comment.CN_USER_PICTURE, tb_grp_comment.CN_FB_COMMENT_ID, tb_grp_comment.CN_PARENT_COMMENT_ID, }; List<WhereNode> wnCommentQuery = new List<WhereNode> { new WhereNode(tb_grp_comment.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), article_uid), new WhereNode(tb_grp_comment.CN_STATUS, WhereNode.EColumnOperation.EOT_NEQ, typeof(tb_grp_comment), (int)FbHelper.CommentStatus.TransferOrder), new WhereNode(tb_grp_comment.CN_STATUS_FLAG, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), BLWording.STATUS_FLAG_ON) }; qjeArticleToProduct.wherecols = new WhereNode(WhereNode.ENodeOperation.ENO_AND, wnCommentQuery.ToArray()); // Sort List<Tuple<QueryJsonElement, string, string>> qjeArticleToProductOrder = new List<Tuple<QueryJsonElement, string, string>>() { Tuple.Create(qjeArticle, tb_grp_comment.CN_COMMENT_TIME, BLWording.ORDER_ASC) }; qjeArticleToProduct.ordercols = qjeArticleToProductOrder; lBlocks.Add(qjeArticleToProduct); QueryJsonElement qjeMember = lBlocks.GetInst(); qjeMember.table = tb_meb_member.TABLENAME; qjeMember.jointable = qjeArticleToProduct; qjeMember.jointype = QueryJsonElement.LEFT_JOIN; qjeMember.joincols = new Dictionary<string, string>() { { tb_meb_member.CN_GROUP_USER_ID, tb_grp_comment.CN_GROUP_USER_ID }}; qjeMember.displaycols = new List<string>() { tb_meb_member.CN_NAME, tb_meb_member.CN_FB_PIC, tb_meb_member.CN_STATUS_FLAG, tb_meb_member.CN_GROUP_ID, tb_meb_member.CN_DEFAULT_BRANCH }; qjeMember.aliascols = new Dictionary<string, List<string>> { { tb_meb_member.CN_UID, new List<string>() { "member_uid" } } }; List<WhereNode> wnMemberQuery = new List<WhereNode> { new WhereNode(tb_meb_member.CN_GROUP_ID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_meb_member), articles[0].fb_group_id), new WhereNode(tb_meb_member.CN_GROUP_ID, WhereNode.EColumnOperation.EOT_ISNULL, typeof(tb_meb_member)) }; qjeMember.wherecols = new WhereNode(WhereNode.ENodeOperation.ENO_OR, wnMemberQuery.ToArray()); lBlocks.Add(qjeMember); sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes); if (sMsg != null) { break; } ai = ArsenalDBMgr.GetInst(cRes); List<CommentViewModel> qdArticle = ai.RunQueryList<CommentViewModel>(cRes); var parentData = qdArticle.GroupBy(x => x.parent_comment_id); if (!cRes.IsSuccess) { sMsg = cRes.LastErrorCode; break; } crmRes = new CSuccessResponseMessage(null, i_crmInput); // 填寫回傳 crmRes.param.Add(BLWording.DATA, parentData); crmRes.param.Add("post_status", articles); } while (false); } catch (Exception ex) { sMsg = $"{nameof(ReadComment)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}."; #if DEBUG System.Diagnostics.Debug.WriteLine(sMsg); #endif } if (sMsg != null) { crmRes = new CErrorResponseMessage(sMsg, null); } return crmRes; } public CResponseMessage DeleteComment(CRequestMessage i_crmInput) { string sMsg = null; CResponseMessage crmRes = null; List<Command> lcCmds = new List<Command>(); try { do { sMsg = getCommonParameter(i_crmInput, BLWording.DEL_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession); if (sMsg != null) { break; } if (jaDataArray.Count != 1 || jaDataArray[0] == null) { sMsg = MessageWording.PARAM_NOT_EXPECTED; break; } var uid = jaDataArray[0][BLWording.WHEREDATA][BLWording.UID].ToString(); tb_grp_comment u = new tb_grp_comment() { status_flag = BLWording.STATUS_FLAG_OFF }; Command c = Command.SetupUpdateCmd(u, new WhereNode(tb_grp_comment.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), uid)); lcCmds.Add(c); ArsenalInterface ai = ArsenalDBMgr.GetInst(lcCmds[0], GetDefaultSystemColumnInfo()); ai.RunEditCmds(lcCmds); sMsg = GetLastErrorCode(lcCmds); if (sMsg != null) { crmRes = new CErrorResponseMessage(sMsg, null); } else { crmRes = new CSuccessResponseMessage(null, i_crmInput); } } while (false); } catch (Exception ex) { sMsg = $"{nameof(DeleteComment)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}."; #if DEBUG System.Diagnostics.Debug.WriteLine(sMsg); #endif } if (sMsg != null) { crmRes = new CErrorResponseMessage(sMsg, null); } return crmRes; } public CResponseMessage CreateComment(CRequestMessage i_crmInput) { string sMsg = null; CResponseMessage crmRes = null; try { do { sMsg = getCommonParameter(i_crmInput, BLWording.ADD_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession); if (sMsg != null) { break; } var article = jaDataArray[0][BLWording.DATA]["article_data"].ToObject<tb_grp_article>(); var member = jaDataArray[0][BLWording.DATA]["member_data"].ToObject<tb_meb_member>(); var comment = jaDataArray[0][BLWording.DATA][BLWording.DATA].ToString(); List<Command> lCmds = new List<Command>(); var comments = new List<tb_grp_comment>(); // 取回該社團可以取貨的地點 var branches = GetBranches(article.group_uid).Select(x => x.branch_name).ToList(); var products = GetProducts(article.uid); var productInfos = GetProductInfos(products); Logger.Info($"開始解析貼文 文章ID: {article.uid} 設定: {JsonConvert.SerializeObject(productInfos)}"); var parser = new GroupBuyParser.GroupBuyParser { Settings = new GroupBuyParser.ParserSettings { Products = productInfos, Branches = branches } }; if(member == null) { return new CErrorResponseMessage("沒有設定會員名稱", null); } // 如果取不回fb_id(使用者沒有允許應用程式查看貼文)仍要處理 string group_user_id = member.group_user_id; string json = ""; int status = 0; var parseData = parser.Parse(comment); if (parseData.Success) { bool isProductCorrect = true; foreach (var product in parseData.Product) { if (product.Name == "I") { isProductCorrect = false; break; } } if (isProductCorrect) // 名稱有I 不Insert進資料庫 { json = JsonConvert.SerializeObject(parseData.Product); status = (int)CommentStatus.OK; } else { status = (int)CommentStatus.InvalidFormat; } } else { status = (int)CommentStatus.InvalidFormat; // 增加log紀錄確認解析失敗的原因 Logger.Info($"解析貼文失敗 姓名: {member.name} 內容: {comment} 原因: {parseData.ErrorMessage} 貼文ID: {article.uid}"); } if (string.IsNullOrEmpty(group_user_id)) { status = (int)CommentStatus.UnknownMember; } tb_grp_comment cNew = new tb_grp_comment { uid = Guid.NewGuid().ToString(), article_uid = article.uid, origin_comment = comment, comment = json, group_user_id = group_user_id, comment_time = DateTime.Now, fb_comment_id = null, status = status, user_name = member.name, user_picture = member.fb_pic }; comments.Add(cNew); // 沒有任何留言就不處理 if (comments.Count == 0) { return null; } lCmds.AddRange(comments.Select(x => Command.SetupInsertCmd(x))); var ai = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo()); ai.RunEditCmds(lCmds); sMsg = GetLastErrorCode(lCmds); if (sMsg != null) { crmRes = new CErrorResponseMessage(sMsg, null); } else { crmRes = new CSuccessResponseMessage(null, i_crmInput); } } while (false); } catch (Exception ex) { sMsg = $"{nameof(DeleteComment)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}."; #if DEBUG System.Diagnostics.Debug.WriteLine(sMsg); #endif Logger.Error(ex.ToString()); } if (sMsg != null) { crmRes = new CErrorResponseMessage(sMsg, null); } return crmRes; } /// <summary> /// 參考 CreateComment /// </summary> /// <param name="i_crmInput"></param> /// <returns></returns> public CResponseMessage ImportComment(CRequestMessage i_crmInput) { string sMsg = null; CResponseMessage crmRes = null; var logInfos = new StringBuilder(); try { do { sMsg = getCommonParameter(i_crmInput, BLWording.ADD_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession); if (sMsg != null) break; var article = jaDataArray[0][BLWording.DATA]["article_data"].ToObject<tb_grp_article>(); var comments = jaDataArray[0][BLWording.DATA][BLWording.DATA].ToString().Split('\n'); var tb_grp_comment_List = new List<tb_grp_comment>(); var misMatchMembers = new StringBuilder(); List<Command> lCmds = new List<Command>(); // 取回該社團可以取貨的地點 var branches = GetBranches(article.group_uid); var products = GetProducts(article.uid); var members = GetMembers(article.group_uid); var productInfos = GetProductInfos(products);// 將名稱以['A', 'B'...]這樣依序產生,如果產品有3個,就要放入['A', 'B', 'C'] logInfos.AppendLine($"{nameof(ImportComment)} 開始解析貼文留言 文章ID: {article.uid} 設定: {JsonConvert.SerializeObject(productInfos)}"); var parser = new GroupBuyParser.GroupBuyParser { Settings = new GroupBuyParser.ParserSettings { Products = productInfos, Branches = branches.Select(x => x.branch_name).ToList() } }; // 去除匯入留言前面的空白行 var blankLineCount = 0; foreach (var comment in comments) { if (!string.IsNullOrWhiteSpace(comment)) break; blankLineCount++; } comments = comments[(blankLineCount)..(comments.Count())]; var sortMillsecond = 0;// 累加毫秒數, 用來排序正確留言順序 List<(string member, string orders)> membersAndOrders = new List<(string, string)>(); // Parse comment for (int i = 1; i < comments.Length; i++) { var parserData = ParserComment(parser, comments[i], branches.First().branch_name); if (!parserData.Success) continue; string orders = parserData.Text; string member = comments[i - 1];// 往上抓客人名稱 // 往下抓可能有多行的訂單 for (++i; i < comments.Length; i++) { parserData = ParserComment(parser, comments[i], branches.First().branch_name); if (!parserData.Success) break; orders += parserData.Text; } membersAndOrders.Add((member, orders)); } // Match member & default branch foreach (var memberAndOrders in membersAndOrders) { var member = members.Find(item => item.name == memberAndOrders.member); if (member == null)// 沒匹配的會員名稱 { misMatchMembers.AppendLine($"[{memberAndOrders.orders}] "); continue; } int status = (int)CommentStatus.UnknownMember; var json = ""; var parseData = ParserComment(parser, memberAndOrders.orders, $"{branches.Find(x => x.uid == member.default_branch)?.branch_name}");// 匯入留言後面加上預設分店中文名稱 if (parseData.Success) { bool isProductCorrect = true; isProductCorrect = parseData.Product.Find(x => x.Name == "I") == null ? true : false; if (isProductCorrect) // 名稱有I 不Insert進資料庫 { var Branch = branches.Find(item => item.uid == member.default_branch)?.branch_name;// Parser解析Branch會為null, 經討論後都放預設分店 parseData.Product.ForEach(item => item.Branch = Branch); json = JsonConvert.SerializeObject(parseData.Product); status = (int)CommentStatus.OK; } else { status = (int)CommentStatus.InvalidFormat; } } else { status = (int)CommentStatus.InvalidFormat; logInfos.AppendLine($"{nameof(ImportComment)} 解析貼文失敗 內容: {memberAndOrders.orders} 原因: {parseData.ErrorMessage} 貼文ID: {article.uid}"); } tb_grp_comment cNew = new tb_grp_comment { uid = Guid.NewGuid().ToString(), article_uid = article.uid, origin_comment = memberAndOrders.orders, comment = string.IsNullOrWhiteSpace(json) ? "" : json, group_user_id = member.group_user_id, comment_time = DateTime.Now.AddMilliseconds(sortMillsecond++), fb_comment_id = null, status = status, user_name = member.name, user_picture = member.fb_pic, }; tb_grp_comment_List.Add(cNew); } if (tb_grp_comment_List.Count == 0) { sMsg = "沒有要匯入的留言"; break; } lCmds.AddRange(tb_grp_comment_List.Select(x => Command.SetupInsertCmd(x))); var ai2 = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo()); ai2.RunEditCmds(lCmds); sMsg = GetLastErrorCode(lCmds); if (sMsg != null) { break; } if (!string.IsNullOrWhiteSpace(misMatchMembers.ToString())) { misMatchMembers.Insert(0, "以下下單會員資料查詢不到, 不匯入系統: "); } crmRes = new CSuccessResponseMessage(misMatchMembers.Insert(0, "匯入成功 ").ToString(), i_crmInput); } while (false); } catch(Exception ex) { sMsg = $"{nameof(DeleteComment)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}."; #if DEBUG System.Diagnostics.Debug.WriteLine(sMsg); #endif Logger.Error(ex.ToString()); } finally { Logger.Info(logInfos.ToString()); } if (sMsg != null) { crmRes = new CErrorResponseMessage(sMsg, null); } return crmRes; } private List<tb_prd_article2product> GetProducts(string article_uid) { /**開始組指令**/ QueryJsonElementCollection lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeArticleToProduct = lBlocks.GetInst(); qjeArticleToProduct.table = tb_prd_article2product.TABLENAME; qjeArticleToProduct.displaycols = new List<string>() { tb_prd_article2product.CN_UID, tb_prd_article2product.CN_NAME, tb_prd_article2product.CN_PRICE, tb_prd_article2product.CN_SEQ, tb_prd_article2product.CN_SPECIFICATION }; qjeArticleToProduct.wherecols = new WhereNode(tb_prd_article2product.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_prd_article2product), article_uid); lBlocks.Add(qjeArticleToProduct); QueryJsonElement qjeProduct = lBlocks.GetInst(); qjeProduct.table = tb_prd_product.TABLENAME; qjeProduct.jointable = qjeArticleToProduct; qjeProduct.joincols = new Dictionary<string, string>() { { tb_prd_product.CN_UID, tb_prd_article2product.CN_PRD_UID } }; lBlocks.Add(qjeProduct); var sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes); var ai = ArsenalDBMgr.GetInst(cRes); List<tb_prd_article2product> data = ai.RunQueryList<tb_prd_article2product>(cRes); return data.ToList(); } private List<tb_grp_branch> GetBranches(string group_uid) { tb_grp_branch cDisplay = new tb_grp_branch(); cDisplay.SetFullDirty(); var whereNode = new WhereNode(tb_grp_branch.CN_GROUP_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), group_uid); var cSelect = Command.SetupSelectCmd(cDisplay, whereNode); var ai = ArsenalDBMgr.GetInst(cSelect); var data = ai.RunQueryList<tb_grp_branch>(cSelect); return data; } public List<tb_meb_member> GetMembers(string group_uid_) { QueryJsonElementCollection lBlocks = new QueryJsonElementCollection(); QueryJsonElement qjeMember = lBlocks.GetInst(); qjeMember.table = tb_meb_member.TABLENAME; qjeMember.displaycols = new List<string>() { tb_meb_member.CN_UID, tb_meb_member.CN_NAME, tb_meb_member.CN_GROUP_ID, tb_meb_member.CN_DEFAULT_BRANCH, tb_meb_member.CN_GROUP_USER_ID, tb_meb_member.CN_FB_PIC }; //qjeMember.wherecols = new WhereNode(tb_meb_member.CN_GROUP_ID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_meb_member), article.group_uid); lBlocks.Add(qjeMember); QueryJsonElement qjeProduct = lBlocks.GetInst(); qjeProduct.table = tb_grp_group.TABLENAME; qjeProduct.jointable = qjeMember; qjeProduct.joincols = new Dictionary<string, string>() { { tb_grp_group.CN_FB_GROUP_ID, tb_meb_member.CN_GROUP_ID } }; qjeProduct.wherecols = new WhereNode(tb_grp_group.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_meb_member), group_uid_); lBlocks.Add(qjeProduct); var sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes); if (!string.IsNullOrWhiteSpace(sMsg)) { throw new Exception(sMsg); } var ai = ArsenalDBMgr.GetInst(cRes); return ai.RunQueryList<tb_meb_member>(cRes); } /// <summary> /// 使用原本解析器, 加上隨意的預設分店防止錯誤訊息跳出 /// </summary> /// <param name="branch_name"></param> /// <param name="comment"></param> /// <param name="parser"></param> /// <returns></returns> private GroupBuyParser.ParserData ParserComment(GroupBuyParser.GroupBuyParser parser, string comment, string branch_name) { var parserData = new GroupBuyParser.ParserData() { DefaultBranch = branch_name }; parserData.Text = comment; parser.Parse(parserData); return parserData; } /// <summary> /// 條列A~Z項目時要忽略I項目, Example: ABCDEFGH >>> JKL, 屬於客製化設計 /// </summary> /// <param name="products"></param> /// <returns></returns> private List<GroupBuyParser.ProductInfo> GetProductInfos(List<tb_prd_article2product> products) { return products.Select((x, i) => new GroupBuyParser.ProductInfo { Name = ((char)('A' + (i < 8 ? i : i + 1))).ToString(),// Jump over product items [ I ], Name = ABCDEFGHJ.....etc Specifications = string.IsNullOrEmpty(x.specification) ? null : x.specification.Split(',', StringSplitOptions.RemoveEmptyEntries) }).ToList(); } } }