public void Check() { var warningPeriod = DateTime.Now.Subtract(TimeSpan.FromHours(48)); var minDate = DateTime.Now.AddMonths(-3); var messages = new List <string>(); using (var db = _dbFactory.GetRWDb()) { var actions = db.SystemActions.GetAllAsDto() .Where(a => a.Type == (int)SystemActionType.UpdateOnMarketReturnOrder //&& (a.Status == (int) SystemActionStatus.Fail //NOTE: all statuses, in case some of action isn't process && a.Status != (int)SystemActionStatus.Done && a.CreateDate <warningPeriod && a.CreateDate> minDate) .ToList(); foreach (var action in actions) { var data = JsonConvert.DeserializeObject <ReturnOrderInput>(action.InputData); DTOOrder order = null; if (data.OrderId > 0) { order = db.Orders.GetAllAsDto().FirstOrDefault(o => o.Id == data.OrderId); } if (order == null) { order = db.Orders.GetAllAsDto().FirstOrDefault(o => o.OrderId == data.OrderNumber); } if (order == null) { _log.Info("Unable to find order: orderId=" + data.OrderId + ", orderNumber=" + data.OrderNumber); continue; } var requestedAmount = data.Items.Sum(i => i.RefundItemPrice + (data.IncludeShipping ? i.RefundShippingPrice : 0) - (data.DeductShipping ? i.DeductShippingPrice : 0) - (data.IsDeductPrepaidLabelCost ? i.DeductPrepaidLabelCost : 0)); messages.Add("Order #: " + order.OrderId + ", market: " + MarketHelper.GetMarketName(order.Market, order.MarketplaceId) + ", status: " + SystemActionHelper.GetName((SystemActionStatus)action.Status) + ", amount: " + requestedAmount + ", create date: " + action.CreateDate); } } if (messages.Any()) { _log.Info(String.Join("\r\n", messages)); _emailService.SendSystemEmailToAdmin("Support Notification: " + Name + " - To Review (" + messages.Count() + ")", "Unprocessed refunds:<br/>" + String.Join("<br/>", messages)); } else { _emailService.SendSystemEmailToAdmin("Support Notification: " + Name + " - Success", ""); } }
public void ProcessSystemAction(ISystemActionService actionService, string feedDirectory) { using (var db = _dbFactory.GetRWDb()) { var toProcessActions = actionService.GetUnprocessedByType(db, SystemActionType.ProcessUploadOrderFeed, null, null); foreach (var action in toProcessActions) { _log.Info("Find action: " + action.Id); var actionStatus = SystemActionStatus.None; var output = new PublishFeedOutput(); try { var inputData = SystemActionHelper.FromStr <PublishFeedInput>(action.InputData); var filepath = Path.Combine(feedDirectory, inputData.FileName); var uploadResult = UploadFeed(filepath, (MarketType)(inputData.Market ?? (int)MarketType.OfflineOrders), inputData.MarketplaceId, (PublishFeedModes)(inputData.Mode ?? (int)PublishFeedModes.Publish), inputData.IsPrime); output.ProgressPercent = 100; output.IsSuccess = true; if (uploadResult != null) { output.MatchedCount = uploadResult.MatchedCount; output.ParsedCount = uploadResult.ParsedCount; output.Processed1OperationCount = uploadResult.Processed1Count; output.Processed2OperationCount = uploadResult.Processed2Count; } actionStatus = SystemActionStatus.Done; _log.Info("Sale feed processed: " + filepath + ", actionId=" + action.Id); } catch (Exception ex) { actionStatus = SystemActionStatus.Fail; _log.Error("Fail quantity distributed, actionId=" + action.Id + ", status=" + actionStatus, ex); } actionService.SetResult(db, action.Id, actionStatus, output, null); } db.Commit(); } }
public CallResult UpdateQuantity(ItemDTO item) { using (var db = _dbFactory.GetRWDb()) { var itemView = db.Items.GetAllViewAsDto().FirstOrDefault(i => i.SKU == item.SKU); if (itemView == null) { return(new CallResult() { Status = CallStatus.Fail, Message = "Unable to find item: " + item.SKU }); } if (!itemView.StyleItemId.HasValue) { return(new CallResult() { Status = CallStatus.Fail, Message = "Item hasn't linked StyleItemId: " + item.SKU }); } var dbStyleItem = db.StyleItems.GetAll().FirstOrDefault(si => si.Id == itemView.StyleItemId); if (dbStyleItem == null) { return(new CallResult() { Status = CallStatus.Fail, Message = "Unable to find styleItem: " + dbStyleItem.Id }); } if (dbStyleItem.Quantity != item.RealQuantity) { _log.Info("Quantity changed, SKU=" + item.SKU + ", " + dbStyleItem.Quantity + "=>" + item.RealQuantity); } dbStyleItem.Quantity = item.RealQuantity; dbStyleItem.QuantitySetDate = _time.GetAppNowTime(); dbStyleItem.QuantitySetBy = null; db.Commit(); SystemActionHelper.RequestQuantityDistribution(db, _actionService, dbStyleItem.StyleId, null); } return(new CallResult() { Status = CallStatus.Success }); }
public virtual ActionResult GetFeed(long id) { LogI("GetLabelPrintFile, id=" + id); var uploadAction = Db.SystemActions.Get(id); if (uploadAction != null) { var inputModel = SystemActionHelper.FromStr <PublishFeedInput>(uploadAction.InputData); var filepath = Path.Combine(Models.UrlHelper.GetUploadOrderFeedPath(), inputModel.FileName); var filename = inputModel.FileName; return(File(filepath, FileHelper.GetMimeTypeByExt(Path.GetExtension(filepath)), filename)); } return(new HttpNotFoundResult()); }
public static void CancelOrder(IUnitOfWork db, ILogService log, ITime time, ISystemActionService actionService, IOrderHistoryService orderHistoryService, long orderId, long?by) { var dbOrder = db.Orders.Get(orderId); if (dbOrder != null) { var orderItems = db.OrderItemSources.GetWithListingInfo().Where(oi => oi.OrderId == orderId).ToList(); var itemIdList = orderItems.Where(oi => !String.IsNullOrEmpty(oi.SourceMarketId)) .Select(oi => oi.SourceMarketId) .ToList(); log.Info("Items to cancel: " + String.Join(";", itemIdList)); db.OrderNotifies.Add(new OrderNotify() { OrderId = dbOrder.Id, Type = (int)OrderNotifyType.CancellationRequest, Status = 1, Message = "Email cancelation from web page", CreateDate = time.GetAppNowTime(), }); db.Commit(); orderHistoryService.AddRecord(dbOrder.Id, OrderHistoryHelper.CancellationRequestKey, null, true, by); SystemActionHelper.AddCancelationActionSequences(db, actionService, dbOrder.Id, dbOrder.AmazonIdentifier, String.Join(";", itemIdList), null, null, null, null, by, CancelReasonType.Manually); } }
public void CheckRemovedOrder(IUnitOfWork db, ILogService log, ISystemActionService systemAction, Order order, long?toBatchId, long?by) { log.Info("CheckRemovedOrder"); var orderNumber = order.AmazonIdentifier; var customerOrderId = order.CustomerOrderId; var buyerEmail = order.BuyerEmail; //NOTE: when remove from batch if has cancellation request process them var cancelationRequests = db.OrderNotifies.GetAll().Where(o => o.OrderId == order.Id && o.Type == (int)OrderNotifyType.CancellationRequest).ToList(); if (cancelationRequests.Any() && toBatchId == null) //Move to Order Page { log.Info("Order status was changed to Canceled, orderNumber=" + orderNumber); var itemIdList = cancelationRequests .Where(r => !String.IsNullOrEmpty(r.Params)) .Select(r => r.Params) .Distinct(); SystemActionHelper.AddCancelationActionSequences(db, systemAction, order.Id, orderNumber, String.Join(";", itemIdList), null, null, null, null, by, CancelReasonType.PerBuyerRequest); order.OrderStatus = OrderStatusEnumEx.Canceled; db.Commit(); } }
public UploadOrderFeedViewModel(SystemActionDTO action) { Id = action.Id; Status = action.Status; var inputModel = SystemActionHelper.FromStr <PublishFeedInput>(action.InputData); var outputModel = SystemActionHelper.FromStr <PublishFeedOutput>(action.OutputData); FileName = inputModel.FileName; FieldMappingsId = inputModel.FieldMappingsId; ProgressPercent = outputModel?.ProgressPercent ?? 0; CreateDate = action.CreateDate; ParsedCount = outputModel?.ParsedCount; MatchedCount = outputModel?.MatchedCount; Valid1OperationCount = outputModel?.Valid1OperationCount; Valid2OperationCount = outputModel?.Valid2OperationCount; Processed1OperationCount = outputModel?.Processed1OperationCount; Processed2OperationCount = outputModel?.Processed2OperationCount; }
public void TestSendEmails() { var settings = SettingsBuilder.GetSmtpSettingsFromAppSettings(); var email = new EmailService(_log, settings, _addressService); var actionServiceStub = new Mock <ISystemActionService>(); actionServiceStub .Setup(l => l.GetUnprocessedByType(It.IsAny <IUnitOfWork>(), It.IsAny <SystemActionType>(), null, null)) .Returns(new List <SystemActionDTO>() { new SystemActionDTO() { InputData = SystemActionHelper.ToStr(new SendEmailInput() { OrderId = "106-0610855-5158626", EmailType = EmailTypes.NoticeLeft, Args = null }) } }); actionServiceStub .Setup(l => l.SetResult(It.IsAny <IUnitOfWork>(), It.IsAny <long>(), It.IsAny <SystemActionStatus>(), It.IsAny <ISystemActionOutput>(), It.IsAny <string>())).Callback((IUnitOfWork db, long actionId, SystemActionStatus status, ISystemActionOutput output, string groupId) => { Console.WriteLine(SystemActionHelper.ToStr(output)); }); email.ProcessEmailActions(_dbFactory, _time, _company, actionServiceStub.Object); }
public void ReadListingInventory() { if (_api.Market == MarketType.Walmart) { var markAllWFSListingInfos = ((WalmartApi)_api).GetWFSInventory(null); var markAllWFSSKUs = markAllWFSListingInfos.Where(i => i.RealQuantity > 0 || i.AmazonRealQuantity > 0).Select(i => i.SKU).ToList(); using (var db = _dbFactory.GetRWDb()) { var dbWFSListings = db.Listings.GetAll().Where(l => l.IsFBA && l.Market == (int)MarketType.Walmart && !l.IsRemoved) .ToList(); var dbExistWFSSKUs = dbWFSListings.Select(l => l.SKU).ToList(); var newWFSListingSKUs = markAllWFSSKUs.Where(i => !dbExistWFSSKUs.Contains(i)).ToList(); var dbNewWFSListings = db.Listings.GetAll().Where(l => newWFSListingSKUs.Contains(l.SKU) && l.Market == (int)MarketType.Walmart && !l.IsRemoved).ToList(); foreach (var dbNewWFSListing in dbNewWFSListings) { _log.Info("Set IsFBA=true, for SKU=" + dbNewWFSListing.SKU); _itemHistoryService.AddRecord(dbNewWFSListing.ItemId, ItemHistoryHelper.IsFBAKey, dbNewWFSListing.IsFBA, true, null); dbNewWFSListing.IsFBA = true; SystemActionHelper.RequestPriceRecalculation(db, _actionService, dbNewWFSListing.Id, null); } var dbRemoveWFSStatus = dbWFSListings.Where(i => !markAllWFSSKUs.Contains(i.SKU)).ToList(); foreach (var dbRemoveWFSListing in dbRemoveWFSStatus) { _log.Info("Rest IsFBA=false, for SKU=" + dbRemoveWFSListing.SKU); _itemHistoryService.AddRecord(dbRemoveWFSListing.ItemId, ItemHistoryHelper.IsFBAKey, dbRemoveWFSListing.IsFBA, false, null); dbRemoveWFSListing.IsFBA = false; SystemActionHelper.RequestPriceRecalculation(db, _actionService, dbRemoveWFSListing.Id, null); } } } }
protected override void UpdateEntitiesAfterResponse(long feedId, IList <FeedResultMessage> errorList) { using (var db = DbFactory.GetRWDb()) { var groupId = feedId.ToString(); var groupActions = _actionService.GetByTypeAndGroupId(db, SystemActionType.UpdateOnMarketCancelOrder, groupId); foreach (var action in groupActions) { var input = SystemActionHelper.FromStr <CancelOrderInput>(action.InputData); var output = SystemActionHelper.FromStr <CancelOrderOutput>(action.OutputData); if (errorList.All(e => e.MessageId != output.Identifier)) { output.IsProcessed = true; _actionService.SetResult(db, action.Id, SystemActionStatus.Done, output); } else { if (action.AttemptNumber > 10) { _actionService.SetResult(db, action.Id, SystemActionStatus.Fail, output); } else { _actionService.SetResult(db, action.Id, SystemActionStatus.None, output); } Log.Warn("Order not acknowledgement, orderId=" + input.OrderNumber + ", attemptNumber=" + action.AttemptNumber); } } db.Commit(); } }
protected override void UpdateEntitiesAfterResponse(long feedId, IList <FeedResultMessage> errorList) { using (var db = DbFactory.GetRWDb()) { var groupId = feedId.ToString(); var groupActions = _actionService.GetByTypeAndGroupId(db, SystemActionType.UpdateOnMarketReturnOrder, groupId); foreach (var action in groupActions) { var input = SystemActionHelper.FromStr <ReturnOrderInput>(action.InputData); var output = SystemActionHelper.FromStr <ReturnOrderOutput>(action.OutputData); var error = errorList.FirstOrDefault(e => e.MessageId == output.Identifier); if (error == null) { output.IsProcessed = true; _actionService.SetResult(db, action.Id, SystemActionStatus.Done, output); } else { output.ResultMessage = error.ResultCode + ": " + error.MessageCode + ": " + error.Message; _actionService.SetResult(db, action.Id, SystemActionStatus.Fail, output); _emailService.SendSystemEmail( "System can't process refund, order #" + input.OrderNumber, "Details: " + output.ResultMessage, EmailHelper.RafiEmail + ";" + EmailHelper.RaananEmail, EmailHelper.SupportDgtexEmail); Log.Warn("Order not adjustment, orderId=" + input.OrderNumber); } } db.Commit(); } }
protected void DefaultActionUpdateEntitiesAfterResponse(long feedId, IList <FeedResultMessage> errorList, string itemAdditionalFieldName, int maxAttemptCount) { using (var db = DbFactory.GetRWDb()) { var feedItems = db.FeedItems.GetAllAsDto().Where(fi => fi.FeedId == feedId).ToList(); var systemActionIds = feedItems.Select(f => f.ItemId).ToList(); var systemActions = db.SystemActions.GetAll().Where(i => systemActionIds.Contains(i.Id)).ToList(); var itemIds = systemActions.Select(a => StringHelper.TryGetInt(a.Tag)) .Where(a => a.HasValue) .Select(a => a.Value) .ToList(); //Remove all exist errors var dbExistErrors = db.ItemAdditions.GetAll().Where(i => itemIds.Contains(i.ItemId) && i.Field == itemAdditionalFieldName).ToList(); foreach (var dbExistError in dbExistErrors) { db.ItemAdditions.Remove(dbExistError); } foreach (var action in systemActions) { var feedItem = feedItems.FirstOrDefault(fi => fi.ItemId == action.Id); if (feedItem != null) { var itemErrors = errorList.Where(e => e.MessageId == feedItem.MessageId).ToList(); TextMessageOutput output = null; SystemActionStatus status = SystemActionStatus.None; if (itemErrors.Any()) { action.AttemptNumber++; action.AttemptDate = Time.GetAppNowTime(); if (action.AttemptNumber > maxAttemptCount) { action.Status = (int)SystemActionStatus.Fail; } var itemId = StringHelper.TryGetLong(action.Tag); if (itemId.HasValue) { foreach (var itemError in itemErrors) { db.ItemAdditions.Add(new Core.Entities.Listings.ItemAddition() { ItemId = (int)itemId.Value, Field = itemAdditionalFieldName, Value = itemError.Message, CreateDate = Time.GetAppNowTime(), }); } } output = new TextMessageOutput() { IsSuccess = false, Messages = itemErrors.Select(i => new MessageString() { Status = MessageStatus.Error, Message = i.Message }).ToList() }; status = SystemActionStatus.Fail; } else { output = new TextMessageOutput() { IsSuccess = false }; status = SystemActionStatus.Done; } action.OutputData = SystemActionHelper.ToStr(output); action.Status = (int)status; Log.Info("Update action status, actionId=" + action.Id + ", status=" + action.Status); } } db.Commit(); } }
public void ProcessSystemAction() { using (var db = _dbFactory.GetRWDb()) { var commentActions = _actionService.GetUnprocessedByType(db, SystemActionType.AddComment, null, null); foreach (var action in commentActions) { var actionStatus = SystemActionStatus.None; try { var inputData = SystemActionHelper.FromStr <AddCommentInput>(action.InputData); var orderId = inputData.OrderId; if (!orderId.HasValue && !String.IsNullOrEmpty(inputData.OrderNumber)) { var order = db.Orders.GetByCustomerOrderNumber(inputData.OrderNumber); if (order == null) { throw new ArgumentException("Can't find order", "OrderNumber"); } orderId = order.Id; } if (orderId.HasValue) { db.OrderComments.Add(new OrderComment() { OrderId = orderId.Value, Message = inputData.Message, Type = inputData.Type, LinkedEmailId = inputData.LinkedEmailId, CreateDate = _time.GetAppNowTime(), CreatedBy = inputData.By, }); db.Commit(); actionStatus = SystemActionStatus.Done; _log.Info("Comment was added, actionId=" + action.Id); } else { actionStatus = SystemActionStatus.NotFoundEntity; _log.Info("Can't find order, orderId=" + inputData.OrderId + ", orderNumber=" + inputData.OrderNumber); } } catch (Exception ex) { actionStatus = SystemActionStatus.Fail; if (action.CreateDate > _time.GetUtcTime().AddHours(-6)) { actionStatus = SystemActionStatus.None; } _log.Error("Fail add comment action, actionId=" + action.Id + ", status=" + actionStatus, ex); } _actionService.SetResult(db, action.Id, actionStatus, null, null); } db.Commit(); } }
public void SyncQty(DropShipperApi api) { var styles = api.GetQuantities(_log, MarketType.DropShipper, MarketplaceKeeper.DsPAWMCom); styles = styles.Where(st => st.StyleID == "WS20052SS").ToList(); using (var db = _dbFactory.GetRWDb()) { foreach (var incomeStyle in styles) { var findStyle = db.Styles.GetAll().FirstOrDefault(st => (st.StyleID == incomeStyle.StyleID || st.OriginalStyleID.Contains(incomeStyle.StyleID + ";")) && !st.Deleted); if (findStyle != null) { var changedStyleItemIds = new List <long>(); foreach (var incomeStyleItem in incomeStyle.StyleItems) { var findStyleItem = db.StyleItems.GetAll().FirstOrDefault(si => si.StyleId == findStyle.Id && si.Size == incomeStyleItem.Size && (si.Color == incomeStyleItem.Color || (String.IsNullOrEmpty(si.Color) && String.IsNullOrEmpty(incomeStyleItem.Color)))); if (findStyleItem != null && (findStyleItem.Quantity != incomeStyleItem.Quantity || findStyleItem.QuantitySetDate != incomeStyleItem.QuantitySetDate)) { _quantityManager.LogStyleItemQuantity(db, findStyleItem.Id, incomeStyleItem.Quantity, findStyleItem.Quantity, QuantityChangeSourceType.SetByAutoQuantity, null, null, null, _time.GetAppNowTime(), null); findStyleItem.Quantity = incomeStyleItem.Quantity; findStyleItem.QuantitySetDate = incomeStyleItem.QuantitySetDate; changedStyleItemIds.Add(incomeStyleItem.StyleItemId); } else { _log.Info("Unable to find style size: " + findStyle.StyleID + " - " + incomeStyleItem.Size + " / " + incomeStyleItem.Color); } } db.Commit(); if (changedStyleItemIds.Any()) { _cacheService.RequestStyleIdUpdates(db, new List <long>() { findStyle.Id }, UpdateCacheMode.IncludeChild, null); SystemActionHelper.RequestQuantityDistribution(db, _actionService, findStyle.Id, null); } } else { _log.Info("Unable to find style: " + incomeStyle.StyleID); } } } }
public void ProcessSystemAction(CancellationToken cancelToken) { var syncInfo = new EmptySyncInformer(_log, SyncType.Orders); using (var db = _dbFactory.GetRWDb()) { var updateRateActions = _actionService.GetUnprocessedByType(db, SystemActionType.UpdateRates, null, null); foreach (var action in updateRateActions) { if (cancelToken.IsCancellationRequested) { return; } var actionStatus = SystemActionStatus.None; try { var inputData = SystemActionHelper.FromStr <UpdateRatesInput>(action.InputData); var orderId = inputData.OrderId; if (!orderId.HasValue && !String.IsNullOrEmpty(inputData.OrderNumber)) { var order = db.Orders.GetByOrderNumber(inputData.OrderNumber); orderId = order.Id; } if (orderId.HasValue) { var orderIdList = new long[] { orderId.Value }; IList <DTOOrder> dtoOrders = db.ItemOrderMappings.GetSelectedOrdersWithItems(_weightService, orderIdList, includeSourceItems: true).ToList(); foreach (var dtoOrder in dtoOrders) { //Ignore shipped orders if ((dtoOrder.Market != (int)MarketType.eBay && ShippingUtils.IsOrderShipped(dtoOrder.OrderStatus)) || dtoOrder.ShippingInfos.Any(s => !String.IsNullOrEmpty(s.LabelPath)) || dtoOrder.BatchId.HasValue) //NOTE: SKip orders in batch { actionStatus = SystemActionStatus.Skipped; } else { var markets = new MarketplaceKeeper(_dbFactory, false); markets.Init(); var companyAddress = new CompanyAddressService(_company, markets.GetAll()); var synchronizer = new AmazonOrdersSynchronizer(_log, _company, syncInfo, _rateProviders, companyAddress, _time, _weightService, _messageService); if (!synchronizer.UIUpdate(db, dtoOrder, false, false, keepCustomShipping: false, switchToMethodId: null)) { actionStatus = SystemActionStatus.Fail; } else { actionStatus = SystemActionStatus.Done; } } } _log.Info("Order rates was recalculated, actionId=" + action.Id + ", status=" + actionStatus); } else { actionStatus = SystemActionStatus.NotFoundEntity; _log.Info("Can't find order, actionId=" + action.Id + ", orderId=" + inputData.OrderId + ", orderNumber=" + inputData.OrderNumber); } } catch (Exception ex) { _log.Error("Fail recalculate order rates action, actionId=" + action.Id, ex); actionStatus = SystemActionStatus.Fail; } _actionService.SetResult(db, action.Id, actionStatus, null, null); } db.Commit(); } }
private void CancelOrder(IUnitOfWork db, EmailReadingResult result, string orderNumber, Order order) { if (!String.IsNullOrEmpty(orderNumber)) { var itemId = EmailHelper.ExtractWalmartItemId(result.Email.Message); _log.Info("ItemId=" + itemId); var existCancellationActions = _systemAction.GetByTypeAndTag(db, SystemActionType.UpdateOnMarketCancelOrder, orderNumber); var isExistCancelRequest = existCancellationActions.Any(); if (existCancellationActions.Any() && order != null && (order.Market == (int)MarketType.Walmart || order.Market == (int)MarketType.WalmartCA)) //NOTE: for Walmart checking by item cancallation { var existItemCancallation = false; foreach (var action in existCancellationActions) { var data = JsonConvert.DeserializeObject <CancelOrderInput>(action.InputData); if (data.ItemId == itemId) { existItemCancallation = true; } } isExistCancelRequest = existItemCancallation; } if (!isExistCancelRequest) { result.WasEmailProcessed = true; _log.Info("CancellationEmailRule, WasEmailProcessed=" + result.WasEmailProcessed); var comment = ""; //NOTE: "system to cancel that order if it wasn’t shipped and it’s not assigned to Active Batch yet, and send client an email" //NOTE: if no order in system if (order == null || ((order.OrderStatus == OrderStatusEnumEx.Unshipped || order.OrderStatus == OrderStatusEnumEx.Pending || order.OrderStatus == OrderStatusEnumEx.Canceled) && !order.BatchId.HasValue)) { _log.Info("Order status was changed to Canceled, orderNumber=" + orderNumber); SystemActionHelper.AddCancelationActionSequences(db, _systemAction, order.Id, orderNumber, itemId, result.Email.Id, result.Email.From, (order != null && (order.Market == (int)MarketType.Walmart || order.Market == (int)MarketType.WalmartCA)) ? result.Email.Subject : null, EmailHelper.ExtractShortMessageBody(result.Email.Message, 200, true), null, CancelReasonType.PerBuyerRequest); if (order != null && order.Market != (int)MarketType.Walmart && order.Market != (int)MarketType.WalmartCA) //NOTE: Exclude Walmart, cancellation happen only for one item { order.OrderStatus = OrderStatusEnumEx.Canceled; } //if (order != null && (order.Market == (int) MarketType.Walmart || order.Market == (int)MarketType.WalmartCA)) //{ // if (!order.BatchId.HasValue) //Only when not in batch // { // var orderItemLineCount = db.OrderItems.GetByOrderIdAsDto(order.Id).Count(); // if (orderItemLineCount > 1) // { // _log.Info("Walmart Order set OnHold, in case it has more then one item line = " + orderItemLineCount); // order.OnHold = true; // db.OrderComments.Add(new OrderComment() // { // OrderId = order.Id, // Message = String.Format("[System] Partial email cancellation request, 1 / {0} order lines", orderItemLineCount), // Type = (int)CommentType.ReturnExchange, // LinkedEmailId = result.Email.Id, // CreateDate = _time.GetAppNowTime(), // UpdateDate = _time.GetAppNowTime(), // }); // } // } //} if (order != null) { comment = "Marked as cancelled + emailed"; db.OrderNotifies.Add(new OrderNotify() { OrderId = order.Id, Status = 1, Type = (int)OrderNotifyType.CancellationRequest, Params = itemId, Message = "Email cancelation request in progress", CreateDate = _time.GetAppNowTime(), }); } } else { var commentText = "[System] Email cancelation request wasn't processed. Order already shipped."; if (order.OrderStatus != OrderStatusEnumEx.Shipped) { db.OrderNotifies.Add(new OrderNotify() { OrderId = order.Id, Status = 1, Type = (int)OrderNotifyType.CancellationRequest, Params = itemId, Message = "Email cancelation request, order in batch", CreateDate = _time.GetAppNowTime(), }); } else { _systemAction.AddAction(db, SystemActionType.SendEmail, orderNumber, new SendEmailInput() { EmailType = EmailTypes.RejectOrderCancellationToBuyer, OrderId = orderNumber, ReplyToEmail = result.Email.From, ReplyToSubject = result.Email.Subject, }, null, null); commentText += " Email was sent to customer."; } db.OrderComments.Add(new OrderComment() { OrderId = order.Id, Message = commentText, Type = (int)CommentType.ReturnExchange, LinkedEmailId = result.Email.Id, CreateDate = _time.GetAppNowTime(), UpdateDate = _time.GetAppNowTime(), }); comment = "Cancellation skipped"; } db.OrderEmailNotifies.Add(new OrderEmailNotify() { OrderNumber = orderNumber, Type = (int)OrderEmailNotifyType.InputOrderCancelledEmail, Reason = comment, CreateDate = _time.GetUtcTime() }); db.Commit(); } else { _log.Info("Repeated OrderCancellation email, no action"); } } else { _log.Info("Can't OrderCancellation, no order number!"); } }
public long Apply(IUnitOfWork db, ICacheService cache, IQuantityManager quantityManager, IStyleHistoryService styleHistory, ISystemActionService actionService, DateTime when, long?by) { var style = db.Styles.Get(StyleId); style.UpdateDate = when; style.UpdatedBy = by; style.ReSaveDate = when; style.ReSaveBy = by; StyleViewModel.UpdateLocations(db, styleHistory, StyleId, Locations, when, by); var wasAnyChanges = false; if (Sizes != null && Sizes.Any()) { var styleItems = db.StyleItems.GetFiltered(si => si.StyleId == StyleId).ToList(); var styleItemCaches = db.StyleItemCaches.GetFiltered(si => si.StyleId == StyleId).ToList(); foreach (var size in Sizes) //Update quantity (marking when/by) { //int? oldQuantity = null; //int? newQuantity = null; string tag = null; bool wasChanged = false; var styleItem = styleItems.FirstOrDefault(si => si.Id == size.StyleItemId); var styleItemCache = styleItemCaches.FirstOrDefault(sic => sic.Id == size.StyleItemId); if (styleItem != null) { if (size.UseBoxQuantity) { if (styleItem.Quantity != null) { var oldQuantity = styleItem.Quantity; var newQuantity = size.BoxQuantity; tag = size.BoxQuantitySetDate.ToString(); styleItem.Quantity = null; styleItem.QuantitySetDate = null; styleItem.QuantitySetBy = null; //styleItem.RestockDate = null; wasChanged = true; quantityManager.LogStyleItemQuantity(db, styleItem.Id, newQuantity, oldQuantity, QuantityChangeSourceType.UseBoxQuantity, tag, null, null, when, by); } } if (size.NewRestockDate.HasValue && styleItem.RestockDate != size.NewRestockDate) { styleHistory.AddRecord(styleItem.StyleId, StyleHistoryHelper.RestockDateKey, DateHelper.ToDateTimeString(styleItem.RestockDate), StringHelper.JoinTwo("-", styleItem.Size, styleItem.Color), DateHelper.ToDateTimeString(size.NewRestockDate), styleItem.Id.ToString(), by); styleItem.RestockDate = size.NewRestockDate; wasChanged = true; } if (size.NewManuallyQuantity.HasValue) { var operationType = size.NewManuallyQuantity.Value < 0 ? QuantityOperationType.Lost : QuantityOperationType.AddManually; var quantityOperation = new QuantityOperationDTO() { Type = (int)operationType, QuantityChanges = new List <QuantityChangeDTO>() { new QuantityChangeDTO() { StyleId = style.Id, StyleItemId = styleItem.Id, Quantity = -1 * size.NewManuallyQuantity.Value, //NOTE: we need to change sign to opposite because we substract quantity operataions from inventory } }, Comment = "From style quantity dialog", }; quantityManager.AddQuantityOperation(db, quantityOperation, when, by); //NOTE: Hot updating the cache (only for first few seconds to display the updates before recalculation) if (styleItemCache != null) { styleItemCache.SpecialCaseQuantityFromDate += -1 * size.NewManuallyQuantity.Value; styleItemCache.TotalSpecialCaseQuantity += -1 * size.NewManuallyQuantity.Value; } wasChanged = true; } if (size.IsRemoveRestockDate == true) { styleItem.RestockDate = null; wasChanged = true; } if (size.OnHold != styleItem.OnHold) { quantityManager.LogStyleItemQuantity(db, styleItem.Id, size.OnHold ? 0 : styleItem.Quantity, size.OnHold ? styleItem.Quantity : 0, QuantityChangeSourceType.OnHold, size.OnHold.ToString(), null, null, when, by); styleItem.OnHold = size.OnHold; wasChanged = true; } } if (wasChanged) { db.Commit(); wasAnyChanges = true; } } } //NOTE: always update cache cache.RequestStyleIdUpdates(db, new List <long>() { StyleId }, UpdateCacheMode.IncludeChild, AccessManager.UserId); if (wasAnyChanges) { db.Commit(); SystemActionHelper.RequestQuantityDistribution(db, actionService, StyleId, by); } return(StyleId); }
public void Apply(IUnitOfWork db, IQuantityManager quantityManager, ILogService log, ICacheService cache, ISystemActionService actionService, DateTime when, long?by) { log.Info("AddSealedBoxWizardViewModel.Apply, StyleId=" + StyleId); if (IncomeType == (int)BoxIncomePackType.PPK) { var box = new SealedBoxViewModel(); box.StyleId = StyleId; box.BoxBarcode = BoxBarcode; box.BoxQuantity = BoxQuantity; box.Price = Price ?? 0; box.Owned = Owned; box.PolyBags = false; box.Printed = Printed; box.CreateDate = CreateDate.HasValue ? DateHelper.ConvertUtcToApp(CreateDate.Value.ToUniversalTime()) : when; box.StyleItems = new StyleItemCollection() { Items = Sizes.Select(s => new StyleItemViewModel() { Id = s.Id, Breakdown = s.Breakdown, }).ToList() }; box.Apply(db, quantityManager, when, by); } if (IncomeType == (int)BoxIncomePackType.PolyBagged) { foreach (var size in Sizes.Where(si => si.Quantity > 0)) { var box = new SealedBoxViewModel(); box.StyleId = StyleId; box.BoxBarcode = BoxBarcode; box.BoxQuantity = size.Quantity ?? 0; box.Price = Price ?? 0; box.Owned = Owned; box.PolyBags = true; box.Printed = Printed; box.CreateDate = CreateDate.HasValue ? DateHelper.ConvertUtcToApp(CreateDate.Value.ToUniversalTime()) : when; box.StyleItems = new StyleItemCollection() { Items = new List <StyleItemViewModel>() { new StyleItemViewModel() { Id = size.Id, Breakdown = UnitsPerBox } } }; box.Apply(db, quantityManager, when, by); } } if (IncomeType == (int)BoxIncomePackType.Other) { var box = new OpenBoxViewModel(); box.StyleId = StyleId; box.BoxBarcode = BoxBarcode; box.BoxQuantity = 1; box.Price = Price ?? 0; box.Owned = Owned; box.PolyBags = false; box.Printed = Printed; box.CreateDate = CreateDate.HasValue ? DateHelper.ConvertUtcToApp(CreateDate.Value.ToUniversalTime()) : when; box.StyleItems = new StyleItemCollection() { Items = Sizes.Select(s => new StyleItemViewModel() { Id = s.Id, Quantity = s.Quantity, }).ToList() }; box.Apply(db, quantityManager, when, by); } foreach (var size in Sizes) { var styleItem = db.StyleItems.Get(size.Id); if (size.UseBoxQuantity && styleItem.Quantity.HasValue) { log.Info("Switch to box quantity, styleItemId=" + size.Id); var oldQuantity = styleItem.Quantity; styleItem.Quantity = null; styleItem.QuantitySetBy = null; styleItem.QuantitySetDate = null; styleItem.RestockDate = null; db.Commit(); quantityManager.LogStyleItemQuantity(db, styleItem.Id, null, oldQuantity, QuantityChangeSourceType.UseBoxQuantity, null, null, BoxBarcode, when, by); } } cache.RequestStyleIdUpdates(db, new List <long>() { StyleId }, UpdateCacheMode.IncludeChild, by); SystemActionHelper.RequestQuantityDistribution(db, actionService, StyleId, by); }
public CheckResult Check(IUnitOfWork db, long orderId, IList <ListingOrderDTO> orderItems, IList <OrderShippingInfoDTO> shippings, DTOMarketOrder marketOrder) { if (!orderItems.Any() || !shippings.Any()) { return new CheckResult() { IsSuccess = false } } ; if (marketOrder.UpgradeLevel > 0) { return new CheckResult() { IsSuccess = false } } ; if (marketOrder.Market == (int)MarketType.Groupon) { return new CheckResult() { IsSuccess = false } } ; CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US"); culture.NumberFormat.CurrencyNegativePattern = 1; decimal paidShppingCost = orderItems.Sum(i => i.ShippingPrice); string currency = orderItems.First().ShippingPriceCurrency; paidShppingCost = PriceHelper.RougeConvertToUSD(currency, paidShppingCost); if (marketOrder.OrderType == (int)OrderTypeEnum.Prime) { paidShppingCost += orderItems.Sum(oi => AmazonPrimeHelper.GetShippingAmount(oi.Weight)); } decimal?actualShippingsCost = null; if (shippings != null && shippings.Any(sh => sh.IsActive)) { actualShippingsCost = shippings.Where(sh => sh.IsActive && sh.ShippingMethodId != ShippingUtils.FedexSmartPost).Sum(sh => sh.StampsShippingCost ?? 0); } _log.Info("CheckIsExceededShippingCost: paid=" + paidShppingCost + " < actual=" + actualShippingsCost); if (shippings != null) { //"Excessive shipping cost. Because priority flat went up I get lots of “excesive” in cases like. We need to ignore those cases…" var activeShipping = shippings.FirstOrDefault(sh => sh.IsActive); if (activeShipping != null && activeShipping.ShippingMethod != null && activeShipping.ShippingMethod.Id == ShippingUtils.PriorityFlatShippingMethodId) { return new CheckResult() { IsSuccess = false } } ; } #region New Checking //price/1.17-shipping price-product cost-2 > -exc if (actualShippingsCost != null) { decimal totalThreashold = 0; decimal totalCost = 0; bool allHaveCost = true; foreach (var item in orderItems) { decimal?styleThreashold = null; if (item.StyleId.HasValue) { var featureValue = db.StyleFeatureTextValues.GetFeatureValueByStyleIdByFeatureId( item.StyleId.Value, StyleFeatureHelper.EXCESSIVE_SHIPMENT); if (featureValue != null && !String.IsNullOrEmpty(featureValue.Value)) { styleThreashold = StringHelper.TryGetDecimal(featureValue.Value); } var cost = db.StyleItemCaches.GetAllAsDto().Select(i => new { i.Id, i.Cost }).FirstOrDefault(i => i.Id == item.StyleItemId)?.Cost; if (cost.HasValue) { totalCost += cost.Value * item.QuantityOrdered; } else { allHaveCost = false; } } if (styleThreashold.HasValue) { totalThreashold += styleThreashold.Value * item.QuantityOrdered; } } if (allHaveCost) { var totalPaid = PriceHelper.RougeConvertToUSD(currency, orderItems.Sum(i => i.ShippingPrice + i.ItemPrice)); //Please ignore income disparity<1 like 180-111-825-1659 / 381-205-041-7263 if (totalThreashold < 1) { totalThreashold = 1; } var isValid = totalPaid / 1.17M - actualShippingsCost - totalCost - 2 > -totalThreashold; if (!isValid) { var excpectIncome = totalPaid / 1.17M - actualShippingsCost.Value - totalCost - 2; _log.Info(String.Format("Added Income disparity, income: {0}, totalPaid: {1}, actualShippingCost: {2}, totalCost: {3}", excpectIncome.ToString("C", culture), totalPaid, actualShippingsCost, totalCost)); var message = String.Format("Income disparity, income: {0}", excpectIncome.ToString("C", culture)); db.OrderComments.Add(new OrderComment() { OrderId = orderId, Message = message, Type = (int)CommentType.System, CreateDate = _time.GetAppNowTime(), }); db.Commit(); return(new CheckResult() { IsSuccess = true }); } } } #endregion #region Old Checking //TASK: When order has 2 robes, and they sent as 2 First class (like 102-1792536-3635439) don’t show Excess ship. cost if (shippings.Where(sh => sh.IsActive).All(sh => sh.ShippingMethodId == ShippingUtils.AmazonFirstClassShippingMethodId || sh.ShippingMethodId == ShippingUtils.FirstClassShippingMethodId || sh.ShippingMethodId == ShippingUtils.DhlEComSMParcelGroundShippingMethodId || sh.ShippingMethodId == ShippingUtils.DhlEComSMParcelExpeditedShippingMethodId)) { if (orderItems.All( i => ItemStyleHelper.GetFromItemStyleOrTitle(i.ItemStyle, i.Title) == ItemStyleType.Robe)) { return(new CheckResult() { IsSuccess = false }); } } //NOTE: used default threashold: $1 //NOTE: if price disparity <$2 it's ok var threshold = 2.0M; //TASK: When order has 2 or more items and service "Standard" made threashold $2 if (orderItems.Sum(oi => oi.QuantityOrdered) >= 2 && ShippingUtils.IsServiceStandard(marketOrder.InitialServiceType)) { threshold = 2.5M; } var withEmptyThreashold = 0; var withNotEmptyThreashold = 0; foreach (var item in orderItems) { decimal?styleThreashold = null; if (item.StyleId.HasValue) { var featureValue = db.StyleFeatureTextValues.GetFeatureValueByStyleIdByFeatureId( item.StyleId.Value, StyleFeatureHelper.EXCESSIVE_SHIPMENT); if (featureValue != null && !String.IsNullOrEmpty(featureValue.Value)) { styleThreashold = StringHelper.TryGetDecimal(featureValue.Value); } } if (styleThreashold.HasValue) { threshold += styleThreashold.Value * item.QuantityOrdered; withNotEmptyThreashold++; } else { withEmptyThreashold++; } } //if (withEmptyThreashold > 0) // threshold += 1.0M; //if (withNotEmptyThreashold == 0) // threshold = 1.0M; if (actualShippingsCost > 0 && paidShppingCost > 0 && paidShppingCost + threshold < actualShippingsCost) { bool isOverchargeSkipped = false; decimal totalIntlListingPriceInUSD = 0M; decimal totalUsListingPrice = 0; if (ShippingUtils.IsInternational(marketOrder.FinalShippingCountry)) { #region Calc US Shipping Cost decimal?actualUsShippingCost = 0M; var shippingService = ShippingUtils.StandardServiceName; //ShippingUtils.InitialShippingServiceIncludeUpgrade(marketOrder.InitialServiceType.Replace("i:", ""), //convert to local //marketOrder.UpgradeLevel); decimal?paidUsShippingCost = ShippingUtils.GetRougePaidUSShippingAmount(shippingService, orderItems.Sum(i => i.QuantityOrdered)); var usRates = RateHelper.GetRougeChipestUSRate(_log, _stampsRateProvider, _fromAddress, marketOrder, shippingService, orderItems, orderItems); if (usRates.Any()) { actualUsShippingCost = usRates.Sum(r => r.Amount); } #endregion foreach (var orderItem in orderItems) { totalIntlListingPriceInUSD += PriceHelper.RougeConvertToUSD(orderItem.ItemPriceCurrency, orderItem.ItemPrice); var usListingPrice = GetUSListingPrice(db, orderItem); if (usListingPrice == null) { totalUsListingPrice = 0; break; } totalUsListingPrice += (usListingPrice * orderItem.QuantityOrdered) ?? 0; } decimal?usEarnedValue = ((totalUsListingPrice) + (paidUsShippingCost ?? 0) - (actualUsShippingCost ?? 0)); decimal?marketEarnedValue = (totalIntlListingPriceInUSD + paidShppingCost - actualShippingsCost.Value); decimal?howMachEarnedValue = null; if (actualUsShippingCost.HasValue && paidUsShippingCost.HasValue && totalUsListingPrice > 0 && actualShippingsCost.HasValue) { howMachEarnedValue = (totalIntlListingPriceInUSD + paidShppingCost - actualShippingsCost.Value) - //how much we have earned now (totalUsListingPrice + paidUsShippingCost.Value - actualUsShippingCost.Value); //how much we have earned if we sell it in US isOverchargeSkipped = howMachEarnedValue > -threshold; //NOTE: Threashold } if (!isOverchargeSkipped) { //var message = internationalOverchargeSkip ? "No Excessive Shipping cost" : "Excessive Shipping cost"; var message = ""; if (totalUsListingPrice > 0) { message = String.Format("Income disparity: {0}+{1}-{2}={3} vs {4} => income diff.: {5}", //MarketHelper.GetShortName((int)marketOrder.Market, marketOrder.MarketplaceId), (totalUsListingPrice).ToString("C", culture), (paidUsShippingCost ?? 0).ToString("C", culture), (actualUsShippingCost ?? 0).ToString("C", culture), usEarnedValue?.ToString("C", culture), marketEarnedValue?.ToString("C", culture), (howMachEarnedValue ?? 0).ToString("C", culture)); } else { isOverchargeSkipped = true; //SKIP message = "Excessive Shipping validation: no similar US listing"; } db.OrderComments.Add(new OrderComment() { OrderId = orderId, Message = message, Type = (int)CommentType.System, CreateDate = _time.GetAppNowTime(), }); db.Commit(); } } else { //сделай пока $3.02 threashold var localThreshold = Math.Max(threshold, 3.02M); if (paidShppingCost + localThreshold < actualShippingsCost) { var message = String.Format("Paid shipping ({0}) lower shipping cost ({1}) more than threshold ({2})", (paidShppingCost).ToString("C", culture), (actualShippingsCost ?? 0).ToString("C", culture), (localThreshold).ToString("C", culture)); db.OrderComments.Add(new OrderComment() { OrderId = orderId, Message = message, Type = (int)CommentType.System, CreateDate = _time.GetAppNowTime(), }); } else { //NOTE: Temp Do Nothing isOverchargeSkipped = true; } } if (!isOverchargeSkipped) { db.OrderNotifies.Add( ComposeNotify(orderId, (int)OrderNotifyType.OverchargedShpppingCost, 1, paidShppingCost + "<" + actualShippingsCost, _time.GetAppNowTime())); db.Commit(); } if (!isOverchargeSkipped) { foreach (var orderItem in orderItems) { if (orderItem.SourceListingId.HasValue) { var listing = db.Listings.Get(orderItem.SourceListingId.Value); if (listing != null) { SystemActionHelper.RequestPriceRecalculation(db, _actionService, listing.Id, null); if (listing.Market == (int)MarketType.Walmart) //NOTE: need to update Second Day flag { SystemActionHelper.RequestItemUpdate(db, _actionService, listing.Id, null); } } } } } return(new CheckResult() { IsSuccess = !isOverchargeSkipped }); } #endregion return(new CheckResult() { IsSuccess = false }); }
public static void SetFinishStatus(IDbFactory dbFactory, ISystemActionService actionService, long pickListId, bool isFinished, DateTime when, long?by) { if (isFinished) { List <ScanItemDTO> pickListEntries; FBAPickList dbPickList; using (var db = dbFactory.GetRWDb()) { pickListEntries = (from pi in db.FBAPickListEntries.GetAll() join l in db.Listings.GetAll() on pi.ListingId equals l.Id join i in db.Items.GetAll() on l.ItemId equals i.Id where pi.FBAPickListId == pickListId select new ScanItemDTO() { Quantity = pi.Quantity, Barcode = i.Barcode, StyleId = i.StyleId, }).ToList(); dbPickList = db.FBAPickLists.GetAll().FirstOrDefault(pi => pi.Id == pickListId); dbPickList.Status = ShipmentStatuses.Finished; db.Commit(); } using (var invDb = dbFactory.GetInventoryRWDb()) { var scanOrder = new ScanOrderDTO() { Description = dbPickList.FBAPickListType + "-" + DateHelper.ToDateTimeString(dbPickList.CreateDate), FileName = dbPickList.Id.ToString(), OrderDate = when, IsFBA = true }; invDb.ItemOrderMappings.AddNewOrder(scanOrder, pickListEntries); } var styleIds = pickListEntries.Where(i => i.StyleId.HasValue).Select(i => i.StyleId.Value).ToArray(); using (var db = dbFactory.GetRWDb()) { SystemActionHelper.RequestQuantityDistribution(db, actionService, styleIds, by); } } else { FBAPickList dbPickList; using (var db = dbFactory.GetRWDb()) { dbPickList = db.FBAPickLists.GetAll().FirstOrDefault(pi => pi.Id == pickListId); dbPickList.Status = ShipmentStatuses.Default; db.Commit(); } var name = dbPickList.FBAPickListType + "-" + DateHelper.ToDateTimeString(dbPickList.CreateDate); using (var invDb = dbFactory.GetInventoryRWDb()) { var dbInvOrder = invDb.Orders.GetAll().FirstOrDefault(o => o.Description == name); if (dbInvOrder != null) { invDb.Orders.Remove(dbInvOrder); invDb.Commit(); } } } }
protected override DocumentInfo ComposeDocument(IUnitOfWork db, long companyId, MarketType market, string marketplaceId, IList <string> asinList) { Dictionary <string, int> _quantityToSend = new Dictionary <string, int>(); Log.Info("Get listings for quantity update"); var requestInfoes = db.SystemActions.GetAllAsDto() .Where(a => a.Type == (int)SystemActionType.UpdateOnMarketProductQuantity && a.Status != (int)SystemActionStatus.Done) .ToList(); var requestedSKUs = requestInfoes.Select(i => i.Tag).ToList(); var dtoItems = (from i in db.Items.GetAllViewAsDto() where requestedSKUs.Contains(i.SKU) && i.PublishedStatus == (int)PublishedStatuses.Published && i.Market == (int)market && (String.IsNullOrEmpty(marketplaceId) || i.MarketplaceId == marketplaceId) select i).ToList(); foreach (var dtoItem in dtoItems) { var requestInfo = requestInfoes.FirstOrDefault(i => i.Tag == dtoItem.SKU); var info = SystemActionHelper.FromStr <UpdateQtyInput>(requestInfo.InputData); dtoItem.Id = (int)(requestInfo?.Id ?? 0); dtoItem.RealQuantity = info.NewQty; } _quantityToSend = new Dictionary <string, int>(); if (dtoItems.Any()) { var quantMessages = new List <XmlElement>(); var index = 0; foreach (var listing in dtoItems) { //Skip processing duplicate SKU if (_quantityToSend.ContainsKey(listing.SKU)) { continue; } index++; var quantity = listing.RealQuantity; Log.Info("add listing " + index + ", listingId=" + listing.Id + ", SKU=" + listing.SKU + ", quantity=" + quantity); quantMessages.Add(FeedHelper.ComposeInventoryMessage(index, listing.SKU, quantity, null, _fulfillmentLatency)); _quantityToSend.Add(listing.SKU, quantity); } Log.Info("Compose feed"); var merchant = db.Companies.Get(companyId).AmazonFeedMerchantIdentifier; var document = FeedHelper.ComposeFeed(quantMessages, merchant, Type.ToString()); return(new DocumentInfo { XmlDocument = document, NodesCount = index }); } return(null); }