Пример #1
0
        /// <summary>
        /// 取消支付
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        public async Task <Result> Cancel(int orderId, string reason)
        {
            var order = await _orderRepository.Query().FirstOrDefaultAsync(e => e.Id == orderId);

            if (order == null)
            {
                return(Result.Fail(ResultCodes.IdInvalid));
            }

            if (order.OrderStatus == OrderStatus.Canceled)
            {
                return(Result.Fail(ResultCodes.RequestParamError, "当前订单状态不允许删除"));
            }

            var status = new OrderStatus[] { OrderStatus.PaymentFailed, OrderStatus.PendingPayment };

            if (!status.Contains(order.OrderStatus))
            {
                return(Result.Fail(ResultCodes.RequestParamError, "当前订单状态不允许删除"));
            }

            order.OrderStatus  = OrderStatus.Canceled;
            order.CancelReason = reason;
            order.CancelTime   = DateTime.Now;
            _orderRepository.Update(order, false);

            using (var transaction = _orderRepository.BeginTransaction())
            {
                await _orderRepository.SaveAsync();

                transaction.Commit();
            }

            return(Result.Ok());
        }
Пример #2
0
        public async Task <Result> AdminPayment(int id)
        {
            var currentUser = await _workContext.GetCurrentOrThrowAsync();

            var order = await _orderRepository.Query().Where(c => c.Id == id).FirstOrDefaultAsync();

            if (order == null)
            {
                return(Result.Fail("订单不存在"));
            }

            var orderSs = new OrderStatus[] { OrderStatus.New, OrderStatus.PendingPayment, OrderStatus.PaymentFailed };

            if (!orderSs.Contains(order.OrderStatus))
            {
                return(Result.Fail("当前订单状态不允许标记付款"));
            }

            await _orderService.PaymentReceived(new PaymentReceivedParam()
            {
                OrderId = order.Id,
                Note    = "标记付款"
            });

            return(Result.Ok());
        }
Пример #3
0
        public async Task <Result> Cancel(int id, [FromBody] OrderCancelParam reason)
        {
            var user = await _workContext.GetCurrentOrThrowAsync();

            var order = await _orderRepository.Query()
                        .FirstOrDefaultAsync(c => c.CustomerId == user.Id && c.Id == id);

            if (order == null)
            {
                return(Result.Fail("订单不存在"));
            }
            else if (order.OrderStatus == OrderStatus.Canceled)
            {
                return(Result.Fail("订单已取消"));
            }
            var orderSs = new OrderStatus[] { OrderStatus.New, OrderStatus.PendingPayment, OrderStatus.PaymentFailed };

            if (!orderSs.Contains(order.OrderStatus))
            {
                return(Result.Fail("当前订单无法取消"));;
            }
            await _orderService.Cancel(id, user.Id, reason?.Reason);

            return(Result.Ok());
        }
Пример #4
0
        public async Task <Result> Delete(int id)
        {
            var currentUser = await _workContext.GetCurrentUserAsync();

            var order = await _orderRepository
                        .Query()
                        .Include(c => c.BillingAddress)
                        .Include(c => c.ShippingAddress)
                        .Include(c => c.OrderItems).ThenInclude(c => c.Product)
                        .Where(c => c.Id == id).FirstOrDefaultAsync();

            if (order == null)
            {
                return(Result.Fail("订单不存在"));
            }
            var orderSs = new OrderStatus[] { OrderStatus.Complete, OrderStatus.Canceled };

            if (!orderSs.Contains(order.OrderStatus))
            {
                return(Result.Fail("当前订单状态不允许删除"));
            }

            if (order.ShippingAddress != null)
            {
                order.ShippingAddress.IsDeleted = true;
                order.ShippingAddress.UpdatedOn = DateTime.Now;
            }
            if (order.BillingAddress != null)
            {
                order.BillingAddress.IsDeleted = true;
                order.BillingAddress.UpdatedOn = DateTime.Now;
            }

            foreach (var item in order.OrderItems)
            {
                item.IsDeleted = true;
                item.UpdatedOn = DateTime.Now;
                item.UpdatedBy = currentUser;
            }

            //删除订单暂不删除历史

            order.IsDeleted = true;
            order.UpdatedOn = DateTime.Now;
            order.UpdatedBy = currentUser;

            await _orderRepository.SaveChangesAsync();

            return(Result.Ok());
        }
Пример #5
0
        public async Task <Result> OnHold(int id, [FromBody] OrderOnHoldParam param)
        {
            var currentUser = await _workContext.GetCurrentUserAsync();

            var order = await _orderRepository
                        .Query()
                        .Where(c => c.Id == id).FirstOrDefaultAsync();

            if (order == null)
            {
                return(Result.Fail("订单不存在"));
            }

            if (order.OrderStatus == OrderStatus.OnHold)
            {
                return(Result.Fail("订单已挂起"));
            }

            var orderNotSs = new OrderStatus[] { OrderStatus.Canceled, OrderStatus.Complete };

            if (orderNotSs.Contains(order.OrderStatus))
            {
                return(Result.Fail("当前订单状态不允许挂起"));
            }

            var oldStatus = order.OrderStatus;

            order.OrderStatus  = OrderStatus.OnHold;
            order.OnHoldReason = param?.Reason;
            order.UpdatedOn    = DateTime.Now;
            order.UpdatedBy    = currentUser;
            await _orderRepository.SaveChangesAsync();

            var orderStatusChanged = new OrderChanged
            {
                OrderId   = order.Id,
                OldStatus = oldStatus,
                NewStatus = order.OrderStatus,
                Order     = order,
                UserId    = currentUser.Id,
                Note      = "挂起订单"
            };
            await _mediator.Publish(orderStatusChanged);

            return(Result.Ok());
        }
Пример #6
0
        public async Task <Result> Delete(int id)
        {
            var order = await _orderRepository.FirstOrDefaultAsync(id);

            if (order == null)
            {
                return(Result.Fail(ResultCodes.IdInvalid));
            }

            var status = new OrderStatus[] { OrderStatus.Complete, OrderStatus.Canceled };

            if (!status.Contains(order.OrderStatus))
            {
                return(Result.Fail(ResultCodes.RequestParamError, "当前订单状态不允许删除"));
            }

            await _orderRepository.RemoveAsync(order);

            return(Result.Ok());
        }
Пример #7
0
        public async Task <Result> DelayCinfirmReceipt(int id)
        {
            var user = await _workContext.GetCurrentOrThrowAsync();

            var order = await _orderRepository.Query()
                        .FirstOrDefaultAsync(c => c.CustomerId == user.Id && c.Id == id);

            if (order == null)
            {
                return(Result.Fail("订单不存在"));
            }
            else if (order.OrderStatus == OrderStatus.Canceled)
            {
                return(Result.Fail("订单已取消"));
            }
            var orderSs = new OrderStatus[] { OrderStatus.PaymentReceived, OrderStatus.Shipping, OrderStatus.Shipped };

            if (!orderSs.Contains(order.OrderStatus))
            {
                return(Result.Fail("当前订单无法延长确认收货时间"));;
            }

            var timeFromMin = await _appSettingService.Get <int>(OrderKeys.OrderAutoCompleteTimeForMinute);

            if (order.DeliveredEndOn == null)
            {
                order.DeliveredEndOn = DateTime.Now;
            }
            order.DeliveredEndOn = order.DeliveredEndOn.Value.AddMinutes(timeFromMin);

            if (order.DeliveredEndOn > order.CreatedOn.AddDays(60))
            {
                return(Result.Fail("延长确认收货时间最大不可超过60天"));
            }

            order.UpdatedOn   = DateTime.Now;
            order.UpdatedById = user.Id;
            await _orderRepository.SaveChangesAsync();

            return(Result.Ok());
        }
Пример #8
0
        public async Task <Result> CinfirmReceipt(int id)
        {
            var user = await _workContext.GetCurrentOrThrowAsync();

            var order = await _orderRepository.Query()
                        .FirstOrDefaultAsync(c => c.CustomerId == user.Id && c.Id == id);

            if (order == null)
            {
                return(Result.Fail("订单不存在"));
            }
            else if (order.OrderStatus == OrderStatus.Canceled)
            {
                return(Result.Fail("订单已取消"));
            }
            var orderSs = new OrderStatus[] { OrderStatus.PaymentReceived, OrderStatus.Shipping, OrderStatus.Shipped };

            if (!orderSs.Contains(order.OrderStatus))
            {
                return(Result.Fail("当前订单无法确认收货"));;
            }

            order.OrderStatus    = OrderStatus.Complete;
            order.ShippingStatus = ShippingStatus.Delivered;
            order.DeliveredOn    = DateTime.Now;
            order.UpdatedOn      = DateTime.Now;
            order.UpdatedById    = user.Id;
            await _orderRepository.SaveChangesAsync();

            // 自动好评
            var min = await _appSettingService.Get <int>(OrderKeys.OrderCompleteAutoReviewTimeForMinute);

            foreach (var item in order.OrderItems)
            {
                await _jobService.Schedule(() =>
                                           _reviewService.ReviewAutoGood(item.ProductId, EntityTypeWithId.Product, order.Id, ReviewSourceType.Order)
                                           , TimeSpan.FromMinutes(min));
            }

            return(Result.Ok());
        }
Пример #9
0
        /// <summary>
        /// 库增加/存减少规则
        /// 当增加下单数量时减少库存
        /// 当减少下单数量时增加库存
        /// </summary>
        /// <param name="stocks"></param>
        /// <param name="product"></param>
        /// <param name="quantity">减少或增加库存数量,减少库存负数,增加库存整数</param>
        /// <param name="orderId"></param>
        /// <param name="note"></param>
        void OrderStockDoWorker(IList <Stock> stocks, IList <StockHistory> addStockHistories, Product product, User user, int quantity, Order order, string note)
        {
            if (product?.StockTrackingIsEnabled != true || quantity == 0)
            {
                return;
            }

            // 交易取消、交易完成的订单修改下单数量不修改库存
            var notStockOrderStatus = new OrderStatus[] { OrderStatus.Canceled, OrderStatus.Complete };

            if (order == null || notStockOrderStatus.Contains(order.OrderStatus))
            {
                return;
            }

            if (stocks.Count <= 0)
            {
                throw new Exception("商品库存不存在");
            }

            var productStocks = stocks.Where(c => c.ProductId == product.Id && c.IsEnabled);

            if (productStocks.Count() <= 0)
            {
                throw new Exception($"商品:{product.Name},无可用库存");
            }

            switch (product.StockReduceStrategy)
            {
            case StockReduceStrategy.PlaceOrderWithhold:
                //下单减库存时,支持成功,不减少库存
                if (order.OrderStatus == OrderStatus.PaymentReceived)
                {
                    return;
                }
                break;

            case StockReduceStrategy.PaymentSuccessDeduct:
                //支付减库存时,下单、待支付、支付失败,不减少库存
                var oss = new OrderStatus[] { OrderStatus.New, OrderStatus.PendingPayment, OrderStatus.PaymentFailed };
                if (oss.Contains(order.OrderStatus))
                {
                    return;
                }
                break;

            default:
                throw new Exception("库存扣减策略不存在");
            }

            //分布式锁,重新获取库存
            //todo

            if (quantity < 0)
            {
                //减少库存
                var absQuantity = Math.Abs(quantity);
                if (productStocks.Sum(c => c.StockQuantity) < absQuantity)
                {
                    throw new Exception($"商品[{product.Name}]库存不足,库存剩余:{productStocks.Sum(c => c.StockQuantity)}");
                }
                do
                {
                    var firstStock = productStocks.Where(c => c.StockQuantity > 0).OrderBy(c => c.DisplayOrder).FirstOrDefault();
                    if (firstStock == null)
                    {
                        throw new Exception($"商品[{product.Name}]库存不足");
                    }
                    if (firstStock.StockQuantity >= absQuantity)
                    {
                        firstStock.StockQuantity = firstStock.StockQuantity - absQuantity;
                        if (firstStock.StockQuantity < 0)
                        {
                            throw new Exception($"商品[{product.Name}]库存不足");
                        }
                        addStockHistories.Add(new StockHistory()
                        {
                            Note             = $"订单:{order.No},商品:{product.Name},减少库存:{absQuantity}。备注:{note}",
                            CreatedBy        = user,
                            UpdatedBy        = user,
                            AdjustedQuantity = -absQuantity,
                            StockQuantity    = firstStock.StockQuantity,
                            WarehouseId      = firstStock.WarehouseId,
                            ProductId        = product.Id
                        });
                        absQuantity = 0;
                    }
                    else
                    {
                        absQuantity = absQuantity - firstStock.StockQuantity;
                        if (absQuantity < 0)
                        {
                            throw new Exception($"库存扣减异常,请重试");
                        }
                        addStockHistories.Add(new StockHistory()
                        {
                            Note             = $"订单:{order.No},商品:{product.Name},减少库存:{absQuantity}。备注:{note}",
                            CreatedBy        = user,
                            UpdatedBy        = user,
                            AdjustedQuantity = -firstStock.StockQuantity,
                            StockQuantity    = 0,
                            WarehouseId      = firstStock.WarehouseId,
                            ProductId        = product.Id
                        });
                        firstStock.StockQuantity = 0;
                    }
                } while (absQuantity > 0);
            }
            else if (quantity > 0)
            {
                //增加库存
                var firstStock = productStocks.OrderBy(c => c.DisplayOrder).FirstOrDefault();
                if (firstStock == null)
                {
                    throw new Exception($"商品:{product.Name},无可用库存");
                }
                firstStock.StockQuantity += quantity;

                addStockHistories.Add(new StockHistory()
                {
                    Note             = $"订单:{order.No},商品:{product.Name},增加库存(减少下单商品数量):{quantity}。备注:{note}",
                    CreatedBy        = user,
                    UpdatedBy        = user,
                    AdjustedQuantity = quantity,
                    StockQuantity    = firstStock.StockQuantity,
                    WarehouseId      = firstStock.WarehouseId,
                    ProductId        = product.Id
                });
            }
        }
Пример #10
0
        public async Task PaymentReceived(PaymentReceivedParam param)
        {
            if (param == null)
            {
                return;
            }

            var orderSs = new OrderStatus[] { OrderStatus.New, OrderStatus.PendingPayment, OrderStatus.PaymentFailed };
            var user    = await _workContext.GetCurrentUserOrNullAsync();

            var userId = user?.Id ?? (int)UserWithId.System;
            var query  = _orderRepository.Query();

            if (param.OrderId.HasValue && param.OrderId.Value > 0)
            {
                query = query.Where(c => c.Id == param.OrderId.Value);
            }
            else if (!string.IsNullOrWhiteSpace(param.OrderNo))
            {
                var longOrderNo = Convert.ToInt64(param.OrderNo);
                query = query.Where(c => c.No == longOrderNo);
            }
            else
            {
                return;
            }

            var order = await query.Include(c => c.OrderItems).ThenInclude(c => c.Product)
                        .FirstOrDefaultAsync();

            if (order == null || !orderSs.Contains(order.OrderStatus))
            {
                return;
            }

            order.OrderStatus      = OrderStatus.PaymentReceived;
            order.PaymentMethod    = param.PaymentMethod;
            order.PaymentOn        = param.PaymentOn ?? DateTime.Now;
            order.PaymentFeeAmount = param.PaymentFeeAmount ?? order.OrderTotal;
            order.UpdatedOn        = DateTime.Now;
            order.UpdatedById      = userId;

            //标记付款,付款减少库存商品,减少库存
            var productIds = order.OrderItems.Select(c => c.ProductId).Distinct();
            var stocks     = await _stockRepository.Query().Where(c => productIds.Contains(c.ProductId)).ToListAsync();

            var addStockHistories = new List <StockHistory>();

            foreach (var item in order.OrderItems)
            {
                OrderStockDoWorker(stocks, addStockHistories, item.Product, userId, -item.Quantity, order, "标记付款");
            }

            using (var transaction = _orderRepository.BeginTransaction())
            {
                await _orderRepository.SaveChangesAsync();

                await _stockRepository.SaveChangesAsync();

                if (addStockHistories.Count > 0)
                {
                    _stockHistoryRepository.AddRange(addStockHistories);
                    await _stockHistoryRepository.SaveChangesAsync();
                }
                transaction.Commit();
            }
        }
Пример #11
0
        public async Task Cancel(int id, int userId, string reason)
        {
            //var currentUser = await _workContext.GetCurrentUser();
            var order = await _orderRepository.Query()
                        .Include(c => c.OrderItems).ThenInclude(c => c.Product)
                        .Where(c => c.Id == id).FirstOrDefaultAsync();

            if (order == null || order.OrderStatus == OrderStatus.Canceled)
            {
                return;
            }
            var orderSs = new OrderStatus[] { OrderStatus.New, OrderStatus.PendingPayment, OrderStatus.PaymentFailed };

            if (!orderSs.Contains(order.OrderStatus))
            {
                return;
            }

            var productIds = order.OrderItems.Select(c => c.ProductId).Distinct();
            var stocks     = await _stockRepository.Query().Where(c => productIds.Contains(c.ProductId)).ToListAsync();

            var addStockHistories = new List <StockHistory>();

            //取消订单增加库存
            foreach (var item in order.OrderItems)
            {
                OrderStockDoWorker(stocks, addStockHistories, item.Product, userId, item.Quantity, order, "取消订单");
            }
            var oldStatus = order.OrderStatus;

            order.OrderStatus  = OrderStatus.Canceled;
            order.CancelReason = reason;
            order.UpdatedOn    = DateTime.Now;
            order.UpdatedById  = userId;

            using (var transaction = _orderRepository.BeginTransaction())
            {
                await _orderRepository.SaveChangesAsync();

                var orderStatusChanged = new OrderChanged
                {
                    OrderId   = order.Id,
                    OldStatus = oldStatus,
                    NewStatus = order.OrderStatus,
                    Order     = order,
                    UserId    = userId,
                    Note      = "取消订单"
                };
                await _mediator.Publish(orderStatusChanged);

                await _stockRepository.SaveChangesAsync();

                if (addStockHistories.Count > 0)
                {
                    _stockHistoryRepository.AddRange(addStockHistories);
                    await _stockHistoryRepository.SaveChangesAsync();
                }
                transaction.Commit();
            }

            //var orderItems = _orderItemRepository.Query().Include(x => x.Product).Where(x => x.Order.Id == order.Id);
            //foreach (var item in orderItems)
            //{
            //    //if (item.Product.StockTrackingIsEnabled)
            //    //{
            //    //    item.Product.StockQuantity = item.Product.StockQuantity + item.Quantity;
            //    //}
            //    // 库存处理
            //}
        }
Пример #12
0
        public async Task <Result> Payment(int orderId)
        {
            var order = await _orderRepository.Query().FirstOrDefaultAsync(e => e.Id == orderId);

            if (order == null)
            {
                return(Result.Fail(ResultCodes.IdInvalid));
            }

            var status = new OrderStatus[] { OrderStatus.PendingPayment, OrderStatus.PaymentFailed };

            if (!status.Contains(order.OrderStatus))
            {
                return(Result.Fail(ResultCodes.RequestParamError, "当前订单状态不允许付款"));
            }

            if (order.ActuallyAmount <= 0)
            {
                return(Result.Fail(ResultCodes.RequestParamError, "订单金额不能为0"));
            }
            if (order.ActuallyAmount - order.WalletAmount <= 0)
            {
                return(Result.Fail(ResultCodes.RequestParamError, "订单金额不能为0"));
            }

            var user = await _customerManager.GetUserAsync();

            try
            {
                var wechatResponse = await _paymentService.GeneratePaymentOrder(new GeneratePaymentOrderRequest
                {
                    OrderNo  = order.OrderNo,
                    OpenId   = user.OpenId,
                    TotalFee = order.ActuallyAmount - order.WalletAmount,
                    Subject  = "大脉商城",
                });

                var paymentTimeoutEvent = new PaymentTimeoutEvent()
                {
                    OrderId = order.Id,
                    OrderNo = order.OrderNo
                };

                var headers = new Dictionary <string, object>()
                {
                    { "x-delay", 10 * 60 * 1000 } // 延迟10分钟
                };
                var properties = _client.CreateProperties();
                properties.Headers = headers;

                _client.PushMessage(MQConstants.Exchange, MQConstants.PaymentTimeOutRouteKey, paymentTimeoutEvent, properties);

                return(Result.Ok(wechatResponse));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message, ex);

                return(Result.Fail(ResultCodes.PaymentRequestError, ex.Message));
            }
        }
Пример #13
0
		public void GetOrdersArchive_should_filter_orders_by_status()
		{
			_userManager.GetByEmail(Arg.Any<string>()).ReturnsForAnyArgs(_frequentlyUsedClient);
			var allowedStatuses = new OrderStatus[] { OrderStatus.Completed, OrderStatus.Cancelled };

			var actual = _target.GetOrdersArchive(new ClientDashboardFilter() { PageNumber = 1, ItemsPerPage = int.MaxValue });

			actual.Items.Select(e => e.Status).Any(e => !allowedStatuses.Contains(e)).Should().BeFalse();
		}
Пример #14
0
		public void GetActiveOrders_should_filter_orders_by_status()
		{
			_userManager.GetByEmail(Arg.Any<string>()).ReturnsForAnyArgs(_frequentlyUsedClient);
			var excludedStatuses = new OrderStatus[] { OrderStatus.Draft, OrderStatus.PendingAssignment, 
				OrderStatus.Completed, OrderStatus.Cancelled, OrderStatus.CreationProcess };

			var actual = _target.GetActiveOrders(new ClientDashboardFilter() { PageNumber = 1, ItemsPerPage = int.MaxValue });

			actual.Items.Select(e => e.Status).Any(e => excludedStatuses.Contains(e)).Should().BeFalse();
		}
Пример #15
0
        /// <summary>
        /// 支付接收
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task PaymentReceived(PaymentReceivedRequest request)
        {
            var order = await _orderRepository.Query()
                        .Include(e => e.OrderItems)
                        .ThenInclude(e => e.CommissionHistory)
                        .FirstOrDefaultAsync(e => e.OrderNo == request.OrderNo);

            if (order == null)
            {
                return;
            }

            var status = new OrderStatus[] { OrderStatus.PendingPayment, OrderStatus.PaymentFailed };

            if (!status.Contains(order.OrderStatus))
            {
                return;
            }

            var         roleResult = false;
            PartnerRole role       = PartnerRole.Default;

            if (!string.IsNullOrEmpty(order.ExtendParams))
            {
                roleResult = Enum.TryParse <PartnerRole>(order.ExtendParams, true, out role);
            }

            var totalCommission = 0;
            var totalAmount     = 0;
            var commissions     = order.OrderItems.Where(e => e.CommissionHistory != null).Select(e => e.CommissionHistory);

            if (commissions.Count() > 0)
            {
                foreach (var item in commissions)
                {
                    if (order.IsFirstOrder)
                    {
                        totalAmount        += item.Commission;
                        item.Status         = CommissionStatus.Complete;
                        item.SettlementTime = DateTime.Now;
                    }
                    else
                    {
                        totalCommission += item.Commission;
                        item.Status      = CommissionStatus.PendingSettlement;
                    }
                }
            }

            order.OrderStatus   = OrderStatus.PaymentReceived;
            order.PaymentMethod = request.PaymentMethod;
            order.PaymentTime   = request.PaymentTime;
            order.PaymentFee    = request.PaymentFee;

            _orderRepository.Update(order, false);

            using (var transaction = _orderRepository.BeginTransaction())
            {
                await _orderRepository.SaveAsync();

                if (roleResult)
                {
                    await _customerRepository.UpdateProperyAsync(new Customer
                    {
                        Id   = order.CustomerId,
                        Role = role
                    }, nameof(Customer.Role));
                }

                if (totalCommission > 0 || totalAmount > 0)
                {
                    var parentId = commissions.Select(e => e.CustomerId).FirstOrDefault();
                    await _customerManager.UpdateAssets(parentId, totalCommission, totalAmount, "下级首单返佣金");
                }

                if (order.WalletAmount > 0)
                {
                    await _customerManager.UpdateAssets(order.CustomerId, 0, 0, -order.WalletAmount, "商品抵扣金额");
                }

                transaction.Commit();
            }
        }