ArticleBusinessImpl.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. using Common;
  2. using Common.Constant;
  3. using Common.Http;
  4. using Esim.Apis.Singleton;
  5. using Database.Database;
  6. using log4net;
  7. using Microsoft.AspNetCore.Mvc;
  8. using Newtonsoft.Json;
  9. namespace Esim.Apis.Business
  10. {
  11. public class ArticleBusinessImpl : IArticleBusiness
  12. {
  13. private static readonly log4net.ILog log = log4net.LogManager.GetLogger(
  14. typeof(ArticleBusinessImpl)
  15. );
  16. private ModelContext dbContext;
  17. IConfiguration configuration;
  18. public ArticleBusinessImpl(ModelContext _dbContext, IConfiguration _configuration)
  19. {
  20. dbContext = _dbContext;
  21. configuration = _configuration;
  22. }
  23. private string GetParameter(string key)
  24. {
  25. return configuration.GetSection(key).Value ?? "";
  26. }
  27. /// <summary>
  28. /// Load article categories with pagination
  29. /// </summary>
  30. public async Task<IActionResult> ArticleCategory(HttpRequest httpRequest, ArticleCategoryReq request)
  31. {
  32. var url = httpRequest.Path;
  33. var json = JsonConvert.SerializeObject(request);
  34. log.Debug("URL: " + url + " => Request: " + json);
  35. try
  36. {
  37. string lang = (request.lang ?? "lo").ToLower();
  38. int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
  39. int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;
  40. // Query categories
  41. var query = dbContext.ArticleCategories
  42. .Where(c => c.Status == true);
  43. // Filter by parent category
  44. if (request.parentId.HasValue)
  45. {
  46. query = query.Where(c => c.ParentId == request.parentId);
  47. }
  48. else
  49. {
  50. query = query.Where(c => c.ParentId == null); // Root categories
  51. }
  52. // Get total count for pagination
  53. int totalCount = query.Count();
  54. int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
  55. // Apply pagination and ordering
  56. var categories = query
  57. .OrderBy(c => c.DisplayOrder)
  58. .ThenBy(c => c.Id)
  59. .Skip(pageNumber * pageSize)
  60. .Take(pageSize)
  61. .Select(c => new
  62. {
  63. c.Id,
  64. categoryName = lang == "en"
  65. ? (c.CategoryNameEn ?? c.CategoryName)
  66. : (c.CategoryNameLo ?? c.CategoryName),
  67. c.CategorySlug,
  68. description = lang == "en"
  69. ? (c.DescriptionEn ?? c.Description)
  70. : (c.DescriptionLo ?? c.Description),
  71. c.IconUrl,
  72. c.ParentId,
  73. c.DisplayOrder
  74. })
  75. .ToList();
  76. return DotnetLib.Http.HttpResponse.BuildResponse(
  77. log,
  78. url,
  79. json,
  80. CommonErrorCode.Success,
  81. ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
  82. new
  83. {
  84. items = categories,
  85. pagination = new
  86. {
  87. pageNumber,
  88. pageSize,
  89. totalCount,
  90. totalPages
  91. }
  92. }
  93. );
  94. }
  95. catch (Exception exception)
  96. {
  97. log.Error("Exception: ", exception);
  98. }
  99. return DotnetLib.Http.HttpResponse.BuildResponse(
  100. log,
  101. url,
  102. json,
  103. CommonErrorCode.SystemError,
  104. ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
  105. new { }
  106. );
  107. }
  108. /// <summary>
  109. /// Load articles with pagination and filters
  110. /// </summary>
  111. public async Task<IActionResult> ArticleLoad(HttpRequest httpRequest, ArticleLoadReq request)
  112. {
  113. var url = httpRequest.Path;
  114. var json = JsonConvert.SerializeObject(request);
  115. log.Debug("URL: " + url + " => Request: " + json);
  116. try
  117. {
  118. string lang = (request.lang ?? "lo").ToLower();
  119. int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
  120. int pageSize = request.pageSize <= 0 ? 10 : request.pageSize;
  121. // If slug is provided, return single article detail
  122. if (!string.IsNullOrEmpty(request.slug))
  123. {
  124. var article = dbContext.Articles
  125. .Where(a => a.Slug == request.slug && a.Status == true)
  126. .Select(a => new
  127. {
  128. a.Id,
  129. title = lang == "en"
  130. ? (a.TitleEn ?? a.Title)
  131. : (a.TitleLo ?? a.Title),
  132. a.Slug,
  133. summary = lang == "en"
  134. ? (a.SummaryEn ?? a.Summary)
  135. : (a.SummaryLo ?? a.Summary),
  136. content = lang == "en"
  137. ? (a.ContentEn ?? a.Content)
  138. : (a.ContentLo ?? a.Content),
  139. a.ThumbnailUrl,
  140. a.CoverImageUrl,
  141. metaDescription = lang == "en"
  142. ? (a.MetaDescriptionEn ?? a.MetaDescription)
  143. : (a.MetaDescriptionLo ?? a.MetaDescription),
  144. a.MetaKeywords,
  145. a.CategoryId,
  146. a.ViewCount,
  147. a.IsFeatured,
  148. a.PublishedDate,
  149. a.CreatedDate
  150. })
  151. .FirstOrDefault();
  152. if (article == null)
  153. {
  154. return DotnetLib.Http.HttpResponse.BuildResponse(
  155. log,
  156. url,
  157. json,
  158. CommonErrorCode.Error,
  159. ConfigManager.Instance.GetConfigWebValue("ARTICLE_NOT_FOUND", lang),
  160. new { }
  161. );
  162. }
  163. // Increment view count
  164. var articleEntity = dbContext.Articles.FirstOrDefault(a => a.Slug == request.slug);
  165. if (articleEntity != null)
  166. {
  167. articleEntity.ViewCount = (articleEntity.ViewCount ?? 0) + 1;
  168. await dbContext.SaveChangesAsync();
  169. }
  170. return DotnetLib.Http.HttpResponse.BuildResponse(
  171. log,
  172. url,
  173. json,
  174. CommonErrorCode.Success,
  175. ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
  176. new { article }
  177. );
  178. }
  179. // Query articles list
  180. var query = dbContext.Articles
  181. .Where(a => a.Status == true);
  182. // Filter by category
  183. if (request.categoryId.HasValue)
  184. {
  185. query = query.Where(a => a.CategoryId == request.categoryId);
  186. }
  187. // Filter by featured
  188. if (request.isFeatured.HasValue && request.isFeatured.Value)
  189. {
  190. query = query.Where(a => a.IsFeatured == true);
  191. }
  192. // Get total count for pagination
  193. int totalCount = query.Count();
  194. int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
  195. // Apply pagination and ordering (pinned first, then by published date)
  196. var articles = query
  197. .OrderByDescending(a => a.IsPinned)
  198. .ThenByDescending(a => a.PublishedDate)
  199. .ThenByDescending(a => a.CreatedDate)
  200. .Skip(pageNumber * pageSize)
  201. .Take(pageSize)
  202. .Select(a => new
  203. {
  204. a.Id,
  205. title = lang == "en"
  206. ? (a.TitleEn ?? a.Title)
  207. : (a.TitleLo ?? a.Title),
  208. a.Slug,
  209. summary = lang == "en"
  210. ? (a.SummaryEn ?? a.Summary)
  211. : (a.SummaryLo ?? a.Summary),
  212. a.ThumbnailUrl,
  213. a.CategoryId,
  214. a.ViewCount,
  215. a.IsFeatured,
  216. a.IsPinned,
  217. a.PublishedDate
  218. })
  219. .ToList();
  220. return DotnetLib.Http.HttpResponse.BuildResponse(
  221. log,
  222. url,
  223. json,
  224. CommonErrorCode.Success,
  225. ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
  226. new
  227. {
  228. items = articles,
  229. pagination = new
  230. {
  231. pageNumber,
  232. pageSize,
  233. totalCount,
  234. totalPages
  235. }
  236. }
  237. );
  238. }
  239. catch (Exception exception)
  240. {
  241. log.Error("Exception: ", exception);
  242. }
  243. return DotnetLib.Http.HttpResponse.BuildResponse(
  244. log,
  245. url,
  246. json,
  247. CommonErrorCode.SystemError,
  248. ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
  249. new { }
  250. );
  251. }
  252. }
  253. }