/// <summary>
        /// <see cref="Microsoft.Samples.NLayerApp.Domain.MainBoundedContext.BankingModule.Services.IBankTransferService"/>
        /// </summary>
        /// <param name="amount"> <see cref="Microsoft.Samples.NLayerApp.Domain.MainBoundedContext.BankingModule.Services.IBankTransferService"/></param>
        /// <param name="originAccount"> <see cref="Microsoft.Samples.NLayerApp.Domain.MainBoundedContext.BankingModule.Services.IBankTransferService"/></param>
        /// <param name="destinationAccount"> <see cref="Microsoft.Samples.NLayerApp.Domain.MainBoundedContext.BankingModule.Services.IBankTransferService"/></param>
        public void PerformTransfer(decimal amount, BankAccount originAccount, BankAccount destinationAccount)
        {
            if (originAccount != null && destinationAccount != null)
            {
                if (originAccount.BankAccountNumber == destinationAccount.BankAccountNumber) // if transfer in same bank account
                    throw new InvalidOperationException(Messages.exception_CannotTransferMoneyWhenFromIsTheSameAsTo);

                // Check if customer has required credit and if the BankAccount is not locked
                if (originAccount.CanBeWithdrawed(amount))
                {
                    //Domain Logic
                    //Process: Perform transfer operations to in-memory Domain-Model objects        
                    // 1.- Charge money to origin acc
                    // 2.- Credit money to destination acc

                    //Charge money
                    originAccount.WithdrawMoney(amount, string.Format(Messages.messages_TransactionFromMessage, destinationAccount.Id));

                    //Credit money
                    destinationAccount.DepositMoney(amount, string.Format(Messages.messages_TransactionToMessage, originAccount.Id));
                }
                else
                    throw new InvalidOperationException(Messages.exception_BankAccountCannotWithdraw);
            }
        }
        public void AdaptBankAccountToBankAccountDTO()
        {
            //Arrange
            var customer = CustomerFactory.CreateCustomer("jhon", "el rojo", Guid.NewGuid(), new Address("", "", "", ""));
            customer.Id = IdentityGenerator.NewSequentialGuid();

            BankAccount account = new BankAccount();
            account.Id = IdentityGenerator.NewSequentialGuid();
            account.BankAccountNumber = new BankAccountNumber("4444", "5555", "3333333333", "02");
            account.SetCustomer(customer);
            account.DepositMoney(1000, "reason");
            account.Lock();

            //Act
            ITypeAdapter adapter = PrepareTypeAdapter();
            var bankAccountDTO = adapter.Adapt<BankAccount, BankAccountDTO>(account);

            //Assert
            Assert.AreEqual(account.Id, bankAccountDTO.Id);
            Assert.AreEqual(account.Iban, bankAccountDTO.BankAccountNumber);
            Assert.AreEqual(account.Balance, bankAccountDTO.Balance);
            Assert.AreEqual(account.Customer.FirstName, bankAccountDTO.CustomerFirstName);
            Assert.AreEqual(account.Customer.LastName, bankAccountDTO.CustomerLastName);
            Assert.AreEqual(account.Locked, bankAccountDTO.Locked);
        }
        public void BankAccountCannotSetTransientCustomer()
        {
            //Arrange
            var customer = CustomerFactory.CreateCustomer("Unai", "Zorrilla Castro", IdentityGenerator.NewSequentialGuid(),new Address("city","zipcode","AddressLine1","AddressLine2"));

            var bankAccount = new BankAccount();

            //Act
            bankAccount.SetCustomer(customer);
        }
      public void BankAccountCannotSetATransientCustomer()
      {
         //Arrange
         var customer = new Customer()
         {
            FirstName = "Unai",
            LastName = "Zorrilla",
         };

         var bankAccount = new BankAccount();

         //Act
         bankAccount.SetCustomerOwnerOfThisBankAccount(customer);
      }
        /// <summary>
        /// Create a new instance of bankaccount
        /// </summary>
        /// <param name="customerId">The customer identifier</param>
        /// <param name="bankAccountNumber">The bank account number</param>
        /// <returns>A valid bank account</returns>
        public static BankAccount CreateBankAccount(Guid customerId, BankAccountNumber bankAccountNumber)
        {
            var bankAccount = new BankAccount();

            //set the bank account number
            bankAccount.BankAccountNumber = bankAccountNumber;

            //set default bank account as unlocked
            bankAccount.UnLock();

            //set the customer identifier
            bankAccount.CustomerId = customerId;

            return bankAccount;
        }
        /// <summary>
        /// Create a new instance of bankaccount
        /// </summary>
        /// <param name="customer">The customer associated with this bank account</param>
        /// <param name="bankAccountNumber">The bank account number</param>
        /// <returns>A valid bank account</returns>
        public static BankAccount CreateBankAccount(Customer customer, BankAccountNumber bankAccountNumber)
        {
            var bankAccount = new BankAccount();

            //set the bank account number
            bankAccount.BankAccountNumber = bankAccountNumber;

            //set default bank account as unlocked
            bankAccount.UnLock();

            //set the customer for this bank account
            bankAccount.SetCustomer(customer);

            return bankAccount;
        }
        public void BankAccountSetCustomerFixCustomerId()
        {
            //Arrange
            Country country = new Country("Spain", "es-ES");
            country.GenerateNewIdentity();

            var customer = CustomerFactory.CreateCustomer("Unai", "Zorrilla Castro", "+3422", "company", country, new Address("city", "zipcode", "AddressLine1", "AddressLine2"));
            
            //Act
            BankAccount bankAccount = new BankAccount();
            bankAccount.SetCustomerOwnerOfThisBankAccount(customer);

            //Assert
            Assert.AreEqual(customer.Id, bankAccount.CustomerId);
        }
        /// <summary>
        /// Create a new instance of bankaccount
        /// </summary>
        /// <param name="customer">The customer associated with this bank account</param>
        /// <param name="bankAccountNumber">The bank account number</param>
        /// <returns>A valid bank account</returns>
        public static BankAccount CreateBankAccount(Customer customer, BankAccountNumber bankAccountNumber)
        {
            var bankAccount = new BankAccount();

            //set the identity
            bankAccount.GenerateNewIdentity();

            //set the bank account number
            bankAccount.BankAccountNumber = bankAccountNumber;

            //set default bank account as unlocked
            bankAccount.UnLock();

            //set the customer for this bank account
            bankAccount.SetCustomerOwnerOfThisBankAccount(customer);

            return bankAccount;
        }
      public void AdaptEnumerableBankAccountToListBankAccountListDto()
      {
         //Arrange

         var country = new Country("spain", "es-ES");
         country.GenerateNewIdentity();

         var customer = CustomerFactory.CreateCustomer(
            "jhon",
            "el rojo",
            "+341232",
            "company",
            country,
            new Address("", "", "", ""));
         customer.GenerateNewIdentity();

         var account = new BankAccount();
         account.GenerateNewIdentity();
         account.BankAccountNumber = new BankAccountNumber("4444", "5555", "3333333333", "02");
         account.SetCustomerOwnerOfThisBankAccount(customer);
         account.DepositMoney(1000, "reason");
         var accounts = new List<BankAccount>()
         {
            account
         };

         //Act
         var adapter = TypeAdapterFactory.CreateAdapter();
         var bankAccountsDto = adapter.Adapt<IEnumerable<BankAccount>, List<BankAccountDto>>(accounts);

         //Assert
         Assert.IsNotNull(bankAccountsDto);
         Assert.IsTrue(bankAccountsDto.Count == 1);

         Assert.AreEqual(account.Id, bankAccountsDto[0].Id);
         Assert.AreEqual(account.Iban, bankAccountsDto[0].BankAccountNumber);
         Assert.AreEqual(account.Balance, bankAccountsDto[0].Balance);
         Assert.AreEqual(account.Customer.FirstName, bankAccountsDto[0].CustomerFirstName);
         Assert.AreEqual(account.Customer.LastName, bankAccountsDto[0].CustomerLastName);
      }
      public void BankAccountWithEmptyCheckDigistsProduceValidationError()
      {
         //Arrange
         var bankAccount = new BankAccount();
         bankAccount.BankAccountNumber = new BankAccountNumber("1111", "2222", "3333333333", string.Empty);

         //act
         var validationContext = new ValidationContext(bankAccount, null, null);
         var validationResults = bankAccount.Validate(validationContext);

         //assert
         Assert.IsNotNull(validationResults);
         Assert.IsTrue(validationResults.Any());
         Assert.IsTrue(validationResults.First().MemberNames.Contains("CheckDigits"));
      }
      public void BankAccountWithNullAccountNumberProduceValidationError()
      {
         //Arrange
         var bankAccount = new BankAccount();
         bankAccount.BankAccountNumber = new BankAccountNumber("1111", "2222", null, "01");

         //act
         var validationContext = new ValidationContext(bankAccount, null, null);
         var validationResults = bankAccount.Validate(validationContext);

         //assert
         Assert.IsNotNull(validationResults);
         Assert.IsTrue(validationResults.Any());
         Assert.IsTrue(validationResults.First().MemberNames.Contains("AccountNumber"));
      }
        public void BankAccountSetCustomerFixCustomerId()
        {
            //Arrange
            Guid countryId = IdentityGenerator.NewSequentialGuid();
            Customer customer = CustomerFactory.CreateCustomer("Unai", "Zorrilla Castro", countryId, new Address("city", "zipcode", "AddressLine1", "AddressLine2"));
            customer.Id = IdentityGenerator.NewSequentialGuid();
            //Act
            BankAccount bankAccount = new BankAccount();
            bankAccount.SetCustomer(customer);

            //Assert
            Assert.AreEqual(customer.Id, bankAccount.CustomerId);
        }
      public void FindBankAccountActivitiesReturnAllItems()
      {
         //Arrange
         var bankAccountRepository = new StubIBankAccountRepository();
         bankAccountRepository.GetGuid = (guid) =>
         {
            var bActivity1 = new BankAccountActivity()
            {
               Date = DateTime.Now,
               Amount = 1000
            };
            bActivity1.GenerateNewIdentity();

            var bActivity2 = new BankAccountActivity()
            {
               Date = DateTime.Now,
               Amount = 1000
            };
            bActivity2.GenerateNewIdentity();

            var bankAccount = new BankAccount()
            {
               BankAccountActivity = new HashSet<BankAccountActivity>()
               {
                  bActivity1,
                  bActivity2
               }
            };
            bankAccount.GenerateNewIdentity();

            return bankAccount;
         };

         var customerRepository = new StubICustomerRepository();
         IBankTransferService transferService = new BankTransferService();

         IBankAppService bankingService = new BankAppService(bankAccountRepository, customerRepository, transferService);

         //Act
         var result = bankingService.FindBankAccountActivities(Guid.NewGuid());

         //Assert
         Assert.IsNotNull(result);
         Assert.IsTrue(result.Count == 2);
      }
        void SaveBankAccount(BankAccount bankAccount)
        {
            //validate bank account
            var validator = EntityValidatorFactory.CreateValidator();

            if (validator.IsValid<BankAccount>(bankAccount)) // save entity
            {
                _bankAccountRepository.Add(bankAccount);
                _bankAccountRepository.UnitOfWork.Commit();
            }
            else //throw validation errors
                throw new ApplicationValidationErrorsException(validator.GetInvalidMessages(bankAccount));
        }
        public void BankAccountWithEmptyOfficeNumberProduceValidationError()
        {
            //Arrange
            BankAccount bankAccount = new BankAccount();
            bankAccount.BankAccountNumber = new BankAccountNumber(string.Empty, "2222", "3333333333", "01");
            //act
            var validationContext = new ValidationContext(bankAccount, null, null);
            var validationResults = bankAccount.Validate(validationContext);

            //assert
            Assert.IsNotNull(validationResults);
            Assert.IsTrue(validationResults.Any());
            Assert.IsTrue(validationResults.First().MemberNames.Contains("OfficeNumber"));
        }
      public void AdaptBankAccountToBankAccountDto()
      {
         //Arrange
         var country = new Country("Spain", "es-ES");
         country.GenerateNewIdentity();

         var customer = CustomerFactory.CreateCustomer(
            "jhon",
            "el rojo",
            "+3441",
            "company",
            country,
            new Address("", "", "", ""));
         customer.GenerateNewIdentity();

         var account = new BankAccount();
         account.GenerateNewIdentity();
         account.BankAccountNumber = new BankAccountNumber("4444", "5555", "3333333333", "02");
         account.SetCustomerOwnerOfThisBankAccount(customer);
         account.DepositMoney(1000, "reason");
         account.Lock();

         //Act
         var adapter = TypeAdapterFactory.CreateAdapter();
         var bankAccountDto = adapter.Adapt<BankAccount, BankAccountDto>(account);

         //Assert
         Assert.AreEqual(account.Id, bankAccountDto.Id);
         Assert.AreEqual(account.Iban, bankAccountDto.BankAccountNumber);
         Assert.AreEqual(account.Balance, bankAccountDto.Balance);
         Assert.AreEqual(account.Customer.FirstName, bankAccountDto.CustomerFirstName);
         Assert.AreEqual(account.Customer.LastName, bankAccountDto.CustomerLastName);
         Assert.AreEqual(account.Locked, bankAccountDto.Locked);
      }
      public void FindBankAccountsReturnAllItems()
      {
         var bankAccountRepository = new StubIBankAccountRepository();
         bankAccountRepository.GetAll = () =>
         {
            var customer = new Customer();
            customer.GenerateNewIdentity();

            var bankAccount = new BankAccount()
            {
               BankAccountNumber = new BankAccountNumber("4444", "5555", "3333333333", "02"),
            };
            bankAccount.SetCustomerOwnerOfThisBankAccount(customer);
            bankAccount.GenerateNewIdentity();

            var accounts = new List<BankAccount>()
            {
               bankAccount
            };

            return accounts;

         };

         var customerRepository = new StubICustomerRepository();
         IBankTransferService transferService = new BankTransferService();

         IBankAppService bankingService = new BankAppService(bankAccountRepository, customerRepository, transferService);

         //Act
         var result = bankingService.FindBankAccounts();

         Assert.IsNotNull(result);
         Assert.IsTrue(result.Count == 1);

      }
        public void AdaptEnumerableBankAccountToListBankAccountListDTO()
        {
            //Arrange
            var customer = CustomerFactory.CreateCustomer("jhon", "el rojo", Guid.NewGuid(), new Address("", "", "", ""));
            customer.Id = IdentityGenerator.NewSequentialGuid();

            BankAccount account = new BankAccount();
            account.Id = IdentityGenerator.NewSequentialGuid();
            account.BankAccountNumber = new BankAccountNumber("4444", "5555", "3333333333", "02");
            account.SetCustomer(customer);
            account.DepositMoney(1000, "reason");
            var accounts = new List<BankAccount>() { account };

            //Act
            ITypeAdapter adapter = PrepareTypeAdapter();
            var bankAccountsDTO = adapter.Adapt<IEnumerable<BankAccount>, List<BankAccountDTO>>(accounts);

            //Assert
            Assert.IsNotNull(bankAccountsDTO);
            Assert.IsTrue(bankAccountsDTO.Count == 1);

            Assert.AreEqual(account.Id, bankAccountsDTO[0].Id);
            Assert.AreEqual(account.Iban, bankAccountsDTO[0].BankAccountNumber);
            Assert.AreEqual(account.Balance, bankAccountsDTO[0].Balance);
            Assert.AreEqual(account.Customer.FirstName, bankAccountsDTO[0].CustomerFirstName);
            Assert.AreEqual(account.Customer.LastName, bankAccountsDTO[0].CustomerLastName);
        }
      public void LockBankAccountReturnTrueIfBankAccountIsLocked()
      {
         //Arrange
         var customerRepository = new StubICustomerRepository();
         IBankTransferService transferService = new BankTransferService();

         var bankAccountRepository = new StubIBankAccountRepository();
         bankAccountRepository.UnitOfWorkGet = () =>
         {
            var uow = new StubIUnitOfWork();
            uow.Commit = () => { };

            return uow;
         };

         bankAccountRepository.GetGuid = (guid) =>
         {
            var customer = new Customer();
            customer.GenerateNewIdentity();

            var bankAccount = new BankAccount();
            bankAccount.GenerateNewIdentity();

            bankAccount.SetCustomerOwnerOfThisBankAccount(customer);

            return bankAccount;
         };

         IBankAppService bankingService = new BankAppService(bankAccountRepository, customerRepository, transferService);

         //Act
         var result = bankingService.LockBankAccount(Guid.NewGuid());

         //Assert
         Assert.IsTrue(result);
      }
        public void FindBankAccountActivitiesReturnAllItems()
        {
            //Arrange
            SIBankAccountRepository bankAccountRepository = new SIBankAccountRepository();
            bankAccountRepository.GetGuid = (guid) =>
            {
                var bankAccount = new BankAccount()
                {
                    Id = Guid.NewGuid(),
                    BankAccountActivity = new HashSet<BankAccountActivity>()
                    {
                        new BankAccountActivity(){Id = Guid.NewGuid(),Date = DateTime.Now,Amount = 1000},
                        new BankAccountActivity(){Id = Guid.NewGuid(),Date = DateTime.Now,Amount = 1000},
                    }
                };

                return bankAccount;
            };

            SICustomerRepository customerRepository = new SICustomerRepository();
            IBankTransferService transferService = new BankTransferService();
            ITypeAdapter adapter = PrepareTypeAdapter();

            IBankAppService bankingService = new BankAppService(bankAccountRepository, customerRepository, transferService, adapter);

            //Act
            var result = bankingService.FindBankAccountActivities(Guid.NewGuid());

            //Assert
            Assert.IsNotNull(result);
            Assert.IsTrue(result.Count == 2);
        }