Пример #1
0
        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
            });
        }
Пример #4
0
        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);
            }
        }
Пример #6
0
        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();
            }
        }
Пример #7
0
        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;
        }
Пример #8
0
        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);
                    }
                }
            }
        }
Пример #10
0
        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();
            }
        }
Пример #11
0
        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();
            }
        }
Пример #12
0
        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);
                    }
                }
            }
        }
Пример #15
0
        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();
            }
        }
Пример #16
0
        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!");
            }
        }
Пример #17
0
        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);
        }
Пример #19
0
        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);
        }