You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

967 lines
43 KiB

  1. namespace CounsellorBL.BLStructure.SYS
  2. {
  3. using CounsellorBL.GROUP.Helper;
  4. using CounsellorBL.Helper;
  5. using MonumentDefine;
  6. using Newtonsoft.Json;
  7. using Newtonsoft.Json.Linq;
  8. using OT.COM.ArsenalDB;
  9. using OT.COM.LogisticsUtil;
  10. using OT.COM.SignalerMessage;
  11. using SoldierData.EnterprizeV4;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Text.RegularExpressions;
  17. using static CounsellorBL.GROUP.Helper.FbHelper;
  18. public class CommentManageService : SingleDataTableTemplate<tb_grp_comment>
  19. {
  20. private class CommentViewModel
  21. {
  22. public string uid { get; set; }
  23. public string article_uid { get; set; }
  24. public string origin_comment { get; set; }
  25. public string comment { get; set; }
  26. public DateTime comment_time { get; set; }
  27. public string group_user_id { get; set; }
  28. public int status { get; set; }
  29. public string fb_name { get; set; }
  30. public string fb_pic { get; set; }
  31. public string fb_comment_id { get; set; }
  32. public string group_id { get; set; }
  33. public string user_name { get; set; }
  34. public string user_picture { get; set; }
  35. public string member_uid { get; set; }
  36. public int status_flag { get; set; }
  37. public string parent_comment_id { get; set; }
  38. public string default_branch { get; set; }
  39. }
  40. private class GroupViewModel2
  41. {
  42. public string fb_article_id { get; set; }
  43. public string user_token { get; set; }
  44. public string client_secret { get; set; }
  45. public string app_id { get; set; }
  46. }
  47. public CommentManageService()
  48. {
  49. EditMustConditionKeys.Add(tb_grp_comment.CN_ARTICLE_UID);
  50. dgReadCommandGenerator = readCommandGenerator;
  51. dgDeleteCommandGenerator = deleteCommandGenerator;
  52. }
  53. public new CResponseMessage Read(CRequestMessage i_crmInput) => base.Read(i_crmInput);
  54. protected string readCommandGenerator(CRequestMessage i_crmInput, JArray i_jaData, tb_sys_session i_sSessionUser, out Command o_c,
  55. [System.Runtime.CompilerServices.CallerLineNumber] int i_nCodeLine = 0,
  56. [System.Runtime.CompilerServices.CallerMemberName] string i_sMemberName = "",
  57. [System.Runtime.CompilerServices.CallerFilePath] string i_sSourcePath = "")
  58. {
  59. string sMsg;
  60. Command cRes = null;
  61. try
  62. {
  63. do
  64. {
  65. // 取得condition
  66. Dictionary<string, string> dicCondition = GetQueryMasterFirstQJEDicwherecols(i_crmInput);
  67. var lsBranch = ProjectHelper.GetUserGroup(i_crmInput);
  68. /**開始組指令**/
  69. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  70. QueryJsonElement qjeArticle = lBlocks.GetInst();
  71. qjeArticle.table = tb_grp_article.TABLENAME;
  72. qjeArticle.displaycols = new List<string>()
  73. {
  74. tb_grp_article.CN_UID,
  75. tb_grp_article.CN_NAME,
  76. tb_grp_article.CN_GROUP_UID,
  77. tb_grp_article.CN_MESSAGE,
  78. tb_grp_article.CN_FB_ARTICLE_ID,
  79. tb_grp_article.CN_STATUS_FLAG,
  80. tb_grp_article.CN_RELEASE_DATE,
  81. tb_grp_article.CN_REMARK,
  82. tb_grp_article.CN_CLOSE_DATE,
  83. tb_grp_article.CN_POST_DATE
  84. };
  85. List<WhereNode> wnQuery = new List<WhereNode>();
  86. wnQuery.Add(new WhereNode(tb_grp_article.CN_STATUS_FLAG, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), BLWording.STATUS_FLAG_ON));
  87. wnQuery.Add(new WhereNode(tb_grp_article.CN_STATUS_COMMENT, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), BLWording.STATUS_FLAG_ON));
  88. wnQuery.Add(new WhereNode(tb_grp_article.CN_FB_ARTICLE_ID, WhereNode.EColumnOperation.EOT_ISNOTNULL, typeof(tb_grp_article)));
  89. // 搜尋社團
  90. if (dicCondition.ContainsKey(tb_grp_article.CN_GROUP_UID))
  91. {
  92. 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]));
  93. }
  94. if (dicCondition.ContainsKey(tb_grp_article.CN_CLOSE_DATE))
  95. {
  96. if (dicCondition[tb_grp_article.CN_CLOSE_DATE] == "1")
  97. {
  98. wnQuery.Add(new WhereNode(tb_grp_article.CN_CLOSE_DATE, WhereNode.EColumnOperation.EOT_GTEQ, typeof(tb_grp_article), DateTime.Today));
  99. wnQuery.Add(new WhereNode(tb_grp_article.CN_CLOSE_DATE, WhereNode.EColumnOperation.EOT_LT, typeof(tb_grp_article), DateTime.Today.AddDays(1)));
  100. }
  101. }
  102. wnQuery.Add(new WhereNode(tb_grp_article.CN_TYPE, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), (int)Enums.ArticleType.Article));
  103. wnQuery.Add(new WhereNode(tb_grp_article.CN_GROUP_UID, WhereNode.EColumnOperation.EOT_IN, typeof(tb_grp_article), lsBranch.ToArray()));
  104. if (wnQuery.Any())
  105. {
  106. qjeArticle.wherecols = new WhereNode(WhereNode.ENodeOperation.ENO_AND, wnQuery.ToArray());
  107. }
  108. qjeArticle.ordercols = new List<Tuple<QueryJsonElement, string, string>> {
  109. Tuple.Create(qjeArticle, tb_grp_article.CN_POST_DATE, BLWording.ORDER_DESC),
  110. };
  111. lBlocks.Add(qjeArticle);
  112. sMsg = MakeSelectJoinByBlocks(lBlocks, out cRes);
  113. }
  114. while (false);
  115. }
  116. catch (Exception ex)
  117. {
  118. LogHelper.DBLog(Util.GetLastExceptionMsg(ex), i_nCodeLine, i_sMemberName, i_sSourcePath);
  119. sMsg = $"{nameof(readCommandGenerator)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}. Call from {i_sMemberName} {i_sSourcePath}({i_nCodeLine}).";
  120. #if DEBUG
  121. System.Diagnostics.Debug.WriteLine(sMsg);
  122. #endif
  123. }
  124. o_c = cRes;
  125. return sMsg;
  126. }
  127. protected string deleteCommandGenerator(CRequestMessage i_crmInput, JArray i_jaItems, tb_sys_session i_sSessionUser, out List<Command> o_lcResult, List<string> i_saQryContainKeys,
  128. [System.Runtime.CompilerServices.CallerLineNumber] int i_nCodeLine = 0,
  129. [System.Runtime.CompilerServices.CallerMemberName] string i_sMemberName = "",
  130. [System.Runtime.CompilerServices.CallerFilePath] string i_sSourcePath = "")
  131. {
  132. string sMsg = null;
  133. List<Command> lcCmds = new List<Command>();
  134. try
  135. {
  136. do
  137. {
  138. foreach (JToken jtkItem in i_jaItems)
  139. {
  140. Dictionary<string, object> dicItem = jtkItem.ToObject<Dictionary<string, object>>();
  141. sMsg = getManualLog(i_crmInput, dicItem, BLWording.LOG_ACTION_NAME_DELETESQL, out Command cLog);
  142. if (sMsg != null)
  143. {
  144. break;
  145. }
  146. if (cLog != null)
  147. {
  148. lcCmds.Add(cLog);
  149. }
  150. string sMstUID = null;
  151. if (dicItem.ContainsKey(BLWording.WHEREDATA) && dicItem[BLWording.WHEREDATA] is JObject wheredata)
  152. {
  153. Dictionary<string, object> wheredataDic = wheredata.ToObject<Dictionary<string, object>>();
  154. if (wheredataDic.ContainsKey(BLWording.UID))
  155. {
  156. sMstUID = wheredataDic[BLWording.UID].ToString();
  157. tb_grp_article t = new tb_grp_article()
  158. {
  159. status_comment = BLWording.STATUS_FLAG_OFF
  160. };
  161. List<WhereNode> wnQuery = new List<WhereNode>();
  162. wnQuery.Add(new WhereNode(tb_grp_comment.CN_STATUS, WhereNode.EColumnOperation.EOT_NEQ, typeof(tb_grp_comment), 9));
  163. wnQuery.Add(new WhereNode(tb_grp_comment.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), sMstUID));
  164. WhereNode wn = new WhereNode(WhereNode.ENodeOperation.ENO_AND, wnQuery.ToArray());
  165. Command c = Command.SetupDeleteCmd(wn);
  166. Command tt = Command.SetupUpdateCmd(t, new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), sMstUID));
  167. lcCmds.Add(c);
  168. if (!wheredataDic.ContainsKey("type"))
  169. {
  170. lcCmds.Add(tt);
  171. }
  172. }
  173. }
  174. }
  175. }
  176. while (false);
  177. }
  178. catch (Exception ex)
  179. {
  180. LogHelper.DBLog(Util.GetLastExceptionMsg(ex), i_crmInput);
  181. sMsg = $"{nameof(deleteCommandGenerator)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}. Call from {i_sMemberName} {i_sSourcePath}({i_nCodeLine}).";
  182. #if DEBUG
  183. System.Diagnostics.Debug.WriteLine(sMsg);
  184. #endif
  185. }
  186. o_lcResult = lcCmds;
  187. return sMsg;
  188. }
  189. private void SaveFbComment(string article_id)
  190. {
  191. // 取回文章ID跟UserToken
  192. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  193. QueryJsonElement qjeArticle = lBlocks.GetInst();
  194. qjeArticle.table = tb_grp_article.TABLENAME;
  195. qjeArticle.displaycols = new List<string>()
  196. {
  197. tb_grp_article.CN_FB_ARTICLE_ID
  198. };
  199. qjeArticle.wherecols = new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), article_id);
  200. lBlocks.Add(qjeArticle);
  201. QueryJsonElement qjeGroup = lBlocks.GetInst();
  202. qjeGroup.table = tb_grp_group.TABLENAME;
  203. qjeGroup.jointable = qjeArticle;
  204. qjeGroup.jointype = QueryJsonElement.LEFT_JOIN;
  205. qjeGroup.joincols = new Dictionary<string, string> { { tb_grp_group.CN_UID, tb_grp_article.CN_GROUP_UID } };
  206. qjeGroup.displaycols = new List<string>()
  207. {
  208. tb_grp_group.CN_CLIENT_SECRET,
  209. tb_grp_group.CN_APP_ID
  210. };
  211. lBlocks.Add(qjeGroup);
  212. QueryJsonElement qjeGroupUser = lBlocks.GetInst();
  213. qjeGroupUser.table = tb_grp_group2user.TABLENAME;
  214. qjeGroupUser.jointable = qjeGroup;
  215. qjeGroupUser.jointype = QueryJsonElement.LEFT_JOIN;
  216. qjeGroupUser.joincols = new Dictionary<string, string> { { tb_grp_group2user.CN_GROUP_UID, tb_grp_group.CN_UID } };
  217. qjeGroupUser.displaycols = new List<string>()
  218. {
  219. tb_grp_group2user.CN_USER_TOKEN
  220. };
  221. qjeGroupUser.wherecols = new WhereNode(tb_grp_group2user.CN_STATUS_FLAG, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), BLWording.STATUS_FLAG_ON);
  222. lBlocks.Add(qjeGroupUser);
  223. string sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
  224. if (sMsg != null)
  225. {
  226. return;
  227. }
  228. ArsenalInterface ai = ArsenalDBMgr.GetInst(cRes);
  229. List<GroupViewModel2> qdArticle = ai.RunQueryList<GroupViewModel2>(cRes);
  230. string isValid = new FbHelper().CallFbCheckTokenGetAPI(qdArticle.First().user_token, qdArticle.First().app_id, qdArticle.First().client_secret, out int status);
  231. if (isValid != null)
  232. {
  233. sMsg = isValid;
  234. if (status == 2)
  235. {
  236. return;
  237. }
  238. }
  239. bool success = new FbHelper().CallFbCommentGetAPI(article_id, qdArticle.First().user_token, qdArticle.First().fb_article_id, out List<tb_grp_comment> comments);
  240. if (success) // 成功抓取資料
  241. {
  242. if (comments == null || comments.Count == 0) // 無留言
  243. {
  244. }
  245. else // 有留言
  246. {
  247. }
  248. }
  249. else // 無法從FB抓取資料
  250. {
  251. }
  252. }
  253. /// <summary>
  254. /// 傳回商品資訊
  255. /// </summary>
  256. /// <param name="i_crmInput"></param>
  257. /// <returns></returns>
  258. public CResponseMessage FetchCommentFromFB(CRequestMessage i_crmInput)
  259. {
  260. string sMsg = null;
  261. CResponseMessage crmRes = null;
  262. try
  263. {
  264. do
  265. {
  266. sMsg = getCommonParameter(i_crmInput, BLWording.QRY_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession);
  267. if (sMsg != null)
  268. {
  269. break;
  270. }
  271. if (jaDataArray.Count != 1 || jaDataArray[0] == null)
  272. {
  273. sMsg = MessageWording.PARAM_NOT_EXPECTED;
  274. break;
  275. }
  276. var article_uid = jaDataArray[0][BLWording.WHEREDATA][BLWording.UID].ToString();
  277. SaveFbComment(article_uid);
  278. }
  279. while (false);
  280. }
  281. catch (Exception ex)
  282. {
  283. sMsg = $"{nameof(FetchCommentFromFB)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(ex)}.";
  284. Logger.Error(ex);
  285. Logger.Error($"{nameof(FetchCommentFromFB)} sMsg: " + sMsg);
  286. #if DEBUG
  287. System.Diagnostics.Debug.WriteLine(sMsg);
  288. #endif
  289. }
  290. if (sMsg != null)
  291. {
  292. crmRes = new CErrorResponseMessage(sMsg, null);
  293. }
  294. else
  295. {
  296. crmRes = ReadComment(i_crmInput);
  297. }
  298. return crmRes;
  299. }
  300. class ReadCommentModel : tb_grp_article
  301. {
  302. public string fb_group_id { get; set; }
  303. }
  304. /// <summary>
  305. /// 傳回商品資訊
  306. /// </summary>
  307. /// <param name="i_crmInput"></param>
  308. /// <returns></returns>
  309. public CResponseMessage ReadComment(CRequestMessage i_crmInput)
  310. {
  311. string sMsg = null;
  312. CResponseMessage crmRes = null;
  313. try
  314. {
  315. do
  316. {
  317. sMsg = getCommonParameter(i_crmInput, BLWording.QRY_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession);
  318. if (sMsg != null)
  319. {
  320. break;
  321. }
  322. if (jaDataArray.Count != 1 || jaDataArray[0] == null)
  323. {
  324. sMsg = MessageWording.PARAM_NOT_EXPECTED;
  325. break;
  326. }
  327. var article_uid = jaDataArray[0][BLWording.WHEREDATA][BLWording.UID].ToString();
  328. // 取得貼文的post_status與group_id
  329. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  330. QueryJsonElement qjeArticle = lBlocks.GetInst();
  331. qjeArticle.table = tb_grp_article.TABLENAME;
  332. qjeArticle.displaycols = new List<string>()
  333. {
  334. tb_grp_article.CN_POST_STATUS,
  335. };
  336. qjeArticle.wherecols = new WhereNode(tb_grp_article.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_article), article_uid);
  337. lBlocks.Add(qjeArticle);
  338. // 需判斷該會員是否為此社團
  339. QueryJsonElement qjeGroup = lBlocks.GetInst();
  340. qjeGroup.table = tb_grp_group.TABLENAME;
  341. qjeGroup.jointable = qjeArticle;
  342. qjeGroup.jointype = QueryJsonElement.LEFT_JOIN;
  343. qjeGroup.joincols = new Dictionary<string, string>() {
  344. { tb_grp_group.CN_UID, tb_grp_article.CN_GROUP_UID }};
  345. qjeGroup.displaycols = new List<string>()
  346. {
  347. tb_grp_group.CN_FB_GROUP_ID,
  348. };
  349. lBlocks.Add(qjeGroup);
  350. sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cResArticle);
  351. ArsenalInterface ai = ArsenalDBMgr.GetInst(cResArticle);
  352. List<ReadCommentModel> articles = ai.RunQueryList<ReadCommentModel>(cResArticle);
  353. /**開始組指令**/
  354. lBlocks = new QueryJsonElementCollection();
  355. QueryJsonElement qjeArticleToProduct = lBlocks.GetInst();
  356. qjeArticleToProduct.table = tb_grp_comment.TABLENAME;
  357. qjeArticleToProduct.displaycols = new List<string>()
  358. {
  359. tb_grp_comment.CN_UID,
  360. tb_grp_comment.CN_ARTICLE_UID,
  361. tb_grp_comment.CN_ORIGIN_COMMENT,
  362. tb_grp_comment.CN_COMMENT,
  363. tb_grp_comment.CN_COMMENT_TIME,
  364. tb_grp_comment.CN_GROUP_USER_ID,
  365. tb_grp_comment.CN_STATUS,
  366. tb_grp_comment.CN_USER_NAME,
  367. tb_grp_comment.CN_USER_PICTURE,
  368. tb_grp_comment.CN_FB_COMMENT_ID,
  369. tb_grp_comment.CN_PARENT_COMMENT_ID,
  370. };
  371. List<WhereNode> wnCommentQuery = new List<WhereNode>
  372. {
  373. new WhereNode(tb_grp_comment.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), article_uid),
  374. new WhereNode(tb_grp_comment.CN_STATUS, WhereNode.EColumnOperation.EOT_NEQ, typeof(tb_grp_comment), (int)FbHelper.CommentStatus.TransferOrder),
  375. new WhereNode(tb_grp_comment.CN_STATUS_FLAG, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), BLWording.STATUS_FLAG_ON)
  376. };
  377. qjeArticleToProduct.wherecols = new WhereNode(WhereNode.ENodeOperation.ENO_AND, wnCommentQuery.ToArray());
  378. // Sort
  379. List<Tuple<QueryJsonElement, string, string>> qjeArticleToProductOrder = new List<Tuple<QueryJsonElement, string, string>>() {
  380. Tuple.Create(qjeArticle, tb_grp_comment.CN_COMMENT_TIME, BLWording.ORDER_ASC)
  381. };
  382. qjeArticleToProduct.ordercols = qjeArticleToProductOrder;
  383. lBlocks.Add(qjeArticleToProduct);
  384. QueryJsonElement qjeMember = lBlocks.GetInst();
  385. qjeMember.table = tb_meb_member.TABLENAME;
  386. qjeMember.jointable = qjeArticleToProduct;
  387. qjeMember.jointype = QueryJsonElement.LEFT_JOIN;
  388. qjeMember.joincols = new Dictionary<string, string>() {
  389. { tb_meb_member.CN_GROUP_USER_ID, tb_grp_comment.CN_GROUP_USER_ID }};
  390. qjeMember.displaycols = new List<string>()
  391. {
  392. tb_meb_member.CN_NAME,
  393. tb_meb_member.CN_FB_PIC,
  394. tb_meb_member.CN_STATUS_FLAG,
  395. tb_meb_member.CN_GROUP_ID,
  396. tb_meb_member.CN_DEFAULT_BRANCH
  397. };
  398. qjeMember.aliascols = new Dictionary<string, List<string>>
  399. {
  400. { tb_meb_member.CN_UID, new List<string>() { "member_uid" } }
  401. };
  402. List<WhereNode> wnMemberQuery = new List<WhereNode>
  403. {
  404. new WhereNode(tb_meb_member.CN_GROUP_ID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_meb_member), articles[0].fb_group_id),
  405. new WhereNode(tb_meb_member.CN_GROUP_ID, WhereNode.EColumnOperation.EOT_ISNULL, typeof(tb_meb_member))
  406. };
  407. qjeMember.wherecols = new WhereNode(WhereNode.ENodeOperation.ENO_OR, wnMemberQuery.ToArray());
  408. lBlocks.Add(qjeMember);
  409. sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
  410. if (sMsg != null)
  411. {
  412. break;
  413. }
  414. ai = ArsenalDBMgr.GetInst(cRes);
  415. List<CommentViewModel> qdArticle = ai.RunQueryList<CommentViewModel>(cRes);
  416. var parentData = qdArticle.GroupBy(x => x.parent_comment_id);
  417. if (!cRes.IsSuccess)
  418. {
  419. sMsg = cRes.LastErrorCode;
  420. break;
  421. }
  422. crmRes = new CSuccessResponseMessage(null, i_crmInput);
  423. // 填寫回傳
  424. crmRes.param.Add(BLWording.DATA, parentData);
  425. crmRes.param.Add("post_status", articles);
  426. }
  427. while (false);
  428. }
  429. catch (Exception ex)
  430. {
  431. sMsg = $"{nameof(ReadComment)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}.";
  432. #if DEBUG
  433. System.Diagnostics.Debug.WriteLine(sMsg);
  434. #endif
  435. }
  436. if (sMsg != null)
  437. {
  438. crmRes = new CErrorResponseMessage(sMsg, null);
  439. }
  440. return crmRes;
  441. }
  442. public CResponseMessage DeleteComment(CRequestMessage i_crmInput)
  443. {
  444. string sMsg = null;
  445. CResponseMessage crmRes = null;
  446. List<Command> lcCmds = new List<Command>();
  447. try
  448. {
  449. do
  450. {
  451. sMsg = getCommonParameter(i_crmInput, BLWording.DEL_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession);
  452. if (sMsg != null)
  453. {
  454. break;
  455. }
  456. if (jaDataArray.Count != 1 || jaDataArray[0] == null)
  457. {
  458. sMsg = MessageWording.PARAM_NOT_EXPECTED;
  459. break;
  460. }
  461. var uid = jaDataArray[0][BLWording.WHEREDATA][BLWording.UID].ToString();
  462. tb_grp_comment u = new tb_grp_comment()
  463. {
  464. status_flag = BLWording.STATUS_FLAG_OFF
  465. };
  466. Command c = Command.SetupUpdateCmd(u, new WhereNode(tb_grp_comment.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), uid));
  467. lcCmds.Add(c);
  468. ArsenalInterface ai = ArsenalDBMgr.GetInst(lcCmds[0], GetDefaultSystemColumnInfo());
  469. ai.RunEditCmds(lcCmds);
  470. sMsg = GetLastErrorCode(lcCmds);
  471. if (sMsg != null)
  472. {
  473. crmRes = new CErrorResponseMessage(sMsg, null);
  474. }
  475. else
  476. {
  477. crmRes = new CSuccessResponseMessage(null, i_crmInput);
  478. }
  479. }
  480. while (false);
  481. }
  482. catch (Exception ex)
  483. {
  484. sMsg = $"{nameof(DeleteComment)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}.";
  485. #if DEBUG
  486. System.Diagnostics.Debug.WriteLine(sMsg);
  487. #endif
  488. }
  489. if (sMsg != null)
  490. {
  491. crmRes = new CErrorResponseMessage(sMsg, null);
  492. }
  493. return crmRes;
  494. }
  495. public CResponseMessage CreateComment(CRequestMessage i_crmInput)
  496. {
  497. string sMsg = null;
  498. CResponseMessage crmRes = null;
  499. try
  500. {
  501. do
  502. {
  503. sMsg = getCommonParameter(i_crmInput, BLWording.ADD_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession);
  504. if (sMsg != null)
  505. {
  506. break;
  507. }
  508. var article = jaDataArray[0][BLWording.DATA]["article_data"].ToObject<tb_grp_article>();
  509. var member = jaDataArray[0][BLWording.DATA]["member_data"].ToObject<tb_meb_member>();
  510. var comment = jaDataArray[0][BLWording.DATA][BLWording.DATA].ToString();
  511. List<Command> lCmds = new List<Command>();
  512. var comments = new List<tb_grp_comment>();
  513. // 取回該社團可以取貨的地點
  514. var branches = GetBranches(article.group_uid).Select(x => x.branch_name).ToList();
  515. var products = GetProducts(article.uid);
  516. var productInfos = GetProductInfos(products);
  517. Logger.Info($"開始解析貼文 文章ID: {article.uid} 設定: {JsonConvert.SerializeObject(productInfos)}");
  518. var parser = new GroupBuyParser.GroupBuyParser
  519. {
  520. Settings = new GroupBuyParser.ParserSettings
  521. {
  522. Products = productInfos,
  523. Branches = branches
  524. }
  525. };
  526. if(member == null)
  527. {
  528. return new CErrorResponseMessage("沒有設定會員名稱", null);
  529. }
  530. // 如果取不回fb_id(使用者沒有允許應用程式查看貼文)仍要處理
  531. string group_user_id = member.group_user_id;
  532. string json = "";
  533. int status = 0;
  534. var parseData = parser.Parse(comment);
  535. if (parseData.Success)
  536. {
  537. bool isProductCorrect = true;
  538. foreach (var product in parseData.Product)
  539. {
  540. if (product.Name == "I")
  541. {
  542. isProductCorrect = false;
  543. break;
  544. }
  545. }
  546. if (isProductCorrect) // 名稱有I 不Insert進資料庫
  547. {
  548. json = JsonConvert.SerializeObject(parseData.Product);
  549. status = (int)CommentStatus.OK;
  550. }
  551. else
  552. {
  553. status = (int)CommentStatus.InvalidFormat;
  554. }
  555. }
  556. else
  557. {
  558. status = (int)CommentStatus.InvalidFormat;
  559. // 增加log紀錄確認解析失敗的原因
  560. Logger.Info($"解析貼文失敗 姓名: {member.name} 內容: {comment} 原因: {parseData.ErrorMessage} 貼文ID: {article.uid}");
  561. }
  562. if (string.IsNullOrEmpty(group_user_id))
  563. {
  564. status = (int)CommentStatus.UnknownMember;
  565. }
  566. tb_grp_comment cNew = new tb_grp_comment
  567. {
  568. uid = Guid.NewGuid().ToString(),
  569. article_uid = article.uid,
  570. origin_comment = comment,
  571. comment = json,
  572. group_user_id = group_user_id,
  573. comment_time = DateTime.Now,
  574. fb_comment_id = null,
  575. status = status,
  576. user_name = member.name,
  577. user_picture = member.fb_pic
  578. };
  579. comments.Add(cNew);
  580. // 沒有任何留言就不處理
  581. if (comments.Count == 0)
  582. {
  583. return null;
  584. }
  585. lCmds.AddRange(comments.Select(x => Command.SetupInsertCmd(x)));
  586. var ai = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo());
  587. ai.RunEditCmds(lCmds);
  588. sMsg = GetLastErrorCode(lCmds);
  589. if (sMsg != null)
  590. {
  591. crmRes = new CErrorResponseMessage(sMsg, null);
  592. }
  593. else
  594. {
  595. crmRes = new CSuccessResponseMessage(null, i_crmInput);
  596. }
  597. }
  598. while (false);
  599. }
  600. catch (Exception ex)
  601. {
  602. sMsg = $"{nameof(DeleteComment)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}.";
  603. #if DEBUG
  604. System.Diagnostics.Debug.WriteLine(sMsg);
  605. #endif
  606. Logger.Error(ex.ToString());
  607. }
  608. if (sMsg != null)
  609. {
  610. crmRes = new CErrorResponseMessage(sMsg, null);
  611. }
  612. return crmRes;
  613. }
  614. /// <summary>
  615. /// 參考 CreateComment
  616. /// </summary>
  617. /// <param name="i_crmInput"></param>
  618. /// <returns></returns>
  619. public CResponseMessage ImportComment(CRequestMessage i_crmInput)
  620. {
  621. string sMsg = null;
  622. CResponseMessage crmRes = null;
  623. var logInfos = new StringBuilder();
  624. try
  625. {
  626. do
  627. {
  628. sMsg = getCommonParameter(i_crmInput, BLWording.ADD_MASTER, out JArray jaDataArray, out tb_sys_session sUserSession);
  629. if (sMsg != null) break;
  630. var article = jaDataArray[0][BLWording.DATA]["article_data"].ToObject<tb_grp_article>();
  631. var comments = jaDataArray[0][BLWording.DATA][BLWording.DATA].ToString().Split('\n');
  632. var tb_grp_comment_List = new List<tb_grp_comment>();
  633. var misMatchMembers = new StringBuilder();
  634. List<Command> lCmds = new List<Command>();
  635. // 取回該社團可以取貨的地點
  636. var branches = GetBranches(article.group_uid);
  637. var products = GetProducts(article.uid);
  638. var members = GetMembers(article.group_uid);
  639. var productInfos = GetProductInfos(products);// 將名稱以['A', 'B'...]這樣依序產生,如果產品有3個,就要放入['A', 'B', 'C']
  640. logInfos.AppendLine($"{nameof(ImportComment)} 開始解析貼文留言 文章ID: {article.uid} 設定: {JsonConvert.SerializeObject(productInfos)}");
  641. var parser = new GroupBuyParser.GroupBuyParser
  642. {
  643. Settings = new GroupBuyParser.ParserSettings
  644. {
  645. Products = productInfos,
  646. Branches = branches.Select(x => x.branch_name).ToList()
  647. }
  648. };
  649. // 去除匯入留言前面的空白行
  650. var blankLineCount = 0;
  651. foreach (var comment in comments)
  652. {
  653. if (!string.IsNullOrWhiteSpace(comment)) break;
  654. blankLineCount++;
  655. }
  656. comments = comments[(blankLineCount)..(comments.Count())];
  657. var sortMillsecond = 0;// 累加毫秒數, 用來排序正確留言順序
  658. List<(string member, string orders)> membersAndOrders = new List<(string, string)>();
  659. // Parse comment
  660. for (int i = 1; i < comments.Length; i++)
  661. {
  662. var parserData = ParserComment(parser, comments[i], branches.First().branch_name);
  663. if (!parserData.Success) continue;
  664. string orders = parserData.Text;
  665. string member = comments[i - 1];// 往上抓客人名稱
  666. // 往下抓可能有多行的訂單
  667. for (++i; i < comments.Length; i++)
  668. {
  669. parserData = ParserComment(parser, comments[i], branches.First().branch_name);
  670. if (!parserData.Success) break;
  671. orders += parserData.Text;
  672. }
  673. membersAndOrders.Add((member, orders));
  674. }
  675. // Match member & default branch
  676. foreach (var memberAndOrders in membersAndOrders)
  677. {
  678. var member = members.Find(item => item.name == memberAndOrders.member);
  679. if (member == null)// 沒匹配的會員名稱
  680. {
  681. misMatchMembers.AppendLine($"[{memberAndOrders.orders}] ");
  682. continue;
  683. }
  684. int status = (int)CommentStatus.UnknownMember;
  685. var json = "";
  686. var parseData = ParserComment(parser, memberAndOrders.orders, $"{branches.Find(x => x.uid == member.default_branch)?.branch_name}");// 匯入留言後面加上預設分店中文名稱
  687. if (parseData.Success)
  688. {
  689. bool isProductCorrect = true;
  690. isProductCorrect = parseData.Product.Find(x => x.Name == "I") == null ? true : false;
  691. if (isProductCorrect) // 名稱有I 不Insert進資料庫
  692. {
  693. var Branch = branches.Find(item => item.uid == member.default_branch)?.branch_name;// Parser解析Branch會為null, 經討論後都放預設分店
  694. parseData.Product.ForEach(item => item.Branch = Branch);
  695. json = JsonConvert.SerializeObject(parseData.Product);
  696. status = (int)CommentStatus.OK;
  697. }
  698. else
  699. {
  700. status = (int)CommentStatus.InvalidFormat;
  701. }
  702. }
  703. else
  704. {
  705. status = (int)CommentStatus.InvalidFormat;
  706. logInfos.AppendLine($"{nameof(ImportComment)} 解析貼文失敗 內容: {memberAndOrders.orders} 原因: {parseData.ErrorMessage} 貼文ID: {article.uid}");
  707. }
  708. tb_grp_comment cNew = new tb_grp_comment
  709. {
  710. uid = Guid.NewGuid().ToString(),
  711. article_uid = article.uid,
  712. origin_comment = memberAndOrders.orders,
  713. comment = string.IsNullOrWhiteSpace(json) ? "" : json,
  714. group_user_id = member.group_user_id,
  715. comment_time = DateTime.Now.AddMilliseconds(sortMillsecond++),
  716. fb_comment_id = null,
  717. status = status,
  718. user_name = member.name,
  719. user_picture = member.fb_pic,
  720. };
  721. tb_grp_comment_List.Add(cNew);
  722. }
  723. if (tb_grp_comment_List.Count == 0)
  724. {
  725. sMsg = "沒有要匯入的留言";
  726. break;
  727. }
  728. lCmds.AddRange(tb_grp_comment_List.Select(x => Command.SetupInsertCmd(x)));
  729. var ai2 = ArsenalDBMgr.GetInst(lCmds[0], GetDefaultSystemColumnInfo());
  730. ai2.RunEditCmds(lCmds);
  731. sMsg = GetLastErrorCode(lCmds);
  732. if (sMsg != null)
  733. {
  734. break;
  735. }
  736. if (!string.IsNullOrWhiteSpace(misMatchMembers.ToString()))
  737. {
  738. misMatchMembers.Insert(0, "以下下單會員資料查詢不到, 不匯入系統: ");
  739. }
  740. crmRes = new CSuccessResponseMessage(misMatchMembers.Insert(0, "匯入成功 ").ToString(), i_crmInput);
  741. }
  742. while (false);
  743. }
  744. catch(Exception ex)
  745. {
  746. sMsg = $"{nameof(DeleteComment)} unknwon exception. i_crmInput={JsonConvert.SerializeObject(i_crmInput)}.";
  747. #if DEBUG
  748. System.Diagnostics.Debug.WriteLine(sMsg);
  749. #endif
  750. Logger.Error(ex.ToString());
  751. }
  752. finally
  753. {
  754. Logger.Info(logInfos.ToString());
  755. }
  756. if (sMsg != null)
  757. {
  758. crmRes = new CErrorResponseMessage(sMsg, null);
  759. }
  760. return crmRes;
  761. }
  762. private List<tb_prd_article2product> GetProducts(string article_uid)
  763. {
  764. /**開始組指令**/
  765. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  766. QueryJsonElement qjeArticleToProduct = lBlocks.GetInst();
  767. qjeArticleToProduct.table = tb_prd_article2product.TABLENAME;
  768. qjeArticleToProduct.displaycols = new List<string>()
  769. {
  770. tb_prd_article2product.CN_UID,
  771. tb_prd_article2product.CN_NAME,
  772. tb_prd_article2product.CN_PRICE,
  773. tb_prd_article2product.CN_SEQ,
  774. tb_prd_article2product.CN_SPECIFICATION
  775. };
  776. qjeArticleToProduct.wherecols = new WhereNode(tb_prd_article2product.CN_ARTICLE_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_prd_article2product), article_uid);
  777. lBlocks.Add(qjeArticleToProduct);
  778. QueryJsonElement qjeProduct = lBlocks.GetInst();
  779. qjeProduct.table = tb_prd_product.TABLENAME;
  780. qjeProduct.jointable = qjeArticleToProduct;
  781. qjeProduct.joincols = new Dictionary<string, string>()
  782. {
  783. { tb_prd_product.CN_UID, tb_prd_article2product.CN_PRD_UID }
  784. };
  785. lBlocks.Add(qjeProduct);
  786. var sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
  787. var ai = ArsenalDBMgr.GetInst(cRes);
  788. List<tb_prd_article2product> data = ai.RunQueryList<tb_prd_article2product>(cRes);
  789. return data.ToList();
  790. }
  791. private List<tb_grp_branch> GetBranches(string group_uid)
  792. {
  793. tb_grp_branch cDisplay = new tb_grp_branch();
  794. cDisplay.SetFullDirty();
  795. var whereNode = new WhereNode(tb_grp_branch.CN_GROUP_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_grp_comment), group_uid);
  796. var cSelect = Command.SetupSelectCmd(cDisplay, whereNode);
  797. var ai = ArsenalDBMgr.GetInst(cSelect);
  798. var data = ai.RunQueryList<tb_grp_branch>(cSelect);
  799. return data;
  800. }
  801. public List<tb_meb_member> GetMembers(string group_uid_)
  802. {
  803. QueryJsonElementCollection lBlocks = new QueryJsonElementCollection();
  804. QueryJsonElement qjeMember = lBlocks.GetInst();
  805. qjeMember.table = tb_meb_member.TABLENAME;
  806. qjeMember.displaycols = new List<string>()
  807. {
  808. tb_meb_member.CN_UID,
  809. tb_meb_member.CN_NAME,
  810. tb_meb_member.CN_GROUP_ID,
  811. tb_meb_member.CN_DEFAULT_BRANCH,
  812. tb_meb_member.CN_GROUP_USER_ID,
  813. tb_meb_member.CN_FB_PIC
  814. };
  815. //qjeMember.wherecols = new WhereNode(tb_meb_member.CN_GROUP_ID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_meb_member), article.group_uid);
  816. lBlocks.Add(qjeMember);
  817. QueryJsonElement qjeProduct = lBlocks.GetInst();
  818. qjeProduct.table = tb_grp_group.TABLENAME;
  819. qjeProduct.jointable = qjeMember;
  820. qjeProduct.joincols = new Dictionary<string, string>()
  821. {
  822. { tb_grp_group.CN_FB_GROUP_ID, tb_meb_member.CN_GROUP_ID }
  823. };
  824. qjeProduct.wherecols = new WhereNode(tb_grp_group.CN_UID, WhereNode.EColumnOperation.EOT_EQ, typeof(tb_meb_member), group_uid_);
  825. lBlocks.Add(qjeProduct);
  826. var sMsg = MakeSelectJoinByBlocks(lBlocks, out Command cRes);
  827. if (!string.IsNullOrWhiteSpace(sMsg))
  828. {
  829. throw new Exception(sMsg);
  830. }
  831. var ai = ArsenalDBMgr.GetInst(cRes);
  832. return ai.RunQueryList<tb_meb_member>(cRes);
  833. }
  834. /// <summary>
  835. /// 使用原本解析器, 加上隨意的預設分店防止錯誤訊息跳出
  836. /// </summary>
  837. /// <param name="branch_name"></param>
  838. /// <param name="comment"></param>
  839. /// <param name="parser"></param>
  840. /// <returns></returns>
  841. private GroupBuyParser.ParserData ParserComment(GroupBuyParser.GroupBuyParser parser, string comment, string branch_name)
  842. {
  843. var parserData = new GroupBuyParser.ParserData() { DefaultBranch = branch_name };
  844. parserData.Text = comment;
  845. parser.Parse(parserData);
  846. return parserData;
  847. }
  848. /// <summary>
  849. /// 條列A~Z項目時要忽略I項目, Example: ABCDEFGH >>> JKL, 屬於客製化設計
  850. /// </summary>
  851. /// <param name="products"></param>
  852. /// <returns></returns>
  853. private List<GroupBuyParser.ProductInfo> GetProductInfos(List<tb_prd_article2product> products)
  854. {
  855. return products.Select((x, i) => new GroupBuyParser.ProductInfo
  856. {
  857. Name = ((char)('A' + (i < 8 ? i : i + 1))).ToString(),// Jump over product items [ I ], Name = ABCDEFGHJ.....etc
  858. Specifications = string.IsNullOrEmpty(x.specification) ? null : x.specification.Split(',', StringSplitOptions.RemoveEmptyEntries)
  859. }).ToList();
  860. }
  861. }
  862. }