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); }
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."); } } }