/// <summary> /// Отправка оповещений об изменениях статусов заказов /// </summary> public static void SendOrderLineTrackingAlerts(ISendOrderLineTrackingAlertsLog log) { //список менеджеров для отправки копий оповещений IDictionary<string, EmployeeInfo> managers = null; try { managers = AcctgRefCatalog.RmsEmployees.Items.ToDictionary(item => item.EmployeeId); } catch { log.LogManagerListRequestFailed(); } using (var dc = new DCFactory<StoreDataContext>()) { // deas 23.05.2011 task4130 Ускорение работы со статусами //var stRejected = OrderLineStatusUtil.StatusByte(dc, "Rejected"); var stRejected = OrderLineStatusUtil.StatusByte( "Rejected" ); //подгрузить список клиентов, по которым будут отправляться оповещения var hourOfPeriod = DateTime.Now.Hour; //текущий час отправки оповещений (т.е. сервис сработал в этот час) //var clients = (from u in dc.Users.Where(user => user.Role == SecurityRole.Client) // join alert in dc.ClientAlertInfos on u.AcctgID equals alert.ClientID // join o in dc.Orders on u.AcctgID equals o.ClientID // join l in dc.OrderLines on o.OrderID equals l.OrderID // join ac in dc.ClientAlertConfigs on o.ClientID equals ac.ClientID //Для фильтрации по периоду отправки !!! тут явно косяк // where l.CurrentStatusDate > alert.OrderTrackingLastAlertDate // && l.CurrentStatus != stRejected // && ac.HourOfPeriod == null || ac.HourOfPeriod == -1 || ac.HourOfPeriod == hourOfPeriod //Фильтрация по периоду отправки !!! тут явно косяк // select u.AcctgID) // .Distinct() // .ToArray(); //var clients = (from u in dc.Users.Where(user => user.Role == SecurityRole.Client) // join alert in dc.ClientAlertInfos on u.AcctgID equals alert.ClientID // join o in dc.Orders on u.AcctgID equals o.ClientID // join l in dc.OrderLines on o.OrderID equals l.OrderID // //join ac in dc.ClientAlertConfigs.DefaultIfEmpty() on o.ClientID equals ac.ClientID into list //Для фильтрации по периоду отправки // //from listItem in list.DefaultIfEmpty() //left join // where l.CurrentStatusDate > alert.OrderTrackingLastAlertDate // && l.CurrentStatus != stRejected // //&& (listItem != null && (listItem.HourOfPeriod == null || listItem.HourOfPeriod == -1 || listItem.HourOfPeriod == hourOfPeriod)) //Фильтрация по периоду отправки // select u.AcctgID ) // .Distinct() // .ToArray(); //var clients_temp = from u in clients // join ac in dc.ClientAlertConfigs.DefaultIfEmpty() on u equals ac.ClientID // where (ac == null) || (ac.HourOfPeriod == -1) // select u; //var clients = (from u in dc.Users.Where(user => user.Role == SecurityRole.Client) // join alert in dc.ClientAlertInfos on u.AcctgID equals alert.ClientID // join o in dc.Orders on u.AcctgID equals o.ClientID // join l in dc.OrderLines on o.OrderID equals l.OrderID // join ac in dc.ClientAlertConfigs.DefaultIfEmpty() on o.ClientID equals ac.ClientID into list //Для фильтрации по периоду отправки // from listItem in list.DefaultIfEmpty() //left join // where l.CurrentStatusDate > alert.OrderTrackingLastAlertDate // && l.CurrentStatus != stRejected // && (listItem == null || (listItem.HourOfPeriod == null || listItem.HourOfPeriod == -1 || listItem.HourOfPeriod == hourOfPeriod)) //Фильтрация по периоду отправки // select u.AcctgID) // .Distinct() // .ToArray(); // deas 23.05.2011 task4124 Новый вариант настроек фильтра оповещений по статусам var clients = (from u in dc.DataContext.Users.Where(user => user.Role == SecurityRole.Client) join alert in dc.DataContext.ClientAlertInfos on u.AcctgID equals alert.ClientID join o in dc.DataContext.Orders on u.AcctgID equals o.ClientID join l in dc.DataContext.OrderLines on o.OrderID equals l.OrderID join ac in dc.DataContext.UserSettings.DefaultIfEmpty() on u.UserID.ToString() equals ac.UserID into list //Для фильтрации по периоду отправки from listItem in list.DefaultIfEmpty() //left join where l.CurrentStatusDate > alert.OrderTrackingLastAlertDate && l.CurrentStatus != stRejected && ( listItem == null || ( listItem.AlertHourOfPeriod == null || listItem.AlertHourOfPeriod == -1 || listItem.AlertHourOfPeriod == hourOfPeriod ) ) //Фильтрация по периоду отправки select u.AcctgID ) .Distinct() .ToArray(); foreach (var clientId in clients) { try { SendOrderLineTrackingAlerts(clientId, managers, log); } catch (Exception ex) { log.LogError(clientId, ex); } } } }
private static MailAddress GetOrderLineTrackingEmail(string address, string displayName, ISendOrderLineTrackingAlertsLog log, string refId) { MailAddress email = null; try { email = new MailAddress(address, displayName); } catch (ArgumentException) // обработка manager.Email = null или String.Empty { log.LogEmptyEmail(refId); } catch (FormatException) { log.LogInvalidEmail(refId, address); } return email; }
private static void SendOrderLineTrackingAlerts(string clientId, IDictionary<string, EmployeeInfo> managers, ISendOrderLineTrackingAlertsLog log) { using (var dc = new DCFactory<StoreDataContext>()) { DataLoadOptions dlo = new DataLoadOptions(); dlo.LoadWith<OrderLine>(l => l.Order); dlo.LoadWith<OrderLine>(l => l.OrderLineStatusChanges); var profile = ClientProfile.Load(clientId); var clientAlertInfo = dc.DataContext.ClientAlertInfos.Single(a => a.ClientID == clientId); //на всякий случай, для новых пользователей исключить отсылку "старых" оповещений, когда он был офлайн клиентом. if (clientAlertInfo == null) { dc.DataContext.ClientAlertInfos.InsertOnSubmit(new ClientAlertInfo { ClientID = clientId, OrderTrackingLastAlertDate = DateTime.Now }); dc.DataContext.SubmitChanges(); } // deas 23.05.2011 task4130 Ускорение работы со статусами //var stRejected = OrderLineStatusUtil.StatusByte(dc, "Rejected"); var stRejected = OrderLineStatusUtil.StatusByte( "Rejected" ); byte[] selectedStatuses = OrderLineStatusUtil.GetSelectedStatusesOfClient(dc.DataContext, clientId); // ID-шники выбранных этим клиентом статусов //var orderLines = ( from o in dc.Orders // join l in dc.OrderLines on o.OrderID equals l.OrderID // where o.ClientID == clientId // && l.CurrentStatusDate > clientAlertInfo.OrderTrackingLastAlertDate // && l.CurrentStatus != stRejected // && (selectedStatuses.Length > 0 && selectedStatuses.Contains(l.CurrentStatus)) // Для фильтрации по выбранным для оповещения статусам // orderby l.CurrentStatusDate // select l ).ToArray(); var orderLines = new OrderLine[] { }; if (selectedStatuses != null && selectedStatuses.Length > 0) { orderLines = (from o in dc.DataContext.Orders join l in dc.DataContext.OrderLines on o.OrderID equals l.OrderID where o.ClientID == clientId && l.CurrentStatusDate > clientAlertInfo.OrderTrackingLastAlertDate && l.CurrentStatus != stRejected && selectedStatuses.Contains(l.CurrentStatus) // Для фильтрации по выбранным для оповещения статусам orderby l.CurrentStatusDate select l).ToArray(); } else if(selectedStatuses == null) //значит записи в настройках клиента еще нет и тогда отсылаем все статусы (по умолчанию) //if (selectedStatuses != null && selectedStatuses.Length == 0) -> запись в настройках клиента есть, но нет выбранных статусов, тогда ничего не отсылаем { orderLines = (from o in dc.DataContext.Orders join l in dc.DataContext.OrderLines on o.OrderID equals l.OrderID where o.ClientID == clientId && l.CurrentStatusDate > clientAlertInfo.OrderTrackingLastAlertDate && l.CurrentStatus != stRejected orderby l.CurrentStatusDate select l).ToArray(); } if (orderLines.Length != 0) { OrderLineTrackingAlert alert = new OrderLineTrackingAlert(); if (LightBO.IsLight()) { alert = new OrderLineTrackingAlert(profile.InternalFranchName); } var estSupplyDateHint = TextItemsDac.GetTextItem( "Orders.EstSupplyDateHint", "ru-RU" ); alert.EstSupplyDateHint = estSupplyDateHint != null ? estSupplyDateHint.TextItemBody : ""; var blockMailFooter = TextItemsDac.GetTextItem( "OrderLineTrackingAlert.BlockMailFooter", "en-US"/*"ru-RU"*/ ); alert.BlockMailFooter = blockMailFooter != null ? blockMailFooter.TextItemBody.ToString() : ""; alert.NumChange = "0"; // считаем, что "перехода номера" не было. Dictionary<byte, string> dNames = new Dictionary<byte, string>(); foreach (var statusElement in dc.DataContext.OrderLineStatuses) { var status = statusElement.OrderLineStatusID; dNames.Add(status, OrderLineStatusUtil.DisplayName(status)); } alert.OrderLines = orderLines.Select(l => new OrderLineTrackingAlert.OrderLine { OrderDisplayNumber = RmsAuto.Store.Web.OrderTracking.GetOrderDisplayNumber(l.Order), CustOrderNum = l.Order.CustOrderNum, OrderDate = l.Order.OrderDate.ToString("dd.MM.yyyy"), Manufacturer = l.Manufacturer, PartNumber = l.PartNumber, PartName = l.PartName, UnitPrice = l.UnitPrice.ToString("### ### ##0.00"), Qty = l.Qty.ToString(), ReferenceID = l.ReferenceID, Total = l.Total.ToString("### ### ##0.00"), EstSupplyDate = l.EstSupplyDate != null ? l.EstSupplyDate.Value.ToString("dd.MM.yyyy") : "", CurrentStatusDate = l.CurrentStatusDate.Value.ToString("dd.MM.yyyy HH:mm:ss"), CurrentStatusName = dNames[l.CurrentStatus], CurrentStatusDescription = string.Empty,//l.LastStatusChange.StatusChangeInfo, -- закомментированно временно, до тех пор, пока снова не появится "история" по строке заказа ParentOrderLine = l.ParentOrderLine == null ? null : new OrderLineTrackingAlert.OrderLine { Manufacturer = l.ParentOrderLine.Manufacturer, PartNumber = l.ParentOrderLine.PartNumber, PartName = l.ParentOrderLine.PartName, UnitPrice = l.ParentOrderLine.UnitPrice.ToString("### ### ##0.00"), Qty = l.ParentOrderLine.Qty.ToString(), ReferenceID = l.ParentOrderLine.ReferenceID, Total = l.ParentOrderLine.Total.ToString("### ### ##0.00"), EstSupplyDate = l.ParentOrderLine.EstSupplyDate != null ? l.ParentOrderLine.EstSupplyDate.Value.ToString("dd.MM.yyyy") : "" } }).ToArray(); //var stPartNumberTransition = dNames[OrderLineStatusUtil.StatusByte(dc, "PartNumberTransition")]; try { var el = from o in alert.OrderLines where o.ParentOrderLine != null //where o.CurrentStatusName == stPartNumberTransition select o; if (el.Count() > 0) if (el.First() != null) alert.NumChange = "1"; //родительские строки есть! } catch (ApplicationException) { } MailAddress clientEmail = GetOrderLineTrackingEmail(profile.Email, profile.IsLegalWholesale ? profile.ContactPerson : profile.ClientName, log, clientId); MailAddress managerEmail = null; if (managers != null && profile.ManagerId != null) { EmployeeInfo manager; if (managers.TryGetValue(profile.ManagerId, out manager) && manager != null) managerEmail = GetOrderLineTrackingEmail(manager.Email, manager.FullName, log, "manager " + profile.ManagerId); } //создаем аттач Attachment attach = CreateAttachment(alert.OrderLines); //отправляем оповещение if ((clientEmail ?? managerEmail) != null) { /*MailEngine.SendMailWithBcc( clientEmail ?? managerEmail, clientEmail == null ? null : managerEmail, alert );*/ MailEngine.SendMailWithBccAndAttachments( clientEmail ?? managerEmail, clientEmail == null ? null : managerEmail, new Attachment[] { attach }, alert); } //если email не задан или некорректный, то дату последнего оповещения всё равно сдвигаем, //чтобы не заспамить клиента, когда в его профиле будет корректный email. clientAlertInfo.OrderTrackingLastAlertDate = orderLines.Max(l => l.CurrentStatusDate).Value; dc.DataContext.SubmitChanges(); log.LogSuccessfulAlert(clientId); } } }