AppendixNotificationPlugin.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. using GreenTree.Nachtragsmanagement.Core.Plugins;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Web;
  6. using GreenTree.Nachtragsmanagement.Core.Domain.Misc;
  7. using GreenTree.Nachtragsmanagement.Services.User;
  8. using GreenTree.Nachtragsmanagement.Services.Configuration;
  9. using GreenTree.Nachtragsmanagement.Services.Appendix;
  10. using GreenTree.Nachtragsmanagement.Core.Domain.Appendix;
  11. using System.Net.Mail;
  12. using System.Net;
  13. using System.Globalization;
  14. using Quartz;
  15. namespace GreenTree.Nachtragsmanagement.Web.Implementations
  16. {
  17. public class AppendixNotificationPlugin : INotificationPlugin, IJob
  18. {
  19. #region Services
  20. private readonly IUserService _userService;
  21. private readonly IConfigurationService _configurationService;
  22. private readonly IAppendixService _appendixService;
  23. #endregion
  24. #region Properties
  25. /// <summary>
  26. /// Id
  27. /// </summary>
  28. public Guid Id
  29. {
  30. get
  31. {
  32. return Guid.Parse("E99CA4A1-B3A9-4AA6-BBAD-9254CEED0A45");
  33. }
  34. }
  35. /// <summary>
  36. /// System name
  37. /// </summary>
  38. public string SystemName
  39. {
  40. get
  41. {
  42. return "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin";
  43. }
  44. }
  45. /// <summary>
  46. /// List of available notification jobs
  47. /// </summary>
  48. public List<NotificationJob> AvailableNotificationJobs
  49. {
  50. get
  51. {
  52. return new List<NotificationJob>
  53. {
  54. new NotificationJob
  55. (
  56. Guid.Parse("2F3642E0-259D-466D-8629-CB279F740313"),
  57. "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate",
  58. "Verhandlungstermine überprüfen",
  59. "Erstellt automatisch Benachrichtigungen für Nachträge, die nach 8 Wochen nach Einreichung noch keinen " +
  60. "Verhandlungstermin gesetzt haben und ändert den entsprechenden Status ab"
  61. ),
  62. new NotificationJob
  63. (
  64. Guid.Parse("2E46B32A-1912-47F9-951E-C8188AA9BA50"),
  65. "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationProtocol",
  66. "Verhandlungsprotokolle überprüfen",
  67. "Erstellt automatisch Benachrichtigungen für Nachträge, die nach 2 Wochen zwar verhandelt sind, " +
  68. "jedoch noch kein Protokoll aufweisen."
  69. )
  70. };
  71. }
  72. }
  73. /// <summary>
  74. /// Displayed name
  75. /// </summary>
  76. public string Name
  77. {
  78. get
  79. {
  80. return "Nachtragsbenachrichtigung";
  81. }
  82. }
  83. /// <summary>
  84. /// Further description on how this plugin works
  85. /// </summary>
  86. public string Description
  87. {
  88. get
  89. {
  90. return
  91. "Erstellt automatisch Benachrichtigungen für Nachträge, die nach 8 Wochen nach Einreichung noch keinen " +
  92. "Verhandlungstermin gesetzt haben und ändert den entsprechenden Status ab. Außerdem werden alle 2 Wochen " +
  93. "Benachrichtigungen für Nachträge erstellt, die zwar verhandelt sind, jedoch noch kein Protokoll aufweisen.";
  94. }
  95. }
  96. #endregion
  97. /// <summary>
  98. /// Initializes a new instance of the AppendixNotificationPlugin class
  99. /// </summary>
  100. public AppendixNotificationPlugin() { }
  101. /// <summary>
  102. /// Initializes a new instance of the AppendixNotificationPlugin class
  103. /// </summary>
  104. public AppendixNotificationPlugin(
  105. IUserService userService,
  106. IConfigurationService configurationService,
  107. IAppendixService appendixService)
  108. {
  109. _userService = userService;
  110. _configurationService = configurationService;
  111. _appendixService = appendixService;
  112. }
  113. #region Quartz implmentation
  114. /// <summary>
  115. /// Executes the current job
  116. /// </summary>
  117. /// <param name="context"></param>
  118. public void Execute(IJobExecutionContext context)
  119. {
  120. if (!context.JobDetail.JobDataMap.ContainsKey("MailNotifications"))
  121. return;
  122. var mailNotifications = context.JobDetail.JobDataMap.Get("MailNotifications") as IEnumerable<MailNotification>;
  123. if (mailNotifications == null) return;
  124. ProcessNotifications(mailNotifications);
  125. }
  126. #endregion
  127. #region Processing
  128. /// <summary>
  129. /// Process all mail notifications registered for that plugin
  130. /// </summary>
  131. /// <param name="mailNotifications">The notifications which shall be generated.</param>
  132. public void ProcessNotifications(IEnumerable<MailNotification> mailNotifications)
  133. {
  134. if (mailNotifications == null || !mailNotifications.Any()) return;
  135. foreach (var notification in mailNotifications)
  136. {
  137. switch (notification.NotificationJobSystemName)
  138. {
  139. case "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate":
  140. {
  141. ProcessNegotiationDateNotification(notification);
  142. }
  143. break;
  144. case "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationProtocol":
  145. {
  146. ProcessNegotiationProtocolNotification(notification);
  147. }
  148. break;
  149. default:
  150. continue;
  151. }
  152. }
  153. }
  154. /// <summary>
  155. /// Sets the corresponding status for appendices which offering date is older than N weeks and notifies
  156. /// the correspondig recipients
  157. /// </summary>
  158. /// <param name="mailNotification">The notification which shall be generated.</param>
  159. private void ProcessNegotiationDateNotification(MailNotification mailNotification)
  160. {
  161. var ageDays = _configurationService.TryGetConfigItemValue<int>(
  162. "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate.AgeDays", 56);
  163. var stateConditionId = _configurationService.TryGetConfigItemValue<int>(
  164. "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate.StateCondition", 1);
  165. var stateSetId = _configurationService.TryGetConfigItemValue<int>(
  166. "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate.StateSet", 2);
  167. var interval = _configurationService.TryGetConfigItemValue<int>(
  168. "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationDate.Interval", 2);
  169. interval = interval == 0
  170. ? 1
  171. : interval;
  172. var appendices = _appendixService.GetAllAppendices()
  173. .Where(a => a.OfferingDate.HasValue &&
  174. (DateTime.Now - a.OfferingDate).Value.Days >= ageDays &&
  175. a.StateId == stateConditionId &&
  176. a.NegotiationDate == null)
  177. .ToList();
  178. var currentCalendarWeek = GetCalendarWeek(DateTime.Now);
  179. appendices = appendices
  180. .Where(a => ((currentCalendarWeek - GetCalendarWeek(a.OfferingDate.Value) % interval == 0)))
  181. .ToList();
  182. if (appendices.Any())
  183. {
  184. var mailBody = GenerateNegotiationDateMailBody(appendices);
  185. foreach (var appendix in appendices)
  186. {
  187. appendix.StateId = stateSetId;
  188. _appendixService.UpdateAppendix(appendix);
  189. }
  190. SendNotification(mailNotification, "Autom. Übersicht nicht verhandelte Nachträge", mailBody);
  191. }
  192. }
  193. /// <summary>
  194. /// Sets the corresponding status for appendices which negotiation date is older than N weeks and notifies
  195. /// the correspondig recipients
  196. /// </summary>
  197. /// <param name="mailNotification">The notification which shall be generated.</param>
  198. private void ProcessNegotiationProtocolNotification(MailNotification mailNotification)
  199. {
  200. var ageDays = _configurationService.TryGetConfigItemValue<int>(
  201. "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationProtocol.AgeDays", 14);
  202. var stateConditionId = _configurationService.TryGetConfigItemValue<int>(
  203. "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationProtocol.StateCondition", 3);
  204. var interval = _configurationService.TryGetConfigItemValue<int>(
  205. "GreenTree.Nachtragsmanagement.AppendixNotificationPlugin.ProcessNegotiationProtocol.Interval", 2);
  206. interval = interval == 0
  207. ? 1
  208. : interval;
  209. var appendices = _appendixService.GetAllAppendices()
  210. .Where(a => a.NegotiationDate.HasValue &&
  211. (DateTime.Now - a.NegotiationDate).Value.Days >= ageDays &&
  212. a.StateId == stateConditionId)
  213. .ToList();
  214. var currentCalendarWeek = GetCalendarWeek(DateTime.Now);
  215. appendices = appendices
  216. .Where(a => ((currentCalendarWeek - GetCalendarWeek(a.OfferingDate.Value) % interval == 0)))
  217. .ToList();
  218. if (appendices.Any())
  219. {
  220. var mailBody = GenerateNegotiationProtocolMailBody(appendices);
  221. SendNotification(mailNotification, "Autom. Übersicht verhandelte Nachträge o. Protokoll", mailBody);
  222. }
  223. }
  224. #endregion
  225. #region Mail body generation
  226. /// <summary>
  227. /// Generates a mail body with a list of all appendices with a offering date later than N weeks
  228. /// </summary>
  229. /// <param name="appendices">Appendices matching that criteria.</param>
  230. public string GenerateNegotiationDateMailBody(IEnumerable<Appendix> appendices)
  231. {
  232. var template =
  233. "<html>" +
  234. " <body>" +
  235. " <h3>Übersicht \"Nicht verhandelte Nachträge\"</h3>" +
  236. " <p>Folgende Nachträge haben ein Einreichdatum älter als 8 Wochen, jedoch noch kein Verhandlungstermin" +
  237. " gesetzt:</p>" +
  238. " <ul>" +
  239. " {0}" +
  240. " </ul>" +
  241. " </body>" +
  242. "</html>";
  243. if (!appendices.Any()) return String.Format(template, String.Empty);
  244. var appendicesList = String.Empty;
  245. foreach (var appendix in appendices)
  246. {
  247. appendicesList += String.Format(
  248. "<li>Nachtrag <b>\"{0}\"</b> in Baustelle <b>\"{1}\"</b> - Einreichdatum: <b>{2:dd.MM.yyyy}</b>",
  249. appendix.CustomNumber, appendix.Site.CustomNumber, appendix.OfferingDate);
  250. }
  251. return String.Format(template, appendicesList);
  252. }
  253. /// <summary>
  254. /// Generates a mail body with a list of all appendices with a negotiation date later than N weeks
  255. /// </summary>
  256. /// <param name="appendices">Appendices matching that criteria.</param>
  257. public string GenerateNegotiationProtocolMailBody(IEnumerable<Appendix> appendices)
  258. {
  259. var template =
  260. "<html>" +
  261. " <body>" +
  262. " <h3>Übersicht \"Verhandelte Nachträge ohne Protokoll\"</h3>" +
  263. " <p>Folgende Nachträge haben ein Verhandlungstermin älter als zwei Wochen, jedoch noch kein Protokoll:" +
  264. " <ul>" +
  265. " {0}" +
  266. " </ul>" +
  267. " </body>" +
  268. "</html>";
  269. if (!appendices.Any()) return String.Format(template, String.Empty);
  270. var appendicesList = String.Empty;
  271. foreach (var appendix in appendices)
  272. {
  273. appendicesList += String.Format(
  274. "<li>Nachtrag <b>\"{0}\"</b> in Baustelle <b>\"{1}\"</b> - Verhandlungsdatum: <b>{2:dd.MM.yyyy}</b>",
  275. appendix.CustomNumber, appendix.Site.CustomNumber, appendix.NegotiationDate);
  276. }
  277. return String.Format(template, appendicesList);
  278. }
  279. #endregion
  280. #region Mail sending
  281. /// <summary>
  282. /// Sends a generated mail body to the specified recipients in the mail notification
  283. /// </summary>
  284. /// <param name="mailNotification">The mail notification.</param>
  285. /// <param name="subject">The mail subject.</param>
  286. /// <param name="body">The mail body.</param>
  287. public void SendNotification(MailNotification mailNotification, string subject, string body)
  288. {
  289. if (mailNotification == null) return;
  290. var mailServerConfig = _configurationService.GetCurrentConfiguration().MailServerElement;
  291. var smptClient = new SmtpClient(mailServerConfig.SmtpServer, mailServerConfig.Port)
  292. {
  293. EnableSsl = mailServerConfig.UseSsl,
  294. Credentials = new NetworkCredential(
  295. mailServerConfig.Username,
  296. mailServerConfig.Password,
  297. mailServerConfig.Domain)
  298. };
  299. var recipients =
  300. mailNotification.Users
  301. .Select(u => u.MailAddress);
  302. var mailMessage = new MailMessage
  303. {
  304. IsBodyHtml = true,
  305. Subject = subject,
  306. Body = body,
  307. From = new MailAddress("Nachtragsbenachrichtigung@schweerbau.de")
  308. };
  309. foreach (var recipient in recipients)
  310. mailMessage.To.Add(recipient);
  311. smptClient.Send(mailMessage);
  312. }
  313. #endregion
  314. #region Helper
  315. /// <summary>
  316. /// Determines the calendar week of a specific datetime
  317. /// </summary>
  318. /// <param name="date">The datetime which calendarweek should be calculated.</param>
  319. public static int GetCalendarWeek(DateTime date)
  320. {
  321. var currentCulture = CultureInfo.CurrentCulture;
  322. var calendar = currentCulture.Calendar;
  323. var calendarWeek = calendar.GetWeekOfYear(
  324. date,
  325. currentCulture.DateTimeFormat.CalendarWeekRule,
  326. currentCulture.DateTimeFormat.FirstDayOfWeek);
  327. if (calendarWeek > 52)
  328. {
  329. date = date.AddDays(7);
  330. var testCalendarWeek = calendar.GetWeekOfYear(date,
  331. currentCulture.DateTimeFormat.CalendarWeekRule,
  332. currentCulture.DateTimeFormat.FirstDayOfWeek);
  333. if (testCalendarWeek == 2)
  334. calendarWeek = 1;
  335. }
  336. return calendarWeek;
  337. }
  338. #endregion
  339. }
  340. }