Пример #1
0
        public async Task <IActionResult> SubmitAfterSaleServiceAsync([FromBody] SubmitAfterSaleServiceRequestDto requestDto)
        {
            var context = new SubmitAfterSaleServiceContext(requestDto);

            //1.检测售后单提交数据正确性
            (bool checkRes, ResponseDto response) = await CheckSubmitAfterSaleServiceAsync(context);

            if (!checkRes)
            {
                return(response);
            }
            //2.生成售后单数据:售后单、售后单明细、协商记录
            CreateAfterServiceData(context);

            //3.若售后订单为服务类订单,则在申请退款时,需先将对应订单明细的商品卡设置为不可用
            await SetGoodsDisabledAsync(context);

            //4.订单在申请退款时,需将对应的商品待评记录设置为不可用
            await SetOrderProductCommentDisabledAsync(context);

            //5.提交数据库数据
            var result = await new AfterSaleServiceBiz().SubmitAfterSaleServiceAsync(context);

            return(result ? Success() : Failed(ErrorCode.DataBaseError, "提交售后单失败"));
        }
Пример #2
0
        /// <summary>
        /// 生成售后服务单数据
        /// </summary>
        /// <param name="context"></param>
        private void CreateAfterServiceData(SubmitAfterSaleServiceContext context)
        {
            var serviceModel = new AfterSaleServiceModel
            {
                ServiceGuid   = Guid.NewGuid().ToString("N"),
                ServiceNo     = new ServiceNoBiz().GetServiceNo().Result.PadLeft(9, '0'),
                MerchantGuid  = context.OrderModel.MerchantGuid,
                OrderGuid     = context.OrderModel.OrderGuid,
                UserGuid      = context.OrderModel.UserGuid,
                Status        = AfterSaleServiceStatusEnum.Applying.ToString(),
                Type          = context.RequestDto.AfterSaleServiceType.ToString(),
                Reason        = context.RequestDto.Reason,
                CreatedBy     = UserID,
                LastUpdatedBy = UserID,
                OrgGuid       = string.Empty
            };
            var serviceDetails = context.OrderDetails.Select(a => new AfterSaleDetailModel
            {
                DetailGuid      = Guid.NewGuid().ToString("N"),
                ServiceGuid     = serviceModel.ServiceGuid,
                OrderDetailGuid = a.DetailGuid,
                ProductGuid     = a.ProductGuid,
                UnitPrice       = (int)(a.ProductPrice * 100), //订单明细商品的单价为元,需要转换为分
                                                               //售后商品数量,可能要小于实际订单明细的商品数量,例如买了3个苹果,可能2个走售后流程,剩余1个是没有问题的苹果,前端传null表示全部走售后流程
                ProductCount = context.RequestDto.Detials.FirstOrDefault(d => d.OrderDetailGuid == a.DetailGuid).ProductCount ?? a.ProductCount,
#warning 若后续版本加入优惠活动,那么此处的退款价格应该是分摊到订单明细之后的折后价
                RefundFee     = (int)(a.ProductPrice * 100) * (context.RequestDto.Detials.FirstOrDefault(d => d.OrderDetailGuid == a.DetailGuid).ProductCount ?? a.ProductCount),
                CreatedBy     = UserID,
                LastUpdatedBy = UserID,
                OrgGuid       = string.Empty
            }).ToList();

            if (context.RequestDto.AfterSaleServiceType != AfterSaleServiceTypeEnum.RefundWhithReturn && context.RequestDto.AfterSaleServiceType != AfterSaleServiceTypeEnum.RefundWhitoutReturn)
            {
                serviceDetails.ForEach(a =>
                {
                    a.RefundFee = 0;
                });
            }
            serviceModel.RefundFee = serviceDetails.Sum(a => a.RefundFee);//服务单的退款金额=明细退款金额之和,若明细无退款,则无退款金额

            var consultationModels = serviceDetails.Select(a => new AfterSaleConsultationModel
            {
                ConsultationGuid = Guid.NewGuid().ToString("N"),
                DetailGuid       = a.DetailGuid,
                Title            = $"用户发起{context.RequestDto.AfterSaleServiceType.GetDescription()}申请",
                //Content = $"{requestDto.AfterSaleServiceType.GetDescription()}原因:{requestDto.Reason}",
                RoleType      = AfterSaleConsultationRoleEnum.Buyer.ToString(),
                CreatedBy     = UserID,
                LastUpdatedBy = UserID,
                OrgGuid       = string.Empty
            }).ToList();

            context.ServiceModel        = serviceModel;
            context.ServiceDetailModels = serviceDetails;
            context.ConsultationModels  = consultationModels;
        }
Пример #3
0
        /// <summary>
        /// 订单在申请退款时,需将对应的商品待评记录设置为不可用
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private async Task SetOrderProductCommentDisabledAsync(SubmitAfterSaleServiceContext context)
        {
            var models = await new OrderProductCommentBiz().GetModelsByOrderDetailGuidsAsync(context.OrderDetails.Select(a => a.DetailGuid).Distinct().ToArray());

            models.ForEach(a =>
            {
                a.Enable          = false;
                a.LastUpdatedBy   = UserID;
                a.LastUpdatedDate = DateTime.Now;
            });
            context.CommentModels = models;
        }
Пример #4
0
        /// <summary>
        /// 若售后订单为服务类订单,则在申请退款时,需先将对应订单明细的商品卡设置为禁用状态
        /// </summary>
        private async Task SetGoodsDisabledAsync(SubmitAfterSaleServiceContext context)
        {
            if (context.OrderModel.OrderCategory != OrderCategoryEnum.Service.ToString())
            {
                return;
            }
            var goodsModels = await new GoodsBiz().GetModelsByOrderDetailIdAsync(context.RequestDto.Detials.Select(a => a.OrderDetailGuid).Distinct());

            goodsModels.ForEach(a =>
            {
                a.Enable          = false;
                a.LastUpdatedBy   = UserID;
                a.LastUpdatedDate = DateTime.Now;
            });
            context.GoodsModels = goodsModels;
        }
 /// <summary>
 /// 提交售后服务单
 /// </summary>
 /// <param name="context"></param>
 /// <returns></returns>
 public async Task <bool> SubmitAfterSaleServiceAsync(SubmitAfterSaleServiceContext context)
 {
     return(await MySqlHelper.TransactionAsync(async (conn, trans) =>
     {
         await conn.InsertAsync <string, AfterSaleServiceModel>(context.ServiceModel);
         context.ServiceDetailModels.InsertBatch(conn);
         context.ConsultationModels.InsertBatch(conn);
         foreach (var item in context.GoodsModels)
         {
             await conn.UpdateAsync(item);
         }
         foreach (var item in context.CommentModels)
         {
             await conn.UpdateAsync(item);
         }
         return true;
     }));
 }
Пример #6
0
        /// <summary>
        /// 检测售后单提交数据正确性
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private async Task <(bool, ResponseDto)> CheckSubmitAfterSaleServiceAsync(SubmitAfterSaleServiceContext context)
        {
            if (context.RequestDto.Detials == null || !context.RequestDto.Detials.Any())
            {
                return(false, Failed(ErrorCode.UserData, "请至少选择一种商品"));
            }
            var orderDetails = await new OrderDetailBiz().GetModelsByPrimaryKeyIdsAsync(context.RequestDto.Detials.Select(a => a.OrderDetailGuid), true);

            context.OrderDetails = orderDetails;
            if (!orderDetails.Any())
            {
                return(false, Failed(ErrorCode.UserData, "未找到订单明细数据"));
            }
            if (orderDetails.Select(a => a.OrderGuid).Distinct().Count() != 1)
            {
                return(false, Failed(ErrorCode.UserData, "当前售后订单明细不是属于同一个订单,数据错误"));
            }
            var orderModel = await new OrderBiz().GetAsync(orderDetails.FirstOrDefault().OrderGuid);

            context.OrderModel = orderModel;
            if (orderModel == null)
            {
                return(false, Failed(ErrorCode.UserData, "未找到指定订单数据"));
            }
            if (orderModel.PayType != PayTypeEnum.Wechat.ToString())
            {
                return(false, Failed(ErrorCode.UserData, "目前只支持线上微信支付的订单进行售后操作,请联系客服"));
            }
            //暂时只支持服务类订单的售后服务操作
            if (orderModel.OrderCategory != OrderCategoryEnum.Service.ToString())
            {
                return(false, Failed(ErrorCode.UserData, "暂时只支持服务类订单的售后服务操作,请联系客服"));
            }
            if (orderModel.OrderStatus != OrderStatusEnum.Completed.ToString())
            {
                var orderStatusEnum = (OrderStatusEnum)Enum.Parse(typeof(OrderStatusEnum), orderModel.OrderStatus);
                return(false, Failed(ErrorCode.UserData, $"订单状态为[{orderStatusEnum.GetDescription()}],不支持售后操作"));
            }
            //检查传入的订单详情是否存在售后记录,避免重复提交
            var afterSaleServiceDetails = await new AftersaleDetailBiz().GetByOrderDetialIdsAsync(context.RequestDto.Detials.Select(a => a.OrderDetailGuid));

            if (afterSaleServiceDetails.Any())
            {
                return(false, Failed(ErrorCode.UserData, "已存在售后记录,不可重复提交售后单"));
            }
            //若为服务类订单
            if (context.OrderModel.OrderCategory == OrderCategoryEnum.Service.ToString())
            {
                if ((DateTime.Now - context.OrderModel.PaymentDate.Value).TotalDays > 15)
                {
                    return(false, Failed(ErrorCode.UserData, $"订单完成超过15天,不支持售后操作,请联系客服"));
                }
                var goodsModels  = await new GoodsBiz().GetModelsByOrderDetailIdAsync(context.OrderDetails.Select(a => a.DetailGuid).Distinct());
                var overdueGoods = goodsModels.Where(g => g.EffectiveEndDate != null && g.EffectiveEndDate.Value.Date < DateTime.Now.Date);
                if (overdueGoods.Any())
                {
                    return(false, Failed(ErrorCode.UserData, $"所选商品[{string.Join(",", overdueGoods.Select(a => a.ProductName))}]中存在已过期的商品卡,不可退款"));
                }

                #region 针对服务类商品,若已满足售后要求,还需要检测是否有商品卡已使用过
                var goodsItemModels = await new GoodsItemBiz().GetByOrderDetailIdsAsync(context.RequestDto.Detials.Select(a => a.OrderDetailGuid));
                var usedGoodsItems  = goodsItemModels.Where(a => a.Used > 0);
                if (usedGoodsItems.Count() > 0)
                {
                    var usedGoodsModelNames = goodsModels.Join(usedGoodsItems, p => p.GoodsGuid, u => u.GoodsGuid, (p, u) => p.ProductName);
                    return(false, Failed(ErrorCode.UserData, $"所选商品[{string.Join(",", usedGoodsModelNames)}]中存在已用过商品卡的情况,不可退款"));
                }
                #endregion
                context.RequestDto.AfterSaleServiceType = AfterSaleServiceTypeEnum.RefundWhitoutReturn;//服务类订单售后类型只能为【退款不退货】类型
            }
            return(true, null);
        }