コード例 #1
0
        public async Task Transfer(string sourceWalletJmbg, string sourceWalletPass, decimal amount, string destinationWalletJmbg)
        {
            if (string.IsNullOrEmpty(sourceWalletJmbg))
            {
                throw new ArgumentNullException($"{nameof(sourceWalletJmbg)}");
            }
            if (string.IsNullOrEmpty(sourceWalletPass))
            {
                throw new ArgumentNullException($"{nameof(sourceWalletPass)}");
            }
            if (string.IsNullOrEmpty(destinationWalletJmbg))
            {
                throw new ArgumentNullException($"{nameof(destinationWalletJmbg)}");
            }
            if (amount < 0)
            {
                throw new InvalidOperationException("Amount must be greater than 0");
            }
            Wallet sourceWallet = await CoreUnitOfWork.WalletRepository.GetFirstOrDefaultWithIncludes(
                w => w.JMBG == sourceWalletJmbg,
                w => w.Transactions
                );

            if (sourceWallet == null)
            {
                throw new InvalidOperationException($"{nameof(Wallet)} with JMBG = {sourceWallet} doesn't exist");
            }
            if (!sourceWallet.IsPassValid(sourceWalletPass))
            {
                throw new InvalidOperationException($"Invalid password.");
            }
            if (sourceWallet.IsBlocked)
            {
                throw new InvalidOperationException($"{nameof(Transfer)} from blocked wallet #{sourceWallet.JMBG} is forbidden");
            }

            Wallet destinationWallet = await CoreUnitOfWork.WalletRepository.GetFirstOrDefaultWithIncludes(
                w => w.JMBG == destinationWalletJmbg,
                w => w.Transactions
                );

            if (destinationWallet == null)
            {
                throw new InvalidOperationException($"{nameof(Wallet)} with JMBG = {sourceWalletJmbg} doesn't exist");
            }
            if (destinationWallet.IsBlocked)
            {
                throw new InvalidOperationException($"{nameof(Transfer)} to blocked wallet #{destinationWallet.JMBG} is forbidden");
            }

            decimal transferFee = await FeeService.CalculateTransferFee(
                sourceWallet,
                amount,
                DaysAfterWalletCreationWithNoFee,
                IsFirstTransferFreeInMonth,
                FixedFee,
                PercentageFee,
                FeeLimit);

            await CoreUnitOfWork.BeginTransactionAsync();

            try
            {
                sourceWallet.PayOut(amount, TransactionType.TransferPayOut, MaxWithdraw);
                if (transferFee > 0)
                {
                    sourceWallet.PayOut(transferFee, TransactionType.FeePayOut, MaxWithdraw);
                    await CoreUnitOfWork.WalletRepository.Update(sourceWallet);

                    await CoreUnitOfWork.SaveChangesAsync();
                }
                destinationWallet.PayIn(amount, TransactionType.TransferPayIn, MaxDeposit);

                await CoreUnitOfWork.WalletRepository.Update(sourceWallet);

                await CoreUnitOfWork.SaveChangesAsync();

                await CoreUnitOfWork.WalletRepository.Update(destinationWallet);

                await CoreUnitOfWork.SaveChangesAsync();

                await CoreUnitOfWork.CommitTransactionAsync();
            }
            catch (InvalidOperationException ex)
            {
                await CoreUnitOfWork.RollbackTransactionAsync();

                throw ex;
            }
        }