/// <summary> /// 添加警告信息 /// </summary> public void AddWarnings( SellerOrder order, IList <HtmlString> warnings, OrderOperatorType operatorType) { // 警告担保交易未确认收款 var orderManager = Application.Ioc.Resolve <SellerOrderManager>(); var transactions = orderManager.GetReleatedTransactions(order.Id); if (transactions.Any(t => t.State == PaymentTransactionState.SecuredPaid)) { if (operatorType == OrderOperatorType.Buyer) { warnings.Add(HtmlString.Encode( new T("You're using secured paid, please confirm transaction on payment platform after received goods"))); } else { warnings.Add(HtmlString.Encode( new T("Buyer is using secured paid, please tell the buyer confirm transaction on payment platform after received goods"))); } } // 警告关联交易的最后发生错误 var lastErrors = transactions.Select(t => t.LastError).Where(e => !string.IsNullOrEmpty(e)); foreach (var lastError in lastErrors) { warnings.Add(HtmlString.Encode( new T("Releated transaction contains error: {0}", new T(lastError)))); } }
/// <summary> /// 添加详细信息 /// </summary> public void AddSubjects( SellerOrder order, IList <HtmlString> subjects, OrderOperatorType operatorType) { // 收货地址 var templateManager = Application.Ioc.Resolve <TemplateManager>(); var address = order.OrderParameters.GetShippingAddress(); if (!string.IsNullOrEmpty(address.DetailedAddress)) { subjects.Add(new HtmlString(templateManager.RenderTemplate( "shopping.order/tmpl.order_view.details_subject_row.html", new { name = new T("ShippingAddress"), value = address.GenerateSummary() }))); } // 买家留言和卖家留言 var lastBuyerComment = order.OrderComments .Where(c => c.Side == OrderCommentSide.BuyerComment) .OrderBy(c => c.CreateTime) .LastOrDefault()?.Contents; var lastSellerComment = order.OrderComments .Where(c => c.Side == OrderCommentSide.SellerComment) .OrderBy(c => c.CreateTime) .LastOrDefault()?.Contents; subjects.Add(new HtmlString(templateManager.RenderTemplate( "shopping.order/tmpl.order_view.details_comment_row.html", new { name = new T("BuyerComment"), value = lastBuyerComment }))); subjects.Add(new HtmlString(templateManager.RenderTemplate( "shopping.order/tmpl.order_view.details_comment_row.html", new { name = new T("SellerComment"), value = lastSellerComment }))); // 订单编号 subjects.Add(new HtmlString(templateManager.RenderTemplate( "shopping.order/tmpl.order_view.details_subject_row.html", new { name = new T("OrderSerial"), value = order.Serial }))); // 下单时间 subjects.Add(new HtmlString(templateManager.RenderTemplate( "shopping.order/tmpl.order_view.details_subject_row.html", new { name = new T("CreateTime"), value = order.CreateTime.ToClientTimeString() }))); // 支付接口 var paymentApiManager = Application.Ioc.Resolve <PaymentApiManager>(); var paymentApiId = order.OrderParameters.GetPaymentApiId(); var payment = paymentApiManager.GetWithCache(paymentApiId); subjects.Add(new HtmlString(templateManager.RenderTemplate( "shopping.order/tmpl.order_view.details_subject_row.html", new { name = new T("PaymentApi"), value = new T(payment?.Name) }))); // 物流配送 // 这里只显示买家指定的,不显示后台实际发货使用的 var logisticsManager = Application.Ioc.Resolve <LogisticsManager>(); var logisticsId = order.OrderParameters.GetSellerToLogistics() .GetOrDefault(order.Owner?.Id ?? Guid.Empty); var logistics = logisticsManager.GetWithCache(logisticsId); if (logistics != null) { subjects.Add(new HtmlString(templateManager.RenderTemplate( "shopping.order/tmpl.order_view.details_subject_row.html", new { name = new T("OrderLogistics"), value = new T(logistics?.Name) }))); } }
/// <summary> /// 检查订单是否满足指定条件 /// 返回是否满足和文本信息 /// </summary> /// <param name="order">订单</param> /// <param name="getCheckFunc">获取检查函数的函数</param> /// <returns></returns> public static Pair <bool, string> Check( this SellerOrder order, Func <IOrderChecker, CheckFunc> getCheckFunc) { var result = Pair.Create(false, "No Result"); var checkers = Application.Ioc.ResolveMany <IOrderChecker>(); checkers.ForEach(c => getCheckFunc(c)(order, ref result)); return(result); }
/// <summary> /// 判断是否可以评价这个订单 /// 如果订单状态是交易成功, 并且有至少一个未评价的订单商品则可以评价这个订单 /// </summary> /// <param name="order">卖家订单</param> /// <returns></returns> public virtual bool CanRateOrder(SellerOrder order) { if (order.State != OrderState.OrderSuccess) { return(false); } var orderProductIds = order.OrderProducts.Select(p => p.Id).ToList(); var count = Count(r => orderProductIds.Contains(r.OrderProduct.Id)); return(count < orderProductIds.Count); }
/// <summary> /// 判断订单是否可以发货 /// 后台使用 /// 允许条件: 订单状态是等待发货 /// </summary> public void CanSendGoods(SellerOrder order, ref Pair <bool, string> result) { if (order.State != OrderState.WaitingSellerSendGoods) { result = Pair.Create(false, new T("Order can't send goods because it's not waiting seller send goods").ToString()); } else { result = Pair.Create(true, (string)null); } }
/// <summary> /// 判断订单是否可以确认收货 /// 前台使用 /// 允许条件: 订单状态是已发货 /// </summary> public void CanConfirm(SellerOrder order, ref Pair <bool, string> result) { if (order.State != OrderState.WaitingBuyerConfirm) { result = Pair.Create(false, new T("Order can't be confirmed because it's not waiting buyer confirm").ToString()); } else { result = Pair.Create(true, (string)null); } }
/// <summary> /// 判断订单是否可以付款 /// 前台使用 /// 允许条件: 订单状态是等待付款 /// </summary> public void CanPay(SellerOrder order, ref Pair <bool, string> result) { if (order.State != OrderState.WaitingBuyerPay) { result = Pair.Create(false, new T("Order not payable because it's not waiting buyer pay").ToString()); } else { result = Pair.Create(true, (string)null); } }
/// <summary> /// 添加订单留言 /// </summary> /// <param name="order">订单</param> /// <param name="userId">用户Id</param> /// <param name="side">买家或卖家留言</param> /// <param name="contents">留言内容</param> public void AddComment(SellerOrder order, Guid?userId, OrderCommentSide side, string contents) { var userManager = Application.Ioc.Resolve <UserManager>(); var comment = new OrderComment() { Order = order, Owner = userId.HasValue ? userManager.Get(userId.Value) : null, Side = side, Contents = contents }; Save(ref comment); }
/// <summary> /// 判断订单是否可以编辑收货地址 /// 后台使用 /// 允许条件: 订单状态是等待付款,或等待发货 /// </summary> public void CanEditShippingAddress(SellerOrder order, ref Pair <bool, string> result) { if (order.State != OrderState.WaitingBuyerPay && order.State != OrderState.WaitingSellerSendGoods) { result = Pair.Create(false, new T("Order can't edit shipping address because it's not waiting buyer pay or waiting seller send goods").ToString()); } else { result = Pair.Create(true, (string)null); } }
/// <summary> /// 设置订单的状态和状态时间 /// </summary> /// <param name="order">订单</param> /// <param name="state">状态</param> public static void SetState( this SellerOrder order, OrderState state) { // 设置状态和时间 order.State = state; order.StateTimes[state] = DateTime.UtcNow; // 触发setter order.StateTimes = order.StateTimes; // 通知状态改变 foreach (var handler in Application.Ioc.ResolveMany <IOrderHandler>()) { handler.OnStateChanged(order, state); } }
/// <summary> /// 根据订单状态的改变扣减库存 /// </summary> public void OnStateChanged(SellerOrder order, OrderState state) { var configManager = Application.Ioc.Resolve <GenericConfigManager>(); var orderSettings = configManager.GetData <OrderSettings>(); if ((state == OrderState.WaitingBuyerPay && orderSettings.StockReductionMode == StockReductionMode.AfterCreateOrder) || (state == OrderState.WaitingSellerDeliveryGoods && orderSettings.StockReductionMode == StockReductionMode.AfterOrderPaid)) { var orderManager = Application.Ioc.Resolve <SellerOrderManager>(); orderManager.ReduceStock(order); } }
/// <summary> /// 添加工具按钮 /// </summary> public void AddToolButtons( SellerOrder order, IList <HtmlString> toolButtons, OrderOperatorType operatorType) { // 复制收货人地址的按钮 var address = order.OrderParameters.GetShippingAddress(); if (!string.IsNullOrEmpty(address.DetailedAddress)) { var templateManager = Application.Ioc.Resolve <TemplateManager>(); toolButtons.Add(new HtmlString(templateManager.RenderTemplate( "shopping.order/tmpl.order_view.details_copy_address.html", new { summary = address.GenerateSummary() }))); } }
/// <summary> /// 判断订单是否可以作废 /// 后台使用 /// 允许条件: 订单状态不是已作废或已取消 /// </summary> public void CanSetInvalid(SellerOrder order, ref Pair <bool, string> result) { if (order.State == OrderState.OrderInvalid) { result = Pair.Create(false, new T("Order already invalid").ToString()); } else if (order.State == OrderState.OrderCancelled) { result = Pair.Create(false, new T("Order already cancelled").ToString()); } else { result = Pair.Create(true, (string)null); } }
/// <summary> /// 在订单变为已发货时后台通知支付平台已发货 /// </summary> public void OnStateChanged(SellerOrder order, OrderState state) { if (state == OrderState.WaitingBuyerConfirm) { var transactionManager = Application.Ioc.Resolve <PaymentTransactionManager>(); var lastDelivery = order.OrderDeliveries .OrderByDescending(d => d.CreateTime).FirstOrDefault(); var logisticsName = lastDelivery?.Logistics?.Name; var invoiceNo = lastDelivery?.LogisticsSerial; var orderManager = Application.Ioc.Resolve <SellerOrderManager>(); foreach (var transaction in orderManager.GetReleatedTransactions(order.Id)) { transactionManager.NotifyAllGoodsShippedBackground( transaction.Id, logisticsName, invoiceNo); } } }
/// <summary> /// 添加订单操作 /// </summary> public void AddActions(SellerOrder order, IList <HtmlString> actions, OrderOperatorType operatorType) { // 买家 var productRatingManager = Application.Ioc.Resolve <ProductRatingManager>(); var templateManager = Application.Ioc.Resolve <TemplateManager>(); if (operatorType == OrderOperatorType.Buyer) { // 评价 var canRate = productRatingManager.CanRateOrder(order); if (canRate) { actions.Add(DefaultOrderDisplayInfoProvider.GetLinkAction(templateManager, new T("Rate"), productRatingManager.GetRatingUrl(order), "fa fa-star-o", "btn btn-primary")); } } }
/// <summary> /// 获取商品评价的html /// </summary> /// <param name="order">卖家订单</param> /// <returns></returns> public virtual HtmlString GetProductRatingsHtml(SellerOrder order) { var table = new StaticTableBuilder(); table.Columns.Add("Product"); table.Columns.Add("Rate", "150"); table.Columns.Add("ProductRating", "300"); foreach (var product in order.OrderProducts) { var rating = Get(r => r.OrderProduct.Id == product.Id); table.Rows.Add(new { Product = product.ToDisplayInfo().GetSummaryHtml(), Rate = new T(rating?.Rank.GetDescription() ?? "No Rating"), ProductRating = rating?.Comment }); } return((HtmlString)table.ToLiquid()); }
/// <summary> /// 判断订单是否可以修改价格 /// 后台使用 /// 允许条件: 订单状态是等待付款,且关联的收款交易的状态是初始状态 /// </summary> public void CanEditCost(SellerOrder order, ref Pair <bool, string> result) { var orderManager = Application.Ioc.Resolve <SellerOrderManager>(); if (order.State != OrderState.WaitingBuyerPay) { result = Pair.Create(false, new T("Order can't edit cost because it's not waiting buyer pay").ToString()); } else if (orderManager.GetReleatedTransactions(order.Id).Any(t => t.State != PaymentTransactionState.Initial)) { result = Pair.Create(false, new T("Order can't edit cost because some releated transaction paid or realized").ToString()); } else { result = Pair.Create(true, (string)null); } }
/// <summary> /// 判断订单是否可以付款 /// 前台使用 /// 允许条件: 订单状态是等待付款,且有可支付的关联交易 /// </summary> public void CanPay(SellerOrder order, ref Pair <bool, string> result) { var orderManager = Application.Ioc.Resolve <SellerOrderManager>(); if (order.State != OrderState.WaitingBuyerPay) { result = Pair.Create(false, new T("Order not payable because it's not waiting buyer pay").ToString()); } else if (!orderManager.GetReleatedTransactions(order.Id).Any(t => t.Check(c => c.IsPayable).First)) { result = Pair.Create(false, new T("Order not payable because no payable releated transactions").ToString()); } else { result = Pair.Create(true, (string)null); } }
public async Task <ValidationResult <SellerOrder> > CreateSellerOrder(SellerOrder sellerOrder) { var validationResult = new ValidationResult <SellerOrder>(); try { await _dataService.CreateAsync(sellerOrder); validationResult.Entity = sellerOrder; validationResult.Succeeded = true; } catch (Exception ex) { validationResult.Succeeded = false; validationResult.Errors = new List <string> { ex.InnerMessage() }; validationResult.Exception = ex; } return(validationResult); }
/// <summary> /// 判断订单是否可以取消 /// 前台使用 /// 允许条件: 订单状态是等待付款,且关联的收款交易的状态是初始状态或等待付款 /// </summary> public void CanSetCancelled(SellerOrder order, ref Pair <bool, string> result) { var orderManage = Application.Ioc.Resolve <SellerOrderManager>(); if (order.State != OrderState.WaitingBuyerPay) { result = Pair.Create(false, new T("Order not cancellable because it's not waiting buyer pay").ToString()); } else if (orderManage.GetReleatedTransactions(order.Id).Any(t => t.State == PaymentTransactionState.SecuredPaid || t.State == PaymentTransactionState.Success)) { result = Pair.Create(false, new T("Order not cancellable because some releated transaction already paid").ToString()); } else { result = Pair.Create(true, (string)null); } }
/// <summary> /// 是否可处理订单所有商品已发货 /// 修改订单状态时使用 /// 允许条件: 订单状态是等待发货,且所有商品都已经发货 /// </summary> public void CanProcessAllGoodsSent(SellerOrder order, ref Pair <bool, string> result) { if (order.State != OrderState.WaitingSellerSendGoods) { result = Pair.Create(false, new T("Order can't be sent because not waiting seller send goods").ToString()); } else { var allSent = order.OrderProducts.All(p => p.Deliveries.Sum(d => d.Count) >= p.Count); if (!allSent) { result = Pair.Create(false, new T("Order can't be sent because not all products sent").ToString()); } else { result = Pair.Create(true, (string)null); } } }
/// <summary> /// 是否可处理订单已付款 /// 修改订单状态时使用 /// 允许条件: 订单状态是等待付款,且关联的所有交易状态是交易成功或担保交易已付款 /// </summary> public void CanProcessOrderPaid(SellerOrder order, ref Pair <bool, string> result) { var orderManager = Application.Ioc.Resolve <SellerOrderManager>(); if (order.State != OrderState.WaitingBuyerPay) { result = Pair.Create(false, new T("Order can't be paid because it's not waiting buyer pay").ToString()); } else if (orderManager.GetReleatedTransactions(order.Id) .Any(t => t.State != PaymentTransactionState.Success && t.State != PaymentTransactionState.SecuredPaid)) { result = Pair.Create(false, new T("Order can't be paid because not all releated transaction paid").ToString()); } else { result = Pair.Create(true, (string)null); } }
/// <summary> /// 转换订单到显示信息 /// </summary> /// <param name="order">订单</param> /// <param name="operatorType">操作人类型</param> /// <returns></returns> public static OrderDisplayInfo ToDisplayInfo(this SellerOrder order, OrderOperatorType operatorType) { var currencyManager = Application.Ioc.Resolve <CurrencyManager>(); var currency = currencyManager.GetCurrency(order.Currency); var displayInfoProviders = Application.Ioc.ResolveMany <IOrderDisplayInfoProvider>(); var info = new OrderDisplayInfo(); info.Serial = order.Serial; info.BuyerId = order.Buyer?.Id; info.Buyer = order.Buyer?.Username; info.SellerId = order.Owner?.Id; info.Seller = order.Owner?.Username; info.State = order.State.ToString(); info.StateDescription = new T(order.State.GetDescription()); info.StateTimes = order.StateTimes.ToDictionary( e => e.Key.ToString(), e => e.Value.ToClientTimeString()); info.OrderParameters = order.OrderParameters; info.TotalCost = order.TotalCost; info.TotalCostString = currency.Format(info.TotalCost); info.TotalCostDescription = order.TotalCostCalcResult.Parts.GetDescription(); info.TotalCostCalcResult = order.TotalCostCalcResult; info.OriginalTotalCost = order.OriginalTotalCostCalcResult.Parts.Sum(); info.OriginalTotalCostString = currency.Format(info.OriginalTotalCost); info.OriginalTotalCostDescription = order.OriginalTotalCostCalcResult.Parts.GetDescription(); info.OriginalTotalCostResult = order.OriginalTotalCostCalcResult; info.Currency = currencyManager.GetCurrency(order.Currency); info.RemarkFlags = order.RemarkFlags; info.CreateTime = order.CreateTime.ToClientTimeString(); foreach (var provider in displayInfoProviders) { provider.AddWarnings(order, info.WarningHtmls, operatorType); provider.AddToolButtons(order, info.ToolButtonHtmls, operatorType); provider.AddSubjects(order, info.SubjectHtmls, operatorType); provider.AddActions(order, info.ActionHtmls, operatorType); } info.OrderProducts = order.OrderProducts.Select(p => p.ToDisplayInfo()).ToList(); return(info); }
/// <summary> /// 添加工具按钮 /// </summary> public void AddToolButtons(SellerOrder order, IList <HtmlString> toolButtons, OrderOperatorType operatorType) { }
//PLACE ORDER--LAST STEP public ActionResult PlaceOrder(FormCollection getCheckoutDetails) { int shpID = 1; if (ds.SellerShippingDetails.Count() > 0) { shpID = ds.SellerShippingDetails.Max(x => x.ShippingID) + 1; } int payID = 1; if (ds.SellerPayments.Count() > 0) { payID = ds.SellerPayments.Max(x => x.PaymentID) + 1; } int orderID = 1; if (ds.SellerOrders.Count() > 0) { orderID = ds.SellerOrders.Max(x => x.OrderID) + 1; } SellerShippingDetail shpDetails = new SellerShippingDetail(); shpDetails.ShippingID = shpID; shpDetails.FirstName = getCheckoutDetails["FirstName"]; shpDetails.LastName = getCheckoutDetails["LastName"]; shpDetails.Email = getCheckoutDetails["Email"]; shpDetails.Mobile = getCheckoutDetails["Mobile"]; shpDetails.Address = getCheckoutDetails["Address"]; shpDetails.Province = getCheckoutDetails["Province"]; shpDetails.City = getCheckoutDetails["City"]; shpDetails.PostCode = getCheckoutDetails["PostCode"]; ds.SellerShippingDetails.Add(shpDetails); ds.SaveChanges(); SellerPayment pay = new SellerPayment(); pay.PaymentID = payID; pay.Type = Convert.ToInt32(getCheckoutDetails["PayMethod"]); ds.SellerPayments.Add(pay); ds.SaveChanges(); SellerOrder o = new SellerOrder(); o.OrderID = orderID; o.CustomerID = SellerShippingData.UserID; o.PaymentID = payID; o.ShippingID = shpID; o.Discount = Convert.ToInt32(getCheckoutDetails["discount"]); o.TotalAmount = Convert.ToInt32(getCheckoutDetails["totalAmount"]); o.isCompleted = true; o.OrderDate = DateTime.Now; ds.SellerOrders.Add(o); ds.SaveChanges(); foreach (var OD in SellerShippingData.items) { OD.OrderID = orderID; OD.SellerOrder = ds.SellerOrders.Find(orderID); OD.ProductSeller = ds.ProductSellers.Find(OD.ProductID); ds.SellerOrderDetails.Add(OD); ds.SaveChanges(); } return(RedirectToAction("Voucher", "ForSellerThankYou")); }
/// <summary> /// 获取评价订单商品的Url /// </summary> /// <param name="order">卖家订单</param> /// <returns></returns> public virtual string GetRatingUrl(SellerOrder order) { return($"/user/orders/rate?serial={order.Serial}"); }
/// <summary> /// 添加警告信息 /// </summary> public void AddWarnings(SellerOrder order, IList <HtmlString> warnings, OrderOperatorType operatorType) { }
/// <summary> /// 获取已发货的订单商品数量索引 /// 返回 { 订单商品Id: 已发数量 } /// </summary> /// <param name="order">订单</param> /// <returns></returns> public virtual IDictionary <Guid, long> GetShippedProductMapping(SellerOrder order) { return(order.OrderProducts.ToDictionary( p => p.Id, p => p.Deliveries.Sum(d => d.Count))); }
/// <summary> /// 判断订单是否包含实体商品 /// </summary> /// <param name="order">订单</param> /// <returns></returns> public static bool ContainsRealProduct(this SellerOrder order) { return(order.OrderProducts.Any(p => p.Product.GetProductType() is IAmRealProduct)); }
/// <summary> /// 添加详细信息 /// </summary> public void AddSubjects(SellerOrder order, IList <HtmlString> subjects, OrderOperatorType operatorType) { }