コード例 #1
0
        public long AddAction(IUnitOfWork db,
                              SystemActionType type,
                              string tag,
                              ISystemActionInput inputData,
                              long?parentActionId,
                              long?by,
                              SystemActionStatus?status = SystemActionStatus.None)
        {
            var input = JsonConvert.SerializeObject(inputData);

            _logService.Info("AddAction, type=" + type + ", inputData=" + input);
            var newAction = new SystemActionDTO()
            {
                ParentId  = parentActionId,
                Status    = (int)status,
                Type      = (int)type,
                Tag       = tag,
                InputData = input,

                CreateDate = _time.GetUtcTime(),
                CreatedBy  = by,
            };

            db.SystemActions.AddAction(newAction);

            return(newAction.Id);
        }
コード例 #2
0
        public void UpdateAllShippedOrderStatus(TrackingManager trackingService,
                                                ITime time,
                                                IUnitOfWork db,
                                                ITrackingProvider trackingProvider,
                                                CompanyDTO company)
        {
            var carrierNames = ShippingServiceUtils.GetRelatedCarrierNames(trackingProvider.Carrier);

            var shippings = db.Orders.GetUnDeliveredMailInfoes(time.GetUtcTime(), true, null)
                            .OrderBy(o => o.OrderDate) //NOTE: first reprocess old trackings
                            .Where(sh => carrierNames.Contains(sh.Carrier))
                            .Take(500)
                            .ToList();

            shippings.AddRange(db.Orders.GetUnDeliveredShippingInfoes(time.GetUtcTime(), true, null)
                               .OrderBy(o => o.OrderDate) //NOTE: first reprocess old trackings
                               .Where(sh => carrierNames.Contains(sh.Carrier))
                               .Take(500)
                               .ToList());

            trackingService.UpdateOrderTracking(db,
                                                company,
                                                shippings,
                                                trackingProvider);
        }
コード例 #3
0
        public void SyncBegin(int?count)
        {
            if (_syncHistoryId.HasValue)
            {
                return;
            }

            using (var db = _dbFactory.GetRWDb())
            {
                var history = new SyncHistory
                {
                    StartDate      = _time.GetUtcTime(),
                    Type           = (int)_syncType,
                    Market         = (int)_market,
                    MarketplaceId  = _marketplaceId,
                    AdditionalData = _additionalData,
                    PingDate       = _time.GetUtcTime(),
                    Status         = (int)SyncStatus.InProgresss,
                    CountToProcess = count
                };
                db.SyncHistory.Add(history);
                db.Commit();

                _syncHistoryId = history.Id;
                _withErrors    = new List <string>();
                _withWarning   = new List <string>();
                _orderList     = new SynchronizedCollection <string>();

                _logger.Info("[Sync] start, type=" + _syncType
                             + ", market=" + _market
                             + ", marketplaceId=" + _marketplaceId
                             + ", id=" + _syncHistoryId);
            }
        }
コード例 #4
0
        public void ReProcessTrackNotifications(IDbFactory dbFactory)
        {
            var from      = _time.GetAppNowTime().AddDays(-42); //NOTE: Possible/not sure: After 42 days USPS not update/keep info
            var orderFrom = _time.GetAppNowTime().AddDays(-90);

            using (var db = dbFactory.GetRWDb())
            {
                var shippings = db.Orders.GetUnDeliveredShippingInfoes(_time.GetUtcTime(), false, null)
                                .Where(o => (!o.TrackingStateDate.HasValue || o.TrackingStateDate.Value > from) &&
                                       o.OrderDate > orderFrom)
                                .OrderBy(o => o.OrderDate)
                                .ToList();

                shippings.AddRange(db.Orders.GetUnDeliveredMailInfoes(_time.GetUtcTime(), false, null)
                                   .Where(o => (!o.TrackingStateDate.HasValue || o.TrackingStateDate.Value > from) &&
                                          o.OrderDate > orderFrom)
                                   .OrderBy(o => o.OrderDate)
                                   .ToList());

                var actionService       = new SystemActionService(_log, _time);
                var companyAddress      = new CompanyAddressService(_company);
                var addressService      = new AddressService(null, companyAddress.GetReturnAddress(MarketIdentifier.Empty()), companyAddress.GetPickupAddress(MarketIdentifier.Empty()));
                var notificationService = new NotificationService(_log, _time, dbFactory);

                var ruleList = new List <ITrackingRule>()
                {
                    //new NeverShippedTrackingRule(_log, notificationService, _time),
                    //new GetStuckTrackingRule(_log, notificationService, _time),
                    //new NoticeLeftTrackingRule(actionService, _log)
                };

                var trackingService = new TrackingManager(_log,
                                                          actionService,
                                                          addressService,
                                                          _emailService,
                                                          _time,
                                                          ruleList);


                foreach (var shipping in shippings)
                {
                    trackingService.CheckRules(db,
                                               shipping,
                                               shipping.TrackingStateEvent,
                                               shipping.TrackingStateDate,
                                               new List <TrackingRecord>()
                    {
                        new TrackingRecord()
                        {
                            Date    = shipping.TrackingStateDate,
                            Message = shipping.TrackingStateEvent,
                        }
                    },
                                               ruleList);
                }
            }
        }
コード例 #5
0
        public void UpdateMyPrice(AmazonApi api, IUnitOfWork db)
        {
            var lastUpdate = _time.GetUtcTime().AddHours(-12);

            var allItems = db.Listings
                           .GetAll()
                           .Where(p => p.Market == (int)api.Market &&
                                  p.MarketplaceId == api.MarketplaceId &&
                                  !p.IsRemoved &&
                                  (!p.PriceFromMarketUpdatedDate.HasValue ||
                                   p.PriceFromMarketUpdatedDate < lastUpdate))
                           .ToList();
            var index    = 0;
            var stepSize = 20;

            var stepSleeper = new StepSleeper(TimeSpan.FromSeconds(1), 5);

            while (index < allItems.Count)
            {
                try
                {
                    var itemsToUpdate = allItems.Skip(index).Take(stepSize).ToList();
                    var skuList       = itemsToUpdate.Select(i => i.SKU).ToList();
                    var items         = api.GetMyPriceBySKU(skuList);

                    foreach (var item in items)
                    {
                        var toUpdate = itemsToUpdate.FirstOrDefault(pi => pi.SKU == item.SKU);
                        if (toUpdate != null)
                        {
                            toUpdate.ListingPriceFromMarket     = item.ListingPriceFromMarket;
                            toUpdate.ShippingPriceFromMarket    = item.ShippingPriceFromMarket;
                            toUpdate.ReqularPriceFromMarket     = item.ReqularPriceFromMarket;
                            toUpdate.PriceFromMarketUpdatedDate = _time.GetUtcTime();
                        }
                    }
                }
                catch (Exception ex)
                {
                    _log.Error("Error when updating rank for index: " + index, ex);
                }
                index += stepSize;

                db.Commit();

                stepSleeper.NextStep();
            }
        }
コード例 #6
0
        private bool IsPrintLabelsInProgress(IUnitOfWork db, ISystemActionService actionService, ITime time)
        {
            var after = time.GetUtcTime().AddHours(-1);
            var printInProgressList = actionService.GetInProgressByType(db, SystemActionType.PrintBatch, after);

            return(printInProgressList.Any());
        }
コード例 #7
0
        private void AddActions(IUnitOfWork db, ParentItemDTO parentItemDto)
        {
            foreach (var item in parentItemDto.Variations)
            {
                var actions = new List <SystemActionType>()
                {
                    SystemActionType.UpdateOnMarketProductRelationship,
                    SystemActionType.UpdateOnMarketProductImage,
                };

                foreach (var actionType in actions)
                {
                    var newAction = new SystemActionDTO()
                    {
                        ParentId  = null,
                        Status    = (int)SystemActionStatus.None,
                        Type      = (int)actionType,
                        Tag       = item.Id.ToString(),
                        InputData = null,

                        CreateDate = _time.GetUtcTime(),
                        CreatedBy  = null,
                    };
                    db.SystemActions.AddAction(newAction);
                }
            }
            db.Commit();
        }
コード例 #8
0
        public IList <ItemDTO> CheckItemsSizeMappingIssue()
        {
            IList <ItemDTO> newSizeIssues = new List <ItemDTO>();

            using (var db = _dbFactory.GetRWDb())
            {
                var existListingWithIssues = db.ListingSizeIssues.GetAll().ToList();
                var allListingWithIssues   = db.Items.GetAllWithSizeMappingIssues().ToList();
                var existListingIds        = existListingWithIssues.Select(i => i.ListingId).ToList();

                newSizeIssues = allListingWithIssues
                                .Where(l => l.ListingEntityId.HasValue && !existListingIds.Contains(l.ListingEntityId.Value))
                                .ToList();

                foreach (var sizeIssue in newSizeIssues)
                {
                    db.ListingSizeIssues.Add(new ListingSizeIssue()
                    {
                        ListingId  = sizeIssue.ListingEntityId.Value,
                        AmazonSize = sizeIssue.Size,
                        StyleSize  = sizeIssue.StyleSize,

                        IsActual    = true,
                        ReCheckDate = _time.GetUtcTime(),
                        CreateDate  = _time.GetUtcTime(),
                    });
                }
                db.Commit();

                foreach (var existIssue in existListingWithIssues)
                {
                    var listingIssue = allListingWithIssues.FirstOrDefault(l => l.ListingEntityId == existIssue.ListingId);
                    if (listingIssue == null)
                    {
                        existIssue.IsActual = false;
                    }
                    else
                    {
                        existIssue.IsActual = true;
                    }
                    existIssue.ReCheckDate = _time.GetUtcTime();
                }
            }
            return(newSizeIssues.OrderByDescending(l => l.OpenDate).ToList());
        }
コード例 #9
0
        public CheckResult Check(IUnitOfWork db, DTOMarketOrder order, IList <ListingOrderDTO> items)
        {
            var result = DuplicateValidatorCheck(db, order, items);

            _log.Info("CheckDuplicate, result=" + result.IsSuccess + ", message=" + result.Message);

            if (!result.IsSuccess)
            {
                db.OrderNotifies.Add(
                    ComposeNotify(order.Id,
                                  (int)OrderNotifyType.Duplicate,
                                  1,
                                  result.Message,
                                  _time.GetAppNowTime()));

                db.Commit();

                var emailInfo = new DuplicateEmailInfo(_emailService.AddressService,
                                                       order.CustomerOrderId,
                                                       (MarketType)order.Market,
                                                       new DuplicateOrdersDTO
                {
                    Items        = items,
                    OrderNumbers = result.AdditionalData
                },
                                                       order.BuyerName,
                                                       order.BuyerEmail);

                _emailService.SendEmail(emailInfo, CallSource.Service);
                _log.Info("Send duplicated order email, orderId=" + order.Id);

                db.OrderEmailNotifies.Add(new OrderEmailNotify()
                {
                    OrderNumber = order.OrderId,
                    Reason      = "System emailed, found duplicate",
                    Type        = (int)OrderEmailNotifyType.OutputDuplicateAlertEmail,
                    CreateDate  = _time.GetUtcTime(),
                });

                db.OrderComments.Add(new OrderComment()
                {
                    OrderId    = order.Id,
                    Message    = "[System] Duplicate order alert email sent",
                    Type       = (int)CommentType.OutputEmail,
                    CreateDate = _time.GetAppNowTime(),
                    UpdateDate = _time.GetAppNowTime()
                });

                db.Commit();
            }
            return(result);
        }
コード例 #10
0
        public IList <TrackingState> TrackShipments(IList <TrackingNumberToCheckDto> trackingNumbers)
        {
            var results            = new List <TrackingState>();
            var trackingNumberList = trackingNumbers.Select(t => t.TrackingNumber).ToList();

            foreach (var trackingNumber in trackingNumberList)
            {
                _log.Info("Begin get CA track info=" + trackingNumber);
                var perOneTrackingResult = _api.GetTrackingField(new List <string>()
                {
                    trackingNumber
                });
                if (perOneTrackingResult.Status == CallStatus.Fail)
                {
                    _log.Info(String.Format("Error, tracking number={0}: {1}", trackingNumber,
                                            perOneTrackingResult.Message));
                    results.Add(new TrackingState()
                    {
                        TrackingNumber = trackingNumber,
                        Records        = new List <TrackingRecord>()
                        {
                            new TrackingRecord()
                            {
                                Message = TrackingHelper.BuildUndefinedMessage(perOneTrackingResult.Message),
                                Date    = _time.GetUtcTime(),
                            }
                        }
                    });
                }
                else
                {
                    foreach (var result in perOneTrackingResult.Data)
                    {
                        _log.Info("CA tracking result=" + result.TrackingNumber + ", last status=" +
                                  (result.Records != null && result.Records.Any()
                                      ? result.Records[0].Message + " at " + result.Records[0].Date
                                      : ""));
                    }
                    results.AddRange(perOneTrackingResult.Data);
                }
            }

            foreach (var info in results)
            {
                if (info.Records != null)
                {
                    info.Records.ForEach(r => r.Source = TrackingStatusSources.CanadaPost);
                }
            }

            return(results);
        }
コード例 #11
0
        public void Import(string filename)
        {
            var lines = File.ReadAllLines(filename);

            using (var db = _dbFactory.GetRWDb())
            {
                var existBarcodes = db.CustomBarcodes.GetAllAsDto().ToList();

                var index      = 0;
                var existIndex = 0;
                foreach (var line in lines)
                {
                    if (String.IsNullOrEmpty(line))
                    {
                        continue;
                    }
                    var barcode = line.Trim();
                    var exist   = existBarcodes.FirstOrDefault(b => b.Barcode == barcode);
                    if (exist == null)
                    {
                        var newBarcode = new CustomBarcode()
                        {
                            Barcode    = barcode,
                            CreateDate = _time.GetUtcTime()
                        };

                        db.CustomBarcodes.Add(newBarcode);

                        existBarcodes.Add(new CustomBarcodeDTO()
                        {
                            Barcode = barcode
                        });

                        index++;
                        _log.Info("Added: " + index);
                    }
                    else
                    {
                        existIndex++;
                        _log.Info("Exist: " + existIndex);
                    }

                    if (index % 200 == 0)
                    {
                        db.Commit();
                    }
                }
            }
        }
コード例 #12
0
        public void ProcessResult(CheckResult result,
                                  Order dbOrder,
                                  DTOOrder order,
                                  IList <ListingOrderDTO> orderItems)
        {
            if (result.IsSuccess)
            {
                _log.Info("Send sign confirmation request order email, orderId=" + order.Id);

                var alreadySend = _db.OrderEmailNotifies.IsExist(order.OrderId,
                                                                 OrderEmailNotifyType.OutputSignConfirmationEmail);

                if (alreadySend)
                {
                    return;
                }

                var emailInfo = new SignConfirmationRequestEmailInfo(_emailService.AddressService,
                                                                     null,
                                                                     order.OrderId,
                                                                     (MarketType)order.Market,
                                                                     orderItems,
                                                                     //NOTE: make sense only express or not
                                                                     ShippingUtils.IsServiceNextDay(order.InitialServiceType) ? ShippingTypeCode.PriorityExpress : ShippingTypeCode.Standard,
                                                                     order.BuyerName,
                                                                     order.BuyerEmail);

                _emailService.SendEmail(emailInfo, CallSource.Service);

                _db.OrderEmailNotifies.Add(new OrderEmailNotify()
                {
                    OrderNumber = order.OrderId,
                    Reason      = "System emailed, request signconfirmation",
                    Type        = (int)OrderEmailNotifyType.OutputSignConfirmationEmail,
                    CreateDate  = _time.GetUtcTime(),
                });

                _db.OrderComments.Add(new OrderComment()
                {
                    OrderId    = order.Id,
                    Message    = "[System] Sign Confirmation email sent",
                    Type       = (int)CommentType.Address,
                    CreateDate = _time.GetAppNowTime(),
                    UpdateDate = _time.GetAppNowTime()
                });

                _db.Commit();
            }
        }
コード例 #13
0
        public void CheckOrders()
        {
            var from = _time.GetAppNowTime().AddDays(-2);

            using (var invDb = _dbFactory.GetInventoryRWDb())
            {
                var ordersToCheck = invDb.Orders.GetAll().Where(o => o.OrderDate > from &&
                                                                !o.LastCheckedDate.HasValue).ToList();

                foreach (var order in ordersToCheck)
                {
                    if (order.OrderDate < _time.GetUtcTime().AddHours(-2))
                    {
                        _log.Info("Checking order: " + order.OrderDate);
                        using (var db = _dbFactory.GetRDb())
                        {
                            var items = db.Scanned.GetScanItemAsDto()
                                        .Where(i => i.OrderId == order.Id)
                                        .OrderBy(i => i.Barcode)
                                        .ToList();
                            var woStyleItemIds = items.Where(i => !i.StyleItemId.HasValue).ToList();

                            if (woStyleItemIds.Any())
                            {
                                _log.Info("Send notification, orderDate=" + order.OrderDate
                                          + ", barcodes=" + woStyleItemIds.Count);

                                SendWoStyleNotification(order.OrderDate,
                                                        order.Description,
                                                        woStyleItemIds.Select(i => i.Barcode).ToList());
                            }
                            else
                            {
                                _log.Info("All barcodes have styles");
                            }

                            order.LastCheckedDate = _time.GetAppNowTime();
                            invDb.Commit();
                        }
                    }
                }
            }
        }
 public override void SetLastSyncDate(ISettingsService settings, MarketType market, string marketplaceId, DateTime?when)
 {
     settings.SetListingsReadDate(_time.GetUtcTime(), market, marketplaceId);
     settings.SetListingsManualSyncRequest(false, market, marketplaceId);
 }
コード例 #15
0
        public void ProcessCancellations(IUnitOfWork db, string filterTag)
        {
            //NOTE: reprocess cancel request every 2 hours
            var maxLastAttemptDate = _time.GetUtcTime().AddHours(-2);

            var cancelActions    = _actionService.GetUnprocessedByType(db, SystemActionType.UpdateOnMarketCancelOrder, maxLastAttemptDate, null);
            var actionOutputList = new Dictionary <long, CancelOrderOutput>();

            if (!String.IsNullOrEmpty(filterTag))
            {
                cancelActions = cancelActions.Where(a => a.Tag == filterTag).ToList();
            }

            foreach (var action in cancelActions)
            {
                try
                {
                    var data   = JsonConvert.DeserializeObject <CancelOrderInput>(action.InputData);
                    var orders = db.Orders.GetAllByCustomerOrderNumber(data.OrderNumber);
                    if (!orders.Any())
                    {
                        _log.Info(_api.Market + "_" + _api.MarketplaceId + ": Can't find orderId=" + data.OrderNumber);
                        continue;
                    }

                    if (orders[0].Market != (int)_api.Market ||
                        (!String.IsNullOrEmpty(_api.MarketplaceId) &&
                         orders[0].MarketplaceId != _api.MarketplaceId))
                    {
                        //_log.Info("skip order=" + data.OrderNumber + ", market=" + order.Market + ", marketplace=" + order.MarketplaceId);
                        continue;
                    }

                    _log.Info("Order to cancel: " + _api.Market + "_" + _api.MarketplaceId + ", actionId=" + action.Id +
                              ", orderId=" + data.OrderNumber + ", itemId=" + data.ItemId);

                    var itemIdList        = (data.ItemId ?? "").Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    var orderIdList       = orders.Select(o => o.Id).ToList();
                    var allOrderItems     = db.OrderItems.GetWithListingInfo().Where(i => i.OrderId.HasValue && orderIdList.Contains(i.OrderId.Value)).ToList();
                    var orderItemToCancel = itemIdList.Any() ? allOrderItems.Where(i => itemIdList.Contains(i.SourceMarketId)).ToList() : allOrderItems;

                    CallResult <DTOOrder> result;
                    if (orderItemToCancel.Count >= 1)
                    {
                        var orderToCancel = orders.FirstOrDefault(o => o.Id == orderItemToCancel[0].OrderId);
                        result = _api.CancelOrder(orderToCancel.MarketOrderId, orderItemToCancel);
                    }
                    else
                    {
                        result = CallResult <DTOOrder> .Fail("No items to cancel", null);
                    }


                    if (result.IsSuccess)
                    {
                        var output = new CancelOrderOutput()
                        {
                            IsProcessed   = true,
                            ResultMessage = "Cancelled by API"
                        };
                        _actionService.SetResult(db, action.Id, SystemActionStatus.Done, output);
                        db.Commit();
                    }
                    else
                    {
                        var output = new CancelOrderOutput()
                        {
                            IsProcessed   = true,
                            ResultMessage = "Fail: " + result.Message
                        };
                        _actionService.SetResult(db, action.Id, SystemActionStatus.None, output);
                    }
                }
                catch (Exception ex)
                {
                    if (action.AttemptNumber > 10)
                    {
                        var output = new CancelOrderOutput()
                        {
                            IsProcessed   = true,
                            ResultMessage = ex.Message
                        };
                        _actionService.SetResult(db, action.Id, SystemActionStatus.Fail, output);
                        db.Commit();
                    }

                    _log.Error("OrderCancellation.Process", ex);
                }
            }
        }
コード例 #16
0
        public IList <CheckResult <AddressDTO> > CheckAddress(CallSource callSource,
                                                              IUnitOfWork db,
                                                              AddressDTO address,
                                                              long?orderId,
                                                              out AddressDTO addressWithCorrection)
        {
            if (orderId.HasValue && orderId.Value == 0)
            {
                throw new ArgumentOutOfRangeException("order.Id", "Should be non zero");
            }

            addressWithCorrection = null;

            var checkResults = _addressService.CheckAddress(callSource,
                                                            address);

            OrderNotify dbStampsOrderNotify = null;

            foreach (var subResult in checkResults)
            {
                //Stamps
                if (subResult.AdditionalData?[0] == OrderNotifyType.AddressCheckStamps.ToString())
                {
                    if (orderId.HasValue)
                    {
                        dbStampsOrderNotify = new OrderNotify()
                        {
                            OrderId    = orderId.Value,
                            Type       = (int)OrderNotifyType.AddressCheckStamps,
                            Message    = StringHelper.Substring(subResult.Message, 512),
                            Status     = (int)subResult.Status,
                            CreateDate = _time.GetAppNowTime()
                        };

                        db.OrderNotifies.Add(dbStampsOrderNotify);
                    }
                }

                //Previous correction address
                if (subResult.AdditionalData?[0] == OrderNotifyType.AddressCheckWithPerviousCorrection.ToString())
                {
                    addressWithCorrection = subResult.Data;

                    if (orderId.HasValue)
                    {
                        db.OrderNotifies.Add(new OrderNotify()
                        {
                            OrderId    = orderId.Value,
                            Type       = (int)OrderNotifyType.AddressCheckWithPerviousCorrection,
                            Message    = StringHelper.Substring(subResult.Message, 512),
                            Status     = subResult.Status,
                            CreateDate = _time.GetUtcTime()
                        });
                    }

                    if (subResult.Status < (int)AddressValidationStatus.Invalid &&
                        subResult.Status != (int)AddressValidationStatus.None)
                    {
                        if (addressWithCorrection != null &&
                            String.IsNullOrEmpty(addressWithCorrection.Address1) &&
                            String.IsNullOrEmpty(addressWithCorrection.Address2) &&
                            String.IsNullOrEmpty(addressWithCorrection.City) &&
                            String.IsNullOrEmpty(addressWithCorrection.State) &&
                            String.IsNullOrEmpty(addressWithCorrection.Country) &&
                            String.IsNullOrEmpty(addressWithCorrection.Zip) &&
                            String.IsNullOrEmpty(addressWithCorrection.ZipAddon))
                        {
                            addressWithCorrection = null;
                        }

                        if (addressWithCorrection != null)
                        {
                            /*
                             * Похоже идея автоматически менять адрес на предыдущий не совсем хорошая, есть клиент например который хотел послать посылку на новый адрес а мы послали на старый 110-4229580-1843404
                             * Давай теперь вместо автоматического исправления адреса просто писать коммент, «previous delivery to %Old_Address% was successful”
                             */

                            if (orderId.HasValue)
                            {
                                var addressString = AddressHelper.ToString(addressWithCorrection, ", ");

                                db.OrderComments.Add(new OrderComment()
                                {
                                    OrderId    = orderId.Value,
                                    Message    = String.Format("[System] Previous delivery to \"{0}\" was successful", addressString),
                                    Type       = (int)CommentType.Address,
                                    CreateDate = _time.GetUtcTime()
                                });
                            }

                            //NOTE: Previous correction address uses only to create order comment
                            addressWithCorrection = null;
                        }
                    }
                }

                if (subResult.AdditionalData?[0] == OrderNotifyType.AddressCheckMelissa.ToString())
                {
                    //Nothing
                }

                if (subResult.AdditionalData?[0] == OrderNotifyType.AddressCheckGoogleGeocode.ToString())
                {
                    if (orderId.HasValue)
                    {
                        db.OrderNotifies.Add(new OrderNotify()
                        {
                            OrderId    = orderId.Value,
                            Type       = (int)OrderNotifyType.AddressCheckGoogleGeocode,
                            Message    = StringHelper.Substring(subResult.Message, 512),
                            Status     = subResult.Status,
                            CreateDate = _time.GetUtcTime()
                        });
                    }
                }
                if (subResult.AdditionalData?[0] == OrderNotifyType.AddressCheckFedex.ToString())
                {
                    if (orderId.HasValue)
                    {
                        db.OrderNotifies.Add(new OrderNotify()
                        {
                            OrderId    = orderId.Value,
                            Type       = (int)OrderNotifyType.AddressCheckFedex,
                            Message    = StringHelper.Substring(subResult.Message, 512),
                            Status     = subResult.Status,
                            CreateDate = _time.GetUtcTime()
                        });
                    }

                    var stampsResult = checkResults.FirstOrDefault(r => r.AdditionalData[0] == OrderNotifyType.AddressCheckStamps.ToString());
                    if (stampsResult != null && stampsResult.Status >= (int)AddressValidationStatus.Invalid)
                    {
                        if (subResult.Status < (int)AddressValidationStatus.Invalid)
                        {
                            if (addressWithCorrection == null &&
                                subResult.Data != null)
                            {
                                var correctionCandidate = subResult.Data;
                                correctionCandidate.FullName = address.FullName;
                                //TASK: If stamps verify it replace it, and don’t show errors.
                                var addressCandidateResults = _addressService.CheckAddress(callSource,
                                                                                           correctionCandidate,
                                                                                           new Core.Models.Settings.AddressProviderType[] { Core.Models.Settings.AddressProviderType.Stamps });

                                var stampsCandidateResult = addressCandidateResults.FirstOrDefault(r => r.AdditionalData[0] == OrderNotifyType.AddressCheckStamps.ToString());
                                if (stampsCandidateResult.Status < (int)AddressValidationStatus.Invalid)
                                {
                                    _log.Info("Replacing address to Fedex Effective address");

                                    stampsResult.Status = stampsCandidateResult.Status;
                                    if (dbStampsOrderNotify != null)
                                    {
                                        dbStampsOrderNotify.Status = stampsCandidateResult.Status;
                                    }

                                    if (orderId.HasValue)
                                    {
                                        db.OrderComments.Add(new OrderComment()
                                        {
                                            OrderId    = orderId.Value,
                                            Message    = String.Format("[System] Address was replaced by Fedex \"Effective address\""),
                                            Type       = (int)CommentType.Address,
                                            CreateDate = _time.GetUtcTime()
                                        });
                                    }

                                    addressWithCorrection = subResult.Data;
                                }
                            }
                        }
                    }
                }
            }

            return(checkResults);
        }
コード例 #17
0
        public void Process(IUnitOfWork db, EmailReadingResult result)
        {
            if (result.Status == EmailMatchingResultStatus.New &&
                result.HasMatches)
            {
                var noHtml  = StringHelper.TrimTags(result.Email.Message ?? "");
                var message = StringHelper.Substring(noHtml, 70).ToLower();
                //to remove the signature confirmation
                var removeSignConfirmation =
                    message.IndexOf("remove signature confirmation", StringComparison.OrdinalIgnoreCase) >= 0 ||
                    message.IndexOf("remove signature", StringComparison.OrdinalIgnoreCase) >= 0 ||
                    message.IndexOf("remove the signature", StringComparison.OrdinalIgnoreCase) >= 0;

                if (removeSignConfirmation)
                {
                    var orderNumber = result.MatchedIdList.FirstOrDefault();
                    _log.Info("Received RemoveSignatureConfirmation request, orderNumber=" + orderNumber);

                    if (!String.IsNullOrEmpty(orderNumber))
                    {
                        var isExistRemoveSignConfirmation = db.OrderEmailNotifies.IsExist(orderNumber,
                                                                                          OrderEmailNotifyType.InputRemoveSignConfirmationEmail);
                        if (!isExistRemoveSignConfirmation) //NOTE: First remove sign confirmation request
                        {
                            result.WasEmailProcessed = true;
                            _log.Info("RemoveSignatureEmailRule, WasEmailProcessed=" + result.WasEmailProcessed);

                            var comment = String.Empty;
                            var order   = db.Orders.GetByOrderNumber(orderNumber);
                            //var now = _time.GetAppNowTime();
                            //var isWeekday = db.Dates.IsWorkday(_time.GetAppNowTime());

                            if (order.OrderStatus == OrderStatusEnumEx.Shipped
                                //|| (isWeekday && now.Hour > 15)
                                )
                            {
                                //comment = "Skipped. Order already shipped or request came after 3PM on weekday";
                                var commentText = "";
                                if (order.OrderStatus == OrderStatusEnumEx.Shipped)
                                {
                                    commentText = "[System] Remove signature confirmation request came after the order shipped";
                                    comment     = "Skipped. Order already shipped";
                                }
                                //if (isWeekday && now.Hour > 15)
                                //{
                                //    commentText = "[System] Remove signature confirmation request came after 3PM on weekday";
                                //    comment = "Skipped. Request came after 3PM on weekday";
                                //}
                                db.OrderComments.Add(new OrderComment()
                                {
                                    OrderId    = order.Id,
                                    Message    = commentText,
                                    Type       = (int)CommentType.Address,
                                    CreateDate = _time.GetAppNowTime(),
                                    UpdateDate = _time.GetAppNowTime()
                                });

                                var emailInfo = new RejectRemoveSignConfirmationEmailInfo(_emailService.AddressService,
                                                                                          null,
                                                                                          orderNumber,
                                                                                          (MarketType)order.Market,
                                                                                          order.BuyerName,
                                                                                          order.BuyerEmail);

                                _emailService.SendEmail(emailInfo, CallSource.Service);
                            }
                            else
                            {
                                //Tring to remove signature

                                if (order.OrderStatus == OrderStatusEnumEx.Unshipped ||
                                    order.OrderStatus == OrderStatusEnumEx.PartiallyShipped ||
                                    order.OrderStatus == OrderStatusEnumEx.Pending)
                                {
                                    if (order.IsSignConfirmation)
                                    {
                                        order.IsSignConfirmation = false;
                                        _log.Info("Updated IsSignConfirmation=false, orderNumber=" + order.AmazonIdentifier);

                                        db.OrderComments.Add(new OrderComment()
                                        {
                                            OrderId    = order.Id,
                                            Message    = "[System] Signature confirmation was removed per buyer request",
                                            Type       = (int)CommentType.Address,
                                            CreateDate = _time.GetAppNowTime(),
                                            UpdateDate = _time.GetAppNowTime()
                                        });

                                        _actionService.AddAction(db,
                                                                 SystemActionType.UpdateRates,
                                                                 order.AmazonIdentifier,
                                                                 new UpdateRatesInput()
                                        {
                                            OrderId = order.Id
                                        },
                                                                 null,
                                                                 null);

                                        var orderItems = db.Listings.GetOrderItems(order.Id);
                                        var emailInfo  = new AcceptRemoveSignConfirmationEmailInfo(_emailService.AddressService,
                                                                                                   null,
                                                                                                   orderNumber,
                                                                                                   (MarketType)order.Market,
                                                                                                   orderItems,
                                                                                                   order.BuyerName,
                                                                                                   order.BuyerEmail);

                                        _emailService.SendEmail(emailInfo, CallSource.Service);

                                        comment = "Sign confirmation removed + emailed";
                                    }
                                    else
                                    {
                                        db.OrderComments.Add(new OrderComment()
                                        {
                                            OrderId    = order.Id,
                                            Message    = "[System] Remove signature confirmation request skipped. Signature confirmation was already removed",
                                            Type       = (int)CommentType.Address,
                                            CreateDate = _time.GetAppNowTime(),
                                            UpdateDate = _time.GetAppNowTime()
                                        });

                                        comment = "Skipped. Already removed";
                                    }
                                }
                                else
                                {
                                    //NOTE: If OrderStatus=Canceled
                                    comment = "Skipped. Order status=" + order.OrderStatus;
                                }
                            }

                            var dbBuyer = db.Buyers.GetFiltered(b => b.Email == result.Email.From).FirstOrDefault();
                            if (dbBuyer != null)
                            {
                                dbBuyer.RemoveSignConfirmation     = true;
                                dbBuyer.RemoveSignConfirmationDate = _time.GetUtcTime();
                                _log.Info("Set RemoveSignConfirmation=true, buyerEmail=" + result.Email.From);
                            }
                            else
                            {
                                _log.Info("Can't find buyerEmail=" + result.Email.From);
                            }

                            db.OrderEmailNotifies.Add(new OrderEmailNotify()
                            {
                                OrderNumber = orderNumber,
                                Type        = (int)OrderEmailNotifyType.InputRemoveSignConfirmationEmail,
                                Reason      = comment,
                                CreateDate  = _time.GetUtcTime()
                            });

                            db.Commit();
                        }
                        else
                        {
                            _log.Info("Repeated RemoveSignConfirmation email, no action");
                        }
                    }
                    else
                    {
                        _log.Info("Can't RemoveSignConfirmation, no matching orders!");
                    }
                }
            }
        }
コード例 #18
0
        public void ProcessNewListingsWithItems(IUnitOfWork db, IMarketApi api, ITime time, IList <ItemDTO> items)
        {
            _log.Debug("Begin process new items");

            foreach (var dtoItem in items)
            {
                try
                {
                    if (dtoItem.IsExistOnAmazon == true)
                    {
                        _syncInfo.AddSuccess(dtoItem.ASIN, "New listing item was filled by Amazon");

                        if (String.IsNullOrEmpty(dtoItem.ParentASIN))
                        {
                            _syncInfo.AddWarning(dtoItem.ASIN, "Empty ParentASIN");
                        }

                        dtoItem.IsAmazonParentASIN   = !String.IsNullOrEmpty(dtoItem.ParentASIN);
                        dtoItem.LastUpdateFromAmazon = time.GetUtcTime();
                        //Add new item, no need to additional check
                        dtoItem.StyleString = SkuHelper.RetrieveStyleIdFromSKU(db,
                                                                               dtoItem.SKU,
                                                                               dtoItem.Name);


                        var dbItem = db.Items.StoreItemIfNotExist(_itemHistoryService,
                                                                  "ListingLineProcessing",
                                                                  dtoItem,
                                                                  api.Market,
                                                                  api.MarketplaceId,
                                                                  _companyId,
                                                                  time.GetAppNowTime());

                        //NOTE: fresh size (for some reason can start came emtpy)
                        dtoItem.Size = dbItem.Size;

                        if (!dbItem.StyleItemId.HasValue)
                        {
                            //Keep exists styleId
                            dtoItem.StyleId = dbItem.StyleId;

                            var styleItem = FindOrCreateStyleItem(db, dtoItem);
                            if (styleItem != null)
                            {
                                if (styleItem.StyleItemId > 0)
                                {
                                    dbItem.StyleId     = styleItem.StyleId;
                                    dbItem.StyleItemId = styleItem.StyleItemId;
                                }
                                else
                                {
                                    if (!dbItem.StyleId.HasValue)
                                    {
                                        dbItem.StyleId = styleItem.StyleId;
                                    }
                                }
                                _log.Debug(String.Format("Set for ASIN={0}, styleId={1}, styleItemId={2}",
                                                         dtoItem.ASIN,
                                                         styleItem.StyleId,
                                                         styleItem.StyleItemId));
                            }
                            db.Commit();
                        }

                        if (!String.IsNullOrEmpty(dtoItem.Barcode) &&
                            dbItem.StyleItemId.HasValue)
                        {
                            _styleManager.StoreOrUpdateBarcode(db,
                                                               dbItem.StyleItemId.Value,
                                                               dtoItem.Barcode);
                        }

                        var dbListing = db.Listings.StoreOrUpdate(dtoItem,
                                                                  dbItem,
                                                                  api.Market,
                                                                  api.MarketplaceId,
                                                                  time.GetAppNowTime());

                        dtoItem.IsDefault = dbListing.IsDefault;

                        _syncInfo.AddSuccess(dtoItem.ASIN, "New listing item was stored");
                        _log.Debug("Store item:" + dbItem.ASIN + ", parentASIN=" + dbItem.ParentASIN + ", SKU=" + dtoItem.SKU + ", StyleString=" + dbItem.StyleString + ", quantity=" + dtoItem.RealQuantity);
                    }
                    else
                    {
                        _syncInfo.AddWarning(dtoItem.ASIN, "Item is not filled by Amazon (new listing item)");
                        _log.Warn("Item is not filled by Amazon (new listing item), item=" + dtoItem.ASIN);
                    }
                }
                catch (Exception ex)
                {
                    _syncInfo.AddError(dtoItem.ASIN, "Error while creating item", ex);
                    _log.Error(string.Format("Error while creating item, asin={0}", dtoItem.ASIN), ex);
                }
            }
            _log.Debug("End process new items");
        }
コード例 #19
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!");
            }
        }
コード例 #20
0
        private void ProcessItems(IUnitOfWork db,
                                  IMarketApi api,
                                  ITime time,
                                  IList <ItemDTO> listings)
        {
            var syncInfo = Context.SyncInformer;

            Log.Debug("ProcessItems begin");

            var allDbListings = db.Listings.GetAll().Where(l => l.Market == (int)api.Market &&
                                                           (l.MarketplaceId == api.MarketplaceId ||
                                                            String.IsNullOrEmpty(api.MarketplaceId)))
                                .ToList();

            var allDbItems = db.Items.GetAll().Where(l => l.Market == (int)api.Market &&
                                                     (l.MarketplaceId == api.MarketplaceId ||
                                                      String.IsNullOrEmpty(api.MarketplaceId)))
                             .ToList();


            var updateItemIds     = new List <long>();
            var existsListingSKUs = new List <string>();

            //STEP 1. Update listings ASINs
            Log.Debug("Update ASINs begin");
            foreach (var listing in listings)
            {
                var dbListing = allDbListings.FirstOrDefault(l => l.SKU == listing.SKU);
                if (dbListing != null)
                {
                    existsListingSKUs.Add(listing.SKU);

                    if (dbListing.ListingId != listing.ListingId)
                    {
                        dbListing.ListingId = listing.ListingId;
                    }
                    if (dbListing.ASIN != listing.ASIN)
                    {
                        dbListing.ASIN = listing.ASIN;
                    }

                    if (dbListing.AmazonRealQuantity != listing.RealQuantity)
                    {
                        Log.Debug("Price changed: " + dbListing.SKU + ": " + dbListing.AmazonRealQuantity + "=>" + listing.RealQuantity);
                        dbListing.AmazonRealQuantity           = listing.RealQuantity;
                        dbListing.AmazonRealQuantityUpdateDate = time.GetAppNowTime();
                    }
                    if (dbListing.AmazonCurrentPrice != listing.CurrentPrice)
                    {
                        Log.Debug("Price changed: " + dbListing.SKU + ": " + dbListing.AmazonCurrentPrice + "=>" + listing.CurrentPrice);
                        dbListing.AmazonCurrentPrice           = listing.CurrentPrice;
                        dbListing.AmazonCurrentPriceUpdateDate = time.GetAppNowTime();
                    }

                    var dbItem = allDbItems.FirstOrDefault(i => i.Id == dbListing.ItemId);
                    if (dbItem != null)
                    {
                        if (dbItem.ASIN != listing.ASIN)
                        {
                            Log.Debug("Item ASIN changed: " + dbItem.Id + ": " + dbItem.ASIN + " => " + listing.ASIN);
                            dbItem.ASIN = listing.ASIN;
                        }
                        if (dbItem.SourceMarketId != listing.ASIN)
                        {
                            dbItem.SourceMarketId = listing.ASIN;
                        }
                        if (dbItem.ItemPublishedStatusFromMarket != listing.PublishedStatus)
                        {
                            dbItem.ItemPublishedStatusFromMarket     = listing.PublishedStatus;
                            dbItem.ItemPublishedStatusFromMarketDate = time.GetAppNowTime();
                        }
                        if (listing.PublishedStatus == (int)PublishedStatuses.Published)
                        {
                            dbItem.ItemPublishedStatusBeforeRepublishing = dbItem.ItemPublishedStatus;
                            dbItem.ItemPublishedStatus       = listing.PublishedStatus;
                            dbItem.ItemPublishedStatusReason = "Listings report";
                            dbItem.ItemPublishedStatusDate   = time.GetAppNowTime();
                        }

                        updateItemIds.Add(dbItem.Id);
                    }
                }
            }

            db.Commit();
            Log.Debug("Update ASINs end");

            //STEP 1.2. Market all not exists as unpublished
            Log.Debug("Update items Unpublished begin");
            var notUpdatedItems = allDbItems.Where(i => !updateItemIds.Contains(i.Id)).ToList();

            Log.Debug("Not updated items: " + notUpdatedItems.Count());
            foreach (var dbItem in notUpdatedItems)
            {
                if (dbItem.ItemPublishedStatus == (int)PublishedStatuses.Published)
                {
                    Log.Debug("Status changes for: " + dbItem.ASIN + " - " + dbItem.ItemPublishedStatus + "=>" + PublishedStatuses.New);
                    dbItem.ItemPublishedStatusBeforeRepublishing = dbItem.ItemPublishedStatus;
                    dbItem.ItemPublishedStatusReason             = "System Warning: the listing has the Published status, but it does not appear in the listing report.";
                    dbItem.ItemPublishedStatusDate = time.GetAppNowTime();
                    dbItem.ItemPublishedStatus     = (int)PublishedStatuses.New;
                    dbItem.IsAmazonParentASIN      = false;
                    dbItem.IsExistOnAmazon         = false;
                }
            }
            db.Commit();

            Log.Debug("Update items Unpublished end");


            //STEP 2. Update ParentASINs
            Log.Debug("Update ParentASINs begin");
            var newListingsWithError = new List <ItemDTO>();

            try
            {
                api.FillWithAdditionalInfo(Log,
                                           time,
                                           listings,
                                           IdType.SKU,
                                           ItemFillMode.Defualt,
                                           out newListingsWithError);
            }
            catch (Exception ex) //Can continue if only part of records was filled
            {
                syncInfo.AddError("", "Can't fill new listing items with additional info", ex);
                Log.Error("Can't fill new listing items with additional info", ex);
            }

            var allDbParents = db.ParentItems.GetAll().Where(pi => pi.Market == (int)api.Market &&
                                                             (pi.MarketplaceId == api.MarketplaceId ||
                                                              String.IsNullOrEmpty(api.MarketplaceId))).ToList();

            var updatedParentIds = new List <long>();

            foreach (var listing in listings)
            {
                var dbListing    = allDbListings.FirstOrDefault(l => l.SKU == listing.SKU);
                var dbItem       = dbListing == null ? null : allDbItems.FirstOrDefault(i => i.Id == dbListing.ItemId);
                var dbParentItem = dbItem == null ? null : allDbParents.FirstOrDefault(pi => pi.ASIN == dbItem.ParentASIN);

                if (dbItem != null &&
                    dbItem.IsExistOnAmazon != listing.IsExistOnAmazon)
                {
                    Log.Debug("IsExistOnAmazon: " + listing.ASIN + ": " + dbItem.IsExistOnAmazon + "=>" + listing.IsExistOnAmazon);
                    dbItem.IsExistOnAmazon = listing.IsExistOnAmazon;
                }

                var parentASIN = listing.ParentASIN;
                if (String.IsNullOrEmpty(parentASIN))
                {
                    parentASIN = listing.ASIN;
                }

                if (dbItem != null &&
                    dbItem.IsExistOnAmazon == true)
                {
                    dbItem.IsAmazonParentASIN   = !String.IsNullOrEmpty(listing.ParentASIN);
                    dbItem.LastUpdateFromAmazon = time.GetUtcTime();
                }

                if (dbParentItem != null &&
                    listing.IsExistOnAmazon == true)
                {
                    var allItemsForParentItem = allDbItems.Where(i => i.ParentASIN == dbParentItem.ASIN).ToList();

                    if (dbParentItem.ASIN != parentASIN)
                    {
                        Log.Debug("ParentItem ASIN: " + dbParentItem.ASIN + "=>" + parentASIN);
                        dbParentItem.ASIN = parentASIN;

                        allItemsForParentItem.ForEach(i => i.ParentASIN = parentASIN); //UPDATE for all, in case it may have different Parents on Amazon (us last one for all)
                    }


                    if (listing.ParentASIN != dbParentItem.ASIN)
                    {
                        dbParentItem.IsAmazonUpdated = false;
                    }
                    else
                    {
                        dbParentItem.IsAmazonUpdated = listing.IsExistOnAmazon;
                    }
                }
            }
            db.Commit();
            Log.Debug("Update ParentASINs end");

            //2.1 Update not exist parent asins
            var notUpdatedParents = allDbParents.Where(pi => !updatedParentIds.Contains(pi.Id)).ToList();

            Log.Debug("Not exist parent items: " + notUpdatedParents.Count());
            foreach (var dbParentItem in notUpdatedParents)
            {
                Log.Debug("Mark as not processed: " + dbParentItem.ASIN);
                dbParentItem.IsAmazonUpdated = false;
            }
            db.Commit();

            //3.0 Set to inactive not exist listings
            var notExistListings = listings.Where(l => !existsListingSKUs.Contains(l.SKU)).ToList();

            foreach (var notExistListing in notExistListings)
            {
                Log.Debug("Request qty=0 for SKU=" + notExistListing.SKU);
                if (Context.ActionService != null)
                {
                    Context.ActionService.AddAction(db,
                                                    SystemActionType.UpdateOnMarketProductQuantity,
                                                    notExistListing.SKU,
                                                    new UpdateQtyInput()
                    {
                        Market        = api.Market,
                        MarketplaceId = api.MarketplaceId,

                        ListingId      = null,
                        SKU            = notExistListing.SKU,
                        SourceMarketId = notExistListing.SourceMarketId,

                        NewQty = 0,
                    },
                                                    null,
                                                    null);
                }
            }

            Log.Debug("ProcessItems end");
        }
コード例 #21
0
        public void ReadItemsInfo(SupplieroasisApi api)
        {
            _log.Info("Begin ReadItemsInfo");
            var itemsWithError = new List <string>();
            var items          = api.GetItems(_log,
                                              _time,
                                              null,
                                              ItemFillMode.Defualt,
                                              out itemsWithError);

            using (var db = _dbFactory.GetRWDb())
            {
                _log.Info("Total items=" + items.Count());
                //Create
                var allItems = db.Items.GetAllViewAsDto().Where(m => m.Market == (int)api.Market &&
                                                                (m.MarketplaceId == api.MarketplaceId ||
                                                                 String.IsNullOrEmpty(api.MarketplaceId))).ToList();
                foreach (var item in items)
                {
                    foreach (var variation in item.Variations)
                    {
                        var existItem = allItems.FirstOrDefault(i => StringHelper.IsEqualNoCase(i.SKU, variation.SKU));

                        if (existItem == null)
                        {
                            _log.Info("Add new item, MarketItemId=" + variation.SourceMarketId);

                            var exampleItem = db.Items.GetAllViewAsDto().FirstOrDefault(i => i.Market == (int)MarketType.Amazon &&
                                                                                        i.MarketplaceId == MarketplaceKeeper.AmazonComMarketplaceId &&
                                                                                        i.SKU == variation.SKU);
                            if (exampleItem == null)
                            {
                                exampleItem = db.Items.GetAllViewAsDto().OrderByDescending(i => i.CreateDate).FirstOrDefault(i => i.SKU == variation.SKU);
                            }

                            var styleString = SkuHelper.RetrieveStyleIdFromSKU(db, variation.SKU, null);
                            if (String.IsNullOrEmpty(styleString))
                            {
                                styleString = variation.SKU;
                            }

                            if (String.IsNullOrEmpty(styleString))
                            {
                                _log.Info("StyleString is empty for: " + variation.SKU + ", itemSKU=" + item.SKU);
                                continue;
                            }

                            var parentItem = db.ParentItems.GetAll().FirstOrDefault(pi => pi.ASIN == styleString &&
                                                                                    pi.Market == (int)MarketType.OverStock);
                            if (parentItem == null)
                            {
                                parentItem = new ParentItem()
                                {
                                    ASIN           = styleString,
                                    SourceMarketId = styleString,
                                    Market         = item.Market,
                                    MarketplaceId  = item.MarketplaceId,

                                    CreateDate = _time.GetAmazonNowTime()
                                };

                                db.ParentItems.Add(parentItem);
                                db.Commit();
                            }

                            if (exampleItem == null)
                            {
                                exampleItem = new DTO.ItemDTO();
                                var style = db.Styles.GetAll().FirstOrDefault(st => st.StyleID == styleString);
                                if (style != null)
                                {
                                    exampleItem.StyleId = style.Id;
                                }
                                var size = SkuHelper.RetrieveSizeFromSKU(variation.SKU);

                                if (style != null)
                                {
                                    var styleItem = db.StyleItems.GetAll().FirstOrDefault(si => si.StyleId == style.Id &&
                                                                                          si.Size == size);
                                    if (styleItem != null)
                                    {
                                        exampleItem.StyleItemId = styleItem.Id;
                                    }
                                }
                            }

                            var newItem = new Item()
                            {
                                ASIN          = item.ASIN,
                                ParentASIN    = parentItem.ASIN,
                                Market        = item.Market,
                                MarketplaceId = item.MarketplaceId,

                                Barcode = variation.Barcode,

                                SourceMarketId      = item.SourceMarketId,
                                ItemPublishedStatus = variation.PublishedStatus,

                                StyleId     = exampleItem?.StyleId,
                                StyleItemId = exampleItem?.StyleItemId,

                                CreateDate = _time.GetAmazonNowTime()
                            };
                            db.Items.Add(newItem);
                            db.Commit();

                            var newListing = new Listing()
                            {
                                ItemId        = newItem.Id,
                                SKU           = variation.SKU,
                                ListingId     = variation.SKU,
                                Market        = variation.Market,
                                MarketplaceId = variation.MarketplaceId,

                                CreateDate         = _time.GetAmazonNowTime(),
                                AmazonRealQuantity = variation.AmazonRealQuantity,
                            };
                            db.Listings.Add(newListing);
                            db.Commit();
                        }
                    }
                }


                //Update
                var updatedItemIds = new List <long>();
                foreach (var item in items)
                {
                    foreach (var variation in item.Variations)
                    {
                        _log.Info("Read info for SKU=" + variation.SKU);
                        var dbListing = db.Listings.GetAll().FirstOrDefault(m => m.Market == (int)api.Market &&
                                                                            (m.MarketplaceId == api.MarketplaceId ||
                                                                             String.IsNullOrEmpty(api.MarketplaceId)) &&
                                                                            m.SKU == variation.SKU);
                        if (dbListing == null)
                        {
                            _log.Info("Unable to find item for, SKU=" + variation.SKU);
                            continue;
                        }

                        var dbItem = db.Items.GetAll().FirstOrDefault(i => i.Id == dbListing.ItemId);
                        if (dbItem == null)
                        {
                            _log.Info("Unable to find item for itemId=" + dbListing.ItemId);
                            continue;
                        }

                        updatedItemIds.Add(dbItem.Id);

                        if (dbItem.ItemPublishedStatus != variation.PublishedStatus)
                        {
                            dbItem.ItemPublishedStatus       = variation.PublishedStatus;
                            dbItem.ItemPublishedStatusDate   = _time.GetAppNowTime();
                            dbItem.ItemPublishedStatusReason = "Derived from market";
                        }

                        dbItem.Barcode = variation.Barcode;

                        //dbListing.AmazonCurrentPrice = variation.AmazonCurrentPrice;
                        //dbListing.AmazonCurrentPriceUpdateDate = _time.GetAppNowTime();

                        dbListing.AmazonRealQuantity           = variation.AmazonRealQuantity;
                        dbListing.AmazonRealQuantityUpdateDate = _time.GetAppNowTime();
                    }
                }
                db.Commit();

                //Remove not exists
                var toRemoveItems = db.Items.GetAll().Where(i => i.Market == (int)api.Market &&
                                                            (i.MarketplaceId == api.MarketplaceId ||
                                                             String.IsNullOrEmpty(api.MarketplaceId)) &&
                                                            !updatedItemIds.Contains(i.Id) &&
                                                            i.ItemPublishedStatus == (int)PublishedStatuses.Published);
                _log.Info("Items to unpublish, count=" + toRemoveItems.Count());
                foreach (var toRemoveItem in toRemoveItems)
                {
                    toRemoveItem.ItemPublishedStatusBeforeRepublishing = toRemoveItem.ItemPublishedStatus;
                    toRemoveItem.ItemPublishedStatus     = (int)PublishedStatuses.Unpublished;
                    toRemoveItem.ItemPublishedStatusDate = _time.GetUtcTime();
                }
                db.Commit();
            }
            _log.Info("End ReadItemsInfo");
        }
コード例 #22
0
        public CheckResult Check(IUnitOfWork db,
                                 DTOMarketOrder order,
                                 IList <ListingOrderDTO> items,
                                 AddressValidationStatus addressValidationStatus)
        {
            if (order.Id == 0)
            {
                throw new ArgumentOutOfRangeException("order.Id", "Should be non zero");
            }

            if (order.OrderStatus == OrderStatusEnumEx.Pending)
            {
                throw new ArgumentException("order.OrderStatus", "Not supported status Pending");
            }

            //International order has issue with PersonName
            if (ShippingUtils.IsInternational(order.FinalShippingCountry))
            {
                if (String.IsNullOrEmpty(order.FinalShippingPhone))
                {
                    var emailInfo = new PhoneMissingEmailInfo(_emailService.AddressService,
                                                              null,
                                                              order.OrderId,
                                                              (MarketType)order.Market,
                                                              items,
                                                              order.BuyerName,
                                                              order.BuyerEmail);

                    _emailService.SendEmail(emailInfo, CallSource.Service);
                    _log.Info("Send phone missing email, orderId=" + order.Id);

                    db.OrderEmailNotifies.Add(new OrderEmailNotify()
                    {
                        OrderNumber = order.OrderId,
                        Reason      = "System emailed, missing phone number",
                        Type        = (int)OrderEmailNotifyType.OutputPhoneMissingEmail,
                        CreateDate  = _time.GetUtcTime(),
                    });

                    db.OrderComments.Add(new OrderComment()
                    {
                        OrderId    = order.Id,
                        Message    = "[System] Missing phone email sent",
                        Type       = (int)CommentType.Address,
                        CreateDate = _time.GetAppNowTime(),
                        UpdateDate = _time.GetAppNowTime()
                    });

                    db.Commit();

                    return(new CheckResult()
                    {
                        IsSuccess = false
                    });
                }
            }

            return(new CheckResult()
            {
                IsSuccess = true
            });
        }
コード例 #23
0
        public void SendItemUpdates(Action <StyleImageDTO> prepareStyleImageCallback,
                                    Func <ParentItemDTO, bool, IList <ItemExDTO>, IList <StyleEntireDto>, IList <StyleImageDTO>, IList <StyleFeatureValueDTO>, IList <DropShipperDTO>, CallResult <ParentItemDTO> > itemPublishCallback,
                                    MarketType market,
                                    string marketplaceId,
                                    IList <long> styleIds)
        {
            _log.Info("Begin ItemUpdates");

            IList <SystemActionDTO> updateActions = null;

            using (var db = _dbFactory.GetRWDb())
            {
                IList <string> parentASINList;

                if (styleIds == null)
                {
                    DateTime?maxLastAttemptDate = _time.GetUtcTime().AddHours(-4);

                    updateActions = _actionService.GetUnprocessedByType(db,
                                                                        SystemActionType.UpdateOnMarketProductData,
                                                                        maxLastAttemptDate,
                                                                        null);

                    var parentItemIds = updateActions.Select(i => StringHelper.TryGetInt(i.Tag))
                                        .Where(i => i.HasValue)
                                        .ToList();

                    parentASINList = (from pi in db.ParentItems.GetAll()
                                      where parentItemIds.Contains(pi.Id) &&
                                      pi.Market == (int)market &&
                                      pi.MarketplaceId == marketplaceId
                                      select pi.ASIN).Distinct().ToList();
                }
                else
                {
                    parentASINList = (from i in db.Items.GetAll()
                                      join l in db.Listings.GetAll() on i.Id equals l.ItemId
                                      join st in db.Styles.GetAll() on i.StyleId equals st.Id
                                      where !st.Deleted &&
                                      !l.IsRemoved &&
                                      styleIds.Contains(st.Id) &&
                                      i.Market == (int)market &&
                                      (i.MarketplaceId == marketplaceId || String.IsNullOrEmpty(marketplaceId)) &&
                                      i.StyleItemId.HasValue
                                      select i.ParentASIN).Distinct().ToList();
                }

                //NOTE: Need to submit items with group, otherwise we have incorrect color variations calculation, and sometimes image calculation
                var allItemList = db.Items.GetAllActualExAsDto()
                                  .Where(i => parentASINList.Contains(i.ParentASIN) &&
                                         i.Market == (int)market &&
                                         (i.MarketplaceId == marketplaceId || String.IsNullOrEmpty(marketplaceId))).ToList();

                _log.Info("Parent ASIN Count to submit=" + parentASINList.Count + ", item count=" + allItemList.Count);

                //Refresh parentASIN list, exclude asins with not actual items
                parentASINList = allItemList.Select(i => i.ParentASIN).Distinct().ToList();


                var allParentItemList = db.ParentItems.GetAllAsDto().Where(p => parentASINList.Contains(p.ASIN) &&
                                                                           p.Market == (int)market &&
                                                                           (p.MarketplaceId == marketplaceId || String.IsNullOrEmpty(marketplaceId)))
                                        .ToList();

                var allStyleIdList     = allItemList.Where(i => i.StyleId.HasValue).Select(i => i.StyleId.Value).ToList();
                var allStyleList       = db.Styles.GetAllAsDtoEx().Where(s => allStyleIdList.Contains(s.Id)).ToList();
                var allStyleImageList  = db.StyleImages.GetAllAsDto().Where(sim => allStyleIdList.Contains(sim.StyleId)).ToList();
                var allFeatures        = db.StyleFeatureValues.GetAllFeatureValuesByStyleIdAsDto(allStyleIdList).ToList();
                var allDropShipperList = db.DropShippers.GetAllAsDto().ToList();
                allFeatures.AddRange(db.StyleFeatureTextValues.GetAllFeatureTextValuesByStyleIdAsDto(allStyleIdList));
                allFeatures = allFeatures.OrderBy(fv => fv.SortOrder).ToList();

                foreach (var item in allItemList)
                {
                    var parent = allParentItemList.FirstOrDefault(p => p.ASIN == item.ParentASIN);
                    if (parent != null)
                    {
                        item.OnHold = parent.OnHold;
                    }
                }

                //Exclude OnHold (after ParentItem onHold was applied)
                allItemList = allItemList.Where(i => !i.OnHold).ToList();

                foreach (var styleImage in allStyleImageList)
                {
                    try
                    {
                        prepareStyleImageCallback(styleImage);
                    }
                    catch (Exception ex)
                    {
                        _log.Info("PrepareStyleImage error, image=" + styleImage.Image, ex);
                    }
                }

                if (allItemList.Any())
                {
                    _log.Info("Items to update=" + String.Join(", ", allItemList.Select(i => i.SKU).ToList()));

                    foreach (var parentItem in allParentItemList)
                    {
                        var groupItems       = allItemList.Where(i => i.ParentASIN == parentItem.ASIN).ToList();
                        var groupStyleIdList =
                            groupItems.Where(i => i.StyleId.HasValue).Select(i => i.StyleId).Distinct().ToList();
                        var styles        = allStyleList.Where(s => groupStyleIdList.Contains(s.Id)).ToList();
                        var styleFeatures = allFeatures.Where(f => groupStyleIdList.Contains(f.StyleId)).ToList();

                        var enableColorVariation = (parentItem != null && parentItem.ForceEnableColorVariations) ||
                                                   groupItems.GroupBy(i => i.Size)
                                                   .Select(g => new
                        {
                            Count = g.Count(),
                            Size  = g.Key,
                        })
                                                   .Count(g => g.Count > 1) > 0;

                        var styleImages = allStyleImageList
                                          .Where(im => groupStyleIdList.Contains(im.StyleId) && !im.IsSystem)
                                          .OrderBy(im => im.StyleId)
                                          .ThenByDescending(im => im.IsDefault)
                                          .ThenBy(im => im.Id)
                                          .ToList();

                        if (_mode == PublishingMode.Report ||
                            _mode == PublishingMode.ReportAll)
                        {
                            itemPublishCallback(parentItem,
                                                enableColorVariation,
                                                groupItems,
                                                styles,
                                                styleImages,
                                                styleFeatures,
                                                allDropShipperList);
                        }

                        if (_mode == PublishingMode.PerItem)
                        {
                            //SEND
                            var result = itemPublishCallback(parentItem,
                                                             enableColorVariation,
                                                             groupItems,
                                                             styles,
                                                             styleImages,
                                                             styleFeatures,
                                                             allDropShipperList);

                            var parentItemIdStr = parentItem.Id.ToString();
                            var dbSystemActions = db.SystemActions.GetAll()
                                                  .Where(a => a.Tag == parentItemIdStr &&
                                                         a.Type == (int)SystemActionType.UpdateOnMarketProductData)
                                                  .ToList();

                            if (result.IsSuccess)
                            {
                                var dbParentItem = db.ParentItems.GetAll().FirstOrDefault(pi => parentItem.Id == pi.Id);
                                dbParentItem.SourceMarketId  = result.Data.SourceMarketId;
                                dbParentItem.SourceMarketUrl = result.Data.SourceMarketUrl;

                                var itemIds = groupItems.Select(i => i.Id).ToList();
                                var dbItems = db.Items.GetAll().Where(i => itemIds.Contains(i.Id)).ToList();
                                foreach (var groupItem in groupItems)
                                {
                                    var resultItem = result.Data.Variations?.FirstOrDefault(v => v.SKU == groupItem.SKU);
                                    var dbItem     = dbItems.FirstOrDefault(i => i.Id == groupItem.Id);
                                    if (dbItem != null && resultItem != null)
                                    {
                                        dbItem.SourceMarketId          = resultItem.SourceMarketId;
                                        dbItem.SourceMarketUrl         = resultItem.SourceMarketUrl;
                                        dbItem.ItemPublishedStatus     = (int)PublishedStatuses.Published;
                                        dbItem.ItemPublishedStatusDate = _time.GetAppNowTime();
                                    }
                                }

                                foreach (var dbSystemAction in dbSystemActions)
                                {
                                    dbSystemAction.Status = (int)SystemActionStatus.Done;
                                }
                            }
                            else
                            {
                                foreach (var dbSystemAction in dbSystemActions)
                                {
                                    dbSystemAction.AttemptDate = _time.GetAppNowTime();
                                    dbSystemAction.AttemptNumber++;
                                    if (dbSystemAction.AttemptNumber > 3)
                                    {
                                        dbSystemAction.Status = (int)SystemActionStatus.Fail;
                                    }
                                }
                            }

                            db.Commit();
                        }
                    }
                }
                else
                {
                    if (updateActions != null && updateActions.Any())
                    {
                        foreach (var updateAction in updateActions)
                        {
                            _actionService.SetResult(db, updateAction.Id, SystemActionStatus.Fail, null);
                        }
                    }
                }
                _log.Info("End ItemUpdates");
            }
        }
コード例 #24
0
        public void Process(IUnitOfWork db, EmailReadingResult result)
        {
            if (result.Status == EmailMatchingResultStatus.New &&
                result.HasMatches)
            {
                var subject = (result.Email.Subject ?? "");
                var today   = _time.GetAppNowTime().Date;

                //TASK: 1.	Emails which have these in subjects: "Order delivery inquiry" or " Where's My Stuff?”
                //CHANGE: When client sends an email with subject “Package didn’t arrive..” like 113-7086092-7521857, process it same way as emails with subject “Lost Package”…
                var isWhereMyStaff = subject.StartsWith("Order delivery inquiry", StringComparison.OrdinalIgnoreCase) ||
                                     subject.IndexOf("Where's My Stuff?", StringComparison.OrdinalIgnoreCase) >= 0 ||
                                     subject.IndexOf("Where's My Stuff ?", StringComparison.OrdinalIgnoreCase) >= 0 ||
                                     subject.IndexOf("Package didn’t arrive:", StringComparison.OrdinalIgnoreCase) >= 0 ||
                                     subject.IndexOf("Package didn?t arrive", StringComparison.OrdinalIgnoreCase) >= 0 ||
                                     subject.IndexOf("Shipping inquiry", StringComparison.InvariantCultureIgnoreCase) >= 0;    //NOTE: actually came with ? instead of '

                if (isWhereMyStaff)
                {
                    _log.Info("Received 'Where my stuff'");
                    var orderNumber = result.MatchedIdList.FirstOrDefault();
                    if (!String.IsNullOrEmpty(orderNumber))
                    {
                        //TASK: 2.	 Which were successfully delivered to client.
                        var order         = db.Orders.GetByOrderNumber(orderNumber);
                        var shippingInfos = db.OrderShippingInfos.GetByOrderIdAsDto(order.Id).Where(sh => sh.IsActive).ToList();
                        //a.	 delivered to client (not returned to us)
                        var delivered    = shippingInfos.Any() && shippingInfos.All(sh => sh.DeliveredStatus == (int)DeliveredStatusEnum.Delivered);
                        var deliveryDate = shippingInfos.Select(sh => sh.ActualDeliveryDate).FirstOrDefault();
                        //b.	Delivered within last 2 month.
                        if (delivered && deliveryDate.HasValue && deliveryDate > today.AddMonths(-2))
                        {
                            _log.Info("Package was delivered, withing last 2 month");

                            var alreadySendLostTemplate = db.OrderEmailNotifies.IsExist(order.AmazonIdentifier,
                                                                                        OrderEmailNotifyType.OutputLostPackageEmail);

                            //3.	To which we didn’t answer yet with Lost Package template
                            if (!alreadySendLostTemplate)
                            {
                                _log.Info("Not send package lost template");

                                var orderEmails = db.Emails.GetAllByOrderId(order.AmazonIdentifier)
                                                  .Select(m => new
                                {
                                    m.Id,
                                    m.ReceiveDate,
                                    m.Subject
                                }).ToList();
                                var isAnyOtherSimilarEmails = orderEmails.Any(e => e.Id != result.Email.Id &&
                                                                              (e.ReceiveDate <= result.Email.ReceiveDate &&
                                                                               e.Subject.Contains("Where's My Stuff?") ||
                                                                               e.Subject.Contains("Order delivery inquiry")));

                                var isAnyOtherEmailAfterDelivery = deliveryDate.HasValue && orderEmails.Any(e => e.Id != result.Email.Id &&
                                                                                                            e.ReceiveDate >= deliveryDate.Value);

                                //4.	If it’s the first email with that subject ("Order delivery inquiry" or " Where's My Stuff?”)
                                if (!isAnyOtherSimilarEmails && !isAnyOtherEmailAfterDelivery)
                                {
                                    _log.Info("Pass to Order Delivery Inquiry Rule");

                                    OrderShippingInfoDTO shippingInfo   = null;
                                    ShippingMethodDTO    shippingMethod = null;
                                    if (shippingInfos.Any())
                                    {
                                        shippingInfo = shippingInfos.OrderByDescending(sh => sh.ActualDeliveryDate)
                                                       .FirstOrDefault(i => i.IsActive);
                                        if (shippingInfo != null)
                                        {
                                            shippingMethod = db.ShippingMethods.GetByIdAsDto(shippingInfo.ShippingMethodId);
                                        }
                                    }
                                    var emailInfo = new LostPackageEmailInfo(_emailService.AddressService,
                                                                             null,
                                                                             order.AmazonIdentifier,
                                                                             (MarketType)order.Market,
                                                                             shippingInfo != null ? shippingInfo.ActualDeliveryDate : null,
                                                                             shippingInfo != null ? shippingInfo.TrackingStateEvent : null,
                                                                             shippingMethod != null ? shippingMethod.CarrierName : null,
                                                                             shippingInfo != null ? shippingInfo.TrackingNumber : null,
                                                                             order.GetAddressDto(),
                                                                             order.BuyerName,
                                                                             order.BuyerEmail);

                                    _emailService.SendEmail(emailInfo, CallSource.Service);

                                    db.OrderEmailNotifies.Add(new OrderEmailNotify()
                                    {
                                        OrderNumber = order.CustomerOrderId,
                                        Type        = (int)OrderEmailNotifyType.OutputLostPackageEmail,
                                        Reason      = "Email: " + StringHelper.Substring(subject, 40),
                                        CreateDate  = _time.GetUtcTime()
                                    });

                                    db.OrderComments.Add(new OrderComment()
                                    {
                                        OrderId    = order.Id,
                                        Type       = (int)CommentType.OutputEmail,
                                        Message    = "[System] \"Lost Package\" email sent",
                                        CreateDate = _time.GetAppNowTime(),
                                    });

                                    db.Commit();

                                    result.WasEmailProcessed = true;
                                }
                                else
                                {
                                    if (isAnyOtherSimilarEmails)
                                    {
                                        _log.Info("Similar email was found");
                                    }
                                    if (isAnyOtherEmailAfterDelivery)
                                    {
                                        _log.Info("Other email was found after delivery");
                                    }
                                }
                            }
                            else
                            {
                                _log.Info("Already sent Lost Package template");
                            }
                        }
                        else
                        {
                            _log.Info("Package not yet delivered");
                        }
                    }
                }
            }
        }
コード例 #25
0
        private void SetItemFieldsIfExistOnAmazon(IUnitOfWork db, ItemDTO dtoItem, Item dbItem)
        {
            //NOTE: Skip any ParentASIN updates
            //NOTE: updates for childs only when we change ParentItem objects
            //NOTE: to keep source relationships
            //if (!String.IsNullOrEmpty(dtoItem.ParentASIN))
            //{
            //    dbItem.ParentASIN = dtoItem.ParentASIN;
            //}

            //NOTE: only when no ParentASIN
            if (String.IsNullOrEmpty(dbItem.ParentASIN) &&
                !String.IsNullOrEmpty(dtoItem.ParentASIN))
            {
                dbItem.ParentASIN = dtoItem.ParentASIN;
            }

            if (dbItem.ASIN != dtoItem.ASIN)
            {
                _log.Info("For SKU=" + dtoItem.SKU + "(id: " + dbItem.Id + ")" + ", ASIN=" + dbItem.ASIN + "=>" + dtoItem.ASIN);
                dbItem.ASIN = dtoItem.ASIN;
            }

            if (dbItem.ItemPublishedStatus == (int)PublishedStatuses.New ||
                dbItem.ItemPublishedStatus == (int)PublishedStatuses.PublishedInactive ||
                dbItem.ItemPublishedStatus == (int)PublishedStatuses.PublishedInProgress ||
                dbItem.ItemPublishedStatus == (int)PublishedStatuses.PublishingErrors ||
                dbItem.ItemPublishedStatus == (int)PublishedStatuses.None ||
                dbItem.ItemPublishedStatus == (int)PublishedStatuses.HasPublishRequest)
            //NOTE: should be excluded HasUnpublishdRequest
            {
                dbItem.ItemPublishedStatus       = (int)PublishedStatuses.Published;
                dbItem.ItemPublishedStatusReason = "";
                dbItem.ItemPublishedStatusDate   = _time.GetAppNowTime();
            }

            dbItem.ItemPublishedStatusFromMarket     = (int)PublishedStatuses.Published;
            dbItem.ItemPublishedStatusFromMarketDate = _time.GetAppNowTime();

            dbItem.IsAmazonParentASIN = dtoItem.ParentASIN == dbItem.ParentASIN;
            dbItem.SourceMarketId     = dtoItem.SourceMarketId;
            dbItem.MarketParentASIN   = dtoItem.ParentASIN;

            if (dbItem.OnMarketTemplateName != dtoItem.OnMarketTemplateName)
            {
                _log.Debug("Template changed: " + dbItem.OnMarketTemplateName + "=>" + dtoItem.OnMarketTemplateName);
            }
            dbItem.OnMarketTemplateName = dtoItem.OnMarketTemplateName;

            //Updates size if came not null
            if (!String.IsNullOrEmpty(dtoItem.Size))
            {
                var newSize = StringHelper.Substring(dtoItem.Size, 50);
                if (dbItem.Size != newSize)
                {
                    if (_itemHistoryService != null)
                    {
                        _itemHistoryService.AddRecord(dbItem.Id,
                                                      ItemHistoryHelper.SizeKey,
                                                      dbItem.Size,
                                                      "ListingLineProcessing.SetItemFieldsIfExistOnAmazon",
                                                      newSize,
                                                      null,
                                                      null);
                    }
                    dbItem.Size = newSize;
                }
            }
            else
            {
                dtoItem.Size = dbItem.Size; //NOTE: item DTO size using in below code (should be actual)
            }

            dbItem.IsExistOnAmazon      = true;
            dbItem.LastUpdateFromAmazon = _time.GetUtcTime();

            //Set style string
            if (String.IsNullOrEmpty(dbItem.StyleString))
            {
                dtoItem.StyleString = SkuHelper.RetrieveStyleIdFromSKU(db,
                                                                       dtoItem.SKU,
                                                                       dtoItem.Name);

                _log.Debug(string.Format("StyleString updated from={0}, to={1}", dbItem.StyleString, dtoItem.StyleString));
                dbItem.StyleString = dtoItem.StyleString;
            }
            else
            {
                dtoItem.StyleString = dbItem.StyleString;
            }

            //Additional Fields
            dbItem.Title = dtoItem.Name;
            if (!String.IsNullOrEmpty(dtoItem.ImageUrl))
            {
                dbItem.PrimaryImage = dtoItem.ImageUrl;
            }
            dbItem.BrandName        = dtoItem.BrandName;
            dbItem.Type             = StringHelper.Substring(dtoItem.Type, 50);
            dbItem.ListPrice        = dtoItem.ListPrice;
            dbItem.Color            = StringHelper.Substring(dtoItem.Color, 50);
            dbItem.Department       = dtoItem.Department;
            dbItem.AdditionalImages = dtoItem.AdditionalImages;
            if (!String.IsNullOrEmpty(dtoItem.Features))
            {
                dbItem.Features = dtoItem.Features;
            }
            if (!String.IsNullOrEmpty(dtoItem.SearchKeywords))
            {
                dbItem.SearchKeywords = dtoItem.SearchKeywords;
            }
            if (!String.IsNullOrEmpty(dtoItem.Barcode))
            {
                dbItem.Barcode = dtoItem.Barcode;
            }

            //Setting styleId, create style, styleItem if not exist
            if (!dbItem.StyleItemId.HasValue)
            {
                //Kepp exists styleId
                dtoItem.StyleId = dbItem.StyleId;

                _log.Info("FindOrCreateStyleItem");
                var styleItem = FindOrCreateStyleItem(db, dtoItem);
                if (styleItem != null)
                {
                    if (styleItem.StyleItemId > 0)
                    {
                        _styleHistoryService.AddRecord(styleItem.StyleId,
                                                       StyleHistoryHelper.AttachListingKey,
                                                       dbItem.StyleItemId,
                                                       dbItem.Market + ":" + dbItem.MarketplaceId,
                                                       styleItem.StyleItemId,
                                                       dbItem.Id.ToString() + ":" + dbItem.ASIN,
                                                       null);

                        dbItem.StyleId     = styleItem.StyleId;
                        dbItem.StyleItemId = styleItem.StyleItemId;
                    }
                    else
                    {
                        if (!dbItem.StyleId.HasValue)
                        {
                            dbItem.StyleId = styleItem.StyleId;
                        }
                    }

                    _log.Debug(String.Format("Set for ASIN={0}, styleId={1}, styleItemId={2}",
                                             dtoItem.ASIN,
                                             styleItem.StyleId,
                                             styleItem.StyleItemId));
                }
                else
                {
                    _log.Info("Empty StyleItem");
                }
            }

            //Update style image
            if (dbItem.StyleId.HasValue &&
                !String.IsNullOrEmpty(dbItem.PrimaryImage))
            {
                _styleManager.UpdateStyleImageIfEmpty(db, dbItem.StyleId.Value, dbItem.PrimaryImage);
            }

            if (dtoItem.Weight.HasValue &&
                dbItem.StyleItemId.HasValue)
            {
                var dbStyleItem = db.StyleItems.Get(dbItem.StyleItemId.Value);
                if (!dbStyleItem.Weight.HasValue)
                {
                    dbStyleItem.Weight = dtoItem.Weight;
                }
            }

            if (!String.IsNullOrEmpty(dtoItem.Barcode) &&
                dbItem.StyleItemId.HasValue)
            {
                _styleManager.StoreOrUpdateBarcode(db,
                                                   dbItem.StyleItemId.Value,
                                                   dtoItem.Barcode);
            }
        }
コード例 #26
0
        public IList <TrackingState> UpdateOrderTracking(
            IUnitOfWork db,
            CompanyDTO company,
            IList <OrderToTrackDTO> shippings,
            ITrackingProvider trackingProvider)
        {
            _log.Info("UpdateOrderTracking, shippings=" + shippings.Count);
            try
            {
                var ruleList = _ruleList;

                var trackingList = shippings
                                   .Where(o => !String.IsNullOrEmpty(o.TrackingNumber))
                                   .Select(o => new TrackingNumberToCheckDto()
                {
                    TrackingNumber = o.TrackingNumber,
                    ToCountry      = o.ShippingAddress != null ? o.ShippingAddress.FinalCountry : null,
                }).ToList();

                var stateList = trackingProvider.TrackShipments(trackingList);
                var today     = _time.GetAppNowTime();

                _log.Info("UpdateOrderTracking, track count get back=" + stateList.Count);
                var processedShipmentIds = new List <long>();
                var processedMailInfoIds = new List <long>();
                foreach (var state in stateList)
                {
                    //NOTE: Fedex has delivery records not as last record (ex.: 393418292108)
                    var deliveredRecord = state.Records != null?state.Records.FirstOrDefault(r => _deliveryEventList.Contains(r.Message ?? "") || (r.Message ?? "").ToLower().StartsWith("delivered")) : null;

                    var lastRecord = deliveredRecord != null ? deliveredRecord : (state.Records != null ? state.Records.FirstOrDefault() : null);
                    var isBack     = lastRecord != null?_addressService.IsMine(lastRecord.AsAddressDto()) : false;

                    var shippingDto = shippings.FirstOrDefault(sh => sh.TrackingNumber == state.TrackingNumber);
                    if (shippingDto != null)
                    {
                        var hasStateChanges = false;
                        if (lastRecord == null)
                        {
                            hasStateChanges = false;
                            shippingDto.TrackingRequestAttempts = shippingDto.TrackingRequestAttempts + 1;
                            shippingDto.LastTrackingRequestDate = _time.GetUtcTime();
                            _log.Warn("UpdateOrderTracking, empty Records!");
                        }
                        else
                        {
                            _log.Info("UpdateOrderTracking, o=" + shippingDto.OrderNumber + ", tr=" +
                                      shippingDto.TrackingNumber + ", at=" + shippingDto.OrderDate + ", new state=" +
                                      lastRecord.Message + " at=" + lastRecord.Date);

                            var newStateEvent = StringHelper.Substring(lastRecord.Message, 100);
                            hasStateChanges = shippingDto.TrackingStateDate != lastRecord.Date ||
                                              shippingDto.TrackingStateEvent != newStateEvent;

                            shippingDto.TrackingStateSource = (int)lastRecord.Source;
                            shippingDto.TrackingStateDate   = lastRecord.Date;
                            shippingDto.TrackingStateEvent  = newStateEvent;
                            shippingDto.TrackingLocation    = lastRecord.Country + ", " + lastRecord.State + ", " +
                                                              lastRecord.City + ", " + lastRecord.Zip;

                            if (_deliveryEventList.Contains(lastRecord.Message) ||
                                lastRecord.Message.ToLower().StartsWith("delivered") ||
                                (lastRecord.Message.ToLower().Contains("shipment picked up") &&
                                 (state.Records.Count > 5 && lastRecord.Date < today.AddDays(-2))))
                            //NOTE: temporary solution for "Shipment Picked Up", every shipment may have transit status with that name (not final)
                            {
                                shippingDto.DeliveredStatus = isBack
                                    ? (int)DeliveredStatusEnum.DeliveredToSender
                                    : (int)DeliveredStatusEnum.Delivered;

                                shippingDto.IsDelivered        = true;
                                shippingDto.ActualDeliveryDate = lastRecord.Date;
                            }
                            else
                            {
                                //May happend like with refused tracking number https://tools.usps.com/go/TrackConfirmAction!input.action?tRef=qt&tLc=1&tLabels=9400116901495496872649
                                //Order #1577164597317
                                shippingDto.DeliveredStatus    = (int)DeliveredStatusEnum.None;
                                shippingDto.IsDelivered        = false;
                                shippingDto.ActualDeliveryDate = null;
                            }

                            //For DHL
                            if (lastRecord.Message.ToLower().StartsWith("Returned to shipper"))
                            {
                                shippingDto.DeliveredStatus    = (int)DeliveredStatusEnum.DeliveredToSender;
                                shippingDto.IsDelivered        = true;
                                shippingDto.ActualDeliveryDate = lastRecord.Date;
                            }

                            shippingDto.LastTrackingRequestDate = _time.GetUtcTime();

                            if (!hasStateChanges)
                            {
                                shippingDto.TrackingRequestAttempts = shippingDto.TrackingRequestAttempts + 1;
                            }
                            else
                            {
                                shippingDto.TrackingRequestAttempts = 1;
                            }

                            //NOTE: If state no changes for a long time => no requests
                            if (lastRecord.Date < _time.GetAppNowTime().AddDays(-50) ||
                                (shippingDto.OrderDate < _time.GetAppNowTime().AddDays(-90) &&
                                 lastRecord.Message.StartsWith(TrackingHelper.UndefinedPrefix)))
                            {
                                shippingDto.TrackingRequestAttempts = 10000;
                                if (lastRecord.Message.StartsWith(TrackingHelper.UndefinedPrefix))
                                {
                                    _log.Info("Info Unavailable, message=" + lastRecord.Message);
                                    shippingDto.DeliveredStatus = (int)DeliveredStatusEnum.InfoUnavailable;
                                }
                                _log.Info("Last attempt (= 10000)");
                            }
                        }


                        if (shippingDto.ShipmentInfoId.HasValue)
                        {
                            if (processedShipmentIds.Any(sh => sh == shippingDto.ShipmentInfoId.Value))
                            {
                                _log.Info("Shipment with that Id already processed: " + shippingDto.ShipmentInfoId.Value);
                            }
                            else
                            {
                                processedShipmentIds.Add(shippingDto.ShipmentInfoId.Value);

                                var changeFields = new List <Expression <Func <OrderShippingInfo, object> > >()
                                {
                                    p => p.LastTrackingRequestDate,
                                    p => p.TrackingRequestAttempts
                                };
                                if (hasStateChanges)
                                {
                                    changeFields.Add(p => p.TrackingStateSource);
                                    changeFields.Add(p => p.TrackingStateDate);
                                    changeFields.Add(p => p.TrackingStateEvent);
                                    changeFields.Add(p => p.TrackingLocation);

                                    changeFields.Add(p => p.DeliveredStatus);
                                    changeFields.Add(p => p.IsDelivered);
                                    changeFields.Add(p => p.ActualDeliveryDate);
                                }
                                db.OrderShippingInfos.TrackItem(new OrderShippingInfo()
                                {
                                    Id = shippingDto.ShipmentInfoId.Value,
                                    TrackingStateSource     = shippingDto.TrackingStateSource,
                                    TrackingStateDate       = shippingDto.TrackingStateDate,
                                    TrackingStateEvent      = shippingDto.TrackingStateEvent,
                                    TrackingLocation        = shippingDto.TrackingLocation,
                                    DeliveredStatus         = shippingDto.DeliveredStatus,
                                    IsDelivered             = shippingDto.IsDelivered,
                                    ActualDeliveryDate      = shippingDto.ActualDeliveryDate,
                                    LastTrackingRequestDate = shippingDto.LastTrackingRequestDate,
                                    TrackingRequestAttempts = shippingDto.TrackingRequestAttempts ?? 1
                                },
                                                                changeFields);
                            }
                        }

                        if (shippingDto.MailInfoId.HasValue)
                        {
                            if (processedMailInfoIds.Any(sh => sh == shippingDto.MailInfoId.Value))
                            {
                                _log.Info("Shipment with that Id already processed: " + shippingDto.MailInfoId.Value);
                            }
                            else
                            {
                                processedMailInfoIds.Add(shippingDto.MailInfoId.Value);

                                var changeFields = new List <Expression <Func <MailLabelInfo, object> > >()
                                {
                                    p => p.LastTrackingRequestDate,
                                    p => p.TrackingRequestAttempts
                                };
                                if (hasStateChanges)
                                {
                                    changeFields.Add(p => p.TrackingStateSource);
                                    changeFields.Add(p => p.TrackingStateDate);
                                    changeFields.Add(p => p.TrackingStateEvent);
                                    changeFields.Add(p => p.TrackingLocation);

                                    changeFields.Add(p => p.DeliveredStatus);
                                    changeFields.Add(p => p.IsDelivered);
                                    changeFields.Add(p => p.ActualDeliveryDate);
                                }
                                db.MailLabelInfos.TrackItem(new MailLabelInfo()
                                {
                                    Id = shippingDto.MailInfoId.Value,
                                    TrackingStateSource     = shippingDto.TrackingStateSource,
                                    TrackingStateDate       = shippingDto.TrackingStateDate,
                                    TrackingStateEvent      = shippingDto.TrackingStateEvent,
                                    TrackingLocation        = shippingDto.TrackingLocation,
                                    DeliveredStatus         = shippingDto.DeliveredStatus,
                                    IsDelivered             = shippingDto.IsDelivered,
                                    ActualDeliveryDate      = shippingDto.ActualDeliveryDate,
                                    LastTrackingRequestDate = shippingDto.LastTrackingRequestDate,
                                    TrackingRequestAttempts = shippingDto.TrackingRequestAttempts ?? 1
                                },
                                                            changeFields);
                            }
                        }

                        //NOTE: if do checks only when state changed, the rules based on calculate business day were never activated
                        //if (hasStateChanges)
                        if (lastRecord != null)
                        {
                            CheckRules(db,
                                       shippingDto,
                                       lastRecord.Message,
                                       lastRecord.Date,
                                       state.Records,
                                       ruleList);
                        }
                    }
                }
                db.Commit();

                return(stateList);
            }
            catch (Exception ex)
            {
                _log.Error("UpdateOrderTracking", ex);
            }
            return(null);
        }
コード例 #27
0
        public void ReadEmails(string folder,
                               DateTime?fromDate,
                               IList <string> acceptingToAddresses,
                               IList <string> acceptingFromAddresses,
                               CancellationToken?cancel)
        {
            _emailProcessResultList = new List <EmailReadingResult>();

            using (var imap = new ImapClient(_settings.ImapHost,
                                             _settings.ImapPort,
                                             _settings.ImapUsername,
                                             _settings.ImapPassword,
                                             AuthMethod.Login,
                                             ssl: true))
            {
                //var uids = new List<uint>(ImapClient.Search(SearchCondition.SentSince(sentSince).Or(SearchCondition.GreaterThan(lastUid)), mailbox));

                //var uids = new List<uint>(ImapClient.Search(SearchCondition.From("*****@*****.**"), _mailbox));
                //var uids = new List<uint> {lastUid};// 14559 };
                //var uids = new List<uint>(ImapClient.Search(SearchCondition.SentSince(new DateTime(2013, 12, 3)).Or(SearchCondition.GreaterThan(105748)), mailbox));//.SentSince(sentSince.AddHours(-12)), mailbox));


                var sentSince = fromDate ?? _time.GetUtcTime().AddDays(-2);
                using (var db = _dbFactory.GetRWDb())
                {
                    DateTime?maxEmailDate = db.Emails.GetAll().Max(e => e.ReceiveDate);
                    if (maxEmailDate.HasValue)
                    {
                        sentSince = maxEmailDate.Value.AddHours(-5);
                    }
                }

                uint lastUid = 0;

                //_log.Info(String.Join("; ", imap.ListMailboxes()));
                //var uids = new List<uint>(imap.Search(SearchCondition.SentSince(sentSince).Or(SearchCondition.GreaterThan(lastUid)), "INBOX"));
                var uids = new List <uint>();
                if (_settings.IsDebug)
                {
                    uids = new List <uint>()
                    {
                        30456
                    };
                    //  imap.Search(SearchCondition.Subject("kimlimu_cecku3g5 sent a message about Peppa Pig Little Girls"), folder).ToList();}
                }
                else
                {
                    SearchCondition toCriteria = null;
                    if (acceptingToAddresses != null && acceptingToAddresses.Any())
                    {
                        foreach (var to in acceptingToAddresses)
                        {
                            toCriteria = toCriteria == null?SearchCondition.To(to) : toCriteria.Or(SearchCondition.To(to));
                        }
                    }

                    SearchCondition fromCriteria = null;
                    if (acceptingFromAddresses != null && acceptingFromAddresses.Any())
                    {
                        foreach (var from in acceptingFromAddresses)
                        {
                            fromCriteria = fromCriteria == null?SearchCondition.From(from) : fromCriteria.Or(SearchCondition.From(from));
                        }
                    }

                    var searchCriteria = SearchCondition.SentSince(sentSince);
                    if (toCriteria != null)
                    {
                        searchCriteria = searchCriteria.And(toCriteria);
                    }
                    if (fromCriteria != null)
                    {
                        searchCriteria = searchCriteria.And(fromCriteria);
                    }
                    uids = new List <uint>(imap.Search(searchCriteria, folder));
                }


                foreach (var uid in uids)
                {
                    if (cancel.HasValue && cancel.Value.IsCancellationRequested)
                    {
                        _log.Info("Cancellation Requested!");
                        cancel.Value.ThrowIfCancellationRequested();
                    }


                    _log.Info("Begin check uid: " + uid);
                    var emailProcessingThread = new Thread(() => GetEmail(_dbFactory, imap, _time.GetUtcTime(), uid, folder));
                    emailProcessingThread.Priority = ThreadPriority.Highest;
                    emailProcessingThread.Start();

                    if (_settings.IsDebug)
                    {
                        emailProcessingThread.Join();
                    }
                    else
                    {
                        if (!emailProcessingThread.Join(_settings.ProcessMessageThreadTimeout))
                        {
                            emailProcessingThread.Abort();
                            throw new Exception("Timeout exceeded while processing email. Uid:" + uid);
                        }
                    }
                }

                Console.WriteLine(uids.Count);
            }
        }
コード例 #28
0
        public CheckResult Check(IUnitOfWork db,
                                 DTOMarketOrder order,
                                 IList <ListingOrderDTO> items,
                                 AddressValidationStatus addressValidationStatus)
        {
            //NOTE: Skipping valid addresses
            if (addressValidationStatus < AddressValidationStatus.Invalid)
            {
                return(new CheckResult()
                {
                    IsSuccess = true
                });
            }

            var checkUSPSService   = new PersonatorAddressCheckService(_log, _htmlScraper, null);
            var address            = order.GetAddressDto();
            var addressCheckResult = checkUSPSService.ScrappingCheckAddress(address);
            var result             = new CheckResult()
            {
                IsSuccess = !addressCheckResult.IsNotServedByUSPSNote
            };

            _log.Info("AddressNotServedByUSPSChecker, hasNote=" + addressCheckResult.IsNotServedByUSPSNote);

            if (addressCheckResult.IsNotServedByUSPSNote)
            {
                var existNotifier = db.OrderEmailNotifies.IsExist(order.OrderId,
                                                                  OrderEmailNotifyType.OutputAddressNotServedByUSPSEmail);

                if (!existNotifier)
                {
                    var emailInfo = new AddressNotServedByUSPSEmailInfo(_emailService.AddressService,
                                                                        null,
                                                                        order.OrderId,
                                                                        (MarketType)order.Market,
                                                                        address,
                                                                        order.BuyerName,
                                                                        order.BuyerEmail,
                                                                        order.EarliestShipDate ?? (order.OrderDate ?? DateTime.Today).AddDays(1));

                    _emailService.SendEmail(emailInfo, CallSource.Service);
                    _log.Info("Send address not served by USPS email, orderId=" + order.Id);

                    db.OrderEmailNotifies.Add(new OrderEmailNotify()
                    {
                        OrderNumber = order.OrderId,
                        Reason      = "Address isn’t served by USPS",
                        Type        = (int)OrderEmailNotifyType.OutputAddressNotServedByUSPSEmail,
                        CreateDate  = _time.GetUtcTime(),
                    });
                }

                db.OrderComments.Add(new OrderComment()
                {
                    OrderId    = order.Id,
                    Message    = "Address isn’t served by USPS. Address verification email sent.",
                    Type       = (int)CommentType.OutputEmail,
                    CreateDate = _time.GetAppNowTime(),
                    UpdateDate = _time.GetAppNowTime()
                });

                db.Commit();
            }
            return(result);
        }
コード例 #29
0
        public IList <TrackingState> TrackShipments(IList <TrackingNumberToCheckDto> trackingNumbers)
        {
            var index    = 0;
            var stepSize = 10;
            var results  = new List <TrackingState>();

            while (index < trackingNumbers.Count)
            {
                var requestTrackingList = trackingNumbers.Select(t => t.TrackingNumber).Skip(index).Take(stepSize).ToList();
                var trackingResult      = _api.GetTrackingField(requestTrackingList); //If one tracking from batch request fail whole request fail
                if (trackingResult.Status == CallStatus.Success)
                {
                    results.AddRange(trackingResult.Data);
                }
                else
                {
                    //After batch request fail, make per item request
                    foreach (var trackingNumber in requestTrackingList)
                    {
                        var perOneTrackingResult = _api.GetTrackingField(new List <string>()
                        {
                            trackingNumber
                        });
                        if (perOneTrackingResult.Status == CallStatus.Fail)
                        {
                            _log.Info(String.Format("Error, tracking number={0}: {1}", trackingNumber,
                                                    perOneTrackingResult.Message));
                            results.Add(new TrackingState()
                            {
                                TrackingNumber = trackingNumber,
                                Records        = new List <TrackingRecord>()
                                {
                                    new TrackingRecord()
                                    {
                                        Message = TrackingHelper.BuildUndefinedMessage(perOneTrackingResult.Message),
                                        Date    = _time.GetUtcTime(),
                                    }
                                }
                            });
                        }
                        else
                        {
                            results.AddRange(perOneTrackingResult.Data);
                        }
                    }

                    _log.Info("Error: " + trackingResult.Message);
                }

                index += stepSize;
            }

            foreach (var info in results)
            {
                if (info.Records != null)
                {
                    info.Records.ForEach(r => r.Source = TrackingStatusSources.USPS);
                }
            }

            return(results);
        }
コード例 #30
0
        public void ProcessRefunds(IUnitOfWork db, string tag)
        {
            //NOTE: reprocess cancel request every 2 hours
            DateTime?maxLastAttemptDate = _time.GetUtcTime().AddHours(-4);
            var      maxAttempts        = 10;

            var returnActions = _actionService.GetUnprocessedByType(db,
                                                                    SystemActionType.UpdateOnMarketReturnOrder,
                                                                    maxLastAttemptDate,
                                                                    tag);

            foreach (var action in returnActions)
            {
                Order     order        = null;
                decimal   refundAmount = 0M;
                Exception exception    = null;
                try
                {
                    var data = JsonConvert.DeserializeObject <ReturnOrderInput>(action.InputData);
                    order = db.Orders.GetByOrderNumber(data.OrderNumber);
                    if (order == null)
                    {
                        _log.Info(_api.Market + "_" + _api.MarketplaceId + ": Can't find orderId=" + data.OrderNumber);
                        continue;
                    }

                    if (order.Market != (int)_api.Market ||
                        (!String.IsNullOrEmpty(_api.MarketplaceId) &&
                         order.MarketplaceId != _api.MarketplaceId))
                    {
                        //_log.Info("skip order=" + data.OrderNumber + ", market=" + order.Market + ", marketplace=" + order.MarketplaceId);
                        continue;
                    }

                    _log.Info("Order to refund: " + _api.Market + "_" + _api.MarketplaceId
                              + ", actionId=" + action.Id
                              + ", orderId=" + data.OrderNumber);

                    data.MarketOrderId        = order.MarketOrderId;
                    data.Id                   = action.Id;
                    data.PaymentTransactionId = order.PaymentInfo;

                    #region Prepare Fee Data

                    var orderIds = new List <long>()
                    {
                        order.Id
                    };
                    var orderItems      = db.OrderItems.GetAllAsDto().Where(oi => orderIds.Contains(oi.OrderId)).ToList();
                    var previousRefunds = db.SystemActions.GetAllAsDto().Where(a => a.Type == (int)SystemActionType.UpdateOnMarketReturnOrder &&
                                                                               a.Tag == data.OrderNumber &&
                                                                               a.Id != action.Id)
                                          .ToList();
                    var previousRefundDataList = previousRefunds.Select(i => JsonConvert.DeserializeObject <ReturnOrderInput>(i.InputData)).ToList();

                    foreach (var orderItem in orderItems)
                    {
                        var refundItem = data.Items.FirstOrDefault(oi => oi.ItemOrderId == orderItem.ItemOrderIdentifier);
                        if (refundItem == null)
                        {
                            if (order.Market != (int)MarketType.Walmart) //NOTE: Skip Walmart, builded based on return request
                            {
                                data.Items.Add(new ReturnOrderItemInput()
                                {
                                    ItemOrderId = orderItem.ItemOrderIdentifier,
                                    Quantity    = 0,
                                });
                            }
                        }
                        else
                        {
                            if (refundItem.RefundItemPrice > 0)
                            {
                                decimal alreadyRefundedItemSum = 0;
                                foreach (var refundData in previousRefundDataList)
                                {
                                    alreadyRefundedItemSum += refundData.Items.Where(i => i.ItemOrderId == orderItem.ItemOrderIdentifier).Sum(i => i.RefundItemPrice);
                                }
                                decimal totalItemSum           = orderItems.Where(oi => oi.ItemOrderIdentifier == orderItem.ItemOrderIdentifier).Sum(oi => oi.ItemPaid ?? 0);
                                decimal requestedRefundItemSum = refundItem.RefundItemPrice;

                                var perItemPrice = (orderItem.ItemPaid ?? 0) / (decimal)orderItem.QuantityOrdered;

                                var adjustment = refundItem.RefundItemPrice -
                                                 refundItem.Quantity * perItemPrice;
                                if (adjustment > 0)
                                {
                                    refundItem.AdjustmentRefund = adjustment;
                                }
                                if (adjustment < 0)
                                {
                                    refundItem.AdjustmentFee = -adjustment;
                                }
                            }
                            else
                            {
                                refundItem.Quantity = 0;
                            }
                        }
                    }

                    //Group back for virtual styles
                    data.Items = data.Items
                                 .GroupBy(i => String.Join("_", i.ItemOrderId.Split('_').Take(2)))
                                 .Select(g => new ReturnOrderItemInput()
                    {
                        ItemOrderId            = g.Key,
                        Quantity               = g.Max(i => i.Quantity),
                        Feedback               = g.FirstOrDefault()?.Feedback,
                        Notes                  = g.FirstOrDefault()?.Notes,
                        Reason                 = g.FirstOrDefault()?.Reason,
                        TotalPaidAmount        = g.Sum(i => i.TotalPaidAmount),
                        RefundItemPrice        = g.Sum(i => i.RefundItemPrice),
                        RefundShippingPrice    = g.Sum(i => i.RefundShippingPrice),
                        DeductPrepaidLabelCost = g.Sum(i => i.DeductPrepaidLabelCost),
                        DeductShippingPrice    = g.Sum(i => i.DeductShippingPrice),
                        AdjustmentRefund       = g.Sum(i => i.AdjustmentRefund),
                        AdjustmentFee          = g.Sum(i => i.AdjustmentFee),
                    })
                                 .ToList();

                    refundAmount = data.Items.Sum(i => i.AdjustmentRefund);

                    #endregion

                    var result = _api.RefundOrder(order.AmazonIdentifier, data);

                    if (result.IsSuccess)
                    {
                        var output = new ReturnOrderOutput()
                        {
                            IsProcessed   = true,
                            ResultMessage = "Refunds by API"
                        };
                        _actionService.SetResult(db, action.Id, SystemActionStatus.Done, output);
                        db.Commit();
                    }
                    else
                    {
                        _log.Info("Refund Fail: " + result.Message);
                        var output = new ReturnOrderOutput()
                        {
                            IsProcessed   = true,
                            ResultMessage = "Fail: " + result.Message
                        };
                        _actionService.SetResult(db, action.Id, action.AttemptNumber > maxAttempts ? SystemActionStatus.Fail : SystemActionStatus.None, output);
                        db.Commit();
                    }
                }
                catch (Exception ex)
                {
                    exception = ex;
                    _log.Error("WalmartOrderRefund.Process", ex);
                }

                if (action.AttemptNumber > maxAttempts)
                {
                    var output = new ReturnOrderOutput()
                    {
                        IsProcessed   = true,
                        ResultMessage = exception != null ? exception.Message : ""
                    };
                    _actionService.SetResult(db, action.Id, SystemActionStatus.Fail, output);
                    db.Commit();

                    db.OrderComments.Add(new OrderComment()
                    {
                        OrderId    = order.Id,
                        CreateDate = _time.GetAppNowTime(),
                        Type       = (int)CommentType.ReturnExchange,
                        Message    = "Refund failed, amount: $" + PriceHelper.RoundToTwoPrecision(refundAmount)
                    });
                    db.Commit();

                    _emailService.SendSystemEmail(
                        "System can't process refund, order #" + (order != null ? order.CustomerOrderId : "n/a"),
                        "Details: " + (exception != null ? exception.Message : "-"),
                        EmailHelper.RafiEmail + ";" + EmailHelper.RaananEmail,
                        EmailHelper.SupportDgtexEmail);
                }
            }
        }