public async Task <IActionResult> GetMealOrderDetailForTransferAsync(string orderGuid)
        {
            var orderBiz       = new MealOrderBiz();
            var orderDetailBiz = new MealOrderDetailBiz();
            var orderModel     = await orderBiz.GetModelAsync(orderGuid);

            if (orderModel == null)
            {
                return(Failed(ErrorCode.Empty, "无此订单数据"));
            }
            if (orderModel.OrderStatus != MealOrderStatusEnum.Paided.ToString())
            {
                var enumStatus = (MealOrderStatusEnum)Enum.Parse(typeof(MealOrderStatusEnum), orderModel.OrderStatus);
                return(Failed(ErrorCode.UserData, $"当店订单状态为[{enumStatus.GetDescription()}]不支持转让"));
            }
            else if (orderModel.MealEndTime < DateTime.Now)
            {
                return(Failed(ErrorCode.UserData, $"当店订单已过用餐时间,无法转让"));
            }
            var orderDetails = await orderDetailBiz.GetModelsByOrderGuidAsync(orderGuid);

            var response = orderModel.ToDto <GetMealOrderDetailResponseDto>();

            response.Dishees = orderDetails?.Select(a => a.ToDto <GetMealOrderDetailResponseDto.MealOrderDetailDishesDto>()).ToList();
            return(Success(response));
        }
        public async Task <IActionResult> GetTransferedWXAcodeAsync(string orderGuid)
        {
            #region 检测待转让订单是否能被转让
            var orderBiz      = new MealOrderBiz();
            var orderModelOld = await orderBiz.GetModelAsync(orderGuid);

            if (orderModelOld == null)
            {
                return(Failed(ErrorCode.Empty, "无此订单数据"));
            }
            if (orderModelOld.OrderStatus != MealOrderStatusEnum.Paided.ToString())
            {
                var enumStatus = (MealOrderStatusEnum)Enum.Parse(typeof(MealOrderStatusEnum), orderModelOld.OrderStatus);
                return(Failed(ErrorCode.UserData, $"当前订单状态为[{enumStatus.GetDescription()}]不支持转让"));
            }
            else if (orderModelOld.MealEndTime < DateTime.Now)
            {
                return(Failed(ErrorCode.UserData, $"当前订单已过用餐时间,无法转让"));
            }

            #endregion


            var resToken = WeChartApi.GetAccessToken(PlatformSettings.CDMealClientAppId, PlatformSettings.CDMealClientAppSecret).Result;
            if (resToken.Errcode != 0 || resToken == null)
            {
                return(Failed(ErrorCode.SystemException, $"获取token失败:{resToken.Errmsg}"));
            }
            var param = new WXACodeParam
            {
                Path  = $"pages/OrderTransfer/OrderTransfer?orderGuid={orderGuid}",
                Width = 280
            };
            var res = WeChartApi.GetWXACode(param, resToken.AccessToken).Result;
            if (string.IsNullOrWhiteSpace(res))
            {
                return(Failed(ErrorCode.SystemException, $"获取转让码失败"));
            }
            var response = new GetTransferedWXAcodeResponseDto
            {
                TransferedCodeImg = res,
                CategoryName      = orderModelOld.CategoryName,
                MealStartTime     = orderModelOld.MealStartTime,
                MealEndTime       = orderModelOld.MealEndTime
            };
            return(Success(response));
        }
        public async Task <IActionResult> AcceptTransferedMealOrderAsync([FromBody] AcceptTransferedMealOrderRequestDto requestDto)
        {
            var orderGuid      = requestDto.OrderGuid;
            var orderBiz       = new MealOrderBiz();
            var orderDetailBiz = new MealOrderDetailBiz();

            #region 检测待转让订单是否能被转让
            var orderModelOld = await orderBiz.GetModelAsync(orderGuid);

            if (orderModelOld == null)
            {
                return(Failed(ErrorCode.Empty, "无此订单数据"));
            }
            if (orderModelOld.OrderStatus != MealOrderStatusEnum.Paided.ToString())
            {
                var enumStatus = (MealOrderStatusEnum)Enum.Parse(typeof(MealOrderStatusEnum), orderModelOld.OrderStatus);
                return(Failed(ErrorCode.UserData, $"当店订单状态为[{enumStatus.GetDescription()}]不支持转让"));
            }
            else if (orderModelOld.MealEndTime < DateTime.Now)
            {
                return(Failed(ErrorCode.UserData, $"当店订单已过用餐时间,无法转让"));
            }
            else if (orderModelOld.UserGuid == UserID)
            {
                return(Failed(ErrorCode.UserData, $"不能接收来自自己的转让订单"));
            }
            #endregion

            //获取转让订单去向用户的钱包账户
            var accountModels = await new MealAccountBiz().GetModelsByUserIdAsync(UserID, orderModelOld.HospitalGuid);
            if (!accountModels.Any())
            {
                return(Failed(ErrorCode.UserData, "未检测到钱包账户,请先充值"));
            }

            //获取待转让订单的订单明细数据
            var orderDetailsOld = await orderDetailBiz.GetModelsByOrderGuidAsync(orderGuid);

            MealOrderModel orderInsert = new MealOrderModel();                                                //新增订单记录
            MealOrderModel orderUpdate = new MealOrderModel();                                                //更新订单记录
            List <MealOrderDetailModel>   orderDetails   = new List <MealOrderDetailModel>();                 //新增点餐订单明细列表
            List <MealAccountDetailModel> accountDetails = new List <MealAccountDetailModel>();               //新增点餐钱包流水列表
            var tradeModels = new List <MealAccountTradeModel>();                                             //点餐交易流水列表
            List <MealAccountTradeDetailModel> tradeDetailsModels = new List <MealAccountTradeDetailModel>(); //点餐订单交易流水明细列表

            //创建新订单
            var orderModelNew = orderModelOld.Clone() as MealOrderModel;
            orderModelNew.OrderGuid       = Guid.NewGuid().ToString("N");
            orderModelNew.UserGuid        = UserID;
            orderModelNew.CreatedBy       = UserID;
            orderModelNew.CreationDate    = DateTime.Now;
            orderModelNew.LastUpdatedBy   = UserID;
            orderModelNew.LastUpdatedDate = DateTime.Now;
            orderModelNew.TransferredFrom = orderModelOld.OrderGuid;

            //修改旧订单
            orderModelOld.TransferredTo   = orderModelNew.OrderGuid;
            orderModelOld.OrderStatus     = MealOrderStatusEnum.Transferred.ToString();
            orderModelOld.LastUpdatedBy   = UserID;
            orderModelOld.LastUpdatedDate = DateTime.Now;

            orderInsert = orderModelNew;
            orderUpdate = orderModelOld;

            //创建新的订单详情
            for (int i = 0; i < orderDetailsOld.Count; i++)
            {
                var od = orderDetailsOld[i];
                od.OrderDetailGuid = Guid.NewGuid().ToString("N");
                od.OrderGuid       = orderModelNew.OrderGuid;
                od.CreatedBy       = UserID;
                od.CreationDate    = DateTime.Now;
                od.LastUpdatedBy   = UserID;
                od.LastUpdatedDate = DateTime.Now;
            }
            orderDetails.AddRange(orderDetailsOld);

            #region 旧订单退款:创建钱包退款流水、订单退款交易流水

            //退款-订单交易记录
            var refundTradeModels = new MealAccountTradeModel
            {
                AccountTradeGuid        = Guid.NewGuid().ToString("N"),
                OrderGuid               = orderModelOld.OrderGuid,
                AccountTradeType        = (sbyte)MealAccountTradeTypeEnum.Refund,
                AccountTradeFee         = orderModelOld.TotalPrice,
                AccountTradeDescription = string.Empty,
                CreatedBy               = UserID,
                LastUpdatedBy           = UserID,
                OrgGuid = string.Empty
            };
            tradeModels.Add(refundTradeModels);
            //退款-订单交易明细
            var tradeDetal_TransferFrom = await new MealAccountTradeDetailBiz().GetModelsByOrderGuidAsync(orderModelOld.OrderGuid, 0);
            foreach (var td in tradeDetal_TransferFrom)
            {
                var item = td.Clone() as MealAccountTradeDetailModel;
                item.AccountTradeDetailGuid = Guid.NewGuid().ToString("N");
                item.AccountTradeGuid       = refundTradeModels.AccountTradeGuid;
                item.CreatedBy       = UserID;
                item.CreationDate    = DateTime.Now;
                item.LastUpdatedBy   = UserID;
                item.LastUpdatedDate = DateTime.Now;
                tradeDetailsModels.Add(item);
            }
            //退款-钱包账户流水
            var sourceUserAccountModels = await new MealAccountBiz().GetModelsByUserIdAsync(orderModelOld.UserGuid, orderModelOld.HospitalGuid);
            if (!sourceUserAccountModels.Any())
            {
                return(Failed(ErrorCode.UserData, "未检测到钱包账户"));
            }
            accountDetails.AddRange(tradeDetal_TransferFrom.Select(a => new MealAccountDetailModel
            {
                AccountDetailGuid        = Guid.NewGuid().ToString("N"),
                AccountGuid              = a.AccountGuid,
                AccountDetailType        = MealAccountDetailTypeEnum.Refund.ToString(),
                AccountDetailIncomeType  = (sbyte)MealAccountDetailIncomeTypeEnum.Income,
                AccountDetailBeforeFee   = (sourceUserAccountModels.FirstOrDefault(p => p.AccountGuid == a.AccountGuid)?.AccountBalance ?? 0M),
                AccountDetailFee         = a.AccountTradeFee,
                AccountDetailAfterFee    = (sourceUserAccountModels.FirstOrDefault(p => p.AccountGuid == a.AccountGuid)?.AccountBalance ?? 0M) + a.AccountTradeFee,
                AccountDetailDescription = $"订单转让退款:订单号[{orderModelOld.OrderNo}]",
                CreatedBy     = UserID,
                LastUpdatedBy = UserID,
                OrgGuid       = string.Empty
            }).ToList());

            #endregion

            #region 新订单扣款、创建钱包流水、创建订单交易流水
            var accountToal = accountModels.Sum(a => a.AccountBalance);
            var orderTotal  = orderModelNew.TotalPrice;
            if (accountToal < orderTotal)
            {
                return(Failed(ErrorCode.UserData, "余额不足,请先充值"));
            }
            var rechargeAccount = accountModels.FirstOrDefault(a => a.AccountType == MealAccountTypeEnum.Recharge.ToString());
            var grantAccount    = accountModels.FirstOrDefault(a => a.AccountType == MealAccountTypeEnum.Grant.ToString());

            var newOrderTradeModel = new MealAccountTradeModel
            {
                AccountTradeGuid        = Guid.NewGuid().ToString("N"),
                OrderGuid               = orderModelNew.OrderGuid,
                AccountTradeType        = (sbyte)MealAccountTradeTypeEnum.Consumer,
                AccountTradeFee         = orderModelNew.TotalPrice,
                AccountTradeDescription = string.Empty,
                CreatedBy               = UserID,
                LastUpdatedBy           = UserID,
                OrgGuid = string.Empty
            };
            tradeModels.Add(newOrderTradeModel);

            var paidMoney = orderTotal;
            //创建钱包流水记录
            if (grantAccount != null && grantAccount.AccountBalance > 0)
            {
                var grantPaid = grantAccount.AccountBalance > paidMoney ? paidMoney : grantAccount.AccountBalance;
                accountDetails.Add(new MealAccountDetailModel
                {
                    AccountDetailGuid        = Guid.NewGuid().ToString("N"),
                    AccountGuid              = grantAccount.AccountGuid,
                    AccountDetailType        = MealAccountDetailTypeEnum.Consume.ToString(),
                    AccountDetailIncomeType  = (sbyte)MealAccountDetailIncomeTypeEnum.Expenditure,
                    AccountDetailBeforeFee   = grantAccount.AccountBalance,
                    AccountDetailFee         = grantPaid,
                    AccountDetailAfterFee    = grantAccount.AccountBalance - grantPaid,
                    AccountDetailDescription = "订单消费",
                    CreatedBy     = UserID,
                    LastUpdatedBy = UserID,
                    OrgGuid       = string.Empty
                });
                var orderPaid = grantPaid > orderModelNew.TotalPrice ? orderModelNew.TotalPrice : grantPaid;
                tradeDetailsModels.Add(new MealAccountTradeDetailModel
                {
                    AccountTradeDetailGuid = Guid.NewGuid().ToString("N"),
                    AccountGuid            = grantAccount.AccountGuid,
                    AccountTradeGuid       = newOrderTradeModel.AccountTradeGuid,
                    AccountTradeFee        = orderPaid,
                    CreatedBy     = UserID,
                    LastUpdatedBy = UserID,
                    OrgGuid       = string.Empty
                });
                paidMoney -= grantPaid;
            }
            if (paidMoney > 0 && rechargeAccount != null && rechargeAccount.AccountBalance > 0)
            {
                accountDetails.Add(new MealAccountDetailModel
                {
                    AccountDetailGuid        = Guid.NewGuid().ToString("N"),
                    AccountGuid              = rechargeAccount.AccountGuid,
                    AccountDetailType        = MealAccountDetailTypeEnum.Consume.ToString(),
                    AccountDetailIncomeType  = (sbyte)MealAccountDetailIncomeTypeEnum.Expenditure,
                    AccountDetailBeforeFee   = rechargeAccount.AccountBalance,
                    AccountDetailFee         = paidMoney,
                    AccountDetailAfterFee    = rechargeAccount.AccountBalance - paidMoney,
                    AccountDetailDescription = "订单消费",
                    CreatedBy     = UserID,
                    LastUpdatedBy = UserID,
                    OrgGuid       = string.Empty
                });
                tradeDetailsModels.Add(new MealAccountTradeDetailModel
                {
                    AccountTradeDetailGuid = Guid.NewGuid().ToString("N"),
                    AccountGuid            = rechargeAccount.AccountGuid,
                    AccountTradeGuid       = newOrderTradeModel.AccountTradeGuid,
                    AccountTradeFee        = paidMoney,
                    CreatedBy     = UserID,
                    LastUpdatedBy = UserID,
                    OrgGuid       = string.Empty
                });
            }
            #endregion

            var result = await orderBiz.AcceptTransferedMealOrderAsync(orderInsert, orderUpdate, orderDetails, accountDetails, tradeModels, tradeDetailsModels);

            return(result ? Success() : Failed(ErrorCode.DataBaseError, "订单转让操作失败,请重试"));
        }
        public async Task <IActionResult> CancelMealOrderAsync(string orderGuid)
        {
            var orderBiz   = new MealOrderBiz();
            var orderModel = await orderBiz.GetModelAsync(orderGuid);

            if (orderModel == null)
            {
                return(Failed(ErrorCode.Empty, "无此订单数据"));
            }
            var mealCategoryModel = await new MealCategoryBiz().GetModelAsync(orderModel.CategoryGuid);

            if (mealCategoryModel == null)
            {
                return(Failed(ErrorCode.Empty, "餐别数据未找到"));
            }
            if (orderModel.OrderStatus != MealOrderStatusEnum.Paided.ToString())
            {
                return(Failed(ErrorCode.Empty, "此订单已完成取餐或已转让,无法取消"));
            }
            var canCancel = orderModel.OrderStatus == MealOrderStatusEnum.Paided.ToString() && Convert.ToDateTime($"{orderModel.MealDate.AddDays(mealCategoryModel.CategoryAdvanceDay * (-1)).ToString("yyyy-MM-dd")} {mealCategoryModel.CategoryScheduleTime}") > DateTime.Now;

            if (!canCancel)
            {
                return(Failed(ErrorCode.UserData, "此订单已过点餐截止时间,无法取消"));
            }
            //修改订单状态为已取消
            orderModel.OrderStatus = MealOrderStatusEnum.Canceled.ToString();
            //获取应退款的数据
            var tradeDetals = await new MealAccountTradeDetailBiz().GetModelsByOrderGuidAsync(orderModel.OrderGuid, 0);

            //退款-订单交易记录
            var refundTradeModels = new MealAccountTradeModel
            {
                AccountTradeGuid        = Guid.NewGuid().ToString("N"),
                OrderGuid               = orderModel.OrderGuid,
                AccountTradeType        = (sbyte)MealAccountTradeTypeEnum.Refund,
                AccountTradeFee         = orderModel.TotalPrice,
                AccountTradeDescription = string.Empty,
                CreatedBy               = UserID,
                LastUpdatedBy           = UserID,
                OrgGuid = string.Empty
            };
            //退款-订单交易明细
            var refundTradeDetailModels = new List <MealAccountTradeDetailModel>();

            foreach (var td in tradeDetals)
            {
                var item = td.Clone() as MealAccountTradeDetailModel;
                item.AccountTradeDetailGuid = Guid.NewGuid().ToString("N");
                item.AccountTradeGuid       = refundTradeModels.AccountTradeGuid;
                item.CreatedBy       = UserID;
                item.CreationDate    = DateTime.Now;
                item.LastUpdatedBy   = UserID;
                item.LastUpdatedDate = DateTime.Now;
                refundTradeDetailModels.Add(item);
            }
            //退款-钱包账户流水
            var accountModels = await new MealAccountBiz().GetModelsByUserIdAsync(orderModel.UserGuid, orderModel.HospitalGuid);

            if (!accountModels.Any())
            {
                return(Failed(ErrorCode.UserData, "未检测到钱包账户,请先充值"));
            }
            var refundAccountDetailModels = tradeDetals.Select(a => new MealAccountDetailModel
            {
                AccountDetailGuid        = Guid.NewGuid().ToString("N"),
                AccountGuid              = a.AccountGuid,
                AccountDetailType        = MealAccountDetailTypeEnum.Refund.ToString(),
                AccountDetailIncomeType  = (sbyte)MealAccountDetailIncomeTypeEnum.Income,
                AccountDetailBeforeFee   = accountModels.FirstOrDefault(p => p.AccountGuid == a.AccountGuid)?.AccountBalance ?? 0M,
                AccountDetailFee         = a.AccountTradeFee,
                AccountDetailAfterFee    = (accountModels.FirstOrDefault(p => p.AccountGuid == a.AccountGuid)?.AccountBalance ?? 0M) + a.AccountTradeFee,
                AccountDetailDescription = $"订单退款:订单号[{orderModel.OrderNo}]",
                CreatedBy     = UserID,
                LastUpdatedBy = UserID,
                OrgGuid       = string.Empty
            }).ToList();

            var result = await orderBiz.CancelMealOrderAsync(orderModel, refundTradeModels, tradeDetals, refundAccountDetailModels);

            return(result ? Success() : Failed(ErrorCode.DataBaseError));
        }