Пример #1
0
        public AccountTransaction UpdateAccountTransaction(int accountTransactionNo, DateTime verificationDate, DateTime accountingDate, int userNo, int accountNo, decimal amount,
                                                           string note, TagHandlerAction tagHandlerAction, int accountTagNo)
        {
            Account account = GetAccount(accountNo);
            //AccountTransaction transaction = GetAccountTransaction(accountTransactionNo);
            AccountTransaction transaction    = DataCache.GetAccountTransaction(accountTransactionNo);
            decimal            changeInAmount = amount - transaction.Amount;

            transaction.UserNo    = userNo;
            transaction.AccountNo = accountNo;
            transaction.Amount    = amount;
            transaction.Note      = note;

            Verification verification = DataCache.GetVerification(transaction.VerificationNo);

            //Verification verification = GetVerification(transaction.VerificationNo);
            verification.Date           = DanielEiserman.DateAndTime.Date.FloorDateTime(verificationDate);
            verification.AccountingDate = DanielEiserman.DateAndTime.Date.FloorDateTime(accountingDate);

            AccountTagCollection accountTags = GetAccountTagsByAccountNo(accountNo);

            List <LogItem> logItems;

            RecalculateAccountNoValues(verification.No, changeInAmount, tagHandlerAction, accountTagNo, accountTags, account, out logItems);

            if (verification.Date.Year != verificationDate.Year)
            {
                throw new InvalidOperationException("Datumet på verifikationen stämmer inte överens med dess värde.");
            }

            using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, TransactionHelper.Options(System.Transactions.IsolationLevel.ReadCommitted)))
            {
                Database.TheConnection.EnlistTransaction(Transaction.Current);

                DataCache.Save(verification);
                DataCache.Save(transaction);

                foreach (var accountTag in accountTags)
                {
                    Save(accountTag);
                }

                foreach (var accountTag in accountTags)
                {
                    CreateTagAccountSnapshot(accountTag.TagAccountNo, TagAccountSnapshotReason.AccountTransactionUpdated);
                }

                foreach (var logItem in logItems)
                {
                    logItem.VerificationNo = verification.No;
                    Save(logItem);
                }

                transactionScope.Complete();
            }

            // Alert all listeners that a transaction was updated
            ApplicationEvents.OnAccountTransactionUpdated(accountTransactionNo, verification.No);

            return(transaction);
        }
Пример #2
0
        private static void RecalculateAccountNoValues(int verificationNo, decimal amount,
                                                       TagHandlerAction tagHandlerAction, int accountTagNo, AccountTagCollection accountTags, Account account,
                                                       out List <LogItem> logItems)
        {
            AccountTag currentAccountTag = accountTags.Find(at => at.No == accountTagNo);

            decimal totalAbsoluteAmount  = 0;
            decimal totalRelativePercent = 0;

            foreach (var accountTag in accountTags)
            {
                if (accountTag.Type == AccountTagType.PercentOfRest)
                {
                    totalRelativePercent += accountTag.RelativeValue;
                }
                else if (accountTag.Type == AccountTagType.ExactAmount)
                {
                    totalAbsoluteAmount += accountTag.Amount;
                }
            }

            logItems = new List <LogItem>();
            string logText;

            if (tagHandlerAction == TagHandlerAction.Untagged)
            {
                decimal newTotalRelativeAndUntaggedAmount = account.Balance + account.BalanceBroughtForwardAmount - totalAbsoluteAmount + amount;
                var     relativeAccountTags = accountTags.Where(at => at.Type == AccountTagType.PercentOfRest);

                // Recalculate percent values (if there is anything left in the account after the withdrawal)
                if (newTotalRelativeAndUntaggedAmount > 0)
                {
                    foreach (var accountTag in relativeAccountTags)
                    {
                        logText = string.Format("Relative account tag {0} changed value from {1} to ", accountTag.No,
                                                accountTag.RelativeValue.ToString("0.#########"));

                        accountTag.RelativeValue = Math.Round(accountTag.Amount / newTotalRelativeAndUntaggedAmount, 9);

                        if (accountTag.RelativeValue < 0)
                        {
                            accountTag.RelativeValue = 0;
                        }
                        else if (accountTag.RelativeValue > 1)
                        {
                            accountTag.RelativeValue = 1;
                        }

                        logText += accountTag.RelativeValue.ToString("0.#########") + ".";

                        logItems.Add(new LogItem(CurrentApplication.UserNo, verificationNo, account.No,
                                                 LogItemType.AccountTagRecalculated, logText, CurrentApplication.DateTimeNow));
                    }
                }
            }
            else if (tagHandlerAction == TagHandlerAction.Specified)
            {
                decimal newTotalRelativeAndUntaggedAmount = account.Balance + account.BalanceBroughtForwardAmount - totalAbsoluteAmount + amount;
                var     relativeAccountTags       = accountTags.Where(at => at.Type == AccountTagType.PercentOfRest);
                decimal totalRelativePercentAfter = 0m;

                if (currentAccountTag.Type == AccountTagType.ExactAmount)
                {
                    logText = string.Format("Absolute account tag {0} changed value from {1} to {2}.", currentAccountTag.No,
                                            currentAccountTag.MoneyValue.ToString("0.####"), (currentAccountTag.MoneyValue + amount).ToString("0.####"));

                    currentAccountTag.MoneyValue += amount;

                    logItems.Add(new LogItem(CurrentApplication.UserNo, verificationNo, account.No,
                                             LogItemType.AccountTagRecalculated, logText, CurrentApplication.DateTimeNow));
                }
                else
                {
                    // Recalculate percent values (if there is anything left in the account after the withdrawal)
                    if (newTotalRelativeAndUntaggedAmount > 0)
                    {
                        foreach (var accountTag in relativeAccountTags)
                        {
                            decimal accountTagAmount = accountTag.Amount;
                            if (accountTag.No == currentAccountTag.No)
                            {
                                accountTagAmount += amount;
                            }

                            logText = string.Format("Relative account tag {0} changed value from {1} to ", accountTag.No,
                                                    accountTag.RelativeValue.ToString("0.#########"));

                            accountTag.RelativeValue = Math.Round(accountTagAmount / newTotalRelativeAndUntaggedAmount, 9);

                            if (accountTag.RelativeValue < 0)
                            {
                                accountTag.RelativeValue = 0;
                            }
                            else if (accountTag.RelativeValue > 1)
                            {
                                accountTag.RelativeValue = 1;
                            }

                            totalRelativePercentAfter += accountTag.RelativeValue;

                            logText += accountTag.RelativeValue.ToString("0.#########") + ".";

                            logItems.Add(new LogItem(CurrentApplication.UserNo, verificationNo, account.No,
                                                     LogItemType.AccountTagRecalculated, logText, CurrentApplication.DateTimeNow));
                        }
                    }

                    // If the total percent for all relative account tags was 100 percent before transaction,
                    // then make sure that they are 100 percent after.
                    if (totalRelativePercent == 1 || totalRelativePercentAfter > 1)
                    {
                        decimal diff = totalRelativePercentAfter - totalRelativePercent;
                        var     highestAccountTag = relativeAccountTags.OrderByDescending(at => at.Amount).First();

                        logText = string.Format("Relative account tag {0} value was adjusted from {1} to ", highestAccountTag.No,
                                                highestAccountTag.RelativeValue.ToString("0.#########"));

                        highestAccountTag.RelativeValue -= diff;

                        if (diff > 0)
                        {
                            logText += highestAccountTag.RelativeValue.ToString("0.#########") + ".";

                            logItems.Add(new LogItem(CurrentApplication.UserNo, verificationNo, account.No,
                                                     LogItemType.AccountTagRecalculated, logText, CurrentApplication.DateTimeNow));
                        }
                    }
                }
            }
            else if (tagHandlerAction == TagHandlerAction.Split)
            {
                // Do nothing - alla account tag percent values are still correct
            }
            else
            {
                throw new NotImplementedException("TagType action " + tagHandlerAction + " is not implemented.");
            }

            decimal totalUntaggedAndRelativeAmount = account.BalanceBroughtForwardAmount + account.Balance -
                                                     totalAbsoluteAmount;

            // Some validation
            if (amount < 0)
            {
                if (tagHandlerAction == TagHandlerAction.Specified)
                {
                    if (Math.Abs(amount) > currentAccountTag.Amount)
                    {
                        if (currentAccountTag.Type == AccountTagType.ExactAmount)
                        {
                            throw new MoneyTagException(
                                      "Uttaget kan inte genomföras eftersom dess värde överstiger värdet för den valda märkningen som tillåter en transaktion på " +
                                      currentAccountTag.Amount.ToString(CurrentApplication.MoneyDisplayFormat) +
                                      " kr. Om du vill genomföra transaktionen måste du först ändra på märkningen.");
                        }
                        else     // If relative amount
                        {
                            // Om det finns flera relativa kontotaggar med tillräckligt värde på så är det ok, annars inte.
                            if (Math.Abs(amount) > totalUntaggedAndRelativeAmount)
                            {
                                throw new MoneyTagException(
                                          "Uttaget kan inte genomföras eftersom dess värde överstiger värdet för samtliga relativa märkningar inklusive omärkt belopp på " +
                                          totalUntaggedAndRelativeAmount.ToString(CurrentApplication.MoneyDisplayFormat) +
                                          " kr. Om du vill genomföra transaktionen måste du först ändra på märkningen.");
                            }
                        }
                    }
                }
                else
                {
                    if (tagHandlerAction == TagHandlerAction.Split)
                    {
                        if (Math.Abs(amount) > account.Balance + account.BalanceBroughtForwardAmount)
                        {
                            throw new MoneyTagException(
                                      "Uttaget kan inte genomföras eftersom dess värde överstiger det totala värdet för alla relativa märkningar (" +
                                      totalUntaggedAndRelativeAmount.ToString(CurrentApplication.MoneyDisplayFormat) +
                                      " kr). Om du vill genomföra transaktionen måste du först ändra på märkningen.");
                        }
                    }
                }
            }

            if (account.BalanceBroughtForwardAmount + account.Balance < 0 || account.Type == AccountType.Debt)
            {
                if (tagHandlerAction != TagHandlerAction.Untagged)
                {
                    throw new MoneyTagException(
                              "Du kan inte välja en märkning på ett skuldkonto eller på ett konto med negativt belopp.");
                }
            }
        }