public Transaction CheckoutDeptReminder(Guid userId, Guid deptReminderId)
        {
            Transaction res = null;

            using (var sessionTask = _MongoDBClient.StartSessionAsync())
            {
                var session = sessionTask.Result;
                session.StartTransaction();
                try
                {
                    var userDetail = _UserCollection.GetById(userId);
                    if (userDetail != null)
                    {
                        // Get chi tiết nhắc nợ
                        var dept = _DeptReminderCollection.GetById(deptReminderId);
                        if (dept != null && dept.RecipientId == userId)
                        {
                            // Create OTP
                            string otp = null;
                            while (true)
                            {
                                otp = _Context.MakeOTP(6);
                                if (!_TransactionCollection.GetMany(new TransactionFilter()
                                {
                                    Otp = otp, Type = 1
                                }).Any())
                                {
                                    break;
                                }
                            }

                            // expire
                            var transaction = new Transaction();
                            transaction.Id          = Guid.Empty;
                            transaction.ReferenceId = dept.Id;
                            transaction.Otp         = otp;
                            transaction.CreateTime  = DateTime.Now;
                            transaction.ExpireTime  = transaction.CreateTime.AddMinutes(_Setting.TransferExpiration);
                            transaction.Type        = 1;

                            _TransactionCollection.Create(transaction);

                            if (transaction.Id != Guid.Empty)
                            {
                                // Send mail
                                var sb = new StringBuilder();
                                sb.AppendFormat($"Dear {userDetail.Name},");
                                sb.AppendFormat("<br /><br /><b>Bạn đang yêu cầu thanh toán nhắc nợ, mã xác thực của bạn là:</b>");
                                sb.AppendFormat($"<br /><br /><b>{transaction.Otp}</b>");
                                sb.AppendFormat($"<br /><br /><b>Mã xác thực này sẽ hết hạn lúc {transaction.ExpireTime.ToLongTimeString()}.</b>");
                                sb.AppendFormat($"<br /><br /><b>Nếu yêu cầu không phải của bạn, vui lòng bỏ qua mail này.</b>");

                                if (_Context.SendMail("Xác thực thanh toán nhắc nợ", sb.ToString(), userDetail.Email, userDetail.Name))
                                {
                                    res = transaction;
                                }
                            }
                            else
                            {
                                _Setting.Message.SetMessage("Không thể thanh toán nhắc nợ!");
                            }
                        }
                        else
                        {
                            _Setting.Message.SetMessage("Không tìm thấy thông tin nhắc nợ!");
                        }
                    }
                    else
                    {
                        _Setting.Message.SetMessage("Không tìm thấy thông tin khách hàng!");
                    }

                    if (res != null)
                    {
                        session.CommitTransactionAsync();
                    }
                    else
                    {
                        session.AbortTransactionAsync();
                    }
                }
                catch
                {
                    session.AbortTransactionAsync();
                }
            }

            return(res);
        }
        public bool ConfirmForgetting(Guid id, string email, string otp)
        {
            var res = false;

            var details = _UserCollection.Get(new UserFilter()
            {
                Email = email
            });

            if (details != null && details.Any())
            {
                var detail = details.FirstOrDefault();
                // Get chi tiết giao dịch
                var transactions = _TransactionCollection.GetMany(new TransactionFilter()
                {
                    Id = id, ReferenceId = detail.Id, Type = 2
                });
                if (transactions.Any())
                {
                    var transaction = transactions.FirstOrDefault();
                    // Check Otp
                    if (transaction.Otp == otp)
                    {
                        // Check hết hạn
                        var now = DateTime.Now;
                        if (now <= transaction.ExpireTime && now >= transaction.CreateTime)
                        {
                            // Update mật khẩu
                            using (var sessionTask = _MongoDBClient.StartSessionAsync())
                            {
                                var session = sessionTask.Result;
                                session.StartTransaction();
                                try
                                {
                                    // Create mật khẩu mới
                                    string pass = _Context.MakeOTP(8);

                                    if (_UserCollection.ChangePassword(new UserFilter()
                                    {
                                        Id = detail.Id
                                    }, Encrypting.Bcrypt(pass)) > 0)
                                    {
                                        // Update giao dịch
                                        transaction.ConfirmTime = DateTime.Now;

                                        if (_TransactionCollection.Replace(transaction) > 0)
                                        {
                                            // Send mail
                                            var sb = new StringBuilder();
                                            sb.AppendFormat($"Dear {detail.Name},");
                                            sb.AppendFormat("<br /><br /><b>Yêu cầu quên mật khẩu của bạn đã thực hiện thành công, mật khẩu mới của bạn là:</b>");
                                            sb.AppendFormat($"<br /><br /><b>{pass}</b>");
                                            sb.AppendFormat($"<br /><br /><b>Vui lòng đăng nhập vào hệ thống để kiểm tra.</b>");
                                            sb.AppendFormat($"<br /><br /><b>Nếu yêu cầu không phải của bạn, vui lòng bỏ qua mail này.</b>");

                                            if (_Context.SendMail("Yêu cầu quên mật khẩu", sb.ToString(), detail.Email, detail.Name))
                                            {
                                                res = true;
                                            }
                                            else
                                            {
                                                _Setting.Message.SetMessage("Gửi mail thất bại!");
                                            }
                                        }
                                        else
                                        {
                                            _Setting.Message.SetMessage("Không thể cập nhật thông tin giao dịch!");
                                        }
                                    }
                                    else
                                    {
                                        _Setting.Message.SetMessage("Không thể cập nhật thông tin mật khẩu!");
                                    }

                                    if (res)
                                    {
                                        session.CommitTransactionAsync();
                                    }
                                    else
                                    {
                                        session.AbortTransactionAsync();
                                    }
                                }
                                catch (Exception ex)
                                {
                                    session.AbortTransactionAsync();
                                    throw ex;
                                    throw;
                                }
                            }
                        }
                        else
                        {
                            _Setting.Message.SetMessage("Phiên giao dịch đã hết hạn!");
                        }
                    }
                    else
                    {
                        _Setting.Message.SetMessage("Mã OTP không đúng!");
                    }
                }
                else
                {
                    _Setting.Message.SetMessage("Không tìm thấy thông tin giao dịch!");
                }
            }
            else
            {
                _Setting.Message.SetMessage("Không tìm thấy thông tin người dùng!");
            }

            return(res);
        }
        public Transaction Transfer(Guid userId, Transfer transfer)
        {
            Transaction res = null;

            var userDetail = _UserCollection.GetById(userId);

            transfer.SourceAccountNumber = userDetail.AccountNumber;
            transfer.SourceLinkingBankId = Guid.Empty;

            if (userDetail != null)
            {
                User recepient = null;

                if (transfer.DestinationLinkingBankId == Guid.Empty)
                {
                    recepient = _UserCollection.GetByAccountNumber(transfer.DestinationAccountNumber);
                }
                else
                {
                    // Get recepient info from linking bank
                    // TODO
                    // Khuê
                    IExternalBanking externalBanking = null;
                    if (transfer.DestinationLinkingBankId == Guid.Parse("8df09f0a-fd6d-42b9-804c-575183dadaf3"))
                    {
                        externalBanking = new ExternalBanking_BKTBank(_Encrypt, _Setting);
                        externalBanking.SetPartnerCode();
                    }

                    // test only
                    transfer.DestinationAccountNumber = "0000000034";
                    var result = externalBanking.GetInfoUser(transfer.DestinationAccountNumber);
                    if (result != null)
                    {
                        recepient = new User();
                    }
                }

                if (recepient != null)
                {
                    string otp = null;
                    using (var sessionTask = _MongoDBClient.StartSessionAsync())
                    {
                        var session = sessionTask.Result;
                        session.StartTransaction();
                        try
                        {
                            // Create OTP
                            while (true)
                            {
                                otp = _Context.MakeOTP(6);
                                if (!_TransactionCollection.GetMany(new TransactionFilter()
                                {
                                    Otp = otp, Type = 0
                                }).Any())
                                {
                                    break;
                                }
                            }

                            _TransferCollection.Create(transfer);

                            if (!transfer.Id.Equals(Guid.Empty))
                            {
                                // Lưu thông tin giao dịch
                                var transaction = new Transaction();
                                transaction.Id          = Guid.Empty;
                                transaction.ReferenceId = transfer.Id;
                                transaction.Otp         = otp;
                                transaction.CreateTime  = DateTime.Now;
                                transaction.ExpireTime  = transaction.CreateTime.AddMinutes(_Setting.TransferExpiration);
                                transaction.Type        = 0;

                                _TransactionCollection.Create(transaction);

                                if (transaction.Id != Guid.Empty)
                                {
                                    // Send mail
                                    var sb = new StringBuilder();
                                    sb.AppendFormat($"Dear {userDetail.Name},");
                                    sb.AppendFormat("<br /><br /><b>Bạn đang yêu cầu chuyển tiền từ hệ thống của chúng tôi, mã xác thực của bạn là:</b>");
                                    sb.AppendFormat($"<br /><br /><b>{transaction.Otp}</b>");
                                    sb.AppendFormat($"<br /><br /><b>Mã xác thực này sẽ hết hạn lúc {transaction.ExpireTime.ToLongTimeString()}.</b>");
                                    sb.AppendFormat($"<br /><br /><b>Nếu yêu cầu không phải của bạn, vui lòng bỏ qua mail này.</b>");

                                    if (_Context.SendMail("Xác thực yêu cầu chuyển tiền", sb.ToString(), userDetail.Email, userDetail.Name))
                                    {
                                        res = transaction;
                                    }
                                }
                            }
                            session.CommitTransactionAsync();
                        }
                        catch (Exception)
                        {
                            session.AbortTransactionAsync();
                        }
                    }
                }
                else
                {
                    _Setting.Message.SetMessage("Không tìm thấy tài khoản người nhận!");
                }
            }
            else
            {
                _Setting.Message.SetMessage("Không tìm thấy tài khoản người gửi!");
            }

            return(res);
        }
        public IEnumerable <CrossChecking> CrossCheckingIn(DateTime?from, DateTime?to, Guid?bankId)
        {
            var res = new List <CrossChecking>();

            var transfers = _TransferCollection.GetMany(new TransferFilter()
            {
                IsConfirmed = true
            });

            transfers = transfers.Where(x => x.DestinationLinkingBankId == Guid.Empty);
            if (bankId.HasValue)
            {
                transfers = transfers.Where(x => x.SourceLinkingBankId == bankId.Value);
            }
            foreach (var transfer in transfers)
            {
                var bank = _LinkingBankCollection.Get(new LinkingBankFilter()
                {
                    Code = _Setting.BankCode
                }).FirstOrDefault();
                // Get ngân hàng liên kết
                var linkBank = _LinkingBankCollection.GetById(transfer.SourceLinkingBankId);
                if (linkBank != null)
                {
                    // Get thông tin giao dịch
                    var transactions = _TransactionCollection.GetMany(new TransactionFilter()
                    {
                        ReferenceId = transfer.Id, Type = 0
                    });
                    if (from.HasValue)
                    {
                        transactions = transactions.Where(x => x.ConfirmTime.Value.Date >= from.Value.Date);
                    }
                    if (to.HasValue)
                    {
                        transactions = transactions.Where(x => x.ConfirmTime.Value.Date <= to.Value.Date);
                    }

                    if (transactions.Any())
                    {
                        var transaction = transactions.FirstOrDefault();

                        // Get thông tin tài khoản nguồn
                        // TODO
                        var sourceAccount = new ExternalAccount();
                        IExternalBanking externalBanking = null;
                        if (transfer.SourceLinkingBankId == Guid.Parse("8df09f0a-fd6d-42b9-804c-575183dadaf3"))
                        {
                            externalBanking = new ExternalBanking_BKTBank(_Encrypt, _Setting);
                            externalBanking.SetPartnerCode();
                        }
                        var source = externalBanking.GetInfoUser(transfer.SourceAccountNumber);
                        if (source != null)
                        {
                            sourceAccount.Name          = source.full_name;
                            sourceAccount.AccountNumber = source.account_number;
                        }
                        else
                        {
                            sourceAccount = null;
                        }
                        if (sourceAccount != null)
                        {
                            // Get thông tin tài khoản đích
                            var destAccount = _UserCollection.GetByAccountNumber(transfer.DestinationAccountNumber);
                            if (destAccount != null)
                            {
                                var history = new CrossChecking();
                                history.SourceAccountName        = sourceAccount.Name;
                                history.SourceAccountNumber      = sourceAccount.AccountNumber;
                                history.SourceBankName           = linkBank.Name;
                                history.DestinationAccountName   = destAccount.Name;
                                history.DestinationAccountNumber = destAccount.AccountNumber;
                                history.DestinationBankName      = bank.Name;
                                history.Description = transfer.Description;
                                history.Money       = transfer.Money;
                                if (!transfer.IsSenderPay)
                                {
                                    history.Money -= transfer.Fee;
                                }
                                history.ConfirmTime = transaction.ConfirmTime.Value;

                                res.Add(history);
                            }
                        }
                    }
                }
            }

            return(res);
        }